58 |
* -1 is the list terminator. The floating point register numbers |
* -1 is the list terminator. The floating point register numbers |
59 |
* must include the MD_FREG_MASK value. |
* must include the MD_FREG_MASK value. |
60 |
*/ |
*/ |
61 |
//#define MD_FREG_0 (MD_FREG_MASK | 0) |
#define MD_FREG_0 (MD_FREG_MASK | 0) |
62 |
#define MD_FREG_0 -1 /* TODO: implement FPU support */ |
//#define MD_FREG_0 -1 /* TODO: implement FPU support */ |
63 |
#define MD_FREG_1 (MD_FREG_MASK | 1) |
#define MD_FREG_1 (MD_FREG_MASK | 1) |
64 |
#define MD_FREG_2 (MD_FREG_MASK | 2) |
#define MD_FREG_2 (MD_FREG_MASK | 2) |
65 |
#define MD_FREG_3 (MD_FREG_MASK | 3) |
#define MD_FREG_3 (MD_FREG_MASK | 3) |
80 |
* Set this to a non-zero value if floating-point registers are organised |
* Set this to a non-zero value if floating-point registers are organised |
81 |
* in a stack (e.g. the x87 FPU). |
* in a stack (e.g. the x87 FPU). |
82 |
*/ |
*/ |
83 |
#define MD_FP_STACK_SIZE 0 |
#define MD_FP_STACK_SIZE 8 |
84 |
|
|
85 |
/* |
/* |
86 |
* The register that contains the CVM program counter. This may be |
* The register that contains the CVM program counter. This may be |
187 |
* floating-point registers, then load onto the top of the stack. |
* floating-point registers, then load onto the top of the stack. |
188 |
*/ |
*/ |
189 |
#define md_load_const_float_32(inst,reg,mem) \ |
#define md_load_const_float_32(inst,reg,mem) \ |
190 |
x86_fld((inst), (int)(mem), 0) |
do { \ |
191 |
|
amd64_push_reg((inst), MD_REG_PC); \ |
192 |
|
amd64_mov_reg_imm_size((inst), MD_REG_PC, (mem), 8); \ |
193 |
|
amd64_fld_membase((inst), (MD_REG_PC), (0), 0); \ |
194 |
|
amd64_pop_reg((inst), MD_REG_PC);\ |
195 |
|
}while(0) |
196 |
|
|
197 |
/* |
/* |
198 |
* Load a 64-bit floating-point constant into a register. The constant |
* Load a 64-bit floating-point constant into a register. The constant |
199 |
* is at a particular memory location. If the system does not use |
* is at a particular memory location. If the system does not use |
200 |
* floating-point registers, then load onto the top of the stack. |
* floating-point registers, then load onto the top of the stack. |
201 |
|
* TODO: fix all pushes and pops |
202 |
*/ |
*/ |
203 |
#define md_load_const_float_64(inst,reg,mem) \ |
#define md_load_const_float_64(inst,reg,mem) \ |
204 |
x86_fld((inst), (int)(mem), 1) |
do { \ |
205 |
|
amd64_push_reg((inst), MD_REG_PC); \ |
206 |
|
amd64_mov_reg_imm_size((inst), MD_REG_PC, (mem), 8); \ |
207 |
|
amd64_fld_membase((inst), (MD_REG_PC), (0), 1); \ |
208 |
|
amd64_pop_reg((inst), MD_REG_PC);\ |
209 |
|
}while(0) |
210 |
|
|
211 |
/* |
/* |
212 |
* Load the 32-bit constant zero into a register. This will zero-extend |
* Load the 32-bit constant zero into a register. This will zero-extend |
274 |
* floating-point stack. |
* floating-point stack. |
275 |
*/ |
*/ |
276 |
#define md_load_membase_float_32(inst,reg,basereg,offset) \ |
#define md_load_membase_float_32(inst,reg,basereg,offset) \ |
277 |
x86_fld_membase((inst), (basereg), (offset), 0) |
amd64_fld_membase((inst), (basereg), (offset), 0) |
278 |
#define md_load_membase_float_64(inst,reg,basereg,offset) \ |
#define md_load_membase_float_64(inst,reg,basereg,offset) \ |
279 |
x86_fld_membase((inst), (basereg), (offset), 1) |
amd64_fld_membase((inst), (basereg), (offset), 1) |
280 |
#define md_load_membase_float_native(inst,reg,basereg,offset) \ |
#define md_load_membase_float_native(inst,reg,basereg,offset) \ |
281 |
x86_fld80_membase((inst), (basereg), (offset)) |
amd64_fld80_membase((inst), (basereg), (offset)) |
282 |
|
|
283 |
/* |
/* |
284 |
* Store a 32-bit word register to an offset from a pointer register. |
* Store a 32-bit word register to an offset from a pointer register. |
322 |
* Store a short value to an offset from a pointer register. |
* Store a short value to an offset from a pointer register. |
323 |
*/ |
*/ |
324 |
#define md_store_membase_short(inst,reg,basereg,offset) \ |
#define md_store_membase_short(inst,reg,basereg,offset) \ |
325 |
x86_mov_membase_reg((inst), (basereg), (offset), (reg), 2) |
amd64_mov_membase_reg((inst), (basereg), (offset), (reg), 2) |
326 |
|
|
327 |
/* |
/* |
328 |
* Store an unsigned short value to an offset from a pointer register. |
* Store an unsigned short value to an offset from a pointer register. |
329 |
*/ |
*/ |
330 |
#define md_store_membase_ushort(inst,reg,basereg,offset) \ |
#define md_store_membase_ushort(inst,reg,basereg,offset) \ |
331 |
x86_mov_membase_reg((inst), (basereg), (offset), (reg), 2) |
amd64_mov_membase_reg((inst), (basereg), (offset), (reg), 2) |
332 |
|
|
333 |
/* |
/* |
334 |
* Store a floating-point value to an offset from a pointer register. |
* Store a floating-point value to an offset from a pointer register. |
337 |
* floating-point stack. |
* floating-point stack. |
338 |
*/ |
*/ |
339 |
#define md_store_membase_float_32(inst,reg,basereg,offset) \ |
#define md_store_membase_float_32(inst,reg,basereg,offset) \ |
340 |
x86_fst_membase((inst), (basereg), (offset), 0, 1) |
amd64_fst_membase_size((inst), (basereg), (offset), 0, 1, 4) |
341 |
#define md_store_membase_float_64(inst,reg,basereg,offset) \ |
#define md_store_membase_float_64(inst,reg,basereg,offset) \ |
342 |
x86_fst_membase((inst), (basereg), (offset), 1, 1) |
amd64_fst_membase((inst), (basereg), (offset), 1, 1) |
343 |
#define md_store_membase_float_native(inst,reg,basereg,offset) \ |
#define md_store_membase_float_native(inst,reg,basereg,offset) \ |
344 |
x86_fst80_membase((inst), (basereg), (offset)) |
amd64_fst80_membase((inst), (basereg), (offset)) |
345 |
|
|
346 |
/* |
/* |
347 |
* Add an immediate value to a register. |
* Add an immediate value to a register. |
358 |
/* |
/* |
359 |
* Perform arithmetic and logical operations on 32-bit word registers. |
* Perform arithmetic and logical operations on 32-bit word registers. |
360 |
* |
* |
361 |
* Division is tricky, so it is handled elsewhere for x86. |
* Division is tricky, so it is handled elsewhere for AMD64. |
362 |
*/ |
*/ |
363 |
#define md_add_reg_reg_word_32(inst,reg1,reg2) \ |
#define md_add_reg_reg_word_32(inst,reg1,reg2) \ |
364 |
amd64_alu_reg_reg_size((inst), X86_ADD, (reg1), (reg2), 4) |
amd64_alu_reg_reg_size((inst), X86_ADD, (reg1), (reg2), 4) |
366 |
amd64_alu_reg_reg_size((inst), X86_SUB, (reg1), (reg2), 4) |
amd64_alu_reg_reg_size((inst), X86_SUB, (reg1), (reg2), 4) |
367 |
#define md_mul_reg_reg_word_32(inst,reg1,reg2) \ |
#define md_mul_reg_reg_word_32(inst,reg1,reg2) \ |
368 |
amd64_imul_reg_reg_size((inst), (reg1), (reg2), 4) |
amd64_imul_reg_reg_size((inst), (reg1), (reg2), 4) |
|
extern md_inst_ptr _md_x86_divide(md_inst_ptr inst, int reg1, int reg2, |
|
|
int isSigned, int wantRemainder); |
|
369 |
#define md_div_reg_reg_word_32(inst,reg1,reg2) \ |
#define md_div_reg_reg_word_32(inst,reg1,reg2) \ |
370 |
do { ; } while (0) |
do { ; } while (0) |
371 |
#define md_udiv_reg_reg_word_32(inst,reg1,reg2) \ |
#define md_udiv_reg_reg_word_32(inst,reg1,reg2) \ |
433 |
* Perform arithmetic operations on native float values. If the system |
* Perform arithmetic operations on native float values. If the system |
434 |
* uses a floating-point stack, then the register arguments are ignored. |
* uses a floating-point stack, then the register arguments are ignored. |
435 |
* |
* |
436 |
* Note: x86 remainder is handled elsewhere because it is complicated. |
* Note: remainder is handled elsewhere because it is complicated. |
437 |
*/ |
*/ |
438 |
#define md_add_reg_reg_float(inst,reg1,reg2) \ |
#define md_add_reg_reg_float(inst,reg1,reg2) \ |
439 |
x86_fp_op_reg((inst), X86_FADD, 1, 1) |
amd64_fp_op_reg((inst), X86_FADD, 1, 1) |
440 |
#define md_sub_reg_reg_float(inst,reg1,reg2) \ |
#define md_sub_reg_reg_float(inst,reg1,reg2) \ |
441 |
x86_fp_op_reg((inst), X86_FSUB, 1, 1) |
amd64_fp_op_reg((inst), X86_FSUB, 1, 1) |
442 |
#define md_mul_reg_reg_float(inst,reg1,reg2) \ |
#define md_mul_reg_reg_float(inst,reg1,reg2) \ |
443 |
x86_fp_op_reg((inst), X86_FMUL, 1, 1) |
amd64_fp_op_reg((inst), X86_FMUL, 1, 1) |
444 |
#define md_div_reg_reg_float(inst,reg1,reg2) \ |
#define md_div_reg_reg_float(inst,reg1,reg2) \ |
445 |
x86_fp_op_reg((inst), X86_FDIV, 1, 1) |
amd64_fp_op_reg((inst), X86_FDIV, 1, 1) |
446 |
extern md_inst_ptr _md_x86_rem_float |
extern md_inst_ptr _md_amd64_rem_float |
447 |
(md_inst_ptr inst, int reg1, int reg2, int used); |
(md_inst_ptr inst, int reg1, int reg2, int used); |
448 |
#define md_rem_reg_reg_float(inst,reg1,reg2,used) \ |
#define md_rem_reg_reg_float(inst,reg1,reg2,used) \ |
449 |
do { (inst) = _md_x86_rem_float \ |
do { (inst) = _md_amd64_rem_float \ |
450 |
((inst), (reg1), (reg2), (used)); } while (0) |
((inst), (reg1), (reg2), (used)); } while (0) |
451 |
#define md_neg_reg_float(inst,reg) \ |
#define md_neg_reg_float(inst,reg) \ |
452 |
x86_fchs((inst)) |
amd64_fchs((inst)) |
453 |
|
|
454 |
/* |
/* |
455 |
* Compare two floating point values and produce a -1, 0, or 1 result. |
* Compare two floating point values and produce a -1, 0, or 1 result. |
456 |
*/ |
*/ |
457 |
extern md_inst_ptr _md_x86_cmp_float(md_inst_ptr inst, int dreg, int lessop); |
extern md_inst_ptr _md_amd64_cmp_float(md_inst_ptr inst, int dreg, int lessop); |
458 |
#define md_cmp_reg_reg_float(inst, dreg, sreg1, sreg2, lessop) \ |
#define md_cmp_reg_reg_float(inst, dreg, sreg1, sreg2, lessop) \ |
459 |
do { \ |
do { \ |
460 |
(inst) = _md_x86_cmp_float((inst), (dreg), (lessop)); \ |
(inst) = _md_amd64_cmp_float((inst), (dreg), (lessop)); \ |
461 |
} while (0) |
} while (0) |
462 |
|
|
463 |
/* |
/* |
485 |
|
|
486 |
/* |
/* |
487 |
* Truncate floating point values to 32-bit or 64-bit. |
* Truncate floating point values to 32-bit or 64-bit. |
488 |
|
* TODO: use cvt2* opcodes here |
489 |
*/ |
*/ |
490 |
#define md_reg_to_float_32(inst,reg) \ |
#define md_reg_to_float_32(inst,reg) \ |
491 |
do { \ |
do { \ |
492 |
x86_alu_reg_imm((inst), X86_SUB, X86_ESP, 4); \ |
amd64_alu_reg_imm((inst), X86_SUB, AMD64_RSP, 4); \ |
493 |
x86_fst_membase((inst), X86_ESP, 0, 0, 1); \ |
amd64_fst_membase((inst), AMD64_RSP, 0, 0, 1); \ |
494 |
x86_fld_membase((inst), X86_ESP, 0, 0); \ |
amd64_fld_membase((inst), AMD64_RSP, 0, 0); \ |
495 |
x86_alu_reg_imm((inst), X86_ADD, X86_ESP, 4); \ |
amd64_alu_reg_imm((inst), X86_ADD, AMD64_RSP, 4); \ |
496 |
} while (0) |
} while (0) |
497 |
#define md_reg_to_float_64(inst,reg) \ |
#define md_reg_to_float_64(inst,reg) \ |
498 |
do { \ |
do { \ |
499 |
x86_alu_reg_imm((inst), X86_SUB, X86_ESP, 8); \ |
amd64_alu_reg_imm((inst), X86_SUB, AMD64_RSP, 8); \ |
500 |
x86_fst_membase((inst), X86_ESP, 0, 1, 1); \ |
amd64_fst_membase((inst), AMD64_RSP, 0, 1, 1); \ |
501 |
x86_fld_membase((inst), X86_ESP, 0, 1); \ |
amd64_fld_membase((inst), AMD64_RSP, 0, 1); \ |
502 |
x86_alu_reg_imm((inst), X86_ADD, X86_ESP, 8); \ |
amd64_alu_reg_imm((inst), X86_ADD, AMD64_RSP, 8); \ |
503 |
} while (0) |
} while (0) |
504 |
|
|
505 |
/* |
/* |
506 |
* Swap the top two items on the floating-point stack. |
* Swap the top two items on the floating-point stack. |
507 |
*/ |
*/ |
508 |
#define md_freg_swap(inst) x86_fxch((inst), 1) |
#define md_freg_swap(inst) amd64_fxch((inst), 1) |
509 |
|
|
510 |
/* |
/* |
511 |
* Jump back into the CVM interpreter to execute the instruction |
* Jump back into the CVM interpreter to execute the instruction |
625 |
* the condition codes based on the result. |
* the condition codes based on the result. |
626 |
*/ |
*/ |
627 |
#define md_cmp_reg_imm_word_32(inst,cond,reg,imm) \ |
#define md_cmp_reg_imm_word_32(inst,cond,reg,imm) \ |
628 |
x86_alu_reg_imm((inst), X86_CMP, (reg), (int)(imm)) |
amd64_alu_reg_imm_size((inst), X86_CMP, (reg), (int)(imm), 4) |
629 |
|
|
630 |
/* |
/* |
631 |
* Output a branch to a location based on a condition. The actual |
* Output a branch to a location based on a condition. The actual |