Implement floating-point instructions
This commit is contained in:
parent
2e0af6b109
commit
5f563e6cac
471
core/cpu.c
471
core/cpu.c
|
@ -426,6 +426,23 @@ static void cpuAdvance(VB *sim, uint32_t clocks) {
|
|||
sim->cpu.step = 0;
|
||||
}
|
||||
|
||||
/* Interpret floating short bits as word integer bits */
|
||||
static int32_t cpuFloatToWord(float x) {
|
||||
return *(int32_t *) &x;
|
||||
}
|
||||
|
||||
/* Raise an exception */
|
||||
static int cpuThrow(VB *sim, uint16_t cause) {
|
||||
sim->cpu.exception = cause;
|
||||
sim->cpu.operation = CPU_EXCEPTION;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Interpret word integer bits as floating short bits */
|
||||
static float cpuWordToFloat(int32_t x) {
|
||||
return *(float *) &x;
|
||||
}
|
||||
|
||||
/* Retrieve the value of a system register */
|
||||
static uint32_t cpuGetSystemRegister(VB *sim, int index) {
|
||||
switch (index) {
|
||||
|
@ -545,6 +562,56 @@ static int cpuCondition(VB *sim, int id) {
|
|||
return !cpuCondition(sim, id & 7);
|
||||
}
|
||||
|
||||
/* Floating-point common processing */
|
||||
static int cpuFloatCommon(VB *sim, double value, int32_t *bits) {
|
||||
float floatVal;
|
||||
|
||||
/* Overflow */
|
||||
if (value < -FLT_MAX || value > FLT_MAX) {
|
||||
/* TODO: CPU does give reg2 some value */
|
||||
sim->cpu.psw.fov = 1;
|
||||
cpuThrow(sim, 0xFF64);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Underflow */
|
||||
if (value < 0 ? value > -FLT_MIN : value < FLT_MIN) {
|
||||
sim->cpu.psw.fud = 1;
|
||||
floatVal = 0;
|
||||
/* TODO: Can this produce negative zero? */
|
||||
}
|
||||
|
||||
/* Regular conversion */
|
||||
else floatVal = value;
|
||||
|
||||
/* Precision degradation */
|
||||
if (floatVal != value)
|
||||
sim->cpu.psw.fpr = 1;
|
||||
|
||||
/* Update state */
|
||||
*bits = cpuFloatToWord(floatVal);
|
||||
sim->cpu.psw.cy = floatVal < 0;
|
||||
sim->cpu.psw.ov = 0;
|
||||
sim->cpu.psw.s = floatVal < 0;
|
||||
sim->cpu.psw.z = floatVal == 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Test whether a floating-point register value is a reserved operand */
|
||||
static int cpuFloatReservedOne(int32_t bits) {
|
||||
int32_t e = bits >> 23 & 0xFF;
|
||||
return e ? (bits & 0x7FFFFFFF) != 0 : e == 0xFF;
|
||||
}
|
||||
|
||||
/* Test whether floating-point register values are reserved operands */
|
||||
static int cpuFloatReserved(VB *sim, int32_t a, int32_t b) {
|
||||
if (!(cpuFloatReservedOne(a) || cpuFloatReservedOne(b)))
|
||||
return 0;
|
||||
sim->cpu.psw.fro = 1;
|
||||
cpuThrow(sim, 0xFF60);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Jump and branch common processing */
|
||||
static void cpuJump(VB *sim, uint32_t address) {
|
||||
sim->cpu.clocks += cpuClocks(3);
|
||||
|
@ -667,46 +734,55 @@ static int cpuST_OUT(VB *sim, int type) {
|
|||
/************************** Instruction Operations ***************************/
|
||||
|
||||
/* ADD immediate */
|
||||
static int cpuADDImm(VB *sim) {
|
||||
static void cpuADDImm(VB *sim) {
|
||||
cpuSetReg2(sim, cpuAdd(sim, cpuGetImm5S(sim)));
|
||||
cpuAdvance(sim, cpuClocks(1));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ADD register */
|
||||
static int cpuADDReg(VB *sim) {
|
||||
static void cpuADDReg(VB *sim) {
|
||||
cpuSetReg2(sim, cpuAdd(sim, cpuGetReg1(sim)));
|
||||
cpuAdvance(sim, cpuClocks(1));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ADDF.S */
|
||||
static void cpuADDF_S(VB *sim) {
|
||||
int32_t a = cpuGetReg2(sim);
|
||||
int32_t b = cpuGetReg1(sim);
|
||||
double c; /* Result */
|
||||
int32_t d; /* Float bits for result */
|
||||
if (cpuFloatReserved(sim, a, b))
|
||||
return;
|
||||
c = (double) cpuWordToFloat(a) + cpuWordToFloat(b);
|
||||
if (cpuFloatCommon(sim, c, &d))
|
||||
return;
|
||||
cpuSetReg2(sim, d);
|
||||
cpuAdvance(sim, cpuClocks(28)); /* TODO: Research */
|
||||
}
|
||||
|
||||
/* ADDI */
|
||||
static int cpuADDI(VB *sim) {
|
||||
static void cpuADDI(VB *sim) {
|
||||
cpuSetReg2(sim, cpuAdd(sim, cpuGetImm16S(sim)));
|
||||
cpuAdvance(sim, cpuClocks(1));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* AND */
|
||||
static int cpuAND(VB *sim) {
|
||||
static void cpuAND(VB *sim) {
|
||||
cpuSetReg2(sim, cpuBitwise(sim, cpuGetReg2(sim) & cpuGetReg1(sim)));
|
||||
cpuAdvance(sim, cpuClocks(1));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ANDI */
|
||||
static int cpuANDI(VB *sim) {
|
||||
static void cpuANDI(VB *sim) {
|
||||
cpuSetReg2(sim, cpuBitwise(sim, cpuGetReg2(sim) & cpuGetImm16U(sim)));
|
||||
cpuAdvance(sim, cpuClocks(1));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* BCOND */
|
||||
static int cpuBCOND(VB *sim) {
|
||||
static void cpuBCOND(VB *sim) {
|
||||
if (cpuCondition(sim, cpuGetCond(sim)))
|
||||
cpuJump(sim, sim->cpu.pc + cpuGetDisp9(sim));
|
||||
else cpuAdvance(sim, cpuClocks(1));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* CAXI */
|
||||
|
@ -749,28 +825,78 @@ static int cpuCAXI(VB *sim) {
|
|||
}
|
||||
|
||||
/* CLI */
|
||||
static int cpuCLI(VB *sim) {
|
||||
static void cpuCLI(VB *sim) {
|
||||
sim->cpu.psw.id = 0;
|
||||
cpuAdvance(sim, cpuClocks(12));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* CMP immediate */
|
||||
static int cpuCMPImm(VB *sim) {
|
||||
static void cpuCMPImm(VB *sim) {
|
||||
cpuSubtract(sim, cpuGetImm5S(sim));
|
||||
cpuAdvance(sim, cpuClocks(1));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* CMP register */
|
||||
static int cpuCMPReg(VB *sim) {
|
||||
static void cpuCMPReg(VB *sim) {
|
||||
cpuSubtract(sim, cpuGetReg1(sim));
|
||||
cpuAdvance(sim, cpuClocks(1));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* CMPF.S */
|
||||
static void cpuCMPF_S(VB *sim) {
|
||||
int32_t a = cpuGetReg2(sim);
|
||||
int32_t b = cpuGetReg1(sim);
|
||||
double c; /* Result */
|
||||
int32_t d; /* Float bits for result */
|
||||
if (cpuFloatReserved(sim, a, b))
|
||||
return;
|
||||
c = (double) cpuWordToFloat(a) - cpuWordToFloat(b);
|
||||
if (cpuFloatCommon(sim, c, &d))
|
||||
return;
|
||||
cpuAdvance(sim, cpuClocks(10)); /* TODO: Research */
|
||||
}
|
||||
|
||||
/* CVT.SW */
|
||||
static void cpuCVT_SW(VB *sim) {
|
||||
double f;
|
||||
int32_t w = cpuGetReg1(sim);
|
||||
if (cpuFloatReservedOne(w)) {
|
||||
cpuThrow(sim, 0xFF60);
|
||||
return;
|
||||
}
|
||||
f = cpuWordToFloat(w);
|
||||
if (f <= -2147483648.5 || f >= 2147483647.5) {
|
||||
sim->cpu.psw.fiv = 1;
|
||||
cpuThrow(sim, 0xFF70);
|
||||
return;
|
||||
}
|
||||
w = f < 0 ? f - 0.5 : f + 0.5;
|
||||
cpuSetReg2(sim, w);
|
||||
if (w != f)
|
||||
sim->cpu.psw.fpr = 1;
|
||||
sim->cpu.psw.ov = 0;
|
||||
sim->cpu.psw.s = w < 0;
|
||||
sim->cpu.psw.z = w == 0;
|
||||
cpuAdvance(sim, cpuClocks(14)); /* TODO: Research */
|
||||
}
|
||||
|
||||
/* CVT.WS */
|
||||
static void cpuCVT_WS(VB *sim) {
|
||||
int32_t w = cpuGetReg1(sim);
|
||||
float f = w;
|
||||
if (f != w)
|
||||
sim->cpu.psw.fpr = 1;
|
||||
w = cpuFloatToWord(f);
|
||||
cpuSetReg2(sim, w);
|
||||
sim->cpu.psw.cy = w < 0;
|
||||
sim->cpu.psw.ov = 0;
|
||||
sim->cpu.psw.s = w < 0;
|
||||
sim->cpu.psw.z = w == 0;
|
||||
cpuAdvance(sim, cpuClocks(16)); /* TODO: Research */
|
||||
}
|
||||
|
||||
/* DIV */
|
||||
static int cpuDIV(VB *sim) {
|
||||
static void cpuDIV(VB *sim) {
|
||||
int32_t a; /* Dividend */
|
||||
int32_t b; /* Divisor */
|
||||
int32_t c; /* Remainder */
|
||||
|
@ -783,10 +909,8 @@ static int cpuDIV(VB *sim) {
|
|||
/* Zero division */
|
||||
b = cpuGetReg1(sim);
|
||||
if (b == 0) {
|
||||
sim->cpu.exception = 0xFF80;
|
||||
sim->cpu.operation = CPU_EXCEPTION;
|
||||
/* TODO: Research clocks */
|
||||
return 0;
|
||||
cpuThrow(sim, 0xFF80);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Compute results */
|
||||
|
@ -831,11 +955,29 @@ static int cpuDIV(VB *sim) {
|
|||
sim->cpu.psw.s = d < 0;
|
||||
sim->cpu.psw.z = d == 0;
|
||||
cpuAdvance(sim, cpuClocks(38));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* DIVF.S */
|
||||
static void cpuDIVF_S(VB *sim) {
|
||||
int32_t a = cpuGetReg2(sim);
|
||||
int32_t b = cpuGetReg1(sim);
|
||||
double c; /* Result */
|
||||
int32_t d; /* Float bits for result */
|
||||
if (cpuFloatReserved(sim, a, b))
|
||||
return;
|
||||
if ((b & 0x7FFFFFFF) == 0) {
|
||||
cpuThrow(sim, (a & 0x7FFFFFFF) == 0 ? 0xFF70 : 0xFF68);
|
||||
return;
|
||||
}
|
||||
c = (double) cpuWordToFloat(a) / cpuWordToFloat(b);
|
||||
if (cpuFloatCommon(sim, c, &d))
|
||||
return;
|
||||
cpuSetReg2(sim, d);
|
||||
cpuAdvance(sim, cpuClocks(44));
|
||||
}
|
||||
|
||||
/* DIVU */
|
||||
static int cpuDIVU(VB *sim) {
|
||||
static void cpuDIVU(VB *sim) {
|
||||
uint32_t a; /* Dividend */
|
||||
uint32_t b; /* Divisor */
|
||||
int32_t c; /* Remainder */
|
||||
|
@ -844,10 +986,8 @@ static int cpuDIVU(VB *sim) {
|
|||
/* Zero division */
|
||||
b = cpuGetReg1(sim);
|
||||
if (b == 0) {
|
||||
sim->cpu.exception = 0xFF80;
|
||||
sim->cpu.operation = CPU_EXCEPTION;
|
||||
/* TODO: Research clocks */
|
||||
return 0;
|
||||
cpuThrow(sim, 0xFF80);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Compute results */
|
||||
|
@ -862,14 +1002,12 @@ static int cpuDIVU(VB *sim) {
|
|||
sim->cpu.psw.s = d < 0;
|
||||
sim->cpu.psw.z = d == 0;
|
||||
cpuAdvance(sim, cpuClocks(36));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* HALT */
|
||||
static int cpuHALT(VB *sim) {
|
||||
static void cpuHALT(VB *sim) {
|
||||
sim->cpu.operation = CPU_HALTING;
|
||||
/* TODO: Research clocks */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* IN.B */
|
||||
|
@ -888,22 +1026,19 @@ static int cpuIN_W(VB *sim) {
|
|||
}
|
||||
|
||||
/* JAL */
|
||||
static int cpuJAL(VB *sim) {
|
||||
static void cpuJAL(VB *sim) {
|
||||
sim->cpu.program[31] = sim->cpu.pc + 4;
|
||||
cpuJump(sim, sim->cpu.pc + cpuGetDisp26(sim));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* JMP */
|
||||
static int cpuJMP(VB *sim) {
|
||||
static void cpuJMP(VB *sim) {
|
||||
cpuJump(sim, cpuGetReg1(sim));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* JR */
|
||||
static int cpuJR(VB *sim) {
|
||||
static void cpuJR(VB *sim) {
|
||||
cpuJump(sim, sim->cpu.pc + cpuGetDisp26(sim));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* LD.B */
|
||||
|
@ -922,48 +1057,42 @@ static int cpuLD_W(VB *sim) {
|
|||
}
|
||||
|
||||
/* LDSR */
|
||||
static int cpuLDSR(VB *sim) {
|
||||
static void cpuLDSR(VB *sim) {
|
||||
cpuSetSystemRegister(sim, cpuGetImm5U(sim), cpuGetReg2(sim), 0);
|
||||
cpuAdvance(sim, cpuClocks(8));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* MOV immediate */
|
||||
static int cpuMOVImm(VB *sim) {
|
||||
static void cpuMOVImm(VB *sim) {
|
||||
cpuSetReg2(sim, cpuGetImm5S(sim));
|
||||
cpuAdvance(sim, cpuClocks(1));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* MOV register */
|
||||
static int cpuMOVReg(VB *sim) {
|
||||
static void cpuMOVReg(VB *sim) {
|
||||
cpuSetReg2(sim, cpuGetReg1(sim));
|
||||
cpuAdvance(sim, cpuClocks(1));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* MOVEA */
|
||||
static int cpuMOVEA(VB *sim) {
|
||||
static void cpuMOVEA(VB *sim) {
|
||||
cpuSetReg2(sim, cpuGetReg1(sim) + cpuGetImm16S(sim));
|
||||
cpuAdvance(sim, cpuClocks(1));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* MOVHI */
|
||||
static int cpuMOVHI(VB *sim) {
|
||||
static void cpuMOVHI(VB *sim) {
|
||||
cpuSetReg2(sim, cpuGetReg1(sim) + (cpuGetImm16U(sim) << 16));
|
||||
cpuAdvance(sim, cpuClocks(1));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* MPYHW */
|
||||
static int cpuMPYHW(VB *sim) {
|
||||
static void cpuMPYHW(VB *sim) {
|
||||
cpuSetReg2(sim, cpuGetReg2(sim) * SignExtend(cpuGetReg1(sim), 17));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* MUL */
|
||||
static int cpuMUL(VB *sim) {
|
||||
static void cpuMUL(VB *sim) {
|
||||
int64_t a = cpuGetReg2(sim);
|
||||
int64_t b = cpuGetReg1(sim);
|
||||
int64_t c = a * b;
|
||||
|
@ -974,11 +1103,25 @@ static int cpuMUL(VB *sim) {
|
|||
sim->cpu.psw.s = d < 0;
|
||||
sim->cpu.psw.z = d == 0;
|
||||
cpuAdvance(sim, 13);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* MULF.S */
|
||||
static void cpuMULF_S(VB *sim) {
|
||||
int32_t a = cpuGetReg2(sim);
|
||||
int32_t b = cpuGetReg1(sim);
|
||||
double c; /* Result */
|
||||
int32_t d; /* Float bits for result */
|
||||
if (cpuFloatReserved(sim, a, b))
|
||||
return;
|
||||
c = (double) cpuWordToFloat(a) * cpuWordToFloat(b);
|
||||
if (cpuFloatCommon(sim, c, &d))
|
||||
return;
|
||||
cpuSetReg2(sim, d);
|
||||
cpuAdvance(sim, cpuClocks(30)); /* TODO: Research */
|
||||
}
|
||||
|
||||
/* MULU */
|
||||
static int cpuMULU(VB *sim) {
|
||||
static void cpuMULU(VB *sim) {
|
||||
uint64_t a = cpuGetReg2(sim);
|
||||
uint64_t b = cpuGetReg1(sim);
|
||||
int64_t c = a * b;
|
||||
|
@ -989,28 +1132,24 @@ static int cpuMULU(VB *sim) {
|
|||
sim->cpu.psw.s = d < 0;
|
||||
sim->cpu.psw.z = d == 0;
|
||||
cpuAdvance(sim, 13);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* NOT */
|
||||
static int cpuNOT(VB *sim) {
|
||||
static void cpuNOT(VB *sim) {
|
||||
cpuSetReg2(sim, cpuBitwise(sim, ~cpuGetReg1(sim)));
|
||||
cpuAdvance(sim, cpuClocks(1));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* OR */
|
||||
static int cpuOR(VB *sim) {
|
||||
static void cpuOR(VB *sim) {
|
||||
cpuSetReg2(sim, cpuBitwise(sim, cpuGetReg2(sim) | cpuGetReg1(sim)));
|
||||
cpuAdvance(sim, cpuClocks(1));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ORI */
|
||||
static int cpuORI(VB *sim) {
|
||||
static void cpuORI(VB *sim) {
|
||||
cpuSetReg2(sim, cpuBitwise(sim, cpuGetReg2(sim) | cpuGetImm16U(sim)));
|
||||
cpuAdvance(sim, cpuClocks(1));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* OUT.B */
|
||||
|
@ -1029,7 +1168,7 @@ static int cpuOUT_W(VB *sim) {
|
|||
}
|
||||
|
||||
/* RETI */
|
||||
static int cpuRETI(VB *sim) {
|
||||
static void cpuRETI(VB *sim) {
|
||||
if (sim->cpu.psw.np) {
|
||||
sim->cpu.nextPC = sim->cpu.fepc;
|
||||
cpuSetSystemRegister(sim, VB_PSW, sim->cpu.fepsw, 0);
|
||||
|
@ -1039,11 +1178,10 @@ static int cpuRETI(VB *sim) {
|
|||
}
|
||||
sim->cpu.clocks += cpuClocks(10);
|
||||
sim->cpu.operation = CPU_FETCH;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* REV */
|
||||
static int cpuREV(VB *sim) {
|
||||
static void cpuREV(VB *sim) {
|
||||
uint32_t x = cpuGetReg1(sim);
|
||||
x = (x << 16 & 0xFFFF0000) | (x >> 16 & 0x0000FFFF);
|
||||
x = (x << 8 & 0xFF00FF00) | (x >> 8 & 0x00FF00FF);
|
||||
|
@ -1051,63 +1189,54 @@ static int cpuREV(VB *sim) {
|
|||
x = (x << 2 & 0xCCCCCCCC) | (x >> 2 & 0x33333333);
|
||||
x = (x << 1 & 0xAAAAAAAA) | (x >> 1 & 0x55555555);
|
||||
cpuSetReg2(sim, x);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* SAR immediate */
|
||||
static int cpuSARImm(VB *sim) {
|
||||
static void cpuSARImm(VB *sim) {
|
||||
cpuSetReg2(sim, cpuShiftArithmetic(sim, cpuGetImm5U(sim)));
|
||||
cpuAdvance(sim, cpuClocks(1));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* SEI */
|
||||
static int cpuSEI(VB *sim) {
|
||||
static void cpuSEI(VB *sim) {
|
||||
sim->cpu.psw.id = 1;
|
||||
cpuAdvance(sim, cpuClocks(12));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* SETF */
|
||||
static int cpuSETF(VB *sim) {
|
||||
static void cpuSETF(VB *sim) {
|
||||
cpuSetReg2(sim, cpuCondition(sim, cpuGetImm5U(sim) & 15));
|
||||
cpuAdvance(sim, cpuClocks(1));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* SHR register */
|
||||
static int cpuSARReg(VB *sim) {
|
||||
static void cpuSARReg(VB *sim) {
|
||||
cpuSetReg2(sim, cpuShiftArithmetic(sim, cpuGetReg1(sim) & 31));
|
||||
cpuAdvance(sim, cpuClocks(1));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* SHL immediate */
|
||||
static int cpuSHLImm(VB *sim) {
|
||||
static void cpuSHLImm(VB *sim) {
|
||||
cpuSetReg2(sim, cpuShiftLeft(sim, cpuGetImm5U(sim)));
|
||||
cpuAdvance(sim, cpuClocks(1));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* SHR register */
|
||||
static int cpuSHLReg(VB *sim) {
|
||||
static void cpuSHLReg(VB *sim) {
|
||||
cpuSetReg2(sim, cpuShiftLeft(sim, cpuGetReg1(sim) & 31));
|
||||
cpuAdvance(sim, cpuClocks(1));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* SHR immediate */
|
||||
static int cpuSHRImm(VB *sim) {
|
||||
static void cpuSHRImm(VB *sim) {
|
||||
cpuSetReg2(sim, cpuShiftRight(sim, cpuGetImm5U(sim)));
|
||||
cpuAdvance(sim, cpuClocks(1));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* SHR register */
|
||||
static int cpuSHRReg(VB *sim) {
|
||||
static void cpuSHRReg(VB *sim) {
|
||||
cpuSetReg2(sim, cpuShiftRight(sim, cpuGetReg1(sim) & 31));
|
||||
cpuAdvance(sim, cpuClocks(1));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ST.B */
|
||||
|
@ -1126,55 +1255,87 @@ static int cpuST_W(VB *sim) {
|
|||
}
|
||||
|
||||
/* STSR */
|
||||
static int cpuSTSR(VB *sim) {
|
||||
static void cpuSTSR(VB *sim) {
|
||||
cpuSetReg2(sim, cpuGetSystemRegister(sim, cpuGetImm5U(sim)));
|
||||
cpuAdvance(sim, cpuClocks(8));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* SUB */
|
||||
static int cpuSUB(VB *sim) {
|
||||
static void cpuSUB(VB *sim) {
|
||||
cpuSetReg2(sim, cpuSubtract(sim, cpuGetReg1(sim)));
|
||||
cpuAdvance(sim, cpuClocks(1));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* SUBF.S */
|
||||
static void cpuSUBF_S(VB *sim) {
|
||||
int32_t a = cpuGetReg2(sim);
|
||||
int32_t b = cpuGetReg1(sim);
|
||||
double c; /* Result */
|
||||
int32_t d; /* Float bits for result */
|
||||
if (cpuFloatReserved(sim, a, b))
|
||||
return;
|
||||
c = (double) cpuWordToFloat(a) - cpuWordToFloat(b);
|
||||
if (cpuFloatCommon(sim, c, &d))
|
||||
return;
|
||||
cpuSetReg2(sim, d);
|
||||
cpuAdvance(sim, cpuClocks(28)); /* TODO: Research */
|
||||
}
|
||||
|
||||
/* TRAP */
|
||||
static int cpuTRAP(VB *sim) {
|
||||
static void cpuTRAP(VB *sim) {
|
||||
sim->cpu.clocks += cpuClocks(15);
|
||||
sim->cpu.exception = 0xFFA0 + cpuGetImm5U(sim);
|
||||
sim->cpu.operation = CPU_EXCEPTION;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* TRNC.SW */
|
||||
static void cpuTRNC_SW(VB *sim) {
|
||||
double f;
|
||||
int32_t w = cpuGetReg1(sim);
|
||||
if (cpuFloatReservedOne(w)) {
|
||||
cpuThrow(sim, 0xFF60);
|
||||
return;
|
||||
}
|
||||
f = cpuWordToFloat(w);
|
||||
if (f <= -2147483649.0 || f >= 2147483648.0) {
|
||||
sim->cpu.psw.fiv = 1;
|
||||
cpuThrow(sim, 0xFF70);
|
||||
return;
|
||||
}
|
||||
w = f;
|
||||
cpuSetReg2(sim, w);
|
||||
if (w != f)
|
||||
sim->cpu.psw.fpr = 1;
|
||||
sim->cpu.psw.ov = 0;
|
||||
sim->cpu.psw.s = w < 0;
|
||||
sim->cpu.psw.z = w == 0;
|
||||
cpuAdvance(sim, cpuClocks(14)); /* TODO: Research */
|
||||
}
|
||||
|
||||
/* XB */
|
||||
static int cpuXB(VB *sim) {
|
||||
static void cpuXB(VB *sim) {
|
||||
uint32_t x = cpuGetReg2(sim);
|
||||
x = (x & 0xFFFF0000) | (x << 8 & 0x0000FF00) | (x >> 8 & 0x000000FF);
|
||||
cpuSetReg2(sim, x);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* XH */
|
||||
static int cpuXH(VB *sim) {
|
||||
static void cpuXH(VB *sim) {
|
||||
uint32_t x = cpuGetReg2(sim);
|
||||
x = (x << 16 & 0xFFFF0000) | (x >> 16 & 0x0000FFFF);
|
||||
cpuSetReg2(sim, x);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* XOR */
|
||||
static int cpuXOR(VB *sim) {
|
||||
static void cpuXOR(VB *sim) {
|
||||
cpuSetReg2(sim, cpuBitwise(sim, cpuGetReg2(sim) ^ cpuGetReg1(sim)));
|
||||
cpuAdvance(sim, cpuClocks(1));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* XORI */
|
||||
static int cpuXORI(VB *sim) {
|
||||
static void cpuXORI(VB *sim) {
|
||||
cpuSetReg2(sim, cpuBitwise(sim, cpuGetReg2(sim) ^ cpuGetImm16U(sim)));
|
||||
cpuAdvance(sim, cpuClocks(1));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1183,7 +1344,7 @@ static int cpuXORI(VB *sim) {
|
|||
|
||||
/* Process component */
|
||||
static int cpuEmulate(VB *sim, uint32_t clocks) {
|
||||
int brk;
|
||||
int brk = 0;
|
||||
|
||||
/* Process until there are clocks to wait */
|
||||
for (;;) {
|
||||
|
@ -1204,62 +1365,70 @@ static int cpuEmulate(VB *sim, uint32_t clocks) {
|
|||
switch (sim->cpu.operation) {
|
||||
case CPU_FETCH: brk = cpuFetch(sim); break;
|
||||
|
||||
case CPU_ADD_IMM: brk = cpuADDImm(sim); break;
|
||||
case CPU_ADD_REG: brk = cpuADDReg(sim); break;
|
||||
case CPU_ADDI : brk = cpuADDI (sim); break;
|
||||
case CPU_AND : brk = cpuAND (sim); break;
|
||||
case CPU_ANDI : brk = cpuANDI (sim); break;
|
||||
case CPU_BCOND : brk = cpuBCOND (sim); break;
|
||||
case CPU_CAXI : brk = cpuCAXI (sim); break;
|
||||
case CPU_CLI : brk = cpuCLI (sim); break;
|
||||
case CPU_CMP_IMM: brk = cpuCMPImm(sim); break;
|
||||
case CPU_CMP_REG: brk = cpuCMPReg(sim); break;
|
||||
case CPU_DIV : brk = cpuDIV (sim); break;
|
||||
case CPU_DIVU : brk = cpuDIVU (sim); break;
|
||||
case CPU_HALT : brk = cpuHALT (sim); break;
|
||||
case CPU_IN_B : brk = cpuIN_B (sim); break;
|
||||
case CPU_IN_H : brk = cpuIN_H (sim); break;
|
||||
case CPU_IN_W : brk = cpuIN_W (sim); break;
|
||||
case CPU_JAL : brk = cpuJAL (sim); break;
|
||||
case CPU_JMP : brk = cpuJMP (sim); break;
|
||||
case CPU_JR : brk = cpuJR (sim); break;
|
||||
case CPU_LD_B : brk = cpuLD_B (sim); break;
|
||||
case CPU_LD_H : brk = cpuLD_H (sim); break;
|
||||
case CPU_LD_W : brk = cpuLD_W (sim); break;
|
||||
case CPU_LDSR : brk = cpuLDSR (sim); break;
|
||||
case CPU_MOV_IMM: brk = cpuMOVImm(sim); break;
|
||||
case CPU_MOV_REG: brk = cpuMOVReg(sim); break;
|
||||
case CPU_MOVEA : brk = cpuMOVEA (sim); break;
|
||||
case CPU_MOVHI : brk = cpuMOVHI (sim); break;
|
||||
case CPU_MPYHW : brk = cpuMPYHW (sim); break;
|
||||
case CPU_MUL : brk = cpuMUL (sim); break;
|
||||
case CPU_MULU : brk = cpuMULU (sim); break;
|
||||
case CPU_NOT : brk = cpuNOT (sim); break;
|
||||
case CPU_OR : brk = cpuOR (sim); break;
|
||||
case CPU_ORI : brk = cpuORI (sim); break;
|
||||
case CPU_OUT_B : brk = cpuOUT_B (sim); break;
|
||||
case CPU_OUT_H : brk = cpuOUT_H (sim); break;
|
||||
case CPU_OUT_W : brk = cpuOUT_W (sim); break;
|
||||
case CPU_RETI : brk = cpuRETI (sim); break;
|
||||
case CPU_REV : brk = cpuREV (sim); break;
|
||||
case CPU_SAR_IMM: brk = cpuSARImm(sim); break;
|
||||
case CPU_SAR_REG: brk = cpuSARReg(sim); break;
|
||||
case CPU_SEI : brk = cpuSEI (sim); break;
|
||||
case CPU_SETF : brk = cpuSETF (sim); break;
|
||||
case CPU_SHL_IMM: brk = cpuSHLImm(sim); break;
|
||||
case CPU_SHL_REG: brk = cpuSHLReg(sim); break;
|
||||
case CPU_SHR_IMM: brk = cpuSHRImm(sim); break;
|
||||
case CPU_SHR_REG: brk = cpuSHRReg(sim); break;
|
||||
case CPU_ST_B : brk = cpuST_B (sim); break;
|
||||
case CPU_ST_H : brk = cpuST_H (sim); break;
|
||||
case CPU_ST_W : brk = cpuST_W (sim); break;
|
||||
case CPU_STSR : brk = cpuSTSR (sim); break;
|
||||
case CPU_SUB : brk = cpuSUB (sim); break;
|
||||
case CPU_TRAP : brk = cpuTRAP (sim); break;
|
||||
case CPU_XB : brk = cpuXB (sim); break;
|
||||
case CPU_XH : brk = cpuXH (sim); break;
|
||||
case CPU_XOR : brk = cpuXOR (sim); break;
|
||||
case CPU_XORI : brk = cpuXORI (sim); break;
|
||||
case CPU_ADD_IMM: cpuADDImm (sim); break;
|
||||
case CPU_ADD_REG: cpuADDReg (sim); break;
|
||||
case CPU_ADDF_S : cpuADDF_S (sim); break;
|
||||
case CPU_ADDI : cpuADDI (sim); break;
|
||||
case CPU_AND : cpuAND (sim); break;
|
||||
case CPU_ANDI : cpuANDI (sim); break;
|
||||
case CPU_BCOND : cpuBCOND (sim); break;
|
||||
case CPU_CAXI : brk = cpuCAXI (sim); break;
|
||||
case CPU_CLI : cpuCLI (sim); break;
|
||||
case CPU_CMP_IMM: cpuCMPImm (sim); break;
|
||||
case CPU_CMP_REG: cpuCMPReg (sim); break;
|
||||
case CPU_CMPF_S : cpuCMPF_S (sim); break;
|
||||
case CPU_CVT_SW : cpuCVT_SW (sim); break;
|
||||
case CPU_CVT_WS : cpuCVT_WS (sim); break;
|
||||
case CPU_DIV : cpuDIV (sim); break;
|
||||
case CPU_DIVF_S : cpuDIVF_S (sim); break;
|
||||
case CPU_DIVU : cpuDIVU (sim); break;
|
||||
case CPU_HALT : cpuHALT (sim); break;
|
||||
case CPU_IN_B : brk = cpuIN_B (sim); break;
|
||||
case CPU_IN_H : brk = cpuIN_H (sim); break;
|
||||
case CPU_IN_W : brk = cpuIN_W (sim); break;
|
||||
case CPU_JAL : cpuJAL (sim); break;
|
||||
case CPU_JMP : cpuJMP (sim); break;
|
||||
case CPU_JR : cpuJR (sim); break;
|
||||
case CPU_LD_B : brk = cpuLD_B (sim); break;
|
||||
case CPU_LD_H : brk = cpuLD_H (sim); break;
|
||||
case CPU_LD_W : brk = cpuLD_W (sim); break;
|
||||
case CPU_LDSR : cpuLDSR (sim); break;
|
||||
case CPU_MOV_IMM: cpuMOVImm (sim); break;
|
||||
case CPU_MOV_REG: cpuMOVReg (sim); break;
|
||||
case CPU_MOVEA : cpuMOVEA (sim); break;
|
||||
case CPU_MOVHI : cpuMOVHI (sim); break;
|
||||
case CPU_MPYHW : cpuMPYHW (sim); break;
|
||||
case CPU_MUL : cpuMUL (sim); break;
|
||||
case CPU_MULF_S : cpuMULF_S (sim); break;
|
||||
case CPU_MULU : cpuMULU (sim); break;
|
||||
case CPU_NOT : cpuNOT (sim); break;
|
||||
case CPU_OR : cpuOR (sim); break;
|
||||
case CPU_ORI : cpuORI (sim); break;
|
||||
case CPU_OUT_B : brk = cpuOUT_B (sim); break;
|
||||
case CPU_OUT_H : brk = cpuOUT_H (sim); break;
|
||||
case CPU_OUT_W : brk = cpuOUT_W (sim); break;
|
||||
case CPU_RETI : cpuRETI (sim); break;
|
||||
case CPU_REV : cpuREV (sim); break;
|
||||
case CPU_SAR_IMM: cpuSARImm (sim); break;
|
||||
case CPU_SAR_REG: cpuSARReg (sim); break;
|
||||
case CPU_SEI : cpuSEI (sim); break;
|
||||
case CPU_SETF : cpuSETF (sim); break;
|
||||
case CPU_SHL_IMM: cpuSHLImm (sim); break;
|
||||
case CPU_SHL_REG: cpuSHLReg (sim); break;
|
||||
case CPU_SHR_IMM: cpuSHRImm (sim); break;
|
||||
case CPU_SHR_REG: cpuSHRReg (sim); break;
|
||||
case CPU_ST_B : brk = cpuST_B (sim); break;
|
||||
case CPU_ST_H : brk = cpuST_H (sim); break;
|
||||
case CPU_ST_W : brk = cpuST_W (sim); break;
|
||||
case CPU_STSR : cpuSTSR (sim); break;
|
||||
case CPU_SUB : cpuSUB (sim); break;
|
||||
case CPU_SUBF_S : cpuSUBF_S (sim); break;
|
||||
case CPU_TRAP : cpuTRAP (sim); break;
|
||||
case CPU_TRNC_SW: cpuTRNC_SW(sim); break;
|
||||
case CPU_XB : cpuXB (sim); break;
|
||||
case CPU_XH : cpuXH (sim); break;
|
||||
case CPU_XOR : cpuXOR (sim); break;
|
||||
case CPU_XORI : cpuXORI (sim); break;
|
||||
|
||||
default: return -1; /* TODO: Temporary for debugging */
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue