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