drc: support ms ABI
[picodrive.git] / cpu / drc / emit_arm.c
index 64face1..91b4740 100644 (file)
@@ -6,6 +6,7 @@
  * See COPYING file in the top-level directory.
  */
 #define CONTEXT_REG 11
+#define RET_REG     0
 
 // XXX: tcache_ptr type for SVP and SH2 compilers differs..
 #define EMIT_PTR(ptr, x) \
 #define EOP_MSR_IMM(ror2,imm) EOP_C_MSR_IMM(A_COND_AL,ror2,imm)
 #define EOP_MSR_REG(rm)       EOP_C_MSR_REG(A_COND_AL,rm)
 
+#define EOP_MOVW(rd,imm) \
+       EMIT(0xe3000000 | ((rd)<<12) | ((imm)&0xfff) | (((imm)<<4)&0xf0000))
+
+#define EOP_MOVT(rd,imm) \
+       EMIT(0xe3400000 | ((rd)<<12) | (((imm)>>16)&0xfff) | (((imm)>>12)&0xf0000))
 
 // XXX: AND, RSB, *C, will break if 1 insn is not enough
 static void emith_op_imm2(int cond, int s, int op, int rd, int rn, unsigned int imm)
@@ -257,6 +263,19 @@ static void emith_op_imm2(int cond, int s, int op, int rd, int rn, unsigned int
                        imm = ~imm;
                        op = A_OP_MVN;
                }
+#ifdef HAVE_ARMV7
+               for (v = imm, ror2 = 0; v && !(v & 3); v >>= 2)
+                       ror2--;
+               if (v >> 8) {
+                       /* 2+ insns needed - prefer movw/movt */
+                       if (op == A_OP_MVN)
+                               imm = ~imm;
+                       EOP_MOVW(rd, imm);
+                       if (imm & 0xffff0000)
+                               EOP_MOVT(rd, imm);
+                       return;
+               }
+#endif
                break;
 
        case A_OP_EOR:
@@ -351,6 +370,9 @@ static int emith_xbranch(int cond, void *target, int is_call)
 #define EMITH_NOTHING1(cond) \
        (void)(cond)
 
+#define EMITH_SJMP_DECL_()
+#define EMITH_SJMP_START_(cond)        EMITH_NOTHING1(cond)
+#define EMITH_SJMP_END_(cond)  EMITH_NOTHING1(cond)
 #define EMITH_SJMP_START(cond) EMITH_NOTHING1(cond)
 #define EMITH_SJMP_END(cond)   EMITH_NOTHING1(cond)
 #define EMITH_SJMP3_START(cond)        EMITH_NOTHING1(cond)
@@ -360,6 +382,9 @@ static int emith_xbranch(int cond, void *target, int is_call)
 #define emith_move_r_r(d, s) \
        EOP_MOV_REG_SIMPLE(d, s)
 
+#define emith_move_r_r_ptr(d, s) \
+       emith_move_r_r(d, s)
+
 #define emith_mvn_r_r(d, s) \
        EOP_MVN_REG(A_COND_AL,0,d,s,A_AM1_LSL,0)
 
@@ -411,6 +436,9 @@ static int emith_xbranch(int cond, void *target, int is_call)
 #define emith_tst_r_r(d, s) \
        EOP_TST_REG(A_COND_AL,d,s,A_AM1_LSL,0)
 
+#define emith_tst_r_r_ptr(d, s) \
+       emith_tst_r_r(d, s)
+
 #define emith_teq_r_r(d, s) \
        EOP_TEQ_REG(A_COND_AL,d,s,A_AM1_LSL,0)
 
@@ -503,6 +531,9 @@ static int emith_xbranch(int cond, void *target, int is_call)
 #define emith_add_r_r_imm(d, s, imm) \
        emith_op_imm2(A_COND_AL, 0, A_OP_ADD, d, s, imm)
 
+#define emith_add_r_r_ptr_imm(d, s, imm) \
+       emith_add_r_r_imm(d, s, imm)
+
 #define emith_sub_r_r_imm(d, s, imm) \
        emith_op_imm2(A_COND_AL, 0, A_OP_SUB, d, s, imm)
 
@@ -593,6 +624,9 @@ static int emith_xbranch(int cond, void *target, int is_call)
 #define emith_ctx_read(r, offs) \
        emith_read_r_r_offs(r, CONTEXT_REG, offs)
 
+#define emith_ctx_read_ptr(r, offs) \
+       emith_ctx_read(r, offs)
+
 #define emith_ctx_write(r, offs) \
        EOP_STR_IMM(r, CONTEXT_REG, offs)