Commit 0bee699e1db8170071902dbbde9c6b932883a897
1 parent
878d3096
fixed jmpl, rett and call
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1292 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
2 changed files
with
32 additions
and
7 deletions
target-sparc/op.c
target-sparc/translate.c
| ... | ... | @@ -427,6 +427,20 @@ static inline void save_state(DisasContext * dc) |
| 427 | 427 | save_npc(dc); |
| 428 | 428 | } |
| 429 | 429 | |
| 430 | +static inline void gen_mov_pc_npc(DisasContext * dc) | |
| 431 | +{ | |
| 432 | + if (dc->npc == JUMP_PC) { | |
| 433 | + gen_op_generic_branch(dc->jump_pc[0], dc->jump_pc[1]); | |
| 434 | + gen_op_mov_pc_npc(); | |
| 435 | + dc->pc = DYNAMIC_PC; | |
| 436 | + } else if (dc->npc == DYNAMIC_PC) { | |
| 437 | + gen_op_mov_pc_npc(); | |
| 438 | + dc->pc = DYNAMIC_PC; | |
| 439 | + } else { | |
| 440 | + dc->pc = dc->npc; | |
| 441 | + } | |
| 442 | +} | |
| 443 | + | |
| 430 | 444 | static void gen_cond(int cond) |
| 431 | 445 | { |
| 432 | 446 | switch (cond) { |
| ... | ... | @@ -525,6 +539,7 @@ static void gen_fcond(int cond) |
| 525 | 539 | } |
| 526 | 540 | } |
| 527 | 541 | |
| 542 | +/* XXX: potentially incorrect if dynamic npc */ | |
| 528 | 543 | static void do_branch(DisasContext * dc, int32_t offset, uint32_t insn) |
| 529 | 544 | { |
| 530 | 545 | 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) |
| 533 | 548 | if (cond == 0x0) { |
| 534 | 549 | /* unconditional not taken */ |
| 535 | 550 | if (a) { |
| 536 | - dc->pc = dc->npc + 4; | |
| 551 | + dc->pc = dc->npc + 4; | |
| 537 | 552 | dc->npc = dc->pc + 4; |
| 538 | 553 | } else { |
| 539 | 554 | dc->pc = dc->npc; |
| ... | ... | @@ -563,6 +578,7 @@ static void do_branch(DisasContext * dc, int32_t offset, uint32_t insn) |
| 563 | 578 | } |
| 564 | 579 | } |
| 565 | 580 | |
| 581 | +/* XXX: potentially incorrect if dynamic npc */ | |
| 566 | 582 | static void do_fbranch(DisasContext * dc, int32_t offset, uint32_t insn) |
| 567 | 583 | { |
| 568 | 584 | unsigned int cond = GET_FIELD(insn, 3, 6), a = (insn & (1 << 29)); |
| ... | ... | @@ -609,6 +625,7 @@ static int sign_extend(int x, int len) |
| 609 | 625 | return (x << len) >> len; |
| 610 | 626 | } |
| 611 | 627 | |
| 628 | +/* before an instruction, dc->pc must be static */ | |
| 612 | 629 | static void disas_sparc_insn(DisasContext * dc) |
| 613 | 630 | { |
| 614 | 631 | unsigned int insn, opc, rs1, rs2, rd; |
| ... | ... | @@ -669,7 +686,7 @@ static void disas_sparc_insn(DisasContext * dc) |
| 669 | 686 | gen_op_movl_T0_im(dc->pc); |
| 670 | 687 | gen_movl_T0_reg(15); |
| 671 | 688 | target += dc->pc; |
| 672 | - dc->pc = dc->npc; | |
| 689 | + gen_mov_pc_npc(dc); | |
| 673 | 690 | dc->npc = target; |
| 674 | 691 | } |
| 675 | 692 | goto jmp_insn; |
| ... | ... | @@ -1173,12 +1190,12 @@ static void disas_sparc_insn(DisasContext * dc) |
| 1173 | 1190 | switch (xop) { |
| 1174 | 1191 | case 0x38: /* jmpl */ |
| 1175 | 1192 | { |
| 1176 | - gen_op_movl_npc_T0(); | |
| 1177 | 1193 | if (rd != 0) { |
| 1178 | - gen_op_movl_T0_im(dc->pc); | |
| 1179 | - gen_movl_T0_reg(rd); | |
| 1194 | + gen_op_movl_T1_im(dc->pc); | |
| 1195 | + gen_movl_T1_reg(rd); | |
| 1180 | 1196 | } |
| 1181 | - dc->pc = dc->npc; | |
| 1197 | + gen_mov_pc_npc(dc); | |
| 1198 | + gen_op_movl_npc_T0(); | |
| 1182 | 1199 | dc->npc = DYNAMIC_PC; |
| 1183 | 1200 | } |
| 1184 | 1201 | goto jmp_insn; |
| ... | ... | @@ -1187,10 +1204,12 @@ static void disas_sparc_insn(DisasContext * dc) |
| 1187 | 1204 | { |
| 1188 | 1205 | if (!supervisor(dc)) |
| 1189 | 1206 | goto priv_insn; |
| 1207 | + gen_mov_pc_npc(dc); | |
| 1190 | 1208 | gen_op_movl_npc_T0(); |
| 1209 | + dc->npc = DYNAMIC_PC; | |
| 1191 | 1210 | gen_op_rett(); |
| 1192 | 1211 | } |
| 1193 | - break; | |
| 1212 | + goto jmp_insn; | |
| 1194 | 1213 | #endif |
| 1195 | 1214 | case 0x3b: /* flush */ |
| 1196 | 1215 | gen_op_flush_T0(); |
| ... | ... | @@ -1605,6 +1624,7 @@ void cpu_reset(CPUSPARCState *env) |
| 1605 | 1624 | env->user_mode_only = 1; |
| 1606 | 1625 | #else |
| 1607 | 1626 | env->psrs = 1; |
| 1627 | + env->psrps = 1; | |
| 1608 | 1628 | env->pc = 0xffd00000; |
| 1609 | 1629 | env->gregs[1] = ram_size; |
| 1610 | 1630 | env->mmuregs[0] = (0x04 << 24); /* Impl 0, ver 4, MMU disabled */ | ... | ... |