Last active
August 29, 2015 13:58
-
-
Save gfwilliams/9958815 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// http://ece.uwaterloo.ca/~ece222/ARM/ARM7-TDMI-manual-pt3.pdf | |
function rlist_lr(value) { | |
var regs = value.split(","); | |
var vals = { r0:1,r1:2,r2:4,r3:8,r4:16,r5:32,r6:64,r7:128,lr:256 }; | |
var bits = 0; | |
for (var i in regs) { | |
var reg = regs[i].trim(); | |
if (!(reg in vals)) throw "Unknown register name "+reg; | |
bits |= vals[reg]; | |
} | |
return bits; | |
} | |
function reg(reg_offset) { | |
return function(reg) { | |
var vals = { r0:0,r1:1,r2:2,r3:3,r4:4,r5:5,r6:6,r7:7 }; | |
if (!(reg in vals)) throw "Unknown register name "+reg; | |
return vals[reg]<<reg_offset; | |
} | |
} | |
function reg_or_immediate(reg_offset, immediate_bit) { | |
return function(reg) { | |
var regVal = parseInt(reg); | |
if (regVal>=0 && regVal<8) | |
return ((regVal&7)<<reg_offset) | (1<<immediate_bit); | |
var vals = { r0:0,r1:1,r2:2,r3:3,r4:4,r5:5,r6:6,r7:7 }; | |
if (!(reg in vals)) throw "Unknown register name, or immediate out of range 0..7 "+reg; | |
return vals[reg]<<reg_offset; | |
} | |
} | |
function reg_base_offset(base_offset, offset_offset) { | |
return function(value) { | |
var parms = value.split(","); | |
return reg(base_offset)(parms[0]) | reg(offset_offset)(parms[0]); | |
} | |
} | |
function uint7_shr2(offset) { | |
return function(value) { | |
var bits = parseInt(value); | |
if (bits>=0 && bits<=511 && (bits&3)==0) | |
return (bits>>2)<<offset; | |
throw "Invalid number '"+value+"' - must be between 0 and 508 and a multiple of 4" | |
} | |
} | |
function uint8_shr2(offset) { | |
return function(value) { | |
var bits = parseInt(value); | |
if (bits>=0 && bits<=1023 && (bits&3)==0) | |
return (bits>>2)<<offset; | |
throw "Invalid number '"+value+"' - must be between 0 and 1020 and a multiple of 4" | |
} | |
} | |
function uint8(offset) { | |
return function(value) { | |
var bits = parseInt(value); | |
if (bits>=0 && bits<=255) | |
return bits<<offset; | |
throw "Invalid number '"+value+"' - must be between 0 and 255" | |
} | |
} | |
function uint5_shr2(offset) { | |
return function(value) { | |
var bits = parseInt(value); | |
if (bits>=0 && bits<=63*4) | |
return (bits>>2)<<offset; | |
throw "Invalid number '"+value+"' - must be between 0 and 255 and a multiple of 4" | |
} | |
} | |
var ops = { | |
"push" :[{ base:"1011010-________", regex : /^{(.*)}$/, args:[rlist_lr] }], | |
"pop" :[{ base:"1011110-________", regex : /^{(.*)}$/, args:[rlist_lr] }], | |
"add" :[{ base:"10100---________", regex : /^(r[0-7]),pc,#([0-9]+)$/,args:[reg(8),uint8_shr2(0)] }, | |
{ base:"10101---________", regex : /^(r[0-7]),sp,#([0-9]+)$/, args:[reg(8),uint8_shr2(0)] }, | |
{ base:"101100000_______", regex : /^sp,#([0-9]+)$/, args:[uint7_shr2(0)] }, | |
/* { base:"00011-0___---___", regex : /^(r[0-7]),(r[0-7]),([^,]+)$/, args:[reg(0),reg(3),reg_or_immediate(6,10)] } */], // ? | |
"adds" :[{ base:"00011-0___---___", regex : /^(r[0-7]),(r[0-7]),([^,]+)$/, args:[reg(0),reg(3),reg_or_immediate(6,10)] } ], | |
"adc.w":[{ base:"111010110100----________--------", regex : /^(r[0-7]),(r[0-7]),(r[0-7])$/,args:[reg(16),reg(8),reg(0)] }], // made this up. probably wrong | |
"add.w":[{ base:"11110001--------________--------", regex : /^(r[0-7]),(r[0-7]),#([0-9]+)$/,args:[reg(16),reg(8),uint8(0)] }], // made this up. probably wrong | |
"sub" :[/*{ base:"10100---________", regex : /^([^,]+),pc,#([0-9]+)$/,args:[reg(8),uint8_shr2(0)] },*/ | |
{ base:"101100001_______", regex : /^sp,#([0-9]+)$/, args:[uint7_shr2(0)] }, | |
{ base:"00011-1___---___", regex : /^([^,]+),([^,]+),([^,]+)$/, args:[reg(0),reg(3),reg_or_immediate(6,10)] } ], | |
"str" :[{ base:"0101000---___---", regex : /(r[0-7]),\[(r[0-7]),(r[0-7])\]/, args:[reg(0),reg(3),reg(6)] }, | |
{ base:"0110000---___---", regex : /(r[0-7]),\[(r[0-7]),#([0-9]+)\]/, args:[reg(0),reg(3), uint5_shr2(6)] }], | |
"strb" :[{ base:"0101010---___---", regex : /(r[0-7]),\[(r[0-7]),(r[0-7])\]/, args:[reg(0),reg(3),reg(6)] }], | |
"ldr" :[{ base:"0101100---___---", regex : /(r[0-7]),\[(r[0-7]),(r[0-7])\]/, args:[reg(0),reg(3),reg(6)] }, | |
{ base:"0110100---___---", regex : /(r[0-7]),\[(r[0-7]),#([0-9]+)\]/, args:[reg(0),reg(3), uint5_shr2(6)] }], | |
"ldrb" :[{ base:"0101110---___---", regex : /(r[0-7]),\[(r[0-7]),(r[0-7])\]/, args:[reg(0),reg(3),reg(6)] }], | |
"mov" :[{ base:"0100011000---___", regex : /(r[0-7]),(r[0-7])/, args:[reg(0),reg(3)] }, | |
{ base:"0100011010---101", regex : /sp,(r[0-7])/, args:[reg(3)] }], // made up again | |
"movs" :[{ base:"00100---________", regex : /(r[0-7]),#([0-9]+)/, args:[reg(8),uint8(0)] }], | |
"bx" :[{ base:"0100011101110000", regex : /lr/, args:[] }], // made up again | |
"nop" :[{ base:"1011111100000000", regex : "", args:[] }], // made up again | |
}; | |
function getOpCode(binary) { | |
var base = ""; | |
for (var b in binary) | |
if ("-_".indexOf(binary[b])>=0) | |
base += "0"; | |
else | |
base += binary[b]; | |
var opCode = parseInt(base,2); | |
if (opCode<0) opCode = opCode + 2147483648.0; | |
return opCode; | |
} | |
function asm(text) { | |
text.split("\n").forEach(function (line) { | |
line = line.trim(); | |
console.log("'"+line+"'"); | |
if (line=="") return; | |
var firstArgEnd = line.indexOf("\t"); | |
if (firstArgEnd<0) firstArgEnd = line.indexOf(" "); | |
if (firstArgEnd<0) firstArgEnd=line.length; | |
var opName = line.substr(0,firstArgEnd); | |
var args = line.substr(firstArgEnd).replace(/[ \t]/g,"").trim(); | |
if (!(opName in ops)) throw "Unknown Op '"+opName+"'"; | |
// search ops | |
var found = false; | |
for (var n in ops[opName]) { | |
var op = ops[opName][n]; | |
var m; | |
if (m=args.match(op.regex)) { | |
found = true; | |
// work out the base opcode | |
var opCode = getOpCode(op.base); | |
// remove the first element | |
for (var i in op.args) { | |
//console.log(i,m[(i|0)+1]); | |
var argFunction = op.args[i]; | |
var bits = argFunction(m[(i|0)+1]); | |
//console.log(" ",bits) | |
opCode |= bits; | |
} | |
if (opCode<0 || opCode>0xFFFF) | |
console.log((opCode>>>16).toString(16), (opCode&0xFFFF).toString(16)); | |
else | |
console.log(opCode.toString(16)); | |
break; | |
} | |
} | |
// now parse args | |
if (!found) | |
throw "Unknown arg style '"+args+"' in '"+line+"'"; | |
}); | |
} | |
var text = "push {r7}\n"+ | |
"sub sp, #12\n"+ | |
"add r7, sp, #0\n"+ | |
"str r0, [r7, #4]\n"+ | |
"ldr r3, [r7, #4]\n"+ | |
"add.w r3, r3, #2\n"+ | |
"mov r0, r3\n"+ | |
"add.w r7, r7, #12\n"+ | |
"mov sp, r7\n"+ | |
"pop {r7}\n"+ | |
"bx lr\n"+ | |
"nop\n"; | |
/*var text = | |
"movs r2, #2 \n"+ | |
"movs r3, #0 \n"+ | |
"adds r2, r2, r0\n"+ | |
"adc.w r3, r3, r1\n"+ | |
"mov r0, r2 \n"+ | |
"mov r1, r3 \n"+ | |
"bx lr \n";*/ | |
asm(text); | |
/* | |
0: b480 push {r7} | |
2: b083 sub sp, #12 | |
4: af00 add r7, sp, #0 | |
6: 6078 str r0, [r7, #4] | |
8: 687b ldr r3, [r7, #4] | |
a: f103 0302 add.w r3, r3, #2 | |
e: 4618 mov r0, r3 | |
10: f107 070c add.w r7, r7, #12 | |
14: 46bd mov sp, r7 | |
16: bc80 pop {r7} | |
18: 4770 bx lr | |
1a: bf00 nop | |
0: 2202 movs r2, #2 | |
2: 2300 movs r3, #0 | |
4: 1812 adds r2, r2, r0 | |
6: eb43 0301 adc.w r3, r3, r1 | |
a: 4610 mov r0, r2 | |
c: 4619 mov r1, r3 | |
e: 4770 bx lr | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment