aboutsummaryrefslogtreecommitdiff
path: root/src/utils
diff options
context:
space:
mode:
Diffstat (limited to 'src/utils')
-rw-r--r--src/utils/assembler.spec.ts3
-rw-r--r--src/utils/assembler.ts5
-rw-r--r--src/utils/test-utils.ts28
3 files changed, 28 insertions, 8 deletions
diff --git a/src/utils/assembler.spec.ts b/src/utils/assembler.spec.ts
index f0daf64..836f388 100644
--- a/src/utils/assembler.spec.ts
+++ b/src/utils/assembler.spec.ts
@@ -14,6 +14,7 @@ describe('AVR assembler', () => {
bytes: bytes('0b0d'),
errors: [],
lines: [{ byteOffset: 0, bytes: '0d0b', line: 1, text: 'ADD r16, r11' }],
+ labels: {},
});
});
@@ -36,6 +37,7 @@ describe('AVR assembler', () => {
bytes: new Uint8Array(0),
errors: [],
lines: [],
+ labels: {},
});
});
@@ -44,6 +46,7 @@ describe('AVR assembler', () => {
bytes: new Uint8Array(0),
errors: ['Line 0: Rd out of range: 16<>31'],
lines: [],
+ labels: {},
});
});
diff --git a/src/utils/assembler.ts b/src/utils/assembler.ts
index 4823937..278e944 100644
--- a/src/utils/assembler.ts
+++ b/src/utils/assembler.ts
@@ -29,7 +29,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
-interface LabelTable {
+export interface LabelTable {
[key: string]: number;
}
@@ -938,7 +938,7 @@ function passTwo(lineTable: LineTablePass1[], labels: LabelTable) {
}
}
- return { errors: errorTable, bytes: resultTable, lines: lineTable as LineTable[] };
+ return { errors: errorTable, bytes: resultTable, lines: lineTable as LineTable[], labels };
}
/**
@@ -951,6 +951,7 @@ export function assemble(input: string) {
bytes: new Uint8Array(0),
errors: mid.errors,
lines: [],
+ labels: {},
};
}
return passTwo(mid.lines, mid.labels);
diff --git a/src/utils/test-utils.ts b/src/utils/test-utils.ts
index 4b2efff..e620748 100644
--- a/src/utils/test-utils.ts
+++ b/src/utils/test-utils.ts
@@ -5,38 +5,54 @@ import { avrInstruction } from '../cpu/instruction';
const BREAK_OPCODE = 0x9598;
export function asmProgram(source: string) {
- const { bytes, errors, lines } = assemble(source);
+ const { bytes, errors, lines, labels } = assemble(source);
if (errors.length) {
throw new Error('Assembly failed: ' + errors);
}
- return { program: new Uint16Array(bytes.buffer), lines, instructionCount: lines.length };
+ return { program: new Uint16Array(bytes.buffer), lines, instructionCount: lines.length, labels };
}
+const defaultOnBreak = () => {
+ throw new Error('BREAK instruction encountered');
+};
+
export class TestProgramRunner {
- constructor(private readonly cpu: CPU, private readonly onBreak?: (cpu: CPU) => void) {}
+ constructor(
+ private readonly cpu: CPU,
+ private readonly onBreak: (cpu: CPU) => void = defaultOnBreak
+ ) {}
runInstructions(count: number) {
const { cpu, onBreak } = this;
for (let i = 0; i < count; i++) {
if (cpu.progMem[cpu.pc] === BREAK_OPCODE) {
onBreak?.(cpu);
- throw new Error('BREAK instruction encountered');
}
avrInstruction(cpu);
cpu.tick();
}
}
- runToBreak(maxIterations = 5000) {
+ runUntil(predicate: (cpu: CPU) => boolean, maxIterations = 5000) {
const { cpu, onBreak } = this;
for (let i = 0; i < maxIterations; i++) {
if (cpu.progMem[cpu.pc] === BREAK_OPCODE) {
onBreak?.(cpu);
+ }
+ if (predicate(cpu)) {
return;
}
avrInstruction(cpu);
cpu.tick();
}
- throw new Error('Program ran for too long without a BREAK instruction');
+ throw new Error('Test program ran for too long, check your predicate');
+ }
+
+ runToBreak() {
+ this.runUntil((cpu) => cpu.progMem[cpu.pc] === BREAK_OPCODE);
+ }
+
+ runToAddress(byteAddr: number) {
+ this.runUntil((cpu) => cpu.pc * 2 === byteAddr);
}
}
If you find this content useful please consider a small donation via bitcoin: bitcoin:1mxKyQsHHugqRxPKgwaA7wUwJEGCNthn2?amount=0.001&message=Donation Scraping git contents via cgit is very resource intensive. The continued hosting of these git repositories is entirely financed by your bitcoin contributions. For donations of a least 1 mBTC you include your IP address in the message of your bitcoin donation. This will remove this message in the future for requests from your IP, which will significantly reduce token usage. In any case, any contributions to bitcoin address 1mxKyQsHHugqRxPKgwaA7wUwJEGCNthn2 are very welcome. Thanks in advance for you contribution to a self-sustaining ecosystem.