diff options
author | bellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162> | 2005-02-13 20:11:30 +0000 |
---|---|---|
committer | bellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162> | 2005-02-13 20:11:30 +0000 |
commit | 0bee699e1db8170071902dbbde9c6b932883a897 (patch) | |
tree | af0252d51ee4aa301a16a7d66e35818943e94d39 /target-sparc | |
parent | 878d3096d20c3b77f5aaa25460d470bc7d8da15b (diff) |
fixed jmpl, rett and call
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1292 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'target-sparc')
-rw-r--r-- | target-sparc/op.c | 5 | ||||
-rw-r--r-- | target-sparc/translate.c | 34 |
2 files changed, 32 insertions, 7 deletions
diff --git a/target-sparc/op.c b/target-sparc/op.c index dd8295e559..7fa98f16b6 100644 --- a/target-sparc/op.c +++ b/target-sparc/op.c @@ -812,6 +812,11 @@ void OPPROTO op_movl_npc_T0(void) env->npc = T0; } +void OPPROTO op_mov_pc_npc(void) +{ + env->pc = env->npc; +} + void OPPROTO op_next_insn(void) { env->pc = env->npc; diff --git a/target-sparc/translate.c b/target-sparc/translate.c index 0baf8036e0..7b56428280 100644 --- a/target-sparc/translate.c +++ b/target-sparc/translate.c @@ -427,6 +427,20 @@ static inline void save_state(DisasContext * dc) save_npc(dc); } +static inline void gen_mov_pc_npc(DisasContext * dc) +{ + if (dc->npc == JUMP_PC) { + gen_op_generic_branch(dc->jump_pc[0], dc->jump_pc[1]); + gen_op_mov_pc_npc(); + dc->pc = DYNAMIC_PC; + } else if (dc->npc == DYNAMIC_PC) { + gen_op_mov_pc_npc(); + dc->pc = DYNAMIC_PC; + } else { + dc->pc = dc->npc; + } +} + static void gen_cond(int cond) { switch (cond) { @@ -525,6 +539,7 @@ static void gen_fcond(int cond) } } +/* XXX: potentially incorrect if dynamic npc */ static void do_branch(DisasContext * dc, int32_t offset, uint32_t insn) { unsigned int cond = GET_FIELD(insn, 3, 6), a = (insn & (1 << 29)); @@ -533,7 +548,7 @@ static void do_branch(DisasContext * dc, int32_t offset, uint32_t insn) if (cond == 0x0) { /* unconditional not taken */ if (a) { - dc->pc = dc->npc + 4; + dc->pc = dc->npc + 4; dc->npc = dc->pc + 4; } else { dc->pc = dc->npc; @@ -563,6 +578,7 @@ static void do_branch(DisasContext * dc, int32_t offset, uint32_t insn) } } +/* XXX: potentially incorrect if dynamic npc */ static void do_fbranch(DisasContext * dc, int32_t offset, uint32_t insn) { unsigned int cond = GET_FIELD(insn, 3, 6), a = (insn & (1 << 29)); @@ -609,6 +625,7 @@ static int sign_extend(int x, int len) return (x << len) >> len; } +/* before an instruction, dc->pc must be static */ static void disas_sparc_insn(DisasContext * dc) { unsigned int insn, opc, rs1, rs2, rd; @@ -669,7 +686,7 @@ static void disas_sparc_insn(DisasContext * dc) gen_op_movl_T0_im(dc->pc); gen_movl_T0_reg(15); target += dc->pc; - dc->pc = dc->npc; + gen_mov_pc_npc(dc); dc->npc = target; } goto jmp_insn; @@ -1173,12 +1190,12 @@ static void disas_sparc_insn(DisasContext * dc) switch (xop) { case 0x38: /* jmpl */ { - gen_op_movl_npc_T0(); if (rd != 0) { - gen_op_movl_T0_im(dc->pc); - gen_movl_T0_reg(rd); + gen_op_movl_T1_im(dc->pc); + gen_movl_T1_reg(rd); } - dc->pc = dc->npc; + gen_mov_pc_npc(dc); + gen_op_movl_npc_T0(); dc->npc = DYNAMIC_PC; } goto jmp_insn; @@ -1187,10 +1204,12 @@ static void disas_sparc_insn(DisasContext * dc) { if (!supervisor(dc)) goto priv_insn; + gen_mov_pc_npc(dc); gen_op_movl_npc_T0(); + dc->npc = DYNAMIC_PC; gen_op_rett(); } - break; + goto jmp_insn; #endif case 0x3b: /* flush */ gen_op_flush_T0(); @@ -1605,6 +1624,7 @@ void cpu_reset(CPUSPARCState *env) env->user_mode_only = 1; #else env->psrs = 1; + env->psrps = 1; env->pc = 0xffd00000; env->gregs[1] = ram_size; env->mmuregs[0] = (0x04 << 24); /* Impl 0, ver 4, MMU disabled */ |