Mercurial > yaAGC
changeset 2:e452e83436c7
set up the instruction array with function pointers
author | Josef "Jeff" Sipek <jeffpc@josefsipek.net> |
---|---|
date | Thu, 31 May 2007 21:35:47 -0400 |
parents | 7071d144fa81 |
children | 5188cbc52a00 |
files | yaAGC/agc_engine.c yaAGC/agc_engine.h |
diffstat | 2 files changed, 213 insertions(+), 84 deletions(-) [+] |
line wrap: on
line diff
--- a/yaAGC/agc_engine.c Thu May 31 20:54:48 2007 -0400 +++ b/yaAGC/agc_engine.c Thu May 31 21:35:47 2007 -0400 @@ -328,28 +328,206 @@ // are taken into account. There are two arrays -- one for normal // instructions and one for "extracode" instructions. static const int InstructionTiming[32] = { - 0, 0, 0, 0, // Opcode = 00. - 1, 0, 0, 0, // Opcode = 01. - 2, 1, 1, 1, // Opcode = 02. - 1, 1, 1, 1, // Opcode = 03. - 1, 1, 1, 1, // Opcode = 04. - 1, 2, 1, 1, // Opcode = 05. - 1, 1, 1, 1, // Opcode = 06. - 1, 1, 1, 1 // Opcode = 07. }; // Note that the following table does not properly handle the EDRUPT or // BZF/BZMF instructions, and extra delay may need to be added specially for // those cases. The table figures 2 MCT for EDRUPT and 1 MCT for BZF/BZMF. static const int ExtracodeTiming[32] = { - 1, 1, 1, 1, // Opcode = 010. - 5, 0, 0, 0, // Opcode = 011. - 1, 1, 1, 1, // Opcode = 012. - 2, 2, 2, 2, // Opcode = 013. - 2, 2, 2, 2, // Opcode = 014. - 1, 1, 1, 1, // Opcode = 015. - 1, 0, 0, 0, // Opcode = 016. - 2, 2, 2, 2 // Opcode = 017. +}; + +// TC instruction (1 MCT). +void AGC_INST_TC(State_t *morestate) +{ + int ValueK = Address12; // Convert AGC numerical format to native CPU format. + if (ValueK == 3) // RELINT instruction. + State->AllowInterrupt = 1; + else if (ValueK == 4) // INHINT instruction. + State->AllowInterrupt = 0; + else if (ValueK == 6) // EXTEND instruction. + { + State->ExtraCode = 1; + // Normally, ExtraCode will be reset when agc_engine is finished. + // We inhibit that behavior with this flag. + morestate->KeepExtraCode = 1; + } + else + { + BacktraceAdd (State, 0); + if (ValueK != RegQ) // If not a RETURN instruction ... + c (RegQ) = 0177777 & NextZ; + NextZ = Address12; + } +} + +// CCS instruction (2 MCT). +void AGC_INST_CCS(State_t *state) +{ + // Figure out where the data is stored, and fetch it. + if (Address10 < REG16) + { + Operand16 = OverflowCorrected (0177777 & c (Address10)); + c (RegA) = odabs (0177777 & c (Address10)); + } + else // K!=accumulator. + { + WhereWord = FindMemoryWord (State, Address10); + Operand16 = *WhereWord & 077777; + // Compute the "diminished absolute value", and save in accumulator. + c (RegA) = dabs (Operand16); + } + AssignFromPointer (State, WhereWord, Operand16); + // Now perform the actual comparison and jump on the basis + // of it. There's no explanation I can find as to what + // happens if we're already at the end of the memory bank, + // so I'll just pretend that that can't happen. Note, + // by the way, that if the Operand is > +0, then NextZ + // is already correct, and in the other cases we need to + // increment it by 2 less because NextZ has already been + // incremented. + if (Address10 < REG16 + && ValueOverflowed (0177777 & c (Address10)) == AGC_P1) + NextZ += 0; + else if (Address10 < REG16 + && ValueOverflowed (0177777 & c (Address10)) == AGC_M1) + NextZ += 2; + else if (Operand16 == AGC_P0) + NextZ += 1; + else if (Operand16 == AGC_M0) + NextZ += 3; + else if (0 != (Operand16 & 040000)) + NextZ += 2; +} + +static const InstructionInfo_t Instructions[0177] = { + { .time = 0, .func = AGC_INST_TC }, // 0000 + { .time = 0, .func = AGC_INST_TC }, // 0001 + { .time = 0, .func = AGC_INST_TC }, // 0002 + { .time = 0, .func = AGC_INST_TC }, // 0003 + { .time = 0, .func = AGC_INST_TC }, // 0004 + { .time = 0, .func = AGC_INST_TC }, // 0005 + { .time = 0, .func = AGC_INST_TC }, // 0006 + { .time = 0, .func = AGC_INST_TC }, // 0007 + { .time = 1, .func = AGC_INST_CCS }, // 0010 + { .time = 1, .func = AGC_INST_CCS }, // 0011 + { .time = 0, .func = AGC_INST_TCF }, // 0012 + { .time = 0, .func = AGC_INST_TCF }, // 0013 + { .time = 0, .func = AGC_INST_TCF }, // 0014 + { .time = 0, .func = AGC_INST_TCF }, // 0015 + { .time = 0, .func = AGC_INST_TCF }, // 0016 + { .time = 0, .func = AGC_INST_TCF }, // 0017 + { .time = 2, .func = AGC_INST_DAS }, // 0020 + { .time = 2, .func = AGC_INST_DAS }, // 0021 + { .time = 1, .func = AGC_INST_LXCH }, // 0022 + { .time = 1, .func = AGC_INST_LXCH }, // 0023 + { .time = 1, .func = NULL }, // 0024 + { .time = 1, .func = NULL }, // 0025 + { .time = 1, .func = NULL }, // 0026 + { .time = 1, .func = NULL }, // 0027 + { .time = 1, .func = NULL }, // 0030 + { .time = 1, .func = NULL }, // 0031 + { .time = 1, .func = NULL }, // 0032 + { .time = 1, .func = NULL }, // 0033 + { .time = 1, .func = NULL }, // 0034 + { .time = 1, .func = NULL }, // 0035 + { .time = 1, .func = NULL }, // 0036 + { .time = 1, .func = NULL }, // 0037 + { .time = 1, .func = NULL }, // 0040 + { .time = 1, .func = NULL }, // 0041 + { .time = 1, .func = NULL }, // 0042 + { .time = 1, .func = NULL }, // 0043 + { .time = 1, .func = NULL }, // 0044 + { .time = 1, .func = NULL }, // 0045 + { .time = 1, .func = NULL }, // 0046 + { .time = 1, .func = NULL }, // 0047 + { .time = 1, .func = NULL }, // 0050 + { .time = 1, .func = NULL }, // 0051 + { .time = 2, .func = NULL }, // 0052 + { .time = 2, .func = NULL }, // 0053 + { .time = 1, .func = NULL }, // 0054 + { .time = 1, .func = NULL }, // 0055 + { .time = 1, .func = NULL }, // 0056 + { .time = 1, .func = NULL }, // 0057 + { .time = 1, .func = NULL }, // 0060 + { .time = 1, .func = NULL }, // 0061 + { .time = 1, .func = NULL }, // 0062 + { .time = 1, .func = NULL }, // 0063 + { .time = 1, .func = NULL }, // 0064 + { .time = 1, .func = NULL }, // 0065 + { .time = 1, .func = NULL }, // 0066 + { .time = 1, .func = NULL }, // 0067 + { .time = 1, .func = NULL }, // 0070 + { .time = 1, .func = NULL }, // 0071 + { .time = 1, .func = NULL }, // 0072 + { .time = 1, .func = NULL }, // 0073 + { .time = 1, .func = NULL }, // 0074 + { .time = 1, .func = NULL }, // 0075 + { .time = 1, .func = NULL }, // 0076 + { .time = 1, .func = NULL }, // 0077 + { .time = 1, .func = NULL }, // 0100 + { .time = 1, .func = NULL }, // 0101 + { .time = 1, .func = NULL }, // 0102 + { .time = 1, .func = NULL }, // 0103 + { .time = 1, .func = NULL }, // 0104 + { .time = 1, .func = NULL }, // 0105 + { .time = 1, .func = NULL }, // 0106 + { .time = 1, .func = NULL }, // 0107 + { .time = 5, .func = NULL }, // 0110 + { .time = 5, .func = NULL }, // 0111 + { .time = 0, .func = NULL }, // 0112 + { .time = 0, .func = NULL }, // 0113 + { .time = 0, .func = NULL }, // 0114 + { .time = 0, .func = NULL }, // 0115 + { .time = 0, .func = NULL }, // 0116 + { .time = 0, .func = NULL }, // 0117 + { .time = 1, .func = NULL }, // 0120 + { .time = 1, .func = NULL }, // 0121 + { .time = 1, .func = NULL }, // 0122 + { .time = 1, .func = NULL }, // 0123 + { .time = 1, .func = NULL }, // 0124 + { .time = 1, .func = NULL }, // 0125 + { .time = 1, .func = NULL }, // 0126 + { .time = 1, .func = NULL }, // 0127 + { .time = 2, .func = NULL }, // 0130 + { .time = 2, .func = NULL }, // 0131 + { .time = 2, .func = NULL }, // 0132 + { .time = 2, .func = NULL }, // 0133 + { .time = 2, .func = NULL }, // 0134 + { .time = 2, .func = NULL }, // 0135 + { .time = 2, .func = NULL }, // 0136 + { .time = 2, .func = NULL }, // 0137 + { .time = 2, .func = NULL }, // 0140 + { .time = 2, .func = NULL }, // 0141 + { .time = 2, .func = NULL }, // 0142 + { .time = 2, .func = NULL }, // 0143 + { .time = 2, .func = NULL }, // 0144 + { .time = 2, .func = NULL }, // 0145 + { .time = 2, .func = NULL }, // 0146 + { .time = 2, .func = NULL }, // 0147 + { .time = 1, .func = NULL }, // 0150 + { .time = 1, .func = NULL }, // 0151 + { .time = 1, .func = NULL }, // 0152 + { .time = 1, .func = NULL }, // 0153 + { .time = 1, .func = NULL }, // 0154 + { .time = 1, .func = NULL }, // 0155 + { .time = 1, .func = NULL }, // 0156 + { .time = 1, .func = NULL }, // 0157 + { .time = 1, .func = NULL }, // 0160 + { .time = 1, .func = NULL }, // 0161 + { .time = 0, .func = NULL }, // 0162 + { .time = 0, .func = NULL }, // 0163 + { .time = 0, .func = NULL }, // 0164 + { .time = 0, .func = NULL }, // 0165 + { .time = 0, .func = NULL }, // 0166 + { .time = 0, .func = NULL }, // 0167 + { .time = 2, .func = NULL }, // 0170 + { .time = 2, .func = NULL }, // 0171 + { .time = 2, .func = NULL }, // 0172 + { .time = 2, .func = NULL }, // 0173 + { .time = 2, .func = NULL }, // 0174 + { .time = 2, .func = NULL }, // 0175 + { .time = 2, .func = NULL }, // 0176 + { .time = 2, .func = NULL }, // 0177 }; // A way, for debugging, to disable interrupts. The 0th entry disables @@ -1492,7 +1670,6 @@ uint16_t ProgramCounter, Instruction, OpCode, QuarterCode, sExtraCode; int16_t *WhereWord; uint16_t Address12, Address10, Address9; - int ValueK, KeepExtraCode = 0; //int Operand; int16_t Operand16; int16_t CurrentEB, CurrentFB, CurrentBB; @@ -1918,75 +2095,16 @@ ExtendedOpcode = Instruction >> 9; //2; if (sExtraCode) ExtendedOpcode |= 0100; + + InstructionInfo_t *ii = &opcodetable[ExtendedOpcode]; + State_t temp_state = { + .KeepExtraCode = 0, + }; + + ii->func(temp_state); // execute! + switch (ExtendedOpcode) { - case 000: // TC. - case 001: - case 002: - case 003: - case 004: - case 005: - case 006: - case 007: - // TC instruction (1 MCT). - ValueK = Address12; // Convert AGC numerical format to native CPU format. - if (ValueK == 3) // RELINT instruction. - State->AllowInterrupt = 1; - else if (ValueK == 4) // INHINT instruction. - State->AllowInterrupt = 0; - else if (ValueK == 6) // EXTEND instruction. - { - State->ExtraCode = 1; - // Normally, ExtraCode will be reset when agc_engine is finished. - // We inhibit that behavior with this flag. - KeepExtraCode = 1; - } - else - { - BacktraceAdd (State, 0); - if (ValueK != RegQ) // If not a RETURN instruction ... - c (RegQ) = 0177777 & NextZ; - NextZ = Address12; - } - break; - case 010: // CCS. - case 011: - // CCS instruction (2 MCT). - // Figure out where the data is stored, and fetch it. - if (Address10 < REG16) - { - Operand16 = OverflowCorrected (0177777 & c (Address10)); - c (RegA) = odabs (0177777 & c (Address10)); - } - else // K!=accumulator. - { - WhereWord = FindMemoryWord (State, Address10); - Operand16 = *WhereWord & 077777; - // Compute the "diminished absolute value", and save in accumulator. - c (RegA) = dabs (Operand16); - } - AssignFromPointer (State, WhereWord, Operand16); - // Now perform the actual comparison and jump on the basis - // of it. There's no explanation I can find as to what - // happens if we're already at the end of the memory bank, - // so I'll just pretend that that can't happen. Note, - // by the way, that if the Operand is > +0, then NextZ - // is already correct, and in the other cases we need to - // increment it by 2 less because NextZ has already been - // incremented. - if (Address10 < REG16 - && ValueOverflowed (0177777 & c (Address10)) == AGC_P1) - NextZ += 0; - else if (Address10 < REG16 - && ValueOverflowed (0177777 & c (Address10)) == AGC_M1) - NextZ += 2; - else if (Operand16 == AGC_P0) - NextZ += 1; - else if (Operand16 == AGC_M0) - NextZ += 3; - else if (0 != (Operand16 & 040000)) - NextZ += 2; - break; case 012: // TCF. case 013: case 014:
--- a/yaAGC/agc_engine.h Thu May 31 20:54:48 2007 -0400 +++ b/yaAGC/agc_engine.h Thu May 31 21:35:47 2007 -0400 @@ -368,6 +368,17 @@ int ChannelMasks[256]; } Client_t; +typedef struct +{ + int KeepExtraCode; +} State_t; + +typedef struct +{ + int time; // number of extra machine cycles + void (*func)(State_t *); // function to service the instruction +} InstructionInfo_t; + #define DEFAULT_MAX_CLIENTS 10 #ifdef AGC_ENGINE_C