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