David Rimer / Mbed OS Gigatron_Emulator
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers GigatronCPU.cpp Source File

GigatronCPU.cpp

00001 #include<GigatronCPU.h>
00002 
00003 CPUStates GigatronCPU::CpuCycle(CPUStates states)
00004 {
00005     CPUState *T = states.New;
00006     CPUState *state = states.Current;
00007     
00008     //states.CopyToNew();
00009     //memcpy(T, state, sizeof(CPUState));       // 1us
00010     
00011     // --- 25us
00012     int data = this->ROM[state->PC];
00013     
00014 
00015     // --- 21us 
00016     T->IR = data;       // GetAddressL(this->ROM, state->PC);
00017     T->D = (data >> 8);     // GetAddressH(this->ROM, state->PC);   // 4us
00018     
00019     // --- 17us
00020     
00021     int ins = state->IR >> 5;               // Instruction
00022     int mod = (state->IR >> 2) & 7;         // Addressing mode (or condition)
00023     int bus = state->IR & 3;                // Busmode
00024     bool W = (ins == 6);                    // Write instruction?
00025     bool J = (ins == 7);                    // Jump instruction?
00026 
00027     char lo = state->D;
00028     char hi = 0;
00029     
00030     //uint32_t t0 = micros();
00031     
00032     // --- 17us
00033         
00034     // Load address to read from
00035     bool incX = false;
00036     if (!J)                         // If we are not jumping
00037     {
00038         switch (mod)
00039         {
00040             case 0: // From 0D, _AC
00041                 break;
00042 
00043             case 1: // From OX, _AC
00044                 lo = state->X;
00045                 break;
00046 
00047             case 2: // From YD, _AC
00048                 hi = state->Y;
00049                 break;
00050 
00051             case 3: // From YX, _AC
00052                 lo = state->X;
00053                 hi = state->Y;
00054                 break;
00055 
00056             case 4: // From 0D, X
00057                 break;
00058 
00059             case 5: // From 0D, Y
00060                 break;
00061 
00062             case 6: // From 0D, OUT
00063                 break;
00064 
00065             case 7: // From Y,X++, OUT
00066                 lo = state->X;
00067                 hi = state->Y;
00068                 incX = true;
00069                 break;
00070         }
00071     }
00072             
00073     // --- 18
00074     uint16_t addr = (uint16_t)((hi << 8) | lo); //1us
00075     // --- 17
00076 
00077     // Feed to Data bus
00078     uint8_t B = state->undef; // Data Bus
00079     switch (bus)
00080     {
00081         case 0:
00082             B = state->D;
00083             break;
00084 
00085         case 1:
00086             if (!W)
00087             {
00088                 B = this->RAM[addr & 0x7fff];
00089                 break;
00090             }
00091             break;
00092 
00093         case 2:
00094             B = state->_AC;
00095             break;
00096 
00097         case 3:
00098             B = T->IN;
00099             break;
00100     }
00101     
00102     // --- 13us
00103 
00104     if (W)
00105     {
00106         this->RAM[addr & 0x7fff] = B; // Random Access Memory
00107     }
00108 
00109     // ALU
00110     uint8_t ALU = 0; // Arithmetic and Logic Unit
00111     switch (ins)
00112     {
00113         case 0:
00114             ALU = (uint8_t) B;
00115             break; // LD
00116 
00117         case 1:
00118             ALU = (uint8_t)(state->_AC & B);
00119             break; // ANDA
00120 
00121         case 2:
00122             ALU = (uint8_t)(state->_AC | B);
00123             break; // ORA
00124 
00125         case 3:
00126             ALU = (uint8_t)(state->_AC ^ B);
00127             break; // XORA
00128 
00129         case 4:
00130             ALU = (uint8_t)(state->_AC + B);
00131             break; // ADDA
00132 
00133         case 5:
00134             ALU = (uint8_t) (state->_AC - B);
00135             break; // SUBA
00136 
00137         case 6:
00138             ALU = state->_AC;
00139             break; // ST
00140 
00141         case 7:
00142             ALU = (uint8_t) -state->_AC;
00143             break; // Bcc/JMP
00144     }
00145 
00146 
00147     // Output to where it needs to go
00148     if (!J)                         // If we are not jumping & not writing
00149     {
00150         switch (mod)
00151         {
00152             case 0: // To _AC
00153             case 1:
00154             case 2:
00155             case 3:
00156                 if (!W)
00157                 {
00158                     T->_AC = ALU;
00159                 }
00160                 break;
00161 
00162             case 4: // To X
00163                 T->X = ALU;
00164                 break;
00165 
00166             case 5: // To Y
00167                 T->Y = ALU;
00168                 break;
00169 
00170             case 6: // To OUT
00171             case 7: // To OUT
00172                 if (!W)
00173                 {
00174                     T->OUT = ALU;
00175 
00176                     int rising = (~state->OUT & ALU);
00177 
00178                     if ((rising & 0x40) > 0)      // hSync rising
00179                     {
00180                         T->OUTX = T->_AC;
00181                     }
00182                 }
00183                 break;
00184         }
00185     }
00186     
00187     if (incX)
00188     {
00189         T->X = (uint8_t)(state->X + 1); // Increment X
00190     }
00191     
00192     if (J)
00193     {
00194         if (mod != 0)
00195         {
00196             // Conditional branch within page
00197             int cond = (state->_AC >> 7) + 2 * (state->_AC == 0 ? 1 : 0);
00198             if ((mod & (1 << cond)) > 0) // 74153
00199             {
00200                 T->PC = (uint16_t)((state->PC & 0xff00) | B);
00201             }
00202             else
00203             {
00204                 T->PC = (uint16_t) (state->PC + 1); // Next instruction
00205             }
00206         }
00207         else
00208         {
00209             T->PC = (uint16_t)((state->Y << 8) | B); // Unconditional far jump
00210         }
00211     }
00212     else
00213     {
00214         T->PC = (uint16_t) (state->PC + 1); // Next instruction
00215     }
00216     
00217     //uint32_t t1 = micros();
00218     //uint32_t delta_t = t1 - t0;
00219     //Serial.printf( "Delta = %u\n", delta_t ); // this prints around 51 on my system.
00220     
00221 
00222     memcpy(state, T, sizeof(CPUState));     // 2us
00223     //states.CopyNewToCurrent();
00224     
00225     return states;
00226 }