31 |
#define MIPS_DEBUG_DISAS |
#define MIPS_DEBUG_DISAS |
32 |
//#define MIPS_SINGLE_STEP |
//#define MIPS_SINGLE_STEP |
33 |
|
|
34 |
|
#ifdef USE_DIRECT_JUMP |
35 |
|
#define TBPARAM(x) |
36 |
|
#else |
37 |
|
#define TBPARAM(x) (long)(x) |
38 |
|
#endif |
39 |
|
|
40 |
enum { |
enum { |
41 |
#define DEF(s, n, copy_size) INDEX_op_ ## s, |
#define DEF(s, n, copy_size) INDEX_op_ ## s, |
42 |
#include "opc.h" |
#include "opc.h" |
928 |
ctx->bstate = BS_STOP; |
ctx->bstate = BS_STOP; |
929 |
} |
} |
930 |
|
|
931 |
|
static inline void gen_jmp_tb(long tb, int n, uint32_t dest) |
932 |
|
{ |
933 |
|
if (n == 0) |
934 |
|
gen_op_goto_tb0(TBPARAM(tb)); |
935 |
|
else |
936 |
|
gen_op_goto_tb1(TBPARAM(tb)); |
937 |
|
gen_op_save_pc(dest); |
938 |
|
gen_op_set_T0(tb + n); |
939 |
|
gen_op_exit_tb(); |
940 |
|
} |
941 |
|
|
942 |
/* Branches (before delay slot) */ |
/* Branches (before delay slot) */ |
943 |
static void gen_compute_branch (DisasContext *ctx, uint16_t opc, |
static void gen_compute_branch (DisasContext *ctx, uint16_t opc, |
944 |
int rs, int rt, int32_t offset) |
int rs, int rt, int32_t offset) |
1035 |
case OPC_BLTZL: /* 0 < 0 likely */ |
case OPC_BLTZL: /* 0 < 0 likely */ |
1036 |
/* Skip the instruction in the delay slot */ |
/* Skip the instruction in the delay slot */ |
1037 |
MIPS_DEBUG("bnever and skip"); |
MIPS_DEBUG("bnever and skip"); |
1038 |
gen_op_branch((long)ctx->tb, ctx->pc + 4); |
gen_jmp_tb((long)ctx->tb, 0, ctx->pc + 4); |
1039 |
return; |
return; |
1040 |
case OPC_J: |
case OPC_J: |
1041 |
ctx->hflags |= MIPS_HFLAG_DS | MIPS_HFLAG_B; |
ctx->hflags |= MIPS_HFLAG_DS | MIPS_HFLAG_B; |
1272 |
|
|
1273 |
#endif |
#endif |
1274 |
|
|
1275 |
|
static void gen_blikely(DisasContext *ctx) |
1276 |
|
{ |
1277 |
|
int l1; |
1278 |
|
l1 = gen_new_label(); |
1279 |
|
gen_op_jnz_T2(l1); |
1280 |
|
gen_op_save_state(ctx->hflags & ~(MIPS_HFLAG_BMASK | MIPS_HFLAG_DS)); |
1281 |
|
gen_jmp_tb((long)ctx->tb, 1, ctx->pc + 4); |
1282 |
|
} |
1283 |
|
|
1284 |
static void decode_opc (DisasContext *ctx) |
static void decode_opc (DisasContext *ctx) |
1285 |
{ |
{ |
1286 |
int32_t offset; |
int32_t offset; |
1292 |
(ctx->hflags & MIPS_HFLAG_BL)) { |
(ctx->hflags & MIPS_HFLAG_BL)) { |
1293 |
/* Handle blikely not taken case */ |
/* Handle blikely not taken case */ |
1294 |
MIPS_DEBUG("blikely condition (%08x)", ctx->pc + 4); |
MIPS_DEBUG("blikely condition (%08x)", ctx->pc + 4); |
1295 |
gen_op_blikely((long)ctx->tb, ctx->pc + 4, |
gen_blikely(ctx); |
|
ctx->hflags & ~(MIPS_HFLAG_BMASK | MIPS_HFLAG_DS)); |
|
1296 |
} |
} |
1297 |
op = ctx->opcode >> 26; |
op = ctx->opcode >> 26; |
1298 |
rs = ((ctx->opcode >> 21) & 0x1F); |
rs = ((ctx->opcode >> 21) & 0x1F); |
1502 |
case MIPS_HFLAG_B: |
case MIPS_HFLAG_B: |
1503 |
/* unconditional branch */ |
/* unconditional branch */ |
1504 |
MIPS_DEBUG("unconditional branch"); |
MIPS_DEBUG("unconditional branch"); |
1505 |
gen_op_branch((long)ctx->tb, ctx->btarget); |
gen_jmp_tb((long)ctx->tb, 0, ctx->btarget); |
1506 |
break; |
break; |
1507 |
case MIPS_HFLAG_BL: |
case MIPS_HFLAG_BL: |
1508 |
/* blikely taken case */ |
/* blikely taken case */ |
1509 |
MIPS_DEBUG("blikely branch taken"); |
MIPS_DEBUG("blikely branch taken"); |
1510 |
gen_op_branch((long)ctx->tb, ctx->btarget); |
gen_jmp_tb((long)ctx->tb, 0, ctx->btarget); |
1511 |
break; |
break; |
1512 |
case MIPS_HFLAG_BC: |
case MIPS_HFLAG_BC: |
1513 |
/* Conditional branch */ |
/* Conditional branch */ |
1514 |
MIPS_DEBUG("conditional branch"); |
MIPS_DEBUG("conditional branch"); |
1515 |
gen_op_bcond((long)ctx->tb, ctx->btarget, ctx->pc + 4); |
{ |
1516 |
|
int l1; |
1517 |
|
l1 = gen_new_label(); |
1518 |
|
gen_op_jnz_T2(l1); |
1519 |
|
gen_jmp_tb((long)ctx->tb, 0, ctx->btarget); |
1520 |
|
gen_set_label(l1); |
1521 |
|
gen_jmp_tb((long)ctx->tb, 1, ctx->pc + 4); |
1522 |
|
} |
1523 |
break; |
break; |
1524 |
case MIPS_HFLAG_BR: |
case MIPS_HFLAG_BR: |
1525 |
/* unconditional branch to register */ |
/* unconditional branch to register */ |
1545 |
gen_opc_ptr = gen_opc_buf; |
gen_opc_ptr = gen_opc_buf; |
1546 |
gen_opc_end = gen_opc_buf + OPC_MAX_SIZE; |
gen_opc_end = gen_opc_buf + OPC_MAX_SIZE; |
1547 |
gen_opparam_ptr = gen_opparam_buf; |
gen_opparam_ptr = gen_opparam_buf; |
1548 |
|
nb_gen_labels = 0; |
1549 |
ctx.pc = pc_start; |
ctx.pc = pc_start; |
1550 |
ctx.tb = tb; |
ctx.tb = tb; |
1551 |
ctx.bstate = BS_NONE; |
ctx.bstate = BS_NONE; |
1603 |
} |
} |
1604 |
if (ctx.bstate != BS_BRANCH && ctx.bstate != BS_EXCP) { |
if (ctx.bstate != BS_BRANCH && ctx.bstate != BS_EXCP) { |
1605 |
save_cpu_state(ctxp, 0); |
save_cpu_state(ctxp, 0); |
1606 |
gen_op_branch((long)ctx.tb, ctx.pc); |
gen_jmp_tb((long)ctx.tb, 0, ctx.pc); |
1607 |
} |
} |
1608 |
gen_op_reset_T0(); |
gen_op_reset_T0(); |
1609 |
/* Generate the return instruction */ |
/* Generate the return instruction */ |