# HG changeset patch # User Mike Pavone # Date 1357537377 28800 # Node ID e2918b5208ebc6fe5a38b12da7e8953e67489307 # Parent 7504200cac863dc99bf88102d84d8e99857f17c9 Print a message when we try to run an invalid instruction, not when we try to translate it diff -r 7504200cac86 -r e2918b5208eb 68kinst.c --- a/68kinst.c Sun Jan 06 20:49:42 2013 -0800 +++ b/68kinst.c Sun Jan 06 21:42:57 2013 -0800 @@ -85,6 +85,8 @@ break; } break; + default: + return NULL; } break; } @@ -110,6 +112,7 @@ uint16_t * m68k_decode(uint16_t * istream, m68kinst * decoded, uint32_t address) { + uint16_t *start = istream; uint8_t optype = *istream >> 12; uint8_t size; uint8_t reg; @@ -162,6 +165,10 @@ decoded->src.params.regs.pri = m68k_reg_quick_field(*istream); decoded->extra.size = OPSIZE_BYTE; istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->dst)); + if (!istream) { + decoded->op = M68K_INVALID; + return start+1; + } if (decoded->dst.addr_mode == MODE_REG) { decoded->extra.size = OPSIZE_LONG; } @@ -188,6 +195,10 @@ decoded->src.params.immed = *(++istream) & 0xFF; decoded->extra.size = OPSIZE_BYTE; istream = m68k_decode_op_ex(istream, opmode, reg, decoded->extra.size, &(decoded->dst)); + if (!istream) { + decoded->op = M68K_INVALID; + return start+1; + } if (decoded->dst.addr_mode == MODE_REG) { decoded->extra.size = OPSIZE_LONG; } @@ -230,6 +241,10 @@ break; } istream = m68k_decode_op_ex(istream, opmode, reg, size, &(decoded->dst)); + if (!istream) { + decoded->op = M68K_INVALID; + return start+1; + } } break; case 1: @@ -265,6 +280,10 @@ break; } istream = m68k_decode_op_ex(istream, opmode, reg, size, &(decoded->dst)); + if (!istream) { + decoded->op = M68K_INVALID; + return start+1; + } } break; case 2: @@ -288,6 +307,10 @@ break; } istream = m68k_decode_op_ex(istream, opmode, reg, size, &(decoded->dst)); + if (!istream) { + decoded->op = M68K_INVALID; + return start+1; + } break; case 3: decoded->op = M68K_ADD; @@ -310,6 +333,10 @@ break; } istream = m68k_decode_op_ex(istream, opmode, reg, size, &(decoded->dst)); + if (!istream) { + decoded->op = M68K_INVALID; + return start+1; + } break; case 4: //BTST, BCHG, BCLR, BSET @@ -331,6 +358,10 @@ decoded->src.addr_mode = MODE_IMMEDIATE; decoded->src.params.immed = *(++istream) & 0xFF; istream = m68k_decode_op(istream, OPSIZE_BYTE, &(decoded->dst)); + if (!istream) { + decoded->op = M68K_INVALID; + return start+1; + } break; case 5: //EORI, EORI to CCR, EORI to SR @@ -365,6 +396,10 @@ break; } istream = m68k_decode_op_ex(istream, opmode, reg, size, &(decoded->dst)); + if (!istream) { + decoded->op = M68K_INVALID; + return start+1; + } } break; case 6: @@ -388,6 +423,10 @@ break; } istream = m68k_decode_op_ex(istream, opmode, reg, size, &(decoded->dst)); + if (!istream) { + decoded->op = M68K_INVALID; + return start+1; + } break; case 7: @@ -404,7 +443,15 @@ opmode = (*istream >> 6) & 0x7; reg = m68k_reg_quick_field(*istream); istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->src)); + if (!istream) { + decoded->op = M68K_INVALID; + return start+1; + } istream = m68k_decode_op_ex(istream, opmode, reg, decoded->extra.size, &(decoded->dst)); + if (!istream) { + decoded->op = M68K_INVALID; + return start+1; + } break; case MISC: @@ -414,6 +461,10 @@ decoded->dst.addr_mode = MODE_AREG; decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream); istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->src)); + if (!istream) { + decoded->op = M68K_INVALID; + return start+1; + } } else { if (*istream & 0x100) { decoded->op = M68K_CHK; @@ -429,6 +480,10 @@ #endif } istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->src)); + if (!istream) { + decoded->op = M68K_INVALID; + return start+1; + } decoded->dst.addr_mode = MODE_REG; decoded->dst.addr_mode = m68k_reg_quick_field(*istream); } else { @@ -442,10 +497,18 @@ decoded->dst.addr_mode = MODE_REG; decoded->dst.params.immed = *(++istream); istream = m68k_decode_op_ex(istream, opmode, reg, decoded->extra.size, &(decoded->src)); + if (!istream) { + decoded->op = M68K_INVALID; + return start+1; + } } else { decoded->src.addr_mode = MODE_REG; decoded->src.params.immed = *(++istream); istream = m68k_decode_op_ex(istream, opmode, reg, decoded->extra.size, &(decoded->dst)); + if (!istream) { + decoded->op = M68K_INVALID; + return start+1; + } } } else { optype = (*istream >> 9) & 0x7; @@ -462,6 +525,10 @@ } decoded->extra.size = size; istream= m68k_decode_op(istream, size, &(decoded->dst)); + if (!istream) { + decoded->op = M68K_INVALID; + return start+1; + } break; case 1: //MOVE from CCR or CLR @@ -477,6 +544,10 @@ } decoded->extra.size = size; istream= m68k_decode_op(istream, size, &(decoded->dst)); + if (!istream) { + decoded->op = M68K_INVALID; + return start+1; + } break; case 2: //MOVE to CCR or NEG @@ -484,9 +555,17 @@ decoded->op = M68K_MOVE_CCR; size = OPSIZE_WORD; istream= m68k_decode_op(istream, size, &(decoded->src)); + if (!istream) { + decoded->op = M68K_INVALID; + return start+1; + } } else { decoded->op = M68K_NEG; istream= m68k_decode_op(istream, size, &(decoded->dst)); + if (!istream) { + decoded->op = M68K_INVALID; + return start+1; + } } decoded->extra.size = size; break; @@ -496,9 +575,17 @@ decoded->op = M68K_MOVE_SR; size = OPSIZE_WORD; istream= m68k_decode_op(istream, size, &(decoded->src)); + if (!istream) { + decoded->op = M68K_INVALID; + return start+1; + } } else { decoded->op = M68K_NOT; istream= m68k_decode_op(istream, size, &(decoded->dst)); + if (!istream) { + decoded->op = M68K_INVALID; + return start+1; + } } decoded->extra.size = size; break; @@ -550,10 +637,18 @@ decoded->op = M68K_NBCD; decoded->extra.size = OPSIZE_BYTE; istream = m68k_decode_op(istream, OPSIZE_BYTE, &(decoded->dst)); + if (!istream) { + decoded->op = M68K_INVALID; + return start+1; + } } else if((*istream & 0x1C0) == 0x40) { decoded->op = M68K_PEA; decoded->extra.size = OPSIZE_LONG; istream = m68k_decode_op(istream, OPSIZE_LONG, &(decoded->src)); + if (!istream) { + decoded->op = M68K_INVALID; + return start+1; + } } } break; @@ -572,6 +667,10 @@ decoded->op = M68K_TST; decoded->extra.size = size; istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->src)); + if (!istream) { + decoded->op = M68K_INVALID; + return start+1; + } } } break; @@ -592,6 +691,10 @@ } decoded->extra.size = OPSIZE_UNSIZED; istream = m68k_decode_op(istream, OPSIZE_UNSIZED, &(decoded->src)); + if (!istream) { + decoded->op = M68K_INVALID; + return start+1; + } } else { //it would appear bit 6 needs to be set for it to be a valid instruction here switch((*istream >> 3) & 0x7) @@ -702,6 +805,10 @@ decoded->op = M68K_SCC; decoded->extra.cond = (*istream >> 8) & 0xF; istream = m68k_decode_op(istream, OPSIZE_BYTE, &(decoded->dst)); + if (!istream) { + decoded->op = M68K_INVALID; + return start+1; + } } } else { //ADDQ, SUBQ @@ -719,6 +826,10 @@ decoded->op = M68K_ADD; } istream = m68k_decode_op(istream, size, &(decoded->dst)); + if (!istream) { + decoded->op = M68K_INVALID; + return start+1; + } } break; case BRANCH: @@ -765,6 +876,10 @@ decoded->dst.addr_mode = MODE_REG; decoded->dst.params.regs.pri = (*istream >> 9) & 0x7; istream = m68k_decode_op(istream, OPSIZE_WORD, &(decoded->src)); + if (!istream) { + decoded->op = M68K_INVALID; + return start+1; + } break; case 4: decoded->op = M68K_SBCD; @@ -786,6 +901,10 @@ decoded->dst.addr_mode = MODE_REG; decoded->dst.params.regs.pri = (*istream >> 9) & 0x7; istream = m68k_decode_op(istream, OPSIZE_WORD, &(decoded->src)); + if (!istream) { + decoded->op = M68K_INVALID; + return start+1; + } break; } } else { @@ -795,10 +914,18 @@ decoded->src.addr_mode = MODE_REG; decoded->src.params.regs.pri = (*istream >> 9) & 0x7; istream = m68k_decode_op(istream, size, &(decoded->dst)); + if (!istream) { + decoded->op = M68K_INVALID; + return start+1; + } } else { decoded->dst.addr_mode = MODE_REG; decoded->dst.params.regs.pri = (*istream >> 9) & 0x7; istream = m68k_decode_op(istream, size, &(decoded->src)); + if (!istream) { + decoded->op = M68K_INVALID; + return start+1; + } } } break; @@ -814,17 +941,29 @@ decoded->dst.addr_mode = MODE_AREG; decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream); istream = m68k_decode_op(istream, OPSIZE_LONG, &(decoded->src)); + if (!istream) { + decoded->op = M68K_INVALID; + return start+1; + } } else { decoded->extra.size = size; decoded->src.addr_mode = MODE_REG; decoded->src.params.regs.pri = m68k_reg_quick_field(*istream); istream = m68k_decode_op(istream, size, &(decoded->dst)); + if (!istream) { + decoded->op = M68K_INVALID; + return start+1; + } } } else { //SUBX decoded->op = M68K_SUBX; decoded->extra.size = size; istream = m68k_decode_op(istream, size, &(decoded->src)); + if (!istream) { + decoded->op = M68K_INVALID; + return start+1; + } decoded->dst.addr_mode = decoded->src.addr_mode; decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream); } @@ -839,6 +978,10 @@ } decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream); istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->src)); + if (!istream) { + decoded->op = M68K_INVALID; + return start+1; + } } break; case RESERVED: @@ -853,8 +996,16 @@ decoded->dst.addr_mode = MODE_AREG; decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream); istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->src)); + if (!istream) { + decoded->op = M68K_INVALID; + return start+1; + } } else { istream = m68k_decode_op(istream, size, &(decoded->dst)); + if (!istream) { + decoded->op = M68K_INVALID; + return start+1; + } if (decoded->src.addr_mode == MODE_AREG) { //CMPM decoded->src.addr_mode = decoded->dst.addr_mode = MODE_AREG_POSTINC; @@ -879,6 +1030,10 @@ } decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream); istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->src)); + if (!istream) { + decoded->op = M68K_INVALID; + return start+1; + } } break; case AND_MUL_ABCD_EXG: @@ -898,6 +1053,10 @@ decoded->dst.addr_mode = MODE_REG; decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream); istream = m68k_decode_op(istream, OPSIZE_WORD, &(decoded->src)); + if (!istream) { + decoded->op = M68K_INVALID; + return start+1; + } } else if(!(*istream & 0xF0)) { decoded->op = M68K_ABCD; decoded->extra.size = OPSIZE_BYTE; @@ -925,6 +1084,10 @@ decoded->src.addr_mode = MODE_REG; decoded->src.params.regs.pri = m68k_reg_quick_field(*istream); istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->dst)); + if (!istream) { + decoded->op = M68K_INVALID; + return start+1; + } } } else { if ((*istream & 0xC0) == 0xC0) { @@ -933,12 +1096,20 @@ decoded->dst.addr_mode = MODE_REG; decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream); istream = m68k_decode_op(istream, OPSIZE_WORD, &(decoded->src)); + if (!istream) { + decoded->op = M68K_INVALID; + return start+1; + } } else { decoded->op = M68K_AND; decoded->extra.size = (*istream >> 6) & 0x3; decoded->dst.addr_mode = MODE_REG; decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream); istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->src)); + if (!istream) { + decoded->op = M68K_INVALID; + return start+1; + } } } break; @@ -954,11 +1125,19 @@ decoded->dst.addr_mode = MODE_AREG; decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream); istream = m68k_decode_op(istream, OPSIZE_LONG, &(decoded->src)); + if (!istream) { + decoded->op = M68K_INVALID; + return start+1; + } } else { decoded->extra.size = size; decoded->src.addr_mode = MODE_REG; decoded->src.params.regs.pri = m68k_reg_quick_field(*istream); istream = m68k_decode_op(istream, size, &(decoded->dst)); + if (!istream) { + decoded->op = M68K_INVALID; + return start+1; + } } } else { //ADDX @@ -966,6 +1145,10 @@ //FIXME: Size is not technically correct decoded->extra.size = size; istream = m68k_decode_op(istream, size, &(decoded->src)); + if (!istream) { + decoded->op = M68K_INVALID; + return start+1; + } decoded->dst.addr_mode = decoded->src.addr_mode; decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream); } @@ -980,6 +1163,10 @@ } decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream); istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->src)); + if (!istream) { + decoded->op = M68K_INVALID; + return start+1; + } } break; case SHIFT_ROTATE: @@ -1013,6 +1200,10 @@ } decoded->extra.size = OPSIZE_WORD; istream = m68k_decode_op(istream, OPSIZE_WORD, &(decoded->dst)); + if (!istream) { + decoded->op = M68K_INVALID; + return start+1; + } } else if((*istream & 0xC0) != 0xC0) { switch(((*istream >> 2) & 0x6) | ((*istream >> 8) & 1)) { diff -r 7504200cac86 -r e2918b5208eb m68k_to_x86.c --- a/m68k_to_x86.c Sun Jan 06 20:49:42 2013 -0800 +++ b/m68k_to_x86.c Sun Jan 06 21:42:57 2013 -0800 @@ -42,6 +42,7 @@ void m68k_native_addr(); void m68k_native_addr_and_sync(); void m68k_trap(); +void m68k_invalid(); void set_sr(); void set_ccr(); void get_sr(); @@ -2532,6 +2533,9 @@ return translate_m68k_scc(dst, inst, opts); } else if(inst->op == M68K_MOVEP) { return translate_m68k_movep(dst, inst, opts); + } else if(inst->op == M68K_INVALID) { + dst = mov_ir(dst, inst->address, SCRATCH1, SZ_D); + return call(dst, (uint8_t *)m68k_invalid); } x86_ea src_op, dst_op; if (inst->src.addr_mode != MODE_UNUSED) { @@ -3468,8 +3472,6 @@ } dst = add_ir(dst, 4, opts->aregs[7], SZ_D); break; - /*case M68K_INVALID: - break;*/ default: m68k_disasm(inst, disasm_buf); printf("%X: %s\ninstruction %d not yet implemented\n", inst->address, disasm_buf, inst->op); diff -r 7504200cac86 -r e2918b5208eb runtime.S --- a/runtime.S Sun Jan 06 20:49:42 2013 -0800 +++ b/runtime.S Sun Jan 06 21:42:57 2013 -0800 @@ -88,6 +88,18 @@ call m68k_native_addr_and_sync add $24, %eax jmp *%rcx + +invalid_msg: + .asciz "Invalid instruction at %X\n" + + .global m68k_invalid +m68k_invalid: + lea invalid_msg(%rip), %rdi + mov %ecx, %esi + xor %rax, %rax + call printf + mov $1, %rdi + call exit int_dbg_msg: .asciz "Executing Interrupt!"