CPU corrections
This commit is contained in:
parent
b33a6c3055
commit
a7985bad6e
|
@ -88,8 +88,8 @@
|
||||||
{ format: 6, mnemonic: "ST.W" },
|
{ format: 6, mnemonic: "ST.W" },
|
||||||
{ format: 6, mnemonic: "IN.B" },
|
{ format: 6, mnemonic: "IN.B" },
|
||||||
{ format: 6, mnemonic: "IN.H" },
|
{ format: 6, mnemonic: "IN.H" },
|
||||||
{ format: 6, mnemonic: "IN.W" },
|
|
||||||
{ format: 6, mnemonic: "CAXI" },
|
{ format: 6, mnemonic: "CAXI" },
|
||||||
|
{ format: 6, mnemonic: "IN.W" },
|
||||||
{ format: 6, mnemonic: "OUT.B" },
|
{ format: 6, mnemonic: "OUT.B" },
|
||||||
{ format: 6, mnemonic: "OUT.H" },
|
{ format: 6, mnemonic: "OUT.H" },
|
||||||
{ format: 7, mnemonic: null },
|
{ format: 7, mnemonic: null },
|
||||||
|
@ -258,9 +258,6 @@
|
||||||
case 0b000110: // JMP
|
case 0b000110: // JMP
|
||||||
inst.operands = "[" + reg1 + "]";
|
inst.operands = "[" + reg1 + "]";
|
||||||
break;
|
break;
|
||||||
case 0b001111: // NOT
|
|
||||||
inst.operands = reg1;
|
|
||||||
break;
|
|
||||||
default: // All others
|
default: // All others
|
||||||
inst.operands = reg1 + ", " + this.PROREGNAMES[bits >> 5 & 31];
|
inst.operands = reg1 + ", " + this.PROREGNAMES[bits >> 5 & 31];
|
||||||
}
|
}
|
||||||
|
@ -275,7 +272,7 @@
|
||||||
case 0b010010: // SETF
|
case 0b010010: // SETF
|
||||||
inst.operands = this.SETFS[other & 15] + ", " + reg2;
|
inst.operands = this.SETFS[other & 15] + ", " + reg2;
|
||||||
break;
|
break;
|
||||||
case 0b011001: // TRAP
|
case 0b011000: // TRAP
|
||||||
inst.operands = other;
|
inst.operands = other;
|
||||||
break;
|
break;
|
||||||
case 0b011100: // LDSR
|
case 0b011100: // LDSR
|
||||||
|
@ -355,6 +352,7 @@
|
||||||
case 0b110011: // LD.W
|
case 0b110011: // LD.W
|
||||||
case 0b111000: // IN.B
|
case 0b111000: // IN.B
|
||||||
case 0b111001: // IN.H
|
case 0b111001: // IN.H
|
||||||
|
case 0b111010: // CAXI
|
||||||
case 0b111011: // IN.W
|
case 0b111011: // IN.W
|
||||||
inst.operands = disp + "[" + reg1 + "], " + reg2;
|
inst.operands = disp + "[" + reg1 + "], " + reg2;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -194,6 +194,7 @@ globalThis.MemoryWindow = class MemoryWindow extends Toolkit.Window {
|
||||||
case "ArrowLeft" : change = - 1 ; break;
|
case "ArrowLeft" : change = - 1 ; break;
|
||||||
case "ArrowRight": change = 1 ; break;
|
case "ArrowRight": change = 1 ; break;
|
||||||
case "ArrowUp" : change = -16 ; break;
|
case "ArrowUp" : change = -16 ; break;
|
||||||
|
case "Enter" : change = 0 ; break;
|
||||||
case "PageDown" : change = visible; break;
|
case "PageDown" : change = visible; break;
|
||||||
case "PageUp" : change = -visible; break;
|
case "PageUp" : change = -visible; break;
|
||||||
case "0": case "1": case "2": case "3": case "4":
|
case "0": case "1": case "2": case "3": case "4":
|
||||||
|
|
|
@ -137,9 +137,35 @@
|
||||||
let text;
|
let text;
|
||||||
switch (this.format) {
|
switch (this.format) {
|
||||||
case "float":
|
case "float":
|
||||||
text = CPUWindow.Register.intBitsToFloat(value).toString();
|
let e = value >> 23 & 0xFF;
|
||||||
|
let s = value & 0x007FFFFF;
|
||||||
|
|
||||||
|
// Check for denormal number
|
||||||
|
if (e == 0x00 & s != 0) {
|
||||||
|
text = "Denormal";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for reserved operand
|
||||||
|
if (e == 0xFF) {
|
||||||
|
text = s!=0 ? "NaN" : value<0 ? "-Infinity" : "Infinity";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for negative zero
|
||||||
|
if ((value & 0xFFFFFFFF) >>> 0 == 0x80000000) {
|
||||||
|
text = "-0.0";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Format the number
|
||||||
|
text = CPUWindow.Register.intBitsToFloat(value).toFixed(6);
|
||||||
if (text.indexOf(".") == -1)
|
if (text.indexOf(".") == -1)
|
||||||
text += ".0";
|
text += ".0";
|
||||||
|
while (text.endsWith("0"))
|
||||||
|
text = text.substring(0, text.length - 1);
|
||||||
|
if (text.endsWith("."))
|
||||||
|
text += "0";
|
||||||
break;
|
break;
|
||||||
case "hex":
|
case "hex":
|
||||||
text = ("0000000" +
|
text = ("0000000" +
|
||||||
|
|
116
core/cpu.c
116
core/cpu.c
|
@ -229,24 +229,24 @@ static int32_t cpuAdd(VB *emu, int32_t left, int32_t right) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Bit string search */
|
/* Bit string search */
|
||||||
static int cpuBitSearch(VB *emu, int bit, int dir) {
|
static int cpuBitSearch(VB *emu, int32_t bit, int32_t dir) {
|
||||||
int32_t offset; /* Bit offset in source word */
|
int32_t offset; /* Bit offset in source word */
|
||||||
int32_t value; /* Alias of source word */
|
int32_t value; /* Alias of source word */
|
||||||
|
|
||||||
|
/* Read the source word */
|
||||||
|
if (!emu->cpu.busWait) {
|
||||||
|
|
||||||
|
/* Initialize state */
|
||||||
|
emu->cpu.program[30] &= 0xFFFFFFFC;
|
||||||
|
emu->cpu.program[27] &= 0x0000001F;
|
||||||
|
emu->cpu.psw.z = 1;
|
||||||
|
|
||||||
/* The bit string is of zero length */
|
/* The bit string is of zero length */
|
||||||
if (emu->cpu.program[28] == 0) {
|
if (emu->cpu.program[28] == 0) {
|
||||||
emu->cpu.clocks = dir == 1 ? 13 : 15;
|
emu->cpu.clocks = dir == 1 ? 13 : 15;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Read the source word */
|
|
||||||
if (!emu->cpu.busWait && !emu->cpu.substring) {
|
|
||||||
|
|
||||||
/* Initialize state */
|
|
||||||
emu->cpu.program[30] &= 0xFFFFFFFC;
|
|
||||||
emu->cpu.program[27] &= 0x0000001F;
|
|
||||||
emu->cpu.psw.z = 1;
|
|
||||||
|
|
||||||
/* Read the data unit from the bus */
|
/* Read the data unit from the bus */
|
||||||
if (cpuRead(emu, emu->cpu.program[30], VB_S32))
|
if (cpuRead(emu, emu->cpu.program[30], VB_S32))
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -260,6 +260,10 @@ static int cpuBitSearch(VB *emu, int bit, int dir) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Update state */
|
||||||
|
emu->cpu.busWait = 0;
|
||||||
|
emu->cpu.substring = 0;
|
||||||
|
|
||||||
/* Search the bit string */
|
/* Search the bit string */
|
||||||
for (
|
for (
|
||||||
offset = emu->cpu.program[27], value = emu->cpu.access.value;
|
offset = emu->cpu.program[27], value = emu->cpu.access.value;
|
||||||
|
@ -268,31 +272,36 @@ static int cpuBitSearch(VB *emu, int bit, int dir) {
|
||||||
) {
|
) {
|
||||||
|
|
||||||
/* The current bit does not match */
|
/* The current bit does not match */
|
||||||
if ((value >> bit & 1) != bit)
|
if ((value >> offset & 1) != bit)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* The current bit matches */
|
/* The current bit matches */
|
||||||
emu->cpu.substring = 0;
|
emu->cpu.program[27] = offset;
|
||||||
emu->cpu.clocks = dir == 1 ? 46 : 51;
|
emu->cpu.clocks = dir == 1 ? 45 : 50;
|
||||||
emu->cpu.psw.z = 0;
|
emu->cpu.psw.z = 0;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* No bit in the current word matches */
|
/* No bit in the current word matches */
|
||||||
|
emu->cpu.program[27] = offset & 31;
|
||||||
|
if (emu->cpu.program[27] != offset)
|
||||||
|
emu->cpu.program[30] += (uint32_t) dir << 2;
|
||||||
|
if (emu->cpu.program[28] != 0) {
|
||||||
emu->cpu.substring = 1;
|
emu->cpu.substring = 1;
|
||||||
emu->cpu.clocks = 5;
|
emu->cpu.clocks = 5;
|
||||||
emu->cpu.program[30] += dir << 2;
|
} else emu->cpu.clocks = dir == 1 ? 46 : 51;
|
||||||
emu->cpu.program[27] &= 0x0000001F;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Bit string bitwise operation */
|
/* Bit string bitwise operation */
|
||||||
static int cpuBitString(VB *emu, VB_INSTRUCTION *inst) {
|
static int cpuBitString(VB *emu, VB_INSTRUCTION *inst) {
|
||||||
|
uint64_t bits; /* Shift register */
|
||||||
int32_t dest; /* Destination word value */
|
int32_t dest; /* Destination word value */
|
||||||
|
int32_t mask; /* Bit mask */
|
||||||
int32_t src; /* Source word value */
|
int32_t src; /* Source word value */
|
||||||
|
|
||||||
/* Initial invocation */
|
/* Initial invocation */
|
||||||
if (emu->cpu.busWait == 0 && !emu->cpu.substring) {
|
if (emu->cpu.busWait == 0) {
|
||||||
|
|
||||||
/* Initialize state */
|
/* Initialize state */
|
||||||
emu->cpu.program[30] &= 0xFFFFFFFC;
|
emu->cpu.program[30] &= 0xFFFFFFFC;
|
||||||
|
@ -355,9 +364,12 @@ static int cpuBitString(VB *emu, VB_INSTRUCTION *inst) {
|
||||||
|
|
||||||
/* Compute and store the destination word */
|
/* Compute and store the destination word */
|
||||||
if (emu->cpu.busWait == 3) {
|
if (emu->cpu.busWait == 3) {
|
||||||
|
bits = ((uint64_t) inst->aux[1] << 32 | (uint32_t) inst->aux[0]);
|
||||||
dest = emu->cpu.access.value;
|
dest = emu->cpu.access.value;
|
||||||
src = ((int64_t) inst->aux[1] << 32 | (uint32_t) inst->aux[0]) >>
|
src = emu->cpu.program[27] <= emu->cpu.program[26] ?
|
||||||
(32 + emu->cpu.program[27] - emu->cpu.program[26]);
|
bits << (emu->cpu.program[26] - emu->cpu.program[27]) :
|
||||||
|
bits >> (emu->cpu.program[27] - emu->cpu.program[26])
|
||||||
|
;
|
||||||
|
|
||||||
/* Perform the operation */
|
/* Perform the operation */
|
||||||
switch (inst->bits[0] & 7) {
|
switch (inst->bits[0] & 7) {
|
||||||
|
@ -372,13 +384,13 @@ static int cpuBitString(VB *emu, VB_INSTRUCTION *inst) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Incorporate only the bits occupied by the bit string */
|
/* Incorporate only the bits occupied by the bit string */
|
||||||
src = (int32_t) 0xFFFFFFFF << emu->cpu.program[26];
|
mask = (uint32_t) 0xFFFFFFFF << emu->cpu.program[26];
|
||||||
if ((uint32_t)emu->cpu.program[28] < (uint32_t)32-emu->cpu.program[26])
|
if ((uint32_t)emu->cpu.program[28] < (uint32_t)32-emu->cpu.program[26])
|
||||||
src &= (1 << (emu->cpu.program[28] + emu->cpu.program[26])) - 1;
|
mask &= (1 << (emu->cpu.program[28] + emu->cpu.program[26])) - 1;
|
||||||
dest = (dest & src) | (emu->cpu.access.value & ~src);
|
dest = (dest & mask) | (emu->cpu.access.value & ~mask);
|
||||||
|
|
||||||
/* Write the data unit to the bus */
|
/* Write the data unit to the bus */
|
||||||
if (cpuWrite(emu, emu->cpu.program[30], VB_S32, dest))
|
if (cpuWrite(emu, emu->cpu.program[29], VB_S32, dest))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
/* Update state */
|
/* Update state */
|
||||||
|
@ -391,23 +403,30 @@ static int cpuBitString(VB *emu, VB_INSTRUCTION *inst) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Working variables */
|
/* Working variables */
|
||||||
dest = 32 - emu->cpu.program[26]; /* Bits processed this invocation */
|
mask = 32 - emu->cpu.program[26]; /* Bits processed this invocation */
|
||||||
if ((uint32_t) emu->cpu.program[28] < (uint32_t) dest)
|
if ((uint32_t) emu->cpu.program[28] < (uint32_t) mask)
|
||||||
dest = emu->cpu.program[28];
|
mask = emu->cpu.program[28];
|
||||||
src = emu->cpu.program[30] + dest; /* New source bit offset */
|
dest = emu->cpu.program[26] + mask; /* New destination bit offset */
|
||||||
|
src = emu->cpu.program[27] + mask; /* New source bit offset */
|
||||||
|
|
||||||
/* Update state */
|
/* Update state */
|
||||||
emu->cpu.busWait = 0;
|
emu->cpu.busWait = 0;
|
||||||
emu->cpu.substring = dest != emu->cpu.program[28];
|
emu->cpu.substring = mask != emu->cpu.program[28];
|
||||||
if (src >= 32) {
|
emu->cpu.program[26] = dest & 31;
|
||||||
inst->aux[0] = inst->aux[1];
|
emu->cpu.program[27] = src & 31;
|
||||||
emu->cpu.program[30] += 4;
|
emu->cpu.program[28] -= mask;
|
||||||
}
|
if (dest >= 32)
|
||||||
emu->cpu.program[29] += 4;
|
emu->cpu.program[29] += 4;
|
||||||
emu->cpu.program[28] -= dest;
|
if (src >= 32)
|
||||||
emu->cpu.program[27] = src & 0x1F;
|
emu->cpu.program[30] += 4;
|
||||||
emu->cpu.program[26] = 0;
|
if (emu->cpu.substring) {
|
||||||
emu->cpu.clocks = emu->cpu.substring ? 6 : 36;
|
emu->cpu.busWait = 1;
|
||||||
|
emu->cpu.clocks = 6;
|
||||||
|
inst->aux[0] = inst->aux[1];
|
||||||
|
} else {
|
||||||
|
emu->cpu.busWait = 0;
|
||||||
|
emu->cpu.clocks = 36;
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -502,7 +521,8 @@ static int32_t cpuFloatResult(VB *emu, double resultd) {
|
||||||
static void cpuFloatToWord(VB *emu, VB_INSTRUCTION *inst, int truncate) {
|
static void cpuFloatToWord(VB *emu, VB_INSTRUCTION *inst, int truncate) {
|
||||||
int32_t bits = emu->cpu.program[inst->bits[0] & 0x1F];
|
int32_t bits = emu->cpu.program[inst->bits[0] & 0x1F];
|
||||||
int32_t result; /* Output value */
|
int32_t result; /* Output value */
|
||||||
int32_t x; /* Working variable field */
|
int32_t x; /* Working variable */
|
||||||
|
int32_t y; /* Working variable */
|
||||||
|
|
||||||
/* Zero */
|
/* Zero */
|
||||||
if ((bits & 0x7FFFFFFF) == 0)
|
if ((bits & 0x7FFFFFFF) == 0)
|
||||||
|
@ -524,7 +544,7 @@ static void cpuFloatToWord(VB *emu, VB_INSTRUCTION *inst, int truncate) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Invalid operation */
|
/* Invalid operation */
|
||||||
if (x >= 135) {
|
if (x >= 158) {
|
||||||
emu->cpu.causeCode = 0xFF70;
|
emu->cpu.causeCode = 0xFF70;
|
||||||
emu->cpu.psw.fiv = 1;
|
emu->cpu.psw.fiv = 1;
|
||||||
return;
|
return;
|
||||||
|
@ -534,22 +554,22 @@ static void cpuFloatToWord(VB *emu, VB_INSTRUCTION *inst, int truncate) {
|
||||||
result = (bits & 0x007FFFFF) | 0x00800000;
|
result = (bits & 0x007FFFFF) | 0x00800000;
|
||||||
|
|
||||||
/* Left shift */
|
/* Left shift */
|
||||||
if (x >= 127)
|
if (x >= 150)
|
||||||
result <<= x - 127;
|
result <<= x - 150;
|
||||||
|
|
||||||
/* Right shift */
|
/* Right shift */
|
||||||
else {
|
else {
|
||||||
x = 127 - x; /* Number of bits to shift */
|
y = result; /* Significant bits */
|
||||||
|
x = 150 - x; /* Number of bits to shift */
|
||||||
result >>= x; /* Update state */
|
result >>= x; /* Update state */
|
||||||
x = 1 << x; /* Position of the "one halfths" bit */
|
|
||||||
|
|
||||||
/* Precision degradation */
|
/* Precision degradation */
|
||||||
if ((bits & (x - 1)) != 0) {
|
if ((y & ((1 << x) - 1)) != 0) {
|
||||||
emu->cpu.psw.fpr = 1;
|
emu->cpu.psw.fpr = 1;
|
||||||
|
|
||||||
/* Apply rounding */
|
/* Apply rounding */
|
||||||
if (!truncate && (bits & x) != 0)
|
if (!truncate)
|
||||||
result += x;
|
result += y >> (x - 1) & 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -885,6 +905,7 @@ static void cpuCVT_WS(VB *emu, VB_INSTRUCTION *inst) {
|
||||||
/* Divide */
|
/* Divide */
|
||||||
static void cpuDIV(VB *emu, VB_INSTRUCTION *inst) {
|
static void cpuDIV(VB *emu, VB_INSTRUCTION *inst) {
|
||||||
int32_t right = emu->cpu.program[inst->bits[0] & 0x1F];
|
int32_t right = emu->cpu.program[inst->bits[0] & 0x1F];
|
||||||
|
int32_t *r30; /* Program register r30 */
|
||||||
int32_t *reg2; /* Program register reg2 */
|
int32_t *reg2; /* Program register reg2 */
|
||||||
|
|
||||||
/* Zero division */
|
/* Zero division */
|
||||||
|
@ -902,7 +923,10 @@ static void cpuDIV(VB *emu, VB_INSTRUCTION *inst) {
|
||||||
|
|
||||||
/* Perform the operation */
|
/* Perform the operation */
|
||||||
else {
|
else {
|
||||||
emu->cpu.program[30] = *reg2 % right;
|
r30 = &emu->cpu.program[30];
|
||||||
|
*r30 = *reg2 % right;
|
||||||
|
if ((*r30 ^ *reg2) < 0)
|
||||||
|
*r30 = -*r30;
|
||||||
*reg2 /= right;
|
*reg2 /= right;
|
||||||
emu->cpu.psw.ov = 0;
|
emu->cpu.psw.ov = 0;
|
||||||
}
|
}
|
||||||
|
@ -1592,7 +1616,7 @@ static int cpuException(VB *emu) {
|
||||||
emu->cpu.eipcTo = emu->cpu.pcTo;
|
emu->cpu.eipcTo = emu->cpu.pcTo;
|
||||||
emu->cpu.psw.ep = 1;
|
emu->cpu.psw.ep = 1;
|
||||||
emu->cpu.pc = (causeCode & 0x0040) != 0 ?
|
emu->cpu.pc = (causeCode & 0x0040) != 0 ?
|
||||||
0xFFFFFF60 : ((uint32_t) 0xFFFF0000 | causeCode);
|
0xFFFFFF60 : ((uint32_t) 0xFFFF0000 | (causeCode & 0xFFF0));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Interrupt */
|
/* Interrupt */
|
||||||
|
@ -1658,7 +1682,7 @@ static int cpuFetch(VB *emu) {
|
||||||
/* Determine the internal ID of the instruction */
|
/* Determine the internal ID of the instruction */
|
||||||
inst->id = CPU_OPCODES[opcode];
|
inst->id = CPU_OPCODES[opcode];
|
||||||
switch (inst->id) {
|
switch (inst->id) {
|
||||||
case CPU_BITSTRING: inst->id = CPU_BITSTRINGS[inst->id & 0x1F]; break;
|
case CPU_BITSTRING: inst->id=CPU_BITSTRINGS[inst->bits[0]&0x1F]; break;
|
||||||
case CPU_FLOATENDO: inst->id=CPU_FLOATENDOS[inst->bits[1]>>10&0x3F];
|
case CPU_FLOATENDO: inst->id=CPU_FLOATENDOS[inst->bits[1]>>10&0x3F];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue