X-Git-Url: http://vcs.maemo.org/git/?a=blobdiff_plain;f=target-ppc%2Ftranslate.c;h=e09e9a7fd1bee7d3b04553f2f339be0b4fdc6509;hb=6d463de2b3e261e95f224767605eef02acbd2701;hp=f6df06b5bfdf82101874d48518f023ad9dcee9d7;hpb=297d8e6227ff1186857b17b1890fc94c637733da;p=qemu diff --git a/target-ppc/translate.c b/target-ppc/translate.c index f6df06b..e09e9a7 100644 --- a/target-ppc/translate.c +++ b/target-ppc/translate.c @@ -17,14 +17,18 @@ * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "dyngen-exec.h" +#include +#include +#include +#include +#include + #include "cpu.h" -#include "exec.h" +#include "exec-all.h" #include "disas.h" //#define DO_SINGLE_STEP -//#define DO_STEP_FLUSH -//#define DEBUG_DISAS +//#define PPC_DEBUG_DISAS enum { #define DEF(s, n, copy_size) INDEX_op_ ## s, @@ -127,13 +131,9 @@ static uint8_t spr_access[1024 / 2]; /* internal defines */ typedef struct DisasContext { struct TranslationBlock *tb; - uint32_t *nip; + uint32_t nip; uint32_t opcode; uint32_t exception; - /* Time base offset */ - uint32_t tb_offset; - /* Decrementer offset */ - uint32_t decr_offset; /* Execution mode */ #if !defined(CONFIG_USER_ONLY) int supervisor; @@ -151,21 +151,26 @@ typedef struct opc_handler_t { void (*handler)(DisasContext *ctx); } opc_handler_t; -#define RET_EXCP(excp, error) \ +#define RET_EXCP(ctx, excp, error) \ do { \ - gen_op_queue_exception_err(excp, error); \ - ctx->exception = excp; \ - return; \ + if ((ctx)->exception == EXCP_NONE) { \ + gen_op_update_nip((ctx)->nip); \ + } \ + gen_op_raise_exception_err((excp), (error)); \ + ctx->exception = (excp); \ } while (0) -#define RET_INVAL() \ -RET_EXCP(EXCP_PROGRAM, EXCP_INVAL | EXCP_INVAL_INVAL) +#define RET_INVAL(ctx) \ +RET_EXCP((ctx), EXCP_PROGRAM, EXCP_INVAL | EXCP_INVAL_INVAL) + +#define RET_PRIVOPC(ctx) \ +RET_EXCP((ctx), EXCP_PROGRAM, EXCP_INVAL | EXCP_PRIV_OPC) -#define RET_PRIVOPC() \ -RET_EXCP(EXCP_PROGRAM, EXCP_INVAL | EXCP_PRIV_OPC) +#define RET_PRIVREG(ctx) \ +RET_EXCP((ctx), EXCP_PROGRAM, EXCP_INVAL | EXCP_PRIV_REG) -#define RET_PRIVREG() \ -RET_EXCP(EXCP_PROGRAM, EXCP_INVAL | EXCP_PRIV_REG) +#define RET_MTMSR(ctx) \ +RET_EXCP((ctx), EXCP_MTMSR, 0) #define GEN_HANDLER(name, opc1, opc2, opc3, inval, type) \ static void gen_##name (DisasContext *ctx); \ @@ -177,10 +182,6 @@ typedef struct opcode_t { opc_handler_t handler; } opcode_t; -/* XXX: move that elsewhere */ -extern FILE *logfile; -extern int loglevel; - /*** Instruction decoding ***/ #define EXTRACT_HELPER(name, shift, nb) \ static inline uint32_t name (uint32_t opcode) \ @@ -276,7 +277,7 @@ static inline uint32_t MASK (uint32_t start, uint32_t end) } #define GEN_OPCODE(name, op1, op2, op3, invl, _typ) \ -__attribute__ ((section(".opcodes"), unused)) \ +__attribute__ ((section(".opcodes"), unused, aligned (8) )) \ static opcode_t opc_##name = { \ .opc1 = op1, \ .opc2 = op2, \ @@ -289,7 +290,7 @@ static opcode_t opc_##name = { \ } #define GEN_OPCODE_MARK(name) \ -__attribute__ ((section(".opcodes"), unused)) \ +__attribute__ ((section(".opcodes"), unused, aligned (8) )) \ static opcode_t opc_##name = { \ .opc1 = 0xFF, \ .opc2 = 0xFF, \ @@ -307,29 +308,26 @@ GEN_OPCODE_MARK(start); /* Invalid instruction */ GEN_HANDLER(invalid, 0x00, 0x00, 0x00, 0xFFFFFFFF, PPC_NONE) { - RET_INVAL(); + RET_INVAL(ctx); } /* Special opcode to stop emulation */ GEN_HANDLER(stop, 0x06, 0x00, 0xFF, 0x03FFFFC1, PPC_COMMON) { - gen_op_queue_exception(EXCP_HLT); - ctx->exception = EXCP_HLT; + RET_EXCP(ctx, EXCP_HLT, 0); } /* Special opcode to call open-firmware */ GEN_HANDLER(of_enter, 0x06, 0x01, 0xFF, 0x03FFFFC1, PPC_COMMON) { - gen_op_queue_exception(EXCP_OFCALL); - ctx->exception = EXCP_OFCALL; + RET_EXCP(ctx, EXCP_OFCALL, 0); } /* Special opcode to call RTAS */ GEN_HANDLER(rtas_enter, 0x06, 0x02, 0xFF, 0x03FFFFC1, PPC_COMMON) { printf("RTAS entry point !\n"); - gen_op_queue_exception(EXCP_RTASCALL); - ctx->exception = EXCP_RTASCALL; + RET_EXCP(ctx, EXCP_RTASCALL, 0); } static opc_handler_t invalid_handler = { @@ -639,7 +637,7 @@ GEN_HANDLER(xori, 0x1A, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) } gen_op_load_gpr_T0(rS(ctx->opcode)); if (uimm != 0) - gen_op_xori(UIMM(ctx->opcode)); + gen_op_xori(uimm); gen_op_store_T0_gpr(rA(ctx->opcode)); } @@ -654,7 +652,7 @@ GEN_HANDLER(xoris, 0x1B, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) } gen_op_load_gpr_T0(rS(ctx->opcode)); if (uimm != 0) - gen_op_xori(UIMM(ctx->opcode) << 16); + gen_op_xori(uimm << 16); gen_op_store_T0_gpr(rA(ctx->opcode)); } @@ -682,25 +680,29 @@ GEN_HANDLER(rlwinm, 0x15, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) mb = MB(ctx->opcode); me = ME(ctx->opcode); gen_op_load_gpr_T0(rS(ctx->opcode)); +#if 1 // TRY + if (sh == 0) { + gen_op_andi_(MASK(mb, me)); + goto store; + } +#endif if (mb == 0) { if (me == 31) { gen_op_rotlwi(sh); goto store; +#if 0 } else if (me == (31 - sh)) { gen_op_slwi(sh); goto store; - } else if (sh == 0) { - gen_op_andi_(MASK(0, me)); - goto store; +#endif } } else if (me == 31) { +#if 0 if (sh == (32 - mb)) { gen_op_srwi(mb); goto store; - } else if (sh == 0) { - gen_op_andi_(MASK(mb, 31)); - goto store; } +#endif } gen_op_rlwinm(sh, MASK(mb, me)); store: @@ -1005,7 +1007,8 @@ GEN_HANDLER(l##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) \ uint32_t simm = SIMM(ctx->opcode); \ if (rA(ctx->opcode) == 0 || \ rA(ctx->opcode) == rD(ctx->opcode)) { \ - RET_INVAL(); \ + RET_INVAL(ctx); \ + return; \ } \ gen_op_load_gpr_T0(rA(ctx->opcode)); \ if (simm != 0) \ @@ -1020,7 +1023,8 @@ GEN_HANDLER(l##width##ux, 0x1F, 0x17, opc, 0x00000001, PPC_INTEGER) \ { \ if (rA(ctx->opcode) == 0 || \ rA(ctx->opcode) == rD(ctx->opcode)) { \ - RET_INVAL(); \ + RET_INVAL(ctx); \ + return; \ } \ gen_op_load_gpr_T0(rA(ctx->opcode)); \ gen_op_load_gpr_T1(rB(ctx->opcode)); \ @@ -1081,7 +1085,8 @@ GEN_HANDLER(st##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) \ { \ uint32_t simm = SIMM(ctx->opcode); \ if (rA(ctx->opcode) == 0) { \ - RET_INVAL(); \ + RET_INVAL(ctx); \ + return; \ } \ gen_op_load_gpr_T0(rA(ctx->opcode)); \ if (simm != 0) \ @@ -1095,7 +1100,8 @@ GEN_HANDLER(st##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) \ GEN_HANDLER(st##width##ux, 0x1F, 0x17, opc, 0x00000001, PPC_INTEGER) \ { \ if (rA(ctx->opcode) == 0) { \ - RET_INVAL(); \ + RET_INVAL(ctx); \ + return; \ } \ gen_op_load_gpr_T0(rA(ctx->opcode)); \ gen_op_load_gpr_T1(rB(ctx->opcode)); \ @@ -1231,7 +1237,8 @@ GEN_HANDLER(lswi, 0x1F, 0x15, 0x12, 0x00000001, PPC_INTEGER) nr = nb / 4; if (((start + nr) > 32 && start <= ra && (start + nr - 32) > ra) || ((start + nr) <= 32 && start <= ra && (start + nr) > ra)) { - RET_EXCP(EXCP_PROGRAM, EXCP_INVAL | EXCP_INVAL_LSWX); + RET_EXCP(ctx, EXCP_PROGRAM, EXCP_INVAL | EXCP_INVAL_LSWX); + return; } if (ra == 0) { gen_op_set_T0(0); @@ -1263,12 +1270,16 @@ GEN_HANDLER(lswx, 0x1F, 0x15, 0x10, 0x00000001, PPC_INTEGER) /* stswi */ GEN_HANDLER(stswi, 0x1F, 0x15, 0x16, 0x00000001, PPC_INTEGER) { + int nb = NB(ctx->opcode); + if (rA(ctx->opcode) == 0) { gen_op_set_T0(0); } else { gen_op_load_gpr_T0(rA(ctx->opcode)); } - gen_op_set_T1(NB(ctx->opcode)); + if (nb == 0) + nb = 32; + gen_op_set_T1(nb); op_ldsts(stsw, rS(ctx->opcode)); } @@ -1371,7 +1382,8 @@ GEN_HANDLER(l##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) \ uint32_t simm = SIMM(ctx->opcode); \ if (rA(ctx->opcode) == 0 || \ rA(ctx->opcode) == rD(ctx->opcode)) { \ - RET_INVAL(); \ + RET_INVAL(ctx); \ + return; \ } \ gen_op_load_gpr_T0(rA(ctx->opcode)); \ if (simm != 0) \ @@ -1386,7 +1398,8 @@ GEN_HANDLER(l##width##ux, 0x1F, 0x17, opc, 0x00000001, PPC_INTEGER) \ { \ if (rA(ctx->opcode) == 0 || \ rA(ctx->opcode) == rD(ctx->opcode)) { \ - RET_INVAL(); \ + RET_INVAL(ctx); \ + return; \ } \ gen_op_load_gpr_T0(rA(ctx->opcode)); \ gen_op_load_gpr_T1(rB(ctx->opcode)); \ @@ -1443,7 +1456,8 @@ GEN_HANDLER(st##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) \ { \ uint32_t simm = SIMM(ctx->opcode); \ if (rA(ctx->opcode) == 0) { \ - RET_INVAL(); \ + RET_INVAL(ctx); \ + return; \ } \ gen_op_load_gpr_T0(rA(ctx->opcode)); \ if (simm != 0) \ @@ -1457,7 +1471,8 @@ GEN_HANDLER(st##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) \ GEN_HANDLER(st##width##ux, 0x1F, 0x17, opc, 0x00000001, PPC_INTEGER) \ { \ if (rA(ctx->opcode) == 0) { \ - RET_INVAL(); \ + RET_INVAL(ctx); \ + return; \ } \ gen_op_load_gpr_T0(rA(ctx->opcode)); \ gen_op_load_gpr_T1(rB(ctx->opcode)); \ @@ -1497,214 +1512,139 @@ GEN_STFS(fs, 0x14); /* stfiwx */ GEN_HANDLER(stfiwx, 0x1F, 0x17, 0x1E, 0x00000001, PPC_FLOAT) { - RET_INVAL(); + RET_INVAL(ctx); } /*** Branch ***/ -#define GEN_BCOND(name, opc1, opc2, opc3, prologue, \ - bl_ctr, b_ctr, bl_ctrz, b_ctrz, b, bl, \ - bl_ctr_true, b_ctr_true, bl_ctrz_true, b_ctrz_true, bl_true, b_true, \ - bl_ctr_false, b_ctr_false, bl_ctrz_false, b_ctrz_false, bl_false, b_false) \ -GEN_HANDLER(name, opc1, opc2, opc3, 0x00000000, PPC_FLOW) \ -{ \ - __attribute__ ((unused)) uint32_t target; \ - uint32_t bo = BO(ctx->opcode); \ - uint32_t bi = BI(ctx->opcode); \ - uint32_t mask; \ - gen_op_update_tb(ctx->tb_offset); \ - gen_op_update_decr(ctx->decr_offset); \ - gen_op_process_exceptions((uint32_t)ctx->nip - 4); \ - prologue; \ -/* gen_op_set_T1((uint32_t)ctx->tb);*/ \ - if ((bo & 0x4) == 0) \ - gen_op_dec_ctr(); \ - if (bo & 0x10) { \ - /* No CR condition */ \ - switch (bo & 0x6) { \ - case 0: \ - if (LK(ctx->opcode)) { \ - bl_ctr; \ - } else { \ - b_ctr; \ - } \ - break; \ - case 2: \ - if (LK(ctx->opcode)) { \ - bl_ctrz; \ - } else { \ - b_ctrz; \ - } \ - break; \ - case 4: \ - case 6: \ - if (LK(ctx->opcode)) { \ - bl; \ - } else { \ - b; \ - } \ - break; \ - default: \ - printf("ERROR: %s: unhandled ba case (%d)\n", __func__, bo); \ - RET_INVAL(); \ - break; \ - } \ - } else { \ - mask = 1 << (3 - (bi & 0x03)); \ - gen_op_load_crf_T0(bi >> 2); \ - if (bo & 0x8) { \ - switch (bo & 0x6) { \ - case 0: \ - if (LK(ctx->opcode)) { \ - bl_ctr_true; \ - } else { \ - b_ctr_true; \ - } \ - break; \ - case 2: \ - if (LK(ctx->opcode)) { \ - bl_ctrz_true; \ - } else { \ - b_ctrz_true; \ - } \ - break; \ - case 4: \ - case 6: \ - if (LK(ctx->opcode)) { \ - bl_true; \ - } else { \ - b_true; \ - } \ - break; \ - default: \ - printf("ERROR: %s: unhandled b case (%d)\n", __func__, bo); \ - RET_INVAL(); \ - break; \ - } \ - } else { \ - switch (bo & 0x6) { \ - case 0: \ - if (LK(ctx->opcode)) { \ - bl_ctr_false; \ - } else { \ - b_ctr_false; \ - } \ - break; \ - case 2: \ - if (LK(ctx->opcode)) { \ - bl_ctrz_false; \ - } else { \ - b_ctrz_false; \ - } \ - break; \ - case 4: \ - case 6: \ - if (LK(ctx->opcode)) { \ - bl_false; \ - } else { \ - b_false; \ - } \ - break; \ - default: \ - printf("ERROR: %s: unhandled bn case (%d)\n", __func__, bo); \ - RET_INVAL(); \ - break; \ - } \ - } \ - } \ - ctx->exception = EXCP_BRANCH; \ -} /* b ba bl bla */ GEN_HANDLER(b, 0x12, 0xFF, 0xFF, 0x00000000, PPC_FLOW) { - uint32_t li = s_ext24(LI(ctx->opcode)), target; + uint32_t li, target; + + /* sign extend LI */ + li = ((int32_t)LI(ctx->opcode) << 6) >> 6; - gen_op_update_tb(ctx->tb_offset); - gen_op_update_decr(ctx->decr_offset); - gen_op_process_exceptions((uint32_t)ctx->nip - 4); if (AA(ctx->opcode) == 0) - target = (uint32_t)ctx->nip + li - 4; + target = ctx->nip + li - 4; else target = li; -// gen_op_set_T1((uint32_t)ctx->tb); if (LK(ctx->opcode)) { - gen_op_bl(target, (uint32_t)ctx->nip); - } else { - gen_op_b(target); + gen_op_setlr(ctx->nip); } + gen_op_b((long)ctx->tb, target); ctx->exception = EXCP_BRANCH; } -/* bc bca bcl bcla */ -GEN_BCOND(bc, 0x10, 0xFF, 0xFF, - do { - uint32_t li = s_ext16(BD(ctx->opcode)); - if (AA(ctx->opcode) == 0) { - target = (uint32_t)ctx->nip + li - 4; - } else { - target = li; - } - } while (0), - gen_op_bl_ctr((uint32_t)ctx->nip, target), - gen_op_b_ctr((uint32_t)ctx->nip, target), - gen_op_bl_ctrz((uint32_t)ctx->nip, target), - gen_op_b_ctrz((uint32_t)ctx->nip, target), - gen_op_b(target), - gen_op_bl(target, (uint32_t)ctx->nip), - gen_op_bl_ctr_true((uint32_t)ctx->nip, target, mask), - gen_op_b_ctr_true((uint32_t)ctx->nip, target, mask), - gen_op_bl_ctrz_true((uint32_t)ctx->nip, target, mask), - gen_op_b_ctrz_true((uint32_t)ctx->nip, target, mask), - gen_op_bl_true((uint32_t)ctx->nip, target, mask), - gen_op_b_true((uint32_t)ctx->nip, target, mask), - gen_op_bl_ctr_false((uint32_t)ctx->nip, target, mask), - gen_op_b_ctr_false((uint32_t)ctx->nip, target, mask), - gen_op_bl_ctrz_false((uint32_t)ctx->nip, target, mask), - gen_op_b_ctrz_false((uint32_t)ctx->nip, target, mask), - gen_op_bl_false((uint32_t)ctx->nip, target, mask), - gen_op_b_false((uint32_t)ctx->nip, target, mask)); - -/* bcctr bcctrl */ -GEN_BCOND(bcctr, 0x13, 0x10, 0x10, do { } while (0), - gen_op_bctrl_ctr((uint32_t)ctx->nip), - gen_op_bctr_ctr((uint32_t)ctx->nip), - gen_op_bctrl_ctrz((uint32_t)ctx->nip), - gen_op_bctr_ctrz((uint32_t)ctx->nip), - gen_op_bctr(), - gen_op_bctrl((uint32_t)ctx->nip), - gen_op_bctrl_ctr_true((uint32_t)ctx->nip, mask), - gen_op_bctr_ctr_true((uint32_t)ctx->nip, mask), - gen_op_bctrl_ctrz_true((uint32_t)ctx->nip, mask), - gen_op_bctr_ctrz_true((uint32_t)ctx->nip, mask), - gen_op_bctrl_true((uint32_t)ctx->nip, mask), - gen_op_bctr_true((uint32_t)ctx->nip, mask), - gen_op_bctrl_ctr_false((uint32_t)ctx->nip, mask), - gen_op_bctr_ctr_false((uint32_t)ctx->nip, mask), - gen_op_bctrl_ctrz_false((uint32_t)ctx->nip, mask), - gen_op_bctr_ctrz_false((uint32_t)ctx->nip, mask), - gen_op_bctrl_false((uint32_t)ctx->nip, mask), - gen_op_bctr_false((uint32_t)ctx->nip, mask)) - -/* bclr bclrl */ -GEN_BCOND(bclr, 0x13, 0x10, 0x00, do { } while (0), - gen_op_blrl_ctr((uint32_t)ctx->nip), - gen_op_blr_ctr((uint32_t)ctx->nip), - gen_op_blrl_ctrz((uint32_t)ctx->nip), - gen_op_blr_ctrz((uint32_t)ctx->nip), - gen_op_blr(), - gen_op_blrl((uint32_t)ctx->nip), - gen_op_blrl_ctr_true((uint32_t)ctx->nip, mask), - gen_op_blr_ctr_true((uint32_t)ctx->nip, mask), - gen_op_blrl_ctrz_true((uint32_t)ctx->nip, mask), - gen_op_blr_ctrz_true((uint32_t)ctx->nip, mask), - gen_op_blrl_true((uint32_t)ctx->nip, mask), - gen_op_blr_true((uint32_t)ctx->nip, mask), - gen_op_blrl_ctr_false((uint32_t)ctx->nip, mask), - gen_op_blr_ctr_false((uint32_t)ctx->nip, mask), - gen_op_blrl_ctrz_false((uint32_t)ctx->nip, mask), - gen_op_blr_ctrz_false((uint32_t)ctx->nip, mask), - gen_op_blrl_false((uint32_t)ctx->nip, mask), - gen_op_blr_false((uint32_t)ctx->nip, mask)) +#define BCOND_IM 0 +#define BCOND_LR 1 +#define BCOND_CTR 2 + +static inline void gen_bcond(DisasContext *ctx, int type) +{ + uint32_t target = 0; + uint32_t bo = BO(ctx->opcode); + uint32_t bi = BI(ctx->opcode); + uint32_t mask; + uint32_t li; + + if ((bo & 0x4) == 0) + gen_op_dec_ctr(); + switch(type) { + case BCOND_IM: + li = s_ext16(BD(ctx->opcode)); + if (AA(ctx->opcode) == 0) { + target = ctx->nip + li - 4; + } else { + target = li; + } + break; + case BCOND_CTR: + gen_op_movl_T1_ctr(); + break; + default: + case BCOND_LR: + gen_op_movl_T1_lr(); + break; + } + if (LK(ctx->opcode)) { + gen_op_setlr(ctx->nip); + } + if (bo & 0x10) { + /* No CR condition */ + switch (bo & 0x6) { + case 0: + gen_op_test_ctr(); + break; + case 2: + gen_op_test_ctrz(); + break; + default: + case 4: + case 6: + if (type == BCOND_IM) { + gen_op_b((long)ctx->tb, target); + } else { + gen_op_b_T1(); + } + goto no_test; + } + } else { + mask = 1 << (3 - (bi & 0x03)); + gen_op_load_crf_T0(bi >> 2); + if (bo & 0x8) { + switch (bo & 0x6) { + case 0: + gen_op_test_ctr_true(mask); + break; + case 2: + gen_op_test_ctrz_true(mask); + break; + default: + case 4: + case 6: + gen_op_test_true(mask); + break; + } + } else { + switch (bo & 0x6) { + case 0: + gen_op_test_ctr_false(mask); + break; + case 2: + gen_op_test_ctrz_false(mask); + break; + default: + case 4: + case 6: + gen_op_test_false(mask); + break; + } + } + } + if (type == BCOND_IM) { + gen_op_btest((long)ctx->tb, target, ctx->nip); + } else { + gen_op_btest_T1(ctx->nip); + } + no_test: + ctx->exception = EXCP_BRANCH; +} + +GEN_HANDLER(bc, 0x10, 0xFF, 0xFF, 0x00000000, PPC_FLOW) +{ + gen_bcond(ctx, BCOND_IM); +} + +GEN_HANDLER(bcctr, 0x13, 0x10, 0x10, 0x00000000, PPC_FLOW) +{ + gen_bcond(ctx, BCOND_CTR); +} + +GEN_HANDLER(bclr, 0x13, 0x10, 0x00, 0x00000000, PPC_FLOW) +{ + gen_bcond(ctx, BCOND_LR); +} /*** Condition register logical ***/ #define GEN_CRLOGIC(op, opc) \ @@ -1749,14 +1689,15 @@ GEN_HANDLER(mcrf, 0x13, 0x00, 0xFF, 0x00000001, PPC_INTEGER) GEN_HANDLER(rfi, 0x13, 0x12, 0xFF, 0x03FF8001, PPC_FLOW) { #if defined(CONFIG_USER_ONLY) - RET_PRIVOPC(); + RET_PRIVOPC(ctx); #else /* Restore CPU state */ if (!ctx->supervisor) { - RET_PRIVOPC(); + RET_PRIVOPC(ctx); + return; } gen_op_rfi(); - ctx->exception = EXCP_RFI; + RET_EXCP(ctx, EXCP_RFI, 0); #endif } @@ -1764,11 +1705,10 @@ GEN_HANDLER(rfi, 0x13, 0x12, 0xFF, 0x03FF8001, PPC_FLOW) GEN_HANDLER(sc, 0x11, 0xFF, 0xFF, 0x03FFFFFD, PPC_FLOW) { #if defined(CONFIG_USER_ONLY) - gen_op_queue_exception(EXCP_SYSCALL_USER); + RET_EXCP(ctx, EXCP_SYSCALL_USER, 0); #else - gen_op_queue_exception(EXCP_SYSCALL); + RET_EXCP(ctx, EXCP_SYSCALL, 0); #endif - ctx->exception = EXCP_SYSCALL; } /*** Trap ***/ @@ -1836,10 +1776,11 @@ GEN_HANDLER(mfcr, 0x1F, 0x13, 0x00, 0x001FF801, PPC_MISC) GEN_HANDLER(mfmsr, 0x1F, 0x13, 0x02, 0x001FF801, PPC_MISC) { #if defined(CONFIG_USER_ONLY) - RET_PRIVREG(); + RET_PRIVREG(ctx); #else if (!ctx->supervisor) { - RET_PRIVREG(); + RET_PRIVREG(ctx); + return; } gen_op_load_msr(); gen_op_store_T0_gpr(rD(ctx->opcode)); @@ -1858,11 +1799,11 @@ GEN_HANDLER(mfspr, 0x1F, 0x13, 0x0A, 0x00000001, PPC_MISC) #endif { case -1: - RET_EXCP(EXCP_PROGRAM, EXCP_INVAL | EXCP_INVAL_SPR); - break; + RET_EXCP(ctx, EXCP_PROGRAM, EXCP_INVAL | EXCP_INVAL_SPR); + return; case 0: - RET_PRIVREG(); - break; + RET_PRIVREG(ctx); + return; default: break; } @@ -1976,19 +1917,13 @@ GEN_HANDLER(mfspr, 0x1F, 0x13, 0x0A, 0x00000001, PPC_MISC) gen_op_load_sdr1(); break; case V_TBL: - gen_op_update_tb(ctx->tb_offset); - ctx->tb_offset = 0; - /* TBL is still in T0 */ + gen_op_load_tbl(); break; case V_TBU: - gen_op_update_tb(ctx->tb_offset); - ctx->tb_offset = 0; - gen_op_load_tb(1); + gen_op_load_tbu(); break; case DECR: - gen_op_update_decr(ctx->decr_offset); - ctx->decr_offset = 0; - /* decr is still in T0 */ + gen_op_load_decr(); break; default: gen_op_load_spr(sprn); @@ -2005,18 +1940,15 @@ GEN_HANDLER(mftb, 0x1F, 0x13, 0x0B, 0x00000001, PPC_MISC) /* We need to update the time base before reading it */ switch (sprn) { case V_TBL: - gen_op_update_tb(ctx->tb_offset); - /* TBL is still in T0 */ + gen_op_load_tbl(); break; case V_TBU: - gen_op_update_tb(ctx->tb_offset); - gen_op_load_tb(1); + gen_op_load_tbu(); break; default: - RET_INVAL(); - break; + RET_INVAL(ctx); + return; } - ctx->tb_offset = 0; gen_op_store_T0_gpr(rD(ctx->opcode)); } @@ -2031,15 +1963,16 @@ GEN_HANDLER(mtcrf, 0x1F, 0x10, 0x04, 0x00100801, PPC_MISC) GEN_HANDLER(mtmsr, 0x1F, 0x12, 0x04, 0x001FF801, PPC_MISC) { #if defined(CONFIG_USER_ONLY) - RET_PRIVREG(); + RET_PRIVREG(ctx); #else if (!ctx->supervisor) { - RET_PRIVREG(); + RET_PRIVREG(ctx); + return; } gen_op_load_gpr_T0(rS(ctx->opcode)); gen_op_store_msr(); /* Must stop the translation as machine state (may have) changed */ - ctx->exception = EXCP_MTMSR; + RET_MTMSR(ctx); #endif } @@ -2061,10 +1994,10 @@ GEN_HANDLER(mtspr, 0x1F, 0x13, 0x0E, 0x00000001, PPC_MISC) #endif { case -1: - RET_EXCP(EXCP_PROGRAM, EXCP_INVAL | EXCP_INVAL_SPR); + RET_EXCP(ctx, EXCP_PROGRAM, EXCP_INVAL | EXCP_INVAL_SPR); break; case 0: - RET_PRIVREG(); + RET_PRIVREG(ctx); break; default: break; @@ -2075,7 +2008,6 @@ GEN_HANDLER(mtspr, 0x1F, 0x13, 0x0E, 0x00000001, PPC_MISC) gen_op_store_xer(); break; case LR: - gen_op_andi_(~0x03); gen_op_store_lr(); break; case CTR: @@ -2083,148 +2015,150 @@ GEN_HANDLER(mtspr, 0x1F, 0x13, 0x0E, 0x00000001, PPC_MISC) break; case IBAT0U: gen_op_store_ibat(0, 0); - gen_op_tlbia(); + RET_MTMSR(ctx); break; case IBAT1U: gen_op_store_ibat(0, 1); - gen_op_tlbia(); + RET_MTMSR(ctx); break; case IBAT2U: gen_op_store_ibat(0, 2); - gen_op_tlbia(); + RET_MTMSR(ctx); break; case IBAT3U: gen_op_store_ibat(0, 3); - gen_op_tlbia(); + RET_MTMSR(ctx); break; case IBAT4U: gen_op_store_ibat(0, 4); - gen_op_tlbia(); + RET_MTMSR(ctx); break; case IBAT5U: gen_op_store_ibat(0, 5); - gen_op_tlbia(); + RET_MTMSR(ctx); break; case IBAT6U: gen_op_store_ibat(0, 6); - gen_op_tlbia(); + RET_MTMSR(ctx); break; case IBAT7U: gen_op_store_ibat(0, 7); - gen_op_tlbia(); + RET_MTMSR(ctx); break; case IBAT0L: gen_op_store_ibat(1, 0); - gen_op_tlbia(); + RET_MTMSR(ctx); break; case IBAT1L: gen_op_store_ibat(1, 1); - gen_op_tlbia(); + RET_MTMSR(ctx); break; case IBAT2L: gen_op_store_ibat(1, 2); - gen_op_tlbia(); + RET_MTMSR(ctx); break; case IBAT3L: gen_op_store_ibat(1, 3); - gen_op_tlbia(); + RET_MTMSR(ctx); break; case IBAT4L: gen_op_store_ibat(1, 4); - gen_op_tlbia(); + RET_MTMSR(ctx); break; case IBAT5L: gen_op_store_ibat(1, 5); - gen_op_tlbia(); + RET_MTMSR(ctx); break; case IBAT6L: gen_op_store_ibat(1, 6); - gen_op_tlbia(); + RET_MTMSR(ctx); break; case IBAT7L: gen_op_store_ibat(1, 7); - gen_op_tlbia(); + RET_MTMSR(ctx); break; case DBAT0U: gen_op_store_dbat(0, 0); - gen_op_tlbia(); + RET_MTMSR(ctx); break; case DBAT1U: gen_op_store_dbat(0, 1); - gen_op_tlbia(); + RET_MTMSR(ctx); break; case DBAT2U: gen_op_store_dbat(0, 2); - gen_op_tlbia(); + RET_MTMSR(ctx); break; case DBAT3U: gen_op_store_dbat(0, 3); - gen_op_tlbia(); + RET_MTMSR(ctx); break; case DBAT4U: gen_op_store_dbat(0, 4); - gen_op_tlbia(); + RET_MTMSR(ctx); break; case DBAT5U: gen_op_store_dbat(0, 5); - gen_op_tlbia(); + RET_MTMSR(ctx); break; case DBAT6U: gen_op_store_dbat(0, 6); - gen_op_tlbia(); + RET_MTMSR(ctx); break; case DBAT7U: gen_op_store_dbat(0, 7); - gen_op_tlbia(); + RET_MTMSR(ctx); break; case DBAT0L: gen_op_store_dbat(1, 0); - gen_op_tlbia(); + RET_MTMSR(ctx); break; case DBAT1L: gen_op_store_dbat(1, 1); - gen_op_tlbia(); + RET_MTMSR(ctx); break; case DBAT2L: gen_op_store_dbat(1, 2); - gen_op_tlbia(); + RET_MTMSR(ctx); break; case DBAT3L: gen_op_store_dbat(1, 3); - gen_op_tlbia(); + RET_MTMSR(ctx); break; case DBAT4L: gen_op_store_dbat(1, 4); - gen_op_tlbia(); + RET_MTMSR(ctx); break; case DBAT5L: gen_op_store_dbat(1, 5); - gen_op_tlbia(); + RET_MTMSR(ctx); break; case DBAT6L: gen_op_store_dbat(1, 6); - gen_op_tlbia(); + RET_MTMSR(ctx); break; case DBAT7L: gen_op_store_dbat(1, 7); - gen_op_tlbia(); + RET_MTMSR(ctx); break; case SDR1: gen_op_store_sdr1(); - gen_op_tlbia(); + RET_MTMSR(ctx); break; case O_TBL: - gen_op_store_tb(0); - ctx->tb_offset = 0; + gen_op_store_tbl(); break; case O_TBU: - gen_op_store_tb(1); - ctx->tb_offset = 0; + gen_op_store_tbu(); break; case DECR: gen_op_store_decr(); - ctx->decr_offset = 0; break; +#if 0 + case HID0: + gen_op_store_hid0(); + break; +#endif default: gen_op_store_spr(sprn); break; @@ -2239,22 +2173,49 @@ GEN_HANDLER(mtspr, 0x1F, 0x13, 0x0E, 0x00000001, PPC_MISC) /* dcbf */ GEN_HANDLER(dcbf, 0x1F, 0x16, 0x02, 0x03E00001, PPC_CACHE) { + if (rA(ctx->opcode) == 0) { + gen_op_load_gpr_T0(rB(ctx->opcode)); + } else { + gen_op_load_gpr_T0(rA(ctx->opcode)); + gen_op_load_gpr_T1(rB(ctx->opcode)); + gen_op_add(); + } + op_ldst(lbz); } /* dcbi (Supervisor only) */ GEN_HANDLER(dcbi, 0x1F, 0x16, 0x0E, 0x03E00001, PPC_CACHE) { -#if !defined(CONFIG_USER_ONLY) - if (!ctx->supervisor) -#endif - { - RET_PRIVOPC(); +#if defined(CONFIG_USER_ONLY) + RET_PRIVOPC(ctx); +#else + if (!ctx->supervisor) { + RET_PRIVOPC(ctx); + return; } + if (rA(ctx->opcode) == 0) { + gen_op_load_gpr_T0(rB(ctx->opcode)); + } else { + gen_op_load_gpr_T0(rA(ctx->opcode)); + gen_op_load_gpr_T1(rB(ctx->opcode)); + gen_op_add(); + } + op_ldst(lbz); + op_ldst(stb); +#endif } /* dcdst */ GEN_HANDLER(dcbst, 0x1F, 0x16, 0x01, 0x03E00001, PPC_CACHE) { + if (rA(ctx->opcode) == 0) { + gen_op_load_gpr_T0(rB(ctx->opcode)); + } else { + gen_op_load_gpr_T0(rA(ctx->opcode)); + gen_op_load_gpr_T1(rB(ctx->opcode)); + gen_op_add(); + } + op_ldst(lbz); } /* dcbt */ @@ -2288,6 +2249,7 @@ GEN_HANDLER(dcbz, 0x1F, 0x16, 0x1F, 0x03E00001, PPC_CACHE) gen_op_add(); } op_dcbz(); + gen_op_check_reservation(); } /* icbi */ @@ -2315,10 +2277,11 @@ GEN_HANDLER(dcba, 0x1F, 0x16, 0x07, 0x03E00001, PPC_CACHE_OPT) GEN_HANDLER(mfsr, 0x1F, 0x13, 0x12, 0x0010F801, PPC_SEGMENT) { #if defined(CONFIG_USER_ONLY) - RET_PRIVREG(); + RET_PRIVREG(ctx); #else if (!ctx->supervisor) { - RET_PRIVREG(); + RET_PRIVREG(ctx); + return; } gen_op_load_sr(SR(ctx->opcode)); gen_op_store_T0_gpr(rD(ctx->opcode)); @@ -2329,10 +2292,11 @@ GEN_HANDLER(mfsr, 0x1F, 0x13, 0x12, 0x0010F801, PPC_SEGMENT) GEN_HANDLER(mfsrin, 0x1F, 0x13, 0x14, 0x001F0001, PPC_SEGMENT) { #if defined(CONFIG_USER_ONLY) - RET_PRIVREG(); + RET_PRIVREG(ctx); #else if (!ctx->supervisor) { - RET_PRIVREG(); + RET_PRIVREG(ctx); + return; } gen_op_load_gpr_T1(rB(ctx->opcode)); gen_op_load_srin(); @@ -2341,17 +2305,17 @@ GEN_HANDLER(mfsrin, 0x1F, 0x13, 0x14, 0x001F0001, PPC_SEGMENT) } /* mtsr */ -GEN_HANDLER(mtsr, 0x1F, 0x12, 0x02, 0x0010F801, PPC_SEGMENT) +GEN_HANDLER(mtsr, 0x1F, 0x12, 0x06, 0x0010F801, PPC_SEGMENT) { #if defined(CONFIG_USER_ONLY) - RET_PRIVREG(); + RET_PRIVREG(ctx); #else if (!ctx->supervisor) { - RET_PRIVREG(); + RET_PRIVREG(ctx); + return; } gen_op_load_gpr_T0(rS(ctx->opcode)); gen_op_store_sr(SR(ctx->opcode)); - gen_op_tlbia(); #endif } @@ -2359,15 +2323,15 @@ GEN_HANDLER(mtsr, 0x1F, 0x12, 0x02, 0x0010F801, PPC_SEGMENT) GEN_HANDLER(mtsrin, 0x1F, 0x12, 0x07, 0x001F0001, PPC_SEGMENT) { #if defined(CONFIG_USER_ONLY) - RET_PRIVREG(); + RET_PRIVREG(ctx); #else if (!ctx->supervisor) { - RET_PRIVREG(); + RET_PRIVREG(ctx); + return; } gen_op_load_gpr_T0(rS(ctx->opcode)); gen_op_load_gpr_T1(rB(ctx->opcode)); gen_op_store_srin(); - gen_op_tlbia(); #endif } @@ -2377,12 +2341,16 @@ GEN_HANDLER(mtsrin, 0x1F, 0x12, 0x07, 0x001F0001, PPC_SEGMENT) GEN_HANDLER(tlbia, 0x1F, 0x12, 0x0B, 0x03FFFC01, PPC_MEM_OPT) { #if defined(CONFIG_USER_ONLY) - RET_PRIVOPC(); + RET_PRIVOPC(ctx); #else if (!ctx->supervisor) { - RET_PRIVOPC(); + if (loglevel) + fprintf(logfile, "%s: ! supervisor\n", __func__); + RET_PRIVOPC(ctx); + return; } gen_op_tlbia(); + RET_MTMSR(ctx); #endif } @@ -2390,28 +2358,32 @@ GEN_HANDLER(tlbia, 0x1F, 0x12, 0x0B, 0x03FFFC01, PPC_MEM_OPT) GEN_HANDLER(tlbie, 0x1F, 0x12, 0x09, 0x03FF0001, PPC_MEM) { #if defined(CONFIG_USER_ONLY) - RET_PRIVOPC(); + RET_PRIVOPC(ctx); #else if (!ctx->supervisor) { - RET_PRIVOPC(); + RET_PRIVOPC(ctx); + return; } gen_op_load_gpr_T0(rB(ctx->opcode)); gen_op_tlbie(); + RET_MTMSR(ctx); #endif } /* tlbsync */ -GEN_HANDLER(tlbsync, 0x1F, 0x16, 0x11, 0x03FFFC01, PPC_MEM) +GEN_HANDLER(tlbsync, 0x1F, 0x16, 0x11, 0x03FFF801, PPC_MEM) { #if defined(CONFIG_USER_ONLY) - RET_PRIVOPC(); + RET_PRIVOPC(ctx); #else if (!ctx->supervisor) { - RET_PRIVOPC(); + RET_PRIVOPC(ctx); + return; } /* This has no effect: it should ensure that all previous * tlbie have completed */ + RET_MTMSR(ctx); #endif } @@ -2732,59 +2704,78 @@ static void init_spr_rights (uint32_t pvr) spr_set_rights(DBAT3U, SPR_SR | SPR_SW); /* DBAT3L (SPR 543) */ spr_set_rights(DBAT3L, SPR_SR | SPR_SW); - /* DABR (SPR 1013) */ - spr_set_rights(DABR, SPR_SR | SPR_SW); /* FPECR (SPR 1022) */ spr_set_rights(FPECR, SPR_SR | SPR_SW); - /* PIR (SPR 1023) */ + /* Special registers for PPC 604 */ + if ((pvr & 0xFFFF0000) == 0x00040000) { + /* IABR */ + spr_set_rights(IABR , SPR_SR | SPR_SW); + /* DABR (SPR 1013) */ + spr_set_rights(DABR, SPR_SR | SPR_SW); + /* HID0 */ + spr_set_rights(HID0, SPR_SR | SPR_SW); + /* PIR */ spr_set_rights(PIR, SPR_SR | SPR_SW); + /* PMC1 */ + spr_set_rights(PMC1, SPR_SR | SPR_SW); + /* PMC2 */ + spr_set_rights(PMC2, SPR_SR | SPR_SW); + /* MMCR0 */ + spr_set_rights(MMCR0, SPR_SR | SPR_SW); + /* SIA */ + spr_set_rights(SIA, SPR_SR | SPR_SW); + /* SDA */ + spr_set_rights(SDA, SPR_SR | SPR_SW); + } /* Special registers for MPC740/745/750/755 (aka G3) & IBM 750 */ if ((pvr & 0xFFFF0000) == 0x00080000 || (pvr & 0xFFFF0000) == 0x70000000) { /* HID0 */ - spr_set_rights(SPR_ENCODE(1008), SPR_SR | SPR_SW); + spr_set_rights(HID0, SPR_SR | SPR_SW); /* HID1 */ - spr_set_rights(SPR_ENCODE(1009), SPR_SR | SPR_SW); + spr_set_rights(HID1, SPR_SR | SPR_SW); /* IABR */ - spr_set_rights(SPR_ENCODE(1010), SPR_SR | SPR_SW); + spr_set_rights(IABR, SPR_SR | SPR_SW); /* ICTC */ - spr_set_rights(SPR_ENCODE(1019), SPR_SR | SPR_SW); + spr_set_rights(ICTC, SPR_SR | SPR_SW); /* L2CR */ - spr_set_rights(SPR_ENCODE(1017), SPR_SR | SPR_SW); + spr_set_rights(L2CR, SPR_SR | SPR_SW); /* MMCR0 */ - spr_set_rights(SPR_ENCODE(952), SPR_SR | SPR_SW); + spr_set_rights(MMCR0, SPR_SR | SPR_SW); /* MMCR1 */ - spr_set_rights(SPR_ENCODE(956), SPR_SR | SPR_SW); + spr_set_rights(MMCR1, SPR_SR | SPR_SW); /* PMC1 */ - spr_set_rights(SPR_ENCODE(953), SPR_SR | SPR_SW); + spr_set_rights(PMC1, SPR_SR | SPR_SW); /* PMC2 */ - spr_set_rights(SPR_ENCODE(954), SPR_SR | SPR_SW); + spr_set_rights(PMC2, SPR_SR | SPR_SW); /* PMC3 */ - spr_set_rights(SPR_ENCODE(957), SPR_SR | SPR_SW); + spr_set_rights(PMC3, SPR_SR | SPR_SW); /* PMC4 */ - spr_set_rights(SPR_ENCODE(958), SPR_SR | SPR_SW); + spr_set_rights(PMC4, SPR_SR | SPR_SW); /* SIA */ - spr_set_rights(SPR_ENCODE(955), SPR_SR | SPR_SW); + spr_set_rights(SIA, SPR_SR | SPR_SW); + /* SDA */ + spr_set_rights(SDA, SPR_SR | SPR_SW); /* THRM1 */ - spr_set_rights(SPR_ENCODE(1020), SPR_SR | SPR_SW); + spr_set_rights(THRM1, SPR_SR | SPR_SW); /* THRM2 */ - spr_set_rights(SPR_ENCODE(1021), SPR_SR | SPR_SW); + spr_set_rights(THRM2, SPR_SR | SPR_SW); /* THRM3 */ - spr_set_rights(SPR_ENCODE(1022), SPR_SR | SPR_SW); + spr_set_rights(THRM3, SPR_SR | SPR_SW); /* UMMCR0 */ - spr_set_rights(SPR_ENCODE(936), SPR_UR | SPR_UW); + spr_set_rights(UMMCR0, SPR_UR | SPR_UW); /* UMMCR1 */ - spr_set_rights(SPR_ENCODE(940), SPR_UR | SPR_UW); + spr_set_rights(UMMCR1, SPR_UR | SPR_UW); /* UPMC1 */ - spr_set_rights(SPR_ENCODE(937), SPR_UR | SPR_UW); + spr_set_rights(UPMC1, SPR_UR | SPR_UW); /* UPMC2 */ - spr_set_rights(SPR_ENCODE(938), SPR_UR | SPR_UW); + spr_set_rights(UPMC2, SPR_UR | SPR_UW); /* UPMC3 */ - spr_set_rights(SPR_ENCODE(941), SPR_UR | SPR_UW); + spr_set_rights(UPMC3, SPR_UR | SPR_UW); /* UPMC4 */ - spr_set_rights(SPR_ENCODE(942), SPR_UR | SPR_UW); + spr_set_rights(UPMC4, SPR_UR | SPR_UW); /* USIA */ - spr_set_rights(SPR_ENCODE(939), SPR_UR | SPR_UW); + spr_set_rights(USIA, SPR_UR | SPR_UW); } /* MPC755 has special registers */ if (pvr == 0x00083100) { @@ -2829,23 +2820,23 @@ static void init_spr_rights (uint32_t pvr) /* DBAT7L */ spr_set_rights(DBAT7L, SPR_SR | SPR_SW); /* DMISS */ - spr_set_rights(SPR_ENCODE(976), SPR_SR | SPR_SW); + spr_set_rights(DMISS, SPR_SR | SPR_SW); /* DCMP */ - spr_set_rights(SPR_ENCODE(977), SPR_SR | SPR_SW); + spr_set_rights(DCMP, SPR_SR | SPR_SW); /* DHASH1 */ - spr_set_rights(SPR_ENCODE(978), SPR_SR | SPR_SW); + spr_set_rights(DHASH1, SPR_SR | SPR_SW); /* DHASH2 */ - spr_set_rights(SPR_ENCODE(979), SPR_SR | SPR_SW); + spr_set_rights(DHASH2, SPR_SR | SPR_SW); /* IMISS */ - spr_set_rights(SPR_ENCODE(980), SPR_SR | SPR_SW); + spr_set_rights(IMISS, SPR_SR | SPR_SW); /* ICMP */ - spr_set_rights(SPR_ENCODE(981), SPR_SR | SPR_SW); + spr_set_rights(ICMP, SPR_SR | SPR_SW); /* RPA */ - spr_set_rights(SPR_ENCODE(982), SPR_SR | SPR_SW); + spr_set_rights(RPA, SPR_SR | SPR_SW); /* HID2 */ - spr_set_rights(SPR_ENCODE(1011), SPR_SR | SPR_SW); + spr_set_rights(HID2, SPR_SR | SPR_SW); /* L2PM */ - spr_set_rights(SPR_ENCODE(1016), SPR_SR | SPR_SW); + spr_set_rights(L2PM, SPR_SR | SPR_SW); } } @@ -2926,7 +2917,6 @@ static int create_ppc_proc (opc_handler_t **ppc_opcodes, unsigned long pvr) /*****************************************************************************/ /* Misc PPC helpers */ -FILE *stdout; void cpu_ppc_dump_state(CPUPPCState *env, FILE *f, int flags) { @@ -2934,7 +2924,7 @@ void cpu_ppc_dump_state(CPUPPCState *env, FILE *f, int flags) fprintf(f, "nip=0x%08x LR=0x%08x CTR=0x%08x XER=0x%08x " "MSR=0x%08x\n", env->nip, env->lr, env->ctr, - _load_xer(), _load_msr()); + _load_xer(env), _load_msr(env)); for (i = 0; i < 32; i++) { if ((i & 7) == 0) fprintf(f, "GPR%02d:", i); @@ -2957,7 +2947,8 @@ void cpu_ppc_dump_state(CPUPPCState *env, FILE *f, int flags) fprintf(f, " %c%c", a, env->crf[i] & 0x01 ? 'O' : ' '); } fprintf(f, " ] "); - fprintf(f, "TB: 0x%08x %08x\n", env->tb[1], env->tb[0]); + fprintf(f, "TB: 0x%08x %08x\n", cpu_ppc_load_tbu(env), + cpu_ppc_load_tbl(env)); for (i = 0; i < 16; i++) { if ((i & 3) == 0) fprintf(f, "FPR%02d:", i); @@ -2965,8 +2956,8 @@ void cpu_ppc_dump_state(CPUPPCState *env, FILE *f, int flags) if ((i & 3) == 3) fprintf(f, "\n"); } - fprintf(f, "SRR0 0x%08x SRR1 0x%08x\n", - env->spr[SRR0], env->spr[SRR1]); + fprintf(f, "SRR0 0x%08x SRR1 0x%08x DECR=0x%08x\n", + env->spr[SRR0], env->spr[SRR1], cpu_ppc_load_decr(env)); fprintf(f, "reservation 0x%08x\n", env->reserve); fflush(f); } @@ -2981,10 +2972,9 @@ CPUPPCState *cpu_ppc_init(void) cpu_exec_init(); - env = malloc(sizeof(CPUPPCState)); + env = qemu_mallocz(sizeof(CPUPPCState)); if (!env) return NULL; - memset(env, 0, sizeof(CPUPPCState)); #if !defined(CONFIG_USER_ONLY) && defined (USE_OPEN_FIRMWARE) setup_machine(env, 0); #else @@ -2993,22 +2983,34 @@ CPUPPCState *cpu_ppc_init(void) // env->spr[PVR] = 0x00083100; /* MPC755 (G3 embedded) */ // env->spr[PVR] = 0x00070100; /* IBM 750FX */ #endif - env->decr = 0xFFFFFFFF; - if (create_ppc_proc(ppc_opcodes, env->spr[PVR]) < 0) - return NULL; - init_spr_rights(env->spr[PVR]); tlb_flush(env, 1); #if defined (DO_SINGLE_STEP) /* Single step trace mode */ msr_se = 1; #endif + msr_fp = 1; /* Allow floating point exceptions */ + msr_me = 1; /* Allow machine check exceptions */ #if defined(CONFIG_USER_ONLY) msr_pr = 1; + cpu_ppc_register(env, 0x00080000); +#else + env->nip = 0xFFFFFFFC; #endif - + env->access_type = ACCESS_INT; + cpu_single_env = env; return env; } +int cpu_ppc_register (CPUPPCState *env, uint32_t pvr) +{ + env->spr[PVR] = pvr; + if (create_ppc_proc(ppc_opcodes, env->spr[PVR]) < 0) + return -1; + init_spr_rights(env->spr[PVR]); + + return 0; +} + void cpu_ppc_close(CPUPPCState *env) { /* Should also remove all opcode tables... */ @@ -3016,14 +3018,13 @@ void cpu_ppc_close(CPUPPCState *env) } /*****************************************************************************/ -void raise_exception_err (int exception_index, int error_code); int print_insn_powerpc (FILE *out, unsigned long insn, unsigned memaddr, int dialect); int gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb, int search_pc) { - DisasContext ctx; + DisasContext ctx, *ctxp = &ctx; opc_handler_t **table, *handler; uint32_t pc_start; uint16_t *gen_opc_end; @@ -3033,9 +3034,7 @@ int gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb, gen_opc_ptr = gen_opc_buf; gen_opc_end = gen_opc_buf + OPC_MAX_SIZE; gen_opparam_ptr = gen_opparam_buf; - ctx.nip = (uint32_t *)pc_start; - ctx.tb_offset = 0; - ctx.decr_offset = 0; + ctx.nip = pc_start; ctx.tb = tb; ctx.exception = EXCP_NONE; #if defined(CONFIG_USER_ONLY) @@ -3048,6 +3047,7 @@ int gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb, /* Single step trace mode */ msr_se = 1; #endif + env->access_type = ACCESS_CODE; /* Set env in case of segfault during code fetch */ while (ctx.exception == EXCP_NONE && gen_opc_ptr < gen_opc_end) { if (search_pc) { @@ -3058,30 +3058,26 @@ int gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb, lj++; while (lj < j) gen_opc_instr_start[lj++] = 0; - gen_opc_pc[lj] = (uint32_t)ctx.nip; + gen_opc_pc[lj] = ctx.nip; gen_opc_instr_start[lj] = 1; } } -#if defined DEBUG_DISAS - if (loglevel > 0) { +#if defined PPC_DEBUG_DISAS + if (loglevel & CPU_LOG_TB_IN_ASM) { fprintf(logfile, "----------------\n"); - fprintf(logfile, "nip=%p super=%d ir=%d\n", + fprintf(logfile, "nip=%08x super=%d ir=%d\n", ctx.nip, 1 - msr_pr, msr_ir); } #endif - ctx.opcode = ldl_code(ctx.nip); -#if defined DEBUG_DISAS - if (loglevel > 0) { + ctx.opcode = ldl_code((void *)ctx.nip); +#if defined PPC_DEBUG_DISAS + if (loglevel & CPU_LOG_TB_IN_ASM) { fprintf(logfile, "translate opcode %08x (%02x %02x %02x)\n", ctx.opcode, opc1(ctx.opcode), opc2(ctx.opcode), opc3(ctx.opcode)); } #endif - ctx.nip++; - ctx.tb_offset++; - /* Check decrementer exception */ - if (++ctx.decr_offset == env->decr + 1) - ctx.exception = EXCP_DECR; + ctx.nip += 4; table = ppc_opcodes; handler = table[opc1(ctx.opcode)]; if (is_indirect_opcode(handler)) { @@ -3093,38 +3089,38 @@ int gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb, } } /* Is opcode *REALLY* valid ? */ - if ((ctx.opcode & handler->inval) != 0) { - if (loglevel > 0) { if (handler->handler == &gen_invalid) { + if (loglevel > 0) { fprintf(logfile, "invalid/unsupported opcode: " - "%02x -%02x - %02x (%08x) %p\n", + "%02x - %02x - %02x (%08x) 0x%08x %d\n", opc1(ctx.opcode), opc2(ctx.opcode), - opc3(ctx.opcode), ctx.opcode, ctx.nip - 1); + opc3(ctx.opcode), ctx.opcode, ctx.nip - 4, msr_ir); + } else { + printf("invalid/unsupported opcode: " + "%02x - %02x - %02x (%08x) 0x%08x %d\n", + opc1(ctx.opcode), opc2(ctx.opcode), + opc3(ctx.opcode), ctx.opcode, ctx.nip - 4, msr_ir); + } } else { + if ((ctx.opcode & handler->inval) != 0) { + if (loglevel > 0) { fprintf(logfile, "invalid bits: %08x for opcode: " - "%02x -%02x - %02x (0x%08x) (%p)\n", + "%02x -%02x - %02x (0x%08x) (0x%08x)\n", ctx.opcode & handler->inval, opc1(ctx.opcode), opc2(ctx.opcode), opc3(ctx.opcode), - ctx.opcode, ctx.nip - 1); - } - } else { - if (handler->handler == &gen_invalid) { - printf("invalid/unsupported opcode: " - "%02x -%02x - %02x (%08x) %p\n", - opc1(ctx.opcode), opc2(ctx.opcode), - opc3(ctx.opcode), ctx.opcode, ctx.nip - 1); + ctx.opcode, ctx.nip - 4); } else { printf("invalid bits: %08x for opcode: " - "%02x -%02x - %02x (0x%08x) (%p)\n", + "%02x -%02x - %02x (0x%08x) (0x%08x)\n", ctx.opcode & handler->inval, opc1(ctx.opcode), opc2(ctx.opcode), opc3(ctx.opcode), - ctx.opcode, ctx.nip - 1); + ctx.opcode, ctx.nip - 4); } + RET_INVAL(ctxp); + break; } - (*gen_invalid)(&ctx); - } else { - (*(handler->handler))(&ctx); } + (*(handler->handler))(&ctx); /* Check trace mode exceptions */ if ((msr_be && ctx.exception == EXCP_BRANCH) || /* Check in single step trace mode @@ -3132,32 +3128,22 @@ int gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb, * - rfi, trap or syscall * - first instruction of an exception handler */ - (msr_se && ((uint32_t)ctx.nip < 0x100 || - (uint32_t)ctx.nip > 0xF00 || - ((uint32_t)ctx.nip & 0xFC) != 0x04) && + (msr_se && (ctx.nip < 0x100 || + ctx.nip > 0xF00 || + (ctx.nip & 0xFC) != 0x04) && ctx.exception != EXCP_SYSCALL && ctx.exception != EXCP_RFI && ctx.exception != EXCP_TRAP)) { -#if !defined(CONFIG_USER_ONLY) - gen_op_queue_exception(EXCP_TRACE); -#endif - if (ctx.exception == EXCP_NONE) { - ctx.exception = EXCP_TRACE; - } + RET_EXCP(ctxp, EXCP_TRACE, 0); } - /* if too long translation, stop generation too */ - if (gen_opc_ptr >= gen_opc_end || - ((uint32_t)ctx.nip - pc_start) >= (TARGET_PAGE_SIZE - 32)) { - if (ctx.exception == EXCP_NONE) { - gen_op_b((uint32_t)ctx.nip); - ctx.exception = EXCP_BRANCH; + /* if we reach a page boundary, stop generation */ + if ((ctx.nip & (TARGET_PAGE_SIZE - 1)) == 0) { + RET_EXCP(ctxp, EXCP_BRANCH, 0); } } - } - /* In case of branch, this has already been done *BEFORE* the branch */ - if (ctx.exception != EXCP_BRANCH && ctx.exception != EXCP_RFI) { - gen_op_update_tb(ctx.tb_offset); - gen_op_update_decr(ctx.decr_offset); - gen_op_process_exceptions((uint32_t)ctx.nip); + if (ctx.exception == EXCP_NONE) { + gen_op_b((unsigned long)ctx.tb, ctx.nip); + } else if (ctx.exception != EXCP_BRANCH) { + gen_op_set_T0(0); } #if 1 /* TO BE FIXED: T0 hasn't got a proper value, which makes tb_add_jump @@ -3180,21 +3166,25 @@ int gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb, } #endif } else { - tb->size = (uint32_t)ctx.nip - pc_start; + tb->size = ctx.nip - pc_start; } #ifdef DEBUG_DISAS - if (loglevel > 0) { + if (loglevel & CPU_LOG_TB_CPU) { fprintf(logfile, "---------------- excp: %04x\n", ctx.exception); cpu_ppc_dump_state(env, logfile, 0); + } + if (loglevel & CPU_LOG_TB_IN_ASM) { fprintf(logfile, "IN: %s\n", lookup_symbol((void *)pc_start)); - disas(logfile, (void *)pc_start, (uint32_t)ctx.nip - pc_start, 0, 0); + disas(logfile, (void *)pc_start, ctx.nip - pc_start, 0, 0); fprintf(logfile, "\n"); - + } + if (loglevel & CPU_LOG_TB_OP) { fprintf(logfile, "OP:\n"); dump_ops(gen_opc_buf, gen_opparam_buf); fprintf(logfile, "\n"); } #endif + env->access_type = ACCESS_INT; return 0; }