$NetBSD: patch-bb,v 1.2 2007/03/17 14:36:42 tsutsui Exp $

--- ic/m68k/m68k-insns-auto.sh.orig	2005-03-23 11:09:33.000000000 +0900
+++ ic/m68k/m68k-insns-auto.sh	2007-03-17 23:25:24.000000000 +0900
@@ -58,6 +58,96 @@
 EOF
 fi
 
+if $header; then
+    cat <<EOF
+
+/* following are to fix the movel sp,-(sp) problem (of the value being pushed
+   on the stack being off by four) and to warn if there are other possible
+   problems that haven't been tested */
+
+#define PREDEC_POSTINC_CONCERN	(					\\
+									\\
+/* if source and destination register are the same number */		\\
+    (TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE,0,3) ==			\\
+     TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE,9,3)) &&			\\
+									\\
+/* and both are address registers */					\\
+    (									\\
+     (TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE,3,3) >= 1) &&		\\
+     (TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE,3,3) <= 6) &&		\\
+     (TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE,6,3) >= 1) &&		\\
+     (TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE,6,3) <= 6)		\\
+    ) &&								\\
+									\\
+/* and there is a predec or postinc in the src, or a predec in dest */	\\
+    (									\\
+     (TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE,3,3) == 3) ||		\\
+     (TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE,3,3) == 4) ||		\\
+     (TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE,6,3) == 4)		\\
+    )									\\
+  )
+
+
+#define DEST_IS_PREDEC_SRC_IS_REG_BOTH_SP (				\\
+    (TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE,6,3) == 4) &&		\\
+    (TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE,3,3) == 1) &&		\\
+    (TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE,0,3) == 7) &&		\\
+    (TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE,9,3) == 7)			\\
+  )
+
+/* following modes test ok */
+#define MODE35_MODE24_OR_MODE54	(					\\
+									\\
+/* src/dest mode 3,5 : this is move.l (a5)+,(028,a5) */			\\
+    (									\\
+      (TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE,3,3) == 3) &&		\\
+      (TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE,6,3) == 5)		\\
+    ) ||								\\
+									\\
+/* or src/dest mode 2,4 : this is move.l (a5),-(a5) */			\\
+    (									\\
+      (TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE,3,3) == 2) &&		\\
+      (TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE,6,3) == 4)		\\
+    ) ||								\\
+									\\
+/* or src/dest mode 5,4 : this is move.l (028,a5),-(a5) */		\\
+    (									\\
+      (TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE,3,3) == 5) &&		\\
+      (TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE,6,3) == 4)		\\
+    )									\\
+  ) 
+
+
+#define PRINT_WEIRD_SRC_DST_REG_MODE(msg)				\\
+  printf("%s\nsrc reg: %x src mode: %x dest reg: %x dest mode %x at pc:%x\n", \\
+    msg,								\\
+    TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE,0,3),			\\
+    TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE,3,3),			\\
+    TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE,9,3),			\\
+    TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE,6,3),			\\
+    ic->tme_m68k_ireg_pc)
+
+
+#define HITRETURN(msg)	do {						\\
+  printf("%s, pc:0x%08x, insn:0x%08x: please",				\\
+    msg, ic->tme_m68k_ireg_pc, TME_M68K_INSN_OPCODE);			\\
+  printf("  analyze M68K instruction.\n");				\\
+  printf("  generate test case.\n");					\\
+  printf("  if TME emulation is incorrect, correct problem.\n");	\\
+  printf("  modify source to avoid this message in the future.\n");	\\
+  printf("press any to continue:");					\\
+  (void)getchar();							\\
+  printf("continuing\n");						\\
+} while (0)
+
+EOF
+else
+    cat <<EOF
+#include <stdio.h>
+
+EOF
+fi
+
 # permute for the three different operand sizes we need to handle:
 for size in 8 16 32; do
     
@@ -162,16 +252,16 @@
 		    echo ""
 		    echo "  if (!TME_M68K_SEQUENCE_RESTARTING) {"
 		    echo "    ic->_tme_m68k_ea_function_code = function_code;"
-		    echo "    ic->_tme_m68k_ea_address = ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ireg_dst);"
-		    echo "    ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ireg_dst) += ireg_dst_adjust;"
-		    echo "  }"
-		    echo "  tme_m68k_read_memx${size}(ic);"
-		    echo "  if (!TME_M68K_SEQUENCE_RESTARTING) {"
-		    echo "    ic->_tme_m68k_ea_function_code = function_code;"
 		    echo "    ic->_tme_m68k_ea_address = ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ireg_src);"
 		    echo "    ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ireg_src) += ireg_src_adjust;"
 		    echo "  }"
 		    echo "  tme_m68k_read_mem${size}(ic, TME_M68K_IREG_MEMY${size});"
+		    echo "  if (!TME_M68K_SEQUENCE_RESTARTING) {"
+		    echo "    ic->_tme_m68k_ea_function_code = function_code;"
+		    echo "    ic->_tme_m68k_ea_address = ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ireg_dst);"
+		    echo "    ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ireg_dst) += ireg_dst_adjust;"
+		    echo "  }"
+		    echo "  tme_m68k_read_memx${size}(ic);"
 		    echo "  ${dst} = ic->tme_m68k_ireg_memx${size};"
 		    echo "  ${src} = ic->tme_m68k_ireg_memy${size};"
 		    ;;
@@ -181,6 +271,12 @@
 		addx|subx)
 		    echo "  tme_uint16_t memory;"
 		    echo ""
+		    # sanity checks for addx/subx
+		    echo "  if ((ireg_src == ireg_dst) &&"
+		    echo "    (TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE,3,1) == 1)) {"
+		    echo "    HITRETURN(\"weird ${name}${size}\");"
+		    echo "  }"
+		    echo ""
 		    echo "  memory = (TME_M68K_INSN_OPCODE & TME_BIT(3));"
 		    echo "  if (memory) {"
 		    echo "    TME_M68K_INSN_CANFAULT;"
@@ -239,6 +335,35 @@
 	    fi
 	    echo ";"
 
+	    # check "moveX sp,-(sp)" and adjust res
+	    if test ${name} = move; then
+		echo ""
+		echo "  if (PREDEC_POSTINC_CONCERN) {"
+		echo "    if (DEST_IS_PREDEC_SRC_IS_REG_BOTH_SP) {"
+		if test ${size} = 8; then
+		    echo "      printf(\"ERROR: ${name}${size}: how can addr/addr be 8 bits? at pc:%x\\n\","
+		    echo "        ic->tme_m68k_ireg_pc);"
+		else
+		    echo "#if 0"
+		    echo "      printf(\"${name}${size}: chg predec dest res from:%x to %x for register %d at pc %x\\n\","
+		    echo "         res, res + (${size} / 8), TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE,0,3), ic->tme_m68k_ireg_pc);"
+		    echo "#endif"
+		    echo "      res = res + (${size} / 8);"
+		fi
+		echo "      } else if (!(MODE35_MODE24_OR_MODE54)) {"
+		echo "        PRINT_WEIRD_SRC_DST_REG_MODE(\"WEIRD: ${name}${size}\");"
+		echo "    }"
+		echo "  }"
+	    fi
+
+	    # sanity check for cmpa16
+	    if test ${name} = cmpa; then
+		echo ""
+		echo "  if PREDEC_POSTINC_CONCERN {"
+		echo "    PRINT_WEIRD_SRC_DST_REG_MODE(\"weird ${name}${size}\");"
+		echo "  }"
+	    fi
+
 	    # store the result:
 	    if $store_res; then
 		echo ""
@@ -362,6 +487,10 @@
 	adda) op='+' ; src="_op0" ; dst="_op1" ;;
 	movea) op='' ; src="_op1" ; dst="_op0" ;;
 	esac
+	echo "  if (PREDEC_POSTINC_CONCERN) {"
+	echo "    PRINT_WEIRD_SRC_DST_REG_MODE(\"weird ${name}${size}\");"
+	echo "  }"
+	echo ""
 	echo "  *((tme_int32_t *) ${dst}) ${op}= *((tme_int${size}_t *) ${src});"
 	echo "  TME_M68K_INSN_OK;"
 	echo "}"
@@ -801,6 +930,10 @@
 		echo "  tme_uint16_t specopy = TME_M68K_INSN_OP0(tme_uint16_t);"
 		echo "  tme_uint32_t addrx;"
 		echo "  tme_uint32_t addry;"
+	    fi
+	    echo ""
+	    echo "  TME_M68K_INSN_CANFAULT;"
+	    if test $name = cas2_; then
 		echo ""
 		echo "  /* get the function code and addresses we'll be dealing with: */"
 		echo "  ic->_tme_m68k_ea_function_code = TME_M68K_FUNCTION_CODE_DATA(ic);"
