CACAO
emit-asm.hpp
Go to the documentation of this file.
1 /* src/vm/jit/aarch64/emit-asm.hpp - emit asm instructions for Aarch64
2 
3  Copyright (C) 1996-2013
4  CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
5  Copyright (C) 2009 Theobroma Systems Ltd.
6 
7  This file is part of CACAO.
8 
9  This program is free software; you can redistribute it and/or
10  modify it under the terms of the GNU General Public License as
11  published by the Free Software Foundation; either version 2, or (at
12  your option) any later version.
13 
14  This program is distributed in the hope that it will be useful, but
15  WITHOUT ANY WARRANTY; without even the implied warranty of
16  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17  General Public License for more details.
18 
19  You should have received a copy of the GNU General Public License
20  along with this program; if not, write to the Free Software
21  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22  02110-1301, USA.
23 
24 */
25 
26 #ifndef VM_JIT_AARCH64_EMIT_ASM_HPP_
27 #define VM_JIT_AARCH64_EMIT_ASM_HPP_
28 
29 #include <cassert>
30 #include <cstdio>
31 
32 #include "config.h"
33 
34 #include "vm/types.hpp"
35 #include "vm/os.hpp"
37 
38 #define LSL(x,a) ((x) << a)
39 #define LSR(x,a) ((x) >> a)
40 
41 /* Some instructions allow shifts of operands, these are for encoding them */
42 #define CODE_LSL 0
43 #define CODE_LSR 1
44 #define CODE_ASR 2
45 
46 /* Inverts the least significatn bit of the passed value */
47 #define INVERT(x) ((x) ^ 1)
48 
49 /* Condition codes, some instructions allow such a code to be passed as argument */
50 #define COND_EQ 0x0
51 #define COND_NE 0x1
52 #define COND_CS 0x2
53 #define COND_CC 0x3
54 #define COND_MI 0x4
55 #define COND_PL 0x5
56 #define COND_VS 0x6
57 #define COND_VC 0x7
58 #define COND_HI 0x8
59 #define COND_LS 0x9
60 #define COND_GE 0xa
61 #define COND_LT 0xb
62 #define COND_GT 0xc
63 #define COND_LE 0xd
64 #define COND_AL 0xe
65 #define COND_NV 0xf
66 
67 
68 /* Compare & branch (immediate) **********************************************/
69 
70 inline void emit_cmp_branch_imm(codegendata *cd, u1 sf, u1 op, s4 imm, u1 Rt)
71 {
72  *((u4 *) cd->mcodeptr) = LSL(sf, 31) | LSL(op, 24)
73  | LSL(imm, 5) | Rt | 0x34000000;
74  cd->mcodeptr += 4;
75 }
76 
77 #define emit_cbnz(cd, Xt, imm) emit_cmp_branch_imm(cd, 1, 1, imm, Xt)
78 
79 
80 /* Conditional branch (immediate) ********************************************/
81 
82 inline void emit_cond_branch_imm(codegendata *cd, s4 imm19, u1 cond)
83 {
84  *((u4 *) cd->mcodeptr) = LSL((imm19 & 0x7ffff), 5) | cond | 0x54000000;
85  cd->mcodeptr += 4;
86 }
87 
88 #define emit_br_eq(cd, imm) emit_cond_branch_imm(cd, imm, COND_EQ)
89 #define emit_br_ne(cd, imm) emit_cond_branch_imm(cd, imm, COND_NE)
90 #define emit_br_cs(cd, imm) emit_cond_branch_imm(cd, imm, COND_CS)
91 #define emit_br_cc(cd, imm) emit_cond_branch_imm(cd, imm, COND_CC)
92 #define emit_br_mi(cd, imm) emit_cond_branch_imm(cd, imm, COND_MI)
93 #define emit_br_pl(cd, imm) emit_cond_branch_imm(cd, imm, COND_PL)
94 #define emit_br_vs(cd, imm) emit_cond_branch_imm(cd, imm, COND_VS)
95 #define emit_br_vc(cd, imm) emit_cond_branch_imm(cd, imm, COND_VC)
96 #define emit_br_hi(cd, imm) emit_cond_branch_imm(cd, imm, COND_HI)
97 #define emit_br_ls(cd, imm) emit_cond_branch_imm(cd, imm, COND_LS)
98 #define emit_br_ge(cd, imm) emit_cond_branch_imm(cd, imm, COND_GE)
99 #define emit_br_lt(cd, imm) emit_cond_branch_imm(cd, imm, COND_LT)
100 #define emit_br_gt(cd, imm) emit_cond_branch_imm(cd, imm, COND_GT)
101 #define emit_br_le(cd, imm) emit_cond_branch_imm(cd, imm, COND_LE)
102 
103 
104 /* Unconditional branch (immediate) ******************************************/
105 
106 inline void emit_unc_branch_imm(codegendata *cd, u1 op, s4 imm26)
107 {
108  // TODO sanity check imm26
109  *((u4 *) cd->mcodeptr) = LSL(op, 31) | (imm26 & 0x3ffffff) | 0x14000000;
110  cd->mcodeptr += 4;
111 }
112 
113 #define emit_br_imm(cd, imm) emit_unc_branch_imm(cd, 0, imm)
114 #define emit_blr_imm(cd, imm) emit_unc_branch_imm(cd, 1, imm)
115 
116 
117 /* Unconditional branch (register) *******************************************/
118 
119 inline void emit_unc_branch_reg(codegendata *cd, u1 opc, u1 op2, u1 op3, u1 Rn, u1 op4)
120 {
121  *((u4 *) cd->mcodeptr) = LSL(opc, 21) | LSL(op2, 16) | LSL(op3, 10)
122  | LSL(Rn, 5) | op4 | 0xD6000000;
123  cd->mcodeptr += 4;
124 }
125 
126 #define emit_ret(cd) emit_unc_branch_reg(cd, 2, 31, 0, 30, 0)
127 #define emit_blr_reg(cd, Xn) emit_unc_branch_reg(cd, 1, 31, 0, Xn, 0)
128 
129 #define emit_br_reg(cd, Xn) emit_unc_branch_reg(cd, 0, 31, 0, Xn, 0)
130 
131 
132 /* Move wide (immediate) *****************************************************/
133 
134 inline void emit_mov_wide_imm(codegendata *cd, u1 sf, u1 opc, u1 hw, u2 imm16, u1 Rd)
135 {
136  assert(imm16 >= 0 && imm16 <= 65535);
137  *((u4 *) cd->mcodeptr) = LSL(sf, 31) | LSL(opc, 29) | LSL(hw, 21)
138  | LSL(imm16, 5) | Rd | 0x12800000;
139  cd->mcodeptr += 4;
140 }
141 
142 #define emit_mov_imm(cd, Xd, imm) emit_mov_wide_imm(cd, 1, 2, 0, imm, Xd)
143 #define emit_mov_imm32(cd, Xd, imm) emit_mov_wide_imm(cd, 0, 2, 0, imm, Xd)
144 #define emit_movn_imm(cd, Xd, imm) emit_mov_wide_imm(cd, 1, 0, 0, imm, Xd)
145 #define emit_movn_imm32(cd, Xd, imm) emit_mov_wide_imm(cd, 0, 0, 0, imm, Xd)
146 #define emit_movk_imm(cd, Xd, imm, hw) emit_mov_wide_imm(cd, 1, 3, hw, imm, Xd)
147 #define emit_movk_imm32(cd, Xd, imm, hw) emit_mov_wide_imm(cd, 0, 3, hw, imm, Xd)
148 
149 
150 /* Load/Store Register (unscaled immediate) ***********************************/
151 
152 inline void emit_ldstr_reg_usc(codegendata *cd, u1 size, u1 v, u1 opc, s2 imm9, u1 Rt, u1 Rn)
153 {
154  *((u4 *) cd->mcodeptr) = LSL(size, 30) | LSL(v, 26) | LSL(opc, 22)
155  | LSL(imm9 & 0x1ff, 12) | LSL(Rn, 5) | Rt | 0x38400000;
156  cd->mcodeptr += 4;
157 }
158 
159 
160 /* Load/Store Register (register offset) *************************************/
161 
162 inline void emit_ldstr_reg_reg(codegendata *cd, u1 size, u1 v, u1 opc, u1 Rm, u1 option, u1 S, u1 Rn, u1 Rt)
163 {
164  *((u4 *) cd->mcodeptr) = LSL(size, 30) | LSL(v, 26) | LSL(opc, 22)
165  | LSL(Rm, 16) | LSL(option, 13) | LSL(S, 12)
166  | LSL(Rn, 5) | Rt | 0x38200800;
167  cd->mcodeptr += 4;
168 }
169 
170 #define emit_ldr_reg(cd, Xt, Xn, Xm) emit_ldstr_reg_reg(cd, 3, 0, 1, Xm, 3, 0, Xn, Xt)
171 
172 
173 /* Load/Store Register (unsigned immediate) **********************************/
174 
175 inline void emit_ldstr_reg_us(codegendata *cd, u1 size, u1 v, u1 opc, u2 imm12, u1 Rt, u1 Rn)
176 {
177  u2 imm = LSR(imm12, size); /* 64bit: imm = imm12/8, 32bit: imm = imm12/4 */
178 
179  *((u4 *) cd->mcodeptr) = LSL(size, 30) | LSL(v, 26) | LSL(opc, 22)
180  | LSL(imm, 10) | LSL(Rn, 5) | Rt | 0x39000000;
181  cd->mcodeptr += 4;
182 }
183 
184 
185 /* Handle ambigous Load/Store instructions ***********************************/
186 
187 /* See Armv8 reference manual for the ambigous case rules */
188 inline void emit_ldstr_ambigous(codegendata *cd, u1 size, u1 v, u1 opc, s2 imm, u1 Rt, u1 Rn)
189 {
190  u1 sz = LSL(1, size); /* 64bit: 8, 32bit: 4 */
191 
192  /* handle ambigous case first */
193  if (imm >= 0 && imm <= 255 && (imm % sz == 0))
194  emit_ldstr_reg_us(cd, size, v, opc, imm, Rt, Rn);
195  else if (imm >= -256 && imm <= 255)
196  emit_ldstr_reg_usc(cd, size, v, opc, imm, Rt, Rn);
197  else if (imm < 0 && (-imm) < 0xffff) { /* this is for larger negative offsets */
198  // Should only be the case for INVOKESTATIC, which does not use REG_ITMP3
199  emit_movn_imm(cd, REG_ITMP3, (-imm) - 1);
200  emit_ldstr_reg_reg(cd, size, v, opc, REG_ITMP3, 3, 0, Rn, Rt);
201  }
202  else {
203  assert(imm >= 0);
204  assert(imm % sz == 0);
205  assert(imm / sz <= 0xfff);
206  emit_ldstr_reg_us(cd, size, v, opc, imm, Rt, Rn);
207  }
208 }
209 
210 #define emit_ldrh_imm(cd, Xt, Xn, imm) emit_ldstr_ambigous(cd, 1, 0, 1, imm, Xt, Xn)
211 #define emit_strh_imm(cd, Xt, Xn, imm) emit_ldstr_ambigous(cd, 1, 0, 0, imm, Xt, Xn)
212 
213 #define emit_ldrb_imm(cd, Xt, Xn, imm) emit_ldstr_ambigous(cd, 0, 0, 1, imm, Xt, Xn)
214 #define emit_strb_imm(cd, Xt, Xn, imm) emit_ldstr_ambigous(cd, 0, 0, 0, imm, Xt, Xn)
215 
216 #define emit_ldrsb_imm32(cd, Xt, Xn, imm) emit_ldstr_ambigous(cd, 0, 0, 3, imm, Xt, Xn)
217 #define emit_ldrsh_imm32(cd, Xt, Xn, imm) emit_ldstr_ambigous(cd, 1, 0, 3, imm, Xt, Xn)
218 
219 #define emit_ldr_imm(cd, Xt, Xn, imm) emit_ldstr_ambigous(cd, 3, 0, 1, imm, Xt, Xn)
220 #define emit_str_imm(cd, Xt, Xn, imm) emit_ldstr_ambigous(cd, 3, 0, 0, imm, Xt, Xn)
221 
222 #define emit_fp_ldr_imm(cd, Xt, Xn, imm) emit_ldstr_ambigous(cd, 3, 1, 1, imm, Xt, Xn)
223 #define emit_fp_str_imm(cd, Xt, Xn, imm) emit_ldstr_ambigous(cd, 3, 1, 0, imm, Xt, Xn)
224 
225 #define emit_ldr_imm32(cd, Xt, Xn, imm) emit_ldstr_ambigous(cd, 2, 0, 1, imm, Xt, Xn)
226 #define emit_str_imm32(cd, Xt, Xn, imm) emit_ldstr_ambigous(cd, 2, 0, 0, imm, Xt, Xn)
227 
228 #define emit_fp_ldr_imm32(cd, Xt, Xn, imm) emit_ldstr_ambigous(cd, 2, 1, 1, imm, Xt, Xn)
229 #define emit_fp_str_imm32(cd, Xt, Xn, imm) emit_ldstr_ambigous(cd, 2, 1, 0, imm, Xt, Xn)
230 
231 
232 /* Add/subtract (immediate) **************************************************/
233 
234 inline void emit_addsub_imm(codegendata *cd, u1 sf, u1 op, u1 S, u1 shift, u2 imm12, u1 Rn, u1 Rd)
235 {
236  assert(imm12 >= 0 && imm12 <= 0xfff);
237  *((u4 *) cd->mcodeptr) = LSL(sf, 31) | LSL(op, 30) | LSL(S, 29)
238  | LSL(shift, 22) | LSL(imm12, 10) | LSL(Rn, 5)
239  | Rd | 0x11000000;
240  cd->mcodeptr += 4;
241 }
242 
243 inline void emit_addsub_imm(codegendata *cd, u1 sf, u1 op, u1 Xd, u1 Xn, u4 imm)
244 {
245  assert(imm >= 0 && imm <= 0xffffff);
246  u2 lo = imm & 0xfff;
247  u2 hi = (imm & 0xfff000) >> 12;
248  if (hi == 0)
249  emit_addsub_imm(cd, sf, op, 0, 0, lo, Xn, Xd);
250  else {
251  emit_addsub_imm(cd, sf, op, 0, 1, hi, Xn, Xd);
252  emit_addsub_imm(cd, sf, op, 0, 0, lo, Xd, Xd);
253  }
254 }
255 
256 #define emit_add_imm(cd, Xd, Xn, imm) emit_addsub_imm(cd, 1, 0, Xd, Xn, imm)
257 #define emit_add_imm32(cd, Xd, Xn, imm) emit_addsub_imm(cd, 0, 0, Xd, Xn, imm)
258 
259 #define emit_sub_imm(cd, Xd, Xn, imm) emit_addsub_imm(cd, 1, 1, Xd, Xn, imm)
260 #define emit_sub_imm32(cd, Xd, Xn, imm) emit_addsub_imm(cd, 0, 1, Xd, Xn, imm)
261 
262 #define emit_subs_imm(cd, Xd, Xn, imm) emit_addsub_imm(cd, 1, 1, 1, 0, imm, Xn, Xd)
263 #define emit_subs_imm32(cd, Xd, Xn, imm) emit_addsub_imm(cd, 0, 1, 1, 0, imm, Xn, Xd)
264 
265 #define emit_adds_imm(cd, Xd, Xn, imm) emit_addsub_imm(cd, 1, 0, 1, 0, imm, Xn, Xd)
266 #define emit_adds_imm32(cd, Xd, Xn, imm) emit_addsub_imm(cd, 0, 0, 1, 0, imm, Xn, Xd)
267 
268 #define emit_mov_sp(cd, Xd, Xn) emit_add_imm(cd, Xd, Xn, 0)
269 
270 #define emit_cmp_imm(cd, Xn, imm) emit_subs_imm(cd, 31, Xn, imm)
271 #define emit_cmp_imm32(cd, Xn, imm) emit_subs_imm32(cd, 31, Xn, imm)
272 
273 #define emit_cmn_imm(cd, Xn, imm) emit_adds_imm(cd, 31, Xn, imm)
274 #define emit_cmn_imm32(cd, Wn, imm) emit_adds_imm32(cd, 31, Wn, imm)
275 
276 
277 /* Bitfield ******************************************************************/
278 
279 inline void emit_bitfield(codegendata *cd, u1 sf, u1 opc, u1 N, u1 immr, u1 imms, u1 Rn, u1 Rd)
280 {
281  assert(immr >= 0 && immr <= 0x3f);
282  assert(imms >= 0 && imms <= 0x3f);
283  *((u4 *) cd->mcodeptr) = LSL(sf, 31) | LSL(opc, 29) | LSL(N, 22)
284  | LSL(immr, 16) | LSL(imms, 10) | LSL(Rn, 5)
285  | Rd | 0x13000000;
286  cd->mcodeptr += 4;
287 }
288 
289 #define emit_ubfm(cd, Xd, Xn, immr, imms) emit_bitfield(cd, 1, 2, 1, immr, imms, Xn, Xd)
290 #define emit_ubfm32(cd, Wd, Wn, immr, imms) emit_bitfield(cd, 0, 2, 0, immr, imms, Wn, Wd)
291 
292 #define emit_lsl_imm(cd, Xd, Xn, shift) emit_ubfm(cd, Xd, Xn, ((u1)(-(shift))) % 64, 63 - (shift))
293 #define emit_lsl_imm32(cd, Wd, Wn, shift) emit_ubfm32(cd, Wd, Wn, ((u1)(-(shift))) % 32, 31 - (shift))
294 
295 #define emit_lsr_imm(cd, Xd, Xn, shift) emit_ubfm(cd, Xd, Xn, shift, 63)
296 #define emit_lsr_imm32(cd, Wd, Wn, shift) emit_ubfm32(cd, Wd, Wn, shift, 31)
297 
298 #define emit_uxtb(cd, Wd, Wn) emit_ubfm32(cd, Wd, Wn, 0, 7)
299 #define emit_uxth(cd, Wd, Wn) emit_ubfm32(cd, Wd, Wn, 0, 15)
300 
301 #define emit_sbfm(cd, Xd, Xn, immr, imms) emit_bitfield(cd, 1, 0, 1, immr, imms, Xn, Xd)
302 #define emit_sbfm32(cd, Wd, Wn, immr, imms) emit_bitfield(cd, 0, 0, 0, immr, imms, Wn, Wd)
303 
304 #define emit_sxtb(cd, Wd, Wn) emit_sbfm32(cd, Wd, Wn, 0, 7)
305 #define emit_sxth(cd, Wd, Wn) emit_sbfm32(cd, Wd, Wn, 0, 15)
306 
307 #define emit_asr_imm(cd, Xd, Xn, shift) emit_sbfm(cd, Xd, Xn, shift, 63)
308 #define emit_asr_imm32(cd, Wd, Wn, shift) emit_sbfm32(cd, Wd, Wn, shift, 31)
309 
310 #define emit_sxtw(cd, Xd, Wn) emit_sbfm(cd, Xd, Wn, 0, 31)
311 
312 
313 /* Logical (immediate) *******************************************************/
314 
315 inline void emit_logical_imm(codegendata *cd, u1 sf, u1 opc, u2 imm, u1 Rn, u1 Rd)
316 {
317  // TODO: fix this, keep in mind the imm encoding is complicated
318  os::abort("emit_logical_imm not supported atm.");
319  assert(imm >= 0 && imm <= 0xfff);
320  u1 immr = imm & 0x3f;
321  u1 imms = (imm >> 6) & 0x3f;
322 
323  *((u4 *) cd->mcodeptr) = LSL(sf, 31) | LSL(opc, 29) | LSL(immr, 16)
324  | LSL(imms, 10) | LSL(Rn, 5) | Rd | 0x12000000;
325  cd->mcodeptr += 4;
326 }
327 
328 #define emit_and_imm(cd, Xd, Xn, imm) emit_logical_imm(cd, 1, 0, imm, Xn, Xd)
329 #define emit_and_imm32(cd, Wd, Wn, imm) emit_logical_imm(cd, 0, 0, imm, Wn, Wd)
330 
331 
332 /* PC relative addressing ****************************************************/
333 
334 inline void emit_pcrel(codegendata *cd, u1 op, u1 immlo, u4 immhi, u1 Rd)
335 {
336  *((u4 *) cd->mcodeptr) = LSL(op, 31) | LSL(immlo, 29) | LSL(immhi, 5)
337  | Rd | 0x10000000;
338  cd->mcodeptr += 4;
339 }
340 
341 #define emit_adr(cd, Xd, immhi) emit_pcrel(cd, 0, 0, immhi, Xd)
342 
343 /* Add/subtract (shifted register) *******************************************/
344 
345 inline void emit_addsub_reg(codegendata *cd, u1 sf, u1 op, u1 S, u1 shift, u1 Rm, u1 imm6, u1 Rn, u1 Rd)
346 {
347  assert(imm6 >= 0 && imm6 <= 0x3f);
348  *((u4 *) cd->mcodeptr) = LSL(sf, 31) | LSL(op, 30) | LSL(S, 29)
349  | LSL(shift, 22) | LSL(Rm, 16) | LSL(imm6, 10)
350  | LSL(Rn, 5) | Rd | 0xB000000;
351  cd->mcodeptr += 4;
352 }
353 
354 #define emit_add_reg(cd, Xd, Xn, Xm) emit_addsub_reg(cd, 1, 0, 0, 0, Xm, 0, Xn, Xd)
355 #define emit_sub_reg(cd, Xd, Xn, Xm) emit_addsub_reg(cd, 1, 1, 0, 0, Xm, 0, Xn, Xd)
356 
357 #define emit_subs_reg(cd, Xd, Xn, Xm) emit_addsub_reg(cd, 1, 1, 1, 0, Xm, 0, Xn, Xd)
358 #define emit_subs_reg32(cd, Xd, Xn, Xm) emit_addsub_reg(cd, 0, 1, 1, 0, Xm, 0, Xn, Xd)
359 
360 #define emit_cmp_reg(cd, Xn, Xm) emit_subs_reg(cd, 31, Xn, Xm)
361 #define emit_cmp_reg32(cd, Xn, Xm) emit_subs_reg32(cd, 31, Xn, Xm)
362 
363 #define emit_add_reg_shift(cd, Xd, Xn, Xm, s, a) emit_addsub_reg(cd, 1, 0, 0, s, Xm, a, Xn, Xd)
364 #define emit_sub_reg_shift(cd, Xd, Xn, Xm, s, a) emit_addsub_reg(cd, 1, 1, 0, s, Xm, a, Xn, Xd)
365 
366 #define emit_add_reg32(cd, Xd, Xn, Xm) emit_addsub_reg(cd, 0, 0, 0, 0, Xm, 0, Xn, Xd)
367 #define emit_sub_reg32(cd, Xd, Xn, Xm) emit_addsub_reg(cd, 0, 1, 0, 0, Xm, 0, Xn, Xd)
368 
369 
370 /* Alpha like LDA ************************************************************/
371 
372 inline void emit_lda(codegendata *cd, u1 Xd, u1 Xn, s4 imm)
373 {
374  if (imm >= 0)
375  emit_add_imm(cd, Xd, Xn, imm);
376  else
377  emit_sub_imm(cd, Xd, Xn, -imm);
378 }
379 
380 
381 /* Conditional select ********************************************************/
382 
383 inline void emit_cond_select(codegendata *cd, u1 sf, u1 op, u1 S, u1 Rm, u1 cond, u1 op2, u1 Rn, u1 Rd)
384 {
385  *((u4 *) cd->mcodeptr) = LSL(sf, 31) | LSL(op, 30) | LSL(S, 29)
386  | LSL(Rm, 16) | LSL(cond, 12) | LSL(op2, 10) | LSL(Rn, 5)
387  | Rd | 0x1a800000;
388  cd->mcodeptr += 4;
389 }
390 
391 #define emit_csel(cd, Xd, Xn, Xm, cond) emit_cond_select(cd, 1, 0, 0, Xm, cond, 0, Xn, Xd)
392 #define emit_csel32(cd, Xd, Xn, Xm, cond) emit_cond_select(cd, 0, 0, 0, Xm, cond, 0, Xn, Xd)
393 #define emit_csinc(cd, Xd, Xn, Xm, cond) emit_cond_select(cd, 1, 0, 0, Xm, cond, 1, Xn, Xd)
394 #define emit_cset(cd, Xd, cond) emit_csinc(cd, Xd, 31, 31, INVERT(cond))
395 
396 #define emit_csinv(cd, Xd, Xn, Xm, cond) emit_cond_select(cd, 1, 1, 0, Xm, cond, 0, Xn, Xd)
397 #define emit_csetm(cd, Xd, cond) emit_csinv(cd, Xd, 31, 31, INVERT(cond))
398 
399 #define emit_csneg32(cd, Wd, Wn, Wm, cond) emit_cond_select(cd, 0, 1, 0, Wm, cond, 1, Wn, Wd)
400 
401 /* Data-processing (2 source) ************************************************/
402 
403 inline void emit_dp2(codegendata *cd, u1 sf, u1 S, u1 Rm, u1 opc, u1 Rn, u1 Rd)
404 {
405  *((u4 *) cd->mcodeptr) = LSL(sf, 31) | LSL(S, 29) | LSL(Rm, 16)
406  | LSL(opc, 10) | LSL(Rn, 5) | Rd
407  | 0x1AC00000;
408  cd->mcodeptr += 4;
409 }
410 
411 #define emit_sdiv(cd, Xd, Xn, Xm) emit_dp2(cd, 1, 0, Xm, 3, Xn, Xd)
412 #define emit_sdiv32(cd, Wd, Wn, Wm) emit_dp2(cd, 0, 0, Wm, 3, Wn, Wd)
413 
414 #define emit_asr(cd, Xd, Xn, Xm) emit_dp2(cd, 1, 0, Xm, 10, Xn, Xd)
415 #define emit_asr32(cd, Wd, Wn, Wm) emit_dp2(cd, 0, 0, Wm, 10, Wn, Wd)
416 
417 #define emit_lsl(cd, Xd, Xn, Xm) emit_dp2(cd, 1, 0, Xm, 8, Xn, Xd)
418 #define emit_lsl32(cd, Wd, Wn, Wm) emit_dp2(cd, 0, 0, Wm, 8, Wn, Wd)
419 
420 #define emit_lsr(cd, Xd, Xn, Xm) emit_dp2(cd, 1, 0, Xm, 9, Xn, Xd)
421 #define emit_lsr32(cd, Wd, Wn, Wm) emit_dp2(cd, 0, 0, Wm, 9, Wn, Wd)
422 
423 /* Data-processing (3 source) ************************************************/
424 
425 inline void emit_dp3(codegendata *cd, u1 sf, u1 op31, u1 Rm, u1 o0, u1 Ra, u1 Rn, u1 Rd)
426 {
427  *((u4 *) cd->mcodeptr) = LSL(sf, 31) | LSL(op31, 21) | LSL(Rm, 16)
428  | LSL(o0, 15) | LSL(Ra, 10) | LSL(Rn, 5)
429  | Rd | 0x1B000000;
430  cd->mcodeptr += 4;
431 }
432 
433 #define emit_madd(cd, Xd, Xn, Xm, Xa) emit_dp3(cd, 1, 0, Xm, 0, Xa, Xn, Xd)
434 #define emit_madd32(cd, Xd, Xn, Xm, Xa) emit_dp3(cd, 0, 0, Xm, 0, Xa, Xn, Xd)
435 
436 #define emit_msub(cd, Xd, Xn, Xm, Xa) emit_dp3(cd, 1, 0, Xm, 1, Xa, Xn, Xd)
437 #define emit_msub32(cd, Xd, Xn, Xm, Xa) emit_dp3(cd, 0, 0, Xm, 1, Xa, Xn, Xd)
438 
439 #define emit_mul(cd, Xd, Xn, Xm) emit_madd(cd, Xd, Xn, Xm, 31)
440 #define emit_mul32(cd, Xd, Xn, Xm) emit_madd32(cd, Xd, Xn, Xm, 31)
441 
442 
443 /* Logical (shifted register) ************************************************/
444 
445 inline void emit_logical_sreg(codegendata *cd, u1 sf, u1 opc, u1 shift, u1 N, u1 Rm, u1 imm6, u1 Rn, u1 Rd)
446 {
447  assert(imm6 >= 0 && imm6 <= 0x3f);
448  *((u4 *) cd->mcodeptr) = LSL(sf, 31) | LSL(opc, 29) | LSL(shift, 22)
449  | LSL(N, 21) | LSL(Rm, 16) | LSL(imm6, 10) | LSL(Rn, 5)
450  | Rd | 0x0a000000;
451  cd->mcodeptr += 4;
452 }
453 
454 #define emit_orr_sreg(cd, Xd, Xn, Xm) emit_logical_sreg(cd, 1, 1, 0, 0, Xm, 0, Xn, Xd)
455 #define emit_orr_sreg32(cd, Wd, Wn, Wm) emit_logical_sreg(cd, 0, 1, 0, 0, Wm, 0, Wn, Wd)
456 
457 #define emit_ands_sreg(cd, Xd, Xn, Xm) emit_logical_sreg(cd, 1, 3, 0, 0, Xm, 0, Xn, Xd)
458 #define emit_ands_sreg32(cd, Wd, Wn, Wm) emit_logical_sreg(cd, 0, 3, 0, 0, Wm, 0, Wn, Wd)
459 
460 #define emit_and_sreg(cd, Xd, Xn, Xm) emit_logical_sreg(cd, 1, 0, 0, 0, Xm, 0, Xn, Xd)
461 #define emit_and_sreg32(cd, Wd, Wn, Wm) emit_logical_sreg(cd, 0, 0, 0, 0, Wm, 0, Wn, Wd)
462 
463 #define emit_eor_sreg(cd, Xd, Xn, Xm) emit_logical_sreg(cd, 1, 2, 0, 0, Xm, 0, Xn, Xd)
464 #define emit_eor_sreg32(cd, Wd, Wn, Wm) emit_logical_sreg(cd, 0, 2, 0, 0, Wm, 0, Wn, Wd)
465 
466 #define emit_mov_reg(cd, Xd, Xm) emit_orr_sreg(cd, Xd, 31, Xm)
467 #define emit_mov_reg32(cd, Wd, Wm) emit_orr_sreg32(cd, Wd, 31, Wm)
468 
469 #define emit_tst_sreg(cd, Xn, Xm) emit_ands_sreg(cd, 31, Xn, Xm)
470 #define emit_tst_sreg32(cd, Wn, Wm) emit_ands_sreg32(cd, 31, Wn, Wm)
471 
472 #define emit_clr(cd, Xd) emit_eor_sreg(cd, Xd, Xd, Xd)
473 
474 inline void emit_mov(codegendata *cd, u1 Xd, u1 Xm) {
475  if (Xd == 31 || Xm == 31)
476  emit_mov_sp(cd, Xd, Xm);
477  else
478  emit_mov_reg(cd, Xd, Xm);
479 }
480 
481 
482 /* Floating-point comparison *************************************************/
483 
484 inline void emit_fp_cmp(codegendata *cd, u1 type, u1 Rm, u1 Rn, u1 opc)
485 {
486  *((u4 *) cd->mcodeptr) = LSL(type, 22) | LSL(Rm, 16) | LSL(Rn, 5)
487  | LSL(opc, 3) | 0x1E202000;
488  cd->mcodeptr += 4;
489 }
490 
491 
492 /* Floating-point data-processing (1 source) *********************************/
493 
494 inline void emit_fp_dp1(codegendata *cd, u1 M, u1 S, u1 type, u1 opc, u1 Rn, u1 Rd)
495 {
496  *((u4 *) cd->mcodeptr) = LSL(M, 31) | LSL(S, 29) | LSL(type, 22)
497  | LSL(opc, 15) | LSL(Rn, 5)
498  | Rd | 0x1E204000;
499  cd->mcodeptr += 4;
500 }
501 
502 #define emit_fmovs(cd, Sd, Sn) emit_fp_dp1(cd, 0, 0, 0, 0, Sn, Sd)
503 #define emit_fmovd(cd, Dd, Dn) emit_fp_dp1(cd, 0, 0, 1, 0, Dn, Dd)
504 
505 #define emit_fnegs(cd, Sd, Sn) emit_fp_dp1(cd, 0, 0, 0, 2, Sn, Sd)
506 #define emit_fnegd(cd, Dd, Dn) emit_fp_dp1(cd, 0, 0, 1, 2, Dn, Dd)
507 
508 /* Floating-point data-processing (2 source) *********************************/
509 
510 inline void emit_fp_dp2(codegendata *cd, u1 M, u1 S, u1 type, u1 Rm, u1 opc, u1 Rn, u1 Rd)
511 {
512  *((u4 *) cd->mcodeptr) = LSL(M, 31) | LSL(S, 29) | LSL(type, 22)
513  | LSL(Rm, 16) | LSL(opc, 12) | LSL(Rn, 5)
514  | Rd | 0x1E200800;
515  cd->mcodeptr += 4;
516 }
517 
518 #define emit_fmuls(cd, Sd, Sn, Sm) emit_fp_dp2(cd, 0, 0, 0, Sm, 0, Sn, Sd)
519 #define emit_fmuld(cd, Dd, Dn, Dm) emit_fp_dp2(cd, 0, 0, 1, Dm, 0, Dn, Dd)
520 
521 #define emit_fdivs(cd, Sd, Sn, Sm) emit_fp_dp2(cd, 0, 0, 0, Sm, 1, Sn, Sd)
522 #define emit_fdivd(cd, Dd, Dn, Dm) emit_fp_dp2(cd, 0, 0, 1, Dm, 1, Dn, Dd)
523 
524 #define emit_fadds(cd, Sd, Sn, Sm) emit_fp_dp2(cd, 0, 0, 0, Sm, 2, Sn, Sd)
525 #define emit_faddd(cd, Dd, Dn, Dm) emit_fp_dp2(cd, 0, 0, 1, Dm, 2, Dn, Dd)
526 
527 #define emit_fsubs(cd, Sd, Sn, Sm) emit_fp_dp2(cd, 0, 0, 0, Sm, 3, Sn, Sd)
528 #define emit_fsubd(cd, Dd, Dn, Dm) emit_fp_dp2(cd, 0, 0, 1, Dm, 3, Dn, Dd)
529 
530 
531 /* Convert floating-point precision ******************************************/
532 
533 inline void emit_fcvt(codegendata *cd, u1 type, u1 opc, u1 Rn, u1 Rd)
534 {
535  *((u4 *) cd->mcodeptr) = LSL(type, 22) | LSL(opc, 15) | LSL(Rn, 5)
536  | Rd | 0x1E224000;
537  cd->mcodeptr += 4;
538 }
539 
540 
541 /* Conversion between floating-point and integer *****************************/
542 
543 inline void emit_conversion_fp(codegendata *cd, u1 sf, u1 S, u1 type, u1 rmode, u1 opc, u1 Rn, u1 Rd)
544 {
545  *((u4 *) cd->mcodeptr) = LSL(sf, 31) | LSL(S, 29) | LSL(type, 22)
546  | LSL(rmode, 19) | LSL(opc, 16) | LSL(Rn, 5)
547  | Rd | 0x1E200000;
548  cd->mcodeptr += 4;
549 }
550 
551 #define emit_scvtf(cd, sf, type, Rn, Rd) emit_conversion_fp(cd, sf, 0, type, 0, 2, Rn, Rd)
552 #define emit_fcvtzs(cd, sf, type, Rn, Rd) emit_conversion_fp(cd, sf, 0, type, 3, 0, Rn, Rd)
553 
554 
555 /* Traps *********************************************************************/
556 
557 /**
558  * - First byte is the register.
559  * - Second byte is the type of the trap.
560  * - Bit 27 and 28 have to be 0 to be in the unallocated encoding space so we
561  * use E7 as our mark byte.
562  */
563 inline void emit_trap(codegendata *cd, u1 Xd, int type)
564 {
565  *((u4 *) cd->mcodeptr) = Xd | LSL(type & 0xff, 8) | 0xE7000000;
566  cd->mcodeptr += 4;
567 }
568 
569 
570 /* Barriers ******************************************************************/
571 
572 inline void emit_sync(codegendata *cd, u1 option, u1 opc)
573 {
574  *((u4 *) cd->mcodeptr) = LSL(option & 0xf, 8) | LSL(opc & 0x3, 5) | 0xD503309F;
575  cd->mcodeptr += 4;
576 }
577 
578 #define emit_dmb(cd, option) emit_sync(cd, option, 1);
579 #define emit_dsb(cd, option) emit_sync(cd, option, 0);
580 
581 
582 /* Misc **********************************************************************/
583 
584 inline void emit_nop(codegendata *cd)
585 {
586  *((u4 *) cd->mcodeptr) = (0xd503201f);
587  cd->mcodeptr += 4;
588 }
589 
590 #endif // VM_JIT_AARCH64_EMIT_ASM_HPP_
591 
592 /*
593  * These are local overrides for various environment variables in Emacs.
594  * Please do not remove this and leave it at the end of the file, where
595  * Emacs will automagically detect them.
596  * ---------------------------------------------------------------------
597  * Local variables:
598  * mode: c++
599  * indent-tabs-mode: t
600  * c-basic-offset: 4
601  * tab-width: 4
602  * End:
603  * vim:noexpandtab:sw=4:ts=4:
604  */
void emit_dp2(codegendata *cd, u1 sf, u1 S, u1 Rm, u1 opc, u1 Rn, u1 Rd)
Definition: emit-asm.hpp:403
void emit_fp_cmp(codegendata *cd, u1 type, u1 Rm, u1 Rn, u1 opc)
Definition: emit-asm.hpp:484
#define N(name)
Definition: icmd.cpp:34
#define emit_movn_imm(cd, Xd, imm)
Definition: emit-asm.hpp:144
u2 op
Definition: disass.cpp:129
#define LSR(x, a)
Definition: emit-asm.hpp:39
uint8_t u1
Definition: types.hpp:40
void emit_unc_branch_reg(codegendata *cd, u1 opc, u1 op2, u1 op3, u1 Rn, u1 op4)
Definition: emit-asm.hpp:119
void emit_addsub_imm(codegendata *cd, u1 sf, u1 op, u1 S, u1 shift, u2 imm12, u1 Rn, u1 Rd)
Definition: emit-asm.hpp:234
void emit_lda(codegendata *cd, u1 Xd, u1 Xn, s4 imm)
Definition: emit-asm.hpp:372
void emit_sync(codegendata *cd, u1 option, u1 opc)
Definition: emit-asm.hpp:572
void emit_fcvt(codegendata *cd, u1 type, u1 opc, u1 Rn, u1 Rd)
Definition: emit-asm.hpp:533
JNIEnv jthread jobject jclass jlong size
Definition: jvmti.h:387
void emit_mov(codegendata *cd, u1 Xd, u1 Xm)
Definition: emit-asm.hpp:474
void emit_fp_dp2(codegendata *cd, u1 M, u1 S, u1 type, u1 Rm, u1 opc, u1 Rn, u1 Rd)
Definition: emit-asm.hpp:510
void emit_ldstr_reg_reg(codegendata *cd, u1 size, u1 v, u1 opc, u1 Rm, u1 option, u1 S, u1 Rn, u1 Rt)
Definition: emit-asm.hpp:162
void emit_unc_branch_imm(codegendata *cd, u1 op, s4 imm26)
Definition: emit-asm.hpp:106
void emit_addsub_reg(codegendata *cd, u1 sf, u1 op, u1 S, u1 shift, u1 Rm, u1 imm6, u1 Rn, u1 Rd)
Definition: emit-asm.hpp:345
uint16_t u2
Definition: types.hpp:43
#define emit_add_imm(cd, Xd, Xn, imm)
Definition: emit-asm.hpp:256
#define LSL(x, a)
Definition: emit-asm.hpp:38
#define emit_sub_imm(cd, Xd, Xn, imm)
Definition: emit-asm.hpp:259
void emit_mov_wide_imm(codegendata *cd, u1 sf, u1 opc, u1 hw, u2 imm16, u1 Rd)
Definition: emit-asm.hpp:134
void emit_trap(codegendata *cd, u1 Xd, int type)
Definition: emit-asm.hpp:563
void emit_logical_imm(codegendata *cd, u1 sf, u1 opc, u2 imm, u1 Rn, u1 Rd)
Definition: emit-asm.hpp:315
void emit_ldstr_reg_usc(codegendata *cd, u1 size, u1 v, u1 opc, s2 imm9, u1 Rt, u1 Rn)
Definition: emit-asm.hpp:152
int32_t s4
Definition: types.hpp:45
void emit_conversion_fp(codegendata *cd, u1 sf, u1 S, u1 type, u1 rmode, u1 opc, u1 Rn, u1 Rd)
Definition: emit-asm.hpp:543
void emit_bitfield(codegendata *cd, u1 sf, u1 opc, u1 N, u1 immr, u1 imms, u1 Rn, u1 Rd)
Definition: emit-asm.hpp:279
static void abort()
Definition: os.hpp:196
void emit_ldstr_ambigous(codegendata *cd, u1 size, u1 v, u1 opc, s2 imm, u1 Rt, u1 Rn)
Definition: emit-asm.hpp:188
uint32_t u4
Definition: types.hpp:46
void emit_cond_select(codegendata *cd, u1 sf, u1 op, u1 S, u1 Rm, u1 cond, u1 op2, u1 Rn, u1 Rd)
Definition: emit-asm.hpp:383
void emit_logical_sreg(codegendata *cd, u1 sf, u1 opc, u1 shift, u1 N, u1 Rm, u1 imm6, u1 Rn, u1 Rd)
Definition: emit-asm.hpp:445
void emit_fp_dp1(codegendata *cd, u1 M, u1 S, u1 type, u1 opc, u1 Rn, u1 Rd)
Definition: emit-asm.hpp:494
void emit_nop(codegendata *cd)
Definition: emit-asm.hpp:584
void emit_dp3(codegendata *cd, u1 sf, u1 op31, u1 Rm, u1 o0, u1 Ra, u1 Rn, u1 Rd)
Definition: emit-asm.hpp:425
const Method & M
int16_t s2
Definition: types.hpp:42
#define emit_mov_sp(cd, Xd, Xn)
Definition: emit-asm.hpp:268
void emit_cond_branch_imm(codegendata *cd, s4 imm19, u1 cond)
Definition: emit-asm.hpp:82
void emit_ldstr_reg_us(codegendata *cd, u1 size, u1 v, u1 opc, u2 imm12, u1 Rt, u1 Rn)
Definition: emit-asm.hpp:175
#define REG_ITMP3
Definition: md-abi.hpp:48
void emit_cmp_branch_imm(codegendata *cd, u1 sf, u1 op, s4 imm, u1 Rt)
Definition: emit-asm.hpp:70
#define emit_mov_reg(cd, Xd, Xm)
Definition: emit-asm.hpp:466
void emit_pcrel(codegendata *cd, u1 op, u1 immlo, u4 immhi, u1 Rd)
Definition: emit-asm.hpp:334