]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
JIT loop mode improved CCR error checking and reporting.
authorToni Wilen <twilen@winuae.net>
Tue, 21 Jul 2020 18:53:56 +0000 (21:53 +0300)
committerToni Wilen <twilen@winuae.net>
Tue, 21 Jul 2020 18:53:56 +0000 (21:53 +0300)
cputest.cpp
cputest/cputestgen.ini
cputest/main.c

index 8db40d67ed524aefa7760741825bbf254f052abb..30db6f02b31f494a0c4fd109cae2bcf7707dd71f 100644 (file)
@@ -68,7 +68,6 @@ static int feature_flag_mode = 0;
 static int feature_usp = 0;
 static int feature_exception_vectors = 0;
 static int feature_interrupts = 0;
-static int feature_randomize = 0;
 static int feature_instruction_size = 0;
 static TCHAR *feature_instruction_size_text = NULL;
 static uae_u32 feature_addressing_modes[2];
@@ -166,7 +165,7 @@ static uae_u16 extra_or, extra_and;
 static struct regstruct cur_regs;
 static uae_u16 read_buffer_prev;
 static int interrupt_count;
-static int interrupt_cycle_cnt;
+static int interrupt_cycle_cnt, interrupt_delay_cnt;
 static int interrupt_level;
 static uaecptr test_instruction_end_pc;
 
@@ -450,7 +449,7 @@ uae_u32 get_ilong_test(uaecptr addr)
                uae_u16 v1 = get_iword_test(addr + 2);
                v = (v0 << 16) | (v1 << 0);
        } else {
-               uae_u8 *p = get_addr(addr, 4, 1);
+               uae_u8 *p = get_addr(addr, 4, 4);
                v = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | (p[3]);
                add_memory_cycles(2);
        }
@@ -1786,6 +1785,9 @@ static bool regchange(int reg, uae_u32 *regs)
                v ^= 0x8000;
                break;
        case 12:
+               if (feature_loop_mode && !feature_loop_mode_68010) {
+                       return false;
+               }
                v ^= 0x80000000;
                v = (v & 0xffffff00) | ((v + 0x14) & 0xff);
                break;
@@ -2289,7 +2291,8 @@ static void save_data(uae_u8 *dst, const TCHAR *dir, int size)
                pl(data, opcode_memory_start);
                fwrite(data, 1, 4, f);
                pl(data, (cpu_lvl << 16) | sr_undefined_mask | (addressing_mask == 0xffffffff ? 0x80000000 : 0) |
-                       (feature_min_interrupt_mask << 20) | (safe_memory_mode << 23) | (feature_interrupts << 26) | (feature_randomize << 28));
+                       (feature_min_interrupt_mask << 20) | (safe_memory_mode << 23) | (feature_interrupts << 26) |
+                       ((feature_loop_mode ? 1 : 0) << 28) | ((feature_loop_mode_68010 ? 1 : 0) << 29));
                fwrite(data, 1, 4, f);
                pl(data, currprefs.fpu_model);
                fwrite(data, 1, 4, f);
@@ -2311,10 +2314,11 @@ static void save_data(uae_u8 *dst, const TCHAR *dir, int size)
                fwrite(data, 1, 4, f);
                pl(data, feature_exception_vectors);
                fwrite(data, 1, 4, f);
-               data[0] = data[1] = data[2] = data[3] = 0;
-               fwrite(data, 1, 4, f);
-               fwrite(data, 1, 4, f);
-               fwrite(data, 1, 4, f);
+               data[0] = data[1] = data[2] = 0;
+               pl(data, feature_loop_mode);
+               fwrite(&data[0], 1, 4, f);
+               fwrite(&data[1], 1, 4, f);
+               fwrite(&data[2], 1, 4, f);
                fwrite(inst_name, 1, sizeof(inst_name) - 1, f);
                data[0] = CT_END_FINISH;
                data[1] = 0;
@@ -2515,7 +2519,7 @@ static int create_ea_random(uae_u16 *opcodep, uaecptr pc, int mode, int reg, str
                return -1;
 
        if (feature_loop_mode) {
-               // loop mode JMP or JSR: skip if A3 or A7 is used in EA calculation
+               // loop mode JMP or JSR: skip if A3, A4 or A7 is used in EA calculation
                if (dp->mnemo == i_JMP || dp->mnemo == i_JSR) {
                        if (mode == Areg || mode == Aind || mode == Aipi || mode == Apdi || mode == Ad16 || mode == Ad8r) {
                                if (reg == 3 || reg == 7) {
@@ -2645,7 +2649,7 @@ static int create_ea_random(uae_u16 *opcodep, uaecptr pc, int mode, int reg, str
                                        if (currprefs.cpu_model >= 68020)
                                                v &= ~0x100;
                                        ereg = v >> 12;
-                                       if (loopmodelimit && (ereg == 0 || ereg == 8 + 3 || ereg == 8 + 7 || ereg == feature_loop_mode_register)) {
+                                       if (loopmodelimit && (ereg == 0 || ereg == 8 + 3 || ereg == 8 + 4 || ereg == 8 + 7 || ereg == feature_loop_mode_register)) {
                                                continue;
                                        }
                                        break;
@@ -2700,7 +2704,7 @@ static int create_ea_random(uae_u16 *opcodep, uaecptr pc, int mode, int reg, str
                                break;
                        }
                        int ereg = v >> 12;
-                       if (loopmodelimit && (ereg == 0 || ereg == 8 + 3 || ereg == 8 + 7 || ereg == feature_loop_mode_register)) {
+                       if (loopmodelimit && (ereg == 0 || ereg == 8 + 3 || ereg == 8 + 4 || ereg == 8 + 7 || ereg == feature_loop_mode_register)) {
                                return -1;
                        }
                        *regused = ereg;
@@ -4346,7 +4350,8 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
        int count = 0;
 
        if (feature_loop_mode && !feature_loop_mode_68010) {
-               registers[8 + 3] = 0;
+               registers[8 + 3] = 0; // A3 = 0
+               registers[8 + 4] = 0; // A4 = 0
        }
 
        registers[8 + 6] = opcode_memory_start - 0x100;
@@ -4636,6 +4641,7 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                                        uaecptr startpc = opcode_memory_start;
                                        uaecptr pc = startpc + 2;
 
+                                       // target opcode mode
                                        if (target_opcode_address != 0xffffffff) {
                                                pc -= 2;
                                                int cnt = 0;
@@ -4651,6 +4657,17 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                                                startpc = opcode_memory_address;
                                        }
 
+                                       // interrupt timing test mode
+                                       if (feature_interrupts == 2) {
+                                               pc -= 2;
+                                               put_word_test(pc + 0, 0x7000 | interrupt_delay_cnt); // moveq #x,d0 (4 cycles)
+                                               put_word_test(pc + 2, 0xe0b9); // ror.l d0,d1 (4 + 4 + d0 * 2 cycles)
+                                               put_word_test(pc + 4, NOP_OPCODE);
+                                               pc += 6;
+                                               opcode_memory_address = startpc = pc;
+                                               pc += 2;
+                                       }
+
                                        // Start address to start address + 3 must be accessible or
                                        // jump prefetch would cause early bus error which we don't want
                                        if (is_nowrite_address(startpc, 4)) {
@@ -4801,7 +4818,7 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                                        test_instruction_end_pc = pc;
 
                                        // loop mode
-                                       if (feature_loop_mode) {
+                                       if (feature_loop_mode) {
                                                // dbf dn, opcode_memory_start
                                                if (!feature_loop_mode_68010) {
                                                        uae_u16 ccrmaskt = get_ccr_ignore(dp, extraword, true);
@@ -4810,25 +4827,52 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                                                                ccrmask |= 0x02;
                                                        if (ccrmaskt & 0x02)
                                                                ccrmask |= 0x04;
+                                                       // add.l a3,a3
+                                                       put_word(pc, 0xd7cb);
+                                                       pc += 2;
+                                                       // add.l a4,a4
+                                                       put_word(pc, 0xd9cc);
+                                                       pc += 2;
                                                        for (int i = 0; i < 4; i++) {
                                                                // bcc, bne, bvc, bpl
-                                                               put_word(pc, 0x6400 + (i * 0x0200) + 4);
+                                                               uaecptr bcc = pc;
                                                                pc += 2;
+                                                               uae_u32 add = 0;
                                                                if (!(ccrmask & (1 << i))) {
-                                                                       // adda.w #x,a3
-                                                                       put_long(pc, 0xd6fc0000 | (1 << (i * 3)));
+                                                                       add = 1 << (i * 8);
+                                                               }
+                                                               if (add >= 1 && add <= 8) {
+                                                                       if (add == 8) {
+                                                                               add = 0;
+                                                                       }
+                                                                       // addq.w #x,a3
+                                                                       put_word(pc, 0x5048 | 3 | (add << 9));
+                                                                       pc += 2;
+                                                               } else if (add < 65536) {
+                                                                       // add.w #x,a3
+                                                                       put_long(pc, (0xd6fc << 16) | add);
+                                                                       pc += 4;
                                                                } else {
-                                                                       // adda.w #0,a3
-                                                                       put_long(pc, 0xd6fc0000);
+                                                                       // add.l #x,a3
+                                                                       put_word(pc, 0xd7fc);
+                                                                       pc += 2;
+                                                                       put_long(pc, add);
+                                                                       pc += 4;
                                                                }
-                                                               pc += 4;
+                                                               put_word(bcc, 0x6400 + (i * 0x0200) + (pc - bcc) - 2);
                                                        }
-                                                       // adda.l a3,a3
-                                                       put_word(pc, 0xd7cb);
+                                                       // sub.l d0,a4
+                                                       put_word(pc, 0x99c0);
+                                                       pc += 2;
+                                                       // negx.w d0
+                                                       put_word(pc, 0x4080);
+                                                       pc += 2;
+                                                       // neg.w d0
+                                                       put_word(pc, 0x4480);
+                                                       pc += 2;
+                                                       // add.l d0,a4
+                                                       put_word(pc, 0xd9c0);
                                                        pc += 2;
-                                                       // negx.b d0 ; add.w d0,d0
-                                                       put_long(pc, 0x4000d040);
-                                                       pc += 4;
                                                }
                                                // dbf dn,label
                                                put_long_test(pc, ((0x51c8 | feature_loop_mode_register) << 16) | ((opcode_memory_address - pc - 2) & 0xffff));
@@ -5715,6 +5759,15 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                        nextround = true;
                }
 
+               if (feature_interrupts == 2) {
+                       interrupt_delay_cnt++;
+                       if (interrupt_delay_cnt >= 64) {
+                               nextround = false;
+                       } else {
+                               nextround = true;
+                       }
+               }
+
                if (target_opcode_address != 0xffffffff || target_usp_address != 0xffffffff) {
                        nextround = false;
                        target_ea_opcode_cnt++;
@@ -6343,8 +6396,6 @@ static int test(struct ini_data *ini, const TCHAR *sections, const TCHAR *testna
        ini_getvalx(ini, sections, _T("feature_exception_vectors"), &feature_exception_vectors);
        feature_interrupts = 0;
        ini_getvalx(ini, sections, _T("feature_interrupts"), &feature_interrupts);
-       feature_randomize = 0;
-       ini_getvalx(ini, sections, _T("feature_randomize"), &feature_randomize);
 
        feature_full_extension_format = 0;
        if (currprefs.cpu_model >= 68020) {
@@ -6510,12 +6561,17 @@ static int test(struct ini_data *ini, const TCHAR *sections, const TCHAR *testna
 
        v = 0;
        if (ini_getvalx(ini, sections, _T("opcode_memory_start"), &v)) {
-               opcode_memory_start = v;
-               opcode_memory = test_memory + (opcode_memory_start - test_memory_start);
-               if (opcode_memory_start < test_memory_start || opcode_memory_start + OPCODE_AREA >= test_memory_end) {
-                       wprintf(_T("Opcode memory out of bounds, using default location.\n"));
+               if (v == -1) {
                        opcode_memory = test_memory + test_memory_size / 2;
                        opcode_memory_start = test_memory_start + test_memory_size / 2;
+               } else {
+                       opcode_memory_start = v;
+                       opcode_memory = test_memory + (opcode_memory_start - test_memory_start);
+                       if (opcode_memory_start < test_memory_start || opcode_memory_start + OPCODE_AREA >= test_memory_end) {
+                               wprintf(_T("Opcode memory out of bounds, using default location.\n"));
+                               opcode_memory = test_memory + test_memory_size / 2;
+                               opcode_memory_start = test_memory_start + test_memory_size / 2;
+                       }
                }
        } else {
                opcode_memory = test_memory + test_memory_size / 2;
index dbf9b60804d07a2e2b3d148537e34931ba61e62e..d26f6e96f67d22c710902ccaa7abc968f5c0b27d 100644 (file)
@@ -487,8 +487,9 @@ mode=fillegal
 enabled=0
 cpu=68020-68060
 cpu_address_space=68020
-feature_loop_mode=10
+feature_loop_mode=8
 feature_loop_mode_reload=1
 feature_loop_mode_register=7
+opcode_memory_start=-1
 mode=all
 verbose=0
index ab158462aa9a4bb68b8ba5a4a8801c969c936dff..6c764e951b45fa7cd3e65c26c8c382963e1008b0 100644 (file)
@@ -133,6 +133,7 @@ static short quit;
 static uae_u8 ccr_mask;
 static uae_u32 addressing_mask = 0x00ffffff;
 static uae_u32 interrupt_mask;
+static short loop_mode, loop_mode_68010, loop_mode_cnt;
 static short instructionsize;
 static short disasm;
 static short basicexcept;
@@ -146,7 +147,6 @@ static int exitcnt;
 static short cycles, cycles_range, cycles_adjust;
 static short gotcycles;
 static short interrupttest;
-static short randomizetest;
 static uae_u32 cyclecounter_addr;
 static int errorcnt;
 static short uaemode;
@@ -2313,6 +2313,49 @@ static short fpucheckextra(struct fpureg *f1, struct fpureg *f2)
        return 1;
 }
 
+static void loop_mode_error(uae_u32 ov, uae_u32 nv)
+{
+       strcpy(outbp, " expected ");
+       outbp += strlen(outbp);
+       for (short i = loop_mode_cnt - 1; i >= 0; i--) {
+               if ((ov >> i) & 1) {
+                       *outbp++ = '1';
+               } else {
+                       *outbp++ = '0';
+               }
+       }
+       strcpy(outbp, " got ");
+       outbp += strlen(outbp);
+       for (short i = loop_mode_cnt - 1; i >= 0; i--) {
+               if ((nv >> i) & 1) {
+                       *outbp++ = '1';
+               } else {
+                       *outbp++ = '0';
+               }
+       }
+       *outbp++ = '\n';
+}
+
+static const char cvzn[] = { "CVZN" };
+static void loop_mode_error_CVZN(uae_u32 ov, uae_u32 nv)
+{
+       for (short i = 0; i < 4; i++) {
+               if ((ov & 0xff) != (nv & 0xff)) {
+                       sprintf(outbp, "Loop mode %c:", cvzn[i]);
+                       outbp += strlen(outbp);
+                       loop_mode_error(ov, nv);
+               }
+               ov >>= 8;
+               nv >>= 8;
+       }
+}
+static void loop_mode_error_X(uae_u32 ov, uae_u32 nv)
+{
+       sprintf(outbp, "Loop mode X:");
+       outbp += strlen(outbp);
+       loop_mode_error(ov, nv);
+}
+
 // sregs: registers before execution of test code
 // tregs: registers used during execution of test code, also modified by test code.
 // lregs: registers after modifications from data files. Test ok if tregs == lregs.
@@ -2459,6 +2502,13 @@ static uae_u8 *validate_test(uae_u8 *p, short ignore_errors, short ignore_sr, st
                                                        sprintf(outbp, "%c%d: expected %08x but got %08x\n", mode < CT_AREG ? 'D' : 'A', mode & 7, val, tregs->regs[mode]);
                                                }
                                                outbp += strlen(outbp);
+                                               if (loop_mode && !loop_mode_68010) {
+                                                       if (mode == CT_AREG + 3) {
+                                                               loop_mode_error_CVZN(val, tregs->regs[mode]);
+                                                       } else if (mode == CT_AREG + 4) {
+                                                               loop_mode_error_X(val, tregs->regs[mode]);
+                                                       }
+                                               }
                                        }
                                        errflag |= 1 << 0;
                                }
@@ -2656,6 +2706,14 @@ static uae_u8 *validate_test(uae_u8 *p, short ignore_errors, short ignore_sr, st
                                        if (dooutput) {
                                                uae_u32 val = lregs->regs[mode];
                                                sprintf(outbp, "%c%d: expected %08x but got %08x\n", mode < CT_AREG ? 'D' : 'A', mode & 7, val, tregs->regs[mode]);
+                                               outbp += strlen(outbp);
+                                               if (loop_mode && !loop_mode_68010) {
+                                                       if (mode == CT_AREG + 3) {
+                                                               loop_mode_error_CVZN(val, tregs->regs[mode]);
+                                                       } else if (mode == CT_AREG + 4) {
+                                                               loop_mode_error_X(val, tregs->regs[mode]);
+                                                       }
+                                               }
                                        }
                                        errflag |= 1 << 0;
                                }
@@ -3296,9 +3354,10 @@ static int test_mnemo(const char *opcode)
        interrupt_mask = (lvl_mask >> 20) & 7;
        addressing_mask = (lvl_mask & 0x80000000) ? 0xffffffff : 0x00ffffff;
        interrupttest = (lvl_mask >> 26) & 1;
-       randomizetest = (lvl_mask >> 28) & 1;
        sr_undefined_mask = lvl_mask & 0xffff;
        safe_memory_mode = (lvl_mask >> 23) & 7;
+       loop_mode = (lvl_mask >> 28) & 1;
+       loop_mode_68010 = (lvl_mask >> 29) & 1;
        fpu_model = read_u32(headerfile, &headoffset);
        test_low_memory_start = read_u32(headerfile, &headoffset);
        test_low_memory_end = read_u32(headerfile, &headoffset);
@@ -3309,7 +3368,10 @@ static int test_mnemo(const char *opcode)
        user_stack_memory = read_u32(headerfile, &headoffset);
        super_stack_memory = read_u32(headerfile, &headoffset);
        exception_vectors = read_u32(headerfile, &headoffset);
-       read_u32(headerfile, &headoffset);
+       v = read_u32(headerfile, &headoffset);
+       if (loop_mode) {
+               loop_mode_cnt = v & 0xff;
+       }
        read_u32(headerfile, &headoffset);
        read_u32(headerfile, &headoffset);
        memcpy(inst_name, headerfile + headoffset, sizeof(inst_name) - 1);