drc: debug improvements
[picodrive.git] / cpu / drc / emit_arm.c
index 53c235f..2ac8e32 100644 (file)
@@ -25,6 +25,7 @@
 #define A_R9M  (1 << 9)
 #define A_R10M (1 << 10)
 #define A_R11M (1 << 11)
+#define A_R12M (1 << 12)
 #define A_R14M (1 << 14)
 #define A_R15M (1 << 15)
 
@@ -362,6 +363,9 @@ static int emith_xbranch(int cond, void *target, int is_call)
 #define emith_mvn_r_r(d, s) \
        EOP_MVN_REG(A_COND_AL,0,d,s,A_AM1_LSL,0)
 
+#define emith_add_r_r_r_lsl(d, s1, s2, lslimm) \
+       EOP_ADD_REG(A_COND_AL,0,d,s1,s2,A_AM1_LSL,lslimm)
+
 #define emith_or_r_r_r_lsl(d, s1, s2, lslimm) \
        EOP_ORR_REG(A_COND_AL,0,d,s1,s2,A_AM1_LSL,lslimm)
 
@@ -377,6 +381,9 @@ static int emith_xbranch(int cond, void *target, int is_call)
 #define emith_eor_r_r_lsr(d, s, lsrimm) \
        emith_eor_r_r_r_lsr(d, d, s, lsrimm)
 
+#define emith_add_r_r_r(d, s1, s2) \
+       emith_add_r_r_r_lsl(d, s1, s2, 0)
+
 #define emith_or_r_r_r(d, s1, s2) \
        emith_or_r_r_r_lsl(d, s1, s2, 0)
 
@@ -384,7 +391,7 @@ static int emith_xbranch(int cond, void *target, int is_call)
        emith_eor_r_r_r_lsl(d, s1, s2, 0)
 
 #define emith_add_r_r(d, s) \
-       EOP_ADD_REG(A_COND_AL,0,d,d,s,A_AM1_LSL,0)
+       emith_add_r_r_r(d, d, s)
 
 #define emith_sub_r_r(d, s) \
        EOP_SUB_REG(A_COND_AL,0,d,d,s,A_AM1_LSL,0)
@@ -632,6 +639,21 @@ static int emith_xbranch(int cond, void *target, int is_call)
        EOP_MOV_REG_ASR(d,d,32 - (bits)); \
 }
 
+#define emith_do_caller_regs(mask, func) { \
+       u32 _reg_mask = (mask) & 0x500f; \
+       if (_reg_mask) { \
+               if (__builtin_parity(_reg_mask) == 1) \
+                       _reg_mask |= 0x10; /* eabi align */ \
+               func(_reg_mask); \
+       } \
+}
+
+#define emith_save_caller_regs(mask) \
+       emith_do_caller_regs(mask, EOP_STMFD_SP)
+
+#define emith_restore_caller_regs(mask) \
+       emith_do_caller_regs(mask, EOP_LDMFD_SP)
+
 // upto 4 args
 #define emith_pass_arg_r(arg, reg) \
        EOP_MOV_REG_SIMPLE(arg, reg)
@@ -707,18 +729,14 @@ static int emith_xbranch(int cond, void *target, int is_call)
        rd = arg
 
 /* SH2 drc specific */
+/* pushes r12 for eabi alignment */
 #define emith_sh2_drc_entry() \
-       EOP_STMFD_SP(A_R4M|A_R5M|A_R6M|A_R7M|A_R8M|A_R9M|A_R10M|A_R11M|A_R14M)
+       EOP_STMFD_SP(A_R4M|A_R5M|A_R6M|A_R7M|A_R8M|A_R9M|A_R10M|A_R11M|A_R12M|A_R14M)
 
 #define emith_sh2_drc_exit() \
-       EOP_LDMFD_SP(A_R4M|A_R5M|A_R6M|A_R7M|A_R8M|A_R9M|A_R10M|A_R11M|A_R15M)
-
-#define emith_sh2_wcall(a, tab, ret_ptr) { \
-       int val_ = (char *)(ret_ptr) - (char *)tcache_ptr - 2*4; \
-       if (val_ >= 0) \
-               emith_add_r_r_imm(14, 15, val_); \
-       else if (val_ < 0) \
-               emith_sub_r_r_imm(14, 15, -val_); \
+       EOP_LDMFD_SP(A_R4M|A_R5M|A_R6M|A_R7M|A_R8M|A_R9M|A_R10M|A_R11M|A_R12M|A_R15M)
+
+#define emith_sh2_wcall(a, tab) { \
        emith_lsr(12, a, SH2_WRITE_SHIFT); \
        EOP_LDR_REG_LSL(A_COND_AL,12,tab,12,2); \
        emith_ctx_read(2, offsetof(SH2, is_slave)); \