Skip to content

Instantly share code, notes, and snippets.

@daeken
Created June 12, 2016 17:50
Show Gist options
  • Save daeken/b1d037684ab3f85377e350eba0fd7d8a to your computer and use it in GitHub Desktop.
Save daeken/b1d037684ab3f85377e350eba0fd7d8a to your computer and use it in GitHub Desktop.
import re
def regex(pattern, flags=0):
def sub(text):
match = pattern.match(text)
if match == None:
return False
return match.groups()
pattern = re.compile(pattern, flags)
return sub
labels = {}
mlabel = regex(r'^\s*([a-zA-Z0-9.]+):\s*$')
mint = regex(r'^(-?[0-9]+)$')
mref = regex(r'^(-?[0-9]+)\(\$([0-9]+)\)$')
def parseOperand(op):
if op in labels:
return [labels[op]]
elif op.startswith('$'):
return [int(op[1:])]
elif op.startswith('0x'):
return [int(op[2:], 16)]
elif op.startswith('-0x'):
return [-int(op[3:], 16)]
elif mint(op):
return [int(op)]
elif mref(op):
return list(map(int, mref(op)))
else:
print 'unknown', op
def processInsn(mnem, ops):
if mnem == 'nop':
return [('sll', ('0', '0', '0'))]
else:
return [(mnem, ops)]
def assemble(base, code):
insns = []
for line in code.split('\n'):
line = line.split('#', 1)[0]
match = mlabel(line)
if match:
label = match[0]
labels[label] = base + len(insns) * 4
elif line.strip():
line = line.strip().split(' ', 1)
if len(line) == 1:
mnem, rest = line[0], ''
else:
mnem, rest = line
ops = [x.strip() for x in rest.split(',') if x.strip()]
insns += processInsn(mnem.lower(), ops)
out = []
for i, (mnem, ops) in enumerate(insns):
ops = reduce(lambda a, b: a+b, map(parseOperand, ops))
out.append(buildInsn(base + i * 4, mnem, ops))
return out
def unsigned(val, size):
if val >= 0:
return val
else:
return (1 << size) + val
def buildInsn(addr, mnem, ops):
if mnem not in indefs:
print 'Unknown instruction:', mnem, ops
return 0
inst = 0
type, odef, params = indefs[mnem]
if type == IType:
inst |= odef << 26
for i, name in enumerate(params):
val = ops[i]
if name == rs:
inst |= unsigned(val, 5) << 21
elif name == rt:
inst |= unsigned(val, 5) << 16
elif name == imm:
inst |= unsigned(val, 16)
elif type == JType:
inst |= odef << 26
for i, name in enumerate(params):
val = ops[i]
if name == target:
inst |= (val & 0x0FFFFFFF) >> 2
elif type == RType:
inst |= odef[0] << 26
inst |= odef[1]
for i, name in enumerate(params):
val = ops[i]
if name == rs:
inst |= unsigned(val, 5) << 21
elif name == rt:
inst |= unsigned(val, 5) << 16
elif name == rd:
inst |= unsigned(val, 5) << 11
elif name == shamt:
inst |= unsigned(val, 5) << 6
else:
print 'Unknown type:', type
return inst
IType, JType, RType = 'itype', 'jtype', 'rtype'
imm, offset, rd, rs, rt, shamt, target = 'imm', 'offset', 'rd', 'rs', 'rt', 'shamt', 'target'
indefs = dict(
add=(RType, (0b000000, 0b100000), (rd, rs, rt)),
addi=(IType, 0b001000, (rt, rs, imm)),
j=(JType, 0b000010, (target, )),
lb=(IType, 0b100000, (rt, offset, rs)),
lbu=(IType, 0b100100, (rt, offset, rs)),
sll=(RType, (0b000000, 0b000000), (rd, rt, shamt)),
)
import disasm
def disassemble(base, insns):
for i, insn in enumerate(insns):
print '%08x %s' % (base + i * 4, disasm.disassemble(base + i * 4, insn))
print
print disassemble(0x80100000, assemble(0x80100000, '''
j .part1
j .part2
addi $3, $0, 1
.part1:
addi $1, $0, 1
j end
nop
.part2:
addi $2, $0, 1
end:
nop
'''))
print disassemble(0x80100000, assemble(0x80100000, '''
lb $1, 0($30)
lbu $2, 0($30)
#lh $3, 0($30)
#lw $4, 0($30)
'''))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment