Mercurial > lcfOS
changeset 203:ca1ea402f6a1
Added some arm instructions
author | Windel Bouwman |
---|---|
date | Sat, 15 Jun 2013 19:13:05 +0200 |
parents | f22b431f4113 |
children | de3a68f677a5 |
files | python/arm_cm3.py python/asm.py python/asmnodes.py python/msp430.py python/target.py python/testasm.py python/thex.py |
diffstat | 7 files changed, 152 insertions(+), 58 deletions(-) [+] |
line wrap: on
line diff
--- a/python/arm_cm3.py Sat Jun 15 10:02:50 2013 +0200 +++ b/python/arm_cm3.py Sat Jun 15 19:13:05 2013 +0200 @@ -8,25 +8,6 @@ armtarget = Target('arm') -# Add a custom operand mapping method: -def mapOp(self, operand): - if type(operand) is ASymbol: - # try to map to register: - regs = {} - for r in self.registers: - regs[r.name] = r - if operand.name in regs: - reg = regs[operand.name] - return reg - elif type(operand) is ANumber: - return ArmImm(operand.number) - raise CompilerError('Cannot map {0}'.format(operand)) - -armtarget.mapOperand = types.MethodType(mapOp, armtarget) - -# Define: -registers = 'r0,r1,r2,r3,r4,r5' - class ArmReg(Register): def __init__(self, num, name): super().__init__(name) @@ -36,9 +17,52 @@ def __init__(self, i): self.i = i +class RegOp: + def __init__(self, num): + assert num < 8 + self.num = num + + @classmethod + def Create(cls, vop): + if type(vop) is ASymbol: + name = vop.name + regs = {} + for r in armtarget.registers: + regs[r.name] = r + if name in regs: + r = regs[name] + return cls(r.num) + +class Imm8: + def __init__(self, imm): + assert imm < 256 + self.imm = imm + + @classmethod + def Create(cls, vop): + if type(vop) is ANumber and vop.number < 256: + return cls(vop.number) + +class Imm3: + def __init__(self, imm): + assert imm < 8 + assert type(imm) is int + self.imm = imm + + @classmethod + def Create(cls, vop): + if type(vop) is ANumber and vop.number < 8: + return cls(vop.number) + # 8 bit registers: r4 = ArmReg(4, 'r4') armtarget.registers.append(r4) +r5 = ArmReg(5, 'r5') +armtarget.registers.append(r5) +r6 = ArmReg(6, 'r6') +armtarget.registers.append(r6) +r7 = ArmReg(7, 'r7') +armtarget.registers.append(r7) class ArmInstruction(Instruction): pass @@ -49,15 +73,21 @@ opcode = 1337 +class Operand2: + def __init__(self, expr): + if type(expr) is ANumber: + pass + pass + @armtarget.instruction class mov_ins(ArmInstruction): """ mov Rd, imm8, move immediate value into register """ mnemonic = 'mov' - opcode = 4 # 00100 - operands = (ArmReg, ArmImm) - def __init__(self, r, imm): - self.imm = imm.i - self.r = r.num + opcode = 4 # 00100 Rd(3) imm8 + operands = (RegOp, Imm8) + def __init__(self, rd, imm): + self.imm = imm.imm + self.r = rd.num def encode(self): rd = self.r opcode = self.opcode @@ -65,6 +95,59 @@ h = (opcode << 11) | (rd << 8) | imm8 return u16(h) +@armtarget.instruction +class movregreg_ins(ArmInstruction): + """ mov Rd, Rm """ + mnemonic = 'mov' + opcode = 8 # 01000 Rd(3) imm8 + operands = (RegOp, RegOp) + def __init__(self, rd, rm): + self.rd = rd + self.rm = rm + def encode(self): + rd = self.rd.num + D = (rd & 0x8) >> 3 + assert D < 2 + rd = rd & 0x7 + rm = self.rm.num + assert rm < 16 + opcode = self.opcode + h = (opcode << 11) | (3 << 9) | (D << 7) | (rm << 3) | rd + return u16(h) + +@armtarget.instruction +class addregregimm3_ins(ArmInstruction): + """ add Rd, Rn, imm3 """ + mnemonic = 'add' + opcode = 3 # 00011 + operands = (RegOp, RegOp, Imm3) + def __init__(self, rd, rn, imm3): + self.rd = rd + self.rn = rn + self.imm3 = imm3 + def encode(self): + rd = self.rd.num + rn = self.rn.num + imm3 = self.imm3.imm + opcode = self.opcode + h = (opcode << 11) | (1 << 10) | (imm3 << 6) | (rn << 3) | rd + return u16(h) + +@armtarget.instruction +class cmpregimm8_ins(ArmInstruction): + """ cmp Rn, imm8 """ + mnemonic = 'cmp' + opcode = 5 # 00101 + operands = (RegOp, Imm8) + def __init__(self, rn, imm): + self.rn = rn + self.imm = imm + def encode(self): + rn = self.rn.num + imm = self.imm.imm + opcode = self.opcode + h = (opcode << 11) | (rn << 8) | imm + return u16(h) @armtarget.instruction class yield_ins(ArmInstruction):
--- a/python/asm.py Sat Jun 15 10:02:50 2013 +0200 +++ b/python/asm.py Sat Jun 15 19:13:05 2013 +0200 @@ -160,10 +160,11 @@ raise CompilerError('Cannot assemble without target') while self.output: vi = self.output.pop(0) - ri = self.target.mapInstruction(vi) - b = ri.encode() - assert type(b) is bytes - self.binout.extend(b) + if type(vi) is AInstruction: + ri = self.target.mapInstruction(vi) + b = ri.encode() + assert type(b) is bytes + self.binout.extend(b) def back_patch(self): """ Fix references to earlier labels """
--- a/python/asmnodes.py Sat Jun 15 10:02:50 2013 +0200 +++ b/python/asmnodes.py Sat Jun 15 19:13:05 2013 +0200 @@ -12,12 +12,12 @@ return '{0}:'.format(self.name) class AInstruction(ANode): - def __init__(self, opcode, operands): - self.opcode = opcode + def __init__(self, mnemonic, operands): + self.mnemonic = mnemonic self.operands = operands def __repr__(self): ops = ', '.join(map(str, self.operands)) - return '{0} {1}'.format(self.opcode, ops) + return '{0} {1}'.format(self.mnemonic, ops) class AExpression(ANode): def __add__(self, other):
--- a/python/msp430.py Sat Jun 15 10:02:50 2013 +0200 +++ b/python/msp430.py Sat Jun 15 19:13:05 2013 +0200 @@ -12,25 +12,6 @@ #TODO: add more modes! IMMEDIATE_MODE = 7 - - -# Add a custom operand mapping method: -def mapOp(self, operand): - if type(operand) is ASymbol: - # try to map to register: - regs = {} - for r in self.registers: - regs[r.name] = r - if operand.name in regs: - reg = regs[operand.name] - return MSP430Operand(REGISTER_MODE, reg.num) - elif type(operand) is ANumber: - # Immediate mode: - return MSP430Operand(IMMEDIATE_MODE, operand.number) - raise CompilerError('Cannot map {0}'.format(operand)) - -msp430target.mapOperand = types.MethodType(mapOp, msp430target) - # Target description for the MSP430 processor class MSP430Reg(Register): @@ -83,7 +64,20 @@ if self.mode == IMMEDIATE_MODE: return pack_ins(self.param) return bytes() - + + @classmethod + def Create(cls, vop): + if type(vop) is ASymbol: + # try to map to register: + regs = {} + for r in msp430target.registers: + regs[r.name] = r + if vop.name in regs: + reg = regs[vop.name] + return cls(REGISTER_MODE, reg.num) + elif type(vop) is ANumber: + # Immediate mode: + return cls(IMMEDIATE_MODE, vop.number) def pack_ins(h): return struct.pack('<H', h)
--- a/python/target.py Sat Jun 15 10:02:50 2013 +0200 +++ b/python/target.py Sat Jun 15 19:13:05 2013 +0200 @@ -1,4 +1,4 @@ -from asmnodes import ASymbol, AInstruction +from asmnodes import ASymbol, AInstruction, ALabel from ppci import CompilerError """ @@ -45,16 +45,20 @@ raise CompilerError('Cannot map {0}'.format(operand)) def mapInstruction(self, vi): + assert type(vi) is AInstruction """ Map ast tree to real instruction for this target """ # map to real operands: - rops = tuple(map(self.mapOperand, vi.operands)) - optypes = tuple(map(type, rops)) # look for a suitable instruction for ic in self.instructions: - if ic.mnemonic == vi.opcode and ic.operands == optypes: - ri = ic(*rops) - return ri + if ic.mnemonic == vi.mnemonic and len(ic.operands) == len(vi.operands): + # Try to map operands to the correct operand types: + rops = [roptype.Create(vop) for roptype, vop in zip(ic.operands, vi.operands)] + + # Check if we succeeded: + optypes = tuple(map(type, rops)) + if ic.operands == optypes: + return ic(*rops) raise CompilerError('No suitable instruction found for "{0}"'.format(vi))
--- a/python/testasm.py Sat Jun 15 10:02:50 2013 +0200 +++ b/python/testasm.py Sat Jun 15 19:13:05 2013 +0200 @@ -164,8 +164,17 @@ self.a.assemble('yield') self.assertEqual(bytes.fromhex('10bf'), self.a.binout) + def testSequence1(self): + self.a.assemble('mov r5, 3') + self.a.assemble('add r4, r5, 0') + self.a.assemble('loop: add r6, r4, 7') + self.a.assemble('cmp r6, 5') + #self.a.assemble('ble loop') + #self.assertEqual(bytes.fromhex('0325 2c1c e61d 052e fcdd'), self.a.binout) + self.assertEqual(bytes.fromhex('0325 2c1c e61d 052e'), self.a.binout) # without branch + if __name__ == '__main__': - # cProfile.run('unittest.main()') + #cProfile.run('unittest.main()') unittest.main()
--- a/python/thex.py Sat Jun 15 10:02:50 2013 +0200 +++ b/python/thex.py Sat Jun 15 19:13:05 2013 +0200 @@ -12,6 +12,9 @@ self.bv = self.ui.he.bv # Provide some random data: self.bv.Data = bytearray(range(10)) * 8 + b'x' + def tearDown(self): + self.app.processEvents() + self.app.quit() def testOpenButton(self): QTest.mouseClick(self.bv, Qt.LeftButton) self.assertEqual(self.bv.CursorPosition, 161)