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_ALD_MEM(REG_METHODPTR, TRAP_THROW);
1736 18423 : break;
1737 :
1738 : case ICMD_IF_LEQ: /* ..., value ==> ... */
1739 : case ICMD_IF_LNE:
1740 : case ICMD_IF_LLT:
1741 : case ICMD_IF_LGE:
1742 : case ICMD_IF_LGT:
1743 : case ICMD_IF_LLE:
1744 :
1745 295 : s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1746 560 : if (IS_IMM32(iptr->sx.val.l))
1747 265 : M_LCMP_IMM(iptr->sx.val.l, s1);
1748 : else {
1749 30 : M_MOV_IMM(iptr->sx.val.l, REG_ITMP2);
1750 30 : M_LCMP(REG_ITMP2, s1);
1751 : }
1752 295 : emit_bcc(cd, iptr->dst.block, iptr->opc - ICMD_IF_LEQ, BRANCH_OPT_NONE);
1753 295 : break;
1754 :
1755 : case ICMD_IF_LCMPEQ: /* ..., value, value ==> ... */
1756 : case ICMD_IF_LCMPNE:
1757 : case ICMD_IF_LCMPLT:
1758 : case ICMD_IF_LCMPGE:
1759 : case ICMD_IF_LCMPGT:
1760 : case ICMD_IF_LCMPLE:
1761 :
1762 124 : s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1763 124 : s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1764 124 : M_LCMP(s2, s1);
1765 124 : emit_bcc(cd, iptr->dst.block, iptr->opc - ICMD_IF_LCMPEQ, BRANCH_OPT_NONE);
1766 124 : break;
1767 :
1768 : case ICMD_TABLESWITCH: /* ..., index ==> ... */
1769 : {
1770 : s4 i, l;
1771 : branch_target_t *table;
1772 :
1773 72 : table = iptr->dst.table;
1774 :
1775 72 : l = iptr->sx.s23.s2.tablelow;
1776 72 : i = iptr->sx.s23.s3.tablehigh;
1777 :
1778 72 : s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1779 72 : M_INTMOVE(s1, REG_ITMP1);
1780 :
1781 72 : if (l != 0)
1782 44 : M_ISUB_IMM(l, REG_ITMP1);
1783 :
1784 : /* number of targets */
1785 72 : i = i - l + 1;
1786 :
1787 : /* range check */
1788 :
1789 72 : M_ICMP_IMM(i - 1, REG_ITMP1);
1790 72 : emit_bugt(cd, table[0].block);
1791 :
1792 : /* build jump table top down and use address of lowest entry */
1793 :
1794 72 : table += i;
1795 :
1796 1218 : while (--i >= 0) {
1797 1074 : dseg_add_target(cd, table->block);
1798 1074 : --table;
1799 : }
1800 :
1801 : /* length of dataseg after last dseg_add_target is used
1802 : by load */
1803 :
1804 72 : M_MOV_IMM(0, REG_ITMP2);
1805 72 : dseg_adddata(cd);
1806 72 : emit_mov_memindex_reg(cd, -(cd->dseglen), REG_ITMP2, REG_ITMP1, 3, REG_ITMP1);
1807 72 : M_JMP(REG_ITMP1);
1808 : }
1809 72 : break;
1810 :
1811 : case ICMD_BUILTIN:
1812 77258 : bte = iptr->sx.s23.s3.bte;
1813 77258 : if (bte->stub == NULL) {
1814 1840 : M_MOV_IMM(bte->fp, REG_ITMP1);
1815 : }
1816 : else {
1817 75418 : M_MOV_IMM(bte->stub, REG_ITMP1);
1818 : }
1819 77258 : M_CALL(REG_ITMP1);
1820 77258 : break;
1821 :
1822 : case ICMD_INVOKESPECIAL:
1823 98529 : emit_nullpointer_check(cd, iptr, REG_A0);
1824 : /* fall through */
1825 :
1826 : case ICMD_INVOKESTATIC:
1827 155417 : if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1828 43458 : um = iptr->sx.s23.s3.um;
1829 43458 : disp = dseg_add_unique_address(cd, um);
1830 :
1831 : patcher_add_patch_ref(jd, PATCHER_invokestatic_special,
1832 43458 : um, disp);
1833 : }
1834 : else {
1835 111959 : lm = iptr->sx.s23.s3.fmiref->p.method;
1836 111959 : disp = dseg_add_functionptr(cd, lm->stubroutine);
1837 : }
1838 :
1839 155417 : M_ALD(REG_ITMP2, RIP, disp);
1840 155417 : M_CALL(REG_ITMP2);
1841 155417 : break;
1842 :
1843 : case ICMD_INVOKEVIRTUAL:
1844 119224 : if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1845 19564 : um = iptr->sx.s23.s3.um;
1846 19564 : patcher_add_patch_ref(jd, PATCHER_invokevirtual, um, 0);
1847 19564 : emit_arbitrary_nop(cd, PATCH_ALIGNMENT((uintptr_t) cd->mcodeptr, 6, sizeof(int32_t)));
1848 :
1849 19564 : s1 = 0;
1850 : }
1851 : else {
1852 99660 : lm = iptr->sx.s23.s3.fmiref->p.method;
1853 99660 : s1 = OFFSET(vftbl_t, table[0]) +
1854 199320 : sizeof(methodptr) * lm->vftblindex;
1855 : }
1856 :
1857 : /* implicit null-pointer check */
1858 119224 : M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_object_t, vftbl));
1859 119224 : M_ALD32(REG_ITMP3, REG_METHODPTR, s1);
1860 119224 : M_CALL(REG_ITMP3);
1861 119224 : break;
1862 :
1863 : case ICMD_INVOKEINTERFACE:
1864 7503 : if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1865 1210 : um = iptr->sx.s23.s3.um;
1866 1210 : patcher_add_patch_ref(jd, PATCHER_invokeinterface, um, 0);
1867 1210 : emit_arbitrary_nop(cd, PATCH_ALIGNMENT((uintptr_t) cd->mcodeptr, 6, sizeof(int32_t)));
1868 :
1869 1210 : s1 = 0;
1870 1210 : s2 = 0;
1871 : }
1872 : else {
1873 6293 : lm = iptr->sx.s23.s3.fmiref->p.method;
1874 6293 : s1 = OFFSET(vftbl_t, interfacetable[0]) -
1875 6293 : sizeof(methodptr) * lm->clazz->index;
1876 :
1877 6293 : s2 = sizeof(methodptr) * (lm - lm->clazz->methods);
1878 : }
1879 :
1880 : /* implicit null-pointer check */
1881 7503 : M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_object_t, vftbl));
1882 7503 : M_ALD32(REG_METHODPTR, REG_METHODPTR, s1);
1883 7503 : if (INSTRUCTION_IS_UNRESOLVED(iptr))
1884 1210 : emit_arbitrary_nop(cd, PATCH_ALIGNMENT((uintptr_t) cd->mcodeptr, 3, sizeof(int32_t)));
1885 7503 : M_ALD32(REG_ITMP3, REG_METHODPTR, s2);
1886 7503 : M_CALL(REG_ITMP3);
1887 7503 : break;
1888 :
1889 : case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
1890 :
1891 9191 : if (!(iptr->flags.bits & INS_FLAG_ARRAY)) {
1892 : /* object type cast-check */
1893 :
1894 : classinfo *super;
1895 : s4 superindex;
1896 :
1897 8232 : if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1898 1714 : super = NULL;
1899 1714 : superindex = 0;
1900 : }
1901 : else {
1902 6518 : super = iptr->sx.s23.s3.c.cls;
1903 6518 : superindex = super->index;
1904 : }
1905 :
1906 8232 : s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1907 :
1908 : /* if class is not resolved, check which code to call */
1909 :
1910 8232 : if (super == NULL) {
1911 1714 : M_TEST(s1);
1912 1714 : emit_label_beq(cd, BRANCH_LABEL_1);
1913 :
1914 : patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_flags,
1915 1714 : iptr->sx.s23.s3.c.ref, 0);
1916 :
1917 1714 : emit_arbitrary_nop(cd, PATCH_ALIGNMENT((uintptr_t) cd->mcodeptr, 2, sizeof(int32_t)));
1918 :
1919 1714 : M_IMOV_IMM(0, REG_ITMP2); /* super->flags */
1920 1714 : M_IAND_IMM(ACC_INTERFACE, REG_ITMP2);
1921 1714 : emit_label_beq(cd, BRANCH_LABEL_2);
1922 : }
1923 :
1924 : /* interface checkcast code */
1925 :
1926 8232 : if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
1927 2093 : if (super != NULL) {
1928 379 : M_TEST(s1);
1929 379 : emit_label_beq(cd, BRANCH_LABEL_3);
1930 : }
1931 :
1932 2093 : M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
1933 :
1934 2093 : if (super == NULL) {
1935 : patcher_add_patch_ref(jd, PATCHER_checkcast_interface,
1936 : iptr->sx.s23.s3.c.ref,
1937 1714 : 0);
1938 1714 : emit_arbitrary_nop(cd, PATCH_ALIGNMENT((uintptr_t) cd->mcodeptr, 10, sizeof(int32_t)));
1939 : }
1940 :
1941 : M_ILD32(REG_ITMP3,
1942 2093 : REG_ITMP2, OFFSET(vftbl_t, interfacetablelength));
1943 2093 : M_ICMP_IMM32(superindex, REG_ITMP3);
1944 2093 : emit_classcast_check(cd, iptr, BRANCH_LE, REG_ITMP3, s1);
1945 :
1946 2093 : if (super == NULL)
1947 1714 : emit_arbitrary_nop(cd, PATCH_ALIGNMENT((uintptr_t) cd->mcodeptr, 3, sizeof(int32_t)));
1948 2093 : M_ALD32(REG_ITMP3, REG_ITMP2,
1949 : OFFSET(vftbl_t, interfacetable[0]) -
1950 2093 : superindex * sizeof(methodptr*));
1951 2093 : M_TEST(REG_ITMP3);
1952 2093 : emit_classcast_check(cd, iptr, BRANCH_EQ, REG_ITMP3, s1);
1953 :
1954 2093 : if (super == NULL)
1955 1714 : emit_label_br(cd, BRANCH_LABEL_4);
1956 : else
1957 379 : emit_label(cd, BRANCH_LABEL_3);
1958 : }
1959 :
1960 : /* class checkcast code */
1961 :
1962 8232 : if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
1963 7853 : if (super == NULL) {
1964 1714 : emit_label(cd, BRANCH_LABEL_2);
1965 :
1966 1714 : constant_classref *cr = iptr->sx.s23.s3.c.ref;
1967 1714 : disp = dseg_add_unique_address(cd, cr);
1968 :
1969 : patcher_add_patch_ref(jd,
1970 : PATCHER_resolve_classref_to_vftbl,
1971 1714 : cr, disp);
1972 : }
1973 : else {
1974 6139 : M_TEST(s1);
1975 6139 : emit_label_beq(cd, BRANCH_LABEL_5);
1976 :
1977 6139 : disp = dseg_add_address(cd, super->vftbl);
1978 : }
1979 :
1980 7853 : M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
1981 7853 : M_ALD(REG_ITMP3, RIP, disp);
1982 :
1983 9709 : if (super == NULL || super->vftbl->subtype_depth >= DISPLAY_SIZE) {
1984 1856 : M_ILD(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, subtype_offset));
1985 1856 : M_LCMP_MEMINDEX(REG_ITMP2, 0, REG_ITMP1, 0, REG_ITMP3);
1986 1856 : emit_label_beq(cd, BRANCH_LABEL_6); /* good */
1987 :
1988 1856 : if (super == NULL) {
1989 1714 : M_LCMP_IMM(OFFSET(vftbl_t, subtype_display[DISPLAY_SIZE]), REG_ITMP1);
1990 1714 : emit_label_bne(cd, BRANCH_LABEL_10); /* throw */
1991 : }
1992 :
1993 1856 : M_ILD(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, subtype_depth));
1994 1856 : M_ICMP_MEMBASE(REG_ITMP2, OFFSET(vftbl_t, subtype_depth), REG_ITMP1);
1995 1856 : emit_label_bgt(cd, BRANCH_LABEL_9); /* throw */
1996 :
1997 1856 : M_ALD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, subtype_overflow));
1998 1856 : M_LCMP_MEMINDEX(REG_ITMP2, -8*DISPLAY_SIZE, REG_ITMP1, 3, REG_ITMP3);
1999 1856 : emit_label_beq(cd, BRANCH_LABEL_7); /* good */
2000 :
2001 1856 : emit_label(cd, BRANCH_LABEL_9);
2002 1856 : if (super == NULL)
2003 1714 : emit_label(cd, BRANCH_LABEL_10);
2004 :
2005 : /* reload s1, might have been destroyed */
2006 1856 : emit_load_s1(jd, iptr, REG_ITMP1);
2007 1856 : M_ALD_MEM(s1, TRAP_ClassCastException);
2008 :
2009 1856 : emit_label(cd, BRANCH_LABEL_7);
2010 1856 : emit_label(cd, BRANCH_LABEL_6);
2011 : /* reload s1, might have been destroyed */
2012 1856 : emit_load_s1(jd, iptr, REG_ITMP1);
2013 : }
2014 : else {
2015 5997 : M_LCMP_MEMBASE(REG_ITMP2, super->vftbl->subtype_offset, REG_ITMP3);
2016 5997 : emit_classcast_check(cd, iptr, BRANCH_NE, REG_ITMP3, s1);
2017 : }
2018 :
2019 7853 : if (super != NULL)
2020 6139 : emit_label(cd, BRANCH_LABEL_5);
2021 : }
2022 :
2023 8232 : if (super == NULL) {
2024 1714 : emit_label(cd, BRANCH_LABEL_1);
2025 1714 : emit_label(cd, BRANCH_LABEL_4);
2026 : }
2027 :
2028 8232 : d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
2029 : }
2030 : else {
2031 : /* array type cast-check */
2032 :
2033 959 : s1 = emit_load_s1(jd, iptr, REG_ITMP2);
2034 959 : M_INTMOVE(s1, REG_A0);
2035 :
2036 959 : if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2037 160 : constant_classref *cr = iptr->sx.s23.s3.c.ref;
2038 160 : disp = dseg_add_unique_address(cd, cr);
2039 :
2040 : patcher_add_patch_ref(jd,
2041 : PATCHER_resolve_classref_to_classinfo,
2042 160 : cr, disp);
2043 : }
2044 : else {
2045 799 : disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
2046 : }
2047 :
2048 959 : M_ALD(REG_A1, RIP, disp);
2049 959 : M_MOV_IMM(BUILTIN_arraycheckcast, REG_ITMP1);
2050 959 : M_CALL(REG_ITMP1);
2051 :
2052 : /* s1 may have been destroyed over the function call */
2053 959 : s1 = emit_load_s1(jd, iptr, REG_ITMP2);
2054 959 : M_TEST(REG_RESULT);
2055 959 : emit_classcast_check(cd, iptr, BRANCH_EQ, REG_RESULT, s1);
2056 :
2057 959 : d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2058 : }
2059 :
2060 9191 : M_INTMOVE(s1, d);
2061 9191 : emit_store_dst(jd, iptr, d);
2062 9191 : break;
2063 :
2064 : case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
2065 :
2066 : {
2067 : classinfo *super;
2068 : s4 superindex;
2069 :
2070 1267 : if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2071 272 : super = NULL;
2072 272 : superindex = 0;
2073 : }
2074 : else {
2075 995 : super = iptr->sx.s23.s3.c.cls;
2076 995 : superindex = super->index;
2077 : }
2078 :
2079 1267 : s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2080 1267 : d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2081 :
2082 1267 : if (s1 == d) {
2083 145 : M_INTMOVE(s1, REG_ITMP1);
2084 145 : s1 = REG_ITMP1;
2085 : }
2086 :
2087 1267 : M_CLR(d);
2088 :
2089 : /* if class is not resolved, check which code to call */
2090 :
2091 1267 : if (super == NULL) {
2092 272 : M_TEST(s1);
2093 272 : emit_label_beq(cd, BRANCH_LABEL_1);
2094 :
2095 : patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_flags,
2096 272 : iptr->sx.s23.s3.c.ref, 0);
2097 :
2098 272 : emit_arbitrary_nop(cd, PATCH_ALIGNMENT((uintptr_t) cd->mcodeptr, 2, sizeof(int32_t)));
2099 :
2100 272 : M_IMOV_IMM(0, REG_ITMP3); /* super->flags */
2101 272 : M_IAND_IMM(ACC_INTERFACE, REG_ITMP3);
2102 272 : emit_label_beq(cd, BRANCH_LABEL_2);
2103 : }
2104 :
2105 : /* interface instanceof code */
2106 :
2107 1267 : if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
2108 : int nops;
2109 425 : if (super != NULL) {
2110 153 : M_TEST(s1);
2111 153 : emit_label_beq(cd, BRANCH_LABEL_3);
2112 : }
2113 :
2114 425 : M_ALD(REG_ITMP1, s1, OFFSET(java_object_t, vftbl));
2115 :
2116 425 : if (super == NULL) {
2117 : patcher_add_patch_ref(jd, PATCHER_instanceof_interface,
2118 272 : iptr->sx.s23.s3.c.ref, 0);
2119 272 : emit_arbitrary_nop(cd, PATCH_ALIGNMENT((uintptr_t) cd->mcodeptr, 10, sizeof(int32_t)));
2120 : }
2121 :
2122 : M_ILD32(REG_ITMP3,
2123 425 : REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
2124 425 : M_ICMP_IMM32(superindex, REG_ITMP3);
2125 :
2126 425 : nops = super == NULL ? PATCH_ALIGNMENT((uintptr_t) (cd->mcodeptr + 6), 3, sizeof(int32_t)) : 0;
2127 :
2128 425 : int a = 3 + 4 /* mov_membase32_reg */ + 3 /* test */ + 4 /* setcc */ + nops;
2129 :
2130 425 : M_BLE(a);
2131 425 : emit_arbitrary_nop(cd, nops);
2132 425 : M_ALD32(REG_ITMP1, REG_ITMP1,
2133 : OFFSET(vftbl_t, interfacetable[0]) -
2134 425 : superindex * sizeof(methodptr*));
2135 425 : M_TEST(REG_ITMP1);
2136 425 : M_SETNE(d);
2137 :
2138 425 : if (super == NULL)
2139 272 : emit_label_br(cd, BRANCH_LABEL_4);
2140 : else
2141 153 : emit_label(cd, BRANCH_LABEL_3);
2142 : }
2143 :
2144 : /* class instanceof code */
2145 :
2146 1267 : if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
2147 1114 : if (super == NULL) {
2148 272 : emit_label(cd, BRANCH_LABEL_2);
2149 :
2150 272 : constant_classref *cr = iptr->sx.s23.s3.c.ref;
2151 272 : disp = dseg_add_unique_address(cd, cr);
2152 :
2153 : patcher_add_patch_ref(jd,
2154 : PATCHER_resolve_classref_to_vftbl,
2155 272 : cr, disp);
2156 : }
2157 : else {
2158 842 : M_TEST(s1);
2159 842 : emit_label_beq(cd, BRANCH_LABEL_5);
2160 :
2161 842 : disp = dseg_add_address(cd, super->vftbl);
2162 : }
2163 :
2164 1114 : M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
2165 1114 : M_ALD(REG_ITMP3, RIP, disp);
2166 :
2167 1388 : if (super == NULL || super->vftbl->subtype_depth >= DISPLAY_SIZE) {
2168 274 : M_ILD(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, subtype_offset));
2169 274 : M_LCMP_MEMINDEX(REG_ITMP2, 0, REG_ITMP1, 0, REG_ITMP3);
2170 274 : emit_label_bne(cd, BRANCH_LABEL_8); /* jump over INC/SETE */
2171 274 : if (d == REG_ITMP2) {
2172 0 : M_SETE(d);
2173 0 : M_BSEXT(d, d);
2174 : } else
2175 274 : M_LINC(d);
2176 274 : emit_label_br(cd, BRANCH_LABEL_6); /* true */
2177 274 : emit_label(cd, BRANCH_LABEL_8);
2178 :
2179 274 : if (super == NULL) {
2180 272 : M_LCMP_IMM(OFFSET(vftbl_t, subtype_display[DISPLAY_SIZE]), REG_ITMP1);
2181 272 : emit_label_bne(cd, BRANCH_LABEL_10); /* false */
2182 : }
2183 :
2184 274 : M_ILD(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, subtype_depth));
2185 274 : M_ICMP_MEMBASE(REG_ITMP2, OFFSET(vftbl_t, subtype_depth), REG_ITMP1);
2186 274 : emit_label_bgt(cd, BRANCH_LABEL_9); /* false */
2187 :
2188 274 : M_ALD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, subtype_overflow));
2189 274 : M_LCMP_MEMINDEX(REG_ITMP2, -8*DISPLAY_SIZE, REG_ITMP1, 3, REG_ITMP3);
2190 274 : M_SETE(d);
2191 274 : if (d == REG_ITMP2) {
2192 0 : M_BSEXT(d, d);
2193 :
2194 0 : emit_label_br(cd, BRANCH_LABEL_7); /* jump over M_CLR */
2195 : }
2196 :
2197 274 : emit_label(cd, BRANCH_LABEL_9);
2198 274 : if (super == NULL)
2199 272 : emit_label(cd, BRANCH_LABEL_10);
2200 274 : if (d == REG_ITMP2) {
2201 0 : M_CLR(d);
2202 :
2203 0 : emit_label(cd, BRANCH_LABEL_7);
2204 : }
2205 274 : emit_label(cd, BRANCH_LABEL_6);
2206 : }
2207 : else {
2208 840 : M_LCMP_MEMBASE(REG_ITMP2, super->vftbl->subtype_offset, REG_ITMP3);
2209 840 : M_SETE(d);
2210 840 : if (d == REG_ITMP2)
2211 0 : M_BSEXT(d, d);
2212 : }
2213 :
2214 1114 : if (super != NULL)
2215 842 : emit_label(cd, BRANCH_LABEL_5);
2216 : }
2217 :
2218 1267 : if (super == NULL) {
2219 272 : emit_label(cd, BRANCH_LABEL_1);
2220 272 : emit_label(cd, BRANCH_LABEL_4);
2221 : }
2222 :
2223 1267 : emit_store_dst(jd, iptr, d);
2224 : }
2225 1267 : break;
2226 :
2227 : case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
2228 :
2229 : /* check for negative sizes and copy sizes to stack if necessary */
2230 :
2231 15 : MCODECHECK((10 * 4 * iptr->s1.argcount) + 5 + 10 * 8);
2232 :
2233 67 : for (s1 = iptr->s1.argcount; --s1 >= 0; ) {
2234 :
2235 : /* copy SAVEDVAR sizes to stack */
2236 37 : var = VAR(iptr->sx.s23.s2.args[s1]);
2237 :
2238 : /* Already Preallocated? */
2239 37 : if (!(var->flags & PREALLOC)) {
2240 37 : s2 = emit_load(jd, iptr, var, REG_ITMP1);
2241 37 : M_LST(s2, REG_SP, s1 * 8);
2242 : }
2243 : }
2244 :
2245 : /* a0 = dimension count */
2246 :
2247 15 : M_MOV_IMM(iptr->s1.argcount, REG_A0);
2248 :
2249 : /* is a patcher function set? */
2250 :
2251 15 : if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2252 2 : constant_classref *cr = iptr->sx.s23.s3.c.ref;
2253 2 : disp = dseg_add_unique_address(cd, cr);
2254 :
2255 : patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_classinfo,
2256 2 : cr, disp);
2257 : }
2258 : else {
2259 13 : disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
2260 : }
2261 :
2262 : /* a1 = classinfo */
2263 :
2264 15 : M_ALD(REG_A1, RIP, disp);
2265 :
2266 : /* a2 = pointer to dimensions = stack pointer */
2267 :
2268 15 : M_MOV(REG_SP, REG_A2);
2269 :
2270 15 : M_MOV_IMM(BUILTIN_multianewarray, REG_ITMP1);
2271 15 : M_CALL(REG_ITMP1);
2272 :
2273 : /* check for exception before result assignment */
2274 :
2275 15 : emit_exception_check(cd, iptr);
2276 :
2277 15 : s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT);
2278 15 : M_INTMOVE(REG_RESULT, s1);
2279 15 : emit_store_dst(jd, iptr, s1);
2280 15 : break;
2281 :
2282 : default:
2283 0 : vm_abort("Unknown ICMD %d during code generation", iptr->opc);
2284 : } /* switch */
2285 1368799 : }
2286 :
2287 :
2288 : /* codegen_emit_stub_native ****************************************************
2289 :
2290 : Emits a stub routine which calls a native method.
2291 :
2292 : *******************************************************************************/
2293 :
2294 13057 : void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f, int skipparams)
2295 : {
2296 : methodinfo *m;
2297 : codeinfo *code;
2298 : codegendata *cd;
2299 : methoddesc *md;
2300 : int i, j;
2301 : int s1, s2;
2302 : int disp;
2303 :
2304 : /* Sanity check. */
2305 :
2306 13057 : assert(f != NULL);
2307 :
2308 : /* Get required compiler data. */
2309 :
2310 13057 : m = jd->m;
2311 13057 : code = jd->code;
2312 13057 : cd = jd->cd;
2313 :
2314 : /* initialize variables */
2315 :
2316 13057 : md = m->parseddesc;
2317 :
2318 : /* calculate stack frame size */
2319 :
2320 : cd->stackframesize =
2321 : sizeof(stackframeinfo_t) / SIZEOF_VOID_P +
2322 : sizeof(localref_table) / SIZEOF_VOID_P +
2323 : md->paramcount +
2324 : (md->returntype.type == TYPE_VOID ? 0 : 1) +
2325 13057 : nmd->memuse;
2326 :
2327 13057 : ALIGN_ODD(cd->stackframesize); /* keep stack 16-byte aligned */
2328 :
2329 : /* create method header */
2330 :
2331 13057 : (void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
2332 13057 : (void) dseg_add_unique_s4(cd, cd->stackframesize * 8); /* FrameSize */
2333 13057 : (void) dseg_add_unique_s4(cd, 0); /* IsLeaf */
2334 13057 : (void) dseg_add_unique_s4(cd, 0); /* IntSave */
2335 13057 : (void) dseg_add_unique_s4(cd, 0); /* FltSave */
2336 :
2337 : #if defined(ENABLE_PROFILING)
2338 : /* generate native method profiling code */
2339 :
2340 : if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
2341 : /* count frequency */
2342 :
2343 : M_MOV_IMM(code, REG_ITMP3);
2344 : M_IINC_MEMBASE(REG_ITMP3, OFFSET(codeinfo, frequency));
2345 : }
2346 : #endif
2347 :
2348 : /* generate stub code */
2349 :
2350 13057 : M_ASUB_IMM(cd->stackframesize * 8, REG_SP);
2351 :
2352 : #if defined(ENABLE_GC_CACAO)
2353 : /* Save callee saved integer registers in stackframeinfo (GC may
2354 : need to recover them during a collection). */
2355 :
2356 : disp = cd->stackframesize * 8 - sizeof(stackframeinfo_t) +
2357 : OFFSET(stackframeinfo_t, intregs);
2358 :
2359 : for (i = 0; i < INT_SAV_CNT; i++)
2360 : M_AST(abi_registers_integer_saved[i], REG_SP, disp + i * 8);
2361 : #endif
2362 :
2363 : /* save integer and float argument registers */
2364 :
2365 29137 : for (i = 0; i < md->paramcount; i++) {
2366 16080 : if (!md->params[i].inmemory) {
2367 16026 : s1 = md->params[i].regoff;
2368 :
2369 16026 : switch (md->paramtypes[i].type) {
2370 : case TYPE_INT:
2371 : case TYPE_LNG:
2372 : case TYPE_ADR:
2373 15978 : M_LST(s1, REG_SP, i * 8);
2374 15978 : break;
2375 : case TYPE_FLT:
2376 : case TYPE_DBL:
2377 48 : M_DST(s1, REG_SP, i * 8);
2378 48 : break;
2379 : default:
2380 0 : assert(false);
2381 : break;
2382 : }
2383 : }
2384 : }
2385 :
2386 : /* create dynamic stack info */
2387 :
2388 13057 : M_MOV(REG_SP, REG_A0);
2389 13057 : emit_lea_membase_reg(cd, RIP, -((cd->mcodeptr + 7) - cd->mcodebase), REG_A1);
2390 13057 : M_MOV_IMM(codegen_start_native_call, REG_ITMP1);
2391 13057 : M_CALL(REG_ITMP1);
2392 :
2393 : /* remember class argument */
2394 :
2395 13057 : if (m->flags & ACC_STATIC)
2396 5157 : M_MOV(REG_RESULT, REG_ITMP2);
2397 :
2398 : /* restore integer and float argument registers */
2399 :
2400 29137 : for (i = 0; i < md->paramcount; i++) {
2401 16080 : if (!md->params[i].inmemory) {
2402 16026 : s1 = md->params[i].regoff;
2403 :
2404 16026 : switch (md->paramtypes[i].type) {
2405 : case TYPE_INT:
2406 : case TYPE_LNG:
2407 : case TYPE_ADR:
2408 15978 : M_LLD(s1, REG_SP, i * 8);
2409 15978 : break;
2410 : case TYPE_FLT:
2411 : case TYPE_DBL:
2412 48 : M_DLD(s1, REG_SP, i * 8);
2413 48 : break;
2414 : default:
2415 0 : assert(false);
2416 : break;
2417 : }
2418 : }
2419 : }
2420 :
2421 : /* Copy or spill arguments to new locations. */
2422 :
2423 29137 : for (i = md->paramcount - 1, j = i + skipparams; i >= 0; i--, j--) {
2424 16080 : s2 = nmd->params[j].regoff;
2425 :
2426 16080 : switch (md->paramtypes[i].type) {
2427 : case TYPE_INT:
2428 : case TYPE_LNG:
2429 : case TYPE_ADR:
2430 16008 : if (!md->params[i].inmemory) {
2431 15978 : s1 = md->params[i].regoff;
2432 :
2433 15978 : if (!nmd->params[j].inmemory)
2434 15688 : M_INTMOVE(s1, s2);
2435 : else
2436 290 : M_LST(s1, REG_SP, s2);
2437 : }
2438 : else {
2439 30 : s1 = md->params[i].regoff + cd->stackframesize * 8 + 8;/* +1 (RA) */
2440 30 : M_LLD(REG_ITMP1, REG_SP, s1);
2441 30 : M_LST(REG_ITMP1, REG_SP, s2);
2442 : }
2443 16008 : break;
2444 : case TYPE_FLT:
2445 : /* We only copy spilled float arguments, as the float
2446 : argument registers keep unchanged. */
2447 :
2448 31 : if (md->params[i].inmemory) {
2449 12 : s1 = md->params[i].regoff + cd->stackframesize * 8 + 8;/* +1 (RA) */
2450 :
2451 12 : M_FLD(REG_FTMP1, REG_SP, s1);
2452 12 : M_FST(REG_FTMP1, REG_SP, s2);
2453 : }
2454 31 : break;
2455 : case TYPE_DBL:
2456 41 : if (md->params[i].inmemory) {
2457 12 : s1 = md->params[i].regoff + cd->stackframesize * 8 + 8;/* +1 (RA) */
2458 12 : M_DLD(REG_FTMP1, REG_SP, s1);
2459 12 : M_DST(REG_FTMP1, REG_SP, s2);
2460 : }
2461 41 : break;
2462 : default:
2463 0 : assert(false);
2464 : break;
2465 : }
2466 : }
2467 :
2468 : /* Handle native Java methods. */
2469 :
2470 13057 : if (m->flags & ACC_NATIVE) {
2471 : /* put class into second argument register */
2472 :
2473 10775 : if (m->flags & ACC_STATIC)
2474 5157 : M_MOV(REG_ITMP2, REG_A1);
2475 :
2476 : /* put env into first argument register */
2477 :
2478 10775 : M_MOV_IMM(VM::get_current()->get_jnienv(), REG_A0);
2479 : }
2480 :
2481 : /* Call the native function. */
2482 :
2483 13057 : disp = dseg_add_functionptr(cd, f);
2484 13057 : M_ALD(REG_ITMP1, RIP, disp);
2485 13057 : M_CALL(REG_ITMP1);
2486 :
2487 : /* save return value */
2488 :
2489 13057 : switch (md->returntype.type) {
2490 : case TYPE_INT:
2491 : case TYPE_LNG:
2492 : case TYPE_ADR:
2493 11675 : switch (md->returntype.primitivetype) {
2494 : case PRIMITIVETYPE_BOOLEAN:
2495 494 : M_BZEXT(REG_RESULT, REG_RESULT);
2496 494 : break;
2497 : case PRIMITIVETYPE_BYTE:
2498 0 : M_BSEXT(REG_RESULT, REG_RESULT);
2499 0 : break;
2500 : case PRIMITIVETYPE_CHAR:
2501 0 : M_CZEXT(REG_RESULT, REG_RESULT);
2502 0 : break;
2503 : case PRIMITIVETYPE_SHORT:
2504 0 : M_SSEXT(REG_RESULT, REG_RESULT);
2505 : break;
2506 : default:
2507 : break;
2508 : }
2509 11675 : M_LST(REG_RESULT, REG_SP, 0 * 8);
2510 11675 : break;
2511 : case TYPE_FLT:
2512 : case TYPE_DBL:
2513 5 : M_DST(REG_FRESULT, REG_SP, 0 * 8);
2514 5 : break;
2515 : case TYPE_VOID:
2516 1377 : break;
2517 : default:
2518 0 : assert(false);
2519 : break;
2520 : }
2521 :
2522 : /* remove native stackframe info */
2523 :
2524 13057 : M_MOV(REG_SP, REG_A0);
2525 13057 : emit_lea_membase_reg(cd, RIP, -((cd->mcodeptr + 7) - cd->mcodebase), REG_A1);
2526 13057 : M_MOV_IMM(codegen_finish_native_call, REG_ITMP1);
2527 13057 : M_CALL(REG_ITMP1);
2528 13057 : M_MOV(REG_RESULT, REG_ITMP3);
2529 :
2530 : /* restore return value */
2531 :
2532 13057 : switch (md->returntype.type) {
2533 : case TYPE_INT:
2534 : case TYPE_LNG:
2535 : case TYPE_ADR:
2536 11675 : M_LLD(REG_RESULT, REG_SP, 0 * 8);
2537 11675 : break;
2538 : case TYPE_FLT:
2539 : case TYPE_DBL:
2540 5 : M_DLD(REG_FRESULT, REG_SP, 0 * 8);
2541 5 : break;
2542 : case TYPE_VOID:
2543 1377 : break;
2544 : default:
2545 0 : assert(false);
2546 : break;
2547 : }
2548 :
2549 : #if defined(ENABLE_GC_CACAO)
2550 : /* Restore callee saved integer registers from stackframeinfo (GC
2551 : might have modified them during a collection). */
2552 :
2553 : disp = cd->stackframesize * 8 - sizeof(stackframeinfo_t) +
2554 : OFFSET(stackframeinfo_t, intregs);
2555 :
2556 : for (i = 0; i < INT_SAV_CNT; i++)
2557 : M_ALD(abi_registers_integer_saved[i], REG_SP, disp + i * 8);
2558 : #endif
2559 :
2560 : /* remove stackframe */
2561 :
2562 13057 : M_AADD_IMM(cd->stackframesize * 8, REG_SP);
2563 :
2564 : /* test for exception */
2565 :
2566 13057 : M_TEST(REG_ITMP3);
2567 13057 : M_BNE(1);
2568 13057 : M_RET;
2569 :
2570 : /* handle exception */
2571 :
2572 13057 : M_MOV(REG_ITMP3, REG_ITMP1_XPTR);
2573 13057 : M_ALD_MEM(REG_METHODPTR, TRAP_NAT_EXCEPTION);
2574 13057 : }
2575 :
2576 :
2577 : /*
2578 : * These are local overrides for various environment variables in Emacs.
2579 : * Please do not remove this and leave it at the end of the file, where
2580 : * Emacs will automagically detect them.
2581 : * ---------------------------------------------------------------------
2582 : * Local variables:
2583 : * mode: c++
2584 : * indent-tabs-mode: t
2585 : * c-basic-offset: 4
2586 : * tab-width: 4
2587 : * End:
2588 : * vim:noexpandtab:sw=4:ts=4:
2589 : */
|