Virtualmips: merge changes from alexfru.

Fix bug in mips16 disassembler.
This commit is contained in:
Serge Vakulenko
2015-10-30 10:47:11 -07:00
parent 42fd2f99bd
commit b259f58533
3 changed files with 75 additions and 17 deletions

View File

@@ -709,7 +709,7 @@ print_insn_args (const char *d,
default: default:
/* xgettext:c-format */ /* xgettext:c-format */
fprintf (stream, "# internal error, undefined modifier (%c)", *d); fprintf (stream, "# internal error, undefined modifier (%c)\n", *d);
return; return;
} }
} }
@@ -1186,7 +1186,7 @@ print_mips16_insn_arg (char type,
default: default:
/* xgettext:c-format */ /* xgettext:c-format */
fprintf (stream, "# internal disassembler error, unrecognised modifier (%c)", type); fprintf (stream, "# internal disassembler error, unrecognised modifier (%c)\n", type);
abort (); abort ();
} }
} }
@@ -1255,9 +1255,10 @@ static void print_insn_mips16 (unsigned memaddr,
} }
} }
fprintf (stream, "0x");
if (use_extend) if (use_extend)
fprintf (stream, "0x%x", extend | 0xf000); fprintf (stream, "%04x", extend | 0xf000);
fprintf (stream, "0x%x", insn); fprintf (stream, "%04x", insn);
} }
/* /*

View File

@@ -138,7 +138,6 @@ static const struct mips_opcode mips16_opcodes[] =
{"exit", "L", 0xee09, 0xff1f, TRAP, }, {"exit", "L", 0xee09, 0xff1f, TRAP, },
{"exit", "L", 0xef09, 0xff1f, TRAP, }, {"exit", "L", 0xef09, 0xff1f, TRAP, },
{"entry", "l", 0xe809, 0xf81f, TRAP, }, {"entry", "l", 0xe809, 0xf81f, TRAP, },
{"extend", "e", 0xf000, 0xf800, 0, },
{"jalr", "x", 0xe840, 0xf8ff, UBD|WR_31|RD_x, }, {"jalr", "x", 0xe840, 0xf8ff, UBD|WR_31|RD_x, },
{"jalr", "R,x", 0xe840, 0xf8ff, UBD|WR_31|RD_x, }, {"jalr", "R,x", 0xe840, 0xf8ff, UBD|WR_31|RD_x, },
{"jal", "x", 0xe840, 0xf8ff, UBD|WR_31|RD_x, }, {"jal", "x", 0xe840, 0xf8ff, UBD|WR_31|RD_x, },

View File

@@ -2208,10 +2208,10 @@ static int mips_exec_mips16e(cpu_mips_t* cpu, mips_insn_t instr)
res = 1; res = 1;
} else if (!extend) { } else if (!extend) {
switch (op) { switch (op) {
case 0: // addiu[sp] rx, sp, imm8 case 0: // addiu[sp] rx, sp, imm8<<2
cpu->reg_set(cpu, xlat(rx), cpu->gpr[MIPS_GPR_SP] + (imm8 << 2)); cpu->reg_set(cpu, xlat(rx), cpu->gpr[MIPS_GPR_SP] + (imm8 << 2));
break; break;
case 1: // addiu[pc] rx, pc, imm8 case 1: // addiu[pc] rx, pc, imm8<<2
cpu->reg_set(cpu, xlat(rx), (pc + (imm8 << 2)) & 0xFFFFFFFC); cpu->reg_set(cpu, xlat(rx), (pc + (imm8 << 2)) & 0xFFFFFFFC);
break; break;
case 2: // b ofs11<<1 (no delay slot) case 2: // b ofs11<<1 (no delay slot)
@@ -2246,10 +2246,12 @@ static int mips_exec_mips16e(cpu_mips_t* cpu, mips_insn_t instr)
goto lInvalidInstruction; goto lInvalidInstruction;
} }
break; break;
case 8: // addiu ry, rx, imm4 case 8: // RRI-A addiu ry, rx, simm4
if (unlikely(instr & 0x10))
goto lInvalidInstruction;
cpu->reg_set(cpu, xlat(ry), cpu->gpr[xlat(rx)] + simm4); cpu->reg_set(cpu, xlat(ry), cpu->gpr[xlat(rx)] + simm4);
break; break;
case 9: // addiu[8] rx, imm8 case 9: // addiu[8] rx, simm8
cpu->reg_set(cpu, xlat(rx), cpu->gpr[xlat(rx)] + simm8); cpu->reg_set(cpu, xlat(rx), cpu->gpr[xlat(rx)] + simm8);
break; break;
case 10: // slti rx, imm8 case 10: // slti rx, imm8
@@ -2275,7 +2277,7 @@ static int mips_exec_mips16e(cpu_mips_t* cpu, mips_insn_t instr)
case 2: // sw[rasp] ra, ofs8<<2(sp) case 2: // sw[rasp] ra, ofs8<<2(sp)
res = mips_exec_memop2(cpu, MIPS_MEMOP_SW, MIPS_GPR_SP, imm8 << 2, MIPS_GPR_RA, FALSE); res = mips_exec_memop2(cpu, MIPS_MEMOP_SW, MIPS_GPR_SP, imm8 << 2, MIPS_GPR_RA, FALSE);
break; break;
case 3: // ADJSP AKA addiu sp, imm8 case 3: // ADJSP AKA addiu sp, simm8<<3
cpu->reg_set(cpu, MIPS_GPR_SP, cpu->gpr[MIPS_GPR_SP] + (simm8 << 3)); cpu->reg_set(cpu, MIPS_GPR_SP, cpu->gpr[MIPS_GPR_SP] + (simm8 << 3));
break; break;
case 4: // SVRS case 4: // SVRS
@@ -2375,6 +2377,8 @@ static int mips_exec_mips16e(cpu_mips_t* cpu, mips_insn_t instr)
res = 1; res = 1;
break; break;
case 1: // jr ra (delay slot) case 1: // jr ra (delay slot)
if (unlikely(rx))
goto lInvalidInstruction;
nextPc = cpu->gpr[MIPS_GPR_RA]; nextPc = cpu->gpr[MIPS_GPR_RA];
if (mips_exec_bdslot(cpu) == 0) { if (mips_exec_bdslot(cpu) == 0) {
cpu->pc = nextPc & 0xFFFFFFFE; cpu->pc = nextPc & 0xFFFFFFFE;
@@ -2398,6 +2402,8 @@ static int mips_exec_mips16e(cpu_mips_t* cpu, mips_insn_t instr)
res = 1; res = 1;
break; break;
case 5: // jrc ra (no delay slot) case 5: // jrc ra (no delay slot)
if (unlikely(rx))
goto lInvalidInstruction;
nextPc = cpu->gpr[MIPS_GPR_RA]; nextPc = cpu->gpr[MIPS_GPR_RA];
cpu->pc = nextPc & 0xFFFFFFFE; cpu->pc = nextPc & 0xFFFFFFFE;
cpu->is_mips16e = nextPc & 1; // may switch to MIPS32 cpu->is_mips16e = nextPc & 1; // may switch to MIPS32
@@ -2454,6 +2460,8 @@ static int mips_exec_mips16e(cpu_mips_t* cpu, mips_insn_t instr)
cpu->reg_set(cpu, xlat(rx), ~cpu->gpr[xlat(ry)]); cpu->reg_set(cpu, xlat(rx), ~cpu->gpr[xlat(ry)]);
break; break;
case 16: // mfhi rx case 16: // mfhi rx
if (unlikely(ry))
goto lInvalidInstruction;
cpu->reg_set(cpu, xlat(rx), cpu->hi); cpu->reg_set(cpu, xlat(rx), cpu->hi);
break; break;
case 17: // CNVT case 17: // CNVT
@@ -2475,6 +2483,8 @@ static int mips_exec_mips16e(cpu_mips_t* cpu, mips_insn_t instr)
} }
break; break;
case 18: // mflo rx case 18: // mflo rx
if (unlikely(ry))
goto lInvalidInstruction;
cpu->reg_set(cpu, xlat(rx), cpu->lo); cpu->reg_set(cpu, xlat(rx), cpu->lo);
break; break;
case 24: { // mult rx, ry case 24: { // mult rx, ry
@@ -2512,25 +2522,37 @@ static int mips_exec_mips16e(cpu_mips_t* cpu, mips_insn_t instr)
// ^^^ NON-EXTENDED ^^^ // ^^^ NON-EXTENDED ^^^
} else { } else {
// vvv EXTENDED vvv // vvv EXTENDED vvv
if (unlikely(cpu->is_in_bdslot))
goto lInvalidInstruction;
switch (op) { switch (op) {
case 0: // addiu[sp] rx, sp, imm16 case 0: // addiu[sp] rx, sp, simm16
if (unlikely(ry))
goto lInvalidInstruction;
cpu->reg_set(cpu, xlat(rx), cpu->gpr[MIPS_GPR_SP] + simm16); cpu->reg_set(cpu, xlat(rx), cpu->gpr[MIPS_GPR_SP] + simm16);
break; break;
case 1: // addiu[pc] rx, pc, imm16 case 1: // addiu[pc] rx, pc, simm16
if (unlikely(ry))
goto lInvalidInstruction;
cpu->reg_set(cpu, xlat(rx), (pc & 0xFFFFFFFC) + simm16); cpu->reg_set(cpu, xlat(rx), (pc & 0xFFFFFFFC) + simm16);
break; break;
case 2: // b ofs16<<1 (no delay slot) case 2: // b ofs16<<1 (no delay slot)
if (unlikely(instr & 0x7E0))
goto lInvalidInstruction;
nextPc += simm16 << 1; nextPc += simm16 << 1;
cpu->pc = nextPc; cpu->pc = nextPc;
res = 1; res = 1;
break; break;
case 4: // beqz rx, ofs16<<1 (no delay slot) case 4: // beqz rx, ofs16<<1 (no delay slot)
if (unlikely(ry))
goto lInvalidInstruction;
if (cpu->gpr[xlat(rx)] == 0) if (cpu->gpr[xlat(rx)] == 0)
nextPc += simm16 << 1; nextPc += simm16 << 1;
cpu->pc = nextPc; cpu->pc = nextPc;
res = 1; res = 1;
break; break;
case 5: // bnez rx, ofs16<<1 (no delay slot) case 5: // bnez rx, ofs16<<1 (no delay slot)
if (unlikely(ry))
goto lInvalidInstruction;
if (cpu->gpr[xlat(rx)] != 0) if (cpu->gpr[xlat(rx)] != 0)
nextPc += simm16 << 1; nextPc += simm16 << 1;
cpu->pc = nextPc; cpu->pc = nextPc;
@@ -2539,48 +2561,70 @@ static int mips_exec_mips16e(cpu_mips_t* cpu, mips_insn_t instr)
case 6: // SHIFT case 6: // SHIFT
switch (imm2) { switch (imm2) {
case 0: // sll rx, ry, imm5 case 0: // sll rx, ry, imm5
if (unlikely((extend & 0x3F) | rz))
goto lInvalidInstruction;
cpu->reg_set(cpu, xlat(rx), cpu->gpr[xlat(ry)] << sa5); cpu->reg_set(cpu, xlat(rx), cpu->gpr[xlat(ry)] << sa5);
break; break;
case 2: // srl rx, ry, imm5 case 2: // srl rx, ry, imm5
if (unlikely((extend & 0x3F) | rz))
goto lInvalidInstruction;
cpu->reg_set(cpu, xlat(rx), cpu->gpr[xlat(ry)] >> sa5); cpu->reg_set(cpu, xlat(rx), cpu->gpr[xlat(ry)] >> sa5);
break; break;
case 3: // sra rx, ry, imm5 case 3: // sra rx, ry, imm5
if (unlikely((extend & 0x3F) | rz))
goto lInvalidInstruction;
cpu->reg_set(cpu, xlat(rx), (int32_t)cpu->gpr[xlat(ry)] >> sa5); cpu->reg_set(cpu, xlat(rx), (int32_t)cpu->gpr[xlat(ry)] >> sa5);
break; break;
default: default:
goto lInvalidInstruction; goto lInvalidInstruction;
} }
break; break;
case 8: // addiu ry, rx, imm15 case 8: // RRI-A addiu ry, rx, simm15
if (unlikely(instr & 0x10))
goto lInvalidInstruction;
cpu->reg_set(cpu, xlat(ry), cpu->gpr[xlat(rx)] + simm15); cpu->reg_set(cpu, xlat(ry), cpu->gpr[xlat(rx)] + simm15);
break; break;
case 9: // addiu rx, imm16 case 9: // addiu rx, simm16
if (unlikely(ry))
goto lInvalidInstruction;
cpu->reg_set(cpu, xlat(rx), cpu->gpr[xlat(rx)] + simm16); cpu->reg_set(cpu, xlat(rx), cpu->gpr[xlat(rx)] + simm16);
break; break;
case 10: // slti rx, imm16 case 10: // slti rx, simm16
if (unlikely(ry))
goto lInvalidInstruction;
cpu->reg_set(cpu, MIPS_GPR_T8, (int32_t)cpu->gpr[xlat(rx)] < simm16); cpu->reg_set(cpu, MIPS_GPR_T8, (int32_t)cpu->gpr[xlat(rx)] < simm16);
break; break;
case 11: // sltiu rx, imm16 case 11: // sltiu rx, simm16
if (unlikely(ry))
goto lInvalidInstruction;
cpu->reg_set(cpu, MIPS_GPR_T8, cpu->gpr[xlat(rx)] < (uint32_t)simm16); cpu->reg_set(cpu, MIPS_GPR_T8, cpu->gpr[xlat(rx)] < (uint32_t)simm16);
break; break;
case 12: // I8 case 12: // I8
switch (rx) { switch (rx) {
case 0: // bteqz ofs16<<1 (no delay slot) case 0: // bteqz ofs16<<1 (no delay slot)
if (unlikely(ry))
goto lInvalidInstruction;
if (cpu->gpr[MIPS_GPR_T8] == 0) if (cpu->gpr[MIPS_GPR_T8] == 0)
nextPc += simm16 << 1; nextPc += simm16 << 1;
cpu->pc = nextPc; cpu->pc = nextPc;
res = 1; res = 1;
break; break;
case 1: // btnez ofs16<<1 (no delay slot) case 1: // btnez ofs16<<1 (no delay slot)
if (unlikely(ry))
goto lInvalidInstruction;
if (cpu->gpr[MIPS_GPR_T8] != 0) if (cpu->gpr[MIPS_GPR_T8] != 0)
nextPc += simm16 << 1; nextPc += simm16 << 1;
cpu->pc = nextPc; cpu->pc = nextPc;
res = 1; res = 1;
break; break;
case 2: // sw[rasp] ra, ofs16(sp) case 2: // sw[rasp] ra, ofs16(sp)
if (unlikely(ry))
goto lInvalidInstruction;
res = mips_exec_memop2(cpu, MIPS_MEMOP_SW, MIPS_GPR_SP, simm16, MIPS_GPR_RA, FALSE); res = mips_exec_memop2(cpu, MIPS_MEMOP_SW, MIPS_GPR_SP, simm16, MIPS_GPR_RA, FALSE);
break; break;
case 3: // ADJSP AKA addiu sp, imm16 case 3: // ADJSP AKA addiu sp, simm16
if (unlikely(ry))
goto lInvalidInstruction;
cpu->reg_set(cpu, MIPS_GPR_SP, cpu->gpr[MIPS_GPR_SP] + simm16); cpu->reg_set(cpu, MIPS_GPR_SP, cpu->gpr[MIPS_GPR_SP] + simm16);
break; break;
case 4: { // SVRS case 4: { // SVRS
@@ -2592,6 +2636,8 @@ static int mips_exec_mips16e(cpu_mips_t* cpu, mips_insn_t instr)
case 2: case 6: case 10: astatic = 2; break; case 2: case 6: case 10: astatic = 2; break;
case 3: case 7: astatic = 3; break; case 3: case 7: astatic = 3; break;
case 11: astatic = 4; break; case 11: astatic = 4; break;
case 15:
goto lInvalidInstruction; // TBD!!! or address error???
} }
if (instr & 0x80) { // save if (instr & 0x80) { // save
uint32_t args = 0; uint32_t args = 0;
@@ -2600,6 +2646,8 @@ static int mips_exec_mips16e(cpu_mips_t* cpu, mips_insn_t instr)
case 8: case 9: case 10: args = 2; break; case 8: case 9: case 10: args = 2; break;
case 12: case 13: args = 3; break; case 12: case 13: args = 3; break;
case 14: args = 4; break; case 14: args = 4; break;
case 15:
goto lInvalidInstruction; // TBD!!! or address error???
} }
temp = cpu->gpr[MIPS_GPR_SP]; temp = cpu->gpr[MIPS_GPR_SP];
cpu->reg_set(cpu, MIPS_GPR_SP, cpu->gpr[MIPS_GPR_SP] - fmsz8 * 8); cpu->reg_set(cpu, MIPS_GPR_SP, cpu->gpr[MIPS_GPR_SP] - fmsz8 * 8);
@@ -2637,9 +2685,13 @@ static int mips_exec_mips16e(cpu_mips_t* cpu, mips_insn_t instr)
} }
break; break;
case 13: // li rx, imm16 case 13: // li rx, imm16
if (unlikely(ry))
goto lInvalidInstruction;
cpu->reg_set(cpu, xlat(rx), imm16); cpu->reg_set(cpu, xlat(rx), imm16);
break; break;
case 14: // cmpi rx, imm16 case 14: // cmpi rx, imm16
if (unlikely(ry))
goto lInvalidInstruction;
cpu->reg_set(cpu, MIPS_GPR_T8, cpu->gpr[xlat(rx)] ^ imm16); cpu->reg_set(cpu, MIPS_GPR_T8, cpu->gpr[xlat(rx)] ^ imm16);
break; break;
case 16: // lb ry, ofs16(rx) case 16: // lb ry, ofs16(rx)
@@ -2649,6 +2701,8 @@ static int mips_exec_mips16e(cpu_mips_t* cpu, mips_insn_t instr)
res = mips_exec_memop2(cpu, MIPS_MEMOP_LH, xlat(rx), simm16, xlat(ry), TRUE); res = mips_exec_memop2(cpu, MIPS_MEMOP_LH, xlat(rx), simm16, xlat(ry), TRUE);
break; break;
case 18: // lw[sp] rx, ofs16(sp) case 18: // lw[sp] rx, ofs16(sp)
if (unlikely(ry))
goto lInvalidInstruction;
res = mips_exec_memop2(cpu, MIPS_MEMOP_LW, MIPS_GPR_SP, simm16, xlat(rx), TRUE); res = mips_exec_memop2(cpu, MIPS_MEMOP_LW, MIPS_GPR_SP, simm16, xlat(rx), TRUE);
break; break;
case 19: // lw ry, ofs16(rx) case 19: // lw ry, ofs16(rx)
@@ -2661,6 +2715,8 @@ static int mips_exec_mips16e(cpu_mips_t* cpu, mips_insn_t instr)
res = mips_exec_memop2(cpu, MIPS_MEMOP_LHU, xlat(rx), simm16, xlat(ry), TRUE); res = mips_exec_memop2(cpu, MIPS_MEMOP_LHU, xlat(rx), simm16, xlat(ry), TRUE);
break; break;
case 22: // lw[pc] rx, ofs16(pc) case 22: // lw[pc] rx, ofs16(pc)
if (unlikely(ry))
goto lInvalidInstruction;
res = mips_exec_memop(cpu, MIPS_MEMOP_LW, (pc & 0xFFFFFFFC) + simm16, xlat(rx), TRUE); res = mips_exec_memop(cpu, MIPS_MEMOP_LW, (pc & 0xFFFFFFFC) + simm16, xlat(rx), TRUE);
break; break;
case 24: // sb ry, ofs16(rx) case 24: // sb ry, ofs16(rx)
@@ -2670,6 +2726,8 @@ static int mips_exec_mips16e(cpu_mips_t* cpu, mips_insn_t instr)
res = mips_exec_memop2(cpu, MIPS_MEMOP_SH, xlat(rx), simm16, xlat(ry), FALSE); res = mips_exec_memop2(cpu, MIPS_MEMOP_SH, xlat(rx), simm16, xlat(ry), FALSE);
break; break;
case 26: // sw[sp] rx, ofs16(sp) case 26: // sw[sp] rx, ofs16(sp)
if (unlikely(ry))
goto lInvalidInstruction;
res = mips_exec_memop2(cpu, MIPS_MEMOP_SW, MIPS_GPR_SP, simm16, xlat(rx), FALSE); res = mips_exec_memop2(cpu, MIPS_MEMOP_SW, MIPS_GPR_SP, simm16, xlat(rx), FALSE);
break; break;
case 27: // sw ry, ofs16(rx) case 27: // sw ry, ofs16(rx)