Mercurial > lcfOS
changeset 345:b4882ff0ed06
Added more arm isa tests
author | Windel Bouwman |
---|---|
date | Sun, 02 Mar 2014 17:12:08 +0100 |
parents | 1378c4b027a0 |
children | 3bb7dcfe5529 |
files | python/ppci/assembler.py python/ppci/linker.py python/ppci/target/arm/__init__.py python/ppci/target/arm/instructions.py python/ppci/target/arm/token.py python/ppci/target/basetarget.py python/ppci/target/msp430/msp430.py python/ppci/target/target_list.py python/ppci/target/thumb/armtarget.py test/testarmasm.py test/testthumbasm.py |
diffstat | 11 files changed, 430 insertions(+), 180 deletions(-) [+] |
line wrap: on
line diff
--- a/python/ppci/assembler.py Sat Mar 01 16:32:27 2014 +0100 +++ b/python/ppci/assembler.py Sun Mar 02 17:12:08 2014 +0100 @@ -7,10 +7,10 @@ def bit_type(value): - assert value < (2**31) + assert value < (2**32) assert value >= 0 t = 'val32' - for n in [16, 8, 5, 3]: + for n in [16, 12, 8, 5, 3]: if value < (2**n): t = 'val{}'.format(n) return t @@ -100,7 +100,7 @@ # Construct a parser given a grammar: tokens2 = ['ID', 'NUMBER', ',', '[', ']', ':', '+', '-', '*', pyyacc.EPS, 'COMMENT', '{', '}', - pyyacc.EOF, 'val32', 'val16', 'val8', 'val5', 'val3'] + pyyacc.EOF, 'val32', 'val16', 'val12', 'val8', 'val5', 'val3'] tokens2.extend(kws) self.kws = kws g = pyyacc.Grammar(tokens2)
--- a/python/ppci/linker.py Sat Mar 01 16:32:27 2014 +0100 +++ b/python/ppci/linker.py Sun Mar 02 17:12:08 2014 +0100 @@ -76,6 +76,18 @@ section.data[reloc.offset] |= imm6 section.data[reloc.offset + 1] |= (s << 2) +# ARM reloc!! +# TODO: move to target classes??? +@reloc('b_imm24') +def apply_b_imm24(reloc, sym, section, reloc_value): + assert sym.value % 4 == 0 + assert reloc_value % 4 == 0 + offset = (sym.value - (reloc_value + 8)) + rel24 = wrap_negative(offset >> 2, 24) + section.data[reloc.offset+2] = (rel24 >> 16) & 0xFF + section.data[reloc.offset+1] = (rel24 >> 8) & 0xFF + section.data[reloc.offset+0] = rel24 & 0xFF + class Linker: """ Merges the sections of several object files and
--- a/python/ppci/target/arm/__init__.py Sat Mar 01 16:32:27 2014 +0100 +++ b/python/ppci/target/arm/__init__.py Sun Mar 02 17:12:08 2014 +0100 @@ -1,16 +1,16 @@ from ..basetarget import Target -from ..arm.registers import R0, R1, R2, R3, R4, R5, R6, R7, SP, LR, PC +from ..arm.registers import R0, R1, R2, R3, R4, R5, R6, R7 +from ..arm.registers import R8, R9, R10, R11, R12, SP, LR, PC from ..arm.registers import register_range -from .instructions import Mov +from .instructions import Mov, Add, Sub, Orr1, B, Bl, Ble, Bgt, Beq -class ArmArmTarget(Target): +class ArmTarget(Target): def __init__(self): super().__init__('arm_arm') # Assembly grammar: - self.add_keyword('mov') self.add_keyword('r0') self.add_keyword('r1') self.add_keyword('r2') @@ -19,6 +19,11 @@ self.add_keyword('r5') self.add_keyword('r6') self.add_keyword('r7') + self.add_keyword('r8') + self.add_keyword('r9') + self.add_keyword('r10') + self.add_keyword('r11') + self.add_keyword('r12') self.add_rule('reg', ['r0'], lambda rhs: R0) self.add_rule('reg', ['r1'], lambda rhs: R1) @@ -28,15 +33,45 @@ self.add_rule('reg', ['r5'], lambda rhs: R5) self.add_rule('reg', ['r6'], lambda rhs: R6) self.add_rule('reg', ['r7'], lambda rhs: R7) + self.add_rule('reg', ['r8'], lambda rhs: R8) + self.add_rule('reg', ['r9'], lambda rhs: R9) + self.add_rule('reg', ['r10'], lambda rhs: R10) + self.add_rule('reg', ['r11'], lambda rhs: R11) + self.add_rule('reg', ['r12'], lambda rhs: R12) + self.add_keyword('mov') self.add_instruction(['mov', 'reg', ',', 'imm8'], lambda rhs: Mov(rhs[1], rhs[3])) - self.add_rule('imm32', ['val32'], lambda x: x[0].val) - self.add_rule('imm32', ['imm8'], lambda x: x[0]) - self.add_rule('imm8', ['val8'], lambda x: x[0].val) - self.add_rule('imm8', ['imm5'], lambda x: x[0]) - self.add_rule('imm5', ['val5'], lambda x: x[0].val) - self.add_rule('imm5', ['imm3'], lambda x: x[0]) - self.add_rule('imm3', ['val3'], lambda x: x[0].val) + self.add_keyword('add') + self.add_instruction(['add', 'reg', ',', 'reg', ',', 'imm32'], + lambda rhs: Add(rhs[1], rhs[3], rhs[5])) + + self.add_instruction(['add', 'reg', ',', 'reg', ',', 'reg'], + lambda rhs: Add(rhs[1], rhs[3], rhs[5])) + + self.add_keyword('sub') + self.add_instruction(['sub', 'reg', ',', 'reg', ',', 'imm32'], + lambda rhs: Sub(rhs[1], rhs[3], rhs[5])) + + self.add_instruction(['sub', 'reg', ',', 'reg', ',', 'reg'], + lambda rhs: Sub(rhs[1], rhs[3], rhs[5])) + + self.add_keyword('orr') + self.add_instruction(['orr', 'reg', ',', 'reg', ',', 'reg'], + lambda rhs: Orr1(rhs[1], rhs[3], rhs[5])) + + + # Jumping: + self.add_keyword('b') + self.add_instruction(['b', 'ID'], lambda rhs: B(rhs[1].val)) + self.add_keyword('ble') + self.add_instruction(['ble', 'ID'], lambda rhs: Ble(rhs[1].val)) + self.add_keyword('bgt') + self.add_instruction(['bgt', 'ID'], lambda rhs: Bgt(rhs[1].val)) + self.add_keyword('beq') + self.add_instruction(['beq', 'ID'], lambda rhs: Beq(rhs[1].val)) + + self.add_keyword('bl') + self.add_instruction(['bl', 'ID'], lambda rhs: Bl(rhs[1].val))
--- a/python/ppci/target/arm/instructions.py Sat Mar 01 16:32:27 2014 +0100 +++ b/python/ppci/target/arm/instructions.py Sun Mar 02 17:12:08 2014 +0100 @@ -3,8 +3,41 @@ from ..basetarget import Instruction from .token import ArmToken -from .registers import R0, SP +from .registers import R0, SP, ArmRegister + +# Helpers: + +def rotate_right(v, n): + """ bit-wise Rotate right n times """ + mask = (2**n) - 1 + mask_bits = v & mask + return (v >> n) | (mask_bits << (32 - n)) + +def rotate_left(v, n): + assert n >= 0 + assert n < 32 + return rotate_right(v, 32 - n) +masks = [rotate_right(0xFF, i * 2) for i in range(16)] +#0x000000FF, +#0xC000007F, +#0xF000000F, +#0xFC000003, +#0xFF000000, # 4 + +assert masks[4] == 0xFF000000, hex(masks[4]) + +def encode_imm32(v): + """ Bundle 32 bit value into 4 bits rotation and 8 bits value + """ + for i in range(0, 16): + v2 = rotate_left(v, i*2) + if (v2 & 0xFFFFFF00) == 0: + rotation = i + val = v2 & 0xFF + x = (rotation << 8) | val + return x + raise Exception("Invalid value {}".format(v)) # Instructions: @@ -22,7 +55,7 @@ def encode(self): self.token[0:12] = self.imm - self.token[12:16] = self.reg.num + self.token.Rd = self.reg.num self.token[16:20] = 0 self.token[20] = 0 self.token[21:28] = 0b0011101 @@ -33,5 +66,129 @@ return [] def __repr__(self): - return 'DCD 0x{0:X}'.format(self.expr) + return 'Mov {}, {}'.format(self.reg, self.imm) + + +def Add(*args): + if len(args) == 3 and isinstance(args[0], ArmRegister) and \ + isinstance(args[1], ArmRegister): + if isinstance(args[2], ArmRegister): + return Add1(args[0], args[1], args[2]) + elif isinstance(args[2], int): + return Add2(args[0], args[1], args[2]) + raise Exception() + +def Sub(*args): + if len(args) == 3 and isinstance(args[0], ArmRegister) and \ + isinstance(args[1], ArmRegister): + if isinstance(args[2], ArmRegister): + return Sub1(args[0], args[1], args[2]) + elif isinstance(args[2], int): + return Sub2(args[0], args[1], args[2]) + raise Exception() + +class OpRegRegReg(ArmInstruction): + """ add rd, rn, rm """ + def __init__(self, rd, rn, rm, shift=0): + super().__init__() + self.rd = rd + self.rn = rn + self.rm = rm + + def encode(self): + self.token[0:4] = self.rm.num + self.token[4] = 0 + self.token[5:7] = 0 + self.token[7:12] = 0 # Shift + self.token.Rd = self.rd.num + self.token.Rn = self.rn.num + self.token.S = 0 # Set flags + self.token[21:28] = self.opcode + self.token.cond = 0xE # Always! + return self.token.encode() + + def __repr__(self): + return 'add {}, {}, {}'.format(self.rd, self.rn, self.rm) + + +class Add1(OpRegRegReg): + opcode = 0b0000100 + + +class Sub1(OpRegRegReg): + opcode = 0b0000010 + + +class Orr1(OpRegRegReg): + opcode = 0b0001100 + +class OpRegRegImm(ArmInstruction): + """ add rd, rn, imm12 """ + def __init__(self, rd, rn, imm): + super().__init__() + self.rd = rd + self.rn = rn + self.imm2 = encode_imm32(imm) + self.imm = imm + + def encode(self): + self.token[0:12] = self.imm2 + self.token.Rd = self.rd.num + self.token.Rn = self.rn.num + self.token.S = 0 # Set flags + self.token[21:28] = self.opcode + self.token.cond = 0xE # Always! + return self.token.encode() + + def __repr__(self): + return 'add {}, {}, {}'.format(self.rd, self.rn, self.imm) + + +class Add2(OpRegRegImm): + opcode = 0b0010100 + + +class Sub2(OpRegRegImm): + opcode = 0b0010010 + + + +# Branches: + +class BranchBaseRoot(ArmInstruction): + def __init__(self, target): + super().__init__() + self.target = target + + def encode(self): + self.token.cond = self.cond + self.token[24:28] = self.opcode + return self.token.encode() + + def relocations(self): + return [(self.target, 'b_imm24')] + + +class BranchBase(BranchBaseRoot): + opcode = 0b1010 + +class BranchLinkBase(BranchBaseRoot): + opcode = 0b1011 + +class Bl(BranchLinkBase): + cond = 0xE + +class B(BranchBase): + cond = 0xE + +class Beq(BranchBase): + cond = 0x0 + +class Bgt(BranchBase): + cond = 0xC + +class Ble(BranchBase): + cond = 0xD + +
--- a/python/ppci/target/arm/token.py Sat Mar 01 16:32:27 2014 +0100 +++ b/python/ppci/target/arm/token.py Sun Mar 02 17:12:08 2014 +0100 @@ -7,6 +7,9 @@ super().__init__(32) cond = bit_range(28, 32) + S = bit_range(20, 21) + Rd = bit_range(12, 16) + Rn = bit_range(16, 20) def encode(self): return u32(self.bit_value)
--- a/python/ppci/target/basetarget.py Sat Mar 01 16:32:27 2014 +0100 +++ b/python/ppci/target/basetarget.py Sun Mar 02 17:12:08 2014 +0100 @@ -135,6 +135,24 @@ self.assembler_rules = [] self.asm_keywords = [] + # Base rules for constants: + self.add_rule('imm32', ['val32'], lambda x: x[0].val) + self.add_rule('imm32', ['imm16'], lambda x: x[0]) + + self.add_rule('imm16', ['val16'], lambda x: x[0].val) + self.add_rule('imm16', ['imm12'], lambda x: x[0]) + + self.add_rule('imm12', ['val12'], lambda x: x[0].val) + self.add_rule('imm12', ['imm8'], lambda x: x[0]) + + self.add_rule('imm8', ['val8'], lambda x: x[0].val) + self.add_rule('imm8', ['imm5'], lambda x: x[0]) + + self.add_rule('imm5', ['val5'], lambda x: x[0].val) + self.add_rule('imm5', ['imm3'], lambda x: x[0]) + + self.add_rule('imm3', ['val3'], lambda x: x[0].val) + def add_keyword(self, kw): self.asm_keywords.append(kw)
--- a/python/ppci/target/msp430/msp430.py Sat Mar 01 16:32:27 2014 +0100 +++ b/python/ppci/target/msp430/msp430.py Sun Mar 02 17:12:08 2014 +0100 @@ -40,16 +40,6 @@ self.add_keyword('reti') self.add_instruction(['reti'], lambda rhs: Reti()) - # Constants: - self.add_rule('imm32', ['val32'], lambda x: x[0].val) - self.add_rule('imm32', ['imm16'], lambda x: x[0]) - self.add_rule('imm16', ['val16'], lambda x: x[0].val) - self.add_rule('imm16', ['imm8'], lambda x: x[0]) - self.add_rule('imm8', ['val8'], lambda x: x[0].val) - self.add_rule('imm8', ['imm5'], lambda x: x[0]) - self.add_rule('imm5', ['val5'], lambda x: x[0].val) - self.add_rule('imm5', ['imm3'], lambda x: x[0]) - self.add_rule('imm3', ['val3'], lambda x: x[0].val) msp430target = Msp430Target()
--- a/python/ppci/target/target_list.py Sat Mar 01 16:32:27 2014 +0100 +++ b/python/ppci/target/target_list.py Sun Mar 02 17:12:08 2014 +0100 @@ -1,10 +1,10 @@ -from .arm import ArmArmTarget +from .arm import ArmTarget from .thumb import ThumbTarget from .msp430.msp430 import msp430target # Instance: -arm_target = ArmArmTarget() +arm_target = ArmTarget() thumb_target = ThumbTarget() target_list = [arm_target, thumb_target]
--- a/python/ppci/target/thumb/armtarget.py Sat Mar 01 16:32:27 2014 +0100 +++ b/python/ppci/target/thumb/armtarget.py Sun Mar 02 17:12:08 2014 +0100 @@ -146,12 +146,4 @@ self.add_rule('reg8', ['r5'], lambda rhs: R5) self.add_rule('reg8', ['r6'], lambda rhs: R6) self.add_rule('reg8', ['r7'], lambda rhs: R7) - # Constants: - self.add_rule('imm32', ['val32'], lambda x: x[0].val) - self.add_rule('imm32', ['imm8'], lambda x: x[0]) - self.add_rule('imm8', ['val8'], lambda x: x[0].val) - self.add_rule('imm8', ['imm5'], lambda x: x[0]) - self.add_rule('imm5', ['val5'], lambda x: x[0].val) - self.add_rule('imm5', ['imm3'], lambda x: x[0]) - self.add_rule('imm3', ['val3'], lambda x: x[0].val)
--- a/test/testarmasm.py Sat Mar 01 16:32:27 2014 +0100 +++ b/test/testarmasm.py Sun Mar 02 17:12:08 2014 +0100 @@ -3,152 +3,11 @@ from ppci.objectfile import ObjectFile from asm import Assembler from testasm import AsmTestCaseBase -from ppci.target.target_list import arm_target, thumb_target +from ppci.target.target_list import arm_target -class ThumbAssemblerTestCase(AsmTestCaseBase): - def setUp(self): - self.t = thumb_target - self.obj = ObjectFile() - self.o = BinaryOutputStream(self.obj) - self.o.selectSection('.text') - self.a = Assembler(target=self.t, stream=self.o) - def testMovImm8(self): - self.feed('mov r4, 100') - self.check('6424') - - @unittest.skip - def testMovExt(self): - self.feed('mov r3, sp') - self.check('') - - def testYield(self): - self.feed('yield') - self.check('10bf') - - def testPush(self): - self.feed('push {r2,r3,lr}') - self.check('0cb5') - - def testPop(self): - self.feed('pop {r4-r6, pc}') - self.check('70bd') - - def testStr5(self): - self.feed('str r4, [r1 + 0]') - self.check('0c60') - - def testLdr5(self): - self.feed('ldr r4, [r0 + 0]') - self.check('0468') - - def testLdrSpRel(self): - self.feed('ldr r0, [sp + 4]') - self.check('0198') - - def testStrSpRel(self): - self.feed('str r0, [sp + 4]') - self.check('0190') - - def testLdrPcRel(self): - self.feed('ldr r7, henkie') - self.feed('ldr r6, henkie') - self.feed('ldr r1, henkie') - self.feed('align 4') - self.feed('dcd 1') - self.feed('henkie: dcd 2') - self.check('024F024E 01490000 01000000 02000000') - - def testBranch(self): - self.feed('start: b henkie') - self.feed('beq henkie') - self.feed('bne henkie') - self.feed('henkie: b start') - self.feed('eof: b eof') - self.check('01e000d0 ffd1fbe7 fee7') - - def testConditions(self): - self.feed('blt x') - self.feed('bgt x') - self.feed('x:') - self.check('00dbffdc') - - def testBoff(self): - self.feed('b henkie') - self.feed('b henkie') - self.feed('b henkie') - self.feed('b henkie') - self.feed('b henkie') - self.feed('b henkie') - self.feed('b henkie') - self.feed('henkie:') - self.feed('b henkie') - self.feed('b henkie') - self.feed('b henkie') - self.feed('b henkie') - self.check('05e004e0 03e002e0 01e000e0 ffe7fee7 fde7fce7 fbe7') - - def testBl(self): - self.feed('bl henkie') - self.feed('bl henkie') - self.feed('henkie:') - self.feed('bl henkie') - self.feed('bl henkie') - self.check('00f0 02f8 00f0 00f8 fff7 feff fff7 fcff') - - def testCmpRegReg(self): - self.feed('cmp r0, r1') - self.check('8842') - - def testAddimm3(self): - self.feed('add r3, r5, 2') - self.feed('add r4, r1, 6') - self.check('ab1c8c1d') - - def testSubImm3(self): - self.feed('sub r3, r5, 2') - self.feed('sub r4, r1, 6') - self.check('ab1e8c1f') - - def testLeftShift(self): - self.feed('lsl r3, r5') - self.check('ab40') - - def testAddSp(self): - self.feed('add sp,sp,8') - self.feed('add sp,sp,16') - self.check('02b004b0') - - def testSubSp(self): - self.feed('sub sp,sp,32') - self.feed('sub sp,sp,4') - self.check('88b081b0') - - def testSequence1(self): - self.feed('mov r5, 3') - self.feed('add r4, r5, 0') - self.feed('loop: add r6, r4, 7') - self.feed('cmp r6, 5') - self.check('0325 2c1c e61d 052e') - - def testSequence2(self): - self.feed('henkie:') - self.feed('push {r1,r4,r5}') - self.feed('add r5, r2, r4') - self.feed('cmp r4, r2') - self.feed('ldr r0, [sp + 4]') - self.feed('str r3, [sp + 16]') - self.feed('pop {r1, r4, r5}') - self.feed('lsl r3, r4') - self.feed('cmp r3, r5') - self.feed('beq henkie') - self.feed('bne henkie') - self.feed('b henkie') - self.check('32b41519 94420198 049332bc a340ab42 f6d0f5d1 f4e7') - - -class AssemblerArmTestCase(AsmTestCaseBase): +class ArmAssemblerTestCase(AsmTestCaseBase): """ ARM-mode (not thumb-mode) instruction assembly test case """ def setUp(self): self.t = arm_target @@ -160,3 +19,37 @@ def testMovImm(self): self.feed('mov r4, 100') self.check('6440a0e3') + + def testAdd2(self): + self.feed('add r12, r11, 300') + self.check('4bcf8be2') + + def testAdd1(self): + self.feed('add r9, r7, r2') + self.check('029087e0') + + def testSub1(self): + self.feed('sub r5, r6, r2') + self.check('025046e0') + + def testSub2(self): + self.feed('sub r0, r1, 0x80000001') + self.check('060141e2') + + def testOrr1(self): + self.feed('orr r8, r7, r6') + self.check('068087e1') + + def testBranches(self): + self.feed('b sjakie') + self.feed('ble sjakie') + self.feed('bgt sjakie') + self.feed('beq sjakie') + self.feed('bl sjakie') + self.feed('sjakie:') + self.feed('b sjakie') + self.feed('ble sjakie') + self.feed('bgt sjakie') + self.feed('beq sjakie') + self.feed('bl sjakie') + self.check('030000ea 020000da 010000ca 0000000a ffffffeb feffffea fdffffda fcffffca fbffff0a faffffeb')
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/testthumbasm.py Sun Mar 02 17:12:08 2014 +0100 @@ -0,0 +1,150 @@ +import unittest +from ppci.outstream import BinaryOutputStream +from ppci.objectfile import ObjectFile +from asm import Assembler +from testasm import AsmTestCaseBase +from ppci.target.target_list import thumb_target + + +class ThumbAssemblerTestCase(AsmTestCaseBase): + def setUp(self): + self.t = thumb_target + self.obj = ObjectFile() + self.o = BinaryOutputStream(self.obj) + self.o.selectSection('.text') + self.a = Assembler(target=self.t, stream=self.o) + + def testMovImm8(self): + self.feed('mov r4, 100') + self.check('6424') + + @unittest.skip + def testMovExt(self): + self.feed('mov r3, sp') + self.check('') + + def testYield(self): + self.feed('yield') + self.check('10bf') + + def testPush(self): + self.feed('push {r2,r3,lr}') + self.check('0cb5') + + def testPop(self): + self.feed('pop {r4-r6, pc}') + self.check('70bd') + + def testStr5(self): + self.feed('str r4, [r1 + 0]') + self.check('0c60') + + def testLdr5(self): + self.feed('ldr r4, [r0 + 0]') + self.check('0468') + + def testLdrSpRel(self): + self.feed('ldr r0, [sp + 4]') + self.check('0198') + + def testStrSpRel(self): + self.feed('str r0, [sp + 4]') + self.check('0190') + + def testLdrPcRel(self): + self.feed('ldr r7, henkie') + self.feed('ldr r6, henkie') + self.feed('ldr r1, henkie') + self.feed('align 4') + self.feed('dcd 1') + self.feed('henkie: dcd 2') + self.check('024F024E 01490000 01000000 02000000') + + def testBranch(self): + self.feed('start: b henkie') + self.feed('beq henkie') + self.feed('bne henkie') + self.feed('henkie: b start') + self.feed('eof: b eof') + self.check('01e000d0 ffd1fbe7 fee7') + + def testConditions(self): + self.feed('blt x') + self.feed('bgt x') + self.feed('x:') + self.check('00dbffdc') + + def testBoff(self): + self.feed('b henkie') + self.feed('b henkie') + self.feed('b henkie') + self.feed('b henkie') + self.feed('b henkie') + self.feed('b henkie') + self.feed('b henkie') + self.feed('henkie:') + self.feed('b henkie') + self.feed('b henkie') + self.feed('b henkie') + self.feed('b henkie') + self.check('05e004e0 03e002e0 01e000e0 ffe7fee7 fde7fce7 fbe7') + + def testBl(self): + self.feed('bl henkie') + self.feed('bl henkie') + self.feed('henkie:') + self.feed('bl henkie') + self.feed('bl henkie') + self.check('00f0 02f8 00f0 00f8 fff7 feff fff7 fcff') + + def testCmpRegReg(self): + self.feed('cmp r0, r1') + self.check('8842') + + def testAddimm3(self): + self.feed('add r3, r5, 2') + self.feed('add r4, r1, 6') + self.check('ab1c8c1d') + + def testSubImm3(self): + self.feed('sub r3, r5, 2') + self.feed('sub r4, r1, 6') + self.check('ab1e8c1f') + + def testLeftShift(self): + self.feed('lsl r3, r5') + self.check('ab40') + + def testAddSp(self): + self.feed('add sp,sp,8') + self.feed('add sp,sp,16') + self.check('02b004b0') + + def testSubSp(self): + self.feed('sub sp,sp,32') + self.feed('sub sp,sp,4') + self.check('88b081b0') + + def testSequence1(self): + self.feed('mov r5, 3') + self.feed('add r4, r5, 0') + self.feed('loop: add r6, r4, 7') + self.feed('cmp r6, 5') + self.check('0325 2c1c e61d 052e') + + def testSequence2(self): + self.feed('henkie:') + self.feed('push {r1,r4,r5}') + self.feed('add r5, r2, r4') + self.feed('cmp r4, r2') + self.feed('ldr r0, [sp + 4]') + self.feed('str r3, [sp + 16]') + self.feed('pop {r1, r4, r5}') + self.feed('lsl r3, r4') + self.feed('cmp r3, r5') + self.feed('beq henkie') + self.feed('bne henkie') + self.feed('b henkie') + self.check('32b41519 94420198 049332bc a340ab42 f6d0f5d1 f4e7') + +