Line data Source code
1 : /* src/vm/jit/x86_64/codegen.cpp - machine code generator for x86_64
2 :
3 : Copyright (C) 1996-2013
4 : CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
5 :
6 : This file is part of CACAO.
7 :
8 : This program is free software; you can redistribute it and/or
9 : modify it under the terms of the GNU General Public License as
10 : published by the Free Software Foundation; either version 2, or (at
11 : your option) any later version.
12 :
13 : This program is distributed in the hope that it will be useful, but
14 : WITHOUT ANY WARRANTY; without even the implied warranty of
15 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 : 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; if not, write to the Free Software
20 : Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 : 02110-1301, USA.
22 :
23 : */
24 :
25 :
26 : #include "config.h"
27 :
28 : #include <cassert>
29 : #include <cstdio>
30 : #include <stdint.h>
31 :
32 : #include "vm/types.hpp"
33 : #include "vm/os.hpp"
34 :
35 : #include "md-abi.hpp"
36 :
37 : #include "vm/jit/x86_64/codegen.hpp"
38 : #include "vm/jit/x86_64/emit.hpp"
39 :
40 : #include "mm/memory.hpp"
41 :
42 : #include "native/localref.hpp"
43 : #include "native/native.hpp"
44 :
45 : #include "threads/lock.hpp"
46 :
47 : #include "vm/descriptor.hpp"
48 : #include "vm/exceptions.hpp"
49 : #include "vm/field.hpp"
50 : #include "vm/global.hpp"
51 : #include "vm/options.hpp"
52 : #include "vm/primitive.hpp"
53 : #include "vm/statistics.hpp"
54 : #include "vm/vm.hpp"
55 :
56 : #include "vm/jit/abi.hpp"
57 : #include "vm/jit/asmpart.hpp"
58 : #include "vm/jit/builtin.hpp"
59 : #include "vm/jit/code.hpp"
60 : #include "vm/jit/codegen-common.hpp"
61 : #include "vm/jit/dseg.hpp"
62 : #include "vm/jit/emit-common.hpp"
63 : #include "vm/jit/jit.hpp"
64 : #include "vm/jit/linenumbertable.hpp"
65 : #include "vm/jit/methodheader.hpp"
66 : #include "vm/jit/parse.hpp"
67 : #include "vm/jit/patcher-common.hpp"
68 : #include "vm/jit/reg.hpp"
69 : #include "vm/jit/stacktrace.hpp"
70 : #include "vm/jit/trap.hpp"
71 :
72 :
73 : /**
74 : * Generates machine code for the method prolog.
75 : */
76 86399 : void codegen_emit_prolog(jitdata* jd)
77 : {
78 : varinfo* var;
79 : methoddesc* md;
80 : int32_t s1;
81 : int32_t p, t, l;
82 : int32_t varindex;
83 : int i;
84 :
85 : // Get required compiler data.
86 86399 : methodinfo* m = jd->m;
87 86399 : codegendata* cd = jd->cd;
88 86399 : registerdata* rd = jd->rd;
89 :
90 : /* create stack frame (if necessary) */
91 :
92 86399 : if (cd->stackframesize)
93 76451 : M_ASUB_IMM(cd->stackframesize * 8, REG_SP);
94 :
95 : /* save used callee saved registers */
96 :
97 86399 : p = cd->stackframesize;
98 286160 : for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
99 199761 : p--; M_LST(rd->savintregs[i], REG_SP, p * 8);
100 : }
101 86399 : for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
102 0 : p--; M_DST(rd->savfltregs[i], REG_SP, p * 8);
103 : }
104 :
105 : /* take arguments out of register or stack frame */
106 :
107 86399 : md = m->parseddesc;
108 :
109 227649 : for (p = 0, l = 0; p < md->paramcount; p++) {
110 141250 : t = md->paramtypes[p].type;
111 :
112 141250 : varindex = jd->local_map[l * 5 + t];
113 :
114 141250 : l++;
115 141250 : if (IS_2_WORD_TYPE(t)) /* increment local counter for 2 word types */
116 412 : l++;
117 :
118 141250 : if (varindex == jitdata::UNUSED)
119 5607 : continue;
120 :
121 135643 : var = VAR(varindex);
122 :
123 135643 : s1 = md->params[p].regoff;
124 :
125 135643 : if (IS_INT_LNG_TYPE(t)) { /* integer args */
126 134212 : if (!md->params[p].inmemory) { /* register arguments */
127 131907 : if (!IS_INMEMORY(var->flags))
128 126890 : M_INTMOVE(s1, var->vv.regoff);
129 : else
130 5017 : M_LST(s1, REG_SP, var->vv.regoff);
131 : }
132 : else { /* stack arguments */
133 2305 : if (!IS_INMEMORY(var->flags))
134 : /* + 8 for return address */
135 3 : M_LLD(var->vv.regoff, REG_SP, cd->stackframesize * 8 + s1 + 8);
136 : else
137 2302 : var->vv.regoff = cd->stackframesize * 8 + s1 + 8;
138 : }
139 : }
140 : else { /* floating args */
141 : // With SSE, the fst/dld instructions don't actually mean "store a
142 : // float/double to memory", but rather "store the lower 32/64 bits
143 : // of the register to memory". Therefore we get by with treating
144 : // all floating point values the same.
145 1431 : if (!md->params[p].inmemory) { /* register arguments */
146 1383 : if (!IS_INMEMORY(var->flags))
147 23 : emit_fmove(cd, s1, var->vv.regoff);
148 : else
149 1360 : M_DST(s1, REG_SP, var->vv.regoff);
150 : }
151 : else { /* stack arguments */
152 48 : if (!IS_INMEMORY(var->flags))
153 0 : M_DLD(var->vv.regoff, REG_SP, cd->stackframesize * 8 + s1 + 8);
154 : else
155 48 : var->vv.regoff = cd->stackframesize * 8 + s1 + 8;
156 : }
157 : }
158 : }
159 86399 : }
160 :
161 :
162 : /**
163 : * Generates machine code for the method epilog.
164 : */
165 103267 : void codegen_emit_epilog(jitdata* jd)
166 : {
167 : int32_t p;
168 : int i;
169 :
170 : // Get required compiler data.
171 103267 : codegendata* cd = jd->cd;
172 103267 : registerdata* rd = jd->rd;
173 :
174 103267 : p = cd->stackframesize;
175 :
176 : /* restore saved registers */
177 :
178 357549 : for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
179 254282 : p--; M_LLD(rd->savintregs[i], REG_SP, p * 8);
180 : }
181 103267 : for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
182 0 : p--; M_DLD(rd->savfltregs[i], REG_SP, p * 8);
183 : }
184 :
185 : /* deallocate stack */
186 :
187 103267 : if (cd->stackframesize)
188 91235 : M_AADD_IMM(cd->stackframesize * 8, REG_SP);
189 :
190 103267 : M_RET;
191 103267 : }
192 :
193 : /**
194 : * Generates a memory barrier to be used after volatile writes. It can be
195 : * patched out later if the field turns out not to be volatile.
196 : */
197 74865 : void codegen_emit_patchable_barrier(instruction *iptr, codegendata *cd, patchref_t *pr, fieldinfo *fi)
198 : {
199 74865 : if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
200 : /* Align on word boundary */
201 2055 : if ((((intptr_t) cd->mcodeptr) & 3) >= 2)
202 163 : emit_nop(cd, 4 - (((intptr_t) cd->mcodeptr) & 3));
203 : /* Displacement for patching out MFENCE */
204 2055 : pr->disp_mb = (cd->mcodeptr - cd->mcodebase - pr->mpc);
205 : }
206 74865 : if (INSTRUCTION_IS_UNRESOLVED(iptr) || fi->flags & ACC_VOLATILE)
207 3142 : M_MFENCE;
208 74865 : }
209 :
210 : /**
211 : * Ensures that the patched location (an int32_t) is aligned.
212 : */
213 1391 : static void codegen_fixup_alignment(codegendata *cd, patchref_t *pr, u1 *mcodeptr_save)
214 : {
215 1391 : u1 *codeptr = cd->mcodeptr;
216 1391 : int disp = PATCH_ALIGNMENT((uintptr_t) cd->mcodeptr, 0, sizeof(int32_t));
217 1391 : memmove(mcodeptr_save + disp, mcodeptr_save, cd->mcodeptr - mcodeptr_save);
218 1391 : pr->patch_align += cd->mcodeptr - mcodeptr_save + disp;
219 :
220 1391 : cd->mcodeptr = mcodeptr_save;
221 1391 : emit_arbitrary_nop(cd, disp);
222 1391 : cd->mcodeptr = codeptr + disp;
223 1391 : }
224 :
225 : /**
226 : * Generates machine code for one ICMD.
227 : */
228 1368799 : void codegen_emit_instruction(jitdata* jd, instruction* iptr)
229 : {
230 : varinfo* var;
231 : varinfo* dst;
232 : builtintable_entry* bte;
233 : methodinfo* lm; // Local methodinfo for ICMD_INVOKE*.
234 : unresolved_method* um;
235 : fieldinfo* fi;
236 : unresolved_field* uf;
237 : patchref_t* pr;
238 : int32_t fieldtype;
239 : int32_t s1, s2, s3, d;
240 : int32_t disp;
241 1368799 : u1* mcodeptr_save = NULL;
242 :
243 : // Get required compiler data.
244 1368799 : codegendata* cd = jd->cd;
245 :
246 1368799 : switch (iptr->opc) {
247 :
248 : /* constant operations ************************************************/
249 :
250 : case ICMD_FCONST: /* ... ==> ..., constant */
251 :
252 4946 : d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
253 4946 : disp = dseg_add_float(cd, iptr->sx.val.f);
254 4946 : emit_movdl_membase_reg(cd, RIP, -((cd->mcodeptr + ((d > 7) ? 9 : 8)) - cd->mcodebase) + disp, d);
255 4946 : emit_store_dst(jd, iptr, d);
256 4946 : break;
257 :
258 : case ICMD_DCONST: /* ... ==> ..., constant */
259 :
260 233 : d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
261 233 : disp = dseg_add_double(cd, iptr->sx.val.d);
262 233 : emit_movd_membase_reg(cd, RIP, -((cd->mcodeptr + 9) - cd->mcodebase) + disp, d);
263 233 : emit_store_dst(jd, iptr, d);
264 233 : break;
265 :
266 : case ICMD_ACONST: /* ... ==> ..., constant */
267 :
268 165085 : d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
269 :
270 165085 : if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
271 32158 : constant_classref *cr = iptr->sx.val.c.ref;
272 32158 : disp = dseg_add_unique_address(cd, cr);
273 :
274 : /* PROFILE_CYCLE_STOP; */
275 :
276 : patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_classinfo,
277 32158 : cr, disp);
278 :
279 : /* PROFILE_CYCLE_START; */
280 :
281 32158 : M_ALD(d, RIP, disp);
282 : }
283 : else {
284 132927 : if (iptr->sx.val.anyptr == 0) {
285 11807 : M_CLR(d);
286 : }
287 : else {
288 121120 : disp = dseg_add_address(cd, iptr->sx.val.anyptr);
289 121120 : M_ALD(d, RIP, disp);
290 : }
291 : }
292 165085 : emit_store_dst(jd, iptr, d);
293 165085 : break;
294 :
295 :
296 : /* integer operations *************************************************/
297 :
298 : case ICMD_INEG: /* ..., value ==> ..., - value */
299 :
300 756 : s1 = emit_load_s1(jd, iptr, REG_ITMP1);
301 756 : d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
302 756 : M_INTMOVE(s1, d);
303 756 : M_INEG(d);
304 756 : emit_store_dst(jd, iptr, d);
305 756 : break;
306 :
307 : case ICMD_LNEG: /* ..., value ==> ..., - value */
308 :
309 50 : s1 = emit_load_s1(jd, iptr, REG_ITMP1);
310 50 : d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
311 50 : M_INTMOVE(s1, d);
312 50 : M_LNEG(d);
313 50 : emit_store_dst(jd, iptr, d);
314 50 : break;
315 :
316 : case ICMD_I2L: /* ..., value ==> ..., value */
317 :
318 370 : s1 = emit_load_s1(jd, iptr, REG_ITMP1);
319 370 : d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
320 370 : M_ISEXT(s1, d);
321 370 : emit_store_dst(jd, iptr, d);
322 370 : break;
323 :
324 : case ICMD_L2I: /* ..., value ==> ..., value */
325 :
326 267 : s1 = emit_load_s1(jd, iptr, REG_ITMP1);
327 267 : d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
328 267 : M_IMOV(s1, d);
329 267 : emit_store_dst(jd, iptr, d);
330 267 : break;
331 :
332 : case ICMD_INT2BYTE: /* ..., value ==> ..., value */
333 :
334 272 : s1 = emit_load_s1(jd, iptr, REG_ITMP1);
335 272 : d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
336 272 : M_BSEXT(s1, d);
337 272 : emit_store_dst(jd, iptr, d);
338 272 : break;
339 :
340 : case ICMD_INT2CHAR: /* ..., value ==> ..., value */
341 :
342 1037 : s1 = emit_load_s1(jd, iptr, REG_ITMP1);
343 1037 : d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
344 1037 : M_CZEXT(s1, d);
345 1037 : emit_store_dst(jd, iptr, d);
346 1037 : break;
347 :
348 : case ICMD_INT2SHORT: /* ..., value ==> ..., value */
349 :
350 144 : s1 = emit_load_s1(jd, iptr, REG_ITMP1);
351 144 : d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
352 144 : M_SSEXT(s1, d);
353 144 : emit_store_dst(jd, iptr, d);
354 144 : break;
355 :
356 :
357 : case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
358 :
359 6032 : s1 = emit_load_s1(jd, iptr, REG_ITMP1);
360 6032 : s2 = emit_load_s2(jd, iptr, REG_ITMP2);
361 6032 : d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
362 6032 : if (s2 == d)
363 376 : M_IADD(s1, d);
364 : else {
365 5656 : M_INTMOVE(s1, d);
366 5656 : M_IADD(s2, d);
367 : }
368 6032 : emit_store_dst(jd, iptr, d);
369 6032 : break;
370 :
371 : case ICMD_IINC:
372 : case ICMD_IADDCONST: /* ..., value ==> ..., value + constant */
373 : /* sx.val.i = constant */
374 :
375 19771 : s1 = emit_load_s1(jd, iptr, REG_ITMP1);
376 19771 : d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
377 :
378 : /* Using inc and dec is not faster than add (tested with
379 : sieve). */
380 :
381 19771 : M_INTMOVE(s1, d);
382 19771 : M_IADD_IMM(iptr->sx.val.i, d);
383 19771 : emit_store_dst(jd, iptr, d);
384 19771 : break;
385 :
386 : case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */
387 :
388 132 : s1 = emit_load_s1(jd, iptr, REG_ITMP1);
389 132 : s2 = emit_load_s2(jd, iptr, REG_ITMP2);
390 132 : d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
391 132 : if (s2 == d)
392 12 : M_LADD(s1, d);
393 : else {
394 120 : M_INTMOVE(s1, d);
395 120 : M_LADD(s2, d);
396 : }
397 132 : emit_store_dst(jd, iptr, d);
398 132 : break;
399 :
400 : case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
401 : /* sx.val.l = constant */
402 :
403 192 : s1 = emit_load_s1(jd, iptr, REG_ITMP1);
404 192 : d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
405 192 : M_INTMOVE(s1, d);
406 381 : if (IS_IMM32(iptr->sx.val.l))
407 189 : M_LADD_IMM(iptr->sx.val.l, d);
408 : else {
409 3 : M_MOV_IMM(iptr->sx.val.l, REG_ITMP2);
410 3 : M_LADD(REG_ITMP2, d);
411 : }
412 192 : emit_store_dst(jd, iptr, d);
413 192 : break;
414 :
415 : case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
416 :
417 3458 : s1 = emit_load_s1(jd, iptr, REG_ITMP1);
418 3458 : s2 = emit_load_s2(jd, iptr, REG_ITMP2);
419 3458 : d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
420 3458 : if (s2 == d) {
421 749 : M_INTMOVE(s1, REG_ITMP1);
422 749 : M_ISUB(s2, REG_ITMP1);
423 749 : M_INTMOVE(REG_ITMP1, d);
424 : } else {
425 2709 : M_INTMOVE(s1, d);
426 2709 : M_ISUB(s2, d);
427 : }
428 3458 : emit_store_dst(jd, iptr, d);
429 3458 : break;
430 :
431 : case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
432 : /* sx.val.i = constant */
433 :
434 4732 : s1 = emit_load_s1(jd, iptr, REG_ITMP1);
435 4732 : d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
436 4732 : M_INTMOVE(s1, d);
437 4732 : M_ISUB_IMM(iptr->sx.val.i, d);
438 4732 : emit_store_dst(jd, iptr, d);
439 4732 : break;
440 :
441 : case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
442 :
443 59 : s1 = emit_load_s1(jd, iptr, REG_ITMP1);
444 59 : s2 = emit_load_s2(jd, iptr, REG_ITMP2);
445 59 : d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
446 59 : if (s2 == d) {
447 4 : M_INTMOVE(s1, REG_ITMP1);
448 4 : M_LSUB(s2, REG_ITMP1);
449 4 : M_INTMOVE(REG_ITMP1, d);
450 : } else {
451 55 : M_INTMOVE(s1, d);
452 55 : M_LSUB(s2, d);
453 : }
454 59 : emit_store_dst(jd, iptr, d);
455 59 : break;
456 :
457 : case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
458 : /* sx.val.l = constant */
459 :
460 31 : s1 = emit_load_s1(jd, iptr, REG_ITMP1);
461 31 : d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
462 31 : M_INTMOVE(s1, d);
463 60 : if (IS_IMM32(iptr->sx.val.l))
464 29 : M_LSUB_IMM(iptr->sx.val.l, d);
465 : else {
466 2 : M_MOV_IMM(iptr->sx.val.l, REG_ITMP2);
467 2 : M_LSUB(REG_ITMP2, d);
468 : }
469 31 : emit_store_dst(jd, iptr, d);
470 31 : break;
471 :
472 : case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
473 :
474 100 : s1 = emit_load_s1(jd, iptr, REG_ITMP1);
475 100 : s2 = emit_load_s2(jd, iptr, REG_ITMP2);
476 100 : d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
477 100 : if (s2 == d)
478 7 : M_IMUL(s1, d);
479 : else {
480 93 : M_INTMOVE(s1, d);
481 93 : M_IMUL(s2, d);
482 : }
483 100 : emit_store_dst(jd, iptr, d);
484 100 : break;
485 :
486 : case ICMD_IMULCONST: /* ..., value ==> ..., value * constant */
487 : /* sx.val.i = constant */
488 :
489 866 : s1 = emit_load_s1(jd, iptr, REG_ITMP1);
490 866 : d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
491 866 : if (iptr->sx.val.i == 2) {
492 556 : M_INTMOVE(s1, d);
493 556 : M_ISLL_IMM(1, d);
494 : } else
495 310 : M_IMUL_IMM(s1, iptr->sx.val.i, d);
496 866 : emit_store_dst(jd, iptr, d);
497 866 : break;
498 :
499 : case ICMD_LMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
500 :
501 7 : s1 = emit_load_s1(jd, iptr, REG_ITMP1);
502 7 : s2 = emit_load_s2(jd, iptr, REG_ITMP2);
503 7 : d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
504 7 : if (s2 == d)
505 4 : M_LMUL(s1, d);
506 : else {
507 3 : M_INTMOVE(s1, d);
508 3 : M_LMUL(s2, d);
509 : }
510 7 : emit_store_dst(jd, iptr, d);
511 7 : break;
512 :
513 : case ICMD_LMULCONST: /* ..., value ==> ..., value * constant */
514 : /* sx.val.l = constant */
515 :
516 12 : s1 = emit_load_s1(jd, iptr, REG_ITMP1);
517 12 : d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
518 22 : if (IS_IMM32(iptr->sx.val.l))
519 10 : M_LMUL_IMM(s1, iptr->sx.val.l, d);
520 : else {
521 2 : M_MOV_IMM(iptr->sx.val.l, REG_ITMP2);
522 2 : M_INTMOVE(s1, d);
523 2 : M_LMUL(REG_ITMP2, d);
524 : }
525 12 : emit_store_dst(jd, iptr, d);
526 12 : break;
527 :
528 : case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
529 :
530 297 : s1 = emit_load_s1(jd, iptr, RAX);
531 297 : s2 = emit_load_s2(jd, iptr, REG_ITMP3);
532 297 : d = codegen_reg_of_dst(jd, iptr, RAX);
533 :
534 297 : M_INTMOVE(s1, RAX);
535 297 : M_INTMOVE(s2, REG_ITMP3);
536 297 : emit_arithmetic_check(cd, iptr, REG_ITMP3);
537 :
538 297 : M_MOV(RDX, REG_ITMP2); /* save RDX (it's an argument register) */
539 :
540 297 : M_ICMP_IMM(0x80000000, RAX); /* check as described in jvm spec */
541 297 : M_BNE(4 + 6);
542 297 : M_ICMP_IMM(-1, REG_ITMP3); /* 4 bytes */
543 297 : M_BEQ(1 + 3); /* 6 bytes */
544 :
545 297 : emit_cltd(cd); /* 1 byte */
546 297 : emit_idivl_reg(cd, REG_ITMP3); /* 3 bytes */
547 :
548 297 : M_INTMOVE(RAX, d);
549 297 : emit_store_dst(jd, iptr, d);
550 297 : dst = VAROP(iptr->dst);
551 297 : if (IS_INMEMORY(dst->flags) || (dst->vv.regoff != RDX))
552 297 : M_MOV(REG_ITMP2, RDX); /* restore RDX */
553 297 : break;
554 :
555 : case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
556 :
557 1588 : s1 = emit_load_s1(jd, iptr, RAX);
558 1588 : s2 = emit_load_s2(jd, iptr, REG_ITMP3);
559 1588 : d = codegen_reg_of_dst(jd, iptr, RDX);
560 :
561 1588 : M_INTMOVE(s1, RAX);
562 1588 : M_INTMOVE(s2, REG_ITMP3);
563 1588 : emit_arithmetic_check(cd, iptr, REG_ITMP3);
564 :
565 1588 : M_MOV(RDX, REG_ITMP2); /* save RDX (it's an argument register) */
566 :
567 1588 : M_ICMP_IMM(0x80000000, RAX); /* check as described in jvm spec */
568 1588 : M_BNE(3 + 4 + 6);
569 1588 : M_CLR(RDX); /* 3 bytes */
570 1588 : M_ICMP_IMM(-1, REG_ITMP3); /* 4 bytes */
571 1588 : M_BEQ(1 + 3); /* 6 bytes */
572 :
573 1588 : emit_cltd(cd); /* 1 byte */
574 1588 : emit_idivl_reg(cd, REG_ITMP3); /* 3 byte */
575 :
576 1588 : M_INTMOVE(RDX, d);
577 1588 : emit_store_dst(jd, iptr, d);
578 1588 : dst = VAROP(iptr->dst);
579 1588 : if (IS_INMEMORY(dst->flags) || (dst->vv.regoff != RDX))
580 578 : M_MOV(REG_ITMP2, RDX); /* restore RDX */
581 1588 : break;
582 :
583 : case ICMD_IDIVPOW2: /* ..., value ==> ..., value >> constant */
584 : /* sx.val.i = constant */
585 :
586 51 : s1 = emit_load_s1(jd, iptr, REG_ITMP1);
587 51 : d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
588 51 : M_INTMOVE(s1, REG_ITMP1);
589 51 : emit_alul_imm_reg(cd, ALU_CMP, -1, REG_ITMP1);
590 51 : emit_leal_membase_reg(cd, REG_ITMP1, (1 << iptr->sx.val.i) - 1, REG_ITMP2);
591 51 : emit_cmovccl_reg_reg(cd, CC_LE, REG_ITMP2, REG_ITMP1);
592 51 : emit_shiftl_imm_reg(cd, SHIFT_SAR, iptr->sx.val.i, REG_ITMP1);
593 51 : emit_mov_reg_reg(cd, REG_ITMP1, d);
594 51 : emit_store_dst(jd, iptr, d);
595 51 : break;
596 :
597 : case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
598 : /* sx.val.i = constant */
599 :
600 31 : s1 = emit_load_s1(jd, iptr, REG_ITMP1);
601 31 : d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
602 31 : M_INTMOVE(s1, REG_ITMP1);
603 31 : emit_alul_imm_reg(cd, ALU_CMP, -1, REG_ITMP1);
604 31 : emit_leal_membase_reg(cd, REG_ITMP1, iptr->sx.val.i, REG_ITMP2);
605 31 : emit_cmovccl_reg_reg(cd, CC_G, REG_ITMP1, REG_ITMP2);
606 31 : emit_alul_imm_reg(cd, ALU_AND, -1 - (iptr->sx.val.i), REG_ITMP2);
607 31 : emit_alul_reg_reg(cd, ALU_SUB, REG_ITMP2, REG_ITMP1);
608 31 : emit_mov_reg_reg(cd, REG_ITMP1, d);
609 31 : emit_store_dst(jd, iptr, d);
610 31 : break;
611 :
612 :
613 : case ICMD_LDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
614 :
615 31 : s1 = emit_load_s1(jd, iptr, RAX);
616 31 : s2 = emit_load_s2(jd, iptr, REG_ITMP3);
617 31 : d = codegen_reg_of_dst(jd, iptr, RAX);
618 :
619 31 : M_INTMOVE(s1, RAX);
620 31 : M_INTMOVE(s2, REG_ITMP3);
621 31 : emit_arithmetic_check(cd, iptr, REG_ITMP3);
622 :
623 31 : M_MOV(RDX, REG_ITMP2); /* save RDX (it's an argument register) */
624 :
625 : /* check as described in jvm spec */
626 31 : disp = dseg_add_s8(cd, 0x8000000000000000LL);
627 31 : M_LCMP_MEMBASE(RIP, -((cd->mcodeptr + 7) - cd->mcodebase) + disp, RAX);
628 31 : M_BNE(4 + 6);
629 31 : M_LCMP_IMM(-1, REG_ITMP3); /* 4 bytes */
630 31 : M_BEQ(2 + 3); /* 6 bytes */
631 :
632 31 : emit_cqto(cd); /* 2 bytes */
633 31 : emit_idiv_reg(cd, REG_ITMP3); /* 3 bytes */
634 :
635 31 : M_INTMOVE(RAX, d);
636 31 : emit_store_dst(jd, iptr, d);
637 31 : dst = VAROP(iptr->dst);
638 31 : if (IS_INMEMORY(dst->flags) || (dst->vv.regoff != RDX))
639 31 : M_MOV(REG_ITMP2, RDX); /* restore RDX */
640 31 : break;
641 :
642 : case ICMD_LREM: /* ..., val1, val2 ==> ..., val1 % val2 */
643 :
644 30 : s1 = emit_load_s1(jd, iptr, RAX);
645 30 : s2 = emit_load_s2(jd, iptr, REG_ITMP3);
646 30 : d = codegen_reg_of_dst(jd, iptr, RDX);
647 :
648 30 : M_INTMOVE(s1, RAX);
649 30 : M_INTMOVE(s2, REG_ITMP3);
650 30 : emit_arithmetic_check(cd, iptr, REG_ITMP3);
651 :
652 30 : M_MOV(RDX, REG_ITMP2); /* save RDX (it's an argument register) */
653 :
654 : /* check as described in jvm spec */
655 30 : disp = dseg_add_s8(cd, 0x8000000000000000LL);
656 30 : M_LCMP_MEMBASE(RIP, -((cd->mcodeptr + 7) - cd->mcodebase) + disp, REG_ITMP1);
657 30 : M_BNE(3 + 4 + 6);
658 30 : M_LXOR(RDX, RDX); /* 3 bytes */
659 30 : M_LCMP_IMM(-1, REG_ITMP3); /* 4 bytes */
660 30 : M_BEQ(2 + 3); /* 6 bytes */
661 :
662 30 : emit_cqto(cd); /* 2 bytes */
663 30 : emit_idiv_reg(cd, REG_ITMP3); /* 3 bytes */
664 :
665 30 : M_INTMOVE(RDX, d);
666 30 : emit_store_dst(jd, iptr, d);
667 30 : dst = VAROP(iptr->dst);
668 30 : if (IS_INMEMORY(dst->flags) || (dst->vv.regoff != RDX))
669 26 : M_MOV(REG_ITMP2, RDX); /* restore RDX */
670 30 : break;
671 :
672 : case ICMD_LDIVPOW2: /* ..., value ==> ..., value >> constant */
673 : /* sx.val.i = constant */
674 :
675 30 : s1 = emit_load_s1(jd, iptr, REG_ITMP1);
676 30 : d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
677 30 : M_INTMOVE(s1, REG_ITMP1);
678 30 : emit_alu_imm_reg(cd, ALU_CMP, -1, REG_ITMP1);
679 30 : emit_lea_membase_reg(cd, REG_ITMP1, (1 << iptr->sx.val.i) - 1, REG_ITMP2);
680 30 : emit_cmovcc_reg_reg(cd, CC_LE, REG_ITMP2, REG_ITMP1);
681 30 : emit_shift_imm_reg(cd, SHIFT_SAR, iptr->sx.val.i, REG_ITMP1);
682 30 : emit_mov_reg_reg(cd, REG_ITMP1, d);
683 30 : emit_store_dst(jd, iptr, d);
684 30 : break;
685 :
686 : case ICMD_LREMPOW2: /* ..., value ==> ..., value % constant */
687 : /* sx.val.l = constant */
688 :
689 31 : s1 = emit_load_s1(jd, iptr, REG_ITMP1);
690 31 : d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
691 31 : M_INTMOVE(s1, REG_ITMP1);
692 31 : emit_alu_imm_reg(cd, ALU_CMP, -1, REG_ITMP1);
693 31 : emit_lea_membase_reg(cd, REG_ITMP1, iptr->sx.val.i, REG_ITMP2);
694 31 : emit_cmovcc_reg_reg(cd, CC_G, REG_ITMP1, REG_ITMP2);
695 31 : emit_alu_imm_reg(cd, ALU_AND, -1 - (iptr->sx.val.i), REG_ITMP2);
696 31 : emit_alu_reg_reg(cd, ALU_SUB, REG_ITMP2, REG_ITMP1);
697 31 : emit_mov_reg_reg(cd, REG_ITMP1, d);
698 31 : emit_store_dst(jd, iptr, d);
699 31 : break;
700 :
701 : case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
702 :
703 96 : d = codegen_reg_of_dst(jd, iptr, REG_NULL);
704 96 : emit_ishift(jd, SHIFT_SHL, iptr);
705 96 : break;
706 :
707 : case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
708 : /* sx.val.i = constant */
709 :
710 499 : s1 = emit_load_s1(jd, iptr, REG_ITMP1);
711 499 : d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
712 499 : M_INTMOVE(s1, d);
713 499 : M_ISLL_IMM(iptr->sx.val.i, d);
714 499 : emit_store_dst(jd, iptr, d);
715 499 : break;
716 :
717 : case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
718 :
719 148 : d = codegen_reg_of_dst(jd, iptr, REG_NULL);
720 148 : emit_ishift(jd, SHIFT_SAR, iptr);
721 148 : break;
722 :
723 : case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
724 : /* sx.val.i = constant */
725 :
726 185 : s1 = emit_load_s1(jd, iptr, REG_ITMP1);
727 185 : d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
728 185 : M_INTMOVE(s1, d);
729 185 : M_ISRA_IMM(iptr->sx.val.i, d);
730 185 : emit_store_dst(jd, iptr, d);
731 185 : break;
732 :
733 : case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
734 :
735 74 : d = codegen_reg_of_dst(jd, iptr, REG_NULL);
736 74 : emit_ishift(jd, SHIFT_SHR, iptr);
737 74 : break;
738 :
739 : case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
740 : /* sx.val.i = constant */
741 :
742 328 : s1 = emit_load_s1(jd, iptr, REG_ITMP1);
743 328 : d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
744 328 : M_INTMOVE(s1, d);
745 328 : M_ISRL_IMM(iptr->sx.val.i, d);
746 328 : emit_store_dst(jd, iptr, d);
747 328 : break;
748 :
749 : case ICMD_LSHL: /* ..., val1, val2 ==> ..., val1 << val2 */
750 :
751 13 : d = codegen_reg_of_dst(jd, iptr, REG_NULL);
752 13 : emit_lshift(jd, SHIFT_SHL, iptr);
753 13 : break;
754 :
755 : case ICMD_LSHLCONST: /* ..., value ==> ..., value << constant */
756 : /* sx.val.i = constant */
757 :
758 16 : s1 = emit_load_s1(jd, iptr, REG_ITMP1);
759 16 : d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
760 16 : M_INTMOVE(s1, d);
761 16 : M_LSLL_IMM(iptr->sx.val.i, d);
762 16 : emit_store_dst(jd, iptr, d);
763 16 : break;
764 :
765 : case ICMD_LSHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
766 :
767 1 : d = codegen_reg_of_dst(jd, iptr, REG_NULL);
768 1 : emit_lshift(jd, SHIFT_SAR, iptr);
769 1 : break;
770 :
771 : case ICMD_LSHRCONST: /* ..., value ==> ..., value >> constant */
772 : /* sx.val.i = constant */
773 :
774 25 : s1 = emit_load_s1(jd, iptr, REG_ITMP1);
775 25 : d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
776 25 : M_INTMOVE(s1, d);
777 25 : M_LSRA_IMM(iptr->sx.val.i, d);
778 25 : emit_store_dst(jd, iptr, d);
779 25 : break;
780 :
781 : case ICMD_LUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
782 :
783 17 : d = codegen_reg_of_dst(jd, iptr, REG_NULL);
784 17 : emit_lshift(jd, SHIFT_SHR, iptr);
785 17 : break;
786 :
787 : case ICMD_LUSHRCONST: /* ..., value ==> ..., value >>> constant */
788 : /* sx.val.l = constant */
789 :
790 13 : s1 = emit_load_s1(jd, iptr, REG_ITMP1);
791 13 : d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
792 13 : M_INTMOVE(s1, d);
793 13 : M_LSRL_IMM(iptr->sx.val.i, d);
794 13 : emit_store_dst(jd, iptr, d);
795 13 : break;
796 :
797 : case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
798 :
799 914 : s1 = emit_load_s1(jd, iptr, REG_ITMP1);
800 914 : s2 = emit_load_s2(jd, iptr, REG_ITMP2);
801 914 : d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
802 914 : if (s2 == d)
803 282 : M_IAND(s1, d);
804 : else {
805 632 : M_INTMOVE(s1, d);
806 632 : M_IAND(s2, d);
807 : }
808 914 : emit_store_dst(jd, iptr, d);
809 914 : break;
810 :
811 : case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
812 : /* sx.val.i = constant */
813 :
814 1231 : s1 = emit_load_s1(jd, iptr, REG_ITMP1);
815 1231 : d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
816 1231 : M_INTMOVE(s1, d);
817 1231 : M_IAND_IMM(iptr->sx.val.i, d);
818 1231 : emit_store_dst(jd, iptr, d);
819 1231 : break;
820 :
821 : case ICMD_LAND: /* ..., val1, val2 ==> ..., val1 & val2 */
822 :
823 15 : s1 = emit_load_s1(jd, iptr, REG_ITMP1);
824 15 : s2 = emit_load_s2(jd, iptr, REG_ITMP2);
825 15 : d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
826 15 : if (s2 == d)
827 0 : M_LAND(s1, d);
828 : else {
829 15 : M_INTMOVE(s1, d);
830 15 : M_LAND(s2, d);
831 : }
832 15 : emit_store_dst(jd, iptr, d);
833 15 : break;
834 :
835 : case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */
836 : /* sx.val.l = constant */
837 :
838 54 : s1 = emit_load_s1(jd, iptr, REG_ITMP1);
839 54 : d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
840 54 : M_INTMOVE(s1, d);
841 66 : if (IS_IMM32(iptr->sx.val.l))
842 12 : M_LAND_IMM(iptr->sx.val.l, d);
843 : else {
844 42 : M_MOV_IMM(iptr->sx.val.l, REG_ITMP2);
845 42 : M_LAND(REG_ITMP2, d);
846 : }
847 54 : emit_store_dst(jd, iptr, d);
848 54 : break;
849 :
850 : case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
851 :
852 252 : s1 = emit_load_s1(jd, iptr, REG_ITMP1);
853 252 : s2 = emit_load_s2(jd, iptr, REG_ITMP2);
854 252 : d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
855 252 : if (s2 == d)
856 36 : M_IOR(s1, d);
857 : else {
858 216 : M_INTMOVE(s1, d);
859 216 : M_IOR(s2, d);
860 : }
861 252 : emit_store_dst(jd, iptr, d);
862 252 : break;
863 :
864 : case ICMD_IORCONST: /* ..., value ==> ..., value | constant */
865 : /* sx.val.i = constant */
866 :
867 137 : s1 = emit_load_s1(jd, iptr, REG_ITMP1);
868 137 : d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
869 137 : M_INTMOVE(s1, d);
870 137 : M_IOR_IMM(iptr->sx.val.i, d);
871 137 : emit_store_dst(jd, iptr, d);
872 137 : break;
873 :
874 : case ICMD_LOR: /* ..., val1, val2 ==> ..., val1 | val2 */
875 :
876 9 : s1 = emit_load_s1(jd, iptr, REG_ITMP1);
877 9 : s2 = emit_load_s2(jd, iptr, REG_ITMP2);
878 9 : d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
879 9 : if (s2 == d)
880 0 : M_LOR(s1, d);
881 : else {
882 9 : M_INTMOVE(s1, d);
883 9 : M_LOR(s2, d);
884 : }
885 9 : emit_store_dst(jd, iptr, d);
886 9 : break;
887 :
888 : case ICMD_LORCONST: /* ..., value ==> ..., value | constant */
889 : /* sx.val.l = constant */
890 :
891 12 : s1 = emit_load_s1(jd, iptr, REG_ITMP1);
892 12 : d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
893 12 : M_INTMOVE(s1, d);
894 22 : if (IS_IMM32(iptr->sx.val.l))
895 10 : M_LOR_IMM(iptr->sx.val.l, d);
896 : else {
897 2 : M_MOV_IMM(iptr->sx.val.l, REG_ITMP2);
898 2 : M_LOR(REG_ITMP2, d);
899 : }
900 12 : emit_store_dst(jd, iptr, d);
901 12 : break;
902 :
903 : case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
904 :
905 637 : s1 = emit_load_s1(jd, iptr, REG_ITMP1);
906 637 : s2 = emit_load_s2(jd, iptr, REG_ITMP2);
907 637 : d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
908 637 : if (s2 == d)
909 435 : M_IXOR(s1, d);
910 : else {
911 202 : M_INTMOVE(s1, d);
912 202 : M_IXOR(s2, d);
913 : }
914 637 : emit_store_dst(jd, iptr, d);
915 637 : break;
916 :
917 : case ICMD_IXORCONST: /* ..., value ==> ..., value ^ constant */
918 : /* sx.val.i = constant */
919 :
920 28 : s1 = emit_load_s1(jd, iptr, REG_ITMP1);
921 28 : d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
922 28 : M_INTMOVE(s1, d);
923 28 : M_IXOR_IMM(iptr->sx.val.i, d);
924 28 : emit_store_dst(jd, iptr, d);
925 28 : break;
926 :
927 : case ICMD_LXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
928 :
929 2 : s1 = emit_load_s1(jd, iptr, REG_ITMP1);
930 2 : s2 = emit_load_s2(jd, iptr, REG_ITMP2);
931 2 : d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
932 2 : if (s2 == d)
933 0 : M_LXOR(s1, d);
934 : else {
935 2 : M_INTMOVE(s1, d);
936 2 : M_LXOR(s2, d);
937 : }
938 2 : emit_store_dst(jd, iptr, d);
939 2 : break;
940 :
941 : case ICMD_LXORCONST: /* ..., value ==> ..., value ^ constant */
942 : /* sx.val.l = constant */
943 :
944 12 : s1 = emit_load_s1(jd, iptr, REG_ITMP1);
945 12 : d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
946 12 : M_INTMOVE(s1, d);
947 22 : if (IS_IMM32(iptr->sx.val.l))
948 10 : M_LXOR_IMM(iptr->sx.val.l, d);
949 : else {
950 2 : M_MOV_IMM(iptr->sx.val.l, REG_ITMP2);
951 2 : M_LXOR(REG_ITMP2, d);
952 : }
953 12 : emit_store_dst(jd, iptr, d);
954 12 : break;
955 :
956 :
957 : /* floating operations ************************************************/
958 :
959 : case ICMD_FNEG: /* ..., value ==> ..., - value */
960 :
961 0 : s1 = emit_load_s1(jd, iptr, REG_FTMP1);
962 0 : d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
963 0 : disp = dseg_add_s4(cd, 0x80000000);
964 0 : emit_fmove(cd, s1, d);
965 0 : emit_movss_membase_reg(cd, RIP, -((cd->mcodeptr + 9) - cd->mcodebase) + disp, REG_FTMP2);
966 0 : emit_xorps_reg_reg(cd, REG_FTMP2, d);
967 0 : emit_store_dst(jd, iptr, d);
968 0 : break;
969 :
970 : case ICMD_DNEG: /* ..., value ==> ..., - value */
971 :
972 0 : s1 = emit_load_s1(jd, iptr, REG_FTMP1);
973 0 : d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
974 0 : disp = dseg_add_s8(cd, 0x8000000000000000);
975 0 : emit_fmove(cd, s1, d);
976 0 : emit_movd_membase_reg(cd, RIP, -((cd->mcodeptr + 9) - cd->mcodebase) + disp, REG_FTMP2);
977 0 : emit_xorpd_reg_reg(cd, REG_FTMP2, d);
978 0 : emit_store_dst(jd, iptr, d);
979 0 : break;
980 :
981 : case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
982 :
983 1006 : s1 = emit_load_s1(jd, iptr, REG_FTMP1);
984 1006 : s2 = emit_load_s2(jd, iptr, REG_FTMP2);
985 1006 : d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
986 1006 : if (s2 == d)
987 0 : M_FADD(s1, d);
988 : else {
989 1006 : emit_fmove(cd, s1, d);
990 1006 : M_FADD(s2, d);
991 : }
992 1006 : emit_store_dst(jd, iptr, d);
993 1006 : break;
994 :
995 : case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
996 :
997 7 : s1 = emit_load_s1(jd, iptr, REG_FTMP1);
998 7 : s2 = emit_load_s2(jd, iptr, REG_FTMP2);
999 7 : d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1000 7 : if (s2 == d)
1001 0 : M_DADD(s1, d);
1002 : else {
1003 7 : emit_fmove(cd, s1, d);
1004 7 : M_DADD(s2, d);
1005 : }
1006 7 : emit_store_dst(jd, iptr, d);
1007 7 : break;
1008 :
1009 : case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1010 :
1011 3 : s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1012 3 : s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1013 3 : d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1014 3 : if (s2 == d) {
1015 0 : emit_fmove(cd, s2, REG_FTMP2);
1016 0 : s2 = REG_FTMP2;
1017 : }
1018 3 : emit_fmove(cd, s1, d);
1019 3 : M_FSUB(s2, d);
1020 3 : emit_store_dst(jd, iptr, d);
1021 3 : break;
1022 :
1023 : case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1024 :
1025 5 : s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1026 5 : s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1027 5 : d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1028 5 : if (s2 == d) {
1029 0 : emit_fmove(cd, s2, REG_FTMP2);
1030 0 : s2 = REG_FTMP2;
1031 : }
1032 5 : emit_fmove(cd, s1, d);
1033 5 : M_DSUB(s2, d);
1034 5 : emit_store_dst(jd, iptr, d);
1035 5 : break;
1036 :
1037 : case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1038 :
1039 999 : s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1040 999 : s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1041 999 : d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1042 999 : if (s2 == d)
1043 0 : M_FMUL(s1, d);
1044 : else {
1045 999 : emit_fmove(cd, s1, d);
1046 999 : M_FMUL(s2, d);
1047 : }
1048 999 : emit_store_dst(jd, iptr, d);
1049 999 : break;
1050 :
1051 : case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1052 :
1053 10 : s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1054 10 : s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1055 10 : d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1056 10 : if (s2 == d)
1057 0 : M_DMUL(s1, d);
1058 : else {
1059 10 : emit_fmove(cd, s1, d);
1060 10 : M_DMUL(s2, d);
1061 : }
1062 10 : emit_store_dst(jd, iptr, d);
1063 10 : break;
1064 :
1065 : case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1066 :
1067 5 : s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1068 5 : s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1069 5 : d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1070 5 : if (s2 == d) {
1071 0 : emit_fmove(cd, s2, REG_FTMP2);
1072 0 : s2 = REG_FTMP2;
1073 : }
1074 5 : emit_fmove(cd, s1, d);
1075 5 : M_FDIV(s2, d);
1076 5 : emit_store_dst(jd, iptr, d);
1077 5 : break;
1078 :
1079 : case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1080 :
1081 7 : s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1082 7 : s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1083 7 : d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1084 7 : if (s2 == d) {
1085 0 : emit_fmove(cd, s2, REG_FTMP2);
1086 0 : s2 = REG_FTMP2;
1087 : }
1088 7 : emit_fmove(cd, s1, d);
1089 7 : M_DDIV(s2, d);
1090 7 : emit_store_dst(jd, iptr, d);
1091 7 : break;
1092 :
1093 : case ICMD_I2F: /* ..., value ==> ..., (float) value */
1094 :
1095 1278 : s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1096 1278 : d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1097 1278 : M_CVTIF(s1, d);
1098 1278 : emit_store_dst(jd, iptr, d);
1099 1278 : break;
1100 :
1101 : case ICMD_I2D: /* ..., value ==> ..., (double) value */
1102 :
1103 8 : s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1104 8 : d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1105 8 : M_CVTID(s1, d);
1106 8 : emit_store_dst(jd, iptr, d);
1107 8 : break;
1108 :
1109 : case ICMD_L2F: /* ..., value ==> ..., (float) value */
1110 :
1111 1 : s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1112 1 : d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1113 1 : M_CVTLF(s1, d);
1114 1 : emit_store_dst(jd, iptr, d);
1115 1 : break;
1116 :
1117 : case ICMD_L2D: /* ..., value ==> ..., (double) value */
1118 :
1119 3 : s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1120 3 : d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1121 3 : M_CVTLD(s1, d);
1122 3 : emit_store_dst(jd, iptr, d);
1123 3 : break;
1124 :
1125 : case ICMD_F2I: /* ..., value ==> ..., (int) value */
1126 :
1127 0 : s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1128 0 : d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1129 0 : M_CVTFI(s1, d);
1130 0 : M_ICMP_IMM(0x80000000, d); /* corner cases */
1131 : disp = ((s1 == REG_FTMP1) ? 0 : 5) + 10 + 3 +
1132 0 : ((REG_RESULT == d) ? 0 : 3);
1133 0 : M_BNE(disp);
1134 0 : emit_fmove(cd, s1, REG_FTMP1);
1135 0 : M_MOV_IMM(asm_builtin_f2i, REG_ITMP2);
1136 0 : M_CALL(REG_ITMP2);
1137 0 : M_INTMOVE(REG_RESULT, d);
1138 0 : emit_store_dst(jd, iptr, d);
1139 0 : break;
1140 :
1141 : case ICMD_D2I: /* ..., value ==> ..., (int) value */
1142 :
1143 0 : s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1144 0 : d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1145 0 : M_CVTDI(s1, d);
1146 0 : M_ICMP_IMM(0x80000000, d); /* corner cases */
1147 : disp = ((s1 == REG_FTMP1) ? 0 : 5) + 10 + 3 +
1148 0 : ((REG_RESULT == d) ? 0 : 3);
1149 0 : M_BNE(disp);
1150 0 : emit_fmove(cd, s1, REG_FTMP1);
1151 0 : M_MOV_IMM(asm_builtin_d2i, REG_ITMP2);
1152 0 : M_CALL(REG_ITMP2);
1153 0 : M_INTMOVE(REG_RESULT, d);
1154 0 : emit_store_dst(jd, iptr, d);
1155 0 : break;
1156 :
1157 : case ICMD_F2L: /* ..., value ==> ..., (long) value */
1158 :
1159 0 : s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1160 0 : d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1161 0 : M_CVTFL(s1, d);
1162 0 : M_MOV_IMM(0x8000000000000000, REG_ITMP2);
1163 0 : M_LCMP(REG_ITMP2, d); /* corner cases */
1164 : disp = ((s1 == REG_FTMP1) ? 0 : 5) + 10 + 3 +
1165 0 : ((REG_RESULT == d) ? 0 : 3);
1166 0 : M_BNE(disp);
1167 0 : emit_fmove(cd, s1, REG_FTMP1);
1168 0 : M_MOV_IMM(asm_builtin_f2l, REG_ITMP2);
1169 0 : M_CALL(REG_ITMP2);
1170 0 : M_INTMOVE(REG_RESULT, d);
1171 0 : emit_store_dst(jd, iptr, d);
1172 0 : break;
1173 :
1174 : case ICMD_D2L: /* ..., value ==> ..., (long) value */
1175 :
1176 0 : s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1177 0 : d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1178 0 : M_CVTDL(s1, d);
1179 0 : M_MOV_IMM(0x8000000000000000, REG_ITMP2);
1180 0 : M_LCMP(REG_ITMP2, d); /* corner cases */
1181 : disp = ((s1 == REG_FTMP1) ? 0 : 5) + 10 + 3 +
1182 0 : ((REG_RESULT == d) ? 0 : 3);
1183 0 : M_BNE(disp);
1184 0 : emit_fmove(cd, s1, REG_FTMP1);
1185 0 : M_MOV_IMM(asm_builtin_d2l, REG_ITMP2);
1186 0 : M_CALL(REG_ITMP2);
1187 0 : M_INTMOVE(REG_RESULT, d);
1188 0 : emit_store_dst(jd, iptr, d);
1189 0 : break;
1190 :
1191 : case ICMD_F2D: /* ..., value ==> ..., (double) value */
1192 :
1193 19 : s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1194 19 : d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1195 19 : M_CVTFD(s1, d);
1196 19 : emit_store_dst(jd, iptr, d);
1197 19 : break;
1198 :
1199 : case ICMD_D2F: /* ..., value ==> ..., (float) value */
1200 :
1201 5 : s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1202 5 : d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1203 5 : M_CVTDF(s1, d);
1204 5 : emit_store_dst(jd, iptr, d);
1205 5 : break;
1206 :
1207 : case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1208 : /* == => 0, < => 1, > => -1 */
1209 :
1210 1447 : s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1211 1447 : s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1212 1447 : d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1213 1447 : M_CLR(d);
1214 1447 : M_MOV_IMM(1, REG_ITMP1);
1215 1447 : M_MOV_IMM(-1, REG_ITMP2);
1216 1447 : emit_ucomiss_reg_reg(cd, s1, s2);
1217 1447 : M_CMOVULT(REG_ITMP1, d);
1218 1447 : M_CMOVUGT(REG_ITMP2, d);
1219 1447 : M_CMOVP(REG_ITMP2, d); /* treat unordered as GT */
1220 1447 : emit_store_dst(jd, iptr, d);
1221 1447 : break;
1222 :
1223 : case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1224 : /* == => 0, < => 1, > => -1 */
1225 :
1226 443 : s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1227 443 : s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1228 443 : d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1229 443 : M_CLR(d);
1230 443 : M_MOV_IMM(1, REG_ITMP1);
1231 443 : M_MOV_IMM(-1, REG_ITMP2);
1232 443 : emit_ucomiss_reg_reg(cd, s1, s2);
1233 443 : M_CMOVULT(REG_ITMP1, d);
1234 443 : M_CMOVUGT(REG_ITMP2, d);
1235 443 : M_CMOVP(REG_ITMP1, d); /* treat unordered as LT */
1236 443 : emit_store_dst(jd, iptr, d);
1237 443 : break;
1238 :
1239 : case ICMD_DCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1240 : /* == => 0, < => 1, > => -1 */
1241 :
1242 43 : s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1243 43 : s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1244 43 : d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1245 43 : M_CLR(d);
1246 43 : M_MOV_IMM(1, REG_ITMP1);
1247 43 : M_MOV_IMM(-1, REG_ITMP2);
1248 43 : emit_ucomisd_reg_reg(cd, s1, s2);
1249 43 : M_CMOVULT(REG_ITMP1, d);
1250 43 : M_CMOVUGT(REG_ITMP2, d);
1251 43 : M_CMOVP(REG_ITMP2, d); /* treat unordered as GT */
1252 43 : emit_store_dst(jd, iptr, d);
1253 43 : break;
1254 :
1255 : case ICMD_DCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1256 : /* == => 0, < => 1, > => -1 */
1257 :
1258 14 : s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1259 14 : s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1260 14 : d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1261 14 : M_CLR(d);
1262 14 : M_MOV_IMM(1, REG_ITMP1);
1263 14 : M_MOV_IMM(-1, REG_ITMP2);
1264 14 : emit_ucomisd_reg_reg(cd, s1, s2);
1265 14 : M_CMOVULT(REG_ITMP1, d);
1266 14 : M_CMOVUGT(REG_ITMP2, d);
1267 14 : M_CMOVP(REG_ITMP1, d); /* treat unordered as LT */
1268 14 : emit_store_dst(jd, iptr, d);
1269 14 : break;
1270 :
1271 :
1272 : /* memory operations **************************************************/
1273 :
1274 : case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
1275 :
1276 160 : s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1277 160 : s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1278 160 : d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1279 : /* implicit null-pointer check */
1280 160 : emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1281 160 : emit_movsbq_memindex_reg(cd, OFFSET(java_bytearray_t, data[0]), s1, s2, 0, d);
1282 160 : emit_store_dst(jd, iptr, d);
1283 160 : break;
1284 :
1285 : case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
1286 :
1287 3526 : s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1288 3526 : s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1289 3526 : d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1290 : /* implicit null-pointer check */
1291 3526 : emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1292 3526 : emit_movzwq_memindex_reg(cd, OFFSET(java_chararray_t, data[0]), s1, s2, 1, d);
1293 3526 : emit_store_dst(jd, iptr, d);
1294 3526 : break;
1295 :
1296 : case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
1297 :
1298 55 : s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1299 55 : s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1300 55 : d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1301 : /* implicit null-pointer check */
1302 55 : emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1303 55 : emit_movswq_memindex_reg(cd, OFFSET(java_shortarray_t, data[0]), s1, s2, 1, d);
1304 55 : emit_store_dst(jd, iptr, d);
1305 55 : break;
1306 :
1307 : case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
1308 :
1309 301 : s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1310 301 : s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1311 301 : d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1312 : /* implicit null-pointer check */
1313 301 : emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1314 301 : emit_movl_memindex_reg(cd, OFFSET(java_intarray_t, data[0]), s1, s2, 2, d);
1315 301 : emit_store_dst(jd, iptr, d);
1316 301 : break;
1317 :
1318 : case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
1319 :
1320 21 : s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1321 21 : s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1322 21 : d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1323 : /* implicit null-pointer check */
1324 21 : emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1325 21 : emit_mov_memindex_reg(cd, OFFSET(java_longarray_t, data[0]), s1, s2, 3, d);
1326 21 : emit_store_dst(jd, iptr, d);
1327 21 : break;
1328 :
1329 : case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
1330 :
1331 3 : s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1332 3 : s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1333 3 : d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1334 : /* implicit null-pointer check */
1335 3 : emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1336 3 : emit_movss_memindex_reg(cd, OFFSET(java_floatarray_t, data[0]), s1, s2, 2, d);
1337 3 : emit_store_dst(jd, iptr, d);
1338 3 : break;
1339 :
1340 : case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
1341 :
1342 3 : s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1343 3 : s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1344 3 : d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1345 : /* implicit null-pointer check */
1346 3 : emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1347 3 : emit_movsd_memindex_reg(cd, OFFSET(java_doublearray_t, data[0]), s1, s2, 3, d);
1348 3 : emit_store_dst(jd, iptr, d);
1349 3 : break;
1350 :
1351 : case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
1352 :
1353 21245 : s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1354 21245 : s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1355 21245 : d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1356 : /* implicit null-pointer check */
1357 21245 : emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1358 21245 : emit_mov_memindex_reg(cd, OFFSET(java_objectarray_t, data[0]), s1, s2, 3, d);
1359 21245 : emit_store_dst(jd, iptr, d);
1360 21245 : break;
1361 :
1362 :
1363 : case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
1364 :
1365 360 : s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1366 360 : s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1367 : /* implicit null-pointer check */
1368 360 : emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1369 360 : s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1370 360 : emit_movb_reg_memindex(cd, s3, OFFSET(java_bytearray_t, data[0]), s1, s2, 0);
1371 360 : break;
1372 :
1373 : case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
1374 :
1375 1032 : s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1376 1032 : s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1377 : /* implicit null-pointer check */
1378 1032 : emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1379 1032 : s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1380 1032 : emit_movw_reg_memindex(cd, s3, OFFSET(java_chararray_t, data[0]), s1, s2, 1);
1381 1032 : break;
1382 :
1383 : case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
1384 :
1385 52 : s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1386 52 : s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1387 : /* implicit null-pointer check */
1388 52 : emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1389 52 : s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1390 52 : emit_movw_reg_memindex(cd, s3, OFFSET(java_shortarray_t, data[0]), s1, s2, 1);
1391 52 : break;
1392 :
1393 : case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
1394 :
1395 86 : s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1396 86 : s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1397 : /* implicit null-pointer check */
1398 86 : emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1399 86 : s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1400 86 : emit_movl_reg_memindex(cd, s3, OFFSET(java_intarray_t, data[0]), s1, s2, 2);
1401 86 : break;
1402 :
1403 : case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
1404 :
1405 10 : s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1406 10 : s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1407 : /* implicit null-pointer check */
1408 10 : emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1409 10 : s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1410 10 : emit_mov_reg_memindex(cd, s3, OFFSET(java_longarray_t, data[0]), s1, s2, 3);
1411 10 : break;
1412 :
1413 : case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
1414 :
1415 6 : s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1416 6 : s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1417 : /* implicit null-pointer check */
1418 6 : emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1419 6 : s3 = emit_load_s3(jd, iptr, REG_FTMP3);
1420 6 : emit_movss_reg_memindex(cd, s3, OFFSET(java_floatarray_t, data[0]), s1, s2, 2);
1421 6 : break;
1422 :
1423 : case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
1424 :
1425 4 : s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1426 4 : s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1427 : /* implicit null-pointer check */
1428 4 : emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1429 4 : s3 = emit_load_s3(jd, iptr, REG_FTMP3);
1430 4 : emit_movsd_reg_memindex(cd, s3, OFFSET(java_doublearray_t, data[0]), s1, s2, 3);
1431 4 : break;
1432 :
1433 : case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */
1434 :
1435 64566 : s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1436 64566 : s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1437 : /* implicit null-pointer check */
1438 64566 : emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1439 64566 : s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1440 :
1441 64566 : M_MOV(s1, REG_A0);
1442 64566 : M_MOV(s3, REG_A1);
1443 64566 : M_MOV_IMM(BUILTIN_FAST_canstore, REG_ITMP1);
1444 64566 : M_CALL(REG_ITMP1);
1445 64566 : emit_arraystore_check(cd, iptr);
1446 :
1447 64566 : s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1448 64566 : s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1449 64566 : s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1450 64566 : emit_mov_reg_memindex(cd, s3, OFFSET(java_objectarray_t, data[0]), s1, s2, 3);
1451 64566 : break;
1452 :
1453 :
1454 : case ICMD_BASTORECONST: /* ..., arrayref, index ==> ... */
1455 :
1456 725 : s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1457 725 : s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1458 : /* implicit null-pointer check */
1459 725 : emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1460 725 : emit_movb_imm_memindex(cd, iptr->sx.s23.s3.constval, OFFSET(java_bytearray_t, data[0]), s1, s2, 0);
1461 725 : break;
1462 :
1463 : case ICMD_CASTORECONST: /* ..., arrayref, index ==> ... */
1464 :
1465 508614 : s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1466 508614 : s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1467 : /* implicit null-pointer check */
1468 508614 : emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1469 508614 : emit_movw_imm_memindex(cd, iptr->sx.s23.s3.constval, OFFSET(java_chararray_t, data[0]), s1, s2, 1);
1470 508614 : break;
1471 :
1472 : case ICMD_SASTORECONST: /* ..., arrayref, index ==> ... */
1473 :
1474 4 : s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1475 4 : s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1476 : /* implicit null-pointer check */
1477 4 : emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1478 4 : emit_movw_imm_memindex(cd, iptr->sx.s23.s3.constval, OFFSET(java_shortarray_t, data[0]), s1, s2, 1);
1479 4 : break;
1480 :
1481 : case ICMD_IASTORECONST: /* ..., arrayref, index ==> ... */
1482 :
1483 4735 : s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1484 4735 : s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1485 : /* implicit null-pointer check */
1486 4735 : emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1487 4735 : emit_movl_imm_memindex(cd, iptr->sx.s23.s3.constval, OFFSET(java_intarray_t, data[0]), s1, s2, 2);
1488 4735 : break;
1489 :
1490 : case ICMD_LASTORECONST: /* ..., arrayref, index ==> ... */
1491 :
1492 6 : s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1493 6 : s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1494 : /* implicit null-pointer check */
1495 6 : emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1496 :
1497 12 : if (IS_IMM32(iptr->sx.s23.s3.constval)) {
1498 6 : emit_mov_imm_memindex(cd, (u4) (iptr->sx.s23.s3.constval & 0x00000000ffffffff), OFFSET(java_longarray_t, data[0]), s1, s2, 3);
1499 : }
1500 : else {
1501 0 : emit_movl_imm_memindex(cd, (u4) (iptr->sx.s23.s3.constval & 0x00000000ffffffff), OFFSET(java_longarray_t, data[0]), s1, s2, 3);
1502 0 : emit_movl_imm_memindex(cd, (u4) (iptr->sx.s23.s3.constval >> 32), OFFSET(java_longarray_t, data[0]) + 4, s1, s2, 3);
1503 : }
1504 6 : break;
1505 :
1506 : case ICMD_AASTORECONST: /* ..., arrayref, index ==> ... */
1507 :
1508 586 : s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1509 586 : s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1510 : /* implicit null-pointer check */
1511 586 : emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1512 586 : emit_mov_imm_memindex(cd, 0, OFFSET(java_objectarray_t, data[0]), s1, s2, 3);
1513 586 : break;
1514 :
1515 : case ICMD_PUTSTATICCONST: /* ... ==> ... */
1516 : /* val = value (in current instruction) */
1517 : /* following NOP) */
1518 :
1519 814 : if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1520 9 : uf = iptr->sx.s23.s3.uf;
1521 9 : fieldtype = uf->fieldref->parseddesc.fd->type;
1522 9 : disp = dseg_add_unique_address(cd, uf);
1523 :
1524 : /* PROFILE_CYCLE_STOP; */
1525 :
1526 9 : pr = patcher_add_patch_ref(jd, PATCHER_get_putstatic, uf, disp);
1527 :
1528 : /* PROFILE_CYCLE_START; */
1529 :
1530 9 : fi = NULL; /* Silence compiler warning */
1531 : }
1532 : else {
1533 805 : fi = iptr->sx.s23.s3.fmiref->p.field;
1534 805 : fieldtype = fi->type;
1535 805 : disp = dseg_add_address(cd, fi->value);
1536 :
1537 805 : if (!class_is_or_almost_initialized(fi->clazz)) {
1538 : //PROFILE_CYCLE_STOP;
1539 :
1540 : patcher_add_patch_ref(jd, PATCHER_initialize_class,
1541 0 : fi->clazz, 0);
1542 :
1543 : //PROFILE_CYCLE_START;
1544 : }
1545 :
1546 805 : pr = NULL; /* Silence compiler warning */
1547 : }
1548 :
1549 : /* This approach is much faster than moving the field
1550 : address inline into a register. */
1551 :
1552 814 : M_ALD(REG_ITMP1, RIP, disp);
1553 :
1554 814 : switch (fieldtype) {
1555 : case TYPE_INT:
1556 : case TYPE_FLT:
1557 514 : M_IST_IMM(iptr->sx.s23.s2.constval, REG_ITMP1, 0);
1558 514 : break;
1559 : case TYPE_LNG:
1560 : case TYPE_ADR:
1561 : case TYPE_DBL:
1562 595 : if (IS_IMM32(iptr->sx.s23.s2.constval))
1563 295 : M_LST_IMM32(iptr->sx.s23.s2.constval, REG_ITMP1, 0);
1564 : else {
1565 5 : M_MOV_IMM(iptr->sx.s23.s2.constval, REG_ITMP2);
1566 5 : M_LST(REG_ITMP2, REG_ITMP1, 0);
1567 : }
1568 300 : break;
1569 : default:
1570 0 : assert(false);
1571 : break;
1572 : }
1573 814 : codegen_emit_patchable_barrier(iptr, cd, pr, fi);
1574 814 : break;
1575 :
1576 : case ICMD_GETFIELD: /* ... ==> ..., value */
1577 :
1578 100193 : s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1579 :
1580 100193 : if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1581 677 : uf = iptr->sx.s23.s3.uf;
1582 677 : fieldtype = uf->fieldref->parseddesc.fd->type;
1583 677 : disp = 0;
1584 :
1585 : /* PROFILE_CYCLE_STOP; */
1586 :
1587 677 : pr = patcher_add_patch_ref(jd, PATCHER_get_putfield, uf, 0);
1588 677 : mcodeptr_save = cd->mcodeptr;
1589 :
1590 : /* PROFILE_CYCLE_START; */
1591 :
1592 677 : fi = NULL; /* Silence compiler warning */
1593 : }
1594 : else {
1595 99516 : fi = iptr->sx.s23.s3.fmiref->p.field;
1596 99516 : fieldtype = fi->type;
1597 99516 : disp = fi->offset;
1598 :
1599 99516 : pr = 0;
1600 : }
1601 :
1602 : /* implicit null-pointer check */
1603 100193 : switch (fieldtype) {
1604 : case TYPE_INT:
1605 38354 : d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1606 38354 : M_ILD32(d, s1, disp);
1607 38354 : break;
1608 : case TYPE_LNG:
1609 : case TYPE_ADR:
1610 61364 : d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1611 61364 : M_LLD32(d, s1, disp);
1612 61364 : break;
1613 : case TYPE_FLT:
1614 454 : d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1615 454 : M_FLD32(d, s1, disp);
1616 454 : break;
1617 : case TYPE_DBL:
1618 21 : d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1619 21 : M_DLD32(d, s1, disp);
1620 21 : break;
1621 : default:
1622 : // Silence compiler warning.
1623 0 : d = 0;
1624 : }
1625 100193 : if (pr)
1626 677 : codegen_fixup_alignment(cd, pr, mcodeptr_save);
1627 100193 : emit_store_dst(jd, iptr, d);
1628 100193 : break;
1629 :
1630 : case ICMD_PUTFIELD: /* ..., objectref, value ==> ... */
1631 :
1632 40112 : s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1633 40112 : s2 = emit_load_s2(jd, iptr, REG_IFTMP); /* REG_IFTMP == REG_ITMP2 */
1634 :
1635 40112 : if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1636 614 : uf = iptr->sx.s23.s3.uf;
1637 614 : fieldtype = uf->fieldref->parseddesc.fd->type;
1638 614 : disp = 0;
1639 :
1640 : /* PROFILE_CYCLE_STOP; */
1641 :
1642 614 : pr = patcher_add_patch_ref(jd, PATCHER_get_putfield, uf, 0);
1643 614 : mcodeptr_save = cd->mcodeptr;
1644 :
1645 : /* PROFILE_CYCLE_START; */
1646 :
1647 614 : fi = NULL; /* Silence compiler warning */
1648 : }
1649 : else {
1650 39498 : fi = iptr->sx.s23.s3.fmiref->p.field;
1651 39498 : fieldtype = fi->type;
1652 39498 : disp = fi->offset;
1653 :
1654 39498 : pr = NULL; /* Silence compiler warning */
1655 : }
1656 :
1657 : /* implicit null-pointer check */
1658 40112 : switch (fieldtype) {
1659 : case TYPE_INT:
1660 13573 : M_IST32(s2, s1, disp);
1661 13573 : break;
1662 : case TYPE_LNG:
1663 : case TYPE_ADR:
1664 25877 : M_LST32(s2, s1, disp);
1665 25877 : break;
1666 : case TYPE_FLT:
1667 624 : M_FST32(s2, s1, disp);
1668 624 : break;
1669 : case TYPE_DBL:
1670 38 : M_DST32(s2, s1, disp);
1671 : break;
1672 : }
1673 40112 : if (pr)
1674 614 : codegen_fixup_alignment(cd, pr, mcodeptr_save);
1675 40112 : codegen_emit_patchable_barrier(iptr, cd, pr, fi);
1676 40112 : break;
1677 :
1678 : case ICMD_PUTFIELDCONST: /* ..., objectref, value ==> ... */
1679 : /* val = value (in current instruction) */
1680 : /* following NOP) */
1681 :
1682 12129 : s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1683 :
1684 12129 : if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1685 100 : uf = iptr->sx.s23.s3.uf;
1686 100 : fieldtype = uf->fieldref->parseddesc.fd->type;
1687 100 : disp = 0;
1688 :
1689 : /* PROFILE_CYCLE_STOP; */
1690 :
1691 100 : pr = patcher_add_patch_ref(jd, PATCHER_putfieldconst, uf, 0);
1692 100 : mcodeptr_save = cd->mcodeptr;
1693 :
1694 : /* PROFILE_CYCLE_START; */
1695 :
1696 100 : fi = NULL; /* Silence compiler warning */
1697 : }
1698 : else {
1699 12029 : fi = iptr->sx.s23.s3.fmiref->p.field;
1700 12029 : fieldtype = fi->type;
1701 12029 : disp = fi->offset;
1702 :
1703 12029 : pr = NULL; /* Silence compiler warning */
1704 : }
1705 :
1706 : /* implicit null-pointer check */
1707 12129 : switch (fieldtype) {
1708 : case TYPE_INT:
1709 : case TYPE_FLT:
1710 8296 : M_IST32_IMM(iptr->sx.s23.s2.constval, s1, disp);
1711 8296 : break;
1712 : case TYPE_LNG:
1713 : case TYPE_ADR:
1714 : case TYPE_DBL:
1715 : /* XXX why no check for IS_IMM32? -- probably because of the patcher */
1716 3833 : M_MOV_IMM(iptr->sx.s23.s2.constval, REG_ITMP2);
1717 3833 : if (disp) /* resolved, disp can never be 0 */
1718 3828 : M_LST(REG_ITMP2, s1, disp);
1719 : else { /* unresolved */
1720 5 : M_LST32(REG_ITMP2, s1, disp);
1721 5 : pr->patch_align = 4;
1722 : }
1723 : break;
1724 : }
1725 12129 : if (pr)
1726 100 : codegen_fixup_alignment(cd, pr, mcodeptr_save);
1727 12129 : codegen_emit_patchable_barrier(iptr, cd, pr, fi);
1728 12129 : break;
1729 :
1730 :
1731 : /* branch operations **************************************************/
1732 :
1733 : case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
1734 :
1735 18423 : M_CALL_IMM(0); /* passing exception pc */
1736 18423 : M_POP(REG_ITMP2_XPC);
1737 :
1738 18423 : M_MOV_IMM(asm_handle_exception, REG_ITMP3);
1739 18423 : M_JMP(REG_ITMP3);
1740 18423 : break;
1741 :
1742 : case ICMD_IF_LEQ: /* ..., value ==> ... */
1743 : case ICMD_IF_LNE:
1744 : case ICMD_IF_LLT:
1745 : case ICMD_IF_LGE:
1746 : case ICMD_IF_LGT:
1747 : case ICMD_IF_LLE:
1748 :
1749 295 : s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1750 560 : if (IS_IMM32(iptr->sx.val.l))
1751 265 : M_LCMP_IMM(iptr->sx.val.l, s1);
1752 : else {
1753 30 : M_MOV_IMM(iptr->sx.val.l, REG_ITMP2);
1754 30 : M_LCMP(REG_ITMP2, s1);
1755 : }
1756 295 : emit_bcc(cd, iptr->dst.block, iptr->opc - ICMD_IF_LEQ, BRANCH_OPT_NONE);
1757 295 : break;
1758 :
1759 : case ICMD_IF_LCMPEQ: /* ..., value, value ==> ... */
1760 : case ICMD_IF_LCMPNE:
1761 : case ICMD_IF_LCMPLT:
1762 : case ICMD_IF_LCMPGE:
1763 : case ICMD_IF_LCMPGT:
1764 : case ICMD_IF_LCMPLE:
1765 :
1766 124 : s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1767 124 : s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1768 124 : M_LCMP(s2, s1);
1769 124 : emit_bcc(cd, iptr->dst.block, iptr->opc - ICMD_IF_LCMPEQ, BRANCH_OPT_NONE);
1770 124 : break;
1771 :
1772 : case ICMD_TABLESWITCH: /* ..., index ==> ... */
1773 : {
1774 : s4 i, l;
1775 : branch_target_t *table;
1776 :
1777 72 : table = iptr->dst.table;
1778 :
1779 72 : l = iptr->sx.s23.s2.tablelow;
1780 72 : i = iptr->sx.s23.s3.tablehigh;
1781 :
1782 72 : s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1783 72 : M_INTMOVE(s1, REG_ITMP1);
1784 :
1785 72 : if (l != 0)
1786 44 : M_ISUB_IMM(l, REG_ITMP1);
1787 :
1788 : /* number of targets */
1789 72 : i = i - l + 1;
1790 :
1791 : /* range check */
1792 :
1793 72 : M_ICMP_IMM(i - 1, REG_ITMP1);
1794 72 : emit_bugt(cd, table[0].block);
1795 :
1796 : /* build jump table top down and use address of lowest entry */
1797 :
1798 72 : table += i;
1799 :
1800 1218 : while (--i >= 0) {
1801 1074 : dseg_add_target(cd, table->block);
1802 1074 : --table;
1803 : }
1804 :
1805 : /* length of dataseg after last dseg_add_target is used
1806 : by load */
1807 :
1808 72 : M_MOV_IMM(0, REG_ITMP2);
1809 72 : dseg_adddata(cd);
1810 72 : emit_mov_memindex_reg(cd, -(cd->dseglen), REG_ITMP2, REG_ITMP1, 3, REG_ITMP1);
1811 72 : M_JMP(REG_ITMP1);
1812 : }
1813 72 : break;
1814 :
1815 : case ICMD_BUILTIN:
1816 77258 : bte = iptr->sx.s23.s3.bte;
1817 77258 : if (bte->stub == NULL) {
1818 1840 : M_MOV_IMM(bte->fp, REG_ITMP1);
1819 : }
1820 : else {
1821 75418 : M_MOV_IMM(bte->stub, REG_ITMP1);
1822 : }
1823 77258 : M_CALL(REG_ITMP1);
1824 77258 : break;
1825 :
1826 : case ICMD_INVOKESPECIAL:
1827 98529 : emit_nullpointer_check(cd, iptr, REG_A0);
1828 : /* fall through */
1829 :
1830 : case ICMD_INVOKESTATIC:
1831 155417 : if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1832 43458 : um = iptr->sx.s23.s3.um;
1833 43458 : disp = dseg_add_unique_address(cd, um);
1834 :
1835 : patcher_add_patch_ref(jd, PATCHER_invokestatic_special,
1836 43458 : um, disp);
1837 : }
1838 : else {
1839 111959 : lm = iptr->sx.s23.s3.fmiref->p.method;
1840 111959 : disp = dseg_add_functionptr(cd, lm->stubroutine);
1841 : }
1842 :
1843 155417 : M_ALD(REG_ITMP2, RIP, disp);
1844 155417 : M_CALL(REG_ITMP2);
1845 155417 : break;
1846 :
1847 : case ICMD_INVOKEVIRTUAL:
1848 119224 : if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1849 19564 : um = iptr->sx.s23.s3.um;
1850 19564 : patcher_add_patch_ref(jd, PATCHER_invokevirtual, um, 0);
1851 19564 : emit_arbitrary_nop(cd, PATCH_ALIGNMENT((uintptr_t) cd->mcodeptr, 6, sizeof(int32_t)));
1852 :
1853 19564 : s1 = 0;
1854 : }
1855 : else {
1856 99660 : lm = iptr->sx.s23.s3.fmiref->p.method;
1857 99660 : s1 = OFFSET(vftbl_t, table[0]) +
1858 199320 : sizeof(methodptr) * lm->vftblindex;
1859 : }
1860 :
1861 : /* implicit null-pointer check */
1862 119224 : M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_object_t, vftbl));
1863 119224 : M_ALD32(REG_ITMP3, REG_METHODPTR, s1);
1864 119224 : M_CALL(REG_ITMP3);
1865 119224 : break;
1866 :
1867 : case ICMD_INVOKEINTERFACE:
1868 7503 : if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1869 1210 : um = iptr->sx.s23.s3.um;
1870 1210 : patcher_add_patch_ref(jd, PATCHER_invokeinterface, um, 0);
1871 1210 : emit_arbitrary_nop(cd, PATCH_ALIGNMENT((uintptr_t) cd->mcodeptr, 6, sizeof(int32_t)));
1872 :
1873 1210 : s1 = 0;
1874 1210 : s2 = 0;
1875 : }
1876 : else {
1877 6293 : lm = iptr->sx.s23.s3.fmiref->p.method;
1878 6293 : s1 = OFFSET(vftbl_t, interfacetable[0]) -
1879 6293 : sizeof(methodptr) * lm->clazz->index;
1880 :
1881 6293 : s2 = sizeof(methodptr) * (lm - lm->clazz->methods);
1882 : }
1883 :
1884 : /* implicit null-pointer check */
1885 7503 : M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_object_t, vftbl));
1886 7503 : M_ALD32(REG_METHODPTR, REG_METHODPTR, s1);
1887 7503 : if (INSTRUCTION_IS_UNRESOLVED(iptr))
1888 1210 : emit_arbitrary_nop(cd, PATCH_ALIGNMENT((uintptr_t) cd->mcodeptr, 3, sizeof(int32_t)));
1889 7503 : M_ALD32(REG_ITMP3, REG_METHODPTR, s2);
1890 7503 : M_CALL(REG_ITMP3);
1891 7503 : break;
1892 :
1893 : case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
1894 :
1895 9191 : if (!(iptr->flags.bits & INS_FLAG_ARRAY)) {
1896 : /* object type cast-check */
1897 :
1898 : classinfo *super;
1899 : s4 superindex;
1900 :
1901 8232 : if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1902 1714 : super = NULL;
1903 1714 : superindex = 0;
1904 : }
1905 : else {
1906 6518 : super = iptr->sx.s23.s3.c.cls;
1907 6518 : superindex = super->index;
1908 : }
1909 :
1910 8232 : s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1911 :
1912 : /* if class is not resolved, check which code to call */
1913 :
1914 8232 : if (super == NULL) {
1915 1714 : M_TEST(s1);
1916 1714 : emit_label_beq(cd, BRANCH_LABEL_1);
1917 :
1918 : patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_flags,
1919 1714 : iptr->sx.s23.s3.c.ref, 0);
1920 :
1921 1714 : emit_arbitrary_nop(cd, PATCH_ALIGNMENT((uintptr_t) cd->mcodeptr, 2, sizeof(int32_t)));
1922 :
1923 1714 : M_IMOV_IMM(0, REG_ITMP2); /* super->flags */
1924 1714 : M_IAND_IMM(ACC_INTERFACE, REG_ITMP2);
1925 1714 : emit_label_beq(cd, BRANCH_LABEL_2);
1926 : }
1927 :
1928 : /* interface checkcast code */
1929 :
1930 8232 : if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
1931 2093 : if (super != NULL) {
1932 379 : M_TEST(s1);
1933 379 : emit_label_beq(cd, BRANCH_LABEL_3);
1934 : }
1935 :
1936 2093 : M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
1937 :
1938 2093 : if (super == NULL) {
1939 : patcher_add_patch_ref(jd, PATCHER_checkcast_interface,
1940 : iptr->sx.s23.s3.c.ref,
1941 1714 : 0);
1942 1714 : emit_arbitrary_nop(cd, PATCH_ALIGNMENT((uintptr_t) cd->mcodeptr, 10, sizeof(int32_t)));
1943 : }
1944 :
1945 : M_ILD32(REG_ITMP3,
1946 2093 : REG_ITMP2, OFFSET(vftbl_t, interfacetablelength));
1947 2093 : M_ICMP_IMM32(superindex, REG_ITMP3);
1948 2093 : emit_classcast_check(cd, iptr, BRANCH_LE, REG_ITMP3, s1);
1949 :
1950 2093 : if (super == NULL)
1951 1714 : emit_arbitrary_nop(cd, PATCH_ALIGNMENT((uintptr_t) cd->mcodeptr, 3, sizeof(int32_t)));
1952 2093 : M_ALD32(REG_ITMP3, REG_ITMP2,
1953 : OFFSET(vftbl_t, interfacetable[0]) -
1954 2093 : superindex * sizeof(methodptr*));
1955 2093 : M_TEST(REG_ITMP3);
1956 2093 : emit_classcast_check(cd, iptr, BRANCH_EQ, REG_ITMP3, s1);
1957 :
1958 2093 : if (super == NULL)
1959 1714 : emit_label_br(cd, BRANCH_LABEL_4);
1960 : else
1961 379 : emit_label(cd, BRANCH_LABEL_3);
1962 : }
1963 :
1964 : /* class checkcast code */
1965 :
1966 8232 : if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
1967 7853 : if (super == NULL) {
1968 1714 : emit_label(cd, BRANCH_LABEL_2);
1969 :
1970 1714 : constant_classref *cr = iptr->sx.s23.s3.c.ref;
1971 1714 : disp = dseg_add_unique_address(cd, cr);
1972 :
1973 : patcher_add_patch_ref(jd,
1974 : PATCHER_resolve_classref_to_vftbl,
1975 1714 : cr, disp);
1976 : }
1977 : else {
1978 6139 : M_TEST(s1);
1979 6139 : emit_label_beq(cd, BRANCH_LABEL_5);
1980 :
1981 6139 : disp = dseg_add_address(cd, super->vftbl);
1982 : }
1983 :
1984 7853 : M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
1985 7853 : M_ALD(REG_ITMP3, RIP, disp);
1986 :
1987 9709 : if (super == NULL || super->vftbl->subtype_depth >= DISPLAY_SIZE) {
1988 1856 : M_ILD(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, subtype_offset));
1989 1856 : M_LCMP_MEMINDEX(REG_ITMP2, 0, REG_ITMP1, 0, REG_ITMP3);
1990 1856 : emit_label_beq(cd, BRANCH_LABEL_6); /* good */
1991 :
1992 1856 : if (super == NULL) {
1993 1714 : M_LCMP_IMM(OFFSET(vftbl_t, subtype_display[DISPLAY_SIZE]), REG_ITMP1);
1994 1714 : emit_label_bne(cd, BRANCH_LABEL_10); /* throw */
1995 : }
1996 :
1997 1856 : M_ILD(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, subtype_depth));
1998 1856 : M_ICMP_MEMBASE(REG_ITMP2, OFFSET(vftbl_t, subtype_depth), REG_ITMP1);
1999 1856 : emit_label_bgt(cd, BRANCH_LABEL_9); /* throw */
2000 :
2001 1856 : M_ALD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, subtype_overflow));
2002 1856 : M_LCMP_MEMINDEX(REG_ITMP2, -8*DISPLAY_SIZE, REG_ITMP1, 3, REG_ITMP3);
2003 1856 : emit_label_beq(cd, BRANCH_LABEL_7); /* good */
2004 :
2005 1856 : emit_label(cd, BRANCH_LABEL_9);
2006 1856 : if (super == NULL)
2007 1714 : emit_label(cd, BRANCH_LABEL_10);
2008 :
2009 : /* reload s1, might have been destroyed */
2010 1856 : emit_load_s1(jd, iptr, REG_ITMP1);
2011 1856 : M_ALD_MEM(s1, TRAP_ClassCastException);
2012 :
2013 1856 : emit_label(cd, BRANCH_LABEL_7);
2014 1856 : emit_label(cd, BRANCH_LABEL_6);
2015 : /* reload s1, might have been destroyed */
2016 1856 : emit_load_s1(jd, iptr, REG_ITMP1);
2017 : }
2018 : else {
2019 5997 : M_LCMP_MEMBASE(REG_ITMP2, super->vftbl->subtype_offset, REG_ITMP3);
2020 5997 : emit_classcast_check(cd, iptr, BRANCH_NE, REG_ITMP3, s1);
2021 : }
2022 :
2023 7853 : if (super != NULL)
2024 6139 : emit_label(cd, BRANCH_LABEL_5);
2025 : }
2026 :
2027 8232 : if (super == NULL) {
2028 1714 : emit_label(cd, BRANCH_LABEL_1);
2029 1714 : emit_label(cd, BRANCH_LABEL_4);
2030 : }
2031 :
2032 8232 : d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
2033 : }
2034 : else {
2035 : /* array type cast-check */
2036 :
2037 959 : s1 = emit_load_s1(jd, iptr, REG_ITMP2);
2038 959 : M_INTMOVE(s1, REG_A0);
2039 :
2040 959 : if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2041 160 : constant_classref *cr = iptr->sx.s23.s3.c.ref;
2042 160 : disp = dseg_add_unique_address(cd, cr);
2043 :
2044 : patcher_add_patch_ref(jd,
2045 : PATCHER_resolve_classref_to_classinfo,
2046 160 : cr, disp);
2047 : }
2048 : else {
2049 799 : disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
2050 : }
2051 :
2052 959 : M_ALD(REG_A1, RIP, disp);
2053 959 : M_MOV_IMM(BUILTIN_arraycheckcast, REG_ITMP1);
2054 959 : M_CALL(REG_ITMP1);
2055 :
2056 : /* s1 may have been destroyed over the function call */
2057 959 : s1 = emit_load_s1(jd, iptr, REG_ITMP2);
2058 959 : M_TEST(REG_RESULT);
2059 959 : emit_classcast_check(cd, iptr, BRANCH_EQ, REG_RESULT, s1);
2060 :
2061 959 : d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2062 : }
2063 :
2064 9191 : M_INTMOVE(s1, d);
2065 9191 : emit_store_dst(jd, iptr, d);
2066 9191 : break;
2067 :
2068 : case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
2069 :
2070 : {
2071 : classinfo *super;
2072 : s4 superindex;
2073 :
2074 1267 : if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2075 272 : super = NULL;
2076 272 : superindex = 0;
2077 : }
2078 : else {
2079 995 : super = iptr->sx.s23.s3.c.cls;
2080 995 : superindex = super->index;
2081 : }
2082 :
2083 1267 : s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2084 1267 : d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2085 :
2086 1267 : if (s1 == d) {
2087 145 : M_INTMOVE(s1, REG_ITMP1);
2088 145 : s1 = REG_ITMP1;
2089 : }
2090 :
2091 1267 : M_CLR(d);
2092 :
2093 : /* if class is not resolved, check which code to call */
2094 :
2095 1267 : if (super == NULL) {
2096 272 : M_TEST(s1);
2097 272 : emit_label_beq(cd, BRANCH_LABEL_1);
2098 :
2099 : patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_flags,
2100 272 : iptr->sx.s23.s3.c.ref, 0);
2101 :
2102 272 : emit_arbitrary_nop(cd, PATCH_ALIGNMENT((uintptr_t) cd->mcodeptr, 2, sizeof(int32_t)));
2103 :
2104 272 : M_IMOV_IMM(0, REG_ITMP3); /* super->flags */
2105 272 : M_IAND_IMM(ACC_INTERFACE, REG_ITMP3);
2106 272 : emit_label_beq(cd, BRANCH_LABEL_2);
2107 : }
2108 :
2109 : /* interface instanceof code */
2110 :
2111 1267 : if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
2112 : int nops;
2113 425 : if (super != NULL) {
2114 153 : M_TEST(s1);
2115 153 : emit_label_beq(cd, BRANCH_LABEL_3);
2116 : }
2117 :
2118 425 : M_ALD(REG_ITMP1, s1, OFFSET(java_object_t, vftbl));
2119 :
2120 425 : if (super == NULL) {
2121 : patcher_add_patch_ref(jd, PATCHER_instanceof_interface,
2122 272 : iptr->sx.s23.s3.c.ref, 0);
2123 272 : emit_arbitrary_nop(cd, PATCH_ALIGNMENT((uintptr_t) cd->mcodeptr, 10, sizeof(int32_t)));
2124 : }
2125 :
2126 : M_ILD32(REG_ITMP3,
2127 425 : REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
2128 425 : M_ICMP_IMM32(superindex, REG_ITMP3);
2129 :
2130 425 : nops = super == NULL ? PATCH_ALIGNMENT((uintptr_t) (cd->mcodeptr + 6), 3, sizeof(int32_t)) : 0;
2131 :
2132 425 : int a = 3 + 4 /* mov_membase32_reg */ + 3 /* test */ + 4 /* setcc */ + nops;
2133 :
2134 425 : M_BLE(a);
2135 425 : emit_arbitrary_nop(cd, nops);
2136 425 : M_ALD32(REG_ITMP1, REG_ITMP1,
2137 : OFFSET(vftbl_t, interfacetable[0]) -
2138 425 : superindex * sizeof(methodptr*));
2139 425 : M_TEST(REG_ITMP1);
2140 425 : M_SETNE(d);
2141 :
2142 425 : if (super == NULL)
2143 272 : emit_label_br(cd, BRANCH_LABEL_4);
2144 : else
2145 153 : emit_label(cd, BRANCH_LABEL_3);
2146 : }
2147 :
2148 : /* class instanceof code */
2149 :
2150 1267 : if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
2151 1114 : if (super == NULL) {
2152 272 : emit_label(cd, BRANCH_LABEL_2);
2153 :
2154 272 : constant_classref *cr = iptr->sx.s23.s3.c.ref;
2155 272 : disp = dseg_add_unique_address(cd, cr);
2156 :
2157 : patcher_add_patch_ref(jd,
2158 : PATCHER_resolve_classref_to_vftbl,
2159 272 : cr, disp);
2160 : }
2161 : else {
2162 842 : M_TEST(s1);
2163 842 : emit_label_beq(cd, BRANCH_LABEL_5);
2164 :
2165 842 : disp = dseg_add_address(cd, super->vftbl);
2166 : }
2167 :
2168 1114 : M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
2169 1114 : M_ALD(REG_ITMP3, RIP, disp);
2170 :
2171 1388 : if (super == NULL || super->vftbl->subtype_depth >= DISPLAY_SIZE) {
2172 274 : M_ILD(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, subtype_offset));
2173 274 : M_LCMP_MEMINDEX(REG_ITMP2, 0, REG_ITMP1, 0, REG_ITMP3);
2174 274 : emit_label_bne(cd, BRANCH_LABEL_8); /* jump over INC/SETE */
2175 274 : if (d == REG_ITMP2) {
2176 0 : M_SETE(d);
2177 0 : M_BSEXT(d, d);
2178 : } else
2179 274 : M_LINC(d);
2180 274 : emit_label_br(cd, BRANCH_LABEL_6); /* true */
2181 274 : emit_label(cd, BRANCH_LABEL_8);
2182 :
2183 274 : if (super == NULL) {
2184 272 : M_LCMP_IMM(OFFSET(vftbl_t, subtype_display[DISPLAY_SIZE]), REG_ITMP1);
2185 272 : emit_label_bne(cd, BRANCH_LABEL_10); /* false */
2186 : }
2187 :
2188 274 : M_ILD(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, subtype_depth));
2189 274 : M_ICMP_MEMBASE(REG_ITMP2, OFFSET(vftbl_t, subtype_depth), REG_ITMP1);
2190 274 : emit_label_bgt(cd, BRANCH_LABEL_9); /* false */
2191 :
2192 274 : M_ALD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, subtype_overflow));
2193 274 : M_LCMP_MEMINDEX(REG_ITMP2, -8*DISPLAY_SIZE, REG_ITMP1, 3, REG_ITMP3);
2194 274 : M_SETE(d);
2195 274 : if (d == REG_ITMP2) {
2196 0 : M_BSEXT(d, d);
2197 :
2198 0 : emit_label_br(cd, BRANCH_LABEL_7); /* jump over M_CLR */
2199 : }
2200 :
2201 274 : emit_label(cd, BRANCH_LABEL_9);
2202 274 : if (super == NULL)
2203 272 : emit_label(cd, BRANCH_LABEL_10);
2204 274 : if (d == REG_ITMP2) {
2205 0 : M_CLR(d);
2206 :
2207 0 : emit_label(cd, BRANCH_LABEL_7);
2208 : }
2209 274 : emit_label(cd, BRANCH_LABEL_6);
2210 : }
2211 : else {
2212 840 : M_LCMP_MEMBASE(REG_ITMP2, super->vftbl->subtype_offset, REG_ITMP3);
2213 840 : M_SETE(d);
2214 840 : if (d == REG_ITMP2)
2215 0 : M_BSEXT(d, d);
2216 : }
2217 :
2218 1114 : if (super != NULL)
2219 842 : emit_label(cd, BRANCH_LABEL_5);
2220 : }
2221 :
2222 1267 : if (super == NULL) {
2223 272 : emit_label(cd, BRANCH_LABEL_1);
2224 272 : emit_label(cd, BRANCH_LABEL_4);
2225 : }
2226 :
2227 1267 : emit_store_dst(jd, iptr, d);
2228 : }
2229 1267 : break;
2230 :
2231 : case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
2232 :
2233 : /* check for negative sizes and copy sizes to stack if necessary */
2234 :
2235 15 : MCODECHECK((10 * 4 * iptr->s1.argcount) + 5 + 10 * 8);
2236 :
2237 67 : for (s1 = iptr->s1.argcount; --s1 >= 0; ) {
2238 :
2239 : /* copy SAVEDVAR sizes to stack */
2240 37 : var = VAR(iptr->sx.s23.s2.args[s1]);
2241 :
2242 : /* Already Preallocated? */
2243 37 : if (!(var->flags & PREALLOC)) {
2244 37 : s2 = emit_load(jd, iptr, var, REG_ITMP1);
2245 37 : M_LST(s2, REG_SP, s1 * 8);
2246 : }
2247 : }
2248 :
2249 : /* a0 = dimension count */
2250 :
2251 15 : M_MOV_IMM(iptr->s1.argcount, REG_A0);
2252 :
2253 : /* is a patcher function set? */
2254 :
2255 15 : if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2256 2 : constant_classref *cr = iptr->sx.s23.s3.c.ref;
2257 2 : disp = dseg_add_unique_address(cd, cr);
2258 :
2259 : patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_classinfo,
2260 2 : cr, disp);
2261 : }
2262 : else {
2263 13 : disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
2264 : }
2265 :
2266 : /* a1 = classinfo */
2267 :
2268 15 : M_ALD(REG_A1, RIP, disp);
2269 :
2270 : /* a2 = pointer to dimensions = stack pointer */
2271 :
2272 15 : M_MOV(REG_SP, REG_A2);
2273 :
2274 15 : M_MOV_IMM(BUILTIN_multianewarray, REG_ITMP1);
2275 15 : M_CALL(REG_ITMP1);
2276 :
2277 : /* check for exception before result assignment */
2278 :
2279 15 : emit_exception_check(cd, iptr);
2280 :
2281 15 : s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT);
2282 15 : M_INTMOVE(REG_RESULT, s1);
2283 15 : emit_store_dst(jd, iptr, s1);
2284 15 : break;
2285 :
2286 : default:
2287 0 : vm_abort("Unknown ICMD %d during code generation", iptr->opc);
2288 : } /* switch */
2289 1368799 : }
2290 :
2291 :
2292 : /* codegen_emit_stub_native ****************************************************
2293 :
2294 : Emits a stub routine which calls a native method.
2295 :
2296 : *******************************************************************************/
2297 :
2298 13057 : void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f, int skipparams)
2299 : {
2300 : methodinfo *m;
2301 : codeinfo *code;
2302 : codegendata *cd;
2303 : methoddesc *md;
2304 : int i, j;
2305 : int s1, s2;
2306 : int disp;
2307 :
2308 : /* Sanity check. */
2309 :
2310 13057 : assert(f != NULL);
2311 :
2312 : /* Get required compiler data. */
2313 :
2314 13057 : m = jd->m;
2315 13057 : code = jd->code;
2316 13057 : cd = jd->cd;
2317 :
2318 : /* initialize variables */
2319 :
2320 13057 : md = m->parseddesc;
2321 :
2322 : /* calculate stack frame size */
2323 :
2324 : cd->stackframesize =
2325 : sizeof(stackframeinfo_t) / SIZEOF_VOID_P +
2326 : sizeof(localref_table) / SIZEOF_VOID_P +
2327 : md->paramcount +
2328 : (md->returntype.type == TYPE_VOID ? 0 : 1) +
2329 13057 : nmd->memuse;
2330 :
2331 13057 : ALIGN_ODD(cd->stackframesize); /* keep stack 16-byte aligned */
2332 :
2333 : /* create method header */
2334 :
2335 13057 : (void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
2336 13057 : (void) dseg_add_unique_s4(cd, cd->stackframesize * 8); /* FrameSize */
2337 13057 : (void) dseg_add_unique_s4(cd, 0); /* IsLeaf */
2338 13057 : (void) dseg_add_unique_s4(cd, 0); /* IntSave */
2339 13057 : (void) dseg_add_unique_s4(cd, 0); /* FltSave */
2340 :
2341 : #if defined(ENABLE_PROFILING)
2342 : /* generate native method profiling code */
2343 :
2344 : if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
2345 : /* count frequency */
2346 :
2347 : M_MOV_IMM(code, REG_ITMP3);
2348 : M_IINC_MEMBASE(REG_ITMP3, OFFSET(codeinfo, frequency));
2349 : }
2350 : #endif
2351 :
2352 : /* generate stub code */
2353 :
2354 13057 : M_ASUB_IMM(cd->stackframesize * 8, REG_SP);
2355 :
2356 : #if defined(ENABLE_GC_CACAO)
2357 : /* Save callee saved integer registers in stackframeinfo (GC may
2358 : need to recover them during a collection). */
2359 :
2360 : disp = cd->stackframesize * 8 - sizeof(stackframeinfo_t) +
2361 : OFFSET(stackframeinfo_t, intregs);
2362 :
2363 : for (i = 0; i < INT_SAV_CNT; i++)
2364 : M_AST(abi_registers_integer_saved[i], REG_SP, disp + i * 8);
2365 : #endif
2366 :
2367 : /* save integer and float argument registers */
2368 :
2369 29137 : for (i = 0; i < md->paramcount; i++) {
2370 16080 : if (!md->params[i].inmemory) {
2371 16026 : s1 = md->params[i].regoff;
2372 :
2373 16026 : switch (md->paramtypes[i].type) {
2374 : case TYPE_INT:
2375 : case TYPE_LNG:
2376 : case TYPE_ADR:
2377 15978 : M_LST(s1, REG_SP, i * 8);
2378 15978 : break;
2379 : case TYPE_FLT:
2380 : case TYPE_DBL:
2381 48 : M_DST(s1, REG_SP, i * 8);
2382 48 : break;
2383 : default:
2384 0 : assert(false);
2385 : break;
2386 : }
2387 : }
2388 : }
2389 :
2390 : /* create dynamic stack info */
2391 :
2392 13057 : M_MOV(REG_SP, REG_A0);
2393 13057 : emit_lea_membase_reg(cd, RIP, -((cd->mcodeptr + 7) - cd->mcodebase), REG_A1);
2394 13057 : M_MOV_IMM(codegen_start_native_call, REG_ITMP1);
2395 13057 : M_CALL(REG_ITMP1);
2396 :
2397 : /* remember class argument */
2398 :
2399 13057 : if (m->flags & ACC_STATIC)
2400 5157 : M_MOV(REG_RESULT, REG_ITMP2);
2401 :
2402 : /* restore integer and float argument registers */
2403 :
2404 29137 : for (i = 0; i < md->paramcount; i++) {
2405 16080 : if (!md->params[i].inmemory) {
2406 16026 : s1 = md->params[i].regoff;
2407 :
2408 16026 : switch (md->paramtypes[i].type) {
2409 : case TYPE_INT:
2410 : case TYPE_LNG:
2411 : case TYPE_ADR:
2412 15978 : M_LLD(s1, REG_SP, i * 8);
2413 15978 : break;
2414 : case TYPE_FLT:
2415 : case TYPE_DBL:
2416 48 : M_DLD(s1, REG_SP, i * 8);
2417 48 : break;
2418 : default:
2419 0 : assert(false);
2420 : break;
2421 : }
2422 : }
2423 : }
2424 :
2425 : /* Copy or spill arguments to new locations. */
2426 :
2427 29137 : for (i = md->paramcount - 1, j = i + skipparams; i >= 0; i--, j--) {
2428 16080 : s2 = nmd->params[j].regoff;
2429 :
2430 16080 : switch (md->paramtypes[i].type) {
2431 : case TYPE_INT:
2432 : case TYPE_LNG:
2433 : case TYPE_ADR:
2434 16008 : if (!md->params[i].inmemory) {
2435 15978 : s1 = md->params[i].regoff;
2436 :
2437 15978 : if (!nmd->params[j].inmemory)
2438 15688 : M_INTMOVE(s1, s2);
2439 : else
2440 290 : M_LST(s1, REG_SP, s2);
2441 : }
2442 : else {
2443 30 : s1 = md->params[i].regoff + cd->stackframesize * 8 + 8;/* +1 (RA) */
2444 30 : M_LLD(REG_ITMP1, REG_SP, s1);
2445 30 : M_LST(REG_ITMP1, REG_SP, s2);
2446 : }
2447 16008 : break;
2448 : case TYPE_FLT:
2449 : /* We only copy spilled float arguments, as the float
2450 : argument registers keep unchanged. */
2451 :
2452 31 : if (md->params[i].inmemory) {
2453 12 : s1 = md->params[i].regoff + cd->stackframesize * 8 + 8;/* +1 (RA) */
2454 :
2455 12 : M_FLD(REG_FTMP1, REG_SP, s1);
2456 12 : M_FST(REG_FTMP1, REG_SP, s2);
2457 : }
2458 31 : break;
2459 : case TYPE_DBL:
2460 41 : if (md->params[i].inmemory) {
2461 12 : s1 = md->params[i].regoff + cd->stackframesize * 8 + 8;/* +1 (RA) */
2462 12 : M_DLD(REG_FTMP1, REG_SP, s1);
2463 12 : M_DST(REG_FTMP1, REG_SP, s2);
2464 : }
2465 41 : break;
2466 : default:
2467 0 : assert(false);
2468 : break;
2469 : }
2470 : }
2471 :
2472 : /* Handle native Java methods. */
2473 :
2474 13057 : if (m->flags & ACC_NATIVE) {
2475 : /* put class into second argument register */
2476 :
2477 10775 : if (m->flags & ACC_STATIC)
2478 5157 : M_MOV(REG_ITMP2, REG_A1);
2479 :
2480 : /* put env into first argument register */
2481 :
2482 10775 : M_MOV_IMM(VM::get_current()->get_jnienv(), REG_A0);
2483 : }
2484 :
2485 : /* Call the native function. */
2486 :
2487 13057 : disp = dseg_add_functionptr(cd, f);
2488 13057 : M_ALD(REG_ITMP1, RIP, disp);
2489 13057 : M_CALL(REG_ITMP1);
2490 :
2491 : /* save return value */
2492 :
2493 13057 : switch (md->returntype.type) {
2494 : case TYPE_INT:
2495 : case TYPE_LNG:
2496 : case TYPE_ADR:
2497 11675 : switch (md->returntype.primitivetype) {
2498 : case PRIMITIVETYPE_BOOLEAN:
2499 494 : M_BZEXT(REG_RESULT, REG_RESULT);
2500 494 : break;
2501 : case PRIMITIVETYPE_BYTE:
2502 0 : M_BSEXT(REG_RESULT, REG_RESULT);
2503 0 : break;
2504 : case PRIMITIVETYPE_CHAR:
2505 0 : M_CZEXT(REG_RESULT, REG_RESULT);
2506 0 : break;
2507 : case PRIMITIVETYPE_SHORT:
2508 0 : M_SSEXT(REG_RESULT, REG_RESULT);
2509 : break;
2510 : default:
2511 : break;
2512 : }
2513 11675 : M_LST(REG_RESULT, REG_SP, 0 * 8);
2514 11675 : break;
2515 : case TYPE_FLT:
2516 : case TYPE_DBL:
2517 5 : M_DST(REG_FRESULT, REG_SP, 0 * 8);
2518 5 : break;
2519 : case TYPE_VOID:
2520 1377 : break;
2521 : default:
2522 0 : assert(false);
2523 : break;
2524 : }
2525 :
2526 : /* remove native stackframe info */
2527 :
2528 13057 : M_MOV(REG_SP, REG_A0);
2529 13057 : emit_lea_membase_reg(cd, RIP, -((cd->mcodeptr + 7) - cd->mcodebase), REG_A1);
2530 13057 : M_MOV_IMM(codegen_finish_native_call, REG_ITMP1);
2531 13057 : M_CALL(REG_ITMP1);
2532 13057 : M_MOV(REG_RESULT, REG_ITMP3);
2533 :
2534 : /* restore return value */
2535 :
2536 13057 : switch (md->returntype.type) {
2537 : case TYPE_INT:
2538 : case TYPE_LNG:
2539 : case TYPE_ADR:
2540 11675 : M_LLD(REG_RESULT, REG_SP, 0 * 8);
2541 11675 : break;
2542 : case TYPE_FLT:
2543 : case TYPE_DBL:
2544 5 : M_DLD(REG_FRESULT, REG_SP, 0 * 8);
2545 5 : break;
2546 : case TYPE_VOID:
2547 1377 : break;
2548 : default:
2549 0 : assert(false);
2550 : break;
2551 : }
2552 :
2553 : #if defined(ENABLE_GC_CACAO)
2554 : /* Restore callee saved integer registers from stackframeinfo (GC
2555 : might have modified them during a collection). */
2556 :
2557 : disp = cd->stackframesize * 8 - sizeof(stackframeinfo_t) +
2558 : OFFSET(stackframeinfo_t, intregs);
2559 :
2560 : for (i = 0; i < INT_SAV_CNT; i++)
2561 : M_ALD(abi_registers_integer_saved[i], REG_SP, disp + i * 8);
2562 : #endif
2563 :
2564 : /* remove stackframe */
2565 :
2566 13057 : M_AADD_IMM(cd->stackframesize * 8, REG_SP);
2567 :
2568 : /* test for exception */
2569 :
2570 13057 : M_TEST(REG_ITMP3);
2571 13057 : M_BNE(1);
2572 13057 : M_RET;
2573 :
2574 : /* handle exception */
2575 :
2576 13057 : M_MOV(REG_ITMP3, REG_ITMP1_XPTR);
2577 13057 : M_ALD(REG_ITMP2_XPC, REG_SP, 0 * 8); /* get return address from stack */
2578 13057 : M_ASUB_IMM(3, REG_ITMP2_XPC); /* callq */
2579 :
2580 13057 : M_MOV_IMM(asm_handle_nat_exception, REG_ITMP3);
2581 13057 : M_JMP(REG_ITMP3);
2582 13057 : }
2583 :
2584 :
2585 : /*
2586 : * These are local overrides for various environment variables in Emacs.
2587 : * Please do not remove this and leave it at the end of the file, where
2588 : * Emacs will automagically detect them.
2589 : * ---------------------------------------------------------------------
2590 : * Local variables:
2591 : * mode: c++
2592 : * indent-tabs-mode: t
2593 : * c-basic-offset: 4
2594 : * tab-width: 4
2595 : * End:
2596 : * vim:noexpandtab:sw=4:ts=4:
2597 : */
|