X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=cpu%2Fdrc%2Femit_arm.c;h=eb5f332ea048f4957acce34d154f42a3399555d2;hb=98a3d79ba2d05e8883f8e3761f866cb4fa17c214;hp=06483eac84a7c5e31c54195f372fb24d79dc86ab;hpb=a2b8c5a54568093b247ced39f0754cbb30324830;p=picodrive.git diff --git a/cpu/drc/emit_arm.c b/cpu/drc/emit_arm.c index 06483ea..eb5f332 100644 --- a/cpu/drc/emit_arm.c +++ b/cpu/drc/emit_arm.c @@ -1,8 +1,10 @@ -// Basic macros to emit ARM instructions and some utils - -// (c) Copyright 2008-2009, Grazvydas "notaz" Ignotas -// Free for non-commercial use. - +/* + * Basic macros to emit ARM instructions and some utils + * Copyright (C) 2008,2009,2010 notaz + * + * This work is licensed under the terms of MAME license. + * See COPYING file in the top-level directory. + */ #define CONTEXT_REG 11 // XXX: tcache_ptr type for SVP and SH2 compilers differs.. @@ -23,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) @@ -240,6 +243,11 @@ #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) @@ -254,6 +262,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: @@ -360,6 +381,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) @@ -375,6 +399,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) @@ -382,7 +409,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) @@ -630,6 +657,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) @@ -705,21 +747,17 @@ 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)); \ + emith_move_r_r(2, CONTEXT_REG); \ emith_jump_reg(12); \ }