/* addsub.s Test file for AArch64 add-subtract instructions. Copyright (C) 2012-2014 Free Software Foundation, Inc. Contributed by ARM Ltd. This file is part of GAS. GAS is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the license, or (at your option) any later version. GAS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING3. If not, see . */ // TODO: also cover the addsub_imm instructions. /* * Adjust Rm */ .macro adjust_rm op, rd, rn, rm_r, rm_n, extend, amount // for 64-bit instruction, Rm is Xm when is explicitely // or implicitly UXTX, SXTX or LSL; otherwise it Wm. .ifc \rm_r, X .ifnc \extend, UXTX .ifnc \extend, SXTX .ifnc \extend, LSL .ifb \amount \op \rd, \rn, W\()\rm_n, \extend .else \op \rd, \rn, W\()\rm_n, \extend #\amount .endif .exitm .endif .endif .endif .endif .ifb \amount \op \rd, \rn, \rm_r\()\rm_n, \extend .else \op \rd, \rn, \rm_r\()\rm_n, \extend #\amount .endif .endm /* * Emitting addsub_ext instruction */ .macro do_addsub_ext type, op, Rn, reg, extend, amount .ifc \type, 0 // normal add/adds/sub/subs .ifb \extend \op \reg\()16, \Rn, \reg\()1 .else .ifb \amount adjust_rm \op, \reg\()16, \Rn, \reg, 1, \extend .else adjust_rm \op, \reg\()16, \Rn, \reg, 1, \extend, \amount .endif .endif .else .ifc \type, 1 // adds/subs with ZR as Rd .ifb \extend \op \reg\()ZR, \Rn, \reg\()1 .else .ifb \amount adjust_rm \op, \reg\()ZR, \Rn, \reg, 1, \extend .else adjust_rm \op, \reg\()ZR, \Rn, \reg, 1, \extend, \amount .endif .endif .else // cmn/cmp .ifb \extend \op \Rn, \reg\()1 .else .ifb \amount \op \Rn, \reg\()1, \extend .else \op \Rn, \reg\()1, \extend #\amount .endif .endif .endif .endif .endm /* * Optional extension and optional shift amount */ .macro do_extend type, op, Rn, reg // absent // note that when SP is not used, the GAS will encode it as addsub_shift do_addsub_ext \type, \op, \Rn, \reg // optional absent .irp extend, UXTB, UXTH, UXTW, UXTX, SXTB, SXTH, SXTW, SXTX .irp amount, , 0, 1, 2, 3, 4 do_addsub_ext \type, \op, \Rn, \reg, \extend, \amount .endr .endr // when is LSL, cannot be absent // note that when SP is not used, the GAS will encode it as addsub_shift .irp amount, 0, 1, 2, 3, 4 do_addsub_ext \type, \op, \Rn, \reg, LSL, \amount .endr .endm /* * Leaf macro emitting addsub_shift instruction */ .macro do_addsub_shift type, op, R, reg, shift, amount .ifc \type, 0 // normal add/adds/sub/subs .ifb \shift \op \reg\()16, \R, \reg\()1 .else \op \reg\()16, \R, \reg\()1, \shift #\amount .endif .else .ifc \type, 1 // adds/subs with ZR as Rd .ifb \shift \op \reg\()ZR, \R, \reg\()1 .else \op \reg\()ZR, \R, \reg\()1, \shift #\amount .endif .else .ifc \type, 2 // cmn/cmp/neg/negs .ifb \shift \op \R, \reg\()1 .else \op \R, \reg\()1, \shift #\amount .endif .else // sub/subs with ZR as Rn .ifb \shift \op \R, \reg\()ZR, \reg\()1 .else \op \R, \reg\()ZR, \reg\()1, \shift #\amount .endif .endif .endif .endif .endm /* * Optional shift and optional shift amount */ .macro do_shift type, op, R, reg // absent do_addsub_shift \type, \op, \R, \reg // optional absent .irp shift, LSL, LSR, ASR .irp amount, 0, 1, 2, 3, 4, 5, 16, 31 // amount cannot be absent when shift is present. do_addsub_shift \type, \op, \R, \reg, \shift, \amount .endr .ifc \reg, X do_addsub_shift \type, \op, \R, \reg, \shift, 63 .endif .endr .endm func: /* * Add-subtract (extended register) */ .irp op, ADD, ADDS, SUB, SUBS do_extend 0, \op, W7, W do_extend 0, \op, WSP, W do_extend 0, \op, X7, X do_extend 0, \op, SP, X .endr .irp op, ADDS, SUBS do_extend 1, \op, W7, W do_extend 1, \op, WSP, W do_extend 1, \op, X7, X do_extend 1, \op, SP, X .endr .irp op, CMN, CMP do_extend 2, \op, W7, W do_extend 2, \op, WSP, W do_extend 2, \op, X7, X do_extend 2, \op, SP, X .endr /* * Add-subtract (shift register) */ .irp op, ADD, ADDS, SUB, SUBS do_shift 0, \op, W7, W do_shift 0, \op, X7, X .endr .irp op, ADDS, SUBS do_shift 1, \op, W7, W do_shift 1, \op, X7, X .endr .irp op, CMN, CMP do_shift 2, \op, W7, W do_shift 2, \op, X7, X .endr .irp op, SUB, SUBS do_shift 3, \op, W7, W do_shift 3, \op, X7, X .endr .irp op, NEG, NEGS do_shift 2, \op, W7, W do_shift 2, \op, X7, X .endr