Skip to content

Instantly share code, notes, and snippets.

@gfwilliams
Last active August 29, 2015 13:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gfwilliams/9958815 to your computer and use it in GitHub Desktop.
Save gfwilliams/9958815 to your computer and use it in GitHub Desktop.
// 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