summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Pavone <pavone@retrodev.com>2017-09-08 00:38:10 -0700
committerMichael Pavone <pavone@retrodev.com>2017-09-08 00:38:10 -0700
commit0436baae90234aeda75d98c6b028a7da7767ca6f (patch)
tree023fc8c1a9c8c28c278fe1adbc98eb903ea8fb47
parent5a7ad086379c137147374200f1598685c69348f7 (diff)
Fix what are hopefully th elast of the 68K instruction decoder bugs revealed by r57shell/realmonster's test ROM
-rw-r--r--68kinst.c24
1 files changed, 15 insertions, 9 deletions
diff --git a/68kinst.c b/68kinst.c
index c3aebaf..0104eef 100644
--- a/68kinst.c
+++ b/68kinst.c
@@ -395,7 +395,10 @@ uint16_t * m68k_decode(uint16_t * istream, m68kinst * decoded, uint32_t address)
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 || !m68k_valid_immed_dst(&decoded->dst)) {
+ if (
+ !istream || !m68k_valid_immed_dst(&decoded->dst)
+ || (decoded->op != M68K_BTST && !m68k_valid_immed_limited_dst(&decoded->dst))
+ ) {
decoded->op = M68K_INVALID;
break;
}
@@ -629,7 +632,7 @@ uint16_t * m68k_decode(uint16_t * istream, m68kinst * decoded, uint32_t address)
break;
}
istream = m68k_decode_op_ex(istream, opmode, reg, decoded->extra.size, &(decoded->dst));
- if (!istream || !m68k_valid_immed_dst(&(decoded->dst))) {
+ if (!istream || !m68k_valid_immed_limited_dst(&(decoded->dst))) {
decoded->op = M68K_INVALID;
break;
}
@@ -897,7 +900,7 @@ uint16_t * m68k_decode(uint16_t * istream, m68kinst * decoded, uint32_t address)
decoded->op = M68K_TAS;
decoded->extra.size = OPSIZE_BYTE;
istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->dst));
- if (!istream) {
+ if (!istream || !m68k_valid_immed_limited_dst(&decoded->dst)) {
decoded->op = M68K_INVALID;
break;
}
@@ -1198,7 +1201,7 @@ uint16_t * m68k_decode(uint16_t * istream, m68kinst * decoded, uint32_t address)
decoded->src.addr_mode = MODE_REG;
decoded->src.params.regs.pri = (*istream >> 9) & 0x7;
istream = m68k_decode_op(istream, size, &(decoded->dst));
- if (!istream || !m68k_valid_immed_limited_dst(&(decoded->dst))) {
+ if (!istream || !m68k_valid_full_arith_dst(&(decoded->dst))) {
decoded->op = M68K_INVALID;
break;
}
@@ -1319,7 +1322,7 @@ uint16_t * m68k_decode(uint16_t * istream, m68kinst * decoded, uint32_t address)
}
decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream);
istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->src));
- if (!istream) {
+ if (!istream || (decoded->src.addr_mode == MODE_AREG && decoded->extra.size == OPSIZE_BYTE)) {
decoded->op = M68K_INVALID;
break;
}
@@ -1342,7 +1345,7 @@ uint16_t * m68k_decode(uint16_t * istream, m68kinst * decoded, uint32_t address)
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) {
+ if (!istream || decoded->src.addr_mode == MODE_AREG) {
decoded->op = M68K_INVALID;
break;
}
@@ -1364,8 +1367,11 @@ uint16_t * m68k_decode(uint16_t * istream, m68kinst * decoded, uint32_t address)
} else {
decoded->src.addr_mode = decoded->dst.addr_mode = MODE_AREG;
}
- } else {
+ } else if (*istream & 0x40) {
decoded->src.addr_mode = decoded->dst.addr_mode = MODE_REG;
+ } else {
+ decoded->op = M68K_INVALID;
+ break;
}
} else {
decoded->op = M68K_AND;
@@ -1373,7 +1379,7 @@ uint16_t * m68k_decode(uint16_t * istream, m68kinst * decoded, uint32_t address)
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 || !m68k_valid_immed_limited_dst(&(decoded->dst))) {
+ if (!istream || !m68k_valid_full_arith_dst(&(decoded->dst))) {
decoded->op = M68K_INVALID;
break;
}
@@ -1385,7 +1391,7 @@ uint16_t * m68k_decode(uint16_t * istream, m68kinst * decoded, uint32_t address)
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) {
+ if (!istream || decoded->src.addr_mode == MODE_AREG) {
decoded->op = M68K_INVALID;
break;
}