static int feature_usp = 0;
static int feature_exception_vectors = 0;
static int feature_interrupts = 0;
+static int feature_randomize = 0;
static TCHAR *feature_instruction_size = NULL;
static uae_u32 feature_addressing_modes[2];
static int feature_gzip = 0;
static int test_exception_extra;
static int exception_stack_frame_size;
static uae_u8 exception_extra_frame[100];
-static int exception_extra_frame_size;
+static int exception_extra_frame_size, exception_extra_frame_type;
static uaecptr test_exception_addr;
static int test_exception_3_w;
static int test_exception_3_fc;
if (!feature_exception_vectors)
return;
+ int interrupt = test_exception >= 24 && test_exception < 24 + 8;
int original_exception = test_exception;
// odd exception vector
test_exception = 3;
// store original exception stack (which may not be complete)
uae_u8 *sf = test_memory + test_memory_size + EXTRA_RESERVED_SPACE - exception_stack_frame_size;
exception_extra_frame_size = exception_stack_frame_size;
+ exception_extra_frame_type = original_exception;
memcpy(exception_extra_frame, sf, exception_extra_frame_size);
MakeSR();
regs.write_buffer = original_exception * 4;
}
+ if (interrupt) {
+ regs.intmask = original_exception - 24;
+ regs.ir = original_exception;
+ flags |= 0x10000 | 0x20000;
+ }
+
exception3_read(regs.ir | flags, test_exception_addr, 1, 2);
}
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_min_interrupt_mask << 20) | (safe_memory_mode << 23) | (feature_interrupts << 26) | (feature_randomize << 28));
fwrite(data, 1, 4, f);
pl(data, currprefs.fpu_model);
fwrite(data, 1, 4, f);
regs.read_buffer = regs.irc;
regs.write_buffer = 0xf00d;
exception_extra_frame_size = 0;
+ exception_extra_frame_type = 0;
cpu_cycles = 0;
regs.loop_mode = 0;
{
uae_u8 *op = p;
p++;
- *p++ = test_exception_extra;
+ *p++ = test_exception_extra | (exception_extra_frame_type ? 0x40 : 0x00);
+ // bus/address error aborted group 2 exception
+ if (exception_extra_frame_type) {
+ *p++ = exception_extra_frame_type;
+ }
// Separate, non-stacked Trace
if (test_exception_extra & 0x80) {
*p++ = trace_store_sr >> 8;
if (feature_exception3_instruction == 2) {
skipped = 1;
}
- if (feature_usp == 2) {
+ if (feature_exception_vectors) {
skipped = 1;
}
- if (feature_exception_vectors) {
+ }
+
+ if (feature_usp == 2) {
+ // need exception 3
+ if (test_exception != 3) {
+ skipped = 1;
+ }
+ // need also extra exception
+ if (!exception_extra_frame_type) {
skipped = 1;
}
}
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) {
if (verbose == 1)
verbose = 0;
- for (int j = 1; lookuptab[j].name; j++) {
+ for (int j = 1; lookuptab[j].name[0]; j++) {
test_mnemo_text(path, lookuptab[j].name);
}
// Illegal instructions last. All currently selected CPU model's unsupported opcodes
-#define DATA_VERSION 15
+#define DATA_VERSION 16
#define CT_FPREG 0
#define CT_DREG 0
; basic instruction test
[test=ALL]
enabled=0
-mode=tas
+mode=all
feature_sr_mask=0xa000
-; interrupt exception test
+; interrupt exception
[test=IRQ]
enabled=0
mode=nop,ext,swap
mode=all
; user stack address error
-[test=ODD_STACK]
+[test=ODD_STK]
enabled=0
feature_usp=2
-mode=all
+mode=branchs
+
+; exception vector address error
+[test=ODD_EXC]
+enabled=0
+feature_exception_vectors=0x000123
+mode=chk,trap,trapv,divu,divs,orsr
+
+; interrupt exception with odd interrupt vectors
+[test=ODD_IRQ]
+enabled=1
+mode=nop,ext,swap
+feature_interrupts=1
+feature_exception_vectors=0x000123
; prefetch bus error (requires extra hardware)
[test=BE_PR]
static short cycles, cycles_range, cycles_adjust;
static short gotcycles;
static short interrupttest;
+static short randomizetest;
static uae_u32 cyclecounter_addr;
static short uae;
#ifdef AMIGA
}
-static void hexdump(uae_u8 *p, int len)
+static void hexdump(uae_u8 *p, int len, short lf)
{
for (int i = 0; i < len; i++) {
if (i > 0)
sprintf(outbp, "%02x", p[i]);
outbp += strlen(outbp);
}
- *outbp++ = '\n';
+ if (lf)
+ *outbp++ = '\n';
}
static uae_u8 last_exception[256], last_exception_extra;
}
}
-static uae_u8 *validate_exception(struct registers *regs, uae_u8 *p, short excnum, short *gotexcnum, short *experr, short *extratrace)
+static uae_u8 *validate_exception(struct registers *regs, uae_u8 *p, short excnum, short *gotexcnum, short *experr, short *extratrace, short *group2with1)
{
int exclen = 0;
uae_u8 *exc;
if (excdatalen != 0xff) {
// check possible extra trace
last_exception_extra = *p++;
- if ((last_exception_extra & 0x7f) == 9) {
- exceptioncount[0][last_exception_extra & 0x7f]++;
+ if (last_exception_extra & 0x40) {
+ *group2with1 = *p++;
+ last_exception_extra &= ~0x40;
+ }
+ if ((last_exception_extra & 0x3f) == 9) {
+ exceptioncount[0][last_exception_extra & 0x3f]++;
uae_u32 ret = (regs->tracedata[1] << 16) | regs->tracedata[2];
uae_u16 sr = regs->tracedata[0];
if (regs->tracecnt == 0) {
outbp += strlen(outbp);
strcpy(outbp, "Expected: ");
outbp += strlen(outbp);
- hexdump(exc, exclen);
+ hexdump(exc, exclen, 1);
strcpy(outbp, "Got : ");
outbp += strlen(outbp);
- hexdump(sp, exclen);
+ hexdump(sp, exclen, 1);
*experr = 1;
}
exception_stored = exclen;
{
case 2:
case 3:
- return 56;
+ return 60;
case 4:
case 5:
case 6:
}
#endif
-static int check_cycles(int exc, int extratrace)
+static int check_cycles(int exc, short extratrace, short extrag2w1)
{
int gotcycles = 0;
if (extratrace) {
expectedcycles += getexceptioncycles(9);
}
+ // address error during group 2 exception stacking (=odd exception vector)
+ if (extrag2w1) {
+ // 4 idle, write pc low, write sr, write pc high, read vector high, read vector low
+ expectedcycles += 6 * 4;
+ if (cpu_lvl == 1) {
+ // 68010: frame type
+ expectedcycles += 4;
+ }
+ if (extrag2w1 >= 24 && extrag2w1 < 24 + 8) {
+ // interrupt
+ expectedcycles += 2 + 4 + 4;
+ }
+ }
if (0 || abs(gotcycles - expectedcycles) > cycles_range) {
addinfo();
int errflag = 0;
int errflag_orig = 0;
short extratrace = 0;
+ short extrag2w1 = 0;
short exceptionnum = 0;
uae_u8 *outbp_old = outbp;
exception_stored = 0;
}
if (ignore_errors) {
if (exc) {
- p = validate_exception(&test_regs, p, exc, &cpuexc, &experr, &extratrace);
+ p = validate_exception(&test_regs, p, exc, &cpuexc, &experr, &extratrace, &extrag2w1);
}
errflag_orig |= errflag;
errflag = 0;
break;
}
if (exc) {
- p = validate_exception(&test_regs, p, exc, &cpuexc, &experr, &extratrace);
+ p = validate_exception(&test_regs, p, exc, &cpuexc, &experr, &extratrace, &extrag2w1);
if (experr) {
errflag |= 1 << 16;
errflag_orig |= errflag;
outbp += strlen(outbp);
}
} else {
- if (!check_cycles(exc, extratrace)) {
+ if (!check_cycles(exc, extratrace, extrag2w1)) {
errflag |= 1 << 8;
}
}
sprintf(outbp, "OK: exception %d ", exc);
outbp += strlen(outbp);
if (exception_stored) {
- hexdump(last_exception, exception_stored);
- } else {
- *outbp++ = '\n';
+ hexdump(last_exception, exception_stored, 0);
}
+ if (extrag2w1) {
+ sprintf(outbp, " (+EXC %d)", extrag2w1);
+ outbp += strlen(outbp);
+ }
+ *outbp++ = '\n';
}
if ((exc == 3 || exc == 2) && cpu_lvl == 0) {
sprintf(outbp, "RW=%d IN=%d FC=%d\n",
}
#endif
+static uae_u32 xorshiftstate;
+static uae_u32 xorshift32(void)
+{
+ uae_u32 x = xorshiftstate;
+ x ^= x << 13;
+ x ^= x >> 17;
+ x ^= x << 5;
+ xorshiftstate = x;
+ return xorshiftstate;
+}
+
static void process_test(uae_u8 *p)
{
outbp = outbuffer2;
#endif
}
+ if (randomizetest) {
+ ;
+ }
+
+
if (*p == CT_END) {
p++;
break;
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) & 3;
fpu_model = read_u32(headerfile, &headoffset);
gen_set_fault_pc (false, true);
sync_m68k_pc();
out("Exception_cpu(src + 32);\n");
+ write_return_cycles_noadd(0);
did_prefetch = 1;
clear_m68k_offset();
break;
out("uae_u16 format = %s(a + 2 + 4);\n", srcw);
count_read++;
check_bus_error("", 6, 0, 1, NULL, 1);
+
+ out("uae_u32 pc = %s(a + 2) << 16;\n", srcw);
+ count_read++;
+ check_bus_error("", 2, 0, 1, NULL, 1);
+
out("int frame = format >> 12;\n");
out("int offset = 8;\n");
out("if (frame == 0x0) {\n");
write_return_cycles(0);
out("}\n");
- out("uae_u32 pc = %s(a + 2) << 16;\n", srcw);
- count_read++;
- check_bus_error("", 2, 0, 1, NULL, 1);
out("pc |= %s(a + 2 + 2); \n", srcw);
count_read++;
check_bus_error("", 4, 0, 1, NULL, 1);
- 2 idle cycles
- prefetch
+68010:
+
+...
+- write SR
+- write PC high word
+- write frame format
+- read exception address high word
+...
+
*/
static void exception3f(uae_u32 opcode, uaecptr addr, bool writeaccess, bool instructionaccess, bool notinstruction, uaecptr pc, int size, bool plus2, int fc);
if (nr == 7) // TRAPV
start = 0;
else if (nr == 2 || nr == 3)
- start = 8;
+ start = 4 + 8;
}
if (start)
cpu_halt(CPU_HALT_DOUBLE_FAULT);
return;
}
+ if (interrupt)
+ regs.intmask = nr - 24;
newpc = x_get_word (regs.vbr + 4 * vector_nr) << 16; // read high address
newpc |= x_get_word (regs.vbr + 4 * vector_nr + 2); // read low address
exception_in_exception = 0;
regs.t1 = 0;
MakeSR();
m68k_setpc(regs.vbr + 4 * vector_nr);
- exception3_read(regs.ir | 0x40000, newpc, 1, 2);
+ if (interrupt) {
+ regs.ir = nr;
+ exception3_read(regs.ir | 0x20000 | 0x10000, newpc, 1, 2);
+ } else {
+ exception3_read(regs.ir | 0x40000, newpc, 1, 2);
+ }
} else if (currprefs.cpu_model == 68010) {
// offset, not vbr + offset
regs.t1 = 0;
return;
}
m68k_setpc (newpc);
- if (interrupt)
- regs.intmask = nr - 24;
branch_stack_push(currpc, currpc);
regs.ir = x_get_word (m68k_getpc ()); // prefetch 1
#if HARDWARE_BUS_ERROR_EMULATION
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;
}
} else {
- add_approximate_exception_cycles(nr);
nextpc = m68k_getpc ();
if (nr == 2 || nr == 3) {
// 68000 bus/address error
cpu_halt(CPU_HALT_DOUBLE_FAULT);
return;
}
+ if (interrupt)
+ regs.intmask = nr - 24;
newpc = x_get_long (regs.vbr + 4 * vector_nr);
exception_in_exception = 0;
if (newpc & 1) {
cpu_halt(CPU_HALT_DOUBLE_FAULT);
return;
}
+ x_do_cycles(adjust_cycles(6 * 4 * CYCLE_UNIT / 2));
if (currprefs.cpu_model == 68000) {
regs.t1 = 0;
MakeSR();
m68k_setpc(regs.vbr + 4 * vector_nr);
- exception3_read(regs.ir | 0x40000, newpc, 1, 2);
+ if (interrupt) {
+ regs.ir = nr;
+ exception3_read(regs.ir | 0x20000 | 0x10000, newpc, 1, 2);
+ } else {
+ exception3_read(regs.ir | 0x40000, newpc, 1, 2);
+ }
} else if (currprefs.cpu_model == 68010) {
regs.t1 = 0;
MakeSR();
}
return;
}
- if (interrupt)
- regs.intmask = nr - 24;
+ add_approximate_exception_cycles(nr);
m68k_setpc (newpc);
cache_default_data &= ~CACHE_DISABLE_ALLOCATE;
#ifdef JIT
opcode = regs.ir;
}
last_di_for_exception_3 = 1;
- exception3f (opcode, addr, false, ia, ni, 0xffffffff, size, false, fc);
+ exception3f(opcode, addr, false, ia, ni, 0xffffffff, size, false, fc);
}
void exception3_write(uae_u32 opcode, uaecptr addr, int size, uae_u32 val, int fc)
{
opcode = regs.ir;
}
last_di_for_exception_3 = 1;
- exception3f (opcode, addr, true, ia, ni, 0xffffffff, size, false, fc);
+ exception3f(opcode, addr, true, ia, ni, 0xffffffff, size, false, fc);
regs.write_buffer = val;
}
void exception3i(uae_u32 opcode, uaecptr addr)