]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
68010 full support and bug fixes.
authorToni Wilen <twilen@winuae.net>
Sun, 26 Jan 2020 14:24:56 +0000 (16:24 +0200)
committerToni Wilen <twilen@winuae.net>
Sun, 26 Jan 2020 14:24:56 +0000 (16:24 +0200)
15 files changed:
cputest.cpp
cputest/adis/defs.h
cputest/adis/globals.c
cputest/adis/opcode_handler_cpu.c
cputest/adis/opcodes_cpu.c
cputest/adis/util.c
cputest/cputestgen.ini
cputest/main.c
cputest/readme.txt
gencpu.cpp
include/newcpu.h
newcpu.cpp
newcpu_common.cpp
readcpu.cpp
table68k

index 7286362cc18363d0fb39c4e9e5dd133465e11b65..8f0fcb4ebd41a9ef05809e16fa0d378b86e5aaa5 100644 (file)
@@ -167,6 +167,7 @@ struct accesshistory
        uae_u32 val;
        uae_u32 oldval;
        int size;
+       bool donotsave;
 };
 static int ahcnt_current, ahcnt_written;
 static int noaccesshistory = 0;
@@ -359,15 +360,26 @@ uae_u16 get_word_test_prefetch(int o)
        return get_iword_test(m68k_getpci() + o);
 }
 
-// Move from SR does two writes to same address:
-// ignore the first one
 static void previoussame(uaecptr addr, int size)
 {
        if (!ahcnt_current || ahcnt_current == ahcnt_written)
                return;
-       struct accesshistory *ah = &ahist[ahcnt_current - 1];
-       if (ah->addr == addr && ah->size == size) {
-               ahcnt_current--;
+       // Move from SR does two writes to same address.
+       // Loop mode can write different values to same address.
+       // Mark old values as do not save.
+       for (int i = ahcnt_written; i < ahcnt_current; i++) {
+               struct accesshistory  *ah = &ahist[i];
+               if (ah->size == size && ah->addr == addr) {
+                       ah->donotsave = true;
+               }
+               if (size == sz_long) {
+                       if (ah->size == sz_word && ah->addr == addr) {
+                               ah->donotsave = true;
+                       }
+                       if (ah->size == sz_word && ah->addr == addr + 2) {
+                               ah->donotsave = true;
+                       }
+               }
        }
 }
 
@@ -388,6 +400,7 @@ void put_byte_test(uaecptr addr, uae_u32 v)
                ah->val = v & 0xff;
                ah->oldval = *p;
                ah->size = sz_byte;
+               ah->donotsave = false;
        }
        regs.write_buffer = v;
        *p = v;
@@ -414,6 +427,7 @@ void put_word_test(uaecptr addr, uae_u32 v)
                        ah->val = v & 0xffff;
                        ah->oldval = (p[0] << 8) | p[1];
                        ah->size = sz_word;
+                       ah->donotsave = false;
                }
                p[0] = v >> 8;
                p[1] = v & 0xff;
@@ -446,6 +460,7 @@ void put_long_test(uaecptr addr, uae_u32 v)
                        ah->val = v;
                        ah->oldval = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
                        ah->size = sz_long;
+                       ah->donotsave = false;
                }
                p[0] = v >> 24;
                p[1] = v >> 16;
@@ -1512,6 +1527,8 @@ static uae_u8 *store_mem_writes(uae_u8 *dst, int storealways)
                struct accesshistory *ah = &ahist[i];
                if (ah->oldval == ah->val && !storealways)
                        continue;
+               if (ah->donotsave)
+                       continue;
                validate_addr(ah->addr, 1 << ah->size);
                uaecptr addr = ah->addr;
                addr &= addressing_mask;
@@ -2713,8 +2730,8 @@ static void execute_ins(uaecptr endpc, uaecptr targetpc, struct instr *dp)
        uae_u16 opc = regs.ir;
        uae_u16 opw1 = (opcode_memory[2] << 8) | (opcode_memory[3] << 0);
        uae_u16 opw2 = (opcode_memory[4] << 8) | (opcode_memory[5] << 0);
-       if (opc == 0x40ef 
-               && opw1 == 0x64fc
+       if (opc == 0xd196 
+               //&& opw1 == 0x64fc
                //&& opw2 == 0x4afc
                )
                printf("");
@@ -3388,6 +3405,8 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                        if (feature_loop_mode_68010) {
                                if (!opcode_loop_mode(opcode))
                                        continue;
+                               if (dp->mnemo == i_DBcc)
+                                       continue;
                        }
 
                        target_ea[0] = target_ea_bak[0];
index 1a1c53d0a54b4a5dd3c2d5f78efd47cb122fe359..9c1e2a38a8274918029c2cb9296f925a9a6e2c83 100644 (file)
@@ -157,7 +157,8 @@ struct opcode_sub_entry
 enum 
   {
   SR, CCR, USP, SFC, DFC, CACR, VBR, CAAR, MSP, ISP, TC, 
-  ITT0, ITT1, DTT0, DTT1, MMUSR, URP, SRP, TT0, TT1, CRP
+  ITT0, ITT1, DTT0, DTT1, MMUSR, URP, SRP, TT0, TT1, CRP,
+  BUSCR, PCR
   };
 
 #define PC (ushort)16               /* index into reg_names array */
@@ -283,7 +284,8 @@ extern BOOL single_file;
 extern BOOL ascending_label_numbers;
 extern BOOL disasm_as_lib;
 extern BOOL old_style;
-extern BOOL cpu68020,
+extern BOOL cpu68010,
+            cpu68020,
             cpu68030,
             cpu68040,
             cpu68060,
@@ -301,7 +303,6 @@ extern short cpu68020_disabled [];
 extern short cpu68030_disabled [];
 extern short cpu68040_disabled [];
 extern short cpu68060_disabled [];
-extern short cpuCF_disabled [];
 extern short fpu68881_disabled [];
 
 extern int OPCODE_COL;
index e8d53ca927a899481bc8370c1f4ac2094a77d0b1..5500aa019ca976dda106f9f6429229da7861df78 100644 (file)
@@ -87,11 +87,11 @@ BOOL try_small = FALSE;             /* -b */
 BOOL single_file = TRUE;                                   
 BOOL print_illegal_instr_offset = FALSE;         /* -i */
 BOOL old_style = FALSE;
-BOOL cpu68020 = TRUE,              /* -m2 */
+BOOL cpu68010 = TRUE,
+     cpu68020 = TRUE,              /* -m2 */
      cpu68030 = TRUE,              /* -m3 */
      cpu68040 = TRUE,              /* -m4 */
      cpu68060 = TRUE,              /* -m6 */
-     cpuCF = FALSE,
      fpu68881 = TRUE;              /* -m8 */
 BOOL disasm_as_lib = FALSE;         /* -l */
 BOOL ascending_label_numbers = FALSE;   /* -dn */
@@ -188,6 +188,8 @@ char *special_regs [] =
   "tt0",       /* 18 */
   "tt1",       /* 19 */
   "crp"        /* 20 */
+  "buscr"      /* 21 */
+  "pcr"        /* 22 */
   };
 
 /**********************************************************************/
@@ -276,52 +278,3 @@ short cpu68060_disabled [] =
   983, /* PLPAR */
     0
   };
-
-short cpuCF_disabled [] =
-  {
-  452, /* MVS.B */
-  453, /* MVS.W */
-  454, /* MVZ.B */
-  455, /* MVZ.W */
-  460, /* MVS.B */
-  461, /* MVS.W */
-  462, /* MVZ.B */
-  463, /* MVZ.W */
-  468, /* MVS.B */
-  469, /* MVS.W */
-  470, /* MVZ.B */
-  471, /* MVZ.W */
-  476, /* MVS.B */
-  477, /* MVS.W */
-  478, /* MVZ.B */
-  479, /* MVZ.W */
-  484, /* MVS.B */
-  485, /* MVS.W */
-  486, /* MVZ.B */
-  487, /* MVZ.W */
-  492, /* MVS.B */
-  493, /* MVS.W */
-  494, /* MVZ.B */
-  495, /* MVZ.W */
-  500, /* MVS.B */
-  501, /* MVS.W */
-  502, /* MVZ.B */
-  503, /* MVZ.W */
-  508, /* MVS.B */
-  509, /* MVS.W */
-  510, /* MVZ.B */
-  511, /* MVZ.W */
-  645, /* MOV3Q */
-  653, /* MOV3Q */
-  661, /* MOV3Q */
-  669, /* MOV3Q */
-  677, /* MOV3Q */
-  685, /* MOV3Q */
-  693, /* MOV3Q */
-  701, /* MOV3Q */
- 1056, /* BITREV */
- 1057, /* BYTEREV */
- 1058, /* FF1 */
- 1059, /* SATS */
-    0
-  };
index 0700fd24b8cb5cf6c79eca2decd1c6ed365c4112..e5f82f209741632d6c2c2e293d3d0088b920771e 100644 (file)
@@ -380,7 +380,7 @@ if ((*code & 0x38) == 0x30)
     case 3: ptr = "rte";
             instr_end = TRUE;
             break;
-    case 4: if (!cpu68020)
+    case 4: if (!cpu68010)
               return (TRANSFER);
             ptr = "rtd";
             instr_end = TRUE;
@@ -408,7 +408,7 @@ else if ((*code & 0x3e) == 0x3a)          /* MOVEC */
   {
   short reg_offset;
 
-  if (!cpu68020)
+  if (!cpu68010)
     return (TRANSFER);
   switch (*(code + 1) & 0xfff)
     {
@@ -418,30 +418,17 @@ else if ((*code & 0x3e) == 0x3a)          /* MOVEC */
                 break;
     case 0x002: ptr = special_regs [CACR];
                 break;
-    case 0x003: if (cpu68040)
-                  ptr = special_regs [TC];
-                else
-                  return (TRANSFER);
+    case 0x003: ptr = special_regs [TC];
+                break;
+    case 0x004: ptr = special_regs [ITT0];
                 break;
-    case 0x004: if (cpu68040)
-                  ptr = special_regs [ITT0];
-                else
-                  return (TRANSFER);
+    case 0x005: ptr = special_regs [ITT1];
                 break;
-    case 0x005: if (cpu68040)
-                  ptr = special_regs [ITT1];
-                else
-                  return (TRANSFER);
+    case 0x006: ptr = special_regs [DTT0];
                 break;
-    case 0x006: if (cpu68040)
-                  ptr = special_regs [DTT0];
-                else
-                  return (TRANSFER);
+    case 0x007: ptr = special_regs [DTT1];
                 break;
-    case 0x007: if (cpu68040)
-                  ptr = special_regs [DTT1];
-                else
-                  return (TRANSFER);
+    case 0x008: ptr = special_regs [BUSCR];
                 break;
     case 0x800: ptr = special_regs [USP];
                 break;
@@ -453,20 +440,13 @@ else if ((*code & 0x3e) == 0x3a)          /* MOVEC */
                 break;
     case 0x804: ptr = special_regs [ISP];
                 break;
-    case 0x805: if (cpu68040)
-                  ptr = special_regs [MMUSR];
-                else
-                  return (TRANSFER);
+    case 0x805: ptr = special_regs [MMUSR];
+                break;
+    case 0x806: ptr = special_regs [URP];
                 break;
-    case 0x806: if (cpu68040)
-                  ptr = special_regs [URP];
-                else
-                  return (TRANSFER);
+    case 0x807: ptr = special_regs [SRP];
                 break;
-    case 0x807: if (cpu68040)
-                  ptr = special_regs [SRP];
-                else
-                  return (TRANSFER);
+    case 0x808: ptr = special_regs [PCR];
                 break;
     default : return (TRANSFER);
     }
@@ -474,7 +454,7 @@ else if ((*code & 0x3e) == 0x3a)          /* MOVEC */
   reg_offset = (*(code + 1) & 0x8000) ? 8 : 0;
   if (pass3)
     {
-    str_cpy (opcode, "movec.l");
+    str_cpy (opcode, "movec");
     if (*code & 0x1)
       {
       /* from general register to control register */
@@ -1196,29 +1176,3 @@ if (pass3)
   }
 return (1);
 }
-
-/**********************************************************************
- ColdFire handlers
-**********************************************************************/
-
-uint mov3q (struct opcode_entry *op)
-
-/* handler for ColdFire mov3q */
-{
-if (pass3)
-  {
-  char *to;
-  to = src;
-  *to++ = '#';
-  UBYTE data = (UBYTE)op->param;
-  if (data)
-    *to++ = data + '0';
-  else
-    {
-    *to++ = '-';
-    *to++ = '1';
-    }
-  *to = 0;
-  }
-return (decode_ea (dest, MODE_NUM(*code), REG_NUM(*code), ACC_LONG, 1) + 1);
-}
index 12a6cbb4576296214109487ec1a05eea223f0429..320f8d3441634790ef1a175af7e9df98c7ed8537 100644 (file)
@@ -697,7 +697,7 @@ struct opcode_entry opcode_table [] =
 { invalid  , 0xff, 0xff, 1024, 0         , 0, 0            }, /* 1010 000 010 */
 { invalid  , 0xff, 0xff, 1024, 0         , 0, 0            }, /* 1010 000 011 */
 { invalid  , 0xff, 0xff, 1024, 0         , 0, 0            }, /* 1010 000 100 */
-{ mov3q    , 0xff, 0x0f, 1024, "mov3q"   , 0, ACC_LONG     }, /* 1010 000 101 */
+{ invalid  , 0xff, 0xff, 1024, 0         , 0, 0            }, /* 1010 000 101 */
 { invalid  , 0xff, 0xff, 1024, 0         , 0, 0            }, /* 1010 000 110 */
 { invalid  , 0xff, 0xff, 1024, 0         , 0, 0            }, /* 1010 000 111 */
 { invalid  , 0xff, 0xff, 1024, 0         , 0, 0            }, /* 1010 001 000 */
@@ -705,7 +705,7 @@ struct opcode_entry opcode_table [] =
 { invalid  , 0xff, 0xff, 1024, 0         , 0, 0            }, /* 1010 001 010 */
 { invalid  , 0xff, 0xff, 1024, 0         , 0, 0            }, /* 1010 001 011 */
 { invalid  , 0xff, 0xff, 1024, 0         , 0, 0            }, /* 1010 001 100 */
-{ mov3q    , 0xff, 0x0f, 1024, "mov3q"   , 1, ACC_LONG     }, /* 1010 001 101 */
+{ invalid  , 0xff, 0xff, 1024, 0         , 0, 0            }, /* 1010 001 101 */
 { invalid  , 0xff, 0xff, 1024, 0         , 0, 0            }, /* 1010 001 110 */
 { invalid  , 0xff, 0xff, 1024, 0         , 0, 0            }, /* 1010 001 111 */
 { invalid  , 0xff, 0xff, 1024, 0         , 0, 0            }, /* 1010 010 000 */
@@ -713,7 +713,7 @@ struct opcode_entry opcode_table [] =
 { invalid  , 0xff, 0xff, 1024, 0         , 0, 0            }, /* 1010 010 010 */
 { invalid  , 0xff, 0xff, 1024, 0         , 0, 0            }, /* 1010 010 011 */
 { invalid  , 0xff, 0xff, 1024, 0         , 0, 0            }, /* 1010 010 100 */
-{ mov3q    , 0xff, 0x0f, 1024, "mov3q"   , 2, ACC_LONG     }, /* 1010 010 101 */
+{ invalid  , 0xff, 0xff, 1024, 0         , 0, 0            }, /* 1010 010 101 */
 { invalid  , 0xff, 0xff, 1024, 0         , 0, 0            }, /* 1010 010 110 */
 { invalid  , 0xff, 0xff, 1024, 0         , 0, 0            }, /* 1010 010 111 */
 { invalid  , 0xff, 0xff, 1024, 0         , 0, 0            }, /* 1010 011 000 */
@@ -721,7 +721,7 @@ struct opcode_entry opcode_table [] =
 { invalid  , 0xff, 0xff, 1024, 0         , 0, 0            }, /* 1010 011 010 */
 { invalid  , 0xff, 0xff, 1024, 0         , 0, 0            }, /* 1010 011 011 */
 { invalid  , 0xff, 0xff, 1024, 0         , 0, 0            }, /* 1010 011 100 */
-{ mov3q    , 0xff, 0x0f, 1024, "mov3q"   , 3, ACC_LONG     }, /* 1010 011 101 */
+{ invalid  , 0xff, 0xff, 1024, 0         , 0, 0            }, /* 1010 011 101 */
 { invalid  , 0xff, 0xff, 1024, 0         , 0, 0            }, /* 1010 011 110 */
 { invalid  , 0xff, 0xff, 1024, 0         , 0, 0            }, /* 1010 011 111 */
 { invalid  , 0xff, 0xff, 1024, 0         , 0, 0            }, /* 1010 100 000 */
@@ -729,7 +729,7 @@ struct opcode_entry opcode_table [] =
 { invalid  , 0xff, 0xff, 1024, 0         , 0, 0            }, /* 1010 100 010 */
 { invalid  , 0xff, 0xff, 1024, 0         , 0, 0            }, /* 1010 100 011 */
 { invalid  , 0xff, 0xff, 1024, 0         , 0, 0            }, /* 1010 100 100 */
-{ mov3q    , 0xff, 0x0f, 1024, "mov3q"   , 4, ACC_LONG     }, /* 1010 100 101 */
+{ invalid  , 0xff, 0xff, 1024, 0         , 0, 0            }, /* 1010 100 101 */
 { invalid  , 0xff, 0xff, 1024, 0         , 0, 0            }, /* 1010 100 110 */
 { invalid  , 0xff, 0xff, 1024, 0         , 0, 0            }, /* 1010 100 111 */
 { invalid  , 0xff, 0xff, 1024, 0         , 0, 0            }, /* 1010 101 000 */
@@ -737,7 +737,7 @@ struct opcode_entry opcode_table [] =
 { invalid  , 0xff, 0xff, 1024, 0         , 0, 0            }, /* 1010 101 010 */
 { invalid  , 0xff, 0xff, 1024, 0         , 0, 0            }, /* 1010 101 011 */
 { invalid  , 0xff, 0xff, 1024, 0         , 0, 0            }, /* 1010 101 100 */
-{ mov3q    , 0xff, 0x0f, 1024, "mov3q"   , 5, ACC_LONG     }, /* 1010 101 101 */
+{ invalid  , 0xff, 0xff, 1024, 0         , 0, 0            }, /* 1010 101 101 */
 { invalid  , 0xff, 0xff, 1024, 0         , 0, 0            }, /* 1010 101 110 */
 { invalid  , 0xff, 0xff, 1024, 0         , 0, 0            }, /* 1010 101 111 */
 { invalid  , 0xff, 0xff, 1024, 0         , 0, 0            }, /* 1010 110 000 */
@@ -745,7 +745,7 @@ struct opcode_entry opcode_table [] =
 { invalid  , 0xff, 0xff, 1024, 0         , 0, 0            }, /* 1010 110 010 */
 { invalid  , 0xff, 0xff, 1024, 0         , 0, 0            }, /* 1010 110 011 */
 { invalid  , 0xff, 0xff, 1024, 0         , 0, 0            }, /* 1010 110 100 */
-{ mov3q    , 0xff, 0x0f, 1024, "mov3q"   , 6, ACC_LONG     }, /* 1010 110 101 */
+{ invalid  , 0xff, 0xff, 1024, 0         , 0, 0            }, /* 1010 110 101 */
 { invalid  , 0xff, 0xff, 1024, 0         , 0, 0            }, /* 1010 110 110 */
 { invalid  , 0xff, 0xff, 1024, 0         , 0, 0            }, /* 1010 110 111 */
 { invalid  , 0xff, 0xff, 1024, 0         , 0, 0            }, /* 1010 111 000 */
@@ -753,7 +753,7 @@ struct opcode_entry opcode_table [] =
 { invalid  , 0xff, 0xff, 1024, 0         , 0, 0            }, /* 1010 111 010 */
 { invalid  , 0xff, 0xff, 1024, 0         , 0, 0            }, /* 1010 111 011 */
 { invalid  , 0xff, 0xff, 1024, 0         , 0, 0            }, /* 1010 111 100 */
-{ mov3q    , 0xff, 0x0f, 1024, "mov3q"   , 7, ACC_LONG     }, /* 1010 111 101 */
+{ invalid  , 0xff, 0xff, 1024, 0         , 0, 0            }, /* 1010 111 101 */
 { invalid  , 0xff, 0xff, 1024, 0         , 0, 0            }, /* 1010 111 110 */
 { invalid  , 0xff, 0xff, 1024, 0         , 0, 0            }, /* 1010 111 111 */
 { EA_to_Rn , 0xff, 0x1f, 1024, "cmp.b"   , 0, ACC_BYTE     }, /* 1011 000 000 */
@@ -1114,10 +1114,5 @@ struct opcode_entry opcode_table [] =
 { op2_bcdx , 0x03, 0x00, 1024, "subx.b"  , NO_ADJ, 0       }, /* 1052 */
 { op2_bcdx , 0x03, 0x00, 1024, "subx.w"  , NO_ADJ, 0       }, /* 1053 */
 { op2_bcdx , 0x03, 0x00, 1024, "subx.l"  , NO_ADJ, 0       }, /* 1054 */
-{ link_l   , 0x02, 0x00, 1024, "link.l"  , 0, 0            }, /* 1055 */
-/* ColdFire chains */
-{ op1      , 0x03, 0x00, 1024, "bitrev"  , 0, ACC_LONG     }, /* 1056 */
-{ op1      , 0x03, 0x00, 1024, "byterev" , 0, ACC_LONG     }, /* 1057 */
-{ op1      , 0x03, 0x00, 1024, "ff1"     , 0, ACC_LONG     }, /* 1058 */
-{ op1      , 0x03, 0x00, 1024, "sats"    , 0, ACC_SLONG    }  /* 1059 */
+{ link_l   , 0x02, 0x00, 1024, "link.l"  , 0, 0            }  /* 1055 */
 };
index 8df07bded15ad986eab4ce78949cc361112036ff..2288acac979489ed1ab0b022fb8d3f7afb4e4ddc 100644 (file)
@@ -986,6 +986,9 @@ uint disasm_instr(UWORD *instr, char *out, int cpu_lvl)
         cpu68020 = 0;
         fpu68881 = 0;
     }
+    if (cpu_lvl < 1) {
+               cpu68010 = 0;
+               }
 
        set_pass3;
 
index 24007c9b6e0866fbbf8726186d805258866af12e..f00fa188eabeb22bac523289373be1d147bc43b4 100644 (file)
@@ -134,6 +134,8 @@ feature_sr_mask=0x0000
 ; value: 0 = disabled, >0 = number of loops
 feature_loop_mode=0
 feature_loop_mode_register=7
+; only generate 68010 loop mode compatible instructions
+feature_loop_mode_68010=0
 
 ; 68020+ addressing modes (this makes test files much larger if other addressing modes are also enabled)
 ; currently does not generate any reserved mode bit combinations.
index fd66d0ae13162dd2478d4a17b1be85b488c0b0ec..3dba92a76a23a28fffbe68bc19d64fd3e02f8aee 100644 (file)
@@ -128,6 +128,9 @@ static uae_u32 interrupt_mask;
 static short disasm;
 static short basicexcept;
 static short excskipccr;
+static short skipmemwrite;
+static short skipregchange;
+static short skipccrchange;
 static short askifmissing;
 static short nextall;
 static int exitcnt;
@@ -1158,7 +1161,7 @@ static void out_disasm(uae_u8 *mem)
        uae_u8 *p = mem;
        int offset = 0;
        int lines = 0;
-       while (lines++ < 5) {
+       while (lines++ < 7) {
                int v = 0;
                if (!is_valid_test_addr_read((uae_u32)p) || !is_valid_test_addr_read((uae_u32)p + 1)) {
                        sprintf(outbp, "%08x -- INACCESSIBLE --\n", (uae_u32)p);
@@ -1708,18 +1711,15 @@ static int getexceptioncycles(int exc)
                case 3:
                        return 126;
                case 4:
-               case 10:
-               case 11:
-                       return 38;
                case 5:
-                       return 38;
                case 6:
-                       return 44;
-               case 7:
-                       return 40;
                case 8:
-                       return 38;
                case 9:
+               case 10:
+               case 11:
+               case 14:
+                       return 38;
+               case 7:
                        return 38;
                case 24:
                case 25:
@@ -1863,7 +1863,7 @@ static uae_u8 *validate_test(uae_u8 *p, short ignore_errors, short ignore_sr)
 {
        uae_u8 regs_changed[16] = { 0 };
        uae_u8 regs_fpuchanged[8] = { 0 };
-       uae_u8 sr_changed = 0, pc_changed = 0;
+       uae_u8 sr_changed = 0, ccr_changed = 0, pc_changed = 0;
        uae_u8 fpiar_changed = 0, fpsr_changed = 0, fpcr_changed = 0;
        short exc = -1;
 
@@ -1872,9 +1872,12 @@ static uae_u8 *validate_test(uae_u8 *p, short ignore_errors, short ignore_sr)
                        regs_changed[i] = 1;
                }
        }
-       if ((last_registers.sr & test_ccrignoremask) != (test_regs.sr & test_ccrignoremask)) {
+       if ((last_registers.sr & test_ccrignoremask & 0xff00) != (test_regs.sr & test_ccrignoremask & 0xff00)) {
                sr_changed = 1;
        }
+       if ((last_registers.sr & test_ccrignoremask & 0x00ff) != (test_regs.sr & test_ccrignoremask & 0x00ff)) {
+               ccr_changed = 1;
+       }
        if (last_registers.pc != test_regs.pc) {
                pc_changed = 1;
        }
@@ -1979,7 +1982,7 @@ static uae_u8 *validate_test(uae_u8 *p, short ignore_errors, short ignore_sr)
                        uae_u32 val = last_registers.regs[mode];
                        int size;
                        p = restore_value(p, &val, &size);
-                       if (val != test_regs.regs[mode] && !ignore_errors) {
+                       if (val != test_regs.regs[mode] && !ignore_errors && !skipregchange) {
                                if (dooutput) {
                                        sprintf(outbp, "%c%d: expected %08x but got %08x\n", mode < CT_AREG ? 'D' : 'A', mode & 7, val, test_regs.regs[mode]);
                                        outbp += strlen(outbp);
@@ -1988,7 +1991,7 @@ static uae_u8 *validate_test(uae_u8 *p, short ignore_errors, short ignore_sr)
                        }
                        regs_changed[mode] = 0;
                        last_registers.regs[mode] = val;
-               } else if (mode < CT_AREG && (v & CT_SIZE_MASK) == CT_SIZE_FPU) {
+               } else if (mode < CT_AREG && (v & CT_SIZE_MASK) == CT_SIZE_FPU && !skipregchange) {
                        struct fpureg val;
                        p = restore_fpvalue(p, &val);
                        if (memcmp(&val, &test_regs.fpuregs[mode], sizeof(struct fpureg)) && !ignore_errors) {
@@ -2027,11 +2030,12 @@ static uae_u8 *validate_test(uae_u8 *p, short ignore_errors, short ignore_sr)
                                }
                                // CCR check
                                mask = test_ccrignoremask & 0x00ff;
-                               if ((val & (sr_undefined_mask & mask)) == (test_regs.sr & (sr_undefined_mask & mask))) {
+                               if (skipccrchange || ((val & (sr_undefined_mask & mask)) == (test_regs.sr & (sr_undefined_mask & mask)))) {
                                        errflag &= ~(1 << 7);
                                }
                        }
                        sr_changed = 0;
+                       ccr_changed = 0;
                        last_registers.sr = val;
                        if (!(test_regs.expsr & 0x2000)) {
                                sprintf(outbp, "SR S-bit is not set at start of exception handler!\n");
@@ -2107,7 +2111,7 @@ static uae_u8 *validate_test(uae_u8 *p, short ignore_errors, short ignore_sr)
                        {
                                case 0:
                                mval = addr[0];
-                               if (mval != val && !ignore_errors) {
+                               if (mval != val && !ignore_errors && !skipmemwrite) {
                                        if (dooutput) {
                                                sprintf(outbp, "Memory byte write: address %08x, expected %02x but got %02x\n", (uae_u32)addr, val, mval);
                                                outbp += strlen(outbp);
@@ -2118,7 +2122,7 @@ static uae_u8 *validate_test(uae_u8 *p, short ignore_errors, short ignore_sr)
                                break;
                                case 1:
                                mval = (addr[0] << 8) | (addr[1]);
-                               if (mval != val && !ignore_errors) {
+                               if (mval != val && !ignore_errors && !skipmemwrite) {
                                        if (dooutput) {
                                                sprintf(outbp, "Memory word write: address %08x, expected %04x but got %04x\n", (uae_u32)addr, val, mval);
                                                outbp += strlen(outbp);
@@ -2130,7 +2134,7 @@ static uae_u8 *validate_test(uae_u8 *p, short ignore_errors, short ignore_sr)
                                break;
                                case 2:
                                mval = gl(addr);
-                               if (mval != val && !ignore_errors) {
+                               if (mval != val && !ignore_errors && !skipmemwrite) {
                                        if (dooutput) {
                                                sprintf(outbp, "Memory long write: address %08x, expected %08x but got %08x\n", (uae_u32)addr, val, mval);
                                                outbp += strlen(outbp);
@@ -2147,7 +2151,7 @@ static uae_u8 *validate_test(uae_u8 *p, short ignore_errors, short ignore_sr)
                }
        }
        if (!ignore_errors) {
-               if (!ignore_sr) {
+               if (!skipregchange) {
                        for (int i = 0; i < 16; i++) {
                                if (regs_changed[i]) {
                                        if (dooutput) {
@@ -2157,12 +2161,20 @@ static uae_u8 *validate_test(uae_u8 *p, short ignore_errors, short ignore_sr)
                                        errflag |= 1 << 0;
                                }
                        }
+               }
+               if (!ignore_sr) {
                        if (sr_changed) {
                                if (dooutput) {
                                        sprintf(outbp, "SR: modified %04x -> %04x but expected no modifications\n", last_registers.sr & 0xffff, test_regs.sr & 0xffff);
                                        outbp += strlen(outbp);
                                }
                                errflag |= 1 << 2;
+                       } else if (ccr_changed && !skipccrchange) {
+                               if (dooutput) {
+                                       sprintf(outbp, "SR: modified %04x -> %04x but expected no modifications\n", last_registers.sr & 0xffff, test_regs.sr & 0xffff);
+                                       outbp += strlen(outbp);
+                               }
+                               errflag |= 1 << 2;
                        }
                }
                for (int i = 0; i < 8; i++) {
@@ -2886,7 +2898,9 @@ int main(int argc, char *argv[])
                printf("-ccrmask = ignore CCR bits that are not set.\n");
                printf("-nodisasm = do not disassemble failed test.\n");
                printf("-basicexc = do only basic checks when exception is 2 or 3.\n");
-               printf("-excskipccr = ignore CCR if DivByZero, CHK, Address/Bus error exception.\n");
+               printf("-skipexcccr = ignore CCR if DivByZero, CHK, Address/Bus error exception.\n");
+               printf("-skipmem = do not validate memory writes.\n");
+               printf("-skipreg = do not validate registers.\n");
                printf("-askifmissing = ask for new path if dat file is missing.\n");
                printf("-exit n = exit after n tests.\n");
                printf("-cycles [range adjust] = check cycle counts.\n");
@@ -2939,8 +2953,14 @@ int main(int argc, char *argv[])
                        disasm = 0;
                } else if (!_stricmp(s, "-basicexc")) {
                        basicexcept = 1;
-               } else if (!_stricmp(s, "-excskipccr")) {
+               } else if (!_stricmp(s, "-skipexcccr")) {
                        excskipccr = 1;
+               } else if (!_stricmp(s, "-skipmem")) {
+                       skipmemwrite = 1;
+               } else if (!_stricmp(s, "-skipreg")) {
+                       skipregchange = 1;
+               } else if (!_stricmp(s, "-skipccr")) {
+                       skipccrchange = 1;
                } else if (!_stricmp(s, "-askifmissing")) {
                        askifmissing = 1;
                } else if (!_stricmp(s, "-next")) {
index 1c553904480ad33ef63ab88bf81f1dfa4ec295f1..fdd58ff3e74e67fc408617db50dfff408823b91d 100644 (file)
@@ -12,7 +12,7 @@ Verifies:
 - Memory writes, including stack modifications (if any)
 - Loop mode for JIT testing. (generates <test instruction>, dbf dn,loop)
 - Supports 68000, 68010, 68020, 68030 (only difference between 020 and 030 seems to be data cache and MMU), 68040 and 68060.
-- Cycle counts (68000 Amiga only)
+- Cycle counts (68000/68010, Amiga only)
 
 Tests executed for each tested instruction:
 
@@ -43,25 +43,26 @@ Notes and limitations:
 Tester compatibility (integer instructions only):
 
 68000: Complete. Including bus and address error stack frame/register/CCR modification undocumented behavior. Cycle count support.
-68010: Almost complete. Bus errors are only partially supported. DIVS undefined condition codes are not yet supported.
+68010: Almost complete (same as 68000). Loop mode is also fully supported. NOTE: DIVS overflow undocumented N-flag is not fully correct.
 68020: Almost complete (DIV undocumented behavior is not yet known)
 68030: Same as 68020.
 68040: Almost complete (Weird unaligned MOVE16 behavior which may be board specific).
 68060: Same as 68040.
 
-68000 cycle count testing:
+68000/68010 cycle count testing:
 
 Cycle counting requires 100% accurate timing also for following instructions:
 - BSR.B
 - NOP
 - MOVE.W ABS.L,ABS.L
 - MOVE SR,-(SP)
+- MOVE.W #x,ABS.L (68010 only)
 - RTE
 - Illegal instruction exception
 - If instruction internally generates exception, internal exception also needs to be cycle-accurate.
 
 0xDFF006 is used for cycle counting = accuracy will be +-2 CPU cycles. 0xDFF006 behavior must be accurate.
-Currently only supported hardware for cycle counting is 7MHz 68000 PAL Amiga with real Fast RAM.
+Currently only supported hardware for cycle counting is 7MHz 68000/68010 PAL Amiga with real Fast RAM.
 
 Bus error cycle counting is not yet supported.
 
@@ -124,7 +125,18 @@ If mismatch is detected, opcode word(s), instruction disassembly, registers befo
 
 Change log:
 
+18.01.2020
+
 - Cycle count validation (Amiga, 68000 only), including exceptions (except bus errors).
 - Interrupt testing (Amiga only, INTREQ bits set one by one, validate correct exception).
 - Multiple test sets can be generated and tested in single step.
 - Stack usage reduced, gzip decompression works with default 4096 byte stack.
+
+26.01.2020
+
+- 68010 is now almost fully supported, including loop mode and cycle count verification.
+- Removed most ColdFire instructions from disassembler. RTD was not disassembled if 68010. Added missing 68060 PCR and BUSCR control registers.
+- Fixed ahist overflow when generating MOVEM with more than 1 SR flag combination.
+- Some instructions (for example TRAP) had wrong expected cycle count if instruction generated any non-trace exception and also trace exception.
+- added -skipexcccr parameter. Skip CCR check if instruction generates bus, address, divide by zero or CHK exception.
+- added -skipmem (ignore memory write mismatches) -skipreg (ignore register mismatched) -skipccr (ignored CCR mismatch) parameters.
index dd84ab428a445dd078b8ea5ed6c5a6ab229ff1b0..877c8fa9024083dd54ad13ace77e05cf0da93a75 100644 (file)
@@ -59,23 +59,25 @@ static int opcode_nextcopy;
 
 static int optimized_flags;
 
-#define GF_APDI 1
-#define GF_AD8R 2
-#define GF_PC8R 4
-#define GF_AA 7
-#define GF_NOREFILL 8
-#define GF_PREFETCH 16
-#define GF_FC 32
-#define GF_MOVE 64
-#define GF_IR2IRC 128
-#define GF_LRMW 256
-#define GF_NOFAULTPC 512
-#define GF_RMW 1024
-#define GF_OPCE020 2048
-#define GF_REVERSE 4096
-#define GF_REVERSE2 8192
-#define GF_SECONDWORDSETFLAGS 16384
-#define GF_SECONDEA 32768
+#define GF_APDI                0x00001
+#define GF_AD8R                0x00002
+#define GF_PC8R                0x00004
+#define GF_AA          0x00007
+#define GF_NOREFILL    0x00008
+#define GF_PREFETCH    0x00010
+#define GF_FC          0x00020
+#define GF_MOVE                0x00040
+#define GF_IR2IRC      0x00080
+#define GF_LRMW                0x00100
+#define GF_NOFAULTPC   0x00200
+#define GF_RMW         0x00400
+#define GF_OPCE020     0x00800
+#define GF_REVERSE     0x01000
+#define GF_REVERSE2    0x02000
+#define GF_SECONDWORDSETFLAGS  0x04000
+#define GF_SECONDEA    0x08000
+#define GF_NOFETCH     0x10000 // 68010
+#define GF_CLR68010    0x20000 // 68010
 
 typedef enum
 {
@@ -103,6 +105,8 @@ static char rmw_varname[100];
 static struct instr *g_instr;
 static char g_srcname[100];
 static int loopmode;
+static int loopmodeextra;
+static int loopmode_set;
 
 #define GENA_GETV_NO_FETCH     0
 #define GENA_GETV_FETCH                1
@@ -197,7 +201,15 @@ static instr *curi_ce020;
 static bool no_prefetch_ce020;
 static bool got_ea_ce020;
 
-// 68020-30 needs different implementation than 68040/060
+// 68010-40 needs different implementation than 68060
+static void next_level_060_to_040(void)
+{
+       if (cpu_level >= 5) {
+               if (next_cpu_level < 5)
+                       next_cpu_level = 5 - 1;
+       }
+}
+// 68010-30 needs different implementation than 68040/060
 static void next_level_040_to_030(void)
 {
        if (cpu_level >= 4) {
@@ -205,7 +217,6 @@ static void next_level_040_to_030(void)
                        next_cpu_level = 4 - 1;
        }
 }
-
 // 68000 <> 68010
 static void next_level_000(void)
 {
@@ -420,6 +431,15 @@ static void returncycles(const char *s, int cycles)
                printf("%sreturn %d * CYCLE_UNIT / 2;\n", s, cycles);
 }
 
+static void write_return_cycles_none(const char *s)
+{
+       if (using_ce || using_ce020) {
+               printf("%sreturn;\n", s);
+       } else {
+               printf("%sreturn 0;\n", s);
+       }
+}
+
 static void write_return_cycles(const char *s, int end)
 {
        if (end <= 0) {
@@ -909,8 +929,12 @@ static void fill_prefetch_1 (int o)
 {
        if (using_prefetch) {
                printf("\t%s(%d);\n", prefetch_word, o);
-               count_read++;
-               insn_n_cycles += 4;
+               if (!loopmode || using_ce) {
+                       count_read++;
+                       insn_n_cycles += 4;
+               } else {
+                       addcycles000_nonce("\t", 4);
+               }
                check_prefetch_bus_error(o, 0);
                did_prefetch = 1;
                ir2irc = 0;
@@ -1081,25 +1105,113 @@ static void fill_prefetch_0 (void)
        ir2irc = 0;
 }
 
+static void loopmode_start(void)
+{
+       loopmode_set = 0;
+       loopmodeextra = 0;
+       if (loopmode) {
+               printf("\tint loop_mode = regs.loop_mode;\n");
+       }
+}
+static void loopmode_stop(void)
+{
+       if (loopmode) {
+               printf("\tregs.loop_mode = loop_mode;\n");
+       }
+}
 static void loopmode_begin(void)
 {
        if (loopmode) {
-               printf("\tif(!regs.loop_mode) {\n");
+               printf("\tif(!loop_mode) {\n");
+       }
+}
+static void loopmode_access(void)
+{
+       if (loopmode && loopmode_set) {
+               loopmode_set = 0;
+               printf("\tif(loop_mode & 0xfffe) {\n");
+               if (using_ce) {
+                       printf("\t\t%s(loop_mode & 0xfffe);\n", do_cycles);
+               } else {
+                       addcycles000_nonces("\t\t", "loop_mode & 0xfffe");
+               }
+               // CLR.L adds 2 extra cycles when loop exits
+               if (g_instr->mnemo == i_CLR && g_instr->size == sz_long) {
+                       printf("\t\tloop_mode &= 0xffff0000;\n");
+                       printf("\t\tloop_mode |= 1;\n");
+               } else {
+                       printf("\t\tloop_mode = 1;\n");
+               }
+               printf("\t}\n");
        }
 }
+
 static void loopmode_end(void)
 {
        if (loopmode) {
+               int s = g_instr->size;
                int m = g_instr->mnemo;
-               if (using_ce && (g_instr->dmode == Apdi || (m != i_MOVE && m != i_CLR))) {
-                       printf("\t} else {\n");
-                       if (m == i_ASLW || m == i_ASRW || m == i_LSLW || m == i_LSRW || m == i_ROLW || m == i_RORW || m == i_ROXLW || m == i_ROXRW) {
-                               addcycles000(4);
+               int cycs = 0;
+               int ecycs = 0;
+               if (using_prefetch) {
+                       if (m == i_CLR) {
+                               cycs += 2;
+                               ecycs += 4;
+                       } else if (m == i_MOVE) {
+                               cycs += 2;
+                               if (isreg(g_instr->smode)) {
+                                       ecycs = 2;
+                               }
+                       } else if (m == i_ADDX || m == i_SUBX) {
+                               if (s == sz_long) {
+                                       cycs += 2;
+                               } else {
+                                       cycs += 4;
+                               }
+                       } else if (m == i_CMPM) {
+                               if (s == sz_long) {
+                                       cycs += 4;
+                               } else {
+                                       cycs += 2;
+                               }
+                       } else if (m == i_NBCD) {
+                               cycs += 6;
                        } else {
-                               addcycles000(2);
+                               cycs += 4;
+                       }
+                       // destination -(an)?
+                       if ((m == i_MOVE || m == i_ABCD || m == i_SBCD) && g_instr->dmode == Apdi) {
+                               cycs += 2;
+                       }
+
+                       if (ecycs == 0) {
+                               ecycs = cycs;
                        }
+
+                       if (m == i_TST && s == sz_long) {
+                               ecycs = 4;
+                               cycs = 6;
+                       } else if (m == i_MOVE) {
+                               if (isreg(g_instr->smode)) {
+                                       ecycs += 2;
+                               }
+                       } else if (m == i_CMP && s == sz_long) {
+                               ecycs -= 2;
+                       }
+
+                       if (cycs > 0 || ecycs > 0) {
+                               printf("\t} else {\n");
+                               printf("\t\tloop_mode = 0;\n");
+                               if (cycs > 0) {
+                                       printf("\t\tloop_mode |= %d;\n", cycs);
+                               }
+                               if (ecycs > 0) {
+                                       printf("\t\tloop_mode |= %d << 16;\n", ecycs);
+                               }
+                       }
+                       printf("\t}\n");
+                       loopmode_set = 1;
                }
-               printf("\t}\n");
        }
 }
 
@@ -2617,6 +2729,8 @@ static void genamode2x (amodes mode, const char *reg, wordsizes size, const char
                genamode_cnt++;
        }
 
+       loopmode_access();
+
        start_brace ();
 
        switch (mode) {
@@ -2684,6 +2798,9 @@ static void genamode2x (amodes mode, const char *reg, wordsizes size, const char
                printf("\tuaecptr %sa;\n", name);
                add_mmu040_movem (movem);
                printf("\t%sa = m68k_areg(regs, %s);\n", name, reg);
+               if ((flags & GF_NOFETCH) && using_prefetch) {
+                       addcycles000(2);
+               }
                break;
        case Aipi: // (An)+
                switch (fetchmode)
@@ -2697,6 +2814,9 @@ static void genamode2x (amodes mode, const char *reg, wordsizes size, const char
                printf("\tuaecptr %sa;\n", name);
                add_mmu040_movem (movem);
                printf("\t%sa = m68k_areg(regs, %s);\n", name, reg);
+               if ((flags & GF_NOFETCH) && using_prefetch) {
+                       addcycles000(4);
+               }
                break;
        case Apdi: // -(An)
                switch (fetchmode)
@@ -2724,7 +2844,13 @@ static void genamode2x (amodes mode, const char *reg, wordsizes size, const char
                default:
                        term ();
                }
-               if (!(flags & GF_APDI)) {
+               if (flags & GF_NOFETCH) {
+                       if (using_prefetch) {
+                               addcycles000(4);
+                       }
+                       insn_n_cycles += 2;
+                       count_cycles_ea += 2;
+               } else if (!(flags & GF_APDI)) {
                        addcycles000 (2);
                        insn_n_cycles += 2;
                        count_cycles_ea += 2;
@@ -2768,7 +2894,7 @@ static void genamode2x (amodes mode, const char *reg, wordsizes size, const char
                        insn_n_cycles += 4;
                        printf("\t%sa = %s(m68k_areg(regs, %s), %d);\n", name, disp020, reg, disp020cnt++);
                } else {
-                       if (!(flags & GF_AD8R)) {
+                       if (!(flags & GF_AD8R) && !(flags & GF_NOFETCH) && !(flags & GF_CLR68010)) {
                                addcycles000 (2);
                                insn_n_cycles += 2;
                                count_cycles_ea += 2;
@@ -2780,6 +2906,16 @@ static void genamode2x (amodes mode, const char *reg, wordsizes size, const char
                        }
                        count_read_ea++; 
                }
+               if ((flags & GF_NOFETCH) && using_prefetch) {
+                       addcycles000(4);
+                       insn_n_cycles += 4;
+                       count_cycles_ea += 4;
+               }
+               if ((flags & GF_CLR68010) && using_prefetch) {
+                       addcycles000(4);
+                       insn_n_cycles += 4;
+                       count_cycles_ea += 4;
+               }
                addr = true;
                break;
        case PC8r: // (d8,PC,Xn)
@@ -2817,6 +2953,9 @@ static void genamode2x (amodes mode, const char *reg, wordsizes size, const char
                                printf("\t%sa = %s(tmppc, %s);\n", name, disp000, gen_nextiword (flags));
                        }
                }
+               if ((flags & GF_NOFETCH) && using_prefetch) {
+                       addcycles000(4);
+               }
                addr = true;
                break;
        case absw:
@@ -3123,14 +3262,16 @@ static void genamode2x (amodes mode, const char *reg, wordsizes size, const char
                        switch (size) {
                        case sz_byte:
                        {
-                               insn_n_cycles += 4; printf("\tuae_s8 %s = %s(%sa);\n", name, srcbx, name);
+                               insn_n_cycles += 4;
+                               printf("\tuae_s8 %s = %s(%sa);\n", name, srcbx, name);
                                count_read++;
                                check_bus_error(name, 0, 0, 0, NULL, 1);
                                break;
                        }
                        case sz_word:
                        {
-                               insn_n_cycles += 4; printf("\tuae_s16 %s = %s(%sa);\n", name, srcwx, name);
+                               insn_n_cycles += 4;
+                               printf("\tuae_s16 %s = %s(%sa);\n", name, srcwx, name);
                                count_read++;
                                check_bus_error(name, 0, 0, 1, NULL, 1);
                                break;
@@ -3142,14 +3283,14 @@ static void genamode2x (amodes mode, const char *reg, wordsizes size, const char
                                        printf("\tuae_s32 %s = %s(%sa + 2);\n", name, srcwx, name);
                                        count_read++;
                                        check_bus_error(name, 0, 0, 1, NULL, 1);
-                                       printf("\t%s |= %s(%sa) << 16; \n", name, srcw, name);
+                                       printf("\t%s |= %s(%sa) << 16; \n", name, srcwx, name);
                                        count_read++;
                                        check_bus_error(name, -2, 0, 1, NULL, 1);
                                } else {
                                        printf("\tuae_s32 %s = %s(%sa) << 16;\n", name, srcwx, name);
                                        count_read++;
                                        check_bus_error(name, 0, 0, 1, NULL, 1);
-                                       printf("\t%s |= %s(%sa + 2); \n", name, srcw, name);
+                                       printf("\t%s |= %s(%sa + 2); \n", name, srcwx, name);
                                        count_read++;
                                        check_bus_error(name, 2, 0, 1, NULL, 1);
                                }
@@ -3310,6 +3451,9 @@ static void genastore_2 (const char *from, amodes mode, const char *reg, wordsiz
                if (strcmp (rmw_varname, to) != 0)
                        candormw = false;
        }
+
+       loopmode_access();
+
        genastore_done = true;
        if (!(flags & GF_LRMW)) {
                returntail(mode != Dreg && mode != Areg);
@@ -3439,7 +3583,7 @@ static void genastore_2 (const char *from, amodes mode, const char *reg, wordsiz
                                        if (flags & GF_SECONDWORDSETFLAGS) {
                                                genflags(flag_logical, g_instr->size, "src", "", "");
                                        }
-                                       printf("%s(%sa, %s >> 16);\n", dstwx, to, from);
+                                       printf("\t%s(%sa, %s >> 16);\n", dstwx, to, from);
                                        sprintf(tmp, "%s >> 16", from);
                                        count_write++;
                                        check_bus_error(to, 0, 1, 1, tmp, 1);
@@ -4621,6 +4765,7 @@ static void gen_opcode (unsigned int opcode)
                if (curi->mnemo == i_DBcc || loopmode) {
                        next_level_000();
                }
+               loopmode_start();
        }
 
        // do not unnecessarily create useless mmuop030
@@ -4677,10 +4822,14 @@ static void gen_opcode (unsigned int opcode)
                                        if (cpu_level == 0) {
                                                c += 2;
                                        }
+                                       if (cpu_level == 1 && curi->smode == immi) {
+                                               c += 2;
+                                       }
                                        fill_prefetch_next_after(1, "\t\tccr_68000_long_move_ae_LZN(src);\n\t\tdreg_68000_long_replace_low(dstreg, src);\n");
                                } else {
                                        fill_prefetch_next_after(1, "\t\tdreg_68000_long_replace_low(dstreg, src);\n");
                                }
+                               loopmodeextra = 4;
                        } else {
                                fill_prefetch_next_after(0, "\t\tccr_68000_long_move_ae_LZN(src);\n");
                        }
@@ -4695,6 +4844,7 @@ static void gen_opcode (unsigned int opcode)
                                fill_prefetch_next_after(1, NULL);
                        } else {
                                fill_prefetch_next_t();
+                               loopmodeextra = 4;
                        }
                        if (c > 0)
                                addcycles000(c);
@@ -4741,6 +4891,9 @@ static void gen_opcode (unsigned int opcode)
                                        if (cpu_level == 0) {
                                                c += 2;
                                        }
+                                       if (cpu_level == 1 && curi->smode == immi) {
+                                               c += 2;
+                                       }
                                        fill_prefetch_next_after(1,
                                                "\t\tuae_s16 bnewv = (uae_s16)dst - (uae_s16)src;\n"
                                                "\t\tint bflgs = ((uae_s16)(src)) < 0;\n"
@@ -4754,6 +4907,7 @@ static void gen_opcode (unsigned int opcode)
                                } else {
                                        fill_prefetch_next_after(1, "\t\tdreg_68000_long_replace_low(dstreg, newv);\n");
                                }
+                               loopmodeextra = 4;
                        } else {
                                fill_prefetch_next_after(0,
                                        "\t\tuae_s16 bnewv = (uae_s16)dst - (uae_s16)src;\n"
@@ -4776,6 +4930,7 @@ static void gen_opcode (unsigned int opcode)
                                fill_prefetch_next_after(1, NULL);
                        } else {
                                fill_prefetch_next_t();
+                               loopmodeextra = 4;
                        }
                        if (c > 0)
                                addcycles000(c);
@@ -4797,12 +4952,15 @@ static void gen_opcode (unsigned int opcode)
                        c += 4;
                } else {
                        c = curi->size == sz_long ? 2 : 4;
-                       if (islongimm (curi))
+                       if (islongimm(curi)) {
                                c += 2;
+                       }
+                       loopmodeextra = curi->size == sz_long ? 4 : 2;
                }
                fill_prefetch_next_after(0, "\t\tareg_68000_long_replace_low(dstreg, newv);\n");
-               if (c > 0)
-                       addcycles000 (c);
+               if (c > 0) {
+                       addcycles000(c);
+               }
                genastore ("newv", curi->dmode, "dstreg", sz_long, "dst");
                break;
        }
@@ -4912,6 +5070,10 @@ static void gen_opcode (unsigned int opcode)
                                        if (cpu_level == 0) {
                                                c += 2;
                                        }
+                                       if (cpu_level == 1 && curi->smode == immi) {
+                                               // 68010 Immediate long instructions 2 cycles faster, Q variants have same speed.
+                                               c += 2;
+                                       }
                                        fill_prefetch_next_after(1,
                                                "\t\tuae_s16 bnewv = (uae_s16)dst + (uae_s16)src;\n"
                                                "\t\tint bflgs = ((uae_s16)(src)) < 0;\n"
@@ -4925,6 +5087,7 @@ static void gen_opcode (unsigned int opcode)
                                } else {
                                        fill_prefetch_next_after(1, "\t\tdreg_68000_long_replace_low(dstreg, newv);\n");
                                }
+                               loopmodeextra = 4;
                        } else {
                                fill_prefetch_next_after(0,
                                        "\t\tuae_s16 bnewv = (uae_s16)dst + (uae_s16)src;\n"
@@ -4947,6 +5110,7 @@ static void gen_opcode (unsigned int opcode)
                                fill_prefetch_next_after(1, NULL);
                        } else {
                                fill_prefetch_next_t();
+                               loopmodeextra = 4;
                        }
                        if (c > 0)
                                addcycles000(c);
@@ -4968,12 +5132,15 @@ static void gen_opcode (unsigned int opcode)
                        c += 4;
                } else {
                        c = curi->size == sz_long ? 2 : 4;
-                       if (islongimm (curi))
+                       if (islongimm(curi)) {
                                c += 2;
+                       }
+                       loopmodeextra = curi->size == sz_long ? 4 : 2;
                }
                fill_prefetch_next_after(1, "\t\tareg_68000_long_replace_low(dstreg, newv);\n");
-               if (c > 0)
-                       addcycles000 (c);
+               if (c > 0) {
+                       addcycles000(c);
+               }
                genastore("newv", curi->dmode, "dstreg", sz_long, "dst");
                break;
        }
@@ -5221,9 +5388,10 @@ static void gen_opcode (unsigned int opcode)
                                genastore_rev("0", curi->smode, "srcreg", curi->size, "src");
                        }
                } else if (cpu_level == 1) {
-                       genamode(curi, curi->smode, "srcreg", curi->size, "src", 3, 0, 0);
-                       if (isreg(curi->smode) && curi->size == sz_long)
+                       genamode(curi, curi->smode, "srcreg", curi->size, "src", 3, 0, GF_CLR68010);
+                       if (isreg(curi->smode) && curi->size == sz_long) {
                                addcycles000(2);
+                       }
                        if (!isreg(curi->smode) && using_exception_3 && curi->size != sz_byte && (using_prefetch || using_ce)) {
                                printf("\tif(srca & 1) {\n");
                                if (curi->size == sz_word) {
@@ -5344,8 +5512,16 @@ static void gen_opcode (unsigned int opcode)
                }
                bsetcycles(curi);
                // bclr needs 1 extra cycle
-               if (curi->mnemo == i_BCLR && curi->dmode == Dreg)
-                       addcycles000 (2);
+               if (curi->mnemo == i_BCLR && curi->dmode == Dreg) {
+                       addcycles000(2);
+               }
+               if (curi->mnemo == i_BCLR && curi->size == sz_byte) {
+                       if (cpu_level == 1) {
+                               // 68010 BCLR.B is 2 cycles slower
+                               addcycles000(2);
+                       }
+                       next_level_000();
+               }
                if (curi->mnemo == i_BCHG) {
                        printf("\tdst ^= (1 << src);\n");
                        printf("\tSET_ZFLG(((uae_u32)dst & (1 << src)) >> src);\n");
@@ -5397,7 +5573,7 @@ static void gen_opcode (unsigned int opcode)
                /* The next two are coded a little unconventional, but they are doing
                * weird things... */
        case i_MVPRM: // MOVEP R->M
-               genamode (curi, curi->smode, "srcreg", curi->size, "src", 1, 0, 0);
+               genamode (curi, curi->smode, "srcreg", curi->size, "src", 1, 0, cpu_level == 1 ? GF_NOFETCH : 0);
                printf("\tuaecptr mempa = m68k_areg(regs, dstreg) + (uae_s32)(uae_s16)%s;\n", gen_nextiword (0));
                check_prefetch_buserror(m68k_pc_offset);
                if (curi->size == sz_word) {
@@ -5426,7 +5602,7 @@ static void gen_opcode (unsigned int opcode)
        case i_MVPMR: // MOVEP M->R
                printf("\tuaecptr mempa = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)%s;\n", gen_nextiword (0));
                check_prefetch_buserror(m68k_pc_offset);
-               genamode (curi, curi->dmode, "dstreg", curi->size, "dst", 2, 0, 0);
+               genamode (curi, curi->dmode, "dstreg", curi->size, "dst", 2, 0, cpu_level == 1 ? GF_NOFETCH : 0);
                if (curi->size == sz_word) {
                        printf("\tuae_u16 val  = (%s(mempa) & 0xff) << 8;\n", srcb);
                        count_read++;
@@ -5683,7 +5859,8 @@ static void gen_opcode (unsigned int opcode)
                }
                break;
        case i_MVSR2: // MOVE FROM SR
-               genamode (curi, curi->smode, "srcreg", sz_word, "src", cpu_level == 0 ? 2 : 3, 0, 0);
+               next_level_000();
+               genamode (curi, curi->smode, "srcreg", sz_word, "src", cpu_level == 0 ? 2 : 3, 0, cpu_level == 1 ? GF_NOFETCH : 0);
                printf("\tMakeSR();\n");
                if (isreg (curi->smode)) {
                        if (cpu_level == 0 && curi->size == sz_word) {
@@ -5693,7 +5870,9 @@ static void gen_opcode (unsigned int opcode)
                        } else {
                                fill_prefetch_next_after(1, NULL);
                        }
-                       addcycles000 (2);
+                       if (cpu_level == 0) {
+                               addcycles000(2);
+                       }
                } else {
                        // 68000: read first and ignore result
                        if (cpu_level == 0 && curi->size == sz_word) {
@@ -5798,14 +5977,22 @@ static void gen_opcode (unsigned int opcode)
                clear_m68k_offset();
                break;
        case i_MVR2USP:
+               next_level_000();
                genamode(curi, curi->smode, "srcreg", curi->size, "src", 1, 0, 0);
                printf("\tregs.usp = src;\n");
+               if (cpu_level == 1) {
+                       addcycles000(2);
+               }
                fill_prefetch_next_t();
                trace_t0_68040_only();
                break;
        case i_MVUSP2R:
+               next_level_000();
                genamode(curi, curi->smode, "srcreg", curi->size, "src", 2, 0, 0);
                genastore("regs.usp", curi->smode, "srcreg", curi->size, "src");
+               if (cpu_level == 1) {
+                       addcycles000(2);
+               }
                fill_prefetch_next_t();
                break;
        case i_RESET:
@@ -5907,8 +6094,16 @@ static void gen_opcode (unsigned int opcode)
                        // 68010
                        int old_brace_level = n_braces;
                        printf("\tuaecptr oldpc = %s;\n", getpc);
-                       printf("\tuae_u16 newsr; uae_u32 newpc;\n");
+                       printf("\tuae_u16 newsr;\n");
+                       printf("\tuae_u32 newpc;\n");
                        printf("\tuaecptr a = m68k_areg(regs, 7);\n");
+                       printf("\tuae_u16 sr = %s(a);\n", srcw);
+                       count_read++;
+                       check_bus_error("", 0, 0, 1, NULL, 1);
+                       printf("\tuae_u32 pc = %s(a + 2) << 16;\n", srcw);
+                       count_read++;
+                       check_bus_error("", 2, 0, 1, NULL, 1);
+
                        printf("\tuae_u16 format = %s(a + 2 + 4);\n", srcw);
                        count_read++;
                        check_bus_error("", 6, 0, 1, NULL, 1);
@@ -5925,12 +6120,7 @@ static void gen_opcode (unsigned int opcode)
                        printf("\t\tException_cpu(14);\n");
                        write_return_cycles("\t\t", 0);
                        printf("\t}\n");
-                       printf("\tuae_u16 sr = %s(a);\n", srcw);
-                       count_read++;
-                       check_bus_error("", 0, 0, 1, NULL, 1);
-                       printf("\tuae_u32 pc = %s(a + 2) << 16;\n", srcw);
-                       count_read++;
-                       check_bus_error("", 2, 0, 1, NULL, 1);
+
                        printf("\tpc |= %s(a + 4); \n", srcw);
                        count_read++;
                        check_bus_error("", 4, 0, 1, NULL, 1);
@@ -6066,7 +6256,7 @@ static void gen_opcode (unsigned int opcode)
                        printf("\tm68k_areg(regs, 7) += offs;\n");
                } else {
                        genamode (NULL, Aipi, "7", sz_long, "pc", 1, 0, 0);
-                       genamode (curi, curi->smode, "srcreg", curi->size, "offs", 1, 0, 0);
+                       genamode (curi, curi->smode, "srcreg", curi->size, "offs", 1, 0, GF_NOREFILL);
                        printf("\tm68k_areg(regs, 7) += offs;\n");
                }
            printf("\tif (pc & 1) {\n");
@@ -6209,31 +6399,49 @@ static void gen_opcode (unsigned int opcode)
                break;
        case i_TRAPV:
                sync_m68k_pc();
-               // TRAPV is really weird
-               // If V is set but prefetch causes bus error: S is set.
-               // for some reason T is also cleared!
-               if (using_prefetch) {
-                       printf("\tuae_u16 opcode_v = opcode;\n");
-               }
-               fill_prefetch_next_after(1,
-                       "\t\tif (GET_VFLG()) {\n"
-                       "\t\t\tMakeSR();\n"
-                       "\t\t\tregs.sr |= 0x2000;\n"
-                       "\t\t\tregs.sr &= ~0x8000;\n"
-                       "\t\t\tMakeFromSR();\n"
-                       "\t\t} else {\n"
-                       "\t\t\topcode = regs.ir | 0x20000;\n"
-                       "\t\t\tif(regs.t1) opcode |= 0x10000;\n"
-                       "\t\t}\n");
-               printf("\tif (GET_VFLG()) {\n");
-               if (using_prefetch) {
-                       // If exception vector is odd,
-                       // stacked opcode is TRAPV
-                       printf("\t\tregs.ir = opcode_v;\n");
+               next_level_000();
+               if (cpu_level == 0) {
+                       // 68000 TRAPV is really weird
+                       // If V is set but prefetch causes bus error: S is set.
+                       // for some reason T is also cleared!
+                       if (using_prefetch) {
+                               printf("\tuae_u16 opcode_v = opcode;\n");
+                       }
+                       fill_prefetch_next_after(1,
+                               "\t\tif (GET_VFLG()) {\n"
+                               "\t\t\tMakeSR();\n"
+                               "\t\t\tregs.sr |= 0x2000;\n"
+                               "\t\t\tregs.sr &= ~0x8000;\n"
+                               "\t\t\tMakeFromSR();\n"
+                               "\t\t} else {\n"
+                               "\t\t\topcode = regs.ir | 0x20000;\n"
+                               "\t\t\tif(regs.t1) opcode |= 0x10000;\n"
+                               "\t\t}\n");
+                       printf("\tif (GET_VFLG()) {\n");
+                       if (using_prefetch) {
+                               // If exception vector is odd,
+                               // stacked opcode is TRAPV
+                               printf("\t\tregs.ir = opcode_v;\n");
+                       }
+                       printf("\t\tException_cpu(7);\n");
+                       write_return_cycles("\t\t", 0);
+                       printf("\t}\n");
+               } else if (cpu_level == 1) {
+                       push_ins_cnt();
+                       printf("\tif (GET_VFLG()) {\n");
+                       addcycles000(2);
+                       printf("\t\tException_cpu(7);\n");
+                       write_return_cycles("\t\t", 0);
+                       printf("\t}\n");
+                       pop_ins_cnt();
+                       fill_prefetch_next();
+               } else {
+                       fill_prefetch_next();
+                       printf("\tif (GET_VFLG()) {\n");
+                       printf("\t\tException_cpu(7);\n");
+                       write_return_cycles("\t\t", 0);
+                       printf("\t}\n");
                }
-               printf("\t\tException_cpu(7);\n");
-               write_return_cycles("\t\t", 0);
-               printf("\t}\n");
                break;
        case i_RTR:
                printf("\tuaecptr oldpc = %s;\n", getpc);
@@ -6619,10 +6827,12 @@ bccl_not68020:
                        curi->smode, "srcreg", curi->size, "src", 1, GF_AA | (cpu_level < 2 ? GF_NOREFILL : 0),
                        curi->dmode, "dstreg", curi->size, "offs", 1, GF_AA | (cpu_level < 2 ? GF_NOREFILL : 0));
                if (cpu_level == 1) {
-                       printf("\tregs.loop_mode = false;\n");
+                       printf("\tint was_loop_mode = regs.loop_mode;\n");
+                       printf("\tregs.loop_mode = 0;\n");
                }
                printf("\tuaecptr oldpc = %s;\n", getpc);
-               addcycles000 (2);
+               addcycles000(2);
+               addcycles000_nonce("\t", 2);
                if (using_exception_3 && cpu_level >= 4) {
                        printf("\tif (offs & 1) {\n");
                        printf("\t\t\texception3i(opcode, oldpc + (uae_s32)offs + 2);\n");
@@ -6650,35 +6860,73 @@ bccl_not68020:
                // 68010 loop mode handling
                if (cpu_level == 1) {
                        printf("\t\tif(offs == -4 && !regs.t1 && loop_mode_table[regs.ird]) {\n");
-                       printf("\t\t\tregs.loop_mode = true;\n");
+                       // first loop takes as many cycles as normal DBcc branch
+                       // perhaps it also does actual prefetches??
+                       printf("\t\t\tif(!was_loop_mode) {\n");
+                       addcycles000(6);
+                       addcycles000_nonce("\t\t", 6);
+                       printf("\t\t\t}\n");
+                       printf("\t\t\tregs.loop_mode = 1;\n");
                        printf("\t\t\tsrc = m68k_dreg(regs, srcreg);\n");
                        genastore("(src - 1)", curi->smode, "srcreg", curi->size, "src");
                        addcycles000(2);
+                       addcycles000_nonce("\t\t", 2);
                        printf("\t\t\tif (src) {\n");
                        if (using_ce) {
                                printf("\t\t\t\tloop_mode_table[regs.ird](regs.ird);\n");
                        } else {
                                printf("\t\t\t\tcount_cycles += loop_mode_table[regs.ird](regs.ird);\n");
                        }
+
+                       printf("\t // quick exit if condition false and count expired\n");
+                       printf("\t\t\t\tif (!cctrue(%d) && (m68k_dreg(regs, srcreg) & 0xffff) == 0) {\n", curi->cc);
+                       printf("\t\t\t\t\tm68k_dreg(regs, srcreg) |= 0xffff;\n");
+
+                       printf("\t // loop exit: add possible extra cycle(s)\n");
+                       printf("\t\t\t\t\tif(regs.loop_mode >> 16) {\n");
+                       if (using_ce) {
+                               printf("\t\t\t\t\t\t%s(regs.loop_mode >> 16);\n", do_cycles);
+                       }
+                       addcycles000_nonces("\t\t\t\t\t\t", "regs.loop_mode >> 16");
+                       printf("\t\t\t\t\t}\n");
+
+                       printf("\t\t\t\t\tregs.loop_mode = 0;\n");
+                       setpc("oldpc + %d", m68k_pc_offset);
+                       int old_m68k_pc_offset = m68k_pc_offset;
+                       int old_m68k_pc_total = m68k_pc_total;
+                       clear_m68k_offset();
+                       get_prefetch_020_continue();
+                       fill_prefetch_full_000_special();
+                       returncycles("\t\t\t", 8);
+                       m68k_pc_offset = old_m68k_pc_offset;
+                       m68k_pc_total = old_m68k_pc_total;
+                       printf("\t\t\t\t}\n");
+
+                       printf("\t // loop continue: add possible extra cycle(s)\n");
+                       printf("\t\t\t\tif(regs.loop_mode & 0xfffe) {\n");
+                       addcycles000_nonces("\t\t\t\t\t", "regs.loop_mode & 0xfffe");
+                       if (using_ce) {
+                               printf("\t\t\t\t\t%s(regs.loop_mode & 0xfffe);\n", do_cycles);
+                       }
+                       printf("\t\t\t\t}\n");
+
                        setpc("oldpc");
                        check_ipl();
-                       addcycles000(2);
-                       returncycles("\t\t\t\t", 4);
-                       printf("\t\t\t} else {\n");
-                       addcycles000(2);
+                       returncycles("\t\t\t\t", 0);
                        printf("\t\t\t}\n");
-                       printf("\t\t\tregs.loop_mode = false;\n");
+                       printf("\t\t\tregs.loop_mode = 0;\n");
                        setpc("oldpc + %d", m68k_pc_offset);
                        fill_prefetch_full_000_special();
-                       returncycles("\t\t\t", 6);
+                       returncycles("\t\t\t", 8);
                        printf("\t\t}\n");
                }
 
                printf("\t");
                fill_prefetch_1(0);
                printf("\t");
-               if (cpu_level < 2 || cpu_level >= 4)
-                       genastore ("(src - 1)", curi->smode, "srcreg", curi->size, "src");
+               if (cpu_level < 2 || cpu_level >= 4) {
+                       genastore("(src - 1)", curi->smode, "srcreg", curi->size, "src");
+               }
                printf("\t\tif (src) {\n");
                irc2ir ();
                add_head_cycs (6);
@@ -6723,9 +6971,8 @@ bccl_not68020:
                next_level_040_to_030();
                break;
        case i_Scc:
-               // confirmed
                next_level_000();
-               genamode(curi, curi->smode, "srcreg", curi->size, "src", cpu_level == 0 ? 1 : 2, 0, 0);
+               genamode(curi, curi->smode, "srcreg", curi->size, "src", cpu_level == 0 ? 1 : 2, 0, cpu_level == 1 ? GF_NOFETCH : 0);
                if (isreg(curi->smode)) {
                        // If mode is Dn and condition true = 2 extra cycles needed.
                        printf("\tint val = cctrue(%d) ? 0xff : 0x00;\n", curi->cc);
@@ -7235,6 +7482,7 @@ bccl_not68020:
                printf("\tSET_CFLG (cflg);\n");
                duplicate_carry (0);
                genastore ("val", curi->smode, "srcreg", curi->size, "data");
+               loopmodeextra = 2;
                break;
        case i_ASLW:
                genamode (curi, curi->smode, "srcreg", curi->size, "data", 1, 0, GF_RMW);
@@ -7254,6 +7502,7 @@ bccl_not68020:
                duplicate_carry (0);
                printf("\tSET_VFLG (GET_VFLG () | (sign2 != sign));\n");
                genastore ("val", curi->smode, "srcreg", curi->size, "data");
+               loopmodeextra = 2;
                break;
        case i_LSRW:
                genamode (curi, curi->smode, "srcreg", curi->size, "data", 1, 0, GF_RMW);
@@ -7270,6 +7519,7 @@ bccl_not68020:
                printf("\tSET_CFLG (carry);\n");
                duplicate_carry (0);
                genastore ("val", curi->smode, "srcreg", curi->size, "data");
+               loopmodeextra = 2;
                break;
        case i_LSLW:
                genamode (curi, curi->smode, "srcreg", curi->size, "data", 1, 0, GF_RMW);
@@ -7286,6 +7536,7 @@ bccl_not68020:
                printf("\tSET_CFLG (carry >> %d);\n", bit_size (curi->size) - 1);
                duplicate_carry (0);
                genastore ("val", curi->smode, "srcreg", curi->size, "data");
+               loopmodeextra = 2;
                break;
        case i_ROLW:
                genamode (curi, curi->smode, "srcreg", curi->size, "data", 1, 0, GF_RMW);
@@ -7302,6 +7553,7 @@ bccl_not68020:
                genflags (flag_logical, curi->size, "val", "", "");
                printf("\tSET_CFLG (carry >> %d);\n", bit_size (curi->size) - 1);
                genastore ("val", curi->smode, "srcreg", curi->size, "data");
+               loopmodeextra = 2;
                break;
        case i_RORW:
                genamode (curi, curi->smode, "srcreg", curi->size, "data", 1, 0, GF_RMW);
@@ -7318,6 +7570,7 @@ bccl_not68020:
                genflags (flag_logical, curi->size, "val", "", "");
                printf("\tSET_CFLG (carry);\n");
                genastore ("val", curi->smode, "srcreg", curi->size, "data");
+               loopmodeextra = 2;
                break;
        case i_ROXLW:
                genamode (curi, curi->smode, "srcreg", curi->size, "data", 1, 0, GF_RMW);
@@ -7335,6 +7588,7 @@ bccl_not68020:
                printf("\tSET_CFLG (carry >> %d);\n", bit_size (curi->size) - 1);
                duplicate_carry (0);
                genastore ("val", curi->smode, "srcreg", curi->size, "data");
+               loopmodeextra = 2;
                break;
        case i_ROXRW:
                genamode (curi, curi->smode, "srcreg", curi->size, "data", 1, 0, GF_RMW);
@@ -7352,29 +7606,40 @@ bccl_not68020:
                printf("\tSET_CFLG (carry);\n");
                duplicate_carry (0);
                genastore ("val", curi->smode, "srcreg", curi->size, "data");
+               loopmodeextra = 2;
                break;
        case i_MOVEC2:
-               genamode (curi, curi->smode, "srcreg", curi->size, "src", 1, 0, 0);
-               fill_prefetch_next ();
-               start_brace ();
+               if (cpu_level == 1) {
+                       printf("\tif(!regs.s) {\n");
+                       printf("\t\tException(8);\n");
+                       write_return_cycles_none("\t\t");
+                       printf("\t}\n");
+               }
+               genamode(curi, curi->smode, "srcreg", curi->size, "src", 1, 0, 0);
+               fill_prefetch_next();
                printf("\tint regno = (src >> 12) & 15;\n");
                printf("\tuae_u32 *regp = regs.regs + regno;\n");
                printf("\tif (!m68k_movec2(src & 0xFFF, regp)) {\n");
                write_return_cycles("\t\t", 0);
                printf("\t}\n");
-               addcycles000(2);
+               addcycles000(4);
                trace_t0_68040_only();
                break;
        case i_MOVE2C:
+               if (cpu_level == 1) {
+                       printf("\tif(!regs.s) {\n");
+                       printf("\t\tException(8);\n");
+                       write_return_cycles_none("\t\t");
+                       printf("\t}\n");
+               }
                genamode (curi, curi->smode, "srcreg", curi->size, "src", 1, 0, 0);
                fill_prefetch_next ();
-               start_brace ();
                printf("\tint regno = (src >> 12) & 15;\n");
                printf("\tuae_u32 *regp = regs.regs + regno;\n");
                printf("\tif (!m68k_move2c(src & 0xFFF, regp)) {\n");
                write_return_cycles("\t\t", 0);
                printf("\t}\n");
-               addcycles000(4);
+               addcycles000(2);
                trace_t0_68040_only();
                break;
        case i_CAS:
@@ -7477,37 +7742,35 @@ bccl_not68020:
                break;
        case i_MOVES: /* ignore DFC and SFC when using_mmu == false */
                {
-                       int old_brace_level;
                        tail_ce020_done = true;
                        genamode (curi, curi->smode, "srcreg", curi->size, "extra", 1, 0, 0);
+                       strcpy(g_srcname, "src");
+                       addcycles000(4);
                        printf("if (extra & 0x800) {\n");
                        {
+                               int srcdone = 0;
                                int old_m68k_pc_offset = m68k_pc_offset;
                                int old_m68k_pc_total = m68k_pc_total;
-                               old_brace_level = n_braces;
-                               start_brace ();
-                               // 68060 stores original value
-                               if (cpu_level == 5) {
-                                       printf("\tuae_u32 src = regs.regs[(extra >> 12) & 15];\n");
-                               }
-                               genamode (curi, curi->dmode, "dstreg", curi->size, "dst", 2, 0, 0);
+                               push_ins_cnt();
+                               // 68060 stores original value, 68010 MOVES.L also stores original value.
+                               printf("\tuae_u32 src = regs.regs[(extra >> 12) & 15];\n");
+                               genamode (curi, curi->dmode, "dstreg", curi->size, "dst", 2, 0, cpu_level == 1 ? GF_NOFETCH : 0);
                                tail_ce020_done = false;
                                returntail(false);
                                did_prefetch = 0;
                                // Earlier models do -(an)/(an)+ EA calculation first
-                               if (cpu_level <= 4) {
-                                       printf("\tuae_u32 src = regs.regs[(extra >> 12) & 15];\n");
+                               if (!(cpu_level == 5 || (curi->dmode != Aipi && curi->dmode != Apdi) || (cpu_level == 1 && curi->size == sz_long))) {
+                                       printf("\tsrc = regs.regs[(extra >> 12) & 15];\n");
                                }
                                genastore_fc ("src", curi->dmode, "dstreg", curi->size, "dst");
                                sync_m68k_pc();
-                               pop_braces(old_brace_level);
+                               pop_ins_cnt();
                                m68k_pc_offset = old_m68k_pc_offset;
                                m68k_pc_total = old_m68k_pc_total;
                        }
                        printf("} else {\n");
                        {
-                               start_brace();
-                               genamode(curi, curi->dmode, "dstreg", curi->size, "src", 1, 0, GF_FC);
+                               genamode(curi, curi->dmode, "dstreg", curi->size, "src", 1, 0, GF_FC | (cpu_level == 1 ? GF_NOFETCH : 0));
                                printf("\tif (extra & 0x8000) {\n");
                                switch (curi->size) {
                                case sz_byte: printf("\tm68k_areg(regs, (extra >> 12) & 7) = (uae_s32)(uae_s8)src;\n"); break;
@@ -7521,14 +7784,16 @@ bccl_not68020:
                                sync_m68k_pc();
                                tail_ce020_done = false;
                                returntail(false);
-                               pop_braces(old_brace_level);
                        }
                        printf("}\n");
                        trace_t0_68040_only();
+                       fill_prefetch_next();
+                       next_level_060_to_040();
                }
                break;
        case i_BKPT:            /* only needed for hardware emulators */
                sync_m68k_pc ();
+               addcycles000(4);
                printf("\top_illg (opcode);\n");
                did_prefetch = -1;
                break;
@@ -7930,6 +8195,13 @@ bccl_not68020:
                break;
        }
 end:
+       if (loopmode && loopmodeextra) {
+               printf("\tif (loop_mode) {\n");
+               addcycles000_onlyce(loopmodeextra);
+               addcycles000_nonce("\t\t", loopmodeextra);
+               printf("\t}\n");
+       }
+       loopmode_stop();
        if (!genastore_done)
                returntail (0);
        finish_braces ();
index abbb0877460066621010c7e36fa3b36ec054e821..216b346c1f6480bd5e64fd13a07c9fe0edbcf141 100644 (file)
@@ -185,7 +185,7 @@ struct regstruct
        uae_u32 chipset_latch_read;
        uae_u32 chipset_latch_write;
        uae_u16 db, write_buffer, read_buffer;
-       bool loop_mode;
+       int loop_mode;
 
        uaecptr usp, isp, msp;
        uae_u16 sr;
index 904171525a24368e919e509ecae92f1884092641..e8f0dbb19a39b994a4286c382255d0ce4bc411f8 100644 (file)
@@ -2487,7 +2487,7 @@ static void Exception_ce000 (int nr)
                        start = 0;
                else if (nr >= 32 && nr < 32 + 16) // TRAP #x
                        start = 4;
-               else if (nr == 4 || nr == 5 || nr == 6 || nr == 8 || nr == 9 || nr == 10 || nr == 11) // ILLG, DIVBYZERO, PRIV, TRACE, LINEA, LINEF
+               else if (nr == 4 || nr == 5 || nr == 6 || nr == 8 || nr == 9 || nr == 10 || nr == 11 || nr == 14) // ILLG, DIVBYZERO, PRIV, TRACE, LINEA, LINEF, RTE
                        start = 4;
        }
 
@@ -2794,17 +2794,16 @@ static void add_approximate_exception_cycles(int nr)
 {
        int cycles;
 
-       if (currprefs.cpu_model > 68000)
-               return;
-       if (nr >= 24 && nr <= 31) {
-               /* Interrupts */
-               cycles = 44 + 4; 
-       } else if (nr >= 32 && nr <= 47) {
-               /* Trap (total is 34, but cpuemux.c already adds 4) */ 
-               cycles = 34 - 4;
-       } else {
-               switch (nr)
-               {
+       if (currprefs.cpu_model == 68000) {
+               if (nr >= 24 && nr <= 31) {
+                       /* Interrupts */
+                       cycles = 44 + 4;
+               } else if (nr >= 32 && nr <= 47) {
+                       /* Trap (total is 34, but cpuemux.c already adds 4) */
+                       cycles = 34 - 4;
+               } else {
+                       switch (nr)
+                       {
                        case 2: cycles = 50; break;             /* Bus error */
                        case 3: cycles = 50; break;             /* Address error */
                        case 4: cycles = 34; break;             /* Illegal instruction */
@@ -2816,9 +2815,38 @@ static void add_approximate_exception_cycles(int nr)
                        case 10: cycles = 34; break;    /* Line-A */
                        case 11: cycles = 34; break;    /* Line-F */
                        default:
-                       cycles = 4;
-                       break;
+                               cycles = 4;
+                               break;
+                       }
                }
+       } else if (currprefs.cpu_model == 68010) {
+               if (nr >= 24 && nr <= 31) {
+                       /* Interrupts */
+                       cycles = 48 + 4;
+               } else if (nr >= 32 && nr <= 47) {
+                       /* Trap */
+                       cycles = 38 - 4;
+               } else {
+                       switch (nr)
+                       {
+                       case 2: cycles = 126; break;    /* Bus error */
+                       case 3: cycles = 126; break;    /* Address error */
+                       case 4: cycles = 38; break;             /* Illegal instruction */
+                       case 5: cycles = 38; break;             /* Division by zero */
+                       case 6: cycles = 38; break;             /* CHK */
+                       case 7: cycles = 40; break;             /* TRAPV */
+                       case 8: cycles = 38; break;             /* Privilege violation */
+                       case 9: cycles = 38; break;             /* Trace */
+                       case 10: cycles = 38; break;    /* Line-A */
+                       case 11: cycles = 38; break;    /* Line-F */
+                       case 14: cycles = 38; break;    /* RTE frame error */
+                       default:
+                               cycles = 4;
+                               break;
+                       }
+               }
+       } else {
+               return;
        }
        cycles = adjust_cycles(cycles * CYCLE_UNIT / 2);
        x_do_cycles(cycles);
@@ -3006,6 +3034,7 @@ static void Exception_normal (int nr)
                                x_put_word (m68k_areg (regs, 7), 0x1000 + vector_nr * 4);
                        }
                } else {
+                       add_approximate_exception_cycles(nr);
                        Exception_build_stack_frame_common(oldpc, currpc, regs.mmu_ssw, nr);
                        used_exception_build_stack_frame = true;
                }
index d0b35e5b77d14641b6709e8cbf50cd1a9636370f..42e7da936bb19215897203147bce7f49bca130b1 100644 (file)
@@ -646,12 +646,12 @@ int getMulu68kCycles(uae_u16 src)
        int cycles = 0;
        if (currprefs.cpu_model == 68000) {
                cycles = 38 - 4;
+               for (int bits = 0; bits < 16 && src; bits++, src >>= 1) {
+                       if (src & 1)
+                               cycles += 2;
+               }
        } else {
-               cycles = 8 - 4;
-       }
-       for (int bits = 0; bits < 16 && src; bits++, src >>= 1) {
-               if (src & 1)
-                       cycles += 2;
+               cycles = 40 - 4;
        }
        return cycles;
 }
@@ -661,14 +661,17 @@ int getMuls68kCycles(uae_u16 src)
        int cycles;
        if (currprefs.cpu_model == 68000) {
                cycles = 38 - 4;
+               uae_u32 usrc = ((uae_u32)src) << 1;
+               for (int bits = 0; bits < 16 && usrc; bits++, usrc >>= 1) {
+                       if ((usrc & 3) == 1 || (usrc & 3) == 2) {
+                               cycles += 2;
+                       }
+               }
        } else {
-               cycles = 10 - 4;
-       }
-       uae_u32 usrc = ((uae_u32)src) << 1;
-       for (int bits = 0; bits < 16 && usrc; bits++, usrc >>= 1) {
-               if ((usrc & 3) == 1 || (usrc & 3) == 2) {
+               cycles = 40 - 4;
+               // 2 extra cycles added if source is negative
+               if (src & 0x8000)
                        cycles += 2;
-               }
        }
        return cycles;
 }
@@ -741,15 +744,18 @@ int getDivu68kCycles (uae_u32 dividend, uae_u16 divisor)
        if (divisor == 0)
                return 0;
 
+       if (currprefs.cpu_model == 68010) {
+               // Overflow
+               if ((dividend >> 16) >= divisor)
+                       return 4;
+               return 104;
+       }
+
        // Overflow
        if ((dividend >> 16) >= divisor)
                return (mcycles = 5) * 2 - 4;
 
-       if (currprefs.cpu_model == 68000) {
-               mcycles = 38;
-       } else {
-               mcycles = 22;
-       }
+       mcycles = 38;
 
        hdivisor = divisor << 16;
 
@@ -783,6 +789,17 @@ int getDivs68kCycles (uae_s32 dividend, uae_s16 divisor)
        if (divisor == 0)
                return 0;
 
+       if (currprefs.cpu_model == 68010) {
+               // Check for absolute overflow
+               if (((uae_u32)abs(dividend) >> 16) >= (uae_u16)abs(divisor))
+                       return 12;
+               mcycles = 116;
+               // add 2 extra cycles if negative dividend
+               if (dividend < 0)
+                       mcycles += 2;
+               return mcycles;
+       }
+
        mcycles = 6;
 
        if (dividend < 0)
@@ -795,11 +812,7 @@ int getDivs68kCycles (uae_s32 dividend, uae_s16 divisor)
        // Absolute quotient
        aquot = (uae_u32) abs (dividend) / (uae_u16)abs (divisor);
 
-       if (currprefs.cpu_model == 68000) {
-               mcycles += 55;
-       } else {
-               mcycles += 37;
-       }
+       mcycles += 55;
 
        if (divisor >= 0) {
                if (dividend >= 0)
index 0498c34e182caaac559a869e5d2d14a1867ded2c..9891f5c27d9ba1dae470c5d13499bb212addb4a5 100644 (file)
@@ -909,8 +909,8 @@ bool opcode_loop_mode(uae_u16 opcode)
                        (!c->duse || (isreg(c->smode) && !isreg(c->dmode)) || (!isreg(c->smode) && isreg(c->dmode)) || (!isreg(c->smode) && !isreg(c->dmode)))) {
                        loopmode = true;
                }
-               if (c->mnemo == i_MOVE) {
-                       // move x,dn: not supported
+               if (c->mnemo == i_MOVE || c->mnemo == i_MOVEA) {
+                       // move x,reg: not supported
                        if (isreg(c->dmode))
                                loopmode = false;
                        // move reg,-(an): not supported
index 57632d7044b3054fdfbda9e9a9263e880c9d97bb..0ec4ffb62effc49a8ebd49f44bc7acdb61049ba5 100644 (file)
--- a/table68k
+++ b/table68k
 0000 1010 11ss sSSS:200:?????:?????:13: CAS.B   #1,s[!Dreg,Areg,Immd,PC8r,PC16]
 0000 1100 11ss sSSS:200:?????:?????:13: CAS.W   #1,s[!Dreg,Areg,Immd,PC8r,PC16]
 0000 1100 1111 1100:250:?????:?????:10: CAS2.W  #2
-0000 1110 zzss sSSS:202:?????:?????:13: MOVES.z #1,s[!Dreg,Areg,Immd,PC8r,PC16]
+0000 1110 zzss sSSS:102:?????:?????:13: MOVES.z #1,s[!Dreg,Areg,Immd,PC8r,PC16]
 0000 1110 11ss sSSS:200:?????:?????:13: CAS.L   #1,s[!Dreg,Areg,Immd,PC8r,PC16]
 0000 1110 1111 1100:250:?????:?????:10: CAS2.L  #2
 
 0100 1000 00dd dDDD:000:X?Z?C:X-Z--:30: NBCD.B  d[!Areg]
 - 0 0 6
 
-0100 1000 0100 1kkk:200:?????:?????:10: BKPT    #k
+0100 1000 0100 1kkk:100:?????:?????:10: BKPT    #k
 
 0100 1000 01ss sSSS:000:-NZ00:-----:30: SWAP.W  s[Dreg]         
 - 4 0 4