1/* addsub.s Test file for AArch64 add-subtract instructions.
2
3   Copyright (C) 2012-2016 Free Software Foundation, Inc.
4   Contributed by ARM Ltd.
5
6   This file is part of GAS.
7
8   GAS is free software; you can redistribute it and/or modify
9   it under the terms of the GNU General Public License as published by
10   the Free Software Foundation; either version 3 of the license, or
11   (at your option) any later version.
12
13   GAS is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17
18   You should have received a copy of the GNU General Public License
19   along with this program; see the file COPYING3. If not,
20   see <http://www.gnu.org/licenses/>.  */
21
22// TODO: also cover the addsub_imm instructions.
23
24	/*
25	 * Adjust Rm
26	 */
27	.macro adjust_rm	op, rd, rn, rm_r, rm_n, extend, amount
28	// for 64-bit instruction, Rm is Xm when <extend> is explicitely
29	// or implicitly UXTX, SXTX or LSL; otherwise it Wm.
30	.ifc \rm_r, X
31		.ifnc \extend, UXTX
32			.ifnc \extend, SXTX
33				.ifnc \extend, LSL
34					.ifb \amount
35					\op	\rd, \rn, W\()\rm_n, \extend
36					.else
37					\op	\rd, \rn, W\()\rm_n, \extend #\amount
38					.endif
39					.exitm
40				.endif
41			.endif
42		.endif
43	.endif
44
45	.ifb \amount
46	\op	\rd, \rn, \rm_r\()\rm_n, \extend
47	.else
48	\op	\rd, \rn, \rm_r\()\rm_n, \extend #\amount
49	.endif
50	.endm
51
52	/*
53	 * Emitting addsub_ext instruction
54	 */
55	.macro do_addsub_ext	type, op, Rn, reg, extend, amount
56	.ifc \type, 0
57		// normal add/adds/sub/subs
58		.ifb \extend
59		\op	\reg\()16, \Rn, \reg\()1
60		.else
61		.ifb \amount
62		adjust_rm	\op, \reg\()16, \Rn, \reg, 1, \extend
63		.else
64		adjust_rm	\op, \reg\()16, \Rn, \reg, 1, \extend, \amount
65		.endif
66		.endif
67	.else
68	.ifc \type, 1
69		// adds/subs with ZR as Rd
70		.ifb \extend
71		\op	\reg\()ZR, \Rn, \reg\()1
72		.else
73		.ifb \amount
74		adjust_rm	\op, \reg\()ZR, \Rn, \reg, 1, \extend
75		.else
76		adjust_rm	\op, \reg\()ZR, \Rn, \reg, 1, \extend, \amount
77		.endif
78		.endif
79	.else
80		// cmn/cmp
81		.ifb \extend
82		\op	\Rn, \reg\()1
83		.else
84		.ifb \amount
85		\op	\Rn, \reg\()1, \extend
86		.else
87		\op	\Rn, \reg\()1, \extend #\amount
88		.endif
89		.endif
90	.endif
91	.endif
92	.endm
93
94	/*
95	 * Optional extension and optional shift amount
96	 */
97	.macro do_extend type, op, Rn, reg
98	// <extend> absent
99	// note that when SP is not used, the GAS will encode it as addsub_shift
100	do_addsub_ext	\type, \op, \Rn, \reg
101	// optional absent <amount>
102	.irp extend, UXTB, UXTH, UXTW, UXTX, SXTB, SXTH, SXTW, SXTX
103	.irp amount,  , 0, 1, 2, 3, 4
104	do_addsub_ext	\type, \op, \Rn, \reg, \extend, \amount
105	.endr
106	.endr
107	// when <extend> is LSL, <amount> cannot be absent
108	// note that when SP is not used, the GAS will encode it as addsub_shift
109	.irp amount, 0, 1, 2, 3, 4
110	do_addsub_ext	\type, \op, \Rn, \reg, LSL, \amount
111	.endr
112	.endm
113
114	/*
115	 * Leaf macro emitting addsub_shift instruction
116	 */
117	.macro do_addsub_shift	type, op, R, reg, shift, amount
118	.ifc \type, 0
119		// normal add/adds/sub/subs
120		.ifb \shift
121		\op	\reg\()16, \R, \reg\()1
122		.else
123		\op	\reg\()16, \R, \reg\()1, \shift #\amount
124		.endif
125	.else
126	.ifc \type, 1
127		// adds/subs with ZR as Rd
128		.ifb \shift
129		\op	\reg\()ZR, \R, \reg\()1
130		.else
131		\op	\reg\()ZR, \R, \reg\()1, \shift #\amount
132		.endif
133	.else
134	.ifc \type, 2
135		// cmn/cmp/neg/negs
136		.ifb \shift
137		\op	\R, \reg\()1
138		.else
139		\op	\R, \reg\()1, \shift #\amount
140		.endif
141	.else
142		// sub/subs with ZR as Rn
143		.ifb \shift
144		\op	\R, \reg\()ZR, \reg\()1
145		.else
146		\op	\R, \reg\()ZR, \reg\()1, \shift #\amount
147		.endif
148	.endif
149	.endif
150	.endif
151	.endm
152
153	/*
154	 * Optional shift and optional shift amount
155	 */
156	.macro do_shift type, op, R, reg
157	// <shift> absent
158	do_addsub_shift	\type, \op, \R, \reg
159	// optional absent <amount>
160	.irp shift, LSL, LSR, ASR
161	.irp amount, 0, 1, 2, 3, 4, 5, 16, 31
162	// amount cannot be absent when shift is present.
163	do_addsub_shift	\type, \op, \R, \reg, \shift, \amount
164	.endr
165	.ifc \reg, X
166	do_addsub_shift	\type, \op, \R, \reg, \shift, 63
167	.endif
168	.endr
169	.endm
170
171func:
172	/*
173	 * Add-subtract (extended register)
174	 */
175
176	.irp op, ADD, ADDS, SUB, SUBS
177	do_extend	0, \op, W7, W
178	do_extend	0, \op, WSP, W
179	do_extend	0, \op, X7, X
180	do_extend	0, \op, SP, X
181	.endr
182
183	.irp op, ADDS, SUBS
184	do_extend	1, \op, W7, W
185	do_extend	1, \op, WSP, W
186	do_extend	1, \op, X7, X
187	do_extend	1, \op, SP, X
188	.endr
189
190	.irp op, CMN, CMP
191	do_extend	2, \op, W7, W
192	do_extend	2, \op, WSP, W
193	do_extend	2, \op, X7, X
194	do_extend	2, \op, SP, X
195	.endr
196
197	/*
198	 * Add-subtract (shift register)
199	 */
200
201	.irp op, ADD, ADDS, SUB, SUBS
202	do_shift	0, \op, W7, W
203	do_shift	0, \op, X7, X
204	.endr
205
206	.irp op, ADDS, SUBS
207	do_shift	1, \op, W7, W
208	do_shift	1, \op, X7, X
209	.endr
210
211	.irp op, CMN, CMP
212	do_shift	2, \op, W7, W
213	do_shift	2, \op, X7, X
214	.endr
215
216	.irp op, SUB, SUBS
217	do_shift	3, \op, W7, W
218	do_shift	3, \op, X7, X
219	.endr
220
221	.irp op, NEG, NEGS
222	do_shift	2, \op, W7, W
223	do_shift	2, \op, X7, X
224	.endr
225