Commit | Line | Data |
---|---|---|
a06ea964 NC |
1 | /* addsub.s Test file for AArch64 add-subtract instructions. |
2 | ||
b90efa5b | 3 | Copyright (C) 2012-2015 Free Software Foundation, Inc. |
a06ea964 NC |
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 | ||
171 | func: | |
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 |