David Rimer
/
Gigatron_Emulator
A small emulator for the gigatron created for the STM32F746G-DISCO and an NES wii controller
GigatronCPU.cpp
- Committer:
- davidr99
- Date:
- 2020-03-05
- Revision:
- 1:4c1f3d32fceb
- Parent:
- 0:72d8735c099e
File content as of revision 1:4c1f3d32fceb:
#include<GigatronCPU.h> CPUStates GigatronCPU::CpuCycle(CPUStates states) { CPUState *T = states.New; CPUState *state = states.Current; //states.CopyToNew(); //memcpy(T, state, sizeof(CPUState)); // 1us // --- 25us int data = this->ROM[state->PC]; // --- 21us T->IR = data; // GetAddressL(this->ROM, state->PC); T->D = (data >> 8); // GetAddressH(this->ROM, state->PC); // 4us // --- 17us int ins = state->IR >> 5; // Instruction int mod = (state->IR >> 2) & 7; // Addressing mode (or condition) int bus = state->IR & 3; // Busmode bool W = (ins == 6); // Write instruction? bool J = (ins == 7); // Jump instruction? char lo = state->D; char hi = 0; //uint32_t t0 = micros(); // --- 17us // Load address to read from bool incX = false; if (!J) // If we are not jumping { switch (mod) { case 0: // From 0D, _AC break; case 1: // From OX, _AC lo = state->X; break; case 2: // From YD, _AC hi = state->Y; break; case 3: // From YX, _AC lo = state->X; hi = state->Y; break; case 4: // From 0D, X break; case 5: // From 0D, Y break; case 6: // From 0D, OUT break; case 7: // From Y,X++, OUT lo = state->X; hi = state->Y; incX = true; break; } } // --- 18 uint16_t addr = (uint16_t)((hi << 8) | lo); //1us // --- 17 // Feed to Data bus uint8_t B = state->undef; // Data Bus switch (bus) { case 0: B = state->D; break; case 1: if (!W) { B = this->RAM[addr & 0x7fff]; break; } break; case 2: B = state->_AC; break; case 3: B = T->IN; break; } // --- 13us if (W) { this->RAM[addr & 0x7fff] = B; // Random Access Memory } // ALU uint8_t ALU = 0; // Arithmetic and Logic Unit switch (ins) { case 0: ALU = (uint8_t) B; break; // LD case 1: ALU = (uint8_t)(state->_AC & B); break; // ANDA case 2: ALU = (uint8_t)(state->_AC | B); break; // ORA case 3: ALU = (uint8_t)(state->_AC ^ B); break; // XORA case 4: ALU = (uint8_t)(state->_AC + B); break; // ADDA case 5: ALU = (uint8_t) (state->_AC - B); break; // SUBA case 6: ALU = state->_AC; break; // ST case 7: ALU = (uint8_t) -state->_AC; break; // Bcc/JMP } // Output to where it needs to go if (!J) // If we are not jumping & not writing { switch (mod) { case 0: // To _AC case 1: case 2: case 3: if (!W) { T->_AC = ALU; } break; case 4: // To X T->X = ALU; break; case 5: // To Y T->Y = ALU; break; case 6: // To OUT case 7: // To OUT if (!W) { T->OUT = ALU; int rising = (~state->OUT & ALU); if ((rising & 0x40) > 0) // hSync rising { T->OUTX = T->_AC; } } break; } } if (incX) { T->X = (uint8_t)(state->X + 1); // Increment X } if (J) { if (mod != 0) { // Conditional branch within page int cond = (state->_AC >> 7) + 2 * (state->_AC == 0 ? 1 : 0); if ((mod & (1 << cond)) > 0) // 74153 { T->PC = (uint16_t)((state->PC & 0xff00) | B); } else { T->PC = (uint16_t) (state->PC + 1); // Next instruction } } else { T->PC = (uint16_t)((state->Y << 8) | B); // Unconditional far jump } } else { T->PC = (uint16_t) (state->PC + 1); // Next instruction } //uint32_t t1 = micros(); //uint32_t delta_t = t1 - t0; //Serial.printf( "Delta = %u\n", delta_t ); // this prints around 51 on my system. memcpy(state, T, sizeof(CPUState)); // 2us //states.CopyNewToCurrent(); return states; }