A small emulator for the gigatron created for the STM32F746G-DISCO and an NES wii controller

Committer:
davidr99
Date:
Thu Mar 05 01:07:01 2020 +0000
Revision:
0:72d8735c099e
Code for the gigatron emulator

Who changed what in which revision?

UserRevisionLine numberNew contents of line
davidr99 0:72d8735c099e 1 #include<GigatronCPU.h>
davidr99 0:72d8735c099e 2
davidr99 0:72d8735c099e 3 CPUStates GigatronCPU::CpuCycle(CPUStates states)
davidr99 0:72d8735c099e 4 {
davidr99 0:72d8735c099e 5 CPUState *T = states.New;
davidr99 0:72d8735c099e 6 CPUState *state = states.Current;
davidr99 0:72d8735c099e 7
davidr99 0:72d8735c099e 8 //states.CopyToNew();
davidr99 0:72d8735c099e 9 //memcpy(T, state, sizeof(CPUState)); // 1us
davidr99 0:72d8735c099e 10
davidr99 0:72d8735c099e 11 // --- 25us
davidr99 0:72d8735c099e 12 int data = this->ROM[state->PC];
davidr99 0:72d8735c099e 13
davidr99 0:72d8735c099e 14
davidr99 0:72d8735c099e 15 // --- 21us
davidr99 0:72d8735c099e 16 T->IR = data; // GetAddressL(this->ROM, state->PC);
davidr99 0:72d8735c099e 17 T->D = (data >> 8); // GetAddressH(this->ROM, state->PC); // 4us
davidr99 0:72d8735c099e 18
davidr99 0:72d8735c099e 19 // --- 17us
davidr99 0:72d8735c099e 20
davidr99 0:72d8735c099e 21 int ins = state->IR >> 5; // Instruction
davidr99 0:72d8735c099e 22 int mod = (state->IR >> 2) & 7; // Addressing mode (or condition)
davidr99 0:72d8735c099e 23 int bus = state->IR & 3; // Busmode
davidr99 0:72d8735c099e 24 bool W = (ins == 6); // Write instruction?
davidr99 0:72d8735c099e 25 bool J = (ins == 7); // Jump instruction?
davidr99 0:72d8735c099e 26
davidr99 0:72d8735c099e 27 char lo = state->D;
davidr99 0:72d8735c099e 28 char hi = 0;
davidr99 0:72d8735c099e 29
davidr99 0:72d8735c099e 30 //uint32_t t0 = micros();
davidr99 0:72d8735c099e 31
davidr99 0:72d8735c099e 32 // --- 17us
davidr99 0:72d8735c099e 33
davidr99 0:72d8735c099e 34 // Load address to read from
davidr99 0:72d8735c099e 35 bool incX = false;
davidr99 0:72d8735c099e 36 if (!J) // If we are not jumping
davidr99 0:72d8735c099e 37 {
davidr99 0:72d8735c099e 38 switch (mod)
davidr99 0:72d8735c099e 39 {
davidr99 0:72d8735c099e 40 case 0: // From 0D, _AC
davidr99 0:72d8735c099e 41 break;
davidr99 0:72d8735c099e 42
davidr99 0:72d8735c099e 43 case 1: // From OX, _AC
davidr99 0:72d8735c099e 44 lo = state->X;
davidr99 0:72d8735c099e 45 break;
davidr99 0:72d8735c099e 46
davidr99 0:72d8735c099e 47 case 2: // From YD, _AC
davidr99 0:72d8735c099e 48 hi = state->Y;
davidr99 0:72d8735c099e 49 break;
davidr99 0:72d8735c099e 50
davidr99 0:72d8735c099e 51 case 3: // From YX, _AC
davidr99 0:72d8735c099e 52 lo = state->X;
davidr99 0:72d8735c099e 53 hi = state->Y;
davidr99 0:72d8735c099e 54 break;
davidr99 0:72d8735c099e 55
davidr99 0:72d8735c099e 56 case 4: // From 0D, X
davidr99 0:72d8735c099e 57 break;
davidr99 0:72d8735c099e 58
davidr99 0:72d8735c099e 59 case 5: // From 0D, Y
davidr99 0:72d8735c099e 60 break;
davidr99 0:72d8735c099e 61
davidr99 0:72d8735c099e 62 case 6: // From 0D, OUT
davidr99 0:72d8735c099e 63 break;
davidr99 0:72d8735c099e 64
davidr99 0:72d8735c099e 65 case 7: // From Y,X++, OUT
davidr99 0:72d8735c099e 66 lo = state->X;
davidr99 0:72d8735c099e 67 hi = state->Y;
davidr99 0:72d8735c099e 68 incX = true;
davidr99 0:72d8735c099e 69 break;
davidr99 0:72d8735c099e 70 }
davidr99 0:72d8735c099e 71 }
davidr99 0:72d8735c099e 72
davidr99 0:72d8735c099e 73 // --- 18
davidr99 0:72d8735c099e 74 uint16_t addr = (uint16_t)((hi << 8) | lo); //1us
davidr99 0:72d8735c099e 75 // --- 17
davidr99 0:72d8735c099e 76
davidr99 0:72d8735c099e 77 // Feed to Data bus
davidr99 0:72d8735c099e 78 uint8_t B = state->undef; // Data Bus
davidr99 0:72d8735c099e 79 switch (bus)
davidr99 0:72d8735c099e 80 {
davidr99 0:72d8735c099e 81 case 0:
davidr99 0:72d8735c099e 82 B = state->D;
davidr99 0:72d8735c099e 83 break;
davidr99 0:72d8735c099e 84
davidr99 0:72d8735c099e 85 case 1:
davidr99 0:72d8735c099e 86 if (!W)
davidr99 0:72d8735c099e 87 {
davidr99 0:72d8735c099e 88 B = this->RAM[addr & 0x7fff];
davidr99 0:72d8735c099e 89 break;
davidr99 0:72d8735c099e 90 }
davidr99 0:72d8735c099e 91 break;
davidr99 0:72d8735c099e 92
davidr99 0:72d8735c099e 93 case 2:
davidr99 0:72d8735c099e 94 B = state->_AC;
davidr99 0:72d8735c099e 95 break;
davidr99 0:72d8735c099e 96
davidr99 0:72d8735c099e 97 case 3:
davidr99 0:72d8735c099e 98 B = T->IN;
davidr99 0:72d8735c099e 99 break;
davidr99 0:72d8735c099e 100 }
davidr99 0:72d8735c099e 101
davidr99 0:72d8735c099e 102 // --- 13us
davidr99 0:72d8735c099e 103
davidr99 0:72d8735c099e 104 if (W)
davidr99 0:72d8735c099e 105 {
davidr99 0:72d8735c099e 106 this->RAM[addr & 0x7fff] = B; // Random Access Memory
davidr99 0:72d8735c099e 107 }
davidr99 0:72d8735c099e 108
davidr99 0:72d8735c099e 109 // ALU
davidr99 0:72d8735c099e 110 uint8_t ALU = 0; // Arithmetic and Logic Unit
davidr99 0:72d8735c099e 111 switch (ins)
davidr99 0:72d8735c099e 112 {
davidr99 0:72d8735c099e 113 case 0:
davidr99 0:72d8735c099e 114 ALU = (uint8_t) B;
davidr99 0:72d8735c099e 115 break; // LD
davidr99 0:72d8735c099e 116
davidr99 0:72d8735c099e 117 case 1:
davidr99 0:72d8735c099e 118 ALU = (uint8_t)(state->_AC & B);
davidr99 0:72d8735c099e 119 break; // ANDA
davidr99 0:72d8735c099e 120
davidr99 0:72d8735c099e 121 case 2:
davidr99 0:72d8735c099e 122 ALU = (uint8_t)(state->_AC | B);
davidr99 0:72d8735c099e 123 break; // ORA
davidr99 0:72d8735c099e 124
davidr99 0:72d8735c099e 125 case 3:
davidr99 0:72d8735c099e 126 ALU = (uint8_t)(state->_AC ^ B);
davidr99 0:72d8735c099e 127 break; // XORA
davidr99 0:72d8735c099e 128
davidr99 0:72d8735c099e 129 case 4:
davidr99 0:72d8735c099e 130 ALU = (uint8_t)(state->_AC + B);
davidr99 0:72d8735c099e 131 break; // ADDA
davidr99 0:72d8735c099e 132
davidr99 0:72d8735c099e 133 case 5:
davidr99 0:72d8735c099e 134 ALU = (uint8_t) (state->_AC - B);
davidr99 0:72d8735c099e 135 break; // SUBA
davidr99 0:72d8735c099e 136
davidr99 0:72d8735c099e 137 case 6:
davidr99 0:72d8735c099e 138 ALU = state->_AC;
davidr99 0:72d8735c099e 139 break; // ST
davidr99 0:72d8735c099e 140
davidr99 0:72d8735c099e 141 case 7:
davidr99 0:72d8735c099e 142 ALU = (uint8_t) -state->_AC;
davidr99 0:72d8735c099e 143 break; // Bcc/JMP
davidr99 0:72d8735c099e 144 }
davidr99 0:72d8735c099e 145
davidr99 0:72d8735c099e 146
davidr99 0:72d8735c099e 147 // Output to where it needs to go
davidr99 0:72d8735c099e 148 if (!J) // If we are not jumping & not writing
davidr99 0:72d8735c099e 149 {
davidr99 0:72d8735c099e 150 switch (mod)
davidr99 0:72d8735c099e 151 {
davidr99 0:72d8735c099e 152 case 0: // To _AC
davidr99 0:72d8735c099e 153 case 1:
davidr99 0:72d8735c099e 154 case 2:
davidr99 0:72d8735c099e 155 case 3:
davidr99 0:72d8735c099e 156 if (!W)
davidr99 0:72d8735c099e 157 {
davidr99 0:72d8735c099e 158 T->_AC = ALU;
davidr99 0:72d8735c099e 159 }
davidr99 0:72d8735c099e 160 break;
davidr99 0:72d8735c099e 161
davidr99 0:72d8735c099e 162 case 4: // To X
davidr99 0:72d8735c099e 163 T->X = ALU;
davidr99 0:72d8735c099e 164 break;
davidr99 0:72d8735c099e 165
davidr99 0:72d8735c099e 166 case 5: // To Y
davidr99 0:72d8735c099e 167 T->Y = ALU;
davidr99 0:72d8735c099e 168 break;
davidr99 0:72d8735c099e 169
davidr99 0:72d8735c099e 170 case 6: // To OUT
davidr99 0:72d8735c099e 171 case 7: // To OUT
davidr99 0:72d8735c099e 172 if (!W)
davidr99 0:72d8735c099e 173 {
davidr99 0:72d8735c099e 174 T->OUT = ALU;
davidr99 0:72d8735c099e 175
davidr99 0:72d8735c099e 176 int rising = (~state->OUT & ALU);
davidr99 0:72d8735c099e 177
davidr99 0:72d8735c099e 178 if ((rising & 0x40) > 0) // hSync rising
davidr99 0:72d8735c099e 179 {
davidr99 0:72d8735c099e 180 T->OUTX = T->_AC;
davidr99 0:72d8735c099e 181 }
davidr99 0:72d8735c099e 182 }
davidr99 0:72d8735c099e 183 break;
davidr99 0:72d8735c099e 184 }
davidr99 0:72d8735c099e 185 }
davidr99 0:72d8735c099e 186
davidr99 0:72d8735c099e 187 if (incX)
davidr99 0:72d8735c099e 188 {
davidr99 0:72d8735c099e 189 T->X = (uint8_t)(state->X + 1); // Increment X
davidr99 0:72d8735c099e 190 }
davidr99 0:72d8735c099e 191
davidr99 0:72d8735c099e 192 if (J)
davidr99 0:72d8735c099e 193 {
davidr99 0:72d8735c099e 194 if (mod != 0)
davidr99 0:72d8735c099e 195 {
davidr99 0:72d8735c099e 196 // Conditional branch within page
davidr99 0:72d8735c099e 197 int cond = (state->_AC >> 7) + 2 * (state->_AC == 0 ? 1 : 0);
davidr99 0:72d8735c099e 198 if ((mod & (1 << cond)) > 0) // 74153
davidr99 0:72d8735c099e 199 {
davidr99 0:72d8735c099e 200 T->PC = (uint16_t)((state->PC & 0xff00) | B);
davidr99 0:72d8735c099e 201 }
davidr99 0:72d8735c099e 202 else
davidr99 0:72d8735c099e 203 {
davidr99 0:72d8735c099e 204 T->PC = (uint16_t) (state->PC + 1); // Next instruction
davidr99 0:72d8735c099e 205 }
davidr99 0:72d8735c099e 206 }
davidr99 0:72d8735c099e 207 else
davidr99 0:72d8735c099e 208 {
davidr99 0:72d8735c099e 209 T->PC = (uint16_t)((state->Y << 8) | B); // Unconditional far jump
davidr99 0:72d8735c099e 210 }
davidr99 0:72d8735c099e 211 }
davidr99 0:72d8735c099e 212 else
davidr99 0:72d8735c099e 213 {
davidr99 0:72d8735c099e 214 T->PC = (uint16_t) (state->PC + 1); // Next instruction
davidr99 0:72d8735c099e 215 }
davidr99 0:72d8735c099e 216
davidr99 0:72d8735c099e 217 //uint32_t t1 = micros();
davidr99 0:72d8735c099e 218 //uint32_t delta_t = t1 - t0;
davidr99 0:72d8735c099e 219 //Serial.printf( "Delta = %u\n", delta_t ); // this prints around 51 on my system.
davidr99 0:72d8735c099e 220
davidr99 0:72d8735c099e 221
davidr99 0:72d8735c099e 222 memcpy(state, T, sizeof(CPUState)); // 2us
davidr99 0:72d8735c099e 223 //states.CopyNewToCurrent();
davidr99 0:72d8735c099e 224
davidr99 0:72d8735c099e 225 return states;
davidr99 0:72d8735c099e 226 }