Implementing remaining CPU instructions except bit string
This commit is contained in:
parent
2d380460a6
commit
fa1728b424
269
src/core/cpu.c
269
src/core/cpu.c
|
@ -94,7 +94,7 @@ static void cpuBitwise(VUE *vue, int32_t result) {
|
|||
#define cpuFloat(x) ((double) *(float *)&(x))
|
||||
|
||||
/* Determine whether the floating-point operands are reserved values */
|
||||
static vbool cpuFloatReserved(VUE *vue) {
|
||||
static vbool cpuFloatReserved(VUE *vue, vbool left) {
|
||||
int32_t exponent; /* Operand exponent */
|
||||
int32_t operand; /* Current operand */
|
||||
int x; /* Iterator */
|
||||
|
@ -105,7 +105,7 @@ static vbool cpuFloatReserved(VUE *vue) {
|
|||
operands[1] = vue->cpu.program[vue->cpu.inst.reg1];
|
||||
|
||||
/* Process both operands */
|
||||
for (x = 0; x < 2; x++) {
|
||||
for (x = left ^ 1; x < 2; x++) {
|
||||
operand = operands[x];
|
||||
exponent = operand & 0x7F800000;
|
||||
|
||||
|
@ -125,8 +125,69 @@ static vbool cpuFloatReserved(VUE *vue) {
|
|||
return VUE_FALSE;
|
||||
}
|
||||
|
||||
/* Convert a floating short to word */
|
||||
static void cpuFloatConvert(VUE *vue, vbool round) {
|
||||
int32_t bits; /* Number of bits to shift */
|
||||
int32_t digits; /* Significant digits */
|
||||
int32_t result; /* Output value */
|
||||
int32_t sign; /* Sign of the result */
|
||||
|
||||
/* Reserved operand */
|
||||
if (cpuFloatReserved(vue, VUE_FALSE))
|
||||
return;
|
||||
|
||||
/* Parse the floating-point value */
|
||||
result = vue->cpu.program[vue->cpu.inst.reg1];
|
||||
bits = (result >> 23 & 0xFF) - 150;
|
||||
digits = (result & 0x007FFFFF) | 0x00800000;
|
||||
sign = result & 0x80000000;
|
||||
|
||||
/* Maximum negative word value */
|
||||
if (result == (int32_t) 0xCF000000) {
|
||||
digits = (int32_t) 0x80000000;
|
||||
sign = 0;
|
||||
}
|
||||
|
||||
/* Invalid operation (word overflow) */
|
||||
else if (bits >= 8) {
|
||||
vue->cpu.exception.code = 0xFF70;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Zero */
|
||||
else if ((result & 0x7FFFFFFF) == 0)
|
||||
digits = 0;
|
||||
|
||||
/* No significant digits are shifted out */
|
||||
else if (bits >= 0)
|
||||
digits <<= bits;
|
||||
|
||||
/* All significant digits are shifted out */
|
||||
else if (bits < -24) {
|
||||
vue->cpu.psw_fpr = 1; /* The implicit leading 1 was lost */
|
||||
digits = 0;
|
||||
}
|
||||
|
||||
/* Some significant digits are shifted out */
|
||||
else {
|
||||
result = 1 << (-bits - 1); /* Position of the "one half" bit */
|
||||
if (digits & ((result << 1) - 1)) /* The lost bits are not all zero */
|
||||
vue->cpu.psw_fpr = 1;
|
||||
if (round && (digits & result)) /* The "one half" bit is set */
|
||||
digits += result;
|
||||
digits = digits >> -bits;
|
||||
}
|
||||
|
||||
/* Common processing */
|
||||
result = sign ? -digits : digits;
|
||||
vue->cpu.program[vue->cpu.inst.reg2] = result;
|
||||
vue->cpu.psw_ov = 0;
|
||||
vue->cpu.psw_s = result >> 31 & 1;
|
||||
vue->cpu.psw_z = result ? 0 : 1;
|
||||
}
|
||||
|
||||
/* Floating-point result */
|
||||
static void cpuFloatResult(VUE *vue, double full) {
|
||||
static void cpuFloatResult(VUE *vue, vbool compare, double full) {
|
||||
int32_t bits = 0x7F7FFFFF; /* Binary representation of result */
|
||||
float result = *(float *)&bits; /* Operation output */
|
||||
|
||||
|
@ -148,12 +209,14 @@ static void cpuFloatResult(VUE *vue, double full) {
|
|||
vue->cpu.psw_fud = 1;
|
||||
}
|
||||
|
||||
/* Precision degradation */
|
||||
if (result != full)
|
||||
/* Operations other than compare */
|
||||
if (!compare) {
|
||||
vue->cpu.program[vue->cpu.inst.reg2] = bits;
|
||||
if (result != full) /* Precision degradation */
|
||||
vue->cpu.psw_fpr = 1;
|
||||
}
|
||||
|
||||
/* Common processing */
|
||||
vue->cpu.program[vue->cpu.inst.reg2] = bits;
|
||||
vue->cpu.psw_cy = vue->cpu.psw_s = bits >> 31 & 1;
|
||||
vue->cpu.psw_ov = 0;
|
||||
vue->cpu.psw_z = bits ? 0 : 1;
|
||||
|
@ -194,6 +257,25 @@ static int32_t cpuGetSystemRegister(VUE *vue, int32_t index) {
|
|||
return 1; /* Unreachable */
|
||||
}
|
||||
|
||||
/* Proxy for IN and LD */
|
||||
#define cpuIN_LD(vue, type) \
|
||||
if (!cpuRead(vue, vue->cpu.program[vue->cpu.inst.reg1] + \
|
||||
vue->cpu.inst.disp, type, -1)) \
|
||||
vue->cpu.program[vue->cpu.inst.reg2] = vue->cpu.access.value
|
||||
|
||||
/* Transfer program to another address */
|
||||
static void cpuJump(VUE *vue, int32_t address) {
|
||||
int level = vue->cpu.psw_np ? 2 : vue->cpu.psw_ep;
|
||||
vue->cpu.jumpFrom[level] = vue->cpu.pc;
|
||||
vue->cpu.jumpTo [level] = address;
|
||||
vue->cpu.pc = address - vue->cpu.inst.size;
|
||||
}
|
||||
|
||||
/* Proxy for OUT and ST */
|
||||
#define cpuOUT_ST(vue, type) \
|
||||
cpuWrite(vue, vue->cpu.program[vue->cpu.inst.reg1] + \
|
||||
vue->cpu.inst.disp, type, vue->cpu.program[vue->cpu.inst.reg2])
|
||||
|
||||
/* Perform a bus read */
|
||||
static vbool cpuRead(VUE *vue, int32_t address, int8_t type, int8_t fetch) {
|
||||
|
||||
|
@ -384,17 +466,6 @@ static vbool cpuWrite(VUE *vue, int32_t address, int8_t type, int32_t value) {
|
|||
return VUE_FALSE;
|
||||
}
|
||||
|
||||
/* Proxy for IN and LD */
|
||||
#define cpuIN_LD(vue, type) \
|
||||
if (!cpuRead(vue, vue->cpu.program[vue->cpu.inst.reg1] + \
|
||||
vue->cpu.inst.disp, type, -1)) \
|
||||
vue->cpu.program[vue->cpu.inst.reg2] = vue->cpu.access.value
|
||||
|
||||
/* Proxy for OUT and ST */
|
||||
#define cpuOUT_ST(vue, type) \
|
||||
cpuWrite(vue, vue->cpu.program[vue->cpu.inst.reg1] + \
|
||||
vue->cpu.inst.disp, type, vue->cpu.program[vue->cpu.inst.reg2])
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
|
@ -414,7 +485,7 @@ static vbool cpuWrite(VUE *vue, int32_t address, int8_t type, int32_t value) {
|
|||
|
||||
/* Add Floating Short */
|
||||
#define cpuADDF_S(vue) \
|
||||
if (!cpuFloatReserved(vue)) cpuFloatResult(vue, \
|
||||
if (!cpuFloatReserved(vue, VUE_TRUE)) cpuFloatResult(vue, VUE_FALSE, \
|
||||
cpuFloat(vue->cpu.program[vue->cpu.inst.reg2]) + \
|
||||
cpuFloat(vue->cpu.program[vue->cpu.inst.reg1]))
|
||||
|
||||
|
@ -435,10 +506,37 @@ static vbool cpuWrite(VUE *vue, int32_t address, int8_t type, int32_t value) {
|
|||
static void cpuBCOND(VUE *vue) {
|
||||
if (!cpuTestCondition(vue, vue->cpu.inst.cond & 15))
|
||||
return;
|
||||
vue->cpu.pc += vue->cpu.inst.disp - 2;
|
||||
vue->cpu.cycles = 2;
|
||||
cpuJump(vue, vue->cpu.pc + vue->cpu.inst.disp);
|
||||
}
|
||||
|
||||
/* Compare and Exchange Interlocked */
|
||||
static void cpuCAXI(VUE *vue) {
|
||||
int32_t address =
|
||||
vue->cpu.program[vue->cpu.inst.reg1] + vue->cpu.inst.disp;
|
||||
int32_t left = vue->cpu.program[vue->cpu.inst.reg2];
|
||||
int32_t lock; /* Value of lock word */
|
||||
|
||||
/* Retrieve the lock word */
|
||||
if (cpuRead(vue, address, VUE_S32, -1))
|
||||
return;
|
||||
lock = vue->cpu.access.value;
|
||||
|
||||
/* Compare and exchange */
|
||||
if (lock == left)
|
||||
vue->cpu.access.value = vue->cpu.program[30];
|
||||
if (cpuWrite(vue, address, VUE_S32, vue->cpu.access.value))
|
||||
return;
|
||||
|
||||
/* Update CPU state */
|
||||
cpuSubtract(vue, left, lock);
|
||||
vue->cpu.program[vue->cpu.inst.reg2] = lock;
|
||||
}
|
||||
|
||||
/* Clear Interrupt Disable Flag */
|
||||
#define cpuCLI(vue) \
|
||||
vue->cpu.psw_id = 0
|
||||
|
||||
/* Compare Immediate */
|
||||
#define cpuCMP_IMM(vue) \
|
||||
cpuSubtract(vue, \
|
||||
|
@ -450,6 +548,28 @@ static void cpuBCOND(VUE *vue) {
|
|||
vue->cpu.program[vue->cpu.inst.reg2], \
|
||||
vue->cpu.program[vue->cpu.inst.reg1])
|
||||
|
||||
/* Compare Floating Short */
|
||||
#define cpuCMPF_S(vue) \
|
||||
if (!cpuFloatReserved(vue, VUE_TRUE)) cpuFloatResult(vue, VUE_TRUE, \
|
||||
cpuFloat(vue->cpu.program[vue->cpu.inst.reg2]) - \
|
||||
cpuFloat(vue->cpu.program[vue->cpu.inst.reg1]))
|
||||
|
||||
/* Convert Short Floating to Word */
|
||||
#define cpuCVT_SW(vue) \
|
||||
cpuFloatConvert(vue, VUE_TRUE)
|
||||
|
||||
/* Convert Word Integer to Short */
|
||||
static void cpuCVT_WS(VUE *vue) {
|
||||
int32_t bits = vue->cpu.program[vue->cpu.inst.reg1];
|
||||
float result = (float) bits;
|
||||
vue->cpu.program[vue->cpu.inst.reg2] = *(int32_t *)&result;
|
||||
if (result != bits) /* Precision degradation */
|
||||
vue->cpu.psw_fpr = 1;
|
||||
vue->cpu.psw_cy = vue->cpu.psw_s = bits >> 31 & 1;
|
||||
vue->cpu.psw_ov = 0;
|
||||
vue->cpu.psw_z = bits ? 0 : 1;
|
||||
}
|
||||
|
||||
/* Divide */
|
||||
static void cpuDIV(VUE *vue) {
|
||||
int32_t left = vue->cpu.program[vue->cpu.inst.reg2];
|
||||
|
@ -481,6 +601,25 @@ static void cpuDIV(VUE *vue) {
|
|||
vue->cpu.psw_z = result ? 0 : 1;
|
||||
}
|
||||
|
||||
/* Divide Floating Short */
|
||||
static void cpuDIVF_S(VUE *vue) {
|
||||
int32_t left = vue->cpu.program[vue->cpu.inst.reg2];
|
||||
int32_t right = vue->cpu.program[vue->cpu.inst.reg1];
|
||||
|
||||
/* Reserved operand */
|
||||
if (cpuFloatReserved(vue, VUE_TRUE))
|
||||
return;
|
||||
|
||||
/* An exception has occurred */
|
||||
if (!right) {
|
||||
vue->cpu.exception.code = left ? 0xFF68 : 0xFF70;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Perform the operation */
|
||||
cpuFloatResult(vue, VUE_FALSE, cpuFloat(left) / cpuFloat(right));
|
||||
}
|
||||
|
||||
/* Divide Unsigned */
|
||||
static void cpuDIVU(VUE *vue) {
|
||||
uint32_t left = vue->cpu.program[vue->cpu.inst.reg2];
|
||||
|
@ -518,15 +657,15 @@ static void cpuDIVU(VUE *vue) {
|
|||
/* Jump and Link */
|
||||
#define cpuJAL(vue) \
|
||||
vue->cpu.program[31] = vue->cpu.pc + 4, \
|
||||
vue->cpu.pc += vue->cpu.inst.disp - 4
|
||||
cpuJump(vue, vue->cpu.pc + vue->cpu.inst.disp)
|
||||
|
||||
/* Jump Register */
|
||||
#define cpuJMP(vue) \
|
||||
vue->cpu.pc = vue->cpu.program[vue->cpu.inst.reg1] - 2
|
||||
cpuJump(vue, vue->cpu.program[vue->cpu.inst.reg1])
|
||||
|
||||
/* Jump Relative */
|
||||
#define cpuJR(vue) \
|
||||
vue->cpu.pc += vue->cpu.inst.disp - 4
|
||||
cpuJump(vue, vue->cpu.pc + vue->cpu.inst.disp)
|
||||
|
||||
/* Load Byte */
|
||||
#define cpuLD_B(vue) cpuIN_LD(vue, VUE_S8)
|
||||
|
@ -551,6 +690,12 @@ static void cpuDIVU(VUE *vue) {
|
|||
vue->cpu.program[vue->cpu.inst.reg2] = \
|
||||
vue->cpu.program[vue->cpu.inst.reg1]
|
||||
|
||||
/* Multiply Halfword */
|
||||
static void cpuMPYHW(VUE *vue) {
|
||||
int32_t right = vue->cpu.program[vue->cpu.inst.reg1];
|
||||
vue->cpu.program[vue->cpu.inst.reg2] *= SIGN_EXTEND(17, right);
|
||||
}
|
||||
|
||||
/* Multiply */
|
||||
static void cpuMUL(VUE *vue) {
|
||||
int64_t full = (int64_t) vue->cpu.program[vue->cpu.inst.reg2] *
|
||||
|
@ -563,6 +708,12 @@ static void cpuMUL(VUE *vue) {
|
|||
vue->cpu.psw_z = lower ? 0 : 1;
|
||||
}
|
||||
|
||||
/* Multiply Floating Short */
|
||||
#define cpuMULF_S(vue) \
|
||||
if (!cpuFloatReserved(vue, VUE_TRUE)) cpuFloatResult(vue, VUE_FALSE, \
|
||||
cpuFloat(vue->cpu.program[vue->cpu.inst.reg2]) * \
|
||||
cpuFloat(vue->cpu.program[vue->cpu.inst.reg1]))
|
||||
|
||||
/* Multiply Unsigned */
|
||||
static void cpuMULU(VUE *vue) {
|
||||
uint64_t full = (uint64_t)(uint32_t) vue->cpu.program[vue->cpu.inst.reg2] *
|
||||
|
@ -629,6 +780,15 @@ static void cpuRETI(VUE *vue) {
|
|||
cpuShiftArithmetic(vue, vue->cpu.program[vue->cpu.inst.reg2], \
|
||||
vue->cpu.program[vue->cpu.inst.reg1])
|
||||
|
||||
/* Set Interrupt Disable Flag */
|
||||
#define cpuSEI(vue) \
|
||||
vue->cpu.psw_id = 1
|
||||
|
||||
/* Set Flag Condition */
|
||||
#define cpuSETF(vue) \
|
||||
vue->cpu.program[vue->cpu.inst.reg2] = \
|
||||
cpuTestCondition(vue, vue->cpu.inst.imm & 15)
|
||||
|
||||
/* Shift Logical Left by Immediate */
|
||||
#define cpuSHL_IMM(vue) \
|
||||
cpuShiftLeft(vue, vue->cpu.program[vue->cpu.inst.reg2], \
|
||||
|
@ -649,6 +809,17 @@ static void cpuRETI(VUE *vue) {
|
|||
cpuShiftRight(vue, vue->cpu.program[vue->cpu.inst.reg2], \
|
||||
vue->cpu.program[vue->cpu.inst.reg1])
|
||||
|
||||
/* Reverse Bits in Word */
|
||||
static void cpuREV(VUE *vue) {
|
||||
int32_t value = vue->cpu.program[vue->cpu.inst.reg1];
|
||||
value = (value >> 16 & 0x0000FFFF) | value << 16;
|
||||
value = (value >> 8 & 0x00FF00FF) | (value << 8 & 0xFF00FF00);
|
||||
value = (value >> 4 & 0x0F0F0F0F) | (value << 4 & 0xF0F0F0F0);
|
||||
value = (value >> 2 & 0x33333333) | (value << 2 & 0xCCCCCCCC);
|
||||
value = (value >> 1 & 0x55555555) | (value << 1 & 0xAAAAAAAA);
|
||||
vue->cpu.program[vue->cpu.inst.reg2] = value;
|
||||
}
|
||||
|
||||
/* Store Byte */
|
||||
#define cpuST_B(vue) cpuOUT_ST(vue, VUE_S8)
|
||||
|
||||
|
@ -669,11 +840,35 @@ static void cpuRETI(VUE *vue) {
|
|||
vue->cpu.program[vue->cpu.inst.reg2], \
|
||||
vue->cpu.program[vue->cpu.inst.reg1])
|
||||
|
||||
/* Subtract Floating Short */
|
||||
#define cpuSUBF_S(vue) \
|
||||
if (!cpuFloatReserved(vue, VUE_TRUE)) cpuFloatResult(vue, VUE_FALSE, \
|
||||
cpuFloat(vue->cpu.program[vue->cpu.inst.reg2]) - \
|
||||
cpuFloat(vue->cpu.program[vue->cpu.inst.reg1]))
|
||||
|
||||
/* Trap */
|
||||
#define cpuTRAP(vue) \
|
||||
vue->cpu.exception.code = 0xFFA0 | (vue->cpu.inst.imm & 15), \
|
||||
vue->cpu.pc += 2
|
||||
|
||||
/* Truncate Short Floating to Word */
|
||||
#define cpuTRNC_SW(vue) \
|
||||
cpuFloatConvert(vue, VUE_FALSE)
|
||||
|
||||
/* Exchange Byte */
|
||||
static void cpuXB(VUE *vue) {
|
||||
int32_t value = vue->cpu.program[vue->cpu.inst.reg2];
|
||||
vue->cpu.program[vue->cpu.inst.reg2] =
|
||||
(value & 0xFFFF0000) | (value >> 8 & 0xFF) | (value & 0xFF) << 8;
|
||||
}
|
||||
|
||||
/* Exchange Halfword */
|
||||
static void cpuXH(VUE *vue) {
|
||||
int32_t value = vue->cpu.program[vue->cpu.inst.reg2];
|
||||
vue->cpu.program[vue->cpu.inst.reg2] =
|
||||
(value >> 16 & 0xFFFF) | value << 16;
|
||||
}
|
||||
|
||||
/* Exclusive Or */
|
||||
#define cpuXOR(vue) \
|
||||
cpuBitwise(vue, vue->cpu.program[vue->cpu.inst.reg2] ^ \
|
||||
|
@ -795,15 +990,15 @@ static vbool cpuExecute(VUE *vue) {
|
|||
case VUE_ANDI : cpuANDI (vue); break;
|
||||
/*case VUE_ANDNBSU: cpuANDNBSU(vue); break;*/
|
||||
case VUE_BCOND : cpuBCOND (vue); break;
|
||||
/*case VUE_CAXI : cpuCAXI (vue); break;*/
|
||||
/*case VUE_CLI : cpuCLI (vue); break;*/
|
||||
case VUE_CAXI : cpuCAXI (vue); break;
|
||||
case VUE_CLI : cpuCLI (vue); break;
|
||||
case VUE_CMP_IMM: cpuCMP_IMM(vue); break;
|
||||
case VUE_CMP_REG: cpuCMP_REG(vue); break;
|
||||
/*case VUE_CMPF_S : cpuCMPF_S (vue); break;*/
|
||||
/*case VUE_CVT_SW : cpuCVT_SW (vue); break;*/
|
||||
/*case VUE_CVT_WS : cpuCVT_WS (vue); break;*/
|
||||
case VUE_CMPF_S : cpuCMPF_S (vue); break;
|
||||
case VUE_CVT_SW : cpuCVT_SW (vue); break;
|
||||
case VUE_CVT_WS : cpuCVT_WS (vue); break;
|
||||
case VUE_DIV : cpuDIV (vue); break;
|
||||
/*case VUE_DIVF_S : cpuDIVF_S (vue); break;*/
|
||||
case VUE_DIVF_S : cpuDIVF_S (vue); break;
|
||||
case VUE_DIVU : cpuDIVU (vue); break;
|
||||
case VUE_HALT : cpuHALT (vue); break;
|
||||
case VUE_IN_B : cpuIN_B (vue); break;
|
||||
|
@ -821,9 +1016,9 @@ static vbool cpuExecute(VUE *vue) {
|
|||
/*case VUE_MOVBSU : cpuMOVBSU (vue); break;*/
|
||||
case VUE_MOVEA : cpuMOVEA (vue); break;
|
||||
case VUE_MOVHI : cpuMOVHI (vue); break;
|
||||
/*case VUE_MPYHW : cpuMPYHW (vue); break;*/
|
||||
case VUE_MPYHW : cpuMPYHW (vue); break;
|
||||
case VUE_MUL : cpuMUL (vue); break;
|
||||
/*case VUE_MULF_S : cpuMULF_S (vue); break;*/
|
||||
case VUE_MULF_S : cpuMULF_S (vue); break;
|
||||
case VUE_MULU : cpuMULU (vue); break;
|
||||
case VUE_NOT : cpuNOT (vue); break;
|
||||
/*case VUE_NOTBSU : cpuNOTBSU (vue); break;*/
|
||||
|
@ -835,15 +1030,15 @@ static vbool cpuExecute(VUE *vue) {
|
|||
case VUE_OUT_H : cpuOUT_H (vue); break;
|
||||
case VUE_OUT_W : cpuOUT_W (vue); break;
|
||||
case VUE_RETI : cpuRETI (vue); break;
|
||||
/*case VUE_REV : cpuREV (vue); break;*/
|
||||
case VUE_REV : cpuREV (vue); break;
|
||||
case VUE_SAR_IMM: cpuSAR_IMM(vue); break;
|
||||
case VUE_SAR_REG: cpuSAR_REG(vue); break;
|
||||
/*case VUE_SCH0BSD: cpuSCH0BSD(vue); break;*/
|
||||
/*case VUE_SCH0BSU: cpuSCH0BSU(vue); break;*/
|
||||
/*case VUE_SCH1BSD: cpuSCH1BSD(vue); break;*/
|
||||
/*case VUE_SCH1BSU: cpuSCH1BSU(vue); break;*/
|
||||
/*case VUE_SEI : cpuSEI (vue); break;*/
|
||||
/*case VUE_SETF : cpuSETF (vue); break;*/
|
||||
case VUE_SEI : cpuSEI (vue); break;
|
||||
case VUE_SETF : cpuSETF (vue); break;
|
||||
case VUE_SHL_IMM: cpuSHL_IMM(vue); break;
|
||||
case VUE_SHL_REG: cpuSHL_REG(vue); break;
|
||||
case VUE_SHR_IMM: cpuSHR_IMM(vue); break;
|
||||
|
@ -853,11 +1048,11 @@ static vbool cpuExecute(VUE *vue) {
|
|||
case VUE_ST_W : cpuST_W (vue); break;
|
||||
case VUE_STSR : cpuSTSR (vue); break;
|
||||
case VUE_SUB : cpuSUB (vue); break;
|
||||
/*case VUE_SUBF_S : cpuSUBF_S (vue); break;*/
|
||||
case VUE_SUBF_S : cpuSUBF_S (vue); break;
|
||||
case VUE_TRAP : cpuTRAP (vue); break;
|
||||
/*case VUE_TRNC_SW: cpuTRNC_SW(vue); break;*/
|
||||
/*case VUE_XB : cpuXB (vue); break;*/
|
||||
/*case VUE_XH : cpuXH (vue); break;*/
|
||||
case VUE_TRNC_SW: cpuTRNC_SW(vue); break;
|
||||
case VUE_XB : cpuXB (vue); break;
|
||||
case VUE_XH : cpuXH (vue); break;
|
||||
case VUE_XOR : cpuXOR (vue); break;
|
||||
/*case VUE_XORBSU : cpuXORBSU (vue); break;*/
|
||||
case VUE_XORI : cpuXORI (vue); break;
|
||||
|
|
|
@ -116,11 +116,11 @@ static void writeBuffer(uint8_t *data, uint32_t datlen, uint32_t address,
|
|||
#ifdef VUE_BIGENDIAN
|
||||
switch (type) {
|
||||
case VUE_S32:
|
||||
value = (value & 0xFFFF0000) >> 16 | value << 16;
|
||||
value = (value >> 16 & 0x0000FFFF) | value << 16;
|
||||
/* Fallthrough */
|
||||
case VUE_S16: /* Fallthrough */
|
||||
case VUE_U16:
|
||||
value = (value & 0xFF00FF00) >> 8 | (value & 0x00FF00FF) << 8;
|
||||
value = (value >> 8 & 0x00FF00FF) | (value << 8 & 0xFF00FF00);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -480,6 +480,7 @@ class Register {
|
|||
|
||||
// Event handlers
|
||||
ctrl.addActionListener(e->{
|
||||
parent.requestFocus();
|
||||
int val = value >> bit & mask;
|
||||
try { val = Integer.parseInt(ctrl.getText(), hex ? 16 : 10); }
|
||||
catch (Exception x) { }
|
||||
|
@ -501,9 +502,10 @@ class Register {
|
|||
|
||||
// Update the register value
|
||||
private void setValue(int value) {
|
||||
parent.requestFocus();
|
||||
parent.parent.parent.vue.setRegister(index, type != PROGRAM, value);
|
||||
refresh();
|
||||
if (index == VUE.PSW && type == VUE.PSW)
|
||||
parent.registers.get(VUE.PC).refresh();
|
||||
}
|
||||
|
||||
}
|
|
@ -14,10 +14,10 @@ class RegisterList extends JScrollPane {
|
|||
|
||||
// Package fields
|
||||
CPUWindow parent; // Containing CPU window
|
||||
HashMap<Integer, Register> registers; // Register items
|
||||
|
||||
// Private fields
|
||||
private boolean shown; // Component has been shown
|
||||
private HashMap<Integer, Register> registers; // Register items
|
||||
|
||||
// UI components
|
||||
private JPanel client; // Client area
|
||||
|
|
|
@ -350,15 +350,15 @@ this.cycles = 0; // DEBUG: Stop processing after execute
|
|||
case VUE.ANDI : ANDI (); break;
|
||||
//case VUE.ANDNBSU: ANDNBSU(); break;
|
||||
case VUE.BCOND : BCOND (); break;
|
||||
//case VUE.CAXI : CAXI (); break;
|
||||
//case VUE.CLI : CLI (); break;
|
||||
case VUE.CAXI : CAXI (); break;
|
||||
case VUE.CLI : CLI (); break;
|
||||
case VUE.CMP_IMM: CMP_IMM(); break;
|
||||
case VUE.CMP_REG: CMP_REG(); break;
|
||||
//case VUE.CMPF_S : CMPF_S (); break;
|
||||
//case VUE.CVT_SW : CVT_SW (); break;
|
||||
//case VUE.CVT_WS : CVT_WS (); break;
|
||||
case VUE.CMPF_S : CMPF_S (); break;
|
||||
case VUE.CVT_SW : CVT_SW (); break;
|
||||
case VUE.CVT_WS : CVT_WS (); break;
|
||||
case VUE.DIV : DIV (); break;
|
||||
//case VUE.DIVF_S : DIVF_S (); break;
|
||||
case VUE.DIVF_S : DIVF_S (); break;
|
||||
case VUE.DIVU : DIVU (); break;
|
||||
case VUE.HALT : HALT (); break;
|
||||
case VUE.IN_B : IN_B (); break;
|
||||
|
@ -376,9 +376,9 @@ this.cycles = 0; // DEBUG: Stop processing after execute
|
|||
//case VUE.MOVBSU : MOVBSU (); break;
|
||||
case VUE.MOVEA : MOVEA (); break;
|
||||
case VUE.MOVHI : MOVHI (); break;
|
||||
//case VUE.MPYHW : MPYHW (); break;
|
||||
case VUE.MPYHW : MPYHW (); break;
|
||||
case VUE.MUL : MUL (); break;
|
||||
//case VUE.MULF_S : MULF_S (); break;
|
||||
case VUE.MULF_S : MULF_S (); break;
|
||||
case VUE.MULU : MULU (); break;
|
||||
case VUE.NOT : NOT (); break;
|
||||
//case VUE.NOTBSU : NOTBSU (); break;
|
||||
|
@ -390,29 +390,29 @@ this.cycles = 0; // DEBUG: Stop processing after execute
|
|||
case VUE.OUT_H : OUT_H (); break;
|
||||
case VUE.OUT_W : OUT_W (); break;
|
||||
case VUE.RETI : RETI (); break;
|
||||
//case VUE.REV : REV (); break;
|
||||
//case VUE.SAR_IMM: SAR_IMM(); break;
|
||||
//case VUE.SAR_REG: SAR_REG(); break;
|
||||
case VUE.REV : REV (); break;
|
||||
case VUE.SAR_IMM: SAR_IMM(); break;
|
||||
case VUE.SAR_REG: SAR_REG(); break;
|
||||
//case VUE.SCH0BSD: SCH0BSD(); break;
|
||||
//case VUE.SCH0BSU: SCH0BSU(); break;
|
||||
//case VUE.SCH1BSD: SCH1BSD(); break;
|
||||
//case VUE.SCH1BSU: SCH1BSU(); break;
|
||||
//case VUE.SEI : SEI (); break;
|
||||
//case VUE.SETF : SETF (); break;
|
||||
//case VUE.SHL_IMM: SHL_IMM(); break;
|
||||
//case VUE.SHL_REG: SHL_REG(); break;
|
||||
//case VUE.SHR_IMM: SHR_IMM(); break;
|
||||
//case VUE.SHR_REG: SHR_REG(); break;
|
||||
case VUE.SEI : SEI (); break;
|
||||
case VUE.SETF : SETF (); break;
|
||||
case VUE.SHL_IMM: SHL_IMM(); break;
|
||||
case VUE.SHL_REG: SHL_REG(); break;
|
||||
case VUE.SHR_IMM: SHR_IMM(); break;
|
||||
case VUE.SHR_REG: SHR_REG(); break;
|
||||
case VUE.ST_B : ST_B (); break;
|
||||
case VUE.ST_H : ST_H (); break;
|
||||
case VUE.ST_W : ST_W (); break;
|
||||
case VUE.STSR : STSR (); break;
|
||||
case VUE.SUB : SUB (); break;
|
||||
//case VUE.SUBF_S : SUBF_S (); break;
|
||||
case VUE.SUBF_S : SUBF_S (); break;
|
||||
case VUE.TRAP : TRAP (); break;
|
||||
//case VUE.TRNC_SW: TRNC_SW(); break;
|
||||
//case VUE.XB : XB (); break;
|
||||
//case VUE.XH : XH (); break;
|
||||
case VUE.TRNC_SW: TRNC_SW(); break;
|
||||
case VUE.XB : XB (); break;
|
||||
case VUE.XH : XH (); break;
|
||||
case VUE.XOR : XOR (); break;
|
||||
//case VUE.XORBSU : XORBSU (); break;
|
||||
case VUE.XORI : XORI (); break;
|
||||
|
@ -567,9 +567,37 @@ this.cycles = 0; // DEBUG: Stop processing after execute
|
|||
psw_z = result == 0 ? 1 : 0;
|
||||
}
|
||||
|
||||
// Convert a floating short to word
|
||||
private void floatConvert(boolean round) {
|
||||
|
||||
// Reserved operand
|
||||
if (floatReserved(false))
|
||||
return;
|
||||
|
||||
// Determine the value to convert
|
||||
float value = Float.intBitsToFloat(program[inst.reg1]);
|
||||
value = (float) (round ? Math.round(value) :
|
||||
value < 0 ? Math.ceil(value) : Math.floor(value));
|
||||
|
||||
// Invalid operation
|
||||
if (value > 0x7FFFFFFF || value < 0x80000000) {
|
||||
exception.code = 0xFF70;
|
||||
return;
|
||||
}
|
||||
|
||||
// Common processing
|
||||
int result = (int) value;
|
||||
if (result != value) // Precision degradation
|
||||
psw_fpr = 1;
|
||||
program[inst.reg2] = result;
|
||||
psw_ov = 0;
|
||||
psw_s = result >>> 31;
|
||||
psw_z = result == 0 ? 1 : 0;
|
||||
}
|
||||
|
||||
// Determine whether the floating-point operands are reserved values
|
||||
private boolean floatReserved() {
|
||||
for (int x = 0; x < 2; x++) {
|
||||
private boolean floatReserved(boolean left) {
|
||||
for (int x = left ? 0 : 1; x < 2; x++) {
|
||||
int operand = program[x == 0 ? inst.reg2 : inst.reg1];
|
||||
int exponent = operand & 0x7F800000;
|
||||
|
||||
|
@ -588,7 +616,7 @@ this.cycles = 0; // DEBUG: Stop processing after execute
|
|||
}
|
||||
|
||||
// Floating-point result
|
||||
private void floatResult(double full) {
|
||||
private void floatResult(boolean compare, double full) {
|
||||
|
||||
// Overflow
|
||||
if (full > Float.MAX_VALUE || full < -Float.MAX_VALUE) {
|
||||
|
@ -608,12 +636,14 @@ this.cycles = 0; // DEBUG: Stop processing after execute
|
|||
psw_fud = 1;
|
||||
}
|
||||
|
||||
// Precision degradation
|
||||
if (result != full)
|
||||
// Operations other than compare
|
||||
if (!compare) {
|
||||
program[inst.reg2] = bits;
|
||||
if (result != full) // Precision degradation
|
||||
psw_fpr = 1;
|
||||
}
|
||||
|
||||
// Common processing
|
||||
program[inst.reg2] = bits;
|
||||
psw_cy = psw_s = bits >>> 31;
|
||||
psw_ov = 0;
|
||||
psw_z = bits == 0 ? 1 : 0;
|
||||
|
@ -625,6 +655,14 @@ this.cycles = 0; // DEBUG: Stop processing after execute
|
|||
program[inst.reg2] = access.value;
|
||||
}
|
||||
|
||||
// Transfer program to another address
|
||||
private void jump(int address) {
|
||||
int level = psw_np != 0 ? 2 : psw_ep;
|
||||
jumpFrom[level] = pc;
|
||||
jumpTo [level] = address;
|
||||
pc = address - inst.size;
|
||||
}
|
||||
|
||||
// Proxy for OUT and ST
|
||||
private void OUT_ST(int type) {
|
||||
write(program[inst.reg1] + inst.disp, type, program[inst.reg2]);
|
||||
|
@ -679,7 +717,7 @@ this.cycles = 0; // DEBUG: Stop processing after execute
|
|||
|
||||
// Add Floating Short
|
||||
private void ADDF_S() {
|
||||
if (!floatReserved()) floatResult(
|
||||
if (!floatReserved(true)) floatResult(false,
|
||||
(double) Float.intBitsToFloat(program[inst.reg2]) +
|
||||
(double) Float.intBitsToFloat(program[inst.reg1]));
|
||||
}
|
||||
|
@ -703,8 +741,34 @@ this.cycles = 0; // DEBUG: Stop processing after execute
|
|||
private void BCOND() {
|
||||
if (testCondition(inst.cond) == 0)
|
||||
return;
|
||||
pc += inst.disp - 2;
|
||||
cycles = 2;
|
||||
jump(pc + inst.disp);
|
||||
}
|
||||
|
||||
// Compare and Exchange Interlocked
|
||||
private void CAXI() {
|
||||
int address = program[inst.reg1] + inst.disp;
|
||||
int left = program[inst.reg2];
|
||||
|
||||
// Retrieve the lock word
|
||||
if (read(address, VUE.S32, -1))
|
||||
return;
|
||||
int lock = access.value;
|
||||
|
||||
// Compare and exchange
|
||||
if (lock == left)
|
||||
access.value = program[30];
|
||||
if (write(address, VUE.S32, access.value))
|
||||
return;
|
||||
|
||||
// Update CPU state
|
||||
subtract(left, lock);
|
||||
program[inst.reg2] = lock;
|
||||
}
|
||||
|
||||
// Clear Interrupt Disable Flag
|
||||
private void CLI() {
|
||||
psw_id = 0;
|
||||
}
|
||||
|
||||
// Compare Immediate
|
||||
|
@ -717,6 +781,30 @@ this.cycles = 0; // DEBUG: Stop processing after execute
|
|||
subtract(program[inst.reg2], program[inst.reg1]);
|
||||
}
|
||||
|
||||
// Compare Floating Short
|
||||
private void CMPF_S() {
|
||||
if (!floatReserved(true)) floatResult(true,
|
||||
(double) Float.intBitsToFloat(program[inst.reg2]) -
|
||||
(double) Float.intBitsToFloat(program[inst.reg1]));
|
||||
}
|
||||
|
||||
// Convert Short Floating to Word
|
||||
private void CVT_SW() {
|
||||
floatConvert(true);
|
||||
}
|
||||
|
||||
// Convert Word Integer to Short
|
||||
private void CVT_WS() {
|
||||
int bits = program[inst.reg1];
|
||||
float result = (float) bits;
|
||||
program[inst.reg2] = Float.floatToRawIntBits(result);
|
||||
if (result != bits) // Precision degradation
|
||||
psw_fpr = 1;
|
||||
psw_cy = psw_s = bits >>> 31;
|
||||
psw_ov = 0;
|
||||
psw_z = bits == 0 ? 1 : 0;
|
||||
}
|
||||
|
||||
// Divide
|
||||
private void DIV() {
|
||||
int left = program[inst.reg2];
|
||||
|
@ -747,6 +835,27 @@ this.cycles = 0; // DEBUG: Stop processing after execute
|
|||
psw_z = result == 0 ? 1 : 0;
|
||||
}
|
||||
|
||||
// Divide Floating Short
|
||||
private void DIVF_S() {
|
||||
int left = program[inst.reg2];
|
||||
int right = program[inst.reg1];
|
||||
|
||||
// Reserved operand
|
||||
if (floatReserved(true))
|
||||
return;
|
||||
|
||||
// An exception has occurred
|
||||
if (right == 0) {
|
||||
exception.code = left == 0 ? 0xFF70 : 0xFF68;
|
||||
return;
|
||||
}
|
||||
|
||||
// Perform the operation
|
||||
floatResult(false,
|
||||
(double) Float.intBitsToFloat(left) /
|
||||
(double) Float.intBitsToFloat(right));
|
||||
}
|
||||
|
||||
// Divide Unsigned
|
||||
private void DIVU() {
|
||||
long left = program[inst.reg2] & 0xFFFFFFFFL;
|
||||
|
@ -791,17 +900,17 @@ this.cycles = 0; // DEBUG: Stop processing after execute
|
|||
// Jump and Link
|
||||
private void JAL() {
|
||||
program[31] = pc + 4;
|
||||
pc += inst.disp - 4;
|
||||
jump(pc + inst.disp);
|
||||
}
|
||||
|
||||
// Jump Register
|
||||
private void JMP() {
|
||||
pc = program[inst.reg1] - 2;
|
||||
jump(program[inst.reg1]);
|
||||
}
|
||||
|
||||
// Jump Relative
|
||||
private void JR() {
|
||||
pc += inst.disp - 4;
|
||||
jump(pc + inst.disp);
|
||||
}
|
||||
|
||||
// Load Byte
|
||||
|
@ -844,6 +953,11 @@ this.cycles = 0; // DEBUG: Stop processing after execute
|
|||
program[inst.reg2] = program[inst.reg1] + (inst.imm << 16);
|
||||
}
|
||||
|
||||
// Multiply Halfword
|
||||
private void MPYHW() {
|
||||
program[inst.reg2] *= program[inst.reg1] << 15 >> 15;
|
||||
}
|
||||
|
||||
// Multiply
|
||||
private void MUL() {
|
||||
long full = (long) program[inst.reg2] * (long) program[inst.reg1];
|
||||
|
@ -855,6 +969,13 @@ this.cycles = 0; // DEBUG: Stop processing after execute
|
|||
psw_z = result == 0 ? 1 : 0;
|
||||
}
|
||||
|
||||
// Multiply Floating Short
|
||||
private void MULF_S() {
|
||||
if (!floatReserved(true)) floatResult(false,
|
||||
(double) Float.intBitsToFloat(program[inst.reg2]) *
|
||||
(double) Float.intBitsToFloat(program[inst.reg1]));
|
||||
}
|
||||
|
||||
// Multiply Unsigned
|
||||
private void MULU() {
|
||||
long full = (program[inst.reg2] & 0xFFFFFFFFL) *
|
||||
|
@ -908,6 +1029,17 @@ this.cycles = 0; // DEBUG: Stop processing after execute
|
|||
}
|
||||
}
|
||||
|
||||
// Reverse Bits in Word
|
||||
private void REV() {
|
||||
int value = program[inst.reg1];
|
||||
value = value >> 16 & 0x0000FFFF | value << 16;
|
||||
value = value >> 8 & 0x00FF00FF | value << 8 & 0xFF00FF00;
|
||||
value = value >> 4 & 0x0F0F0F0F | value << 4 & 0xF0F0F0F0;
|
||||
value = value >> 2 & 0x33333333 | value << 2 & 0xCCCCCCCC;
|
||||
value = value >> 1 & 0x55555555 | value << 1 & 0xAAAAAAAA;
|
||||
program[inst.reg2] = value;
|
||||
}
|
||||
|
||||
// Shift Arithmetic Right by Immediate
|
||||
private void SAR_IMM() {
|
||||
shiftArithmetic(program[inst.reg2], inst.imm);
|
||||
|
@ -918,6 +1050,16 @@ this.cycles = 0; // DEBUG: Stop processing after execute
|
|||
shiftArithmetic(program[inst.reg2], program[inst.reg1]);
|
||||
}
|
||||
|
||||
// Set Interrupt Disable Flag
|
||||
private void SEI() {
|
||||
psw_id = 1;
|
||||
}
|
||||
|
||||
// Set Flag Condition
|
||||
private void SETF() {
|
||||
program[inst.reg2] = testCondition(inst.imm & 15);
|
||||
}
|
||||
|
||||
// Shift Logical Left by Immediate
|
||||
private void SHL_IMM() {
|
||||
shiftLeft(program[inst.reg2], inst.imm);
|
||||
|
@ -963,12 +1105,37 @@ this.cycles = 0; // DEBUG: Stop processing after execute
|
|||
program[inst.reg2] = subtract(program[inst.reg2], program[inst.reg1]);
|
||||
}
|
||||
|
||||
// Subtract Floating Short
|
||||
private void SUBF_S() {
|
||||
if (!floatReserved(true)) floatResult(false,
|
||||
(double) Float.intBitsToFloat(program[inst.reg2]) -
|
||||
(double) Float.intBitsToFloat(program[inst.reg1]));
|
||||
}
|
||||
|
||||
// Trap
|
||||
private void TRAP() {
|
||||
exception.code = 0xFFA0 | inst.imm & 15;
|
||||
pc += 2;
|
||||
}
|
||||
|
||||
// Truncate Short Floating to Word
|
||||
private void TRNC_SW() {
|
||||
floatConvert(false);
|
||||
}
|
||||
|
||||
// Exchange Byte
|
||||
private void XB() {
|
||||
int value = program[inst.reg2];
|
||||
program[inst.reg2] = value & 0xFFFF0000 |
|
||||
value >> 8 & 0xFF | (value & 0xFF) << 8;
|
||||
}
|
||||
|
||||
// Exchange Halfword
|
||||
private void XH() {
|
||||
int value = program[inst.reg2];
|
||||
program[inst.reg2] = value >> 16 & 0xFFFF | value << 16;
|
||||
}
|
||||
|
||||
// Exclusive Or
|
||||
private void XOR() {
|
||||
bitwise(program[inst.reg2] ^ program[inst.reg1]);
|
||||
|
|
Loading…
Reference in New Issue