Author: leo
Date: Tue Jan 10 11:33:10 2006
New Revision: 11051
Modified:
trunk/src/jit/i386/jit_emit.h
Log:
Math - Divide by zero #3
* throw exception for JIT/i386 div Ix, 0
* TODO JIT, PMCs
Modified: trunk/src/jit/i386/jit_emit.h
==============================================================================
--- trunk/src/jit/i386/jit_emit.h (original)
+++ trunk/src/jit/i386/jit_emit.h Tue Jan 10 11:33:10 2006
@@ -15,6 +15,7 @@
# define JIT_CGP
#endif
+static void call_func(Parrot_jit_info_t *jit_info, void *addr);
/*
* get the register frame pointer
*/
@@ -28,6 +29,13 @@
# define Parrot_jit_emit_get_INTERP(pc, dest) \
emitm_movl_m_r(pc, dest, emit_EBP, emit_None, 1, INTERP_BP_OFFS)
+/* see jit_begin */
+# ifdef JIT_CGP
+# define INTERP_BP_OFFS todo
+# else
+# define INTERP_BP_OFFS -16
+# endif
+
/*
* if we have a delegated method like typeof_i_p, that returns an INTVAL
* and that is all in a sequence of JITted opcodes, and when these INTVAL
@@ -574,197 +582,8 @@ emit_movb_i_m(char *pc, char imm, int ba
# define jit_emit_cdq(pc) *(pc)++ = 0x99
-/* dest /= src
- * edx:eax /= src, quotient => eax, rem => edx
- */
-static char *
-opt_div_rr(Parrot_jit_info_t *jit_info, int dest, int src, int is_div)
-{
- char *pc = jit_info->native_ptr;
- int saved = 0;
- int div_ecx = 0;
- Parrot_jit_register_usage_t *ru;
-
- assert(src != emit_EAX);
-
- if (dest != emit_EAX) {
- jit_emit_mov_rr_i(pc, emit_EAX, dest);
- }
- if (dest == emit_EDX) {
- /* all ok, we can globber it */
- }
- else {
- ru = jit_info->optimizer->cur_section->ru + 0;
- /* if ECX is not mapped use it */
- if (ru->registers_used < INT_REGISTERS_TO_MAP && src == emit_EDX) {
- jit_emit_mov_rr_i(pc, emit_ECX, emit_EDX);
- div_ecx = 1;
- }
- else
- /* if EDX is mapped, preserve EDX on stack */
- if (ru->registers_used >= INT_REGISTERS_TO_MAP - 1) {
- emitm_pushl_r(pc, emit_EDX);
- saved = 1;
- /* if EDX is the src, we need another temp register: ECX */
- if (src == emit_EDX) {
- /* if ECX is mapped save it, but not if it's dest */
- if (ru->registers_used == INT_REGISTERS_TO_MAP &&
- dest != emit_ECX) {
- emitm_pushl_r(pc, emit_ECX);
- saved = 2;
- }
- /* else just use it */
- jit_emit_mov_rr_i(pc, emit_ECX, emit_EDX);
- div_ecx = 1;
- }
- }
- }
-# if 0
- jit_emit_cdq(pc);
-# else
- /* this sequence allows 2 other instructions to run parallel */
- if (dest != emit_EDX) {
- jit_emit_mov_rr_i(pc, emit_EDX, emit_EAX);
- }
- pc = emit_shift_i_r(pc, emit_b111, 31, emit_EDX); /* SAR 31 */
-# endif
- if (div_ecx) {
- emitm_sdivl_r(pc, emit_ECX);
- }
- else {
- emitm_sdivl_r(pc, src);
- }
- if (saved == 2) {
- emitm_popl_r(pc, emit_ECX);
- }
- if (is_div) {
- /* result = quotient in EAX */
- if (saved) {
- emitm_popl_r(pc, emit_EDX);
- }
- if (dest != emit_EAX) {
- jit_emit_mov_rr_i(pc, dest, emit_EAX);
- }
- }
- else {
- /* result = remainder in EDX */
- if (saved) {
- emitm_popl_r(pc, emit_EAX);
- jit_emit_mov_rr_i(pc, dest, emit_EDX);
- jit_emit_mov_rr_i(pc, emit_EDX, emit_EAX);
- }
- else {
- if (dest != emit_EDX)
- jit_emit_mov_rr_i(pc, dest, emit_EDX);
- }
- }
- if (!saved && div_ecx) {
- /* restore EDX */
- jit_emit_mov_rr_i(pc, emit_EDX, emit_ECX);
- }
- return pc;
-}
-
-# define jit_emit_div_rr_i(pc, r1, r2) pc = opt_div_rr(jit_info, r1, r2, 1)
-# define jit_emit_cmod_rr_i(pc, r1, r2) pc = opt_div_rr(jit_info, r1, r2, 0)
-
-
-static char *
-opt_div_ri(Parrot_jit_info_t *jit_info, int dest, INTVAL imm, int is_div)
-{
- char *pc = jit_info->native_ptr;
-
- UINTVAL ld2 = ld((UINTVAL) imm);
- if (is_div && imm > 1 && !(imm & (imm - 1))) {
- /* positive power of 2 - do a shift */
- pc = emit_shift_i_r(pc, emit_b101, ld2, dest);
- }
- else {
- if (dest != emit_EBX) {
- emitm_pushl_r(pc, emit_EBX);
- jit_emit_mov_ri_i(pc, emit_EBX, imm);
- jit_info->native_ptr = pc;
- pc = opt_div_rr(jit_info, dest, emit_EBX, is_div);
- pc = emit_popl_r(pc, emit_EBX);
- }
- else {
- emitm_pushl_r(pc, emit_EDI);
- jit_emit_mov_ri_i(pc, emit_EDI, imm);
- jit_info->native_ptr = pc;
- pc = opt_div_rr(jit_info, dest, emit_EDI, is_div);
- pc = emit_popl_r(pc, emit_EDI);
- }
- }
- return pc;
-}
-
-# define jit_emit_div_ri_i(pc, r1, imm) pc = opt_div_ri(jit_info, r1, imm, 1)
-# define jit_emit_cmod_ri_i(pc, r1, imm) pc = opt_div_ri(jit_info, r1, imm, 0)
-
-static char *
-opt_div_RM(Parrot_jit_info_t *jit_info, int dest, int offs, int is_div)
-{
- char *pc = jit_info->native_ptr;
- int saved = 0;
- extern char **Parrot_exec_rel_addr;
- extern int Parrot_exec_rel_count;
-
- if (dest != emit_EAX) {
- jit_emit_mov_rr_i(pc, emit_EAX, dest);
- }
- if (dest == emit_EDX) {
- /* all ok, we can globber it */
- }
- else {
- /* if ECX is mapped, push EDX on stack */
- if (jit_info->optimizer->cur_section->ru[0].registers_used ==
- INT_REGISTERS_TO_MAP) {
- emitm_pushl_r(pc, emit_EDX);
- saved = 2;
- }
- /* if EDX is mapped, save it in ECX */
- else if (jit_info->optimizer->cur_section->ru[0].registers_used ==
- INT_REGISTERS_TO_MAP - 1) {
- saved = 1;
- jit_emit_mov_rr_i(pc, emit_ECX, emit_EDX);
- }
- }
-# if 0
- jit_emit_cdq(pc);
-# else
- /* this sequence allows 2 other instructions to run parallel */
- jit_emit_mov_rr_i(pc, emit_EDX, emit_EAX);
- pc = emit_shift_i_r(pc, emit_b111, 31, emit_EDX); /* SAR 31 */
-# endif
- emitm_sdivl_m(pc, emit_EBX, 0, 1, offs);
-
- if (is_div) {
- /* result = quotient in EAX */
- if (saved == 1) {
- jit_emit_mov_rr_i(pc, emit_EDX, emit_ECX);
- }
- if (dest != emit_EAX) {
- jit_emit_mov_rr_i(pc, dest, emit_EAX);
- }
- if (saved == 2) {
- emitm_popl_r(pc, emit_EDX);
- }
- }
- else {
- /* result = remainder in EDX */
- if (dest != emit_EDX) {
- jit_emit_mov_rr_i(pc, dest, emit_EDX);
- if (saved == 1) {
- jit_emit_mov_rr_i(pc, emit_EDX, emit_ECX);
- }
- else if (saved == 2)
- emitm_popl_r(pc, emit_EDX);
- }
- }
- return pc;
-}
-# define jit_emit_div_RM_i(pc, r, m) pc = opt_div_RM(jit_info, r, m, 1)
-# define jit_emit_cmod_RM_i(pc, r, m) pc = opt_div_RM(jit_info, r, m, 0)
+/* TEST for zero */
+# define jit_emit_test_r_i(pc, reg1) emitm_alul_r_r(pc, 0x85, reg1, reg1)
# define emitm_smull_r(pc, reg2) emitm_alu_imp_r((pc), emit_b101, (reg2))
@@ -868,9 +687,6 @@ opt_mul(char *pc, int dest, INTVAL imm,
# define emitm_andl_i_m(pc, imm, b, i, s, d) \
emitm_alul_i_m(pc, 0x81, emit_b100, imm, b, i, s, d)
-/* TEST for zero */
-# define jit_emit_test_r_i(pc, reg1) emitm_alul_r_r(pc, 0x85, reg1, reg1)
-
/* TEST op */
# define jit_emit_test_rr_i(pc, r1, r2) emitm_alul_r_r(pc, 0x85, r1, r2)
@@ -1907,6 +1723,225 @@ static unsigned char *lastpc;
# define jit_emit_bxor_MI_i(pc, offs, imm) \
emitm_xorl_i_m(pc, imm, emit_EBX, emit_None, 1, offs)
+/* dest /= src
+ * edx:eax /= src, quotient => eax, rem => edx
+ */
+static char *
+opt_div_rr(Parrot_jit_info_t *jit_info, int dest, int src, int is_div)
+{
+ char *pc = jit_info->native_ptr;
+ int saved = 0;
+ int div_ecx = 0;
+ Parrot_jit_register_usage_t *ru;
+ char *L1, *L2, *L3;
+ static const char* div_by_zero = "Divide by zero";
+
+ assert(src != emit_EAX);
+
+ if (dest != emit_EAX) {
+ jit_emit_mov_rr_i(pc, emit_EAX, dest);
+ }
+ if (dest == emit_EDX) {
+ /* all ok, we can globber it */
+ }
+ else {
+ ru = jit_info->optimizer->cur_section->ru + 0;
+ /* if ECX is not mapped use it */
+ if (ru->registers_used < INT_REGISTERS_TO_MAP && src == emit_EDX) {
+ jit_emit_mov_rr_i(pc, emit_ECX, emit_EDX);
+ div_ecx = 1;
+ }
+ else
+ /* if EDX is mapped, preserve EDX on stack */
+ if (ru->registers_used >= INT_REGISTERS_TO_MAP - 1) {
+ emitm_pushl_r(pc, emit_EDX);
+ saved = 1;
+ /* if EDX is the src, we need another temp register: ECX */
+ if (src == emit_EDX) {
+ /* if ECX is mapped save it, but not if it's dest */
+ if (ru->registers_used == INT_REGISTERS_TO_MAP &&
+ dest != emit_ECX) {
+ emitm_pushl_r(pc, emit_ECX);
+ saved = 2;
+ }
+ /* else just use it */
+ jit_emit_mov_rr_i(pc, emit_ECX, emit_EDX);
+ div_ecx = 1;
+ }
+ }
+ }
+# if 0
+ jit_emit_cdq(pc);
+# else
+ /* this sequence allows 2 other instructions to run parallel */
+ if (dest != emit_EDX) {
+ jit_emit_mov_rr_i(pc, emit_EDX, emit_EAX);
+ }
+ pc = emit_shift_i_r(pc, emit_b111, 31, emit_EDX); /* SAR 31 */
+# endif
+ if (div_ecx) {
+ jit_emit_test_r_i(pc, emit_ECX);
+ L1 = pc;
+ emitm_jxs(pc, emitm_jz, 0);
+ emitm_sdivl_r(pc, emit_ECX);
+ L3 = pc;
+ emitm_jumps(pc, 0);
+ /* L1: */
+ L1[1] = pc - L1 - 2;
+ }
+ else {
+ jit_emit_test_r_i(pc, src);
+ L2 = pc;
+ emitm_jxs(pc, emitm_jz, 0);
+ emitm_sdivl_r(pc, src);
+ L3 = pc;
+ emitm_jumps(pc, 0);
+ /* L2: */
+ L2[1] = pc - L2 - 2;
+ }
+ /* TODO real_exception */
+ emitm_pushl_i(pc, div_by_zero);
+ emitm_pushl_i(pc, E_ZeroDivisionError);
+ emitm_pushl_i(pc, 0); /* NULL */
+ Parrot_jit_emit_get_INTERP(pc, emit_ECX);
+ emitm_pushl_r(pc, emit_ECX);
+ jit_info->native_ptr = pc;
+ call_func(jit_info, (void*) real_exception);
+ pc = jit_info->native_ptr;
+ /* L3: */
+ L3[1] = pc - L3 - 2;
+ if (saved == 2) {
+ emitm_popl_r(pc, emit_ECX);
+ }
+ if (is_div) {
+ /* result = quotient in EAX */
+ if (saved) {
+ emitm_popl_r(pc, emit_EDX);
+ }
+ if (dest != emit_EAX) {
+ jit_emit_mov_rr_i(pc, dest, emit_EAX);
+ }
+ }
+ else {
+ /* result = remainder in EDX */
+ if (saved) {
+ emitm_popl_r(pc, emit_EAX);
+ jit_emit_mov_rr_i(pc, dest, emit_EDX);
+ jit_emit_mov_rr_i(pc, emit_EDX, emit_EAX);
+ }
+ else {
+ if (dest != emit_EDX)
+ jit_emit_mov_rr_i(pc, dest, emit_EDX);
+ }
+ }
+ if (!saved && div_ecx) {
+ /* restore EDX */
+ jit_emit_mov_rr_i(pc, emit_EDX, emit_ECX);
+ }
+ return pc;
+}
+
+# define jit_emit_div_rr_i(pc, r1, r2) pc = opt_div_rr(jit_info, r1, r2, 1)
+# define jit_emit_cmod_rr_i(pc, r1, r2) pc = opt_div_rr(jit_info, r1, r2, 0)
+
+
+static char *
+opt_div_ri(Parrot_jit_info_t *jit_info, int dest, INTVAL imm, int is_div)
+{
+ char *pc = jit_info->native_ptr;
+
+ UINTVAL ld2 = ld((UINTVAL) imm);
+ if (is_div && imm > 1 && !(imm & (imm - 1))) {
+ /* positive power of 2 - do a shift */
+ pc = emit_shift_i_r(pc, emit_b101, ld2, dest);
+ }
+ else {
+ if (dest != emit_EBX) {
+ emitm_pushl_r(pc, emit_EBX);
+ jit_emit_mov_ri_i(pc, emit_EBX, imm);
+ jit_info->native_ptr = pc;
+ pc = opt_div_rr(jit_info, dest, emit_EBX, is_div);
+ pc = emit_popl_r(pc, emit_EBX);
+ }
+ else {
+ emitm_pushl_r(pc, emit_EDI);
+ jit_emit_mov_ri_i(pc, emit_EDI, imm);
+ jit_info->native_ptr = pc;
+ pc = opt_div_rr(jit_info, dest, emit_EDI, is_div);
+ pc = emit_popl_r(pc, emit_EDI);
+ }
+ }
+ return pc;
+}
+
+# define jit_emit_div_ri_i(pc, r1, imm) pc = opt_div_ri(jit_info, r1, imm, 1)
+# define jit_emit_cmod_ri_i(pc, r1, imm) pc = opt_div_ri(jit_info, r1, imm, 0)
+
+static char *
+opt_div_RM(Parrot_jit_info_t *jit_info, int dest, int offs, int is_div)
+{
+ char *pc = jit_info->native_ptr;
+ int saved = 0;
+ extern char **Parrot_exec_rel_addr;
+ extern int Parrot_exec_rel_count;
+
+ if (dest != emit_EAX) {
+ jit_emit_mov_rr_i(pc, emit_EAX, dest);
+ }
+ if (dest == emit_EDX) {
+ /* all ok, we can globber it */
+ }
+ else {
+ /* if ECX is mapped, push EDX on stack */
+ if (jit_info->optimizer->cur_section->ru[0].registers_used ==
+ INT_REGISTERS_TO_MAP) {
+ emitm_pushl_r(pc, emit_EDX);
+ saved = 2;
+ }
+ /* if EDX is mapped, save it in ECX */
+ else if (jit_info->optimizer->cur_section->ru[0].registers_used ==
+ INT_REGISTERS_TO_MAP - 1) {
+ saved = 1;
+ jit_emit_mov_rr_i(pc, emit_ECX, emit_EDX);
+ }
+ }
+# if 0
+ jit_emit_cdq(pc);
+# else
+ /* this sequence allows 2 other instructions to run parallel */
+ jit_emit_mov_rr_i(pc, emit_EDX, emit_EAX);
+ pc = emit_shift_i_r(pc, emit_b111, 31, emit_EDX); /* SAR 31 */
+# endif
+ emitm_sdivl_m(pc, emit_EBX, 0, 1, offs);
+
+ if (is_div) {
+ /* result = quotient in EAX */
+ if (saved == 1) {
+ jit_emit_mov_rr_i(pc, emit_EDX, emit_ECX);
+ }
+ if (dest != emit_EAX) {
+ jit_emit_mov_rr_i(pc, dest, emit_EAX);
+ }
+ if (saved == 2) {
+ emitm_popl_r(pc, emit_EDX);
+ }
+ }
+ else {
+ /* result = remainder in EDX */
+ if (dest != emit_EDX) {
+ jit_emit_mov_rr_i(pc, dest, emit_EDX);
+ if (saved == 1) {
+ jit_emit_mov_rr_i(pc, emit_EDX, emit_ECX);
+ }
+ else if (saved == 2)
+ emitm_popl_r(pc, emit_EDX);
+ }
+ }
+ return pc;
+}
+# define jit_emit_div_RM_i(pc, r, m) pc = opt_div_RM(jit_info, r, m, 1)
+# define jit_emit_cmod_RM_i(pc, r, m) pc = opt_div_RM(jit_info, r, m, 0)
+
enum { JIT_X86BRANCH, JIT_X86JUMP, JIT_X86CALL };
static void
@@ -1981,13 +2016,6 @@ emit_jump(Parrot_jit_info_t *jit_info, o
emitm_jumpl(jit_info->native_ptr, 0xc0def00d);
}
-/* see jit_begin */
-# ifdef JIT_CGP
-# define INTERP_BP_OFFS todo
-# else
-# define INTERP_BP_OFFS -16
-# endif
-
static void
Parrot_emit_jump_to_eax(Parrot_jit_info_t *jit_info,
Interp * interpreter)
@@ -2057,7 +2085,6 @@ Parrot_emit_jump_to_eax(Parrot_jit_info_
emitm_popl_r(pc, emit_EBP); \
} while(0)
-static void call_func(Parrot_jit_info_t *jit_info, void *addr);
static void call_func(Parrot_jit_info_t *jit_info, void *addr)