changeset 1463:63f309cfbef9

Fix what are hopefully th elast of the 68K instruction decoder bugs revealed by r57shell/realmonster's test ROM
author Michael Pavone <pavone@retrodev.com>
date Fri, 08 Sep 2017 00:38:10 -0700
parents d276ec2fff11
children ffe45c5b8390
files 68kinst.c
diffstat 1 files changed, 15 insertions(+), 9 deletions(-) [+]
line wrap: on
line diff
--- a/68kinst.c	Thu Sep 07 00:42:28 2017 -0700
+++ b/68kinst.c	Fri Sep 08 00:38:10 2017 -0700
@@ -395,7 +395,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 || !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 @@
 					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 @@
 								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 @@
 				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 @@
 			}
 			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 @@
 				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 @@
 					} else {
 						decoded->src.addr_mode = decoded->dst.addr_mode = MODE_AREG;
 					}
+				} else if (*istream & 0x40) {
+					decoded->src.addr_mode = decoded->dst.addr_mode = MODE_REG;
 				} else {
-					decoded->src.addr_mode = decoded->dst.addr_mode = MODE_REG;
+					decoded->op = M68K_INVALID;
+					break;
 				}
 			} else {
 				decoded->op = M68K_AND;
@@ -1373,7 +1379,7 @@
 				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 @@
 				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;
 				}