Revising instruction decoder, jump history
This commit is contained in:
parent
0bf2d80a04
commit
b7c2545ea7
144
src/core/cpu.c
144
src/core/cpu.c
|
@ -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_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_MUL , 1, VUE_DIV , 1, VUE_MULU , 1, VUE_DIVU , 1,
|
||||||
VUE_OR , 1, VUE_AND , 1, VUE_XOR , 1, VUE_NOT , 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_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_TRAP , 2, VUE_RETI , 2, VUE_HALT , 2, VUE_ILLEGAL, 0,
|
||||||
VUE_LDSR , 2, VUE_STSR , 2, VUE_SEI , 2, BITSTRING , 2,
|
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_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_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_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,
|
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 */
|
/* Decode an instruction from its binary encoding */
|
||||||
static void cpuDecode(VUE_INST *inst, int32_t bits) {
|
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 */
|
/* Configure instance fields */
|
||||||
inst->bits = bits;
|
inst->bits = bits;
|
||||||
inst->opcode = bits >> 26 & 63;
|
inst->opcode = bits >> 26 & 63;
|
||||||
inst->id = inst->opcode << 1 | 1;
|
x = inst->opcode << 1 | 1;
|
||||||
inst->format = LOOKUP_OPCODE[inst->id + 1];
|
extend = LOOKUP_OPCODE[x];
|
||||||
inst->id = LOOKUP_OPCODE[inst->id];
|
inst->format = LOOKUP_OPCODE[x + 1];
|
||||||
|
inst->id = extend < 0 ? -extend : extend;
|
||||||
/* 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;
|
inst->size = inst->format < 4 ? 2 : 4;
|
||||||
if (inst->size == 2)
|
|
||||||
inst->bits &= 0xFFFF0000;
|
|
||||||
|
|
||||||
/* Decode by format */
|
/* Decode by format */
|
||||||
switch (inst->format) {
|
switch (inst->format) {
|
||||||
case 0: return; /* Nothing to do */
|
case 0: return; /* Illegal opcode */
|
||||||
case 1: cpuFormatI (inst ); break;
|
case 1:
|
||||||
case 2: cpuFormatII (inst, extend); break;
|
inst->reg2 = bits >> 21 & 31;
|
||||||
case 3: cpuFormatIII(inst ); break;
|
inst->reg1 = bits >> 16 & 31;
|
||||||
case 4: cpuFormatIV (inst ); break;
|
break;
|
||||||
case 5: cpuFormatV (inst, extend); break;
|
case 2:
|
||||||
case 6: cpuFormatVI (inst ); break;
|
x = bits >> 16 & 31;
|
||||||
case 7: cpuFormatVII(inst ); break;
|
inst->reg2 = bits >> 21 & 31;
|
||||||
}
|
inst->imm = extend < 0 ? SIGN_EXTEND(5, x) : x;
|
||||||
|
if (inst->id == BITSTRING)
|
||||||
/* Resolve final instruction ID by subopcode */
|
inst->id = x >= 16 ? VUE_ILLEGAL : LOOKUP_BITSTRING[x];
|
||||||
if (inst->id == FLOATENDO)
|
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 :
|
inst->id = inst->subopcode >= 16 ? VUE_ILLEGAL :
|
||||||
LOOKUP_FLOATENDO[inst->subopcode];
|
LOOKUP_FLOATENDO[inst->subopcode];
|
||||||
else if (inst->id == BITSTRING)
|
break;
|
||||||
inst->id = inst->imm >= 16 ? VUE_ILLEGAL :
|
}
|
||||||
LOOKUP_BITSTRING[inst->imm ];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************
|
|
||||||
* Module Functions *
|
|
||||||
*****************************************************************************/
|
|
||||||
|
|
||||||
/* Read a system register */
|
/* Read a system register */
|
||||||
static int32_t cpuGetSystemRegister(VUE *vue, int index) {
|
static int32_t cpuGetSystemRegister(VUE *vue, int index) {
|
||||||
switch (index) {
|
switch (index) {
|
||||||
|
@ -267,7 +231,7 @@ static void cpuReset(VUE *vue) {
|
||||||
int x;
|
int x;
|
||||||
|
|
||||||
/* Configure instance fields */
|
/* Configure instance fields */
|
||||||
vue->cpu.cycles = 0;
|
vue->cpu.cycles = 0; /* Duration of first fetch */
|
||||||
vue->cpu.fetch = 0;
|
vue->cpu.fetch = 0;
|
||||||
vue->cpu.stage = CPU_FETCH;
|
vue->cpu.stage = CPU_FETCH;
|
||||||
|
|
||||||
|
@ -277,10 +241,12 @@ static void cpuReset(VUE *vue) {
|
||||||
cpuSetSystemRegister(vue, x, 0, VUE_TRUE);
|
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 */
|
/* Configure registers */
|
||||||
vue->cpu.ecr_eicc = 0xFFF0;
|
vue->cpu.ecr_eicc = 0xFFF0;
|
||||||
vue->cpu.jumpFrom = 0xFFFFFFF0;
|
|
||||||
vue->cpu.jumpTo = 0xFFFFFFF0;
|
|
||||||
vue->cpu.pc = 0xFFFFFFF0;
|
vue->cpu.pc = 0xFFFFFFF0;
|
||||||
vue->cpu.psw_np = 1;
|
vue->cpu.psw_np = 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -172,9 +172,9 @@ typedef struct {
|
||||||
/* CPU state */
|
/* CPU state */
|
||||||
struct {
|
struct {
|
||||||
uint32_t cycles; /* Cycles until next 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 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 */
|
int stage; /* Current processing stage */
|
||||||
|
|
||||||
/* Program registers */
|
/* Program registers */
|
||||||
|
|
|
@ -43,10 +43,12 @@ int32_t vueGetRegister(VUE *vue, int index, vbool system) {
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Non-indexed registers */
|
/* 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_PC : return vue->cpu.pc;
|
||||||
case VUE_JUMP_FROM: return vue->cpu.jumpFrom;
|
|
||||||
case VUE_JUMP_TO : return vue->cpu.jumpTo;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Indexed registers */
|
/* Indexed registers */
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
package vue;
|
package vue;
|
||||||
|
|
||||||
|
// Java imports
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
// CPU state
|
// CPU state
|
||||||
class CPU {
|
class CPU {
|
||||||
|
|
||||||
|
@ -9,8 +12,8 @@ class CPU {
|
||||||
// Package fields
|
// Package fields
|
||||||
int cycles; // Cycles until next stage
|
int cycles; // Cycles until next stage
|
||||||
int fetch; // Fetch unit index
|
int fetch; // Fetch unit index
|
||||||
int jumpFrom; // Source PC of most recent jump
|
int[] jumpFrom; // Source PCs of most recent jumps
|
||||||
int jumpTo; // Destination PC of most recent jump
|
int[] jumpTo; // Destination PCs of most recent jumps
|
||||||
int stage; // Current processing stage
|
int stage; // Current processing stage
|
||||||
|
|
||||||
// Program registers
|
// Program registers
|
||||||
|
@ -80,6 +83,8 @@ class CPU {
|
||||||
|
|
||||||
// Default constructor
|
// Default constructor
|
||||||
CPU(JavaVUE vue) {
|
CPU(JavaVUE vue) {
|
||||||
|
jumpFrom = new int[3];
|
||||||
|
jumpTo = new int[3];
|
||||||
program = new int[32];
|
program = new int[32];
|
||||||
this.vue = vue;
|
this.vue = vue;
|
||||||
}
|
}
|
||||||
|
@ -115,20 +120,7 @@ class CPU {
|
||||||
|
|
||||||
// Remaining cases to encourage tableswitch
|
// Remaining cases to encourage tableswitch
|
||||||
case 8: case 9: case 10: case 11: case 12: case 13: case 14:
|
case 8: case 9: case 10: case 11: case 12: case 13: case 14:
|
||||||
case 15: case 16: case 17: case 18: case 19: case 20: case 21: // Configure instance fields
|
case 15: case 16: case 17: case 18: case 19: case 20: case 21:
|
||||||
cycles = 0;
|
|
||||||
fetch = 0;
|
|
||||||
stage = FETCH;
|
|
||||||
|
|
||||||
// Reset program counter
|
|
||||||
pc = 0xFFFFFFF0;
|
|
||||||
|
|
||||||
// Clear all registers (hardware only sets ECR, PC and PSW)
|
|
||||||
for (int x = 0; x < 32; x++) {
|
|
||||||
program[x] = 0;
|
|
||||||
setSystemRegister(x, 0, true);
|
|
||||||
}
|
|
||||||
case 22: case 23: case 26: case 27: case 28:
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return 1; // Unreachable
|
return 1; // Unreachable
|
||||||
|
@ -138,7 +130,7 @@ class CPU {
|
||||||
void reset() {
|
void reset() {
|
||||||
|
|
||||||
// Configure instance fields
|
// Configure instance fields
|
||||||
cycles = 0;
|
cycles = 0; // Duration of first fetch
|
||||||
fetch = 0;
|
fetch = 0;
|
||||||
stage = FETCH;
|
stage = FETCH;
|
||||||
|
|
||||||
|
@ -148,10 +140,12 @@ class CPU {
|
||||||
setSystemRegister(x, 0, true);
|
setSystemRegister(x, 0, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Configure jump histories
|
||||||
|
Arrays.fill(jumpFrom, 0xFFFFFFF0);
|
||||||
|
Arrays.fill(jumpTo , 0xFFFFFFF0);
|
||||||
|
|
||||||
// Configure registers
|
// Configure registers
|
||||||
ecr_eicc = 0xFFF0;
|
ecr_eicc = 0xFFF0;
|
||||||
jumpFrom = 0xFFFFFFF0;
|
|
||||||
jumpTo = 0xFFFFFFF0;
|
|
||||||
pc = 0xFFFFFFF0;
|
pc = 0xFFFFFFF0;
|
||||||
psw_np = 1;
|
psw_np = 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,13 +32,13 @@ public class Instruction {
|
||||||
VUE.SHL_REG, 1, VUE.SHR_REG, 1, VUE.JMP , 1, VUE.SAR_REG, 1,
|
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.MUL , 1, VUE.DIV , 1, VUE.MULU , 1, VUE.DIVU , 1,
|
||||||
VUE.OR , 1, VUE.AND , 1, VUE.XOR , 1, VUE.NOT , 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.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.TRAP , 2, VUE.RETI , 2, VUE.HALT , 2, VUE.ILLEGAL, 0,
|
||||||
VUE.LDSR , 2, VUE.STSR , 2, VUE.SEI , 2, BITSTRING , 2,
|
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.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.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.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,
|
VUE.ST_B , 6, VUE.ST_H , 6, VUE.ILLEGAL, 0, VUE.ST_W , 6,
|
||||||
|
@ -90,92 +90,58 @@ public class Instruction {
|
||||||
|
|
||||||
// Decode an instruction from its binary encoding
|
// Decode an instruction from its binary encoding
|
||||||
public void decode(int bits) {
|
public void decode(int bits) {
|
||||||
|
byte extend; // Sign-extend the immediate operand
|
||||||
|
int x; // Working variable
|
||||||
|
|
||||||
// Configure instance fields
|
// Configure instance fields
|
||||||
this.bits = bits;
|
this.bits = bits;
|
||||||
opcode = bits >> 26 & 63;
|
opcode = bits >> 26 & 63;
|
||||||
id = opcode << 1 | 1;
|
x = opcode << 1 | 1;
|
||||||
format = LOOKUP_OPCODE[id + 1];
|
extend = LOOKUP_OPCODE[x];
|
||||||
id = LOOKUP_OPCODE[id];
|
format = LOOKUP_OPCODE[x + 1];
|
||||||
|
id = extend < 0 ? -extend : extend;
|
||||||
// Determine whether to sign-extend the immediate operand
|
|
||||||
boolean extend = format < 0;
|
|
||||||
if (extend)
|
|
||||||
format = -format;
|
|
||||||
|
|
||||||
// Determine the size in bytes of the instruction
|
|
||||||
size = format < 4 ? 2 : 4;
|
size = format < 4 ? 2 : 4;
|
||||||
if (size == 2)
|
|
||||||
this.bits &= 0xFFFF0000;
|
|
||||||
|
|
||||||
// Decode by format
|
// Decode by format
|
||||||
switch (format) {
|
switch (format) {
|
||||||
case 0: return; // Nothing to do
|
case 0: return; // Illegal opcode
|
||||||
case 1: formatI ( ); break;
|
case 1:
|
||||||
case 2: formatII (extend); break;
|
|
||||||
case 3: formatIII( ); break;
|
|
||||||
case 4: formatIV ( ); break;
|
|
||||||
case 5: formatV (extend); break;
|
|
||||||
case 6: formatVI ( ); break;
|
|
||||||
case 7: formatVII( ); break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Resolve final instruction ID by subopcode
|
|
||||||
if (id == FLOATENDO)
|
|
||||||
id = subopcode >= 16 ? VUE.ILLEGAL : LOOKUP_FLOATENDO[subopcode];
|
|
||||||
else if (id == BITSTRING)
|
|
||||||
id = imm >= 16 ? VUE.ILLEGAL : LOOKUP_BITSTRING[imm ];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
|
||||||
// Private Methods //
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
// Decoder for Format I
|
|
||||||
private void formatI() {
|
|
||||||
reg2 = bits >> 21 & 31;
|
reg2 = bits >> 21 & 31;
|
||||||
reg1 = bits >> 16 & 31;
|
reg1 = bits >> 16 & 31;
|
||||||
}
|
break;
|
||||||
|
case 2:
|
||||||
// Decoder for Format II
|
|
||||||
private void formatII(boolean extend) {
|
|
||||||
reg2 = bits >> 21 & 31;
|
reg2 = bits >> 21 & 31;
|
||||||
imm = extend ? bits << 11 >> 27 : bits >> 16 & 31;
|
imm = extend < 0 ? bits << 11 >> 27 : bits >> 16 & 31;
|
||||||
}
|
if (id == BITSTRING)
|
||||||
|
id = imm >= 16 ? VUE.ILLEGAL : LOOKUP_BITSTRING[imm];
|
||||||
// Decoder for Format III
|
break;
|
||||||
private void formatIII() {
|
case 3:
|
||||||
opcode = 0x20;
|
opcode = 0x20;
|
||||||
cond = bits >> 25 & 15;
|
cond = bits >> 25 & 15;
|
||||||
disp = bits << 7 >> 25;
|
disp = bits << 7 >> 23;
|
||||||
}
|
break;
|
||||||
|
case 4:
|
||||||
// Decoder for Format IV
|
|
||||||
private void formatIV() {
|
|
||||||
disp = bits << 6 >> 6;
|
disp = bits << 6 >> 6;
|
||||||
}
|
break;
|
||||||
|
case 5:
|
||||||
// Decoder for Format V
|
|
||||||
private void formatV(boolean extend) {
|
|
||||||
reg2 = bits >> 21 & 31;
|
reg2 = bits >> 21 & 31;
|
||||||
reg1 = bits >> 16 & 31;
|
reg1 = bits >> 16 & 31;
|
||||||
imm = extend ? bits << 16 >> 16 : bits & 0x0000FFFF;
|
imm = extend < 0 ? bits << 16 >> 16 : bits & 0xFFFF;
|
||||||
}
|
break;
|
||||||
|
case 6:
|
||||||
// Decoder for Format VI
|
|
||||||
private void formatVI() {
|
|
||||||
reg2 = bits >> 21 & 31;
|
reg2 = bits >> 21 & 31;
|
||||||
reg1 = bits >> 16 & 31;
|
reg1 = bits >> 16 & 31;
|
||||||
disp = bits << 16 >> 16;
|
disp = bits << 16 >> 16;
|
||||||
}
|
break;
|
||||||
|
case 7:
|
||||||
// Decoder for Format VII
|
|
||||||
private void formatVII() {
|
|
||||||
reg2 = bits >> 21 & 31;
|
reg2 = bits >> 21 & 31;
|
||||||
reg1 = bits >> 16 & 31;
|
reg1 = bits >> 16 & 31;
|
||||||
subopcode = bits >> 10 & 63;
|
subopcode = bits >> 10 & 63;
|
||||||
|
id = subopcode >= 16 ? VUE.ILLEGAL :
|
||||||
|
LOOKUP_FLOATENDO[subopcode];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,9 +43,11 @@ class JavaVUE extends VUE {
|
||||||
|
|
||||||
// Non-indexed registers
|
// Non-indexed registers
|
||||||
if (system) switch (index) {
|
if (system) switch (index) {
|
||||||
|
case VUE.JUMP_FROM: return
|
||||||
|
cpu.jumpFrom[cpu.psw_np != 0 ? 2 : cpu.psw_ep];
|
||||||
|
case VUE.JUMP_TO : return
|
||||||
|
cpu.jumpTo [cpu.psw_np != 0 ? 2 : cpu.psw_ep];
|
||||||
case VUE.PC : return cpu.pc;
|
case VUE.PC : return cpu.pc;
|
||||||
case VUE.JUMP_FROM: return cpu.jumpFrom;
|
|
||||||
case VUE.JUMP_TO : return cpu.jumpTo;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Indexed registers
|
// Indexed registers
|
||||||
|
|
Loading…
Reference in New Issue