blob: 568bbcebc501943fa8f67db178ceb631bec7d25c [file] [log] [blame]
/* addsub.s Test file for AArch64 add-subtract instructions.
Copyright 2012 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 <http://www.gnu.org/licenses/>. */
// 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 <extend> 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
// <extend> 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 <amount>
.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 <extend> is LSL, <amount> 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
// <shift> absent
do_addsub_shift \type, \op, \R, \reg
// optional absent <amount>
.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