summaryrefslogtreecommitdiff
path: root/68kinst.c
diff options
context:
space:
mode:
authorMichael Pavone <pavone@retrodev.com>2015-08-03 22:30:29 -0700
committerMichael Pavone <pavone@retrodev.com>2015-08-03 22:30:29 -0700
commitec247a6ed43c236f884849816de1b7cb2541b784 (patch)
tree78ed430004edb4f08f455f9a33890e7386cc1d44 /68kinst.c
parentf444eb5d14755a12327486839f471c5ce7f1d695 (diff)
Detect invalid destination modes for immediate variant opcodes. This fixes a crash bug in Bill's Tomato Game on Windows
Diffstat (limited to '68kinst.c')
-rw-r--r--68kinst.c28
1 files changed, 22 insertions, 6 deletions
diff --git a/68kinst.c b/68kinst.c
index f53aabe..893617b 100644
--- a/68kinst.c
+++ b/68kinst.c
@@ -258,6 +258,22 @@ uint16_t *m68k_decode_op_ex(uint16_t *cur, uint8_t mode, uint8_t reg, uint8_t si
return cur;
}
+uint8_t m68k_valid_immed_dst(m68k_op_info *dst)
+{
+ if (dst->addr_mode == MODE_AREG || dst->addr_mode == MODE_IMMEDIATE) {
+ return 0;
+ }
+ return 1;
+}
+
+uint8_t m68k_valid_immed_limited_dst(m68k_op_info *dst)
+{
+ if (dst->addr_mode == MODE_AREG || dst->addr_mode > MODE_ABSOLUTE) {
+ return 0;
+ }
+ return 1;
+}
+
uint16_t *m68k_decode_op(uint16_t *cur, uint8_t size, m68k_op_info *dst)
{
uint8_t mode = (*cur >> 3) & 0x7;
@@ -406,7 +422,7 @@ uint16_t * m68k_decode(uint16_t * istream, m68kinst * decoded, uint32_t address)
break;
}
istream = m68k_decode_op_ex(istream, opmode, reg, size, &(decoded->dst));
- if (!istream) {
+ if (!istream || !m68k_valid_immed_limited_dst(&(decoded->dst))) {
decoded->op = M68K_INVALID;
break;
}
@@ -445,7 +461,7 @@ uint16_t * m68k_decode(uint16_t * istream, m68kinst * decoded, uint32_t address)
break;
}
istream = m68k_decode_op_ex(istream, opmode, reg, size, &(decoded->dst));
- if (!istream) {
+ if (!istream || !m68k_valid_immed_limited_dst(&(decoded->dst))) {
decoded->op = M68K_INVALID;
break;
}
@@ -472,7 +488,7 @@ uint16_t * m68k_decode(uint16_t * istream, m68kinst * decoded, uint32_t address)
break;
}
istream = m68k_decode_op_ex(istream, opmode, reg, size, &(decoded->dst));
- if (!istream) {
+ if (!istream || !m68k_valid_immed_limited_dst(&(decoded->dst))) {
decoded->op = M68K_INVALID;
break;
}
@@ -498,7 +514,7 @@ uint16_t * m68k_decode(uint16_t * istream, m68kinst * decoded, uint32_t address)
break;
}
istream = m68k_decode_op_ex(istream, opmode, reg, size, &(decoded->dst));
- if (!istream) {
+ if (!istream || !m68k_valid_immed_limited_dst(&(decoded->dst))) {
decoded->op = M68K_INVALID;
break;
}
@@ -561,7 +577,7 @@ uint16_t * m68k_decode(uint16_t * istream, m68kinst * decoded, uint32_t address)
break;
}
istream = m68k_decode_op_ex(istream, opmode, reg, size, &(decoded->dst));
- if (!istream) {
+ if (!istream || !m68k_valid_immed_limited_dst(&(decoded->dst))) {
decoded->op = M68K_INVALID;
break;
}
@@ -588,7 +604,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) {
+ if (!istream || !m68k_valid_immed_dst(&(decoded->dst))) {
decoded->op = M68K_INVALID;
break;
}