Revising instruction decoder, jump history

This commit is contained in:
2020-08-07 21:24:09 -05:00
parent 0bf2d80a04
commit b7c2545ea7
6 changed files with 132 additions and 202 deletions
+56 -90
View File
@@ -27,13 +27,13 @@ static const int8_t LOOKUP_OPCODE[] = {
VUE_SHL_REG, 1, VUE_SHR_REG, 1, VUE_JMP , 1, VUE_SAR_REG, 1,
VUE_MUL , 1, VUE_DIV , 1, VUE_MULU , 1, VUE_DIVU , 1,
VUE_OR , 1, VUE_AND , 1, VUE_XOR , 1, VUE_NOT , 1,
VUE_MOV_IMM,-2, VUE_ADD_IMM,-2, VUE_SETF , 2, VUE_CMP_IMM,-2,
-VUE_MOV_IMM, 2,-VUE_ADD_IMM, 2, VUE_SETF , 2,-VUE_CMP_IMM, 2,
VUE_SHL_IMM, 2, VUE_SHR_IMM, 2, VUE_CLI , 2, VUE_SAR_IMM, 2,
VUE_TRAP , 2, VUE_RETI , 2, VUE_HALT , 2, VUE_ILLEGAL, 0,
VUE_LDSR , 2, VUE_STSR , 2, VUE_SEI , 2, BITSTRING , 2,
VUE_BCOND , 3, VUE_BCOND , 3, VUE_BCOND , 3, VUE_BCOND , 3,
VUE_BCOND , 3, VUE_BCOND , 3, VUE_BCOND , 3, VUE_BCOND , 3,
VUE_MOVEA ,-5, VUE_ADDI ,-5, VUE_JR , 4, VUE_JAL , 4,
-VUE_MOVEA , 5,-VUE_ADDI , 5, VUE_JR , 4, VUE_JAL , 4,
VUE_ORI , 5, VUE_ANDI , 5, VUE_XORI , 5, VUE_MOVHI , 5,
VUE_LD_B , 6, VUE_LD_H , 6, VUE_ILLEGAL, 0, VUE_LD_W , 6,
VUE_ST_B , 6, VUE_ST_H , 6, VUE_ILLEGAL, 0, VUE_ST_W , 6,
@@ -60,106 +60,70 @@ static const int8_t LOOKUP_FLOATENDO[] = {
/*****************************************************************************
* Instruction Functions *
* Module Functions *
*****************************************************************************/
/* Decoder for Format I */
static void cpuFormatI(VUE_INST *inst) {
inst->reg2 = inst->bits >> 21 & 31;
inst->reg1 = inst->bits >> 16 & 31;
}
/* Decoder for Format II */
static void cpuFormatII(VUE_INST *inst, int extend) {
int32_t imm = inst->bits >> 16 & 31;
inst->reg2 = inst->bits >> 21 & 31;
inst->imm = extend ? SIGN_EXTEND(5, imm) : imm;
}
/* Decoder for Format III */
static void cpuFormatIII(VUE_INST *inst) {
int32_t disp = inst->bits >> 16 & 0x1FF;
inst->opcode = 0x20;
inst->cond = inst->bits >> 25 & 15;
inst->disp = SIGN_EXTEND(9, disp);
}
/* Decoder for Format IV */
static void cpuFormatIV(VUE_INST *inst) {
int32_t disp = inst->bits & 0x3FFFFFF;
inst->disp = SIGN_EXTEND(26, disp);
}
/* Decoder for Format V */
static void cpuFormatV(VUE_INST *inst, int extend) {
int32_t imm = inst->bits & 0xFFFF;
inst->reg2 = inst->bits >> 21 & 31;
inst->reg1 = inst->bits >> 16 & 31;
inst->imm = extend ? SIGN_EXTEND(16, imm) : imm;
}
/* Decoder for Format VI */
static void cpuFormatVI(VUE_INST *inst) {
int32_t disp = inst->bits & 0xFFFF;
inst->reg2 = inst->bits >> 21 & 31;
inst->reg1 = inst->bits >> 16 & 31;
inst->disp = SIGN_EXTEND(16, disp);
}
/* Decoder for Format VII */
static void cpuFormatVII(VUE_INST *inst) {
inst->reg2 = inst->bits >> 21 & 31;
inst->reg1 = inst->bits >> 16 & 31;
inst->subopcode = inst->bits >> 10 & 63;
}
/* Decode an instruction from its binary encoding */
static void cpuDecode(VUE_INST *inst, int32_t bits) {
int extend;
int8_t extend; /* Sign-extend the immediate operand */
int32_t x; /* Working variable */
/* Configure instance fields */
inst->bits = bits;
inst->opcode = bits >> 26 & 63;
inst->id = inst->opcode << 1 | 1;
inst->format = LOOKUP_OPCODE[inst->id + 1];
inst->id = LOOKUP_OPCODE[inst->id];
/* Determine whether to sign-extend the immediate operand */
if ((extend = inst->format < 0))
inst->format = -inst->format;
/* Determine the size in bytes of the instruction */
inst->size = inst->format < 4 ? 2 : 4;
if (inst->size == 2)
inst->bits &= 0xFFFF0000;
x = inst->opcode << 1 | 1;
extend = LOOKUP_OPCODE[x];
inst->format = LOOKUP_OPCODE[x + 1];
inst->id = extend < 0 ? -extend : extend;
inst->size = inst->format < 4 ? 2 : 4;
/* Decode by format */
switch (inst->format) {
case 0: return; /* Nothing to do */
case 1: cpuFormatI (inst ); break;
case 2: cpuFormatII (inst, extend); break;
case 3: cpuFormatIII(inst ); break;
case 4: cpuFormatIV (inst ); break;
case 5: cpuFormatV (inst, extend); break;
case 6: cpuFormatVI (inst ); break;
case 7: cpuFormatVII(inst ); break;
case 0: return; /* Illegal opcode */
case 1:
inst->reg2 = bits >> 21 & 31;
inst->reg1 = bits >> 16 & 31;
break;
case 2:
x = bits >> 16 & 31;
inst->reg2 = bits >> 21 & 31;
inst->imm = extend < 0 ? SIGN_EXTEND(5, x) : x;
if (inst->id == BITSTRING)
inst->id = x >= 16 ? VUE_ILLEGAL : LOOKUP_BITSTRING[x];
break;
case 3:
x = bits >> 16 & 0x1FF;
inst->opcode = 0x20;
inst->cond = bits >> 25 & 15;
inst->disp = SIGN_EXTEND(9, x);
break;
case 4:
x = bits & 0x3FFFFFF;
inst->disp = SIGN_EXTEND(26, x);
break;
case 5:
x = bits & 0xFFFF;
inst->reg2 = bits >> 21 & 31;
inst->reg1 = bits >> 16 & 31;
inst->imm = extend < 0 ? SIGN_EXTEND(16, x) : x;
break;
case 6:
x = bits & 0xFFFF;
inst->reg2 = bits >> 21 & 31;
inst->reg1 = bits >> 16 & 31;
inst->disp = SIGN_EXTEND(16, x);
break;
case 7:
inst->reg2 = bits >> 21 & 31;
inst->reg1 = bits >> 16 & 31;
inst->subopcode = bits >> 10 & 63;
inst->id = inst->subopcode >= 16 ? VUE_ILLEGAL :
LOOKUP_FLOATENDO[inst->subopcode];
break;
}
/* Resolve final instruction ID by subopcode */
if (inst->id == FLOATENDO)
inst->id = inst->subopcode >= 16 ? VUE_ILLEGAL :
LOOKUP_FLOATENDO[inst->subopcode];
else if (inst->id == BITSTRING)
inst->id = inst->imm >= 16 ? VUE_ILLEGAL :
LOOKUP_BITSTRING[inst->imm ];
}
/*****************************************************************************
* Module Functions *
*****************************************************************************/
/* Read a system register */
static int32_t cpuGetSystemRegister(VUE *vue, int index) {
switch (index) {
@@ -267,7 +231,7 @@ static void cpuReset(VUE *vue) {
int x;
/* Configure instance fields */
vue->cpu.cycles = 0;
vue->cpu.cycles = 0; /* Duration of first fetch */
vue->cpu.fetch = 0;
vue->cpu.stage = CPU_FETCH;
@@ -277,10 +241,12 @@ static void cpuReset(VUE *vue) {
cpuSetSystemRegister(vue, x, 0, VUE_TRUE);
}
/* Configure jump history */
for (x = 0; x < 3; x++)
vue->cpu.jumpFrom[x] = vue->cpu.jumpTo[x] = 0xFFFFFFF0;
/* Configure registers */
vue->cpu.ecr_eicc = 0xFFF0;
vue->cpu.jumpFrom = 0xFFFFFFF0;
vue->cpu.jumpTo = 0xFFFFFFF0;
vue->cpu.pc = 0xFFFFFFF0;
vue->cpu.psw_np = 1;
}
+5 -5
View File
@@ -171,11 +171,11 @@ typedef struct {
/* CPU state */
struct {
uint32_t cycles; /* Cycles until next stage */
int fetch; /* Fetch unit index */
int32_t jumpFrom; /* Source PC of most recent jump */
int32_t jumpTo; /* Destination PC of most recent jump */
int stage; /* Current processing stage */
uint32_t cycles; /* Cycles until next stage */
int32_t jumpFrom[3]; /* Source PCs of most recent jumps */
int32_t jumpTo [3]; /* Destination PCs of most recent jumps */
int fetch; /* Fetch unit index */
int stage; /* Current processing stage */
/* Program registers */
int32_t program[32];
+5 -3
View File
@@ -43,10 +43,12 @@ int32_t vueGetRegister(VUE *vue, int index, vbool system) {
return 0;
/* Non-indexed registers */
if (system) switch (index) {
if (system && index < 0) switch (index) {
case VUE_JUMP_FROM:
return vue->cpu.jumpFrom[vue->cpu.psw_np ? 2 : vue->cpu.psw_ep];
case VUE_JUMP_TO :
return vue->cpu.jumpTo [vue->cpu.psw_np ? 2 : vue->cpu.psw_ep];
case VUE_PC : return vue->cpu.pc;
case VUE_JUMP_FROM: return vue->cpu.jumpFrom;
case VUE_JUMP_TO : return vue->cpu.jumpTo;
}
/* Indexed registers */