static uae_u32 feature_addressing_modes[2];
static int ad8r[2], pc8r[2];
-#define HIGH_MEMORY_START (0x01000000 - 0x8000)
+#define HIGH_MEMORY_START (addressing_mask == 0xffffffff ? 0xffff8000 : 0x00ff8000)
// large enough for RTD
#define STACK_SIZE (0x8000 + 8)
low_memory_accessed = w ? -1 : 1;
return 1;
}
- if (addr >= HIGH_MEMORY_START && addr < HIGH_MEMORY_START + 0x8000) {
+ if (addr >= HIGH_MEMORY_START && addr <= HIGH_MEMORY_START + 0x7fff) {
if (addr < test_high_memory_start || test_high_memory_start == 0xffffffff)
goto oob;
if (addr + size >= test_high_memory_end)
return 0;
}
+static void validate_addr(uaecptr addr, int size)
+{
+ if (valid_address(addr, size, 0))
+ return;
+ wprintf(_T("Trying to store invalid memory address %08x!?\n"), addr);
+ abort();
+}
+
+
static uae_u8 *get_addr(uaecptr addr, int size, int w)
{
// allow debug output to read memory even if oob condition
size--;
if (addr + size < low_memory_size) {
return low_memory + addr;
- } else if (addr >= HIGH_MEMORY_START && addr < HIGH_MEMORY_START + 0x8000) {
+ } else if (addr >= HIGH_MEMORY_START && addr <= HIGH_MEMORY_START + 0x7fff) {
return high_memory + (addr - HIGH_MEMORY_START);
} else if (addr >= test_memory_start && addr + size < test_memory_end + EXTRA_RESERVED_SPACE) {
return test_memory + (addr - test_memory_start);
put_long_test(addr, v);
}
+uae_u16 get_wordi_test(uaecptr addr)
+{
+ return get_word_test(addr);
+}
+
uae_u32 memory_get_byte(uaecptr addr)
{
return get_byte_test(addr);
return v;
}
+bool mmu_op30(uaecptr pc, uae_u32 opcode, uae_u16 extra, uaecptr extraa)
+{
+ m68k_setpc(pc);
+ op_illg(opcode);
+ return true;
+}
+
uae_u32(*x_get_long)(uaecptr);
uae_u32(*x_get_word)(uaecptr);
void (*x_put_long)(uaecptr, uae_u32);
} else {
Exception_build_stack_frame_common(regs.instruction_pc, regs.pc, 0, test_exception);
}
- } else if (cpu_lvl == 2) {
+ } else if (cpu_lvl == 2 || cpu_lvl == 3) {
if (test_exception == 3) {
uae_u16 ssw = (sv ? 4 : 0) | test_exception_3_fc;
ssw |= 0x20;
} else {
Exception_build_stack_frame_common(regs.instruction_pc, regs.pc, 0, test_exception);
}
+ } else {
+ if (test_exception == 3) {
+ if (currprefs.cpu_model == 68060)
+ test_exception_addr &= ~1;
+ Exception_build_stack_frame(test_exception_addr, regs.pc, 0, 3, 0x02);
+ } else {
+ Exception_build_stack_frame_common(regs.instruction_pc, regs.pc, 0, test_exception);
+ }
}
exception_stack_frame_size = test_memory_end + EXTRA_RESERVED_SPACE - m68k_areg(regs, 7);
fclose(f);
}
-
-
static uae_u8 *store_rel(uae_u8 *dst, uae_u8 mode, uae_u32 s, uae_u32 d, int ordered)
{
int diff = (uae_s32)d - (uae_s32)s;
*dst++ = mode | CT_ABSOLUTE_WORD;
*dst++ = (d >> 8) & 0xff;
*dst++ = d & 0xff;
- } else if ((d & ~addressing_mask) == ~addressing_mask && (d & addressing_mask) >= HIGH_MEMORY_START) {
+ } else if ((d & ~addressing_mask) == ~addressing_mask && (d & addressing_mask) >= (HIGH_MEMORY_START & addressing_mask)) {
*dst++ = mode | CT_ABSOLUTE_WORD;
*dst++ = (d >> 8) & 0xff;
*dst++ = d & 0xff;
struct accesshistory *ah = &ahist[i];
if (ah->oldval == ah->val && !storealways)
continue;
+ validate_addr(ah->addr, 1 << ah->size);
uaecptr addr = ah->addr;
addr &= addressing_mask;
if (addr < 0x8000) {
fwrite(data, 1, 4, f);
pl(data, opcode_memory_start - test_memory_start);
fwrite(data, 1, 4, f);
- pl(data, (cpu_lvl << 16) | sr_undefined_mask);
+ pl(data, (cpu_lvl << 16) | sr_undefined_mask | (addressing_mask == 0xffffffff ? 0x80000000 : 0));
fwrite(data, 1, 4, f);
pl(data, currprefs.fpu_model);
fwrite(data, 1, 4, f);
{
uae_u16 opw1 = (opcode_memory[2] << 8) | (opcode_memory[3] << 0);
uae_u16 opw2 = (opcode_memory[4] << 8) | (opcode_memory[5] << 0);
- if (opc == 0xf601
-// && opw1 == 0x0000
-// && opw2 == 0x9908
+ if (opc == 0xf603
+ && opw1 == 0x6884
+ && opw2 == 0x618d
)
printf("");
if (regs.sr & 0x2000)
case i_MOVEC2:
case i_FSAVE:
case i_FRESTORE:
+ case i_PFLUSH:
+ case i_PFLUSHA:
+ case i_PFLUSHAN:
+ case i_PFLUSHN:
+ case i_PTESTR:
+ case i_PTESTW:
+ case i_CPUSHA:
+ case i_CPUSHL:
+ case i_CPUSHP:
+ case i_CINVA:
+ case i_CINVL:
+ case i_CINVP:
return 1;
case i_RTE:
if (cpu_lvl > 0)
out_of_test_space = 0;
ahcnt = 0;
- if (opc == 0xf620)
+ if (opc == 0x0156)
printf("");
if (subtest_count == 1537)
printf("");
currprefs.cpu_model = 68000;
ini_getval(ini, INISECTION, _T("cpu"), &currprefs.cpu_model);
- if (currprefs.cpu_model != 68000 && currprefs.cpu_model != 68010 && currprefs.cpu_model != 68020 && currprefs.cpu_model != 68040) {
+ if (currprefs.cpu_model != 68000 && currprefs.cpu_model != 68010 && currprefs.cpu_model != 68020 &&
+ currprefs.cpu_model != 68030 && currprefs.cpu_model != 68040 && currprefs.cpu_model != 68060) {
wprintf(_T("Unsupported CPU model.\n"));
return 0;
}
}
feature_full_extension_format = 0;
- if (currprefs.cpu_model > 68000) {
+ if (currprefs.cpu_model >= 68020) {
ini_getval(ini, INISECTION, _T("feature_full_extension_format"), &feature_full_extension_format);
if (feature_full_extension_format) {
ad8r[0] |= 2;
} else if (currprefs.cpu_model == 68020) {
tbl = op_smalltbl_92_test_ff;
cpu_lvl = 2;
- } else if (currprefs.cpu_model == 68040) {
+ } else if (currprefs.cpu_model == 68030) {
+ tbl = op_smalltbl_93_test_ff;
+ cpu_lvl = 3;
+ } else if (currprefs.cpu_model == 68040 ) {
tbl = op_smalltbl_94_test_ff;
cpu_lvl = 4;
+ } else if (currprefs.cpu_model == 68060) {
+ tbl = op_smalltbl_95_test_ff;
+ cpu_lvl = 5;
} else {
wprintf(_T("Unsupported CPU model.\n"));
abort();
cpudatatbl[opcode].branch = tbl[i].branch;
}
+ currprefs.int_no_unimplemented = true;
+ currprefs.fpu_no_unimplemented = true;
+
for (int opcode = 0; opcode < 65536; opcode++) {
cpuop_func *f;
instr *table = &table68k[opcode];
if (table->mnemo == i_ILLG)
continue;
+ /* unimplemented opcode? */
+ if (table->unimpclev > 0 && cpu_lvl >= table->unimpclev) {
+ if (currprefs.cpu_model == 68060) {
+ // remove unimplemented integer instructions
+ // unimpclev == 5: not implemented in 68060,
+ // generates unimplemented instruction exception.
+ if (currprefs.int_no_unimplemented && table->unimpclev == 5) {
+ cpufunctbl[opcode] = op_unimpl_1;
+ continue;
+ }
+ // remove unimplemented instruction that were removed in previous models,
+ // generates normal illegal instruction exception.
+ // unimplclev < 5: instruction was removed in 68040 or previous model.
+ // clev=4: implemented in 68040 or later. unimpclev=5: not in 68060
+ if (table->unimpclev < 5 || (table->clev == 4 && table->unimpclev == 5)) {
+ cpufunctbl[opcode] = op_illg_1;
+ continue;
+ }
+ } else {
+ cpufunctbl[opcode] = op_illg_1;
+ continue;
+ }
+ }
+
if (table->clev > cpu_lvl) {
continue;
}
_get_cpu_model:
move.l 4.w,a0
move.w 0x128(a0),d1
+ cmp.w #15,d1
+ bne.s .cpucheck2
+ | 68040 but could be also 68060
+ movem.l a5/a6,-(sp)
+ move.l a0,a6
+ lea scpucheck(pc),a5
+ jsr -0x1e(a6)
+ movem.l (sp)+,a5/a6
+ bra.s .cpudone2
+.cpucheck2:
moveq #5,d0
tst.b d1
bmi.s .cpudone2
.cpudone2:
rts
+scpucheck:
+ or.w #0x0700,sr
+ movec vbr,a0
+ move.l 0x10(a0),d1
+ lea illg(pc),a1
+ move.l a1,0x10(a0)
+ move.l sp,a1
+ moveq #4,d0
+.arch 68060
+ movec pcr,d0
+.arch 68020
+ moveq #5,d0
+illg:
+ move.l d1,0x10(a0)
+ move.l a1,sp
+ rte
moveq #0,d0
cmp.w #4,d1
bcc.s .scend1b
+ | 68020-68030 only
movec caar,d0
.scend1b:
move.l d0,(a0)+
moveq #0,d0
cmp.w #5,d1
bcc.s .scend1c
+ | 68020-68040 only
movec msp,d0
.scend1c:
move.l d0,(a0)+
move.l (a1)+,d0
cmp.w #4,d1
bcc.s .scend2b
+ | 68020-68030 only
movec d0,caar
.scend2b:
move.l (a1)+,d0
cmp.w #5,d1
bcc.s .scend2
+ | 68020-68040 only
move.c d0,msp
.scend2:
rts
move.l S_AREG+7*4(a0),a1
move.l a1,USP
movem.l (a0),d0-d7/a0-a6
-
- | cmp.l #0x,0x7a0000
- | bne.s .not
- | clr.w 0x100
-|.not:
-
rte
| 68010+ test entrypoint
[cputest]
-; CPU model (68000, 68020 or 68040).
+; CPU model (68000, 68020, 68040 or 68060).
; Always select 68020 when testing FPU instructions, even if test hardware CPU is 68040 or 68060.
cpu=68020
-; CPU address space. 24-bit or 32-bit.
+; CPU address space. 24-bit or 32-bit. If 24-bit, tester will assume upper 8-bits of addresses gets ignored.
cpu_address_space=32
; FPU model (empty string or 0, 68881, 68882, 68040, 68060)
test_low_memory_start=0x0000
test_low_memory_end=0x8000
-; High address space limits (0x00ff8000 to 0x01000000 is complete space). Comment out to disable.
+; High address space limits (0x00ff8000 to 0x01000000 is complete space if 24-bit). Comment out to disable.
;test_high_memory_start=0x00ff8000
;test_high_memory_end=0x01000000
-; ROM high address space. High memory is only used for read tests.
+; ROM high address space. High memory is only used for read tests, uses last 32k of ROM image file.
high_rom=D:\amiga\roms\Kickstart v3.1 rev 40.63 (1993)(Commodore)(A500-A600-A2000)[!].rom
; main test memory start and size (real hardware must have RAM in this address space)
-test_memory_start=0x780000
-;test_memory_start=0x68800000
+;test_memory_start=0x780000
+test_memory_start=0x68800000
test_memory_size=0x080000
; number of test rounds (registers are re-randomized after each round)
if (cpu_lvl == 1) {
execute_test010(&test_regs);
- } else if (cpu_lvl == 2) {
+ } else if (cpu_lvl >= 2) {
if (fpu_model)
execute_testfpu(&test_regs);
else
fread(data, 1, 4, f);
opcode_memory_addr = gl(data) + test_memory_addr;
fread(data, 1, 4, f);
- lvl = gl(data) >> 16;
+ lvl = (gl(data) >> 16) & 15;
+ addressing_mask = (gl(data) & 0x80000000) ? 0xffffffff : 0x00ffffff;
sr_undefined_mask = gl(data);
fread(data, 1, 4, f);
fpu_model = gl(data);
exit(0);
}
+ printf("CPUlvl=%d, Mask=%08lx\n", cpu_lvl, addressing_mask);
printf("%s:\n", inst_name);
testcnt = 0;
fread(data, 1, 4, f);
if (gl(data) != starttimeid) {
printf("Test data file header mismatch (old test data file?)\n");
- goto next;
+ break;
}
fseek(f, 0, SEEK_END);
test_data_size = ftell(f);
break;
free(test_data);
-next:
filecnt++;
}
if (lvl == 3) {
lvl = 2;
} else if (lvl == 5) {
- lvl = 4;
#ifdef M68K
// Overwrite MOVEC to/from MSP
- // with NOP if 68060
+ // with NOPs if 68060
extern void *msp_address1;
extern void *msp_address2;
extern void *msp_address3;
return 0;
}
- sprintf(path + strlen(path), "%lu/", 68000 + lvl * 10);
+ sprintf(path + strlen(path), "%lu/", 68000 + (lvl == 5 ? 6 : lvl) * 10);
strcpy(opcode, argv[1]);
printf ("\tm68k_areg (regs, 7) += offs;\n");
}
printf ("\tif (pc & 1) {\n");
- printf ("\t\texception3i (0x%04X, pc);\n", opcode);
+ if (cpu_level >= 4) {
+ printf("\t\tm68k_areg(regs, 7) -= 4 + offs;\n");
+ }
+ printf ("\t\texception3i (0x%04X, pc);\n", opcode);
printf ("\t\tgoto %s;\n", endlabelstr);
printf ("\t}\n");
setpc ("pc");
fill_prefetch_full ();
need_endlabel = 1;
branch_inst = 1;
+ if (cpu_level >= 4) {
+ if (next_cpu_level < 4)
+ next_cpu_level = 4 - 1;
+ }
break;
case i_LINK:
// ce confirmed
printf ("\tif (%s & 1) {\n", getpc);
printf ("\t\tuaecptr faultpc = %s;\n", getpc);
setpc ("pc");
+ if (cpu_level >= 4) {
+ printf("\t\tm68k_areg(regs, 7) -= 4;\n");
+ }
printf ("\t\texception3i (0x%04X, faultpc);\n", opcode);
printf ("\t\tgoto %s;\n", endlabelstr);
printf ("\t}\n");
fill_prefetch_full ();
need_endlabel = 1;
branch_inst = 1;
+ if (cpu_level >= 4) {
+ if (next_cpu_level < 4)
+ next_cpu_level = 4 - 1;
+ }
break;
case i_TRAPV:
sync_m68k_pc ();
printf ("\tMakeSR ();\n");
genamode (NULL, Aipi, "7", sz_word, "sr", 1, 0, 0);
genamode (NULL, Aipi, "7", sz_long, "pc", 1, 0, 0);
+ if (cpu_level >= 4) {
+ printf("\tif (pc & 1) {\n");
+ printf("\t\tm68k_areg(regs, 7) -= 6;\n");
+ printf("\t\texception3i (0x%04X, pc);\n", opcode);
+ printf("\t\tgoto %s;\n", endlabelstr);
+ printf("\t}\n");
+ }
printf ("\tregs.sr &= 0xFF00; sr &= 0xFF;\n");
printf ("\tregs.sr |= sr;\n");
setpc ("pc");
makefromsr();
- printf ("\tif (%s & 1) {\n", getpc);
- printf ("\t\tuaecptr faultpc = %s;\n", getpc);
- setpc ("oldpc");
- printf ("\t\texception3i (0x%04X, faultpc);\n", opcode);
- printf ("\t\tgoto %s;\n", endlabelstr);
- printf ("\t}\n");
+ if (cpu_level < 4) {
+ printf("\tif (%s & 1) {\n", getpc);
+ printf("\t\tuaecptr faultpc = %s;\n", getpc);
+ setpc("oldpc");
+ printf("\t\texception3i (0x%04X, faultpc);\n", opcode);
+ printf("\t\tgoto %s;\n", endlabelstr);
+ printf("\t}\n");
+ }
clear_m68k_offset();
fill_prefetch_full ();
need_endlabel = 1;
branch_inst = 1;
tail_ce020_done = true;
+ if (cpu_level >= 4) {
+ if (next_cpu_level < 4)
+ next_cpu_level = 4 - 1;
+ }
break;
case i_JSR:
// possible idle cycle, prefetch from new address, stack high return addr, stack low, prefetch
if (cpu_level <= 1 && using_prefetch)
printf ("\tnextpc += 2;\n");
}
- printf("\tm68k_areg (regs, 7) -= 4;\n");
+ if (cpu_level < 4)
+ printf("\tm68k_areg (regs, 7) -= 4;\n");
if (using_exception_3 && cpu_level <= 1) {
printf("\tif (m68k_areg(regs, 7) & 1) {\n");
printf("\t\texception3_write(opcode, m68k_areg(regs, 7), 1);\n");
printf("\t}\n");
need_endlabel = 1;
}
+ if (cpu_level >= 4)
+ printf("\tm68k_areg (regs, 7) -= 4;\n");
clear_m68k_offset();
fill_prefetch_1 (0);
if (using_ce || using_prefetch) {
fill_prefetch_full_020 ();
fill_prefetch_next ();
branch_inst = 1;
+ if (cpu_level >= 4) {
+ if (next_cpu_level < 4)
+ next_cpu_level = 4 - 1;
+ }
break;
case i_JMP:
no_prefetch_ce020 = true;
printf("\tuaecptr nextpc = oldpc + %d;\n", m68k_pc_offset);
if (using_exception_3 && cpu_level >= 2) {
printf("\tif (s & 1) {\n");
- printf("\t\tm68k_areg(regs, 7) -= 4;\n");
+ if (cpu_level < 4)
+ printf("\t\tm68k_areg(regs, 7) -= 4;\n");
printf("\t\texception3b(opcode, %s + s, 0, 1, %s + s);\n", getpc, getpc);
printf("\t\tgoto %s;\n", endlabelstr);
printf("\t}\n");
}
genamode (curi, curi->smode, "srcreg", curi->size, "src", 1, 0, GF_AA | (cpu_level < 2 ? GF_NOREFILL : 0));
addcycles000 (2);
+ if (using_exception_3 && cpu_level >= 4) {
+ printf("\tif (src & 1) {\n");
+ printf("\t\texception3i (opcode, %s + 2 + (uae_s32)src);\n", getpc);
+ printf("\t\tgoto %s;\n", endlabelstr);
+ printf("\t}\n");
+ need_endlabel = 1;
+ }
printf ("\tif (!cctrue (%d)) goto didnt_jump;\n", curi->cc);
- if (using_exception_3) {
+ if (using_exception_3 && cpu_level < 4) {
printf ("\tif (src & 1) {\n");
printf ("\t\texception3i (opcode, %s + 2 + (uae_s32)src);\n", getpc);
printf ("\t\tgoto %s;\n", endlabelstr);
insn_n_cycles = curi->size == sz_byte ? 8 : 12;
branch_inst = 1;
bccl_not68020:
+ if (cpu_level >= 4) {
+ if (next_cpu_level < 4)
+ next_cpu_level = 4 - 1;
+ }
break;
case i_LEA:
if (curi->smode == Ad8r || curi->smode == PC8r)
//genamode (curi, curi->dmode, "dstreg", curi->size, "offs", 1, 0, GF_AA | GF_NOREFILL);
printf ("\tuaecptr oldpc = %s;\n", getpc);
addcycles000 (2);
+ if (using_exception_3 && cpu_level >= 4) {
+ printf("\tif (offs & 1) {\n");
+ printf("\t\t\texception3i (opcode, oldpc + (uae_s32)offs + 2);\n");
+ printf("\t\t\tgoto %s;\n", endlabelstr);
+ printf("\t\t}\n");
+ need_endlabel = 1;
+ }
push_ins_cnt();
printf ("\tif (!cctrue (%d)) {\n", curi->cc);
printf("\t");
incpc ("(uae_s32)offs + 2");
printf ("\t");
- if (using_exception_3) {
+ if (using_exception_3 && cpu_level < 4) {
printf("\tif (offs & 1) {\n");
printf("\t\t\texception3i (opcode, %s);\n", getpc);
printf("\t\t\tgoto %s;\n", endlabelstr);
insn_n_cycles = 12;
need_endlabel = 1;
branch_inst = 1;
+ if (cpu_level >= 4) {
+ if (next_cpu_level < 4)
+ next_cpu_level = 4 - 1;
+ }
break;
case i_Scc:
// confirmed
int old_m68k_pc_total = m68k_pc_total;
old_brace_level = n_braces;
start_brace ();
+ if (cpu_level >= 4) {
+ printf("\tuae_u32 src = regs.regs[(extra >> 12) & 15];\n");
+ }
genamode (curi, curi->dmode, "dstreg", curi->size, "dst", 2, 0, 0);
tail_ce020_done = false;
returntail(false);
did_prefetch = 0;
- printf("\tuae_u32 src = regs.regs[(extra >> 12) & 15];\n");
+ if (cpu_level < 4) {
+ printf("\tuae_u32 src = regs.regs[(extra >> 12) & 15];\n");
+ }
genastore_fc ("src", curi->dmode, "dstreg", curi->size, "dst");
sync_m68k_pc();
pop_braces(old_brace_level);
returntail(false);
pop_braces (old_brace_level);
}
+ if (cpu_level >= 4) {
+ if (next_cpu_level < 4)
+ next_cpu_level = 4 - 1;
+ }
}
break;
case i_BKPT: /* only needed for hardware emulators */
cpu_level = 2;
using_prefetch = 0;
using_simple_cycles = 0;
+ } else if (mode == 3) {
+ cpu_level = 3;
+ using_prefetch = 0;
+ using_simple_cycles = 0;
} else if (mode == 4) {
cpu_level = 4;
using_prefetch = 0;
using_simple_cycles = 0;
+ } else if (mode == 5) {
+ cpu_level = 5;
+ using_prefetch = 0;
+ using_simple_cycles = 0;
}
read_counts();
generate_cpu_test(0);
generate_cpu_test(1);
generate_cpu_test(2);
+ generate_cpu_test(3);
generate_cpu_test(4);
+ generate_cpu_test(5);
#else
extern const struct cputbl op_smalltbl_90_test_ff[];
extern const struct cputbl op_smalltbl_91_test_ff[];
extern const struct cputbl op_smalltbl_92_test_ff[];
+extern const struct cputbl op_smalltbl_93_test_ff[];
extern const struct cputbl op_smalltbl_94_test_ff[];
+extern const struct cputbl op_smalltbl_95_test_ff[];
extern struct flag_struct regflags;
extern int movem_next[256];
uae_u16 get_word_test_prefetch(int);
+uae_u16 get_wordi_test(uaecptr);
void put_byte_test(uaecptr, uae_u32);
void put_word_test(uaecptr, uae_u32);