| 9120e874 Andy McCall | 1 | // Test fixture for the CPU core: a flat 64K memory and the handful of symbols |
| 2 | // fake6502.c expects the rest of the emulator to provide. |
|
| 3 | // |
|
| 4 | // The CPU is the cheapest part of the machine to test. fake6502.c defines its |
|
| 5 | // own registers, cycle counter and run state, includes no memory.h, and reaches |
|
| 6 | // outside itself for only six symbols -- all supplied here. So a CPU test links |
|
| 7 | // the real instruction tables against this flat memory and nothing else: no |
|
| 8 | // SDL, no ROM, no banking, no devices. |
|
| 9 | // |
|
| 10 | // One fixture covers all three instruction sets. There is no separate 65C816 |
|
| 11 | // core: fake6502.c holds both optable_c02[] and optable_c816[] and swaps a |
|
| 12 | // single pointer inside reset6502(), so which CPU a scenario runs on is a |
|
| 13 | // parameter here rather than a different harness. |
|
| 14 | |
|
| 15 | |
|
| 16 | |
|
| 17 | ||
| 18 | |
|
| 19 | |
|
| 20 | |
|
| 21 | |
|
| 22 | |
|
| 23 | |
|
| 24 | // registers.h defines the type but not the object, and the only declaration of |
|
| 25 | // it lives in glue.h, which reaches SDL. code_map.c and debug_core.c each |
|
| 26 | // declare it locally for the same reason; this does the same. |
|
| 27 | extern struct regs regs; |
|
| 28 | ||
| 29 | // The four CPU configurations the emulator can be in. Three of them change how |
|
| 30 | // wide a register is, which changes what an instruction does with it. |
|
| 31 | typedef enum |
|
| 32 | |
|
| 33 | |
|
| 34 | |
|
| 35 | |
|
| 36 | cpu_mode_t; |
|
| 37 | ||
| 38 | const char *; |
|
| 39 | ||
| 40 | // True where the mode treats A/X/Y as 16 bits. |
|
| 41 | bool ; |
|
| 42 | ||
| 43 | // The machine's memory, exposed directly so a test can seed operands and read |
|
| 44 | // results back without going through the CPU. |
|
| 45 | // |
|
| 46 | // 16 MB, indexed by the 65C816's full 24-bit address: (bank << 16) | offset. |
|
| 47 | // Bank 0 is the first 64K, so a 65C02 test indexes it exactly as before. |
|
| 48 | |
|
| 49 | extern uint8_t cpu_mem; |
|
| 50 | ||
| 51 | // Seed a byte anywhere in the 24-bit space, recording it so the next reset |
|
| 52 | // clears it again. Writing cpu_mem[] directly is fine within bank 0, which is |
|
| 53 | // always cleared; outside it, use this or the byte survives into the next test. |
|
| 54 | void ; |
|
| 55 | ||
| 56 | // Zero memory and counters, point the reset vector at `start`, and reset the |
|
| 57 | // CPU into `mode`. Every scenario begins here, so one test cannot inherit |
|
| 58 | // state from the one before it. |
|
| 59 | void ; |
|
| 60 | ||
| 61 | // Copy a block into memory, returning the address just past it so successive |
|
| 62 | // pieces can be laid down without recomputing offsets. |
|
| 63 | uint16_t ; |
|
| 64 | ||
| 65 | // Execute exactly `count` instructions. |
|
| 66 | void ; |
|
| 67 | ||
| 68 | // Execute one instruction and return what it cost. Timing assertions want this |
|
| 69 | // rather than cpu_last_cycles(), which covers a whole run: reading a per- |
|
| 70 | // instruction cost off a run that also included its setup is an easy mistake to |
|
| 71 | // make and a confusing one to debug. |
|
| 72 | uint32_t ; |
|
| 73 | ||
| 74 | // Run for `ticks` cycles through exec6502(), the loop the emulator itself uses. |
|
| 75 | // step6502() is the loop the debugger drives, and the two are separate pieces |
|
| 76 | // of code that are supposed to agree; this exists so a test can compare them. |
|
| 77 | void ; |
|
| 78 | ||
| 79 | // Cycles consumed by the most recent cpu_steps() call. Cycle counts are worth |
|
| 80 | // asserting on: they are what a debugger hook can perturb without changing any |
|
| 81 | // visible register. |
|
| 82 | uint32_t ; |
|
| 83 | ||
| 84 | // How often the CPU has signalled a halt (STP) or pulled a vector, since the |
|
| 85 | // last reset. Both are otherwise invisible to a test. |
|
| 86 | extern uint32_t cpu_stop_count; |
|
| 87 | extern uint32_t cpu_vector_pulls; |
|
| 88 | ||
| 89 | // Read a register at the width the CPU is currently using. |
|
| 90 | // |
|
| 91 | // The register names are less symmetric than they look: regs.a is the LOW BYTE |
|
| 92 | // of the accumulator, while regs.x and regs.y are the whole 16-bit registers |
|
| 93 | // (regs.xl and regs.yl are their low bytes). Checking regs.a in a 16-bit |
|
| 94 | // scenario would quietly drop the high byte and report a false pass, in exactly |
|
| 95 | // the mode this fixture exists to cover, so prefer these throughout. |
|
| 96 | uint16_t ; |
|
| 97 | uint16_t ; |
|
| 98 | uint16_t ; |
|
| 99 | ||
| 100 | // Set these to watch every bus access the CPU makes, so a test can compare the |
|
| 101 | // order and addresses against a reference trace. NULL by default, which costs |
|
| 102 | // one branch per access and keeps the other tests unaffected. |
|
| 103 | // |
|
| 104 | // The address is the full 24-bit one; on a 65C02 the bank is always zero. |
|
| 105 | extern ; |
|
| 106 | extern ; |
|
| 107 | ||
| 108 | // Whether the CPU is currently treating the accumulator, or the index |
|
| 109 | // registers, as 16 bits. Emulation mode forces both to 8 whatever the flags say. |
|
| 110 | bool ; |
|
| 111 | bool ; |
|
| 112 | ||
| 113 | // X16_TEST_CPU_FIXTURE_H |