• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2012 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 
18 /*! \file LowerAlu.cpp
19     \brief This file lowers ALU bytecodes.
20 */
21 #include "libdex/DexOpcodes.h"
22 #include "libdex/DexFile.h"
23 #include "Lower.h"
24 #include "NcgAot.h"
25 #include "enc_wrapper.h"
26 
27 /////////////////////////////////////////////
28 #define P_GPR_1 PhysicalReg_EBX
29 //! lower bytecode NEG_INT
30 
31 //!
op_neg_int()32 int op_neg_int() {
33     u2 vA = INST_A(inst); //destination
34     u2 vB = INST_B(inst);
35     get_virtual_reg(vB, OpndSize_32, 1, false);
36     alu_unary_reg(OpndSize_32, neg_opc, 1, false);
37     set_virtual_reg(vA, OpndSize_32, 1, false);
38     rPC += 1;
39     return 0;
40 }
41 //! lower bytecode NOT_INT
42 
43 //!
op_not_int()44 int op_not_int() {
45     u2 vA = INST_A(inst); //destination
46     u2 vB = INST_B(inst);
47     get_virtual_reg(vB, OpndSize_32, 1, false);
48     alu_unary_reg(OpndSize_32, not_opc, 1, false);
49     set_virtual_reg(vA, OpndSize_32, 1, false);
50     rPC += 1;
51     return 0;
52 }
53 #undef P_GPR_1
54 //! lower bytecode NEG_LONG
55 
56 //! This implementation uses XMM registers
op_neg_long()57 int op_neg_long() {
58     u2 vA = INST_A(inst); //destination
59     u2 vB = INST_B(inst);
60     get_virtual_reg(vB, OpndSize_64, 1, false);
61     alu_binary_reg_reg(OpndSize_64, xor_opc, 2, false, 2, false);
62     alu_binary_reg_reg(OpndSize_64, sub_opc, 1, false, 2, false);
63     set_virtual_reg(vA, OpndSize_64, 2, false);
64     rPC += 1;
65     return 0;
66 }
67 //! lower bytecode NOT_LONG
68 
69 //! This implementation uses XMM registers
op_not_long()70 int op_not_long() {
71     u2 vA = INST_A(inst); //destination
72     u2 vB = INST_B(inst);
73     get_virtual_reg(vB, OpndSize_64, 1, false);
74     load_global_data_API("64bits", OpndSize_64, 2, false);
75     alu_binary_reg_reg(OpndSize_64, andn_opc, 2, false, 1, false);
76     set_virtual_reg(vA, OpndSize_64, 1, false);
77     rPC += 1;
78     return 0;
79 }
80 #define P_GPR_1 PhysicalReg_EBX
81 //! lower bytecode NEG_FLOAT
82 
83 //! This implementation uses GPR
op_neg_float()84 int op_neg_float() {
85     u2 vA = INST_A(inst); //destination
86     u2 vB = INST_B(inst);
87     get_virtual_reg(vB, OpndSize_32, 1, false);
88     alu_binary_imm_reg(OpndSize_32, add_opc, 0x80000000, 1, false);
89     set_virtual_reg(vA, OpndSize_32, 1, false);
90     rPC += 1;
91     return 0;
92 }
93 #undef P_GPR_1
94 
95 //! lower bytecode NEG_DOUBLE
96 
97 //! This implementation uses XMM registers
op_neg_double()98 int op_neg_double() {
99     u2 vA = INST_A(inst); //destination
100     u2 vB = INST_B(inst);
101     get_virtual_reg(vB, OpndSize_64, 1, false);
102     load_global_data_API("doubNeg", OpndSize_64, 2, false);
103     alu_binary_reg_reg(OpndSize_64, xor_opc, 1, false, 2, false);
104     set_virtual_reg(vA, OpndSize_64, 2, false);
105     rPC += 1;
106     return 0;
107 }
108 
109 //! lower bytecode INT_TO_LONG
110 
111 //! It uses native instruction cdq
op_int_to_long()112 int op_int_to_long() {
113     u2 vA = INST_A(inst); //destination
114     u2 vB = INST_B(inst);
115     get_virtual_reg(vB, OpndSize_32, PhysicalReg_EAX, true);
116     convert_integer(OpndSize_32, OpndSize_64);
117     set_virtual_reg(vA, OpndSize_32, PhysicalReg_EAX, true);
118     set_virtual_reg(vA+1, OpndSize_32, PhysicalReg_EDX, true);
119     rPC += 1;
120     return 0;
121 }
122 //! lower bytecode INT_TO_FLOAT
123 
124 //! This implementation uses FP stack
op_int_to_float()125 int op_int_to_float() {
126     u2 vA = INST_A(inst); //destination
127     u2 vB = INST_B(inst);
128     load_int_fp_stack_VR(OpndSize_32, vB); //fildl
129     store_fp_stack_VR(true, OpndSize_32, vA); //fstps
130     rPC += 1;
131     return 0;
132 }
133 //! lower bytecode INT_TO_DOUBLE
134 
135 //! This implementation uses FP stack
op_int_to_double()136 int op_int_to_double() {
137     u2 vA = INST_A(inst); //destination
138     u2 vB = INST_B(inst);
139     load_int_fp_stack_VR(OpndSize_32, vB); //fildl
140     store_fp_stack_VR(true, OpndSize_64, vA); //fstpl
141     rPC += 1;
142     return 0;
143 }
144 //! lower bytecode LONG_TO_FLOAT
145 
146 //! This implementation uses FP stack
op_long_to_float()147 int op_long_to_float() {
148     u2 vA = INST_A(inst); //destination
149     u2 vB = INST_B(inst);
150     load_int_fp_stack_VR(OpndSize_64, vB); //fildll
151     store_fp_stack_VR(true, OpndSize_32, vA); //fstps
152     rPC += 1;
153     return 0;
154 }
155 //! lower bytecode LONG_TO_DOUBLE
156 
157 //! This implementation uses FP stack
op_long_to_double()158 int op_long_to_double() {
159     u2 vA = INST_A(inst); //destination
160     u2 vB = INST_B(inst);
161     load_int_fp_stack_VR(OpndSize_64, vB); //fildll
162     store_fp_stack_VR(true, OpndSize_64, vA); //fstpl
163     rPC += 1;
164     return 0;
165 }
166 //! lower bytecode FLOAT_TO_DOUBLE
167 
168 //! This implementation uses FP stack
op_float_to_double()169 int op_float_to_double() {
170     u2 vA = INST_A(inst); //destination
171     u2 vB = INST_B(inst);
172     load_fp_stack_VR(OpndSize_32, vB); //flds
173     store_fp_stack_VR(true, OpndSize_64, vA); //fstpl
174     rPC += 1;
175     return 0;
176 }
177 //! lower bytecode DOUBLE_TO_FLOAT
178 
179 //! This implementation uses FP stack
op_double_to_float()180 int op_double_to_float() {
181     u2 vA = INST_A(inst); //destination
182     u2 vB = INST_B(inst);
183     load_fp_stack_VR(OpndSize_64, vB); //fldl
184     store_fp_stack_VR(true, OpndSize_32, vA); //fstps
185     rPC += 1;
186     return 0;
187 }
188 #define P_GPR_1 PhysicalReg_EBX
189 //! lower bytecode LONG_TO_INT
190 
191 //! This implementation uses GPR
op_long_to_int()192 int op_long_to_int() {
193     u2 vA = INST_A(inst); //destination
194     u2 vB = INST_B(inst);
195     get_virtual_reg(vB, OpndSize_32, 1, false);
196     set_virtual_reg(vA, OpndSize_32, 1, false);
197     rPC += 1;
198     return 0;
199 }
200 #undef P_GPR_1
201 
202 //! common code to convert a float or double to integer
203 
204 //! It uses FP stack
common_fp_to_int(bool isDouble,u2 vA,u2 vB)205 int common_fp_to_int(bool isDouble, u2 vA, u2 vB) {
206     if(isDouble) {
207         load_fp_stack_VR(OpndSize_64, vB); //fldl
208     }
209     else {
210         load_fp_stack_VR(OpndSize_32, vB); //flds
211     }
212 
213     load_fp_stack_global_data_API("intMax", OpndSize_32);
214     load_fp_stack_global_data_API("intMin", OpndSize_32);
215 
216     //ST(0) ST(1) ST(2) --> LintMin LintMax value
217     compare_fp_stack(true, 2, false/*isDouble*/); //ST(2)
218     //ST(0) ST(1) --> LintMax value
219     conditional_jump(Condition_AE, ".float_to_int_negInf", true);
220     rememberState(1);
221     compare_fp_stack(true, 1, false/*isDouble*/); //ST(1)
222     //ST(0) --> value
223     rememberState(2);
224     conditional_jump(Condition_C, ".float_to_int_nanInf", true);
225     //fnstcw, orw, fldcw, xorw
226     load_effective_addr(-2, PhysicalReg_ESP, true, PhysicalReg_ESP, true);
227     store_fpu_cw(false/*checkException*/, 0, PhysicalReg_ESP, true);
228     alu_binary_imm_mem(OpndSize_16, or_opc, 0xc00, 0, PhysicalReg_ESP, true);
229     load_fpu_cw(0, PhysicalReg_ESP, true);
230     alu_binary_imm_mem(OpndSize_16, xor_opc, 0xc00, 0, PhysicalReg_ESP, true);
231     store_int_fp_stack_VR(true/*pop*/, OpndSize_32, vA); //fistpl
232     //fldcw
233     load_fpu_cw(0, PhysicalReg_ESP, true);
234     load_effective_addr(2, PhysicalReg_ESP, true, PhysicalReg_ESP, true);
235     rememberState(3);
236     unconditional_jump(".float_to_int_okay", true);
237     insertLabel(".float_to_int_nanInf", true);
238     conditional_jump(Condition_NP, ".float_to_int_posInf", true);
239     //fstps CHECK
240     goToState(2);
241     store_fp_stack_VR(true, OpndSize_32, vA);
242     set_VR_to_imm(vA, OpndSize_32, 0);
243     transferToState(3);
244     unconditional_jump(".float_to_int_okay", true);
245     insertLabel(".float_to_int_posInf", true);
246     //fstps CHECK
247     goToState(2);
248     store_fp_stack_VR(true, OpndSize_32, vA);
249     set_VR_to_imm(vA, OpndSize_32, 0x7fffffff);
250     transferToState(3);
251     unconditional_jump(".float_to_int_okay", true);
252     insertLabel(".float_to_int_negInf", true);
253     goToState(1);
254     //fstps CHECK
255     store_fp_stack_VR(true, OpndSize_32, vA);
256     store_fp_stack_VR(true, OpndSize_32, vA);
257     set_VR_to_imm(vA, OpndSize_32, 0x80000000);
258     transferToState(3);
259     insertLabel(".float_to_int_okay", true);
260     return 0;
261 }
262 //! lower bytecode FLOAT_TO_INT by calling common_fp_to_int
263 
264 //!
op_float_to_int()265 int op_float_to_int() {
266     u2 vA = INST_A(inst); //destination
267     u2 vB = INST_B(inst);
268     int retval = common_fp_to_int(false, vA, vB);
269     rPC += 1;
270     return retval;
271 }
272 //! lower bytecode DOUBLE_TO_INT by calling common_fp_to_int
273 
274 //!
op_double_to_int()275 int op_double_to_int() {
276     u2 vA = INST_A(inst); //destination
277     u2 vB = INST_B(inst);
278     int retval = common_fp_to_int(true, vA, vB);
279     rPC += 1;
280     return retval;
281 }
282 
283 //! common code to convert float or double to long
284 
285 //! It uses FP stack
common_fp_to_long(bool isDouble,u2 vA,u2 vB)286 int common_fp_to_long(bool isDouble, u2 vA, u2 vB) {
287     if(isDouble) {
288         load_fp_stack_VR(OpndSize_64, vB); //fldl
289     }
290     else {
291         load_fp_stack_VR(OpndSize_32, vB); //flds
292     }
293 
294     load_fp_stack_global_data_API("valuePosInfLong", OpndSize_64);
295     load_fp_stack_global_data_API("valueNegInfLong", OpndSize_64);
296 
297     //ST(0) ST(1) ST(2) --> LintMin LintMax value
298     compare_fp_stack(true, 2, false/*isDouble*/); //ST(2)
299     //ST(0) ST(1) --> LintMax value
300     conditional_jump(Condition_AE, ".float_to_long_negInf", true);
301     rememberState(1);
302     compare_fp_stack(true, 1, false/*isDouble*/); //ST(1)
303     rememberState(2);
304     //ST(0) --> value
305     conditional_jump(Condition_C, ".float_to_long_nanInf", true);
306     //fnstcw, orw, fldcw, xorw
307     load_effective_addr(-2, PhysicalReg_ESP, true, PhysicalReg_ESP, true);
308     store_fpu_cw(false/*checkException*/, 0, PhysicalReg_ESP, true);
309     alu_binary_imm_mem(OpndSize_16, or_opc, 0xc00, 0, PhysicalReg_ESP, true);
310     load_fpu_cw(0, PhysicalReg_ESP, true);
311     alu_binary_imm_mem(OpndSize_16, xor_opc, 0xc00, 0, PhysicalReg_ESP, true);
312     store_int_fp_stack_VR(true/*pop*/, OpndSize_64, vA); //fistpll
313     //fldcw
314     load_fpu_cw(0, PhysicalReg_ESP, true);
315     load_effective_addr(2, PhysicalReg_ESP, true, PhysicalReg_ESP, true);
316     rememberState(3);
317     unconditional_jump(".float_to_long_okay", true);
318     insertLabel(".float_to_long_nanInf", true);
319     conditional_jump(Condition_NP, ".float_to_long_posInf", true);
320     //fstpl??
321     goToState(2);
322 
323     load_global_data_API("valueNanLong", OpndSize_64, 1, false);
324 
325     set_virtual_reg(vA, OpndSize_64, 1, false);
326     transferToState(3);
327     unconditional_jump(".float_to_long_okay", true);
328     insertLabel(".float_to_long_posInf", true);
329     //fstpl
330     goToState(2);
331 
332     load_global_data_API("valuePosInfLong", OpndSize_64, 2, false);
333     set_virtual_reg(vA, OpndSize_64, 2, false);
334     transferToState(3);
335     unconditional_jump(".float_to_long_okay", true);
336     insertLabel(".float_to_long_negInf", true);
337     //fstpl
338     //fstpl
339     goToState(1);
340 
341     load_global_data_API("valueNegInfLong", OpndSize_64, 3, false);
342     set_virtual_reg(vA, OpndSize_64, 3, false);
343     transferToState(3);
344     insertLabel(".float_to_long_okay", true);
345     return 0;
346 }
347 //! lower bytecode FLOAT_TO_LONG by calling common_fp_to_long
348 
349 //!
op_float_to_long()350 int op_float_to_long() {
351     u2 vA = INST_A(inst); //destination
352     u2 vB = INST_B(inst);
353     int retval = common_fp_to_long(false, vA, vB);
354     rPC += 1;
355     return retval;
356 }
357 //! lower bytecode DOUBLE_TO_LONG by calling common_fp_to_long
358 
359 //!
op_double_to_long()360 int op_double_to_long() {
361     u2 vA = INST_A(inst); //destination
362     u2 vB = INST_B(inst);
363     int retval = common_fp_to_long(true, vA, vB);
364     rPC += 1;
365     return retval;
366 }
367 #define P_GPR_1 PhysicalReg_EBX
368 //! lower bytecode INT_TO_BYTE
369 
370 //! It uses GPR
op_int_to_byte()371 int op_int_to_byte() {
372     u2 vA = INST_A(inst); //destination
373     u2 vB = INST_B(inst);
374     get_virtual_reg(vB, OpndSize_32, 1, false);
375     alu_binary_imm_reg(OpndSize_32, sal_opc, 24, 1, false);
376     alu_binary_imm_reg(OpndSize_32, sar_opc, 24, 1, false);
377     set_virtual_reg(vA, OpndSize_32, 1, false);
378     rPC += 1;
379     return 0;
380 }
381 //! lower bytecode INT_TO_CHAR
382 
383 //! It uses GPR
op_int_to_char()384 int op_int_to_char() {
385     u2 vA = INST_A(inst); //destination
386     u2 vB = INST_B(inst);
387     get_virtual_reg(vB, OpndSize_32, 1, false);
388     alu_binary_imm_reg(OpndSize_32, sal_opc, 16, 1, false);
389     alu_binary_imm_reg(OpndSize_32, shr_opc, 16, 1, false);
390     set_virtual_reg(vA, OpndSize_32, 1, false);
391     rPC += 1;
392     return 0;
393 }
394 //! lower bytecode INT_TO_SHORT
395 
396 //! It uses GPR
op_int_to_short()397 int op_int_to_short() {
398     u2 vA = INST_A(inst); //destination
399     u2 vB = INST_B(inst);
400     get_virtual_reg(vB, OpndSize_32, 1, false);
401     alu_binary_imm_reg(OpndSize_32, sal_opc, 16, 1, false);
402     alu_binary_imm_reg(OpndSize_32, sar_opc, 16, 1, false);
403     set_virtual_reg(vA, OpndSize_32, 1, false);
404     rPC += 1;
405     return 0;
406 }
407 //! common code to handle integer ALU ops
408 
409 //! It uses GPR
common_alu_int(ALU_Opcode opc,u2 vA,u2 v1,u2 v2)410 int common_alu_int(ALU_Opcode opc, u2 vA, u2 v1, u2 v2) { //except div and rem
411     get_virtual_reg(v1, OpndSize_32, 1, false);
412     //in encoder, reg is first operand, which is the destination
413     //gpr_1 op v2(rFP) --> gpr_1
414     //shift only works with reg cl, v2 should be in %ecx
415     alu_binary_VR_reg(OpndSize_32, opc, v2, 1, false);
416     set_virtual_reg(vA, OpndSize_32, 1, false);
417     return 0;
418 }
419 #undef P_GPR_1
420 #define P_GPR_1 PhysicalReg_EBX
421 //! common code to handle integer shift ops
422 
423 //! It uses GPR
common_shift_int(ALU_Opcode opc,u2 vA,u2 v1,u2 v2)424 int common_shift_int(ALU_Opcode opc, u2 vA, u2 v1, u2 v2) {
425     get_virtual_reg(v2, OpndSize_32, PhysicalReg_ECX, true);
426     get_virtual_reg(v1, OpndSize_32, 1, false);
427     //in encoder, reg2 is first operand, which is the destination
428     //gpr_1 op v2(rFP) --> gpr_1
429     //shift only works with reg cl, v2 should be in %ecx
430     alu_binary_reg_reg(OpndSize_32, opc, PhysicalReg_ECX, true, 1, false);
431     set_virtual_reg(vA, OpndSize_32, 1, false);
432     return 0;
433 }
434 #undef p_GPR_1
435 //! lower bytecode ADD_INT by calling common_alu_int
436 
437 //!
op_add_int()438 int op_add_int() {
439     u2 vA, v1, v2;
440     vA = INST_AA(inst);
441     v1 = *((u1*)rPC + 2);
442     v2 = *((u1*)rPC + 3);
443     int retval = common_alu_int(add_opc, vA, v1, v2);
444     rPC += 2;
445     return retval;
446 }
447 //! lower bytecode SUB_INT by calling common_alu_int
448 
449 //!
op_sub_int()450 int op_sub_int() {
451     u2 vA, v1, v2;
452     vA = INST_AA(inst);
453     v1 = *((u1*)rPC + 2);
454     v2 = *((u1*)rPC + 3);
455     int retval = common_alu_int(sub_opc, vA, v1, v2);
456     rPC += 2;
457     return retval;
458 }
459 //! lower bytecode MUL_INT by calling common_alu_int
460 
461 //!
op_mul_int()462 int op_mul_int() {
463     u2 vA, v1, v2;
464     vA = INST_AA(inst);
465     v1 = *((u1*)rPC + 2);
466     v2 = *((u1*)rPC + 3);
467     int retval = common_alu_int(imul_opc, vA, v1, v2);
468     rPC += 2;
469     return retval;
470 }
471 //! lower bytecode AND_INT by calling common_alu_int
472 
473 //!
op_and_int()474 int op_and_int() {
475     u2 vA, v1, v2;
476     vA = INST_AA(inst);
477     v1 = *((u1*)rPC + 2);
478     v2 = *((u1*)rPC + 3);
479     int retval = common_alu_int(and_opc, vA, v1, v2);
480     rPC += 2;
481     return retval;
482 }
483 //! lower bytecode OR_INT by calling common_alu_int
484 
485 //!
op_or_int()486 int op_or_int() {
487     u2 vA, v1, v2;
488     vA = INST_AA(inst);
489     v1 = *((u1*)rPC + 2);
490     v2 = *((u1*)rPC + 3);
491     int retval = common_alu_int(or_opc, vA, v1, v2);
492     rPC += 2;
493     return retval;
494 }
495 //! lower bytecode XOR_INT by calling common_alu_int
496 
497 //!
op_xor_int()498 int op_xor_int() {
499     u2 vA, v1, v2;
500     vA = INST_AA(inst);
501     v1 = *((u1*)rPC + 2);
502     v2 = *((u1*)rPC + 3);
503     int retval = common_alu_int(xor_opc, vA, v1, v2);
504     rPC += 2;
505     return retval;
506 }
507 //! lower bytecode SHL_INT by calling common_shift_int
508 
509 //!
op_shl_int()510 int op_shl_int() {
511     u2 vA, v1, v2;
512     vA = INST_AA(inst);
513     v1 = *((u1*)rPC + 2);
514     v2 = *((u1*)rPC + 3);
515     int retval = common_shift_int(shl_opc, vA, v1, v2);
516     rPC += 2;
517     return retval;
518 }
519 //! lower bytecode SHR_INT by calling common_shift_int
520 
521 //!
op_shr_int()522 int op_shr_int() {
523     u2 vA, v1, v2;
524     vA = INST_AA(inst);
525     v1 = *((u1*)rPC + 2);
526     v2 = *((u1*)rPC + 3);
527     int retval = common_shift_int(sar_opc, vA, v1, v2);
528     rPC += 2;
529     return retval;
530 }
531 //! lower bytecode USHR_INT by calling common_shift_int
532 
533 //!
op_ushr_int()534 int op_ushr_int() {
535     u2 vA, v1, v2;
536     vA = INST_AA(inst);
537     v1 = *((u1*)rPC + 2);
538     v2 = *((u1*)rPC + 3);
539     int retval = common_shift_int(shr_opc, vA, v1, v2);
540     rPC += 2;
541     return retval;
542 }
543 //! lower bytecode ADD_INT_2ADDR by calling common_alu_int
544 
545 //!
op_add_int_2addr()546 int op_add_int_2addr() {
547     u2 vA, v1, v2;
548     vA = INST_A(inst);
549     v1 = vA;
550     v2 = INST_B(inst);
551     int retval = common_alu_int(add_opc, vA, v1, v2);
552     rPC += 1;
553     return retval;
554 }
555 //! lower bytecode SUB_INT_2ADDR by calling common_alu_int
556 
557 //!
op_sub_int_2addr()558 int op_sub_int_2addr() {
559     u2 vA, v1, v2;
560     vA = INST_A(inst);
561     v1 = vA;
562     v2 = INST_B(inst);
563     int retval = common_alu_int(sub_opc, vA, v1, v2);
564     rPC += 1;
565     return retval;
566 }
567 //! lower bytecode MUL_INT_2ADDR by calling common_alu_int
568 
569 //!
op_mul_int_2addr()570 int op_mul_int_2addr() {
571     u2 vA, v1, v2;
572     vA = INST_A(inst);
573     v1 = vA;
574     v2 = INST_B(inst);
575     int retval = common_alu_int(imul_opc, vA, v1, v2);
576     rPC += 1;
577     return retval;
578 }
579 //! lower bytecode AND_INT_2ADDR by calling common_alu_int
580 
581 //!
op_and_int_2addr()582 int op_and_int_2addr() {
583     u2 vA, v1, v2;
584     vA = INST_A(inst);
585     v1 = vA;
586     v2 = INST_B(inst);
587     int retval = common_alu_int(and_opc, vA, v1, v2);
588     rPC += 1;
589     return retval;
590 }
591 //! lower bytecode OR_INT_2ADDR by calling common_alu_int
592 
593 //!
op_or_int_2addr()594 int op_or_int_2addr() {
595     u2 vA, v1, v2;
596     vA = INST_A(inst);
597     v1 = vA;
598     v2 = INST_B(inst);
599     int retval = common_alu_int(or_opc, vA, v1, v2);
600     rPC += 1;
601     return retval;
602 }
603 //! lower bytecode XOR_INT_2ADDR by calling common_alu_int
604 
605 //!
op_xor_int_2addr()606 int op_xor_int_2addr() {
607     u2 vA, v1, v2;
608     vA = INST_A(inst);
609     v1 = vA;
610     v2 = INST_B(inst);
611     int retval = common_alu_int(xor_opc, vA, v1, v2);
612     rPC += 1;
613     return retval;
614 }
615 //! lower bytecode SHL_INT_2ADDR by calling common_shift_int
616 
617 //!
op_shl_int_2addr()618 int op_shl_int_2addr() {
619     u2 vA, v1, v2;
620     vA = INST_A(inst);
621     v1 = vA;
622     v2 = INST_B(inst);
623     int retval = common_shift_int(shl_opc, vA, v1, v2);
624     rPC += 1;
625     return retval;
626 }
627 //! lower bytecode SHR_INT_2ADDR by calling common_shift_int
628 
629 //!
op_shr_int_2addr()630 int op_shr_int_2addr() {
631     u2 vA, v1, v2;
632     vA = INST_A(inst);
633     v1 = vA;
634     v2 = INST_B(inst);
635     int retval = common_shift_int(sar_opc, vA, v1, v2);
636     rPC += 1;
637     return retval;
638 }
639 //! lower bytecode USHR_INT_2ADDR by calling common_shift_int
640 
641 //!
op_ushr_int_2addr()642 int op_ushr_int_2addr() {
643     u2 vA, v1, v2;
644     vA = INST_A(inst);
645     v1 = vA;
646     v2 = INST_B(inst);
647     int retval = common_shift_int(shr_opc, vA, v1, v2);
648     rPC += 1;
649     return retval;
650 }
651 #define P_GPR_1 PhysicalReg_EBX
652 //!common code to handle integer DIV & REM, it used GPR
653 
654 //!The special case: when op0 == minint && op1 == -1, return 0 for isRem, return 0x80000000 for isDiv
655 //!There are two merge points in the control flow for this bytecode
656 //!make sure the reg. alloc. state is the same at merge points by calling transferToState
common_div_rem_int(bool isRem,u2 vA,u2 v1,u2 v2)657 int common_div_rem_int(bool isRem, u2 vA, u2 v1, u2 v2) {
658     get_virtual_reg(v1, OpndSize_32, PhysicalReg_EAX, true);
659     get_virtual_reg(v2, OpndSize_32, 2, false);
660     compare_imm_reg(OpndSize_32, 0, 2, false);
661     handlePotentialException(
662                                        Condition_E, Condition_NE,
663                                        1, "common_errDivideByZero");
664     /////////////////// handle special cases
665     //conditional move 0 to $edx for rem for the two special cases
666     //conditional move 0x80000000 to $eax for div
667     //handle -1 special case divide error
668     compare_imm_reg(OpndSize_32, -1, 2, false);
669     conditional_jump(Condition_NE, ".common_div_rem_int_normal", true);
670     //handle min int special case divide error
671     rememberState(1);
672     compare_imm_reg(OpndSize_32, 0x80000000, PhysicalReg_EAX, true);
673     transferToState(1);
674     conditional_jump(Condition_E, ".common_div_rem_int_special", true);
675 
676     insertLabel(".common_div_rem_int_normal", true); //merge point
677     convert_integer(OpndSize_32, OpndSize_64); //cdq
678     //idiv: dividend in edx:eax; quotient in eax; remainder in edx
679     alu_unary_reg(OpndSize_32, idiv_opc, 2, false);
680     if(isRem)
681         set_virtual_reg(vA, OpndSize_32, PhysicalReg_EDX, true);
682     else //divide: quotient in %eax
683         set_virtual_reg(vA, OpndSize_32, PhysicalReg_EAX, true);
684     rememberState(2);
685     unconditional_jump(".common_div_rem_int_okay", true);
686 
687     insertLabel(".common_div_rem_int_special", true);
688     goToState(1);
689     if(isRem)
690         set_VR_to_imm(vA, OpndSize_32, 0);
691     else
692         set_VR_to_imm(vA, OpndSize_32, 0x80000000);
693     transferToState(2);
694     insertLabel(".common_div_rem_int_okay", true); //merge point 2
695     return 0;
696 }
697 #undef P_GPR_1
698 //! lower bytecode DIV_INT by calling common_div_rem_int
699 
700 //!
op_div_int()701 int op_div_int() {
702     u2 vA, v1, v2;
703     vA = INST_AA(inst);
704     v1 = *((u1*)rPC + 2);
705     v2 = *((u1*)rPC + 3);
706     int retval = common_div_rem_int(false, vA, v1, v2);
707     rPC += 2;
708     return retval;
709 }
710 //! lower bytecode REM_INT by calling common_div_rem_int
711 
712 //!
op_rem_int()713 int op_rem_int() {
714     u2 vA, v1, v2;
715     vA = INST_AA(inst);
716     v1 = *((u1*)rPC + 2);
717     v2 = *((u1*)rPC + 3);
718     int retval = common_div_rem_int(true, vA, v1, v2);
719     rPC += 2;
720     return retval;
721 }
722 //! lower bytecode DIV_INT_2ADDR by calling common_div_rem_int
723 
724 //!
op_div_int_2addr()725 int op_div_int_2addr() {
726     u2 vA = INST_A(inst);
727     u2 v1 = vA;
728     u2 v2 = INST_B(inst);
729     int retval = common_div_rem_int(false, vA, v1, v2);
730     rPC += 1;
731     return retval;
732 }
733 //! lower bytecode REM_INT_2ADDR by calling common_div_rem_int
734 
735 //!
op_rem_int_2addr()736 int op_rem_int_2addr() {
737     u2 vA = INST_A(inst);
738     u2 v1 = vA;
739     u2 v2 = INST_B(inst);
740     int retval = common_div_rem_int(true, vA, v1, v2);
741     rPC += 1;
742     return retval;
743 }
744 
745 #define P_GPR_1 PhysicalReg_EBX
746 //! common code to handle integer ALU ops with literal
747 
748 //! It uses GPR
common_alu_int_lit(ALU_Opcode opc,u2 vA,u2 vB,s2 imm)749 int common_alu_int_lit(ALU_Opcode opc, u2 vA, u2 vB, s2 imm) { //except div and rem
750     get_virtual_reg(vB, OpndSize_32, 1, false);
751     alu_binary_imm_reg(OpndSize_32, opc, imm, 1, false);
752     set_virtual_reg(vA, OpndSize_32, 1, false);
753     return 0;
754 }
755 //! calls common_alu_int_lit
common_shift_int_lit(ALU_Opcode opc,u2 vA,u2 vB,s2 imm)756 int common_shift_int_lit(ALU_Opcode opc, u2 vA, u2 vB, s2 imm) {
757     return common_alu_int_lit(opc, vA, vB, imm);
758 }
759 #undef p_GPR_1
760 //! lower bytecode ADD_INT_LIT16 by calling common_alu_int_lit
761 
762 //!
op_add_int_lit16()763 int op_add_int_lit16() {
764     u2 vA = INST_A(inst);
765     u2 vB = INST_B(inst);
766     s4 tmp = (s2)FETCH(1);
767     int retval = common_alu_int_lit(add_opc, vA, vB, tmp);
768     rPC += 2;
769     return retval;
770 }
771 
alu_rsub_int(ALU_Opcode opc,u2 vA,s2 imm,u2 vB)772 int alu_rsub_int(ALU_Opcode opc, u2 vA, s2 imm, u2 vB) {
773     move_imm_to_reg(OpndSize_32, imm, 2, false);
774     get_virtual_reg(vB, OpndSize_32, 1, false);
775     alu_binary_reg_reg(OpndSize_32, opc, 1, false, 2, false);
776     set_virtual_reg(vA, OpndSize_32, 2, false);
777     return 0;
778 }
779 
780 
781 //! lower bytecode RSUB_INT by calling common_alu_int_lit
782 
783 //!
op_rsub_int()784 int op_rsub_int() {
785     u2 vA = INST_A(inst);
786     u2 vB = INST_B(inst);
787     s4 tmp = (s2)FETCH(1);
788     int retval = alu_rsub_int(sub_opc, vA, tmp, vB);
789     rPC += 2;
790     return retval;
791 }
792 //! lower bytecode MUL_INT_LIT16 by calling common_alu_int_lit
793 
794 //!
op_mul_int_lit16()795 int op_mul_int_lit16() {
796     u2 vA = INST_A(inst);
797     u2 vB = INST_B(inst);
798     s4 tmp = (s2)FETCH(1);
799     int retval = common_alu_int_lit(imul_opc, vA, vB, tmp);
800     rPC += 2;
801     return retval;
802 }
803 //! lower bytecode AND_INT_LIT16 by calling common_alu_int_lit
804 
805 //!
op_and_int_lit16()806 int op_and_int_lit16() {
807     u2 vA = INST_A(inst);
808     u2 vB = INST_B(inst);
809     s4 tmp = (s2)FETCH(1);
810     int retval = common_alu_int_lit(and_opc, vA, vB, tmp);
811     rPC += 2;
812     return retval;
813 }
814 //! lower bytecode OR_INT_LIT16 by calling common_alu_int_lit
815 
816 //!
op_or_int_lit16()817 int op_or_int_lit16() {
818     u2 vA = INST_A(inst);
819     u2 vB = INST_B(inst);
820     s4 tmp = (s2)FETCH(1);
821     int retval = common_alu_int_lit(or_opc, vA, vB, tmp);
822     rPC += 2;
823     return retval;
824 }
825 //! lower bytecode XOR_INT_LIT16 by calling common_alu_int_lit
826 
827 //!
op_xor_int_lit16()828 int op_xor_int_lit16() {
829     u2 vA = INST_A(inst);
830     u2 vB = INST_B(inst);
831     s4 tmp = (s2)FETCH(1);
832     int retval = common_alu_int_lit(xor_opc, vA, vB, tmp);
833     rPC += 2;
834     return retval;
835 }
836 //! lower bytecode SHL_INT_LIT16 by calling common_shift_int_lit
837 
838 //!
op_shl_int_lit16()839 int op_shl_int_lit16() {
840     u2 vA = INST_A(inst);
841     u2 vB = INST_B(inst);
842     s4 tmp = (s2)FETCH(1);
843     int retval = common_shift_int_lit(shl_opc, vA, vB, tmp);
844     rPC += 2;
845     return retval;
846 }
847 //! lower bytecode SHR_INT_LIT16 by calling common_shift_int_lit
848 
849 //!
op_shr_int_lit16()850 int op_shr_int_lit16() {
851     u2 vA = INST_A(inst);
852     u2 vB = INST_B(inst);
853     s4 tmp = (s2)FETCH(1);
854     int retval = common_shift_int_lit(sar_opc, vA, vB, tmp);
855     rPC += 2;
856     return retval;
857 }
858 //! lower bytecode USHR_INT_LIT16 by calling common_shift_int_lit
859 
860 //!
op_ushr_int_lit16()861 int op_ushr_int_lit16() {
862     u2 vA = INST_A(inst);
863     u2 vB = INST_B(inst);
864     s4 tmp = (s2)FETCH(1);
865     int retval = common_shift_int_lit(shr_opc, vA, vB, tmp);
866     rPC += 2;
867     return retval;
868 }
869 //! lower bytecode ADD_INT_LIT8 by calling common_alu_int_lit
870 
871 //!
op_add_int_lit8()872 int op_add_int_lit8() {
873     u2 vA = INST_AA(inst);
874     u2 vB = (u2)FETCH(1) & 0xff;
875     s2 tmp = (s2)FETCH(1) >> 8;
876     int retval = common_alu_int_lit(add_opc, vA, vB, tmp);
877     rPC += 2;
878     return retval;
879 }
880 //! lower bytecode RSUB_INT_LIT8 by calling common_alu_int_lit
881 
882 //!
op_rsub_int_lit8()883 int op_rsub_int_lit8() {
884     u2 vA = INST_AA(inst);
885     u2 vB = (u2)FETCH(1) & 0xff;
886     s2 tmp = (s2)FETCH(1) >> 8;
887     int retval = alu_rsub_int(sub_opc, vA, tmp, vB);
888     rPC += 2;
889     return retval;
890 }
891 //! lower bytecode MUL_INT_LIT8 by calling common_alu_int_lit
892 
893 //!
op_mul_int_lit8()894 int op_mul_int_lit8() {
895     u2 vA = INST_AA(inst);
896     u2 vB = (u2)FETCH(1) & 0xff;
897     s2 tmp = (s2)FETCH(1) >> 8;
898     int retval = common_alu_int_lit(imul_opc, vA, vB, tmp);
899     rPC += 2;
900     return retval;
901 }
902 //! lower bytecode AND_INT_LIT8 by calling common_alu_int_lit
903 
904 //!
op_and_int_lit8()905 int op_and_int_lit8() {
906     u2 vA = INST_AA(inst);
907     u2 vB = (u2)FETCH(1) & 0xff;
908     s2 tmp = (s2)FETCH(1) >> 8;
909     int retval = common_alu_int_lit(and_opc, vA, vB, tmp);
910     rPC += 2;
911     return retval;
912 }
913 //! lower bytecode OR_INT_LIT8 by calling common_alu_int_lit
914 
915 //!
op_or_int_lit8()916 int op_or_int_lit8() {
917     u2 vA = INST_AA(inst);
918     u2 vB = (u2)FETCH(1) & 0xff;
919     s2 tmp = (s2)FETCH(1) >> 8;
920     int retval = common_alu_int_lit(or_opc, vA, vB, tmp);
921     rPC += 2;
922     return retval;
923 }
924 //! lower bytecode XOR_INT_LIT8 by calling common_alu_int_lit
925 
926 //!
op_xor_int_lit8()927 int op_xor_int_lit8() {
928     u2 vA = INST_AA(inst);
929     u2 vB = (u2)FETCH(1) & 0xff;
930     s2 tmp = (s2)FETCH(1) >> 8;
931     int retval = common_alu_int_lit(xor_opc, vA, vB, tmp);
932     rPC += 2;
933     return retval;
934 }
935 //! lower bytecode SHL_INT_LIT8 by calling common_shift_int_lit
936 
937 //!
op_shl_int_lit8()938 int op_shl_int_lit8() {
939     u2 vA = INST_AA(inst);
940     u2 vB = (u2)FETCH(1) & 0xff;
941     s2 tmp = (s2)FETCH(1) >> 8;
942     int retval = common_shift_int_lit(shl_opc, vA, vB, tmp);
943     rPC += 2;
944     return retval;
945 }
946 //! lower bytecode SHR_INT_LIT8 by calling common_shift_int_lit
947 
948 //!
op_shr_int_lit8()949 int op_shr_int_lit8() {
950     u2 vA = INST_AA(inst);
951     u2 vB = (u2)FETCH(1) & 0xff;
952     s2 tmp = (s2)FETCH(1) >> 8;
953     int retval = common_shift_int_lit(sar_opc, vA, vB, tmp);
954     rPC += 2;
955     return retval;
956 }
957 //! lower bytecode USHR_INT_LIT8 by calling common_shift_int_lit
958 
959 //!
op_ushr_int_lit8()960 int op_ushr_int_lit8() {
961     u2 vA = INST_AA(inst);
962     u2 vB = (u2)FETCH(1) & 0xff;
963     s2 tmp = (s2)FETCH(1) >> 8;
964     int retval = common_shift_int_lit(shr_opc, vA, vB, tmp);
965     rPC += 2;
966     return retval;
967 }
968 
isPowerOfTwo(int imm)969 int isPowerOfTwo(int imm) {
970     int i;
971     for(i = 1; i < 17; i++) {
972         if(imm == (1 << i)) return i;
973     }
974     return -1;
975 }
976 
977 #define P_GPR_1 PhysicalReg_EBX
div_lit_strength_reduction(u2 vA,u2 vB,s2 imm)978 int div_lit_strength_reduction(u2 vA, u2 vB, s2 imm) {
979     if(gDvm.executionMode == kExecutionModeNcgO1) {
980         //strength reduction for div by 2,4,8,...
981         int power = isPowerOfTwo(imm);
982         if(power < 1) return 0;
983         //tmp2 is not updated, so it can share with vB
984         get_virtual_reg(vB, OpndSize_32, 2, false);
985         //if imm is 2, power will be 1
986         if(power == 1) {
987             /* mov tmp1, tmp2
988                shrl $31, tmp1
989                addl tmp2, tmp1
990                sarl $1, tmp1 */
991             move_reg_to_reg(OpndSize_32, 2, false, 1, false);
992             alu_binary_imm_reg(OpndSize_32, shr_opc, 31, 1, false);
993             alu_binary_reg_reg(OpndSize_32, add_opc, 2, false, 1, false);
994             alu_binary_imm_reg(OpndSize_32, sar_opc, 1, 1, false);
995             set_virtual_reg(vA, OpndSize_32, 1, false);
996             return 1;
997         }
998         //power > 1
999         /* mov tmp1, tmp2
1000            sarl $power-1, tmp1
1001            shrl 32-$power, tmp1
1002            addl tmp2, tmp1
1003            sarl $power, tmp1 */
1004         move_reg_to_reg(OpndSize_32, 2, false, 1, false);
1005         alu_binary_imm_reg(OpndSize_32, sar_opc, power-1, 1, false);
1006         alu_binary_imm_reg(OpndSize_32, shr_opc, 32-power, 1, false);
1007         alu_binary_reg_reg(OpndSize_32, add_opc, 2, false, 1, false);
1008         alu_binary_imm_reg(OpndSize_32, sar_opc, power, 1, false);
1009         set_virtual_reg(vA, OpndSize_32, 1, false);
1010         return 1;
1011     }
1012     return 0;
1013 }
1014 
1015 ////////// throws exception!!!
1016 //! common code to handle integer DIV & REM with literal
1017 
1018 //! It uses GPR
common_div_rem_int_lit(bool isRem,u2 vA,u2 vB,s2 imm)1019 int common_div_rem_int_lit(bool isRem, u2 vA, u2 vB, s2 imm) {
1020     if(!isRem) {
1021         int retCode = div_lit_strength_reduction(vA, vB, imm);
1022         if(retCode > 0) return 0;
1023     }
1024     if(imm == 0) {
1025         export_pc(); //use %edx
1026 #ifdef DEBUG_EXCEPTION
1027         LOGI("EXTRA code to handle exception");
1028 #endif
1029         constVREndOfBB();
1030         beforeCall("exception"); //dump GG, GL VRs
1031         unconditional_jump_global_API(
1032                           "common_errDivideByZero", false);
1033 
1034         return 0;
1035     }
1036     get_virtual_reg(vB, OpndSize_32, PhysicalReg_EAX, true);
1037     //check against -1 for DIV_INT??
1038     if(imm == -1) {
1039         compare_imm_reg(OpndSize_32, 0x80000000, PhysicalReg_EAX, true);
1040         conditional_jump(Condition_E, ".div_rem_int_lit_special", true);
1041         rememberState(1);
1042     }
1043     move_imm_to_reg(OpndSize_32, imm, 2, false);
1044     convert_integer(OpndSize_32, OpndSize_64); //cdq
1045     //idiv: dividend in edx:eax; quotient in eax; remainder in edx
1046     alu_unary_reg(OpndSize_32, idiv_opc, 2, false);
1047     if(isRem)
1048         set_virtual_reg(vA, OpndSize_32, PhysicalReg_EDX, true);
1049     else
1050         set_virtual_reg(vA, OpndSize_32, PhysicalReg_EAX, true);
1051 
1052     if(imm == -1) {
1053         unconditional_jump(".div_rem_int_lit_okay", true);
1054         rememberState(2);
1055         insertLabel(".div_rem_int_lit_special", true);
1056         goToState(1);
1057         if(isRem)
1058             set_VR_to_imm(vA, OpndSize_32, 0);
1059         else
1060             set_VR_to_imm(vA, OpndSize_32, 0x80000000);
1061         transferToState(2);
1062     }
1063 
1064     insertLabel(".div_rem_int_lit_okay", true); //merge point 2
1065     return 0;
1066 }
1067 #undef P_GPR_1
1068 //! lower bytecode DIV_INT_LIT16 by calling common_div_rem_int_lit
1069 
1070 //!
op_div_int_lit16()1071 int op_div_int_lit16() {
1072     u2 vA = INST_A(inst);
1073     u2 vB = INST_B(inst);
1074     s4 tmp = (s2)FETCH(1);
1075     int retval = common_div_rem_int_lit(false, vA, vB, tmp);
1076     rPC += 2;
1077     return retval;
1078 }
1079 //! lower bytecode REM_INT_LIT16 by calling common_div_rem_int_lit
1080 
1081 //!
op_rem_int_lit16()1082 int op_rem_int_lit16() {
1083     u2 vA = INST_A(inst);
1084     u2 vB = INST_B(inst);
1085     s4 tmp = (s2)FETCH(1);
1086     int retval = common_div_rem_int_lit(true, vA, vB, tmp);
1087     rPC += 2;
1088     return retval;
1089 }
1090 //! lower bytecode DIV_INT_LIT8 by calling common_div_rem_int_lit
1091 
1092 //!
op_div_int_lit8()1093 int op_div_int_lit8() {
1094     u2 vA = INST_AA(inst);
1095     u2 vB = (u2)FETCH(1) & 0xff;
1096     s2 tmp = (s2)FETCH(1) >> 8;
1097     int retval = common_div_rem_int_lit(false, vA, vB, tmp);
1098     rPC += 2;
1099     return retval;
1100 }
1101 //! lower bytecode REM_INT_LIT8 by calling common_div_rem_int_lit
1102 
1103 //!
op_rem_int_lit8()1104 int op_rem_int_lit8() {
1105     u2 vA = INST_AA(inst);
1106     u2 vB = (u2)FETCH(1) & 0xff;
1107     s2 tmp = (s2)FETCH(1) >> 8;
1108     int retval = common_div_rem_int_lit(true, vA, vB, tmp);
1109     rPC += 2;
1110     return retval;
1111 }
1112 //! common code to hanle long ALU ops
1113 
1114 //! It uses XMM
common_alu_long(ALU_Opcode opc,u2 vA,u2 v1,u2 v2)1115 int common_alu_long(ALU_Opcode opc, u2 vA, u2 v1, u2 v2) { //except div and rem
1116     get_virtual_reg(v1, OpndSize_64, 1, false);
1117     get_virtual_reg(v2, OpndSize_64, 2, false);
1118     alu_binary_reg_reg(OpndSize_64, opc, 2, false, 1, false);
1119     set_virtual_reg(vA, OpndSize_64, 1, false);
1120     return 0;
1121 }
1122 //! lower bytecode ADD_LONG by calling common_alu_long
1123 
1124 //!
op_add_long()1125 int op_add_long() {
1126     u2 vA = INST_AA(inst);
1127     u2 v1 = *((u1*)rPC + 2);
1128     u2 v2 = *((u1*)rPC + 3);
1129     int retval = common_alu_long(add_opc, vA, v1, v2);
1130     rPC += 2;
1131     return retval;
1132 }
1133 //! lower bytecode SUB_LONG by calling common_alu_long
1134 
1135 //!
op_sub_long()1136 int op_sub_long() {
1137     u2 vA = INST_AA(inst);
1138     u2 v1 = *((u1*)rPC + 2);
1139     u2 v2 = *((u1*)rPC + 3);
1140     int retval = common_alu_long(sub_opc, vA, v1, v2);
1141     rPC += 2;
1142     return retval;
1143 }
1144 //! lower bytecode AND_LONG by calling common_alu_long
1145 
1146 //!
op_and_long()1147 int op_and_long() {
1148     u2 vA = INST_AA(inst);
1149     u2 v1 = *((u1*)rPC + 2);
1150     u2 v2 = *((u1*)rPC + 3);
1151     int retval = common_alu_long(and_opc, vA, v1, v2);
1152     rPC += 2;
1153     return retval;
1154 }
1155 //! lower bytecode OR_LONG by calling common_alu_long
1156 
1157 //!
op_or_long()1158 int op_or_long() {
1159     u2 vA = INST_AA(inst);
1160     u2 v1 = *((u1*)rPC + 2);
1161     u2 v2 = *((u1*)rPC + 3);
1162     int retval = common_alu_long(or_opc, vA, v1, v2);
1163     rPC += 2;
1164     return retval;
1165 }
1166 //! lower bytecode XOR_LONG by calling common_alu_long
1167 
1168 //!
op_xor_long()1169 int op_xor_long() {
1170     u2 vA = INST_AA(inst);
1171     u2 v1 = *((u1*)rPC + 2);
1172     u2 v2 = *((u1*)rPC + 3);
1173     int retval = common_alu_long(xor_opc, vA, v1, v2);
1174     rPC += 2;
1175     return retval;
1176 }
1177 //! lower bytecode ADD_LONG_2ADDR by calling common_alu_long
1178 
1179 //!
op_add_long_2addr()1180 int op_add_long_2addr() {
1181     u2 vA = INST_A(inst);
1182     u2 v1 = vA;
1183     u2 v2 = INST_B(inst);
1184     int retval = common_alu_long(add_opc, vA, v1, v2);
1185     rPC += 1;
1186     return retval;
1187 }
1188 //! lower bytecode SUB_LONG_2ADDR by calling common_alu_long
1189 
1190 //!
op_sub_long_2addr()1191 int op_sub_long_2addr() {
1192     u2 vA = INST_A(inst);
1193     u2 v1 = vA;
1194     u2 v2 = INST_B(inst);
1195     int retval = common_alu_long(sub_opc, vA, v1, v2);
1196     rPC += 1;
1197     return retval;
1198 }
1199 //! lower bytecode AND_LONG_2ADDR by calling common_alu_long
1200 
1201 //!
op_and_long_2addr()1202 int op_and_long_2addr() {
1203     u2 vA = INST_A(inst);
1204     u2 v1 = vA;
1205     u2 v2 = INST_B(inst);
1206     int retval = common_alu_long(and_opc, vA, v1, v2);
1207     rPC += 1;
1208     return retval;
1209 }
1210 //! lower bytecode OR_LONG_2ADDR by calling common_alu_long
1211 
1212 //!
op_or_long_2addr()1213 int op_or_long_2addr() {
1214     u2 vA = INST_A(inst);
1215     u2 v1 = vA;
1216     u2 v2 = INST_B(inst);
1217     int retval = common_alu_long(or_opc, vA, v1, v2);
1218     rPC += 1;
1219     return retval;
1220 }
1221 //! lower bytecode XOR_LONG_2ADDR by calling common_alu_long
1222 
1223 //!
op_xor_long_2addr()1224 int op_xor_long_2addr() {
1225     u2 vA = INST_A(inst);
1226     u2 v1 = vA;
1227     u2 v2 = INST_B(inst);
1228     int retval = common_alu_long(xor_opc, vA, v1, v2);
1229     rPC += 1;
1230     return retval;
1231 }
1232 
1233 //signed vs unsigned imul and mul?
1234 #define P_GPR_1 PhysicalReg_EBX
1235 #define P_GPR_2 PhysicalReg_ECX
1236 #define P_GPR_3 PhysicalReg_ESI
1237 //! common code to handle multiplication of long
1238 
1239 //! It uses GPR
common_mul_long(u2 vA,u2 v1,u2 v2)1240 int common_mul_long(u2 vA, u2 v1, u2 v2) {
1241     get_virtual_reg(v2, OpndSize_32, 1, false);
1242     move_reg_to_reg(OpndSize_32, 1, false, PhysicalReg_EAX, true);
1243     //imul: 2L * 1H update temporary 1
1244     alu_binary_VR_reg(OpndSize_32, imul_opc, (v1+1), 1, false);
1245     get_virtual_reg(v1, OpndSize_32, 3, false);
1246     move_reg_to_reg(OpndSize_32, 3, false, 2, false);
1247     //imul: 1L * 2H
1248     alu_binary_VR_reg(OpndSize_32, imul_opc, (v2+1), 2, false);
1249     alu_binary_reg_reg(OpndSize_32, add_opc, 2, false, 1, false);
1250     alu_unary_reg(OpndSize_32, mul_opc, 3, false);
1251     alu_binary_reg_reg(OpndSize_32, add_opc, PhysicalReg_EDX, true, 1, false);
1252     set_virtual_reg(vA+1, OpndSize_32, 1, false);
1253     set_virtual_reg(vA, OpndSize_32, PhysicalReg_EAX, true);
1254     return 0;
1255 }
1256 #undef P_GPR_1
1257 #undef P_GPR_2
1258 #undef P_GPR_3
1259 //! lower bytecode MUL_LONG by calling common_mul_long
1260 
1261 //!
op_mul_long()1262 int op_mul_long() {
1263     u2 vA = INST_AA(inst);
1264     u2 v1 = *((u1*)rPC + 2);
1265     u2 v2 = *((u1*)rPC + 3);
1266     int retval = common_mul_long(vA, v1, v2);
1267     rPC += 2;
1268     return retval;
1269 }
1270 //! lower bytecode MUL_LONG_2ADDR by calling common_mul_long
1271 
1272 //!
op_mul_long_2addr()1273 int op_mul_long_2addr() {
1274     u2 vA = INST_A(inst);
1275     u2 v1 = vA;
1276     u2 v2 = INST_B(inst);
1277     int retval = common_mul_long(vA, v1, v2);
1278     rPC += 1;
1279     return retval;
1280 }
1281 
1282 #define P_GPR_1 PhysicalReg_EBX
1283 #define P_GPR_2 PhysicalReg_ECX
1284 //! common code to handle DIV & REM of long
1285 
1286 //! It uses GPR & XMM; and calls call_moddi3 & call_divdi3
common_div_rem_long(bool isRem,u2 vA,u2 v1,u2 v2)1287 int common_div_rem_long(bool isRem, u2 vA, u2 v1, u2 v2) {
1288     get_virtual_reg(v2, OpndSize_32, 1, false);
1289     get_virtual_reg(v2+1, OpndSize_32, 2, false);
1290     //save to native stack before changing register P_GPR_1
1291     load_effective_addr(-16, PhysicalReg_ESP, true, PhysicalReg_ESP, true);
1292     move_reg_to_mem(OpndSize_32, 1, false, 8, PhysicalReg_ESP, true);
1293     alu_binary_reg_reg(OpndSize_32, or_opc, 2, false, 1, false);
1294 
1295     handlePotentialException(
1296                                        Condition_E, Condition_NE,
1297                                        1, "common_errDivideByZero");
1298     move_reg_to_mem(OpndSize_32, 2, false, 12, PhysicalReg_ESP, true);
1299     get_virtual_reg(v1, OpndSize_64, 1, false);
1300     move_reg_to_mem(OpndSize_64, 1, false, 0, PhysicalReg_ESP, true);
1301     scratchRegs[0] = PhysicalReg_SCRATCH_1;
1302     nextVersionOfHardReg(PhysicalReg_EDX, 2); //next version has 2 refs
1303     if(isRem)
1304         call_moddi3();
1305     else
1306         call_divdi3();
1307     load_effective_addr(16, PhysicalReg_ESP, true, PhysicalReg_ESP, true);
1308     set_virtual_reg(vA+1, OpndSize_32,PhysicalReg_EDX, true);
1309     set_virtual_reg(vA, OpndSize_32, PhysicalReg_EAX, true);
1310     return 0;
1311 }
1312 #undef P_GPR_1
1313 #undef P_GPR_2
1314 //! lower bytecode DIV_LONG by calling common_div_rem_long
1315 
1316 //!
op_div_long()1317 int op_div_long() {
1318     u2 vA = INST_AA(inst);
1319     u2 v1 = *((u1*)rPC + 2);
1320     u2 v2 = *((u1*)rPC + 3);
1321     int retval = common_div_rem_long(false, vA, v1, v2);
1322     rPC += 2;
1323     return retval;
1324 }
1325 //! lower bytecode REM_LONG by calling common_div_rem_long
1326 
1327 //!
op_rem_long()1328 int op_rem_long() {
1329     u2 vA = INST_AA(inst);
1330     u2 v1 = *((u1*)rPC + 2);
1331     u2 v2 = *((u1*)rPC + 3);
1332     int retval = common_div_rem_long(true, vA, v1, v2);
1333     rPC += 2;
1334     return retval;
1335 }
1336 //! lower bytecode DIV_LONG_2ADDR by calling common_div_rem_long
1337 
1338 //!
op_div_long_2addr()1339 int op_div_long_2addr() {
1340     u2 vA = INST_A(inst);
1341     u2 v1 = vA;
1342     u2 v2 = INST_B(inst);
1343     int retval = common_div_rem_long(false, vA, v1, v2);
1344     rPC += 1;
1345     return retval;
1346 }
1347 //! lower bytecode REM_LONG_2ADDR by calling common_div_rem_long
1348 
1349 //!
op_rem_long_2addr()1350 int op_rem_long_2addr() { //call __moddi3 instead of __divdi3
1351     u2 vA = INST_A(inst);
1352     u2 v1 = vA;
1353     u2 v2 = INST_B(inst);
1354     int retval = common_div_rem_long(true, vA, v1, v2);
1355     rPC += 1;
1356     return retval;
1357 }
1358 
1359 //! common code to handle SHL long
1360 
1361 //! It uses XMM
common_shl_long(u2 vA,u2 v1,u2 v2)1362 int common_shl_long(u2 vA, u2 v1, u2 v2) {
1363     get_VR_ss(v2, 2, false);
1364 
1365     load_global_data_API("shiftMask", OpndSize_64, 3, false);
1366 
1367     get_virtual_reg(v1, OpndSize_64, 1, false);
1368     alu_binary_reg_reg(OpndSize_64, and_opc, 3, false, 2, false);
1369     alu_binary_reg_reg(OpndSize_64, sll_opc, 2, false, 1, false);
1370     set_virtual_reg(vA, OpndSize_64, 1, false);
1371     return 0;
1372 }
1373 
1374 //! common code to handle SHR long
1375 
1376 //! It uses XMM
common_shr_long(u2 vA,u2 v1,u2 v2)1377 int common_shr_long(u2 vA, u2 v1, u2 v2) {
1378     get_VR_ss(v2, 2, false);
1379 
1380     load_global_data_API("shiftMask", OpndSize_64, 3, false);
1381 
1382     get_virtual_reg(v1, OpndSize_64, 1, false);
1383     alu_binary_reg_reg(OpndSize_64, and_opc, 3, false, 2, false);
1384     alu_binary_reg_reg(OpndSize_64, srl_opc, 2, false, 1, false);
1385     compare_imm_VR(OpndSize_32, 0, (v1+1));
1386     conditional_jump(Condition_GE, ".common_shr_long_special", true);
1387     rememberState(1);
1388 
1389     load_global_data_API("value64", OpndSize_64, 4, false);
1390 
1391     alu_binary_reg_reg(OpndSize_64, sub_opc, 2, false, 4, false);
1392 
1393     load_global_data_API("64bits", OpndSize_64, 5, false);
1394 
1395     alu_binary_reg_reg(OpndSize_64, sll_opc, 4, false, 5, false);
1396     alu_binary_reg_reg(OpndSize_64, or_opc, 5, false, 1, false);
1397     rememberState(2);
1398     //check whether the target is next instruction TODO
1399     unconditional_jump(".common_shr_long_done", true);
1400 
1401     insertLabel(".common_shr_long_special", true);
1402     goToState(1);
1403     transferToState(2);
1404     insertLabel(".common_shr_long_done", true);
1405     set_virtual_reg(vA, OpndSize_64, 1, false);
1406     return 0;
1407 }
1408 
1409 //! common code to handle USHR long
1410 
1411 //! It uses XMM
common_ushr_long(u2 vA,u2 v1,u2 v2)1412 int common_ushr_long(u2 vA, u2 v1, u2 v2) {
1413     get_VR_sd(v1, 1, false);
1414     get_VR_ss(v2, 2, false);
1415 
1416     load_sd_global_data_API("shiftMask", 3, false);
1417 
1418     alu_binary_reg_reg(OpndSize_64, and_opc, 3, false, 2, false);
1419     alu_binary_reg_reg(OpndSize_64, srl_opc, 2, false, 1, false);
1420     set_VR_sd(vA, 1, false);
1421     return 0;
1422 }
1423 //! lower bytecode SHL_LONG by calling common_shl_long
1424 
1425 //!
op_shl_long()1426 int op_shl_long() {
1427     u2 vA = INST_AA(inst);
1428     u2 v1 = *((u1*)rPC + 2);
1429     u2 v2 = *((u1*)rPC + 3);
1430     int retval = common_shl_long(vA, v1, v2);
1431     rPC += 2;
1432     return retval;
1433 }
1434 //! lower bytecode SHL_LONG_2ADDR by calling common_shl_long
1435 
1436 //!
op_shl_long_2addr()1437 int op_shl_long_2addr() {
1438     u2 vA = INST_A(inst);
1439     u2 v1 = vA;
1440     u2 v2 = INST_B(inst);
1441     int retval = common_shl_long(vA, v1, v2);
1442     rPC += 1;
1443     return retval;
1444 }
1445 //! lower bytecode SHR_LONG by calling common_shr_long
1446 
1447 //!
op_shr_long()1448 int op_shr_long() {
1449     u2 vA = INST_AA(inst);
1450     u2 v1 = *((u1*)rPC + 2);
1451     u2 v2 = *((u1*)rPC + 3);
1452     int retval = common_shr_long(vA, v1, v2);
1453     rPC += 2;
1454     return retval;
1455 }
1456 //! lower bytecode SHR_LONG_2ADDR by calling common_shr_long
1457 
1458 //!
op_shr_long_2addr()1459 int op_shr_long_2addr() {
1460     u2 vA = INST_A(inst);
1461     u2 v1 = vA;
1462     u2 v2 = INST_B(inst);
1463     int retval = common_shr_long(vA, v1, v2);
1464     rPC += 1;
1465     return retval;
1466 }
1467 //! lower bytecode USHR_LONG by calling common_ushr_long
1468 
1469 //!
op_ushr_long()1470 int op_ushr_long() {
1471     u2 vA = INST_AA(inst);
1472     u2 v1 = *((u1*)rPC + 2);
1473     u2 v2 = *((u1*)rPC + 3);
1474     int retval = common_ushr_long(vA, v1, v2);
1475     rPC += 2;
1476     return retval;
1477 }
1478 //! lower bytecode USHR_LONG_2ADDR by calling common_ushr_long
1479 
1480 //!
op_ushr_long_2addr()1481 int op_ushr_long_2addr() {
1482     u2 vA = INST_A(inst);
1483     u2 v1 = vA;
1484     u2 v2 = INST_B(inst);
1485     int retval = common_ushr_long(vA, v1, v2);
1486     rPC += 1;
1487     return retval;
1488 }
1489 #define USE_MEM_OPERAND
1490 ///////////////////////////////////////////
1491 //! common code to handle ALU of floats
1492 
1493 //! It uses XMM
common_alu_float(ALU_Opcode opc,u2 vA,u2 v1,u2 v2)1494 int common_alu_float(ALU_Opcode opc, u2 vA, u2 v1, u2 v2) {//add, sub, mul
1495     get_VR_ss(v1, 1, false);
1496 #ifdef USE_MEM_OPERAND
1497     alu_sd_binary_VR_reg(opc, v2, 1, false, false/*isSD*/);
1498 #else
1499     get_VR_ss(v2, 2, false);
1500     alu_ss_binary_reg_reg(opc, 2, false, 1, false);
1501 #endif
1502     set_VR_ss(vA, 1, false);
1503     return 0;
1504 }
1505 //! lower bytecode ADD_FLOAT by calling common_alu_float
1506 
1507 //!
op_add_float()1508 int op_add_float() {
1509     u2 vA = INST_AA(inst);
1510     u2 v1 = *((u1*)rPC + 2);
1511     u2 v2 = *((u1*)rPC + 3);
1512     int retval = common_alu_float(add_opc, vA, v1, v2);
1513     rPC += 2;
1514     return retval;
1515 }
1516 //! lower bytecode SUB_FLOAT by calling common_alu_float
1517 
1518 //!
op_sub_float()1519 int op_sub_float() {
1520     u2 vA = INST_AA(inst);
1521     u2 v1 = *((u1*)rPC + 2);
1522     u2 v2 = *((u1*)rPC + 3);
1523     int retval = common_alu_float(sub_opc, vA, v1, v2);
1524     rPC += 2;
1525     return retval;
1526 }
1527 //! lower bytecode MUL_FLOAT by calling common_alu_float
1528 
1529 //!
op_mul_float()1530 int op_mul_float() {
1531     u2 vA = INST_AA(inst);
1532     u2 v1 = *((u1*)rPC + 2);
1533     u2 v2 = *((u1*)rPC + 3);
1534     int retval = common_alu_float(mul_opc, vA, v1, v2);
1535     rPC += 2;
1536     return retval;
1537 }
1538 //! lower bytecode ADD_FLOAT_2ADDR by calling common_alu_float
1539 
1540 //!
op_add_float_2addr()1541 int op_add_float_2addr() {
1542     u2 vA = INST_A(inst);
1543     u2 v1 = vA;
1544     u2 v2 = INST_B(inst);
1545     int retval = common_alu_float(add_opc, vA, v1, v2);
1546     rPC += 1;
1547     return retval;
1548 }
1549 //! lower bytecode SUB_FLOAT_2ADDR by calling common_alu_float
1550 
1551 //!
op_sub_float_2addr()1552 int op_sub_float_2addr() {
1553     u2 vA = INST_A(inst);
1554     u2 v1 = vA;
1555     u2 v2 = INST_B(inst);
1556     int retval = common_alu_float(sub_opc, vA, v1, v2);
1557     rPC += 1;
1558     return retval;
1559 }
1560 //! lower bytecode MUL_FLOAT_2ADDR by calling common_alu_float
1561 
1562 //!
op_mul_float_2addr()1563 int op_mul_float_2addr() {
1564     u2 vA = INST_A(inst);
1565     u2 v1 = vA;
1566     u2 v2 = INST_B(inst);
1567     int retval = common_alu_float(mul_opc, vA, v1, v2);
1568     rPC += 1;
1569     return retval;
1570 }
1571 //! common code to handle DIV of float
1572 
1573 //! It uses FP stack
common_div_float(u2 vA,u2 v1,u2 v2)1574 int common_div_float(u2 vA, u2 v1, u2 v2) {
1575     load_fp_stack_VR(OpndSize_32, v1); //flds
1576     fpu_VR(div_opc, OpndSize_32, v2);
1577     store_fp_stack_VR(true, OpndSize_32, vA); //fstps
1578     return 0;
1579 }
1580 //! lower bytecode DIV_FLOAT by calling common_div_float
1581 
1582 //!
op_div_float()1583 int op_div_float() {
1584     u2 vA = INST_AA(inst);
1585     u2 v1 = *((u1*)rPC + 2);
1586     u2 v2 = *((u1*)rPC + 3);
1587     int retval = common_alu_float(div_opc, vA, v1, v2);
1588     rPC += 2;
1589     return retval;
1590 }
1591 //! lower bytecode DIV_FLOAT_2ADDR by calling common_div_float
1592 
1593 //!
op_div_float_2addr()1594 int op_div_float_2addr() {
1595     u2 vA = INST_A(inst);
1596     u2 v1 = vA;
1597     u2 v2 = INST_B(inst);
1598     int retval = common_alu_float(div_opc, vA, v1, v2);
1599     rPC += 1;
1600     return retval;
1601 }
1602 //! common code to handle DIV of double
1603 
1604 //! It uses XMM
common_alu_double(ALU_Opcode opc,u2 vA,u2 v1,u2 v2)1605 int common_alu_double(ALU_Opcode opc, u2 vA, u2 v1, u2 v2) {//add, sub, mul
1606     get_VR_sd(v1, 1, false);
1607 #ifdef USE_MEM_OPERAND
1608     alu_sd_binary_VR_reg(opc, v2, 1, false, true /*isSD*/);
1609 #else
1610     get_VR_sd(v2, 2, false);
1611     alu_sd_binary_reg_reg(opc, 2, false, 1, false);
1612 #endif
1613     set_VR_sd(vA, 1, false);
1614     return 0;
1615 }
1616 //! lower bytecode ADD_DOUBLE by calling common_alu_double
1617 
1618 //!
op_add_double()1619 int op_add_double() {
1620     u2 vA = INST_AA(inst);
1621     u2 v1 = *((u1*)rPC + 2);
1622     u2 v2 = *((u1*)rPC + 3);
1623     int retval = common_alu_double(add_opc, vA, v1, v2);
1624     rPC += 2;
1625     return retval;
1626 }
1627 //! lower bytecode SUB_DOUBLE by calling common_alu_double
1628 
1629 //!
op_sub_double()1630 int op_sub_double() {
1631     u2 vA = INST_AA(inst);
1632     u2 v1 = *((u1*)rPC + 2);
1633     u2 v2 = *((u1*)rPC + 3);
1634     int retval = common_alu_double(sub_opc, vA, v1, v2);
1635     rPC += 2;
1636     return retval;
1637 }
1638 //! lower bytecode MUL_DOUBLE by calling common_alu_double
1639 
1640 //!
op_mul_double()1641 int op_mul_double() {
1642     u2 vA = INST_AA(inst);
1643     u2 v1 = *((u1*)rPC + 2);
1644     u2 v2 = *((u1*)rPC + 3);
1645     int retval = common_alu_double(mul_opc, vA, v1, v2);
1646     rPC += 2;
1647     return retval;
1648 }
1649 //! lower bytecode ADD_DOUBLE_2ADDR by calling common_alu_double
1650 
1651 //!
op_add_double_2addr()1652 int op_add_double_2addr() {
1653     u2 vA = INST_A(inst);
1654     u2 v1 = vA;
1655     u2 v2 = INST_B(inst);
1656     int retval = common_alu_double(add_opc, vA, v1, v2);
1657     rPC += 1;
1658     return retval;
1659 }
1660 //! lower bytecode SUB_DOUBLE_2ADDR by calling common_alu_double
1661 
1662 //!
op_sub_double_2addr()1663 int op_sub_double_2addr() {
1664     u2 vA = INST_A(inst);
1665     u2 v1 = vA;
1666     u2 v2 = INST_B(inst);
1667     int retval = common_alu_double(sub_opc, vA, v1, v2);
1668     rPC += 1;
1669     return retval;
1670 }
1671 //! lower bytecode MUL_DOUBLE_2ADDR by calling common_alu_double
1672 
1673 //!
op_mul_double_2addr()1674 int op_mul_double_2addr() {
1675     u2 vA = INST_A(inst);
1676     u2 v1 = vA;
1677     u2 v2 = INST_B(inst);
1678     int retval = common_alu_double(mul_opc, vA, v1, v2);
1679     rPC += 1;
1680     return retval;
1681 }
1682 //! common code to handle DIV of double
1683 
1684 //! It uses FP stack
common_div_double(u2 vA,u2 v1,u2 v2)1685 int common_div_double(u2 vA, u2 v1, u2 v2) {
1686     load_fp_stack_VR(OpndSize_64, v1); //fldl
1687     fpu_VR(div_opc, OpndSize_64, v2); //fdivl
1688     store_fp_stack_VR(true, OpndSize_64, vA); //fstpl
1689     return 0;
1690 }
1691 //! lower bytecode DIV_DOUBLE by calling common_div_double
1692 
1693 //!
op_div_double()1694 int op_div_double() {
1695     u2 vA = INST_AA(inst);
1696     u2 v1 = *((u1*)rPC + 2);
1697     u2 v2 = *((u1*)rPC + 3);
1698     int retval = common_alu_double(div_opc, vA, v1, v2);
1699     rPC += 2;
1700     return retval;
1701 }
1702 //! lower bytecode DIV_DOUBLE_2ADDR by calling common_div_double
1703 
1704 //!
op_div_double_2addr()1705 int op_div_double_2addr() {
1706     u2 vA = INST_A(inst);
1707     u2 v1 = vA;
1708     u2 v2 = INST_B(inst);
1709     int retval = common_alu_double(div_opc, vA, v1, v2);
1710     rPC += 1;
1711     return retval;
1712 }
1713 #define P_GPR_1 PhysicalReg_EBX
1714 #define P_GPR_2 PhysicalReg_ECX
1715 //! common code to handle REM of float
1716 
1717 //! It uses GPR & calls call_fmodf
common_rem_float(u2 vA,u2 v1,u2 v2)1718 int common_rem_float(u2 vA, u2 v1, u2 v2) {
1719     get_virtual_reg(v1, OpndSize_32, 1, false);
1720     get_virtual_reg(v2, OpndSize_32, 2, false);
1721     load_effective_addr(-8, PhysicalReg_ESP, true, PhysicalReg_ESP, true);
1722     move_reg_to_mem(OpndSize_32, 1, false, 0, PhysicalReg_ESP, true);
1723     move_reg_to_mem(OpndSize_32, 2, false, 4, PhysicalReg_ESP, true);
1724     scratchRegs[0] = PhysicalReg_SCRATCH_1;
1725     call_fmodf(); //(float x, float y) return float
1726     load_effective_addr(8, PhysicalReg_ESP, true, PhysicalReg_ESP, true);
1727     store_fp_stack_VR(true, OpndSize_32, vA); //fstps
1728     return 0;
1729 }
1730 #undef P_GPR_1
1731 #undef P_GPR_2
1732 //! lower bytecode REM_FLOAT by calling common_rem_float
1733 
1734 //!
op_rem_float()1735 int op_rem_float() {
1736     u2 vA = INST_AA(inst);
1737     u2 v1 = *((u1*)rPC + 2);
1738     u2 v2 = *((u1*)rPC + 3);
1739     int retval = common_rem_float(vA, v1, v2);
1740     rPC += 2;
1741     return retval;
1742 }
1743 //! lower bytecode REM_FLOAT_2ADDR by calling common_rem_float
1744 
1745 //!
op_rem_float_2addr()1746 int op_rem_float_2addr() {
1747     u2 vA = INST_A(inst);
1748     u2 v1 = vA;
1749     u2 v2 = INST_B(inst);
1750     int retval = common_rem_float(vA, v1, v2);
1751     rPC += 1;
1752     return retval;
1753 }
1754 //! common code to handle REM of double
1755 
1756 //! It uses XMM & calls call_fmod
common_rem_double(u2 vA,u2 v1,u2 v2)1757 int common_rem_double(u2 vA, u2 v1, u2 v2) {
1758     get_virtual_reg(v1, OpndSize_64, 1, false);
1759     get_virtual_reg(v2, OpndSize_64, 2, false);
1760     load_effective_addr(-16, PhysicalReg_ESP, true, PhysicalReg_ESP, true);
1761     move_reg_to_mem(OpndSize_64, 1, false, 0, PhysicalReg_ESP, true);
1762     move_reg_to_mem(OpndSize_64, 2, false, 8, PhysicalReg_ESP, true);
1763     scratchRegs[0] = PhysicalReg_SCRATCH_1;
1764     call_fmod(); //(long double x, long double y) return double
1765     load_effective_addr(16, PhysicalReg_ESP, true, PhysicalReg_ESP, true);
1766     store_fp_stack_VR(true, OpndSize_64, vA); //fstpl
1767     return 0;
1768 }
1769 //! lower bytecode REM_DOUBLE by calling common_rem_double
1770 
1771 //!
op_rem_double()1772 int op_rem_double() {
1773     u2 vA = INST_AA(inst);
1774     u2 v1 = *((u1*)rPC + 2);
1775     u2 v2 = *((u1*)rPC + 3);
1776     int retval = common_rem_double(vA, v1, v2);
1777     rPC += 2;
1778     return retval;
1779 }
1780 //! lower bytecode REM_DOUBLE_2ADDR by calling common_rem_double
1781 
1782 //!
op_rem_double_2addr()1783 int op_rem_double_2addr() {
1784     u2 vA = INST_A(inst);
1785     u2 v1 = vA;
1786     u2 v2 = INST_B(inst);
1787     int retval = common_rem_double(vA, v1, v2);
1788     rPC += 1;
1789     return retval;
1790 }
1791 //! lower bytecode CMPL_FLOAT
1792 
1793 //!
op_cmpl_float()1794 int op_cmpl_float() {
1795     u2 vA = INST_AA(inst);
1796     u4 v1 = FETCH(1) & 0xff;
1797     u4 v2 = FETCH(1) >> 8;
1798     get_VR_ss(v1, 1, false); //xmm
1799     move_imm_to_reg(OpndSize_32, 0, 1, false);
1800     move_imm_to_reg(OpndSize_32, 1, 2, false);
1801     move_imm_to_reg(OpndSize_32, 0xffffffff, 3, false);
1802     compare_VR_ss_reg(v2, 1, false);
1803     //default: 0xffffffff??
1804     move_imm_to_reg(OpndSize_32,
1805                                  0xffffffff, 4, false);
1806     //ORDER of cmov matters !!! (Z,P,A)
1807     //finalNaN: unordered 0xffffffff
1808     conditional_move_reg_to_reg(OpndSize_32, Condition_Z,
1809                                              1, false, 4, false);
1810     conditional_move_reg_to_reg(OpndSize_32, Condition_P,
1811                                              3, false, 4, false);
1812     conditional_move_reg_to_reg(OpndSize_32, Condition_A,
1813                                              2, false, 4, false);
1814     set_virtual_reg(vA, OpndSize_32, 4, false);
1815     rPC += 2;
1816     return 0;
1817 }
1818 //! lower bytecode CMPG_FLOAT
1819 
1820 //!
op_cmpg_float()1821 int op_cmpg_float() {
1822     u2 vA = INST_AA(inst);
1823     u4 v1 = FETCH(1) & 0xff;
1824     u4 v2 = FETCH(1) >> 8;
1825     get_VR_ss(v1, 1, false);
1826     compare_VR_ss_reg(v2, 1, false);
1827     move_imm_to_reg(OpndSize_32, 0, 1, false);
1828     move_imm_to_reg(OpndSize_32, 1, 2, false);
1829     //default: 0xffffffff??
1830     move_imm_to_reg(OpndSize_32, 0xffffffff, 3, false);
1831     conditional_move_reg_to_reg(OpndSize_32, Condition_Z,
1832                                 1, false, 3, false);
1833     //finalNaN: unordered
1834     conditional_move_reg_to_reg(OpndSize_32, Condition_P,
1835                                 2, false, 3, false);
1836     conditional_move_reg_to_reg(OpndSize_32, Condition_A,
1837                                 2, false, 3, false);
1838     set_virtual_reg(vA, OpndSize_32, 3, false);
1839     rPC += 2;
1840     return 0;
1841 }
1842 //! lower bytecode CMPL_DOUBLE
1843 
1844 //!
op_cmpl_double()1845 int op_cmpl_double() {
1846     u2 vA = INST_AA(inst);
1847     u4 v1 = FETCH(1) & 0xff;
1848     u4 v2 = FETCH(1) >> 8;
1849     get_VR_sd(v1, 1, false);
1850     compare_VR_sd_reg(v2, 1, false);
1851     move_imm_to_reg(OpndSize_32, 0, 1, false);
1852     move_imm_to_reg(OpndSize_32, 1, 2, false);
1853     move_imm_to_reg(OpndSize_32, 0xffffffff, 3, false);
1854 
1855     //default: 0xffffffff??
1856     move_imm_to_reg(OpndSize_32, 0xffffffff, 4, false);
1857     conditional_move_reg_to_reg(OpndSize_32, Condition_Z,
1858                                              1, false, 4, false);
1859     conditional_move_reg_to_reg(OpndSize_32, Condition_P,
1860                                              3, false, 4, false);
1861     conditional_move_reg_to_reg(OpndSize_32, Condition_A,
1862                                              2, false, 4, false);
1863     set_virtual_reg(vA, OpndSize_32, 4, false);
1864     rPC += 2;
1865     return 0;
1866 }
1867 //! lower bytecode CMPG_DOUBLE
1868 
1869 //!
op_cmpg_double()1870 int op_cmpg_double() {
1871     u2 vA = INST_AA(inst);
1872     u4 v1 = FETCH(1) & 0xff;
1873     u4 v2 = FETCH(1) >> 8;
1874     get_VR_sd(v1, 1, false);
1875     compare_VR_sd_reg(v2, 1, false);
1876     move_imm_to_reg(OpndSize_32, 0, 1, false);
1877     move_imm_to_reg(OpndSize_32, 1, 2, false);
1878 
1879     //default: 0xffffffff??
1880     move_imm_to_reg(OpndSize_32,
1881                                  0xffffffff, 3, false);
1882     conditional_move_reg_to_reg(OpndSize_32, Condition_Z,
1883                                              1, false, 3, false);
1884     //finalNaN: unordered
1885     conditional_move_reg_to_reg(OpndSize_32, Condition_P,
1886                                              2, false, 3, false);
1887     conditional_move_reg_to_reg(OpndSize_32, Condition_A,
1888                                              2, false, 3, false);
1889    set_virtual_reg(vA, OpndSize_32, 3, false);
1890     rPC += 2;
1891     return 0;
1892 }
1893 #define P_GPR_1 PhysicalReg_EBX
1894 #define P_GPR_2 PhysicalReg_ECX
1895 #define P_GPR_3 PhysicalReg_ESI
1896 #define P_SCRATCH_1 PhysicalReg_EDX
1897 #define P_SCRATCH_2 PhysicalReg_EAX
1898 #define OPTION_OLD //for simpler cfg
1899 //! lower bytecode CMP_LONG
1900 
1901 //!
op_cmp_long()1902 int op_cmp_long() {
1903     u2 vA = INST_AA(inst);
1904     u4 v1 = FETCH(1) & 0xff;
1905     u4 v2 = FETCH(1) >> 8;
1906     get_virtual_reg(v1+1, OpndSize_32, 2, false);
1907 #ifdef OPTION_OLD
1908     move_imm_to_reg(OpndSize_32, 0xffffffff, 3, false);
1909     move_imm_to_reg(OpndSize_32, 1, 4, false);
1910     move_imm_to_reg(OpndSize_32, 0, 5, false);
1911 #endif
1912     compare_VR_reg(OpndSize_32,
1913                                 v2+1, 2, false);
1914 #ifndef OPTION_OLD
1915     conditional_jump(Condition_L, ".cmp_long_less", true);
1916     conditional_jump(Condition_G, ".cmp_long_greater", true);
1917 #else
1918     conditional_jump(Condition_E, ".cmp_long_equal", true);
1919     rememberState(1);
1920     conditional_move_reg_to_reg(OpndSize_32, Condition_L, //below vs less
1921                                              3, false, 6, false);
1922     conditional_move_reg_to_reg(OpndSize_32, Condition_G, //above vs greater
1923                                              4, false, 6, false);
1924     set_virtual_reg(vA, OpndSize_32, 6, false);
1925     rememberState(2);
1926     unconditional_jump(".cmp_long_okay", true);
1927     insertLabel(".cmp_long_equal", true);
1928     goToState(1);
1929 #endif
1930 
1931     get_virtual_reg(v1, OpndSize_32, 1, false);
1932     compare_VR_reg(OpndSize_32,
1933                                 v2, 1, false);
1934 #ifdef OPTION_OLD
1935     conditional_move_reg_to_reg(OpndSize_32, Condition_E,
1936                                              5, false, 6, false);
1937     conditional_move_reg_to_reg(OpndSize_32, Condition_B, //below vs less
1938                                              3, false, 6, false);
1939     conditional_move_reg_to_reg(OpndSize_32, Condition_A, //above vs greater
1940                                              4, false, 6, false);
1941     set_virtual_reg(vA, OpndSize_32, 6, false);
1942     transferToState(2);
1943 #else
1944     conditional_jump(Condition_A, ".cmp_long_greater", true);
1945     conditional_jump(Condition_NE, ".cmp_long_less", true);
1946     set_VR_to_imm(vA, OpndSize_32, 0);
1947     unconditional_jump(".cmp_long_okay", true);
1948 
1949     insertLabel(".cmp_long_less", true);
1950     set_VR_to_imm(vA, OpndSize_32, 0xffffffff);
1951     unconditional_jump(".cmp_long_okay", true);
1952 
1953     insertLabel(".cmp_long_greater", true);
1954     set_VR_to_imm(vA, OpndSize_32, 1);
1955 #endif
1956     insertLabel(".cmp_long_okay", true);
1957     rPC += 2;
1958     return 0;
1959 }
1960 #undef P_GPR_1
1961 #undef P_GPR_2
1962 #undef P_GPR_3
1963