FILE *tracefile;
+/* Extract the signed 10-bit offset from a 16-bit branch
+ instruction. */
+#define INST2OFFSET(o) ((((signed short)((o & ((1<<10)-1))<<6))>>6)<<1)
+
#define EXTRACT_WORD(addr) (((addr)[0] << 24) \
+ ((addr)[1] << 16) \
+ ((addr)[2] << 8) \
if (inst & (1 << 14))
{
/* This is a Form 3 instruction. */
- /* We haven't implemented any yet, so just SIGILL for now. */
- TRACE("SIGILL3");
- cpu.asregs.exception = SIGILL;
- break;
+ int opcode = (inst >> 10 & 0xf);
+
+ switch (opcode)
+ {
+ case 0x00: /* beq */
+ {
+ TRACE("beq");
+ if (cpu.asregs.cc & CC_EQ)
+ pc += INST2OFFSET(inst) - 2;
+ }
+ break;
+ case 0x01: /* bne */
+ {
+ TRACE("bne");
+ if (! (cpu.asregs.cc & CC_EQ))
+ pc += INST2OFFSET(inst) - 2;
+ }
+ break;
+ case 0x02: /* blt */
+ {
+ TRACE("blt");
+ if (cpu.asregs.cc & CC_LT)
+ pc += INST2OFFSET(inst) - 2;
+ } break;
+ case 0x03: /* bgt */
+ {
+ TRACE("bgt");
+ if (cpu.asregs.cc & CC_GT)
+ pc += INST2OFFSET(inst) - 2;
+ }
+ break;
+ case 0x04: /* bltu */
+ {
+ TRACE("bltu");
+ if (cpu.asregs.cc & CC_LTU)
+ pc += INST2OFFSET(inst) - 2;
+ }
+ break;
+ case 0x05: /* bgtu */
+ {
+ TRACE("bgtu");
+ if (cpu.asregs.cc & CC_GTU)
+ pc += INST2OFFSET(inst) - 2;
+ }
+ break;
+ case 0x06: /* bge */
+ {
+ TRACE("bge");
+ if (cpu.asregs.cc & (CC_GT | CC_EQ))
+ pc += INST2OFFSET(inst) - 2;
+ }
+ break;
+ case 0x07: /* ble */
+ {
+ TRACE("ble");
+ if (cpu.asregs.cc & (CC_LT | CC_EQ))
+ pc += INST2OFFSET(inst) - 2;
+ }
+ break;
+ case 0x08: /* bgeu */
+ {
+ TRACE("bgeu");
+ if (cpu.asregs.cc & (CC_GTU | CC_EQ))
+ pc += INST2OFFSET(inst) - 2;
+ }
+ break;
+ case 0x09: /* bleu */
+ {
+ TRACE("bleu");
+ if (cpu.asregs.cc & (CC_LTU | CC_EQ))
+ pc += INST2OFFSET(inst) - 2;
+ }
+ break;
+ default:
+ {
+ TRACE("SIGILL3");
+ cpu.asregs.exception = SIGILL;
+ break;
+ }
+ }
}
else
{
cpu.asregs.cc = cc;
}
break;
- case 0x0f: /* beq */
+ case 0x0f:
+ case 0x10:
+ case 0x11:
+ case 0x12:
+ case 0x13:
+ case 0x14:
+ case 0x15:
+ case 0x16:
+ case 0x17:
+ case 0x18:
{
- unsigned int tgt = EXTRACT_WORD(&memory[pc+2]);
- TRACE("beq");
- if (cpu.asregs.cc & CC_EQ)
- {
- pc = tgt - 2;
- }
- else
- pc += 4;
+ opc = opcode;
+ TRACE("SIGILL0");
+ cpu.asregs.exception = SIGILL;
+ break;
}
- break;
- case 0x10: /* bne */
- {
- unsigned int tgt = EXTRACT_WORD(&memory[pc+2]);
- TRACE("bne");
- if (! (cpu.asregs.cc & CC_EQ))
- {
- pc = tgt - 2;
- }
- else
- pc += 4;
- }
- break;
- case 0x11: /* blt */
- {
- unsigned int tgt = EXTRACT_WORD(&memory[pc+2]);
- TRACE("blt");
- if (cpu.asregs.cc & CC_LT)
- {
- pc = tgt - 2;
- }
- else
- pc += 4;
- }
- break;
- case 0x12: /* bgt */
- {
- unsigned int tgt = EXTRACT_WORD(&memory[pc+2]);
- TRACE("bgt");
- if (cpu.asregs.cc & CC_GT)
- {
- pc = tgt - 2;
- }
- else
- pc += 4;
- }
- break;
- case 0x13: /* bltu */
- {
- unsigned int tgt = EXTRACT_WORD(&memory[pc+2]);
- TRACE("bltu");
- if (cpu.asregs.cc & CC_LTU)
- {
- pc = tgt - 2;
- }
- else
- pc += 4;
- }
- break;
- case 0x14: /* bgtu */
- {
- unsigned int tgt = EXTRACT_WORD(&memory[pc+2]);
- TRACE("bgtu");
- if (cpu.asregs.cc & CC_GTU)
- {
- pc = tgt - 2;
- }
- else
- pc += 4;
- }
- break;
- case 0x15: /* bge */
- {
- unsigned int tgt = EXTRACT_WORD(&memory[pc+2]);
- TRACE("bge");
- if ((cpu.asregs.cc & CC_GT) || (cpu.asregs.cc & CC_EQ))
- {
- pc = tgt - 2;
- }
- else
- pc += 4;
- }
- break;
- case 0x16: /* ble */
- {
- unsigned int tgt = EXTRACT_WORD(&memory[pc+2]);
- TRACE("ble");
- if ((cpu.asregs.cc & CC_LT) || (cpu.asregs.cc & CC_EQ))
- {
- pc = tgt - 2;
- }
- else
- pc += 4;
- }
- break;
- case 0x17: /* bgeu */
- {
- unsigned int tgt = EXTRACT_WORD(&memory[pc+2]);
- TRACE("bgeu");
- if ((cpu.asregs.cc & CC_GTU) || (cpu.asregs.cc & CC_EQ))
- {
- pc = tgt - 2;
- }
- else
- pc += 4;
- }
- break;
- case 0x18: /* bleu */
- {
- unsigned int tgt = EXTRACT_WORD(&memory[pc+2]);
- TRACE("bleu");
- if ((cpu.asregs.cc & CC_LTU) || (cpu.asregs.cc & CC_EQ))
- {
- pc = tgt - 2;
- }
- else
- pc += 4;
- }
- break;
case 0x19: /* jsr */
{
unsigned int fn = cpu.asregs.regs[(inst >> 4) & 0xf];