aboutsummaryrefslogtreecommitdiffgithub
diff options
context:
space:
mode:
authorAustin Adams <git@austinjadams.com>2019-01-28 16:52:01 -0600
committerAustin Adams <git@austinjadams.com>2019-01-28 16:52:01 -0600
commit5ba7845fb39cb2bc0c61a90003a280f1cfabfd08 (patch)
treeed92049b775aa5bb525ed13ca9cd27a0469bf97c
parent65def1227d3ecf3bd08bce3936deb29987ee05cf (diff)
downloadnovice-5ba7845fb39cb2bc0c61a90003a280f1cfabfd08.tar.gz
novice-5ba7845fb39cb2bc0c61a90003a280f1cfabfd08.tar.xz
Account for 0xffffffff & 0xffffffff in js being -1
-rw-r--r--novice/simulator/cli-debugger.ts14
-rw-r--r--novice/simulator/debugger.ts6
-rw-r--r--novice/simulator/simulator.ts5
-rw-r--r--novice/util.ts15
4 files changed, 28 insertions, 12 deletions
diff --git a/novice/simulator/cli-debugger.ts b/novice/simulator/cli-debugger.ts
index 8e97899..35124d2 100644
--- a/novice/simulator/cli-debugger.ts
+++ b/novice/simulator/cli-debugger.ts
@@ -1,7 +1,7 @@
import * as readline from 'readline';
import { Readable, Writable } from 'stream';
import { IO, Isa } from '../isa';
-import { padStr } from '../util';
+import { forceUnsigned, maxUnsignedVal, padStr } from '../util';
import { Debugger } from './debugger';
interface Command {
@@ -201,12 +201,12 @@ class CliDebugger extends Debugger {
}
private fmtHex(val: number, bits: number): string {
- return '0x' + padStr(Math.abs(val).toString(16),
+ return '0x' + padStr(forceUnsigned(val, bits).toString(16),
Math.ceil(bits / 4), '0');
}
private fmtAddr(addr: number): string {
- return this.fmtHex(addr, this.isa.mem.addressability);
+ return this.fmtHex(addr, this.isa.mem.space);
}
private fmtWord(word: number): string {
@@ -271,7 +271,8 @@ class CliDebugger extends Debugger {
for (let i = 0; i < reg.count; i++) {
// TODO: aliases
const regname = padStr(`${reg.prefix}${i}`, maxLen, ' ');
- const regval = Math.abs(this.regs.range[reg.prefix][i]);
+ const regval = forceUnsigned(this.regs.range[reg.prefix][i],
+ this.isa.mem.word);
const padded = padStr(regval.toString(base),
(base === 2) ? reg.bits : nibbles, '0');
const after = ((i + 1) % rowSize && i < reg.count - 1) ? ' ' : '\n';
@@ -281,7 +282,8 @@ class CliDebugger extends Debugger {
const nibbles = Math.ceil(reg.bits / 4);
const base = (reg.bits <= 4) ? 2 : 16;
const prefix = (reg.bits === 1) ? '' : (base === 2) ? '0b' : '0x';
- const regval = Math.abs(this.regs.solo[reg.name]);
+ const regval = forceUnsigned(this.regs.solo[reg.name],
+ this.isa.mem.word);
const padded = padStr(regval.toString(base),
(base === 2) ? reg.bits : nibbles, '0');
this.stdout.write(`${reg.name}: ${prefix}${padded}\n`);
@@ -296,7 +298,7 @@ class CliDebugger extends Debugger {
// on halts
const pc = this.halted ? this.pc - this.isa.pc.increment : this.pc;
const fromPc = Math.max(0, pc - 4);
- const toPc = Math.min(Math.pow(2, this.isa.mem.space) - 1, pc + 4);
+ const toPc = Math.min(maxUnsignedVal(this.isa.mem.space), pc + 4);
this.printMemRegion(pc, fromPc, toPc);
}
diff --git a/novice/simulator/debugger.ts b/novice/simulator/debugger.ts
index c01019e..0b0ac16 100644
--- a/novice/simulator/debugger.ts
+++ b/novice/simulator/debugger.ts
@@ -1,5 +1,5 @@
import { Fields, InstructionSpec, IO, Isa } from '../isa';
-import { maskTo, sextTo } from '../util';
+import { maskTo, maxUnsignedVal, sextTo } from '../util';
import { Simulator } from './simulator';
class Debugger extends Simulator {
@@ -121,8 +121,8 @@ class Debugger extends Simulator {
addr);
}
- if (addr > Math.abs(maskTo(-1, this.isa.mem.space))) {
- throw new Error(`address ${addr.toString(16)} is too large`);
+ if (addr > maxUnsignedVal(this.isa.mem.space)) {
+ throw new Error(`address 0x${addr.toString(16)} is too large`);
}
}
}
diff --git a/novice/simulator/simulator.ts b/novice/simulator/simulator.ts
index 8e686a4..9c85590 100644
--- a/novice/simulator/simulator.ts
+++ b/novice/simulator/simulator.ts
@@ -1,6 +1,6 @@
import { Fields, InstructionSpec, IO, Isa, MachineStateLogEntry, MachineStateUpdate,
Reg, RegIdentifier } from '../isa';
-import { maskTo, sextTo } from '../util';
+import { forceUnsigned, maskTo, sextTo } from '../util';
class Simulator {
protected pc: number;
@@ -235,8 +235,9 @@ class Simulator {
}
if (!matches.length) {
+ const unsigned = forceUnsigned(ir, this.isa.pc.instrBits);
throw new Error(`cannot decode instruction ` +
- `0x${Math.abs(ir).toString(16)}`);
+ `0x${unsigned.toString(16)}`);
}
matches.sort((left, right) => right.bits - left.bits);
diff --git a/novice/util.ts b/novice/util.ts
index d476e6e..a1e3b93 100644
--- a/novice/util.ts
+++ b/novice/util.ts
@@ -8,6 +8,19 @@ function sextTo(val: number, bits: number): number {
: val | (-1 << bits);
}
+function maxUnsignedVal(bits: number): number {
+ // Need to do this instead of using bitwise operators to get around
+ // the fact that js bitwise operators work on 32-bit two's complement ints
+ return Math.pow(2, bits) - 1;
+}
+
+// 0x80000001 & 0xffffffff = -0x7fffffff in js. This is pretty confusing
+// behavior when dealing with 32-bit addresses, so get the expected
+// value by clearing the MSB and then adding 2^31 to set it again.
+function forceUnsigned(val: number, bits: number): number {
+ return (bits < 32 || !(val & (1 << 31))) ? val : (val & ~(1 << 31)) + Math.pow(2, 31);
+}
+
function padStr(str: string, to: number, withChar: string, right?: boolean) {
const need = to - str.length;
for (let i = 0; i < need; i++) {
@@ -16,4 +29,4 @@ function padStr(str: string, to: number, withChar: string, right?: boolean) {
return str;
}
-export { maskTo, sextTo, padStr };
+export { forceUnsigned, maskTo, maxUnsignedVal, sextTo, padStr };