aboutsummaryrefslogtreecommitdiffgithub
diff options
context:
space:
mode:
-rw-r--r--novice/assembler/codegen/base.ts42
-rw-r--r--novice/assembler/opspec/complx.ts8
-rw-r--r--novice/assembler/opspec/opspec.ts2
-rw-r--r--novice/assembler/opspec/word.ts4
4 files changed, 39 insertions, 17 deletions
diff --git a/novice/assembler/codegen/base.ts b/novice/assembler/codegen/base.ts
index ba202fa..3d4d918 100644
--- a/novice/assembler/codegen/base.ts
+++ b/novice/assembler/codegen/base.ts
@@ -12,13 +12,22 @@ interface ReassembleVictim {
instrIdx: number;
}
+interface HasOp { op: string; }
+type Lut<T extends HasOp> = {[op: string]: T[]};
+
class BaseMachineCodeGenerator implements MachineCodeGenerator {
- private isa: Isa;
- private opSpec: PseudoOpSpec;
+ protected isa: Isa;
+ protected opSpec: PseudoOpSpec;
+ protected instrLut: Lut<InstructionSpec>;
+ protected aliasLut: Lut<AliasSpec>;
+ protected opLut: Lut<OpSpec>;
public constructor(isa: Isa, opSpec: PseudoOpSpec) {
this.isa = isa;
this.opSpec = opSpec;
+ this.instrLut = this.genLut(this.isa.instructions);
+ this.aliasLut = this.genLut(this.isa.aliases);
+ this.opLut = this.genLut(this.opSpec.ops);
}
public gen(asm: Assembly):
@@ -91,13 +100,27 @@ class BaseMachineCodeGenerator implements MachineCodeGenerator {
return [symbtable, sections];
}
+ protected genLut<T extends HasOp>(ops: T[]): Lut<T> {
+ const lut: Lut<T> = {};
+
+ for (const op of ops) {
+ if (!(op.op in lut)) {
+ lut[op.op] = [];
+ }
+ lut[op.op].push(op);
+ }
+
+ return lut;
+ }
+
private inflateInstr(instr: Instruction|PseudoOp,
pc: number,
symbtable: SymbTable|null): [number[], boolean] {
if (instr.kind === 'pseudoop') {
let match: OpSpec|null = null;
+ const candidates = this.opLut[instr.op] || [];
- for (const op of this.opSpec.ops) {
+ for (const op of candidates) {
if (this.opMatch(instr, op)) {
match = op;
break;
@@ -124,9 +147,9 @@ class BaseMachineCodeGenerator implements MachineCodeGenerator {
}
} else {
// If it's an alias, expand that mf
- // TODO: Figure out a more efficient way than this. just a
- // hashmap right?
- for (const alias of this.isa.aliases) {
+ const aliasCandidates = this.aliasLut[instr.op] || [];
+
+ for (const alias of aliasCandidates) {
if (this.aliasMatch(instr, alias)) {
if (!symbtable) {
return [new Array<number>(alias.size), true];
@@ -151,10 +174,9 @@ class BaseMachineCodeGenerator implements MachineCodeGenerator {
}
let match: InstructionSpec|null = null;
+ const candidates = this.instrLut[instr.op] || [];
- // TODO: Figure out a more efficient way than this. just a
- // hashmap right?
- for (const isaInstr of this.isa.instructions) {
+ for (const isaInstr of candidates) {
if (this.instrMatch(instr, isaInstr)) {
match = isaInstr;
break;
@@ -337,7 +359,7 @@ class BaseMachineCodeGenerator implements MachineCodeGenerator {
}
private opMatch(pseudoOp: PseudoOp, opSpec: OpSpec): boolean {
- return pseudoOp.op === opSpec.name && (
+ return pseudoOp.op === opSpec.op && (
!pseudoOp.operand && !opSpec.operands.length ||
opSpec.operands.length === 1 && !!pseudoOp.operand &&
pseudoOp.operand.kind === opSpec.operands[0].kind);
diff --git a/novice/assembler/opspec/complx.ts b/novice/assembler/opspec/complx.ts
index 85bd4bc..3b705e8 100644
--- a/novice/assembler/opspec/complx.ts
+++ b/novice/assembler/opspec/complx.ts
@@ -2,26 +2,26 @@ import { AsmContext, oneWord, OpOperands, PseudoOpSpec } from './opspec';
const complxOpSpec: PseudoOpSpec = {
ops: [
- {name: 'fill',
+ {op: 'fill',
operands: [{kind: 'int', name: 'num'}],
asm: (ctx: AsmContext, operands: OpOperands) =>
// TODO: complain if too big
[operands.ints.num & ~(-1 << ctx.isa.mem.addressability)]},
- {name: 'fill',
+ {op: 'fill',
operands: [{kind: 'label', name: 'label'}],
size: oneWord,
asm: (ctx: AsmContext, operands: OpOperands) =>
// TODO: complain if nonexistent
[ctx.symbtable[operands.labels.label]]},
- {name: 'stringz',
+ {op: 'stringz',
operands: [{kind: 'string', name: 'str'}],
asm: (ctx: AsmContext, operands: OpOperands) =>
// TODO: how is non-ascii handled? probably blow up
operands.strings.str.split('').map(c => c.charCodeAt(0)).concat([0])},
- {name: 'blkw',
+ {op: 'blkw',
operands: [{kind: 'int', name: 'count'}],
asm: (ctx: AsmContext, operands: OpOperands) => {
// TODO: needs to be randomized/uninitialized
diff --git a/novice/assembler/opspec/opspec.ts b/novice/assembler/opspec/opspec.ts
index 58dce93..d1f3923 100644
--- a/novice/assembler/opspec/opspec.ts
+++ b/novice/assembler/opspec/opspec.ts
@@ -17,7 +17,7 @@ interface OpOperands {
}
interface OpSpec {
- name: string;
+ op: string;
operands: OpOperandSpec[];
asm: (ctx: AsmContext, operands: OpOperands) => number[];
size?: (isa: Isa) => number;
diff --git a/novice/assembler/opspec/word.ts b/novice/assembler/opspec/word.ts
index 4125045..d9866ff 100644
--- a/novice/assembler/opspec/word.ts
+++ b/novice/assembler/opspec/word.ts
@@ -3,13 +3,13 @@ import { AsmContext, oneWord, OpOperands, PseudoOpSpec } from './opspec';
const wordOpSpec: PseudoOpSpec = {
ops: [
- {name: 'word',
+ {op: 'word',
operands: [{kind: 'int', name: 'num'}],
asm: (ctx: AsmContext, operands: OpOperands) =>
// TODO: complain if too big
[maskTo(operands.ints.num, ctx.isa.mem.addressability)]},
- {name: 'word',
+ {op: 'word',
operands: [{kind: 'label', name: 'label'}],
size: oneWord,
asm: (ctx: AsmContext, operands: OpOperands) =>