diff --git a/index.html b/index.html
index 4a5faf6f..5a1eb910 100644
--- a/index.html
+++ b/index.html
@@ -540,6 +540,7 @@ if (window.location.host.endsWith('8bitworkshop.com')) {
+
diff --git a/src/codemirror/vasm.js b/src/codemirror/vasm.js
new file mode 100644
index 00000000..af9ad68c
--- /dev/null
+++ b/src/codemirror/vasm.js
@@ -0,0 +1,98 @@
+// CodeMirror, copyright (c) by Marijn Haverbeke and others
+// Distributed under an MIT license: http://codemirror.net/LICENSE
+
+(function(mod) {
+ if (typeof exports == "object" && typeof module == "object") // CommonJS
+ mod(require("../../lib/codemirror"));
+ else if (typeof define == "function" && define.amd) // AMD
+ define(["../../lib/codemirror"], mod);
+ else // Plain browser env
+ mod(CodeMirror);
+})(function(CodeMirror) {
+"use strict";
+
+// vasm DASM syntax
+
+CodeMirror.defineMode('vasm', function(_config, parserConfig) {
+ var keywords1, keywords2;
+
+ var directives_list = [
+ ];
+ var directives = new Map();
+ directives_list.forEach(function(s) { directives.set(s, 'keyword'); });
+
+ var opcodes = /^[a-z]+\b/;
+ var numbers = /^([\da-f]+h|[0-7]+o|[01]+b|\d+d?)\b/i;
+
+ return {
+ startState: function() {
+ return {
+ context: 0
+ };
+ },
+ token: function(stream, state) {
+ if (!stream.column()) {
+ state.context = 0;
+ }
+ if (stream.eatSpace()) {
+ if (!state.context) state.context = 1;
+ return null;
+ }
+
+ var w;
+ if (stream.eatWhile(/\w/)) {
+ w = stream.current();
+ var cur = w.toLowerCase();
+ var style = directives.get(cur);
+ if (style)
+ return style;
+ if (stream.eat(':')) {
+ state.context = 1;
+ return 'tag';
+ }
+ if (state.context == 1 && opcodes.test(w)) {
+ state.context = 4;
+ return 'keyword';
+ } else if (state.context == 4 && numbers.test(w)) {
+ return 'number';
+ } else if (stream.match(numbers)) {
+ return 'number';
+ } else {
+ return null;
+ }
+ } else if (stream.eat('.')) {
+ if (stream.eatWhile(/[\w]/)) {
+ return 'meta';
+ }
+ } else if (stream.eat(';')) {
+ stream.skipToEnd();
+ return 'comment';
+ } else if (stream.eat('"')) {
+ while (w = stream.next()) {
+ if (w == '"')
+ break;
+
+ if (w == '\\')
+ stream.next();
+ }
+ return 'string';
+ } else if (stream.eat('\'')) {
+ if (stream.match(/\\?.'/))
+ return 'number';
+ } else if (stream.eat('$') || stream.eat('#')) {
+ if (stream.eatWhile(/[^;]/i))
+ return 'number';
+ } else if (stream.eat('%')) {
+ if (stream.eatWhile(/[01]/))
+ return 'number';
+ } else {
+ stream.next();
+ }
+ return null;
+ }
+ };
+});
+
+CodeMirror.defineMIME("text/x-vasm", "vasm");
+
+});
diff --git a/src/common/cpu/ARM.ts b/src/common/cpu/ARM.ts
index 9221793b..2a42a615 100644
--- a/src/common/cpu/ARM.ts
+++ b/src/common/cpu/ARM.ts
@@ -101,7 +101,8 @@ export interface ARMCoreState {
bankedRegisters: number[][],
spsr: number,
bankedSPSRs: number[],
- cycles: number
+ cycles: number,
+ instructionWidth: 2 | 4
}
interface ARMCoreType {
@@ -122,6 +123,7 @@ interface ARMCoreType {
spsr: number;
mmu: ARMMMUInterface;
irq : ARMIRQInterface;
+ instructionWidth: 2 | 4;
hasSPSR() : boolean;
unpackCPSR(v : number) : void;
@@ -148,6 +150,33 @@ export enum ARMMode {
MODE_SYSTEM = 0x1F
}
+export enum ARMRegs {
+ SP = 13,
+ LR = 14,
+ PC = 15,
+}
+
+export enum ARMConstants {
+
+ BANK_NONE = 0,
+ BANK_FIQ = 1,
+ BANK_IRQ = 2,
+ BANK_SUPERVISOR = 3,
+ BANK_ABORT = 4,
+ BANK_UNDEFINED = 5,
+
+ WORD_SIZE_ARM = 4,
+ WORD_SIZE_THUMB = 2,
+
+ BASE_RESET = 0x00000000,
+ BASE_UNDEF = 0x00000004,
+ BASE_SWI = 0x00000008,
+ BASE_PABT = 0x0000000C,
+ BASE_DABT = 0x00000010,
+ BASE_IRQ = 0x00000018,
+ BASE_FIQ = 0x0000001C,
+}
+
const UNALLOC_MASK = 0x0FFFFF00;
const USER_MASK = 0xF0000000;
const PRIV_MASK = 0x000000CF; // This is out of spec, but it seems to be what's done in other implementations
@@ -2627,14 +2656,14 @@ function ARMCore() {
};
ARMCore.prototype.resetCPU = function(startOffset) {
- for (var i = 0; i < this.PC; ++i) {
+ for (var i = 0; i < ARMRegs.PC; ++i) {
this.gprs[i] = 0;
}
- this.gprs[this.PC] = startOffset + this.WORD_SIZE_ARM;
+ this.gprs[ARMRegs.PC] = startOffset + ARMConstants.WORD_SIZE_ARM;
this.loadInstruction = this.loadInstructionArm;
this.execMode = ARMMode.MODE_ARM;
- this.instructionWidth = this.WORD_SIZE_ARM;
+ this.instructionWidth = ARMConstants.WORD_SIZE_ARM;
this.mode = ARMMode.MODE_SYSTEM;
@@ -2674,21 +2703,21 @@ ARMCore.prototype.resetCPU = function(startOffset) {
var mmu = this.mmu as ARMMMUInterface;
this.step = function() {
- var instruction = this.instruction || (this.instruction = this.loadInstruction(gprs[this.PC] - this.instructionWidth));
- gprs[this.PC] += this.instructionWidth;
+ var instruction = this.instruction || (this.instruction = this.loadInstruction(gprs[ARMRegs.PC] - this.instructionWidth));
+ gprs[ARMRegs.PC] += this.instructionWidth;
this.conditionPassed = true;
instruction();
if (!instruction.writesPC) {
if (this.instruction != null) { // We might have gotten an interrupt from the instruction
if (instruction.next == null || instruction.next.page.invalid) {
- instruction.next = this.loadInstruction(gprs[this.PC] - this.instructionWidth);
+ instruction.next = this.loadInstruction(gprs[ARMRegs.PC] - this.instructionWidth);
}
this.instruction = instruction.next;
}
} else {
if (this.conditionPassed) {
- var pc = gprs[this.PC] &= 0xFFFFFFFE;
+ var pc = gprs[ARMRegs.PC] &= 0xFFFFFFFE;
if (this.execMode == ARMMode.MODE_ARM) {
mmu.wait32(pc);
mmu.waitPrefetch32(pc);
@@ -2696,12 +2725,12 @@ ARMCore.prototype.resetCPU = function(startOffset) {
mmu.wait(pc);
mmu.waitPrefetch(pc);
}
- gprs[this.PC] += this.instructionWidth;
+ gprs[ARMRegs.PC] += this.instructionWidth;
if (!instruction.fixedJump) {
this.instruction = null;
} else if (this.instruction != null) {
if (instruction.next == null || instruction.next.page.invalid) {
- instruction.next = this.loadInstruction(gprs[this.PC] - this.instructionWidth);
+ instruction.next = this.loadInstruction(gprs[ARMRegs.PC] - this.instructionWidth);
}
this.instruction = instruction.next;
}
@@ -2787,7 +2816,8 @@ ARMCore.prototype.freeze = function() : ARMCoreState {
this.bankedSPSRs[4],
this.bankedSPSRs[5]
],
- 'cycles': this.cycles
+ 'cycles': this.cycles,
+ 'instructionWidth': this.instructionWidth,
};
};
@@ -2860,6 +2890,10 @@ ARMCore.prototype.defrost = function(frost: ARMCoreState) {
this.bankedSPSRs[5] = frost.bankedSPSRs[5];
this.cycles = frost.cycles;
+
+ this.instructionWidth = frost.instructionWidth;
+ this.loadInstruction = frost.instructionWidth == 2 ? this.loadInstructionThumb : this.loadInstructionArm;
+ this.execMode = frost.instructionWidth == 2 ? ARMMode.MODE_THUMB : ARMMode.MODE_ARM;
};
ARMCore.prototype.fetchPage = function(address : number) {
@@ -2921,17 +2955,17 @@ ARMCore.prototype.selectBank = function(mode : ARMMode) {
case ARMMode.MODE_USER:
case ARMMode.MODE_SYSTEM:
// No banked registers
- return this.BANK_NONE;
+ return ARMConstants.BANK_NONE;
case ARMMode.MODE_FIQ:
- return this.BANK_FIQ;
+ return ARMConstants.BANK_FIQ;
case ARMMode.MODE_IRQ:
- return this.BANK_IRQ;
+ return ARMConstants.BANK_IRQ;
case ARMMode.MODE_SUPERVISOR:
- return this.BANK_SUPERVISOR;
+ return ARMConstants.BANK_SUPERVISOR;
case ARMMode.MODE_ABORT:
- return this.BANK_ABORT;
+ return ARMConstants.BANK_ABORT;
case ARMMode.MODE_UNDEFINED:
- return this.BANK_UNDEFINED;
+ return ARMConstants.BANK_UNDEFINED;
default:
throw new EmuHalt("Invalid user mode passed to selectBank");
}
@@ -2941,10 +2975,10 @@ ARMCore.prototype.switchExecMode = function(newMode) {
if (this.execMode != newMode) {
this.execMode = newMode;
if (newMode == ARMMode.MODE_ARM) {
- this.instructionWidth = this.WORD_SIZE_ARM;
+ this.instructionWidth = ARMConstants.WORD_SIZE_ARM;
this.loadInstruction = this.loadInstructionArm;
} else {
- this.instructionWidth = this.WORD_SIZE_THUMB;
+ this.instructionWidth = ARMConstants.WORD_SIZE_THUMB;
this.loadInstruction = this.loadInstructionThumb;
}
}
@@ -2963,8 +2997,8 @@ ARMCore.prototype.switchMode = function(newMode) {
if (newBank != oldBank) {
// TODO: support FIQ
if (newMode == ARMMode.MODE_FIQ || this.mode == ARMMode.MODE_FIQ) {
- var oldFiqBank = (oldBank == this.BANK_FIQ) ? 1 : 0;
- var newFiqBank = (newBank == this.BANK_FIQ) ? 1 : 0;
+ var oldFiqBank = (oldBank == ARMConstants.BANK_FIQ) ? 1 : 0;
+ var newFiqBank = (newBank == ARMConstants.BANK_FIQ) ? 1 : 0;
this.bankedRegisters[oldFiqBank][2] = this.gprs[8];
this.bankedRegisters[oldFiqBank][3] = this.gprs[9];
this.bankedRegisters[oldFiqBank][4] = this.gprs[10];
@@ -2976,10 +3010,10 @@ ARMCore.prototype.switchMode = function(newMode) {
this.gprs[11] = this.bankedRegisters[newFiqBank][5];
this.gprs[12] = this.bankedRegisters[newFiqBank][6];
}
- this.bankedRegisters[oldBank][0] = this.gprs[this.SP];
- this.bankedRegisters[oldBank][1] = this.gprs[this.LR];
- this.gprs[this.SP] = this.bankedRegisters[newBank][0];
- this.gprs[this.LR] = this.bankedRegisters[newBank][1];
+ this.bankedRegisters[oldBank][0] = this.gprs[ARMRegs.SP];
+ this.bankedRegisters[oldBank][1] = this.gprs[ARMRegs.LR];
+ this.gprs[ARMRegs.SP] = this.bankedRegisters[newBank][0];
+ this.gprs[ARMRegs.LR] = this.bankedRegisters[newBank][1];
this.bankedSPSRs[oldBank] = this.spsr;
this.spsr = this.bankedSPSRs[newBank];
@@ -3018,8 +3052,8 @@ ARMCore.prototype.raiseIRQ = function() {
var instructionWidth = this.instructionWidth;
this.switchMode(ARMMode.MODE_IRQ);
this.spsr = cpsr;
- this.gprs[this.LR] = this.gprs[this.PC] - instructionWidth + 4;
- this.gprs[this.PC] = this.BASE_IRQ + this.WORD_SIZE_ARM;
+ this.gprs[ARMRegs.LR] = this.gprs[ARMRegs.PC] - instructionWidth + 4;
+ this.gprs[ARMRegs.PC] = this.BASE_IRQ + ARMConstants.WORD_SIZE_ARM;
this.instruction = null;
this.switchExecMode(ARMMode.MODE_ARM);
this.cpsrI = true;
@@ -3030,8 +3064,8 @@ ARMCore.prototype.raiseTrap = function() {
var instructionWidth = this.instructionWidth;
this.switchMode(ARMMode.MODE_SUPERVISOR);
this.spsr = cpsr;
- this.gprs[this.LR] = this.gprs[this.PC] - instructionWidth;
- this.gprs[this.PC] = this.BASE_SWI + this.WORD_SIZE_ARM;
+ this.gprs[ARMRegs.LR] = this.gprs[ARMRegs.PC] - instructionWidth;
+ this.gprs[ARMRegs.PC] = this.BASE_SWI + ARMConstants.WORD_SIZE_ARM;
this.instruction = null;
this.switchExecMode(ARMMode.MODE_ARM);
this.cpsrI = true;
@@ -3213,7 +3247,7 @@ ARMCore.prototype.compileArm = function(instruction) {
// MRS
var rd = (instruction & 0x0000F000) >> 12;
op = this.armCompiler.constructMRS(rd, r, condOp);
- op.writesPC = rd == this.PC;
+ op.writesPC = rd == ARMRegs.PC;
}
} else {
// Data processing/FSR transfer
@@ -3374,7 +3408,7 @@ ARMCore.prototype.compileArm = function(instruction) {
}
break;
}
- op.writesPC = rd == this.PC;
+ op.writesPC = rd == ARMRegs.PC;
}
} else if ((instruction & 0x0FB00FF0) == 0x01000090) {
// Single data swap
@@ -3386,7 +3420,7 @@ ARMCore.prototype.compileArm = function(instruction) {
} else {
op = this.armCompiler.constructSWP(rd, rn, rm, condOp);
}
- op.writesPC = rd == this.PC;
+ op.writesPC = rd == ARMRegs.PC;
} else {
switch (i) {
case 0x00000000:
@@ -3446,7 +3480,7 @@ ARMCore.prototype.compileArm = function(instruction) {
op = this.armCompiler.constructSMLALS(rd, rn, rs, rm, condOp);
break;
}
- op.writesPC = rd == this.PC;
+ op.writesPC = rd == ARMRegs.PC;
} else {
// Halfword and signed byte data transfer
var load = instruction & 0x00100000;
@@ -3465,7 +3499,7 @@ ARMCore.prototype.compileArm = function(instruction) {
} else {
address = this.armCompiler.constructAddressingMode23Register(instruction, rm, condOp);
}
- address.writesPC = !!w && rn == this.PC;
+ address.writesPC = !!w && rn == ARMRegs.PC;
if ((instruction & 0x00000090) == 0x00000090) {
if (load) {
@@ -3489,7 +3523,7 @@ ARMCore.prototype.compileArm = function(instruction) {
op = this.armCompiler.constructSTRH(rd, address, condOp);
}
}
- op.writesPC = rd == this.PC || address.writesPC;
+ op.writesPC = rd == ARMRegs.PC || address.writesPC;
}
break;
case 0x04000000:
@@ -3541,7 +3575,7 @@ ARMCore.prototype.compileArm = function(instruction) {
op = this.armCompiler.constructSTR(rd, address, condOp);
}
}
- op.writesPC = rd == this.PC || address.writesPC;
+ op.writesPC = rd == ARMRegs.PC || address.writesPC;
break;
case 0x08000000:
// Block data transfer
@@ -3733,7 +3767,7 @@ ARMCore.prototype.compileThumb = function(instruction) {
case 0x0000:
// ADD(4)
op = this.thumbCompiler.constructADD4(rd, rm)
- op.writesPC = rd == this.PC;
+ op.writesPC = rd == ARMRegs.PC;
break;
case 0x0100:
// CMP(3)
@@ -3743,7 +3777,7 @@ ARMCore.prototype.compileThumb = function(instruction) {
case 0x0200:
// MOV(3)
op = this.thumbCompiler.constructMOV3(rd, rm);
- op.writesPC = rd == this.PC;
+ op.writesPC = rd == ARMRegs.PC;
break;
case 0x0300:
// BX
@@ -4198,4 +4232,7 @@ export class ARM32CPU implements CPU, InstructionBased, ARMMMUInterface, ARMIRQI
}
updateTimers() : void {
}
+ isThumb() : boolean {
+ return this.core.instructionWidth == 2;
+ }
}
diff --git a/src/ide/ui.ts b/src/ide/ui.ts
index bb88bd3d..8e0bb0db 100644
--- a/src/ide/ui.ts
+++ b/src/ide/ui.ts
@@ -84,7 +84,7 @@ var TOOL_TO_SOURCE_STYLE = {
'basic': 'basic',
'silice': 'verilog',
'wiz': 'text/x-wiz',
- 'vasmarm': '6502'
+ 'vasmarm': 'vasm'
}
function gaEvent(category:string, action:string, label?:string, value?:string) {
diff --git a/src/ide/views.ts b/src/ide/views.ts
index d172a817..04737284 100644
--- a/src/ide/views.ts
+++ b/src/ide/views.ts
@@ -71,6 +71,7 @@ const MODEDEFS = {
z80: { isAsm: true },
jsasm: { isAsm: true },
gas: { isAsm: true },
+ vasm: { isAsm: true },
inform6: { theme: 'cobalt' },
markdown: { lineWrap: true },
fastbasic: { noGutters: true },
diff --git a/src/machine/arm32.ts b/src/machine/arm32.ts
index 648b9f45..d415d539 100644
--- a/src/machine/arm32.ts
+++ b/src/machine/arm32.ts
@@ -89,12 +89,12 @@ export class ARM32Machine extends BasicScanlineMachine implements Debuggable {
getDebugInfo?(category: string, state: EmuState) : string {
var s = '';
var c = state.c as ARMCoreState;
- for (var i=0; i<13; i++) {
- s += lpad('r'+i, 3) + ' ' + hex(c.gprs[i],8) + '\n';
+ const EXEC_MODE = {2:'Thumb',4:'ARM'};
+ const REGNAMES = {15:'PC',14:'LR',13:'SP',12:'IP',11:'FP',9:'SB'};
+ for (var i=0; i<16; i++) {
+ s += lpad(REGNAMES[i]||'',3) + lpad('r'+i, 5) + ' ' + hex(c.gprs[i],8) + '\n';
}
- s += ' SP ' + hex(c.SP,8) + '\n';
- s += ' LR ' + hex(c.gprs[14],8) + '\n';
- s += ' PC ' + hex(c.PC,8) + '\n';
+ s += 'Flags ';
s += c.cpsrN ? " N" : " -";
s += c.cpsrV ? " V" : " -";
s += c.cpsrF ? " F" : " -";
@@ -102,10 +102,9 @@ export class ARM32Machine extends BasicScanlineMachine implements Debuggable {
s += c.cpsrC ? " C" : " -";
s += c.cpsrI ? " I" : " -";
s += '\n';
- s += 'MODE ' + MODE_NAMES[c.mode];
- s += '\n';
- s += 'cycl ' + c.cycles;
- s += '\n';
+ s += 'MODE ' + EXEC_MODE[c.instructionWidth] + ' ' + MODE_NAMES[c.mode] + '\n';
+ s += 'SPSR ' + hex(c.spsr,8) + '\n';
+ s += 'cycl ' + c.cycles + '\n';
return s;
}
}
diff --git a/src/platform/arm32.ts b/src/platform/arm32.ts
index 351c0b17..68557e19 100644
--- a/src/platform/arm32.ts
+++ b/src/platform/arm32.ts
@@ -231,13 +231,15 @@ export abstract class BaseARMMachinePlatform extends BaseMach
class ARM32Platform extends BaseARMMachinePlatform implements Platform {
- capstone : any;
+ capstone_arm : any;
+ capstone_thumb : any;
async start() {
super.start();
console.log("Loading Capstone");
await loadScript('./lib/capstone-arm.min.js');
- this.capstone = new cs.Capstone(cs.ARCH_ARM, cs.MODE_ARM);
+ this.capstone_arm = new cs.Capstone(cs.ARCH_ARM, cs.MODE_ARM);
+ this.capstone_thumb = new cs.Capstone(cs.ARCH_ARM, cs.MODE_THUMB);
}
newMachine() { return new ARM32Machine(); }
@@ -250,11 +252,13 @@ class ARM32Platform extends BaseARMMachinePlatform implements Plat
{name:'Video RAM',start:0x40000000,size:0x20000,type:'ram'},
] } };
disassemble(pc:number, read:(addr:number)=>number) : DisasmLine {
+ var is_thumb = this.machine.cpu.isThumb();
+ var capstone = is_thumb ? this.capstone_thumb : this.capstone_arm;
var buf = [];
for (var i=0; i<4; i++) {
buf[i] = read(pc+i);
}
- var insns = this.capstone.disasm(buf, pc, 4);
+ var insns = capstone.disasm(buf, pc, 4);
var i0 = insns && insns[0];
if (i0) {
return {
diff --git a/src/worker/wasm/vasmarm_std.js b/src/worker/wasm/vasmarm_std.js
index 8fa72141..3a77d013 100644
--- a/src/worker/wasm/vasmarm_std.js
+++ b/src/worker/wasm/vasmarm_std.js
@@ -750,8 +750,8 @@ var wasmMemory;
// so this creates a (non-native-wasm) table for us.
var wasmTable = new WebAssembly.Table({
- 'initial': 109,
- 'maximum': 109,
+ 'initial': 111,
+ 'maximum': 111,
'element': 'anyfunc'
});
@@ -1372,11 +1372,11 @@ function updateGlobalBufferAndViews(buf) {
}
var STATIC_BASE = 1024,
- STACK_BASE = 5270320,
+ STACK_BASE = 5270912,
STACKTOP = STACK_BASE,
- STACK_MAX = 27440,
- DYNAMIC_BASE = 5270320,
- DYNAMICTOP_PTR = 27280;
+ STACK_MAX = 28032,
+ DYNAMIC_BASE = 5270912,
+ DYNAMICTOP_PTR = 27872;
assert(STACK_BASE % 16 === 0, 'stack must start aligned');
assert(DYNAMIC_BASE % 16 === 0, 'heap must start aligned');
@@ -1940,7 +1940,7 @@ var ASM_CONSTS = {
-// STATICTOP = STATIC_BASE + 26416;
+// STATICTOP = STATIC_BASE + 27008;
/* global initializers */ __ATINIT__.push({ func: function() { ___wasm_call_ctors() } });
@@ -4678,7 +4678,7 @@ var ASM_CONSTS = {
}
function _emscripten_get_sbrk_ptr() {
- return 27280;
+ return 27872;
}
function _emscripten_memcpy_big(dest, src, num) {
@@ -4871,6 +4871,12 @@ var stackRestore = Module["stackRestore"] = createExportWrapper("stackRestore");
/** @type {function(...*):?} */
var stackAlloc = Module["stackAlloc"] = createExportWrapper("stackAlloc");
+/** @type {function(...*):?} */
+var dynCall_iii = Module["dynCall_iii"] = createExportWrapper("dynCall_iii");
+
+/** @type {function(...*):?} */
+var dynCall_vii = Module["dynCall_vii"] = createExportWrapper("dynCall_vii");
+
/** @type {function(...*):?} */
var dynCall_vi = Module["dynCall_vi"] = createExportWrapper("dynCall_vi");
@@ -4889,18 +4895,12 @@ var dynCall_vijjiii = Module["dynCall_vijjiii"] = createExportWrapper("dynCall_v
/** @type {function(...*):?} */
var dynCall_vjjjj = Module["dynCall_vjjjj"] = createExportWrapper("dynCall_vjjjj");
-/** @type {function(...*):?} */
-var dynCall_iii = Module["dynCall_iii"] = createExportWrapper("dynCall_iii");
-
/** @type {function(...*):?} */
var dynCall_iiii = Module["dynCall_iiii"] = createExportWrapper("dynCall_iiii");
/** @type {function(...*):?} */
var dynCall_iidiiii = Module["dynCall_iidiiii"] = createExportWrapper("dynCall_iidiiii");
-/** @type {function(...*):?} */
-var dynCall_vii = Module["dynCall_vii"] = createExportWrapper("dynCall_vii");
-
/** @type {function(...*):?} */
var dynCall_jiji = Module["dynCall_jiji"] = createExportWrapper("dynCall_jiji");
diff --git a/src/worker/wasm/vasmarm_std.wasm b/src/worker/wasm/vasmarm_std.wasm
index ae4771a2..ac010d6f 100644
Binary files a/src/worker/wasm/vasmarm_std.wasm and b/src/worker/wasm/vasmarm_std.wasm differ
diff --git a/src/worker/workermain.ts b/src/worker/workermain.ts
index c74b6a66..be8dbed2 100644
--- a/src/worker/workermain.ts
+++ b/src/worker/workermain.ts
@@ -2910,22 +2910,43 @@ function assembleVASMARM(step:BuildStep) {
/// TODO: match undefined symbols
var re_err1 = /^(fatal error|error|warning)? (\d+) in line (\d+) of "(.+)": (.+)/;
var re_err2 = /^(fatal error|error|warning)? (\d+): (.+)/;
+ var re_undefsym = /symbol <(.+?)>/;
var errors : WorkerError[] = [];
+ var undefsyms = [];
+ function findUndefinedSymbols(line:string) {
+ // find undefined symbols in line
+ undefsyms.forEach((sym) => {
+ if (line.indexOf(sym) >= 0) {
+ console.log(sym,line);
+ errors.push({
+ path:curpath,
+ line:curline,
+ msg:"Undefined symbol: " + sym,
+ })
+ }
+ });
+ }
function match_fn(s) {
- var matches = re_err1.exec(s);
+ let matches = re_err1.exec(s);
if (matches) {
errors.push({
line:parseInt(matches[3]),
- path:matches[2],
+ path:matches[4],
msg:matches[5],
});
+ console.log(matches);
} else {
matches = re_err2.exec(s);
if (matches) {
- errors.push({
- line:0,
- msg:s,
- });
+ let m = re_undefsym.exec(matches[3]);
+ if (m) {
+ undefsyms.push(m[1]);
+ } else {
+ errors.push({
+ line:0,
+ msg:s,
+ });
+ }
} else {
console.log(s);
}
@@ -2937,7 +2958,7 @@ function assembleVASMARM(step:BuildStep) {
var lstpath = step.prefix+".lst";
if (staleFiles(step, [objpath])) {
- var args = [ '-Fbin', '-x', '-wfail', step.path, '-o', objpath, '-L', lstpath ];
+ var args = [ '-Fbin', '-m7tdmi', '-x', '-wfail', step.path, '-o', objpath, '-L', lstpath ];
var vasm = emglobal.vasm({
instantiateWasm: moduleInstFn('vasmarm_std'),
noInitialRun:true,
@@ -2952,60 +2973,74 @@ function assembleVASMARM(step:BuildStep) {
return {errors:errors};
}
- var objout = FS.readFile(objpath, {encoding:'binary'});
- putWorkFile(objpath, objout);
- if (!anyTargetChanged(step, [objpath]))
- return;
+ if (undefsyms.length == 0) {
+ var objout = FS.readFile(objpath, {encoding:'binary'});
+ putWorkFile(objpath, objout);
+ if (!anyTargetChanged(step, [objpath]))
+ return;
+ }
var lstout = FS.readFile(lstpath, {encoding:'utf8'});
- //console.log(lstout);
- // F00:0001 mov r0, #0x884400 ; RGB value
- // S01:00000000: 11 0B A0 E3 22 07 80 E3
- // S01 .text
- // F00 vidfill.vasm
- // LOOP LAB (0x10) sec=.text
+ // 00:00000018 023020E0 14: eor r3, r0, r2
+ // Source: "vidfill.vasm"
+ // 00: ".text" (0-40)
+ // LOOP 00:00000018
+ // STACK S:20010000
var symbolmap = {};
- var segments = [];
+ var segments = []; // TODO
var listings : CodeListingMap = {};
// TODO: parse listings
- var re_lstline = /^F(\d+):(\d+)\s+(.+)/;
- var re_secline = /^\s+S(\d+):([0-9A-F]+):\s*([0-9A-F ]+)/;
- var re_nameline = /^([SF])(\d+)\s+(.+)/;
- var files = {};
+ var re_asmline = /^(\d+):([0-9A-F]+)\s+([0-9A-F ]+)\s+(\d+)([:M])/;
+ var re_secline = /^(\d+):\s+"(.+)"/;
+ var re_nameline = /^Source:\s+"(.+)"/;
+ var re_symline = /^(\w+)\s+(\d+):([0-9A-F]+)/;
+ var re_emptyline = /^\s+(\d+)([:M])/;
+ var curpath = step.path;
+ var curline = 0;
var sections = {};
// map file and section indices -> names
- var lines = lstout.split(re_crlf);
- for (var line of lines) {
- var m;
- if (m = re_nameline.exec(line)) {
- if (m[1] == 'F') {
- files[m[2]] = m[3];
- } else {
- sections[m[2]] = m[3];
- }
- }
- }
- //console.log(files, sections);
+ var lines : string[] = lstout.split(re_crlf);
// parse lines
var lstlines : SourceLine[] = [];
- var linenum = 0;
for (var line of lines) {
var m;
- if (m = re_lstline.exec(line)) {
- linenum = parseInt(m[2]);
- } else if (m = re_secline.exec(line)) {
+ if (m = re_secline.exec(line)) {
+ sections[m[1]] = m[2];
+ } else if (m = re_nameline.exec(line)) {
+ curpath = m[1];
+ } else if (m = re_symline.exec(line)) {
+ symbolmap[m[1]] = parseInt(m[3], 16);
+ } else if (m = re_asmline.exec(line)) {
+ if (m[5] == ':') {
+ curline = parseInt(m[4]);
+ } else {
+ // TODO: macro line
+ }
lstlines.push({
- line: linenum,
+ path: curpath,
+ line: curline,
offset: parseInt(m[2], 16),
- path: step.path,
insns: m[3].replaceAll(' ','')
});
+ findUndefinedSymbols(line);
+ } else if (m = re_emptyline.exec(line)) {
+ curline = parseInt(m[1]);
+ findUndefinedSymbols(line);
+ } else {
+ //console.log(line);
}
}
- listings[lstpath] = {lines:lstlines};
+ listings[lstpath] = {lines:lstlines, text:lstout};
+ // catch-all if no error generated
+ if (undefsyms.length && errors.length == 0) {
+ errors.push({
+ line: 0,
+ msg: 'Undefined symbols: ' + undefsyms.join(', ')
+ })
+ }
return {
- output:objout, //.slice(0),
+ output:objout, //.slice(0x34),
listings:listings,
errors:errors,
symbolmap:symbolmap,