Mercurial > lcfOS
comparison python/testasm.py @ 236:8786811a5a59
Fix pcrel
author | Windel Bouwman |
---|---|
date | Mon, 15 Jul 2013 20:15:31 +0200 |
parents | 83781bd10fdb |
children | 81752b0f85a5 |
comparison
equal
deleted
inserted
replaced
235:ff40407c0240 | 236:8786811a5a59 |
---|---|
4 from ppci import CompilerError | 4 from ppci import CompilerError |
5 from asmnodes import AInstruction, ABinop, AUnop, ASymbol, ALabel, ANumber | 5 from asmnodes import AInstruction, ABinop, AUnop, ASymbol, ALabel, ANumber |
6 from asm import tokenize, Assembler | 6 from asm import tokenize, Assembler |
7 import msp430 | 7 import msp430 |
8 import cortexm3 as arm | 8 import cortexm3 as arm |
9 import outstream | |
10 from target import Label | |
9 | 11 |
10 class AssemblerLexingCase(unittest.TestCase): | 12 class AssemblerLexingCase(unittest.TestCase): |
11 """ Tests the assemblers lexer """ | 13 """ Tests the assemblers lexer """ |
12 | 14 |
13 def testLex0(self): | 15 def testLex0(self): |
40 | 42 |
41 def testParse(self): | 43 def testParse(self): |
42 asmline = 'lab1: mov rax, rbx' | 44 asmline = 'lab1: mov rax, rbx' |
43 self.a.parse_line(asmline) | 45 self.a.parse_line(asmline) |
44 | 46 |
47 def expectTree(self, asmline, stack): | |
48 self.a.parse_line(asmline) | |
49 self.assertSequenceEqual(stack, self.a.stack) | |
50 | |
45 def testParse2(self): | 51 def testParse2(self): |
46 asmline = 'a: mov rax, [rbx + 2]' | 52 asmline = 'a: mov rax, [rbx + 2]' |
47 self.a.parse_line(asmline) | |
48 output = [] | 53 output = [] |
49 output.append(ALabel('a')) | 54 output.append(ALabel('a')) |
50 output.append(AInstruction('mov', [ASymbol('rax'), AUnop('[]', ASymbol('rbx') + ANumber(2))])) | 55 output.append(AInstruction('mov', [ASymbol('rax'), AUnop('[]', ASymbol('rbx') + ANumber(2))])) |
51 self.assertSequenceEqual(output, self.a.output) | 56 self.expectTree(asmline, output) |
52 | 57 |
53 def testParse3(self): | 58 def testParse3(self): |
54 # A label must be optional: | 59 # A label must be optional: |
55 asmline = 'mov rax, 1' | 60 asmline = 'mov rax, 1' |
56 self.a.parse_line(asmline) | |
57 output = [AInstruction('mov', [ASymbol('rax'), ANumber(1)])] | 61 output = [AInstruction('mov', [ASymbol('rax'), ANumber(1)])] |
58 self.assertSequenceEqual(output, self.a.output) | 62 self.expectTree(asmline, output) |
59 | 63 |
60 def testParse4(self): | 64 def testParse4(self): |
61 # Test 3 operands: | 65 # Test 3 operands: |
62 asmline = 'add rax, [4*rbx + 22], rcx' | 66 asmline = 'add rax, [4*rbx + 22], rcx' |
63 self.a.parse_line(asmline) | |
64 ops = [] | 67 ops = [] |
65 ops.append(ASymbol('rax')) | 68 ops.append(ASymbol('rax')) |
66 ops.append(AUnop('[]', ANumber(4) * ASymbol('rbx') + ANumber(22))) | 69 ops.append(AUnop('[]', ANumber(4) * ASymbol('rbx') + ANumber(22))) |
67 ops.append(ASymbol('rcx')) | 70 ops.append(ASymbol('rcx')) |
68 output = [AInstruction('add', ops)] | 71 output = [AInstruction('add', ops)] |
69 self.assertSequenceEqual(output, self.a.output) | 72 self.expectTree(asmline, output) |
70 | 73 |
71 def testParse5(self): | 74 def testParse5(self): |
72 # An instruction must be optional: | 75 # An instruction must be optional: |
73 asmline = 'lab1:' | 76 asmline = 'lab1:' |
74 self.a.parse_line(asmline) | |
75 output = [] | 77 output = [] |
76 output.append(ALabel('lab1')) | 78 output.append(ALabel('lab1')) |
77 self.assertSequenceEqual(output, self.a.output) | 79 self.expectTree(asmline, output) |
78 | 80 |
79 def testParse6(self): | 81 def testParse6(self): |
80 # A line can be empty | 82 # A line can be empty |
81 self.a.parse_line('') | 83 self.a.parse_line('') |
82 | 84 |
97 a = Assembler() | 99 a = Assembler() |
98 a.assemble(testsrc) | 100 a.assemble(testsrc) |
99 # Compare with nasm output: | 101 # Compare with nasm output: |
100 nasmbytes = [0x48, 0x89, 0xd8, 0x48, 0x31, 0xd9, 0x48, 0xff, 0xc1] | 102 nasmbytes = [0x48, 0x89, 0xd8, 0x48, 0x31, 0xd9, 0x48, 0xff, 0xc1] |
101 | 103 |
102 class AssemblerMSP430TestCase(unittest.TestCase): | 104 |
105 class OustreamTestCase(unittest.TestCase): | |
106 def test1(self): | |
107 o = outstream.BinOutputStream() | |
108 o.selectSection('.text') | |
109 o.emit(Label('a')) | |
110 self.assertSequenceEqual(bytes(), o.Data) | |
111 | |
112 | |
113 class AsmTestCaseBase(unittest.TestCase): | |
114 def feed(self, line): | |
115 self.a.assemble(line) | |
116 | |
117 def check(self, hexstr): | |
118 self.assertSequenceEqual(bytes.fromhex(hexstr), self.o.Data) | |
119 | |
120 | |
121 class AssemblerMSP430TestCase(AsmTestCaseBase): | |
103 def setUp(self): | 122 def setUp(self): |
104 self.t = msp430.msp430target | 123 self.t = msp430.msp430target |
105 self.a = Assembler(target=self.t) | 124 self.o = outstream.BinOutputStream() |
125 self.o.selectSection('.text') | |
126 self.a = Assembler(target=self.t, stream=self.o) | |
106 | 127 |
107 def testMapMovInstruction(self): | 128 def testMapMovInstruction(self): |
108 i = AInstruction('mov', [ASymbol('r14'), ASymbol('r15')]) | 129 i = AInstruction('mov', [ASymbol('r14'), ASymbol('r15')]) |
109 ri = self.t.mapInstruction(i) | 130 ri = self.t.mapInstruction(i) |
110 | 131 |
123 o = AUnop('[]', ASymbol('r14')) | 144 o = AUnop('[]', ASymbol('r14')) |
124 mo = self.t.mapOperand(o) | 145 mo = self.t.mapOperand(o) |
125 | 146 |
126 def testMov(self): | 147 def testMov(self): |
127 line1 = "mov r14, r15" | 148 line1 = "mov r14, r15" |
128 self.a.assemble_line(line1) | 149 self.feed(line1) |
129 self.assertEqual(bytes([0x0F, 0x4E]), self.a.binout) | 150 self.check('0F4E') |
130 | 151 |
131 def testMov1337(self): | 152 def testMov1337(self): |
132 line1 = "mov 0x1337, r12" | 153 line1 = "mov 0x1337, r12" |
133 self.a.assemble_line(line1) | 154 self.feed(line1) |
134 self.assertEqual(bytes.fromhex('3C403713'), self.a.binout) | 155 self.check('3C403713') |
135 | 156 |
136 def testAdd(self): | 157 def testAdd(self): |
137 line1 = "add r15, r13" | 158 line1 = "add r15, r13" |
138 self.a.assemble_line(line1) | 159 self.feed(line1) |
139 self.assertEqual(bytes.fromhex('0D5F'), self.a.binout) | 160 self.check('0D5F') |
140 | 161 |
141 def testReti(self): | 162 def testReti(self): |
142 line1 = "reti" | 163 line1 = "reti" |
143 self.a.assemble_line(line1) | 164 self.feed(line1) |
144 self.assertEqual(bytes([0x0, 0x13]), self.a.binout) | 165 self.check('0013') |
145 | 166 |
146 def testMSPinstructionCount(self): | 167 def testMSPinstructionCount(self): |
147 """ Check that there are 27 instructions """ | 168 """ Check that there are 27 instructions """ |
148 self.assertEqual(27, len(self.t.instructions)) | 169 self.assertEqual(27, len(self.t.instructions)) |
149 | 170 |
150 | 171 |
151 class AssemblerARMTestCase(unittest.TestCase): | 172 class AssemblerARMTestCase(AsmTestCaseBase): |
152 def setUp(self): | 173 def setUp(self): |
153 self.t = arm.armtarget | 174 self.t = arm.armtarget |
154 self.a = Assembler(target=self.t) | 175 self.o = outstream.BinOutputStream() |
155 | 176 self.o.selectSection('.text') |
156 def feed(self, line): | 177 self.a = Assembler(target=self.t, stream=self.o) |
157 self.a.assemble(line) | |
158 | |
159 def check(self, hexstr): | |
160 self.assertSequenceEqual(bytes.fromhex(hexstr), self.a.binout) | |
161 | 178 |
162 def testMapOperand(self): | 179 def testMapOperand(self): |
163 pass | 180 pass |
164 | 181 |
165 def testMovImm8(self): | 182 def testMovImm8(self): |
194 self.feed('str r0, [sp + 4]') | 211 self.feed('str r0, [sp + 4]') |
195 self.check('0190') | 212 self.check('0190') |
196 | 213 |
197 def testLdrPcRel(self): | 214 def testLdrPcRel(self): |
198 self.feed('ldr r1, henkie') | 215 self.feed('ldr r1, henkie') |
216 self.feed('align 4') | |
199 self.feed('dcd 1') | 217 self.feed('dcd 1') |
200 self.feed('henkie: dcd 2') | 218 self.feed('henkie: dcd 2') |
201 self.check('04490100000002000000') | 219 self.check('014900000100000002000000') |
202 | 220 |
203 def testCmpRegReg(self): | 221 def testCmpRegReg(self): |
204 self.feed('cmp r0, r1') | 222 self.feed('cmp r0, r1') |
205 self.check('8842') | 223 self.check('8842') |
206 | 224 |