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