Mercurial > lcfOS
annotate test/testasm.py @ 290:7b38782ed496
File moves
author | Windel Bouwman |
---|---|
date | Sun, 24 Nov 2013 11:24:15 +0100 |
parents | 05184b95fa16 |
children | 534b94b40aa8 |
rev | line source |
---|---|
191 | 1 #!/usr/bin/python |
2 | |
199 | 3 import unittest, cProfile |
200 | 4 from ppci import CompilerError |
201 | 5 from asmnodes import AInstruction, ABinop, AUnop, ASymbol, ALabel, ANumber |
6 from asm import tokenize, Assembler | |
290 | 7 import target.armtarget as arm |
236 | 8 import outstream |
9 from target import Label | |
191 | 10 |
290 | 11 |
198 | 12 class AssemblerLexingCase(unittest.TestCase): |
13 """ Tests the assemblers lexer """ | |
191 | 14 |
15 def testLex0(self): | |
16 """ Check if the lexer is OK """ | |
17 asmline, toks = 'mov rax, rbx ', ['ID', 'ID', ',', 'ID'] | |
198 | 18 self.assertSequenceEqual([tok.typ for tok in tokenize(asmline)], toks) |
191 | 19 |
20 def testLex1(self): | |
193 | 21 """ Test if lexer correctly maps some tokens """ |
191 | 22 asmline, toks = 'lab1: mov rax, rbx ', ['ID', ':', 'ID', 'ID', ',', 'ID'] |
198 | 23 self.assertSequenceEqual([tok.typ for tok in tokenize(asmline)], toks) |
191 | 24 |
193 | 25 def testLex1(self): |
26 """ Test if lexer correctly maps some tokens """ | |
27 asmline, toks = 'mov 3.13 0xC 13', ['ID', 'REAL', 'NUMBER', 'NUMBER'] | |
198 | 28 self.assertSequenceEqual([tok.typ for tok in tokenize(asmline)], toks) |
193 | 29 |
191 | 30 def testLex2(self): |
193 | 31 """ Test if lexer fails on a token that is invalid """ |
191 | 32 asmline = '0z4: mov rax, rbx $ ' |
200 | 33 with self.assertRaises(CompilerError): |
198 | 34 list(tokenize(asmline)) |
35 | |
290 | 36 |
198 | 37 class AssemblerParsingTestCase(unittest.TestCase): |
38 """ | |
39 Tests the assembler parts | |
40 """ | |
199 | 41 def setUp(self): |
42 self.a = Assembler() | |
191 | 43 |
44 def testParse(self): | |
45 asmline = 'lab1: mov rax, rbx' | |
199 | 46 self.a.parse_line(asmline) |
191 | 47 |
236 | 48 def expectTree(self, asmline, stack): |
49 self.a.parse_line(asmline) | |
50 self.assertSequenceEqual(stack, self.a.stack) | |
51 | |
193 | 52 def testParse2(self): |
53 asmline = 'a: mov rax, [rbx + 2]' | |
195 | 54 output = [] |
55 output.append(ALabel('a')) | |
56 output.append(AInstruction('mov', [ASymbol('rax'), AUnop('[]', ASymbol('rbx') + ANumber(2))])) | |
236 | 57 self.expectTree(asmline, output) |
194 | 58 |
59 def testParse3(self): | |
60 # A label must be optional: | |
61 asmline = 'mov rax, 1' | |
199 | 62 output = [AInstruction('mov', [ASymbol('rax'), ANumber(1)])] |
236 | 63 self.expectTree(asmline, output) |
195 | 64 |
65 def testParse4(self): | |
66 # Test 3 operands: | |
67 asmline = 'add rax, [4*rbx + 22], rcx' | |
68 ops = [] | |
69 ops.append(ASymbol('rax')) | |
70 ops.append(AUnop('[]', ANumber(4) * ASymbol('rbx') + ANumber(22))) | |
71 ops.append(ASymbol('rcx')) | |
199 | 72 output = [AInstruction('add', ops)] |
236 | 73 self.expectTree(asmline, output) |
195 | 74 |
75 def testParse5(self): | |
76 # An instruction must be optional: | |
77 asmline = 'lab1:' | |
78 output = [] | |
79 output.append(ALabel('lab1')) | |
236 | 80 self.expectTree(asmline, output) |
196 | 81 |
82 def testParse6(self): | |
83 # A line can be empty | |
199 | 84 self.a.parse_line('') |
195 | 85 |
198 | 86 class AssemblerOtherTestCase(unittest.TestCase): |
200 | 87 def testWithoutTarget(self): |
88 a = Assembler() | |
89 with self.assertRaises(CompilerError): | |
90 a.assemble_line('') | |
201 | 91 |
200 | 92 @unittest.skip |
195 | 93 def testX86(self): |
198 | 94 testsrc = """ ; tst |
196 | 95 begin: |
198 | 96 mov rax, rbx ; 0x48, 0x89, 0xd8 |
97 xor rcx, rbx ; 0x48, 0x31, 0xd9 | |
98 inc rcx ; 0x48 0xff 0xc1 | |
196 | 99 """ |
198 | 100 a = Assembler() |
196 | 101 a.assemble(testsrc) |
102 # Compare with nasm output: | |
103 nasmbytes = [0x48, 0x89, 0xd8, 0x48, 0x31, 0xd9, 0x48, 0xff, 0xc1] | |
193 | 104 |
236 | 105 |
106 class OustreamTestCase(unittest.TestCase): | |
107 def test1(self): | |
108 o = outstream.BinOutputStream() | |
109 o.selectSection('.text') | |
110 o.emit(Label('a')) | |
111 self.assertSequenceEqual(bytes(), o.Data) | |
112 | |
113 | |
114 class AsmTestCaseBase(unittest.TestCase): | |
115 def feed(self, line): | |
116 self.a.assemble(line) | |
117 | |
118 def check(self, hexstr): | |
119 self.assertSequenceEqual(bytes.fromhex(hexstr), self.o.Data) | |
120 | |
121 | |
122 class AssemblerMSP430TestCase(AsmTestCaseBase): | |
199 | 123 def setUp(self): |
201 | 124 self.t = msp430.msp430target |
236 | 125 self.o = outstream.BinOutputStream() |
126 self.o.selectSection('.text') | |
127 self.a = Assembler(target=self.t, stream=self.o) | |
200 | 128 |
201 | 129 def testMapMovInstruction(self): |
200 | 130 i = AInstruction('mov', [ASymbol('r14'), ASymbol('r15')]) |
201 | 131 ri = self.t.mapInstruction(i) |
200 | 132 |
201 | 133 def testMapRetiInstruction(self): |
134 i = AInstruction('reti', []) | |
135 ri = self.t.mapInstruction(i) | |
136 | |
137 @unittest.skip | |
200 | 138 def testMapOperand(self): |
139 o = ASymbol('r14') | |
140 mo = self.t.mapOperand(o) | |
141 self.assertEqual(mo, msp430.r14) | |
142 | |
201 | 143 @unittest.skip |
200 | 144 def testMapOperandIndirection(self): |
145 o = AUnop('[]', ASymbol('r14')) | |
146 mo = self.t.mapOperand(o) | |
199 | 147 |
148 def testMov(self): | |
149 line1 = "mov r14, r15" | |
236 | 150 self.feed(line1) |
151 self.check('0F4E') | |
201 | 152 |
153 def testMov1337(self): | |
154 line1 = "mov 0x1337, r12" | |
236 | 155 self.feed(line1) |
156 self.check('3C403713') | |
199 | 157 |
158 def testAdd(self): | |
201 | 159 line1 = "add r15, r13" |
236 | 160 self.feed(line1) |
161 self.check('0D5F') | |
201 | 162 |
163 def testReti(self): | |
164 line1 = "reti" | |
236 | 165 self.feed(line1) |
166 self.check('0013') | |
201 | 167 |
168 def testMSPinstructionCount(self): | |
169 """ Check that there are 27 instructions """ | |
170 self.assertEqual(27, len(self.t.instructions)) | |
199 | 171 |
172 | |
236 | 173 class AssemblerARMTestCase(AsmTestCaseBase): |
202 | 174 def setUp(self): |
218 | 175 self.t = arm.armtarget |
236 | 176 self.o = outstream.BinOutputStream() |
177 self.o.selectSection('.text') | |
178 self.a = Assembler(target=self.t, stream=self.o) | |
232 | 179 |
202 | 180 def testMapOperand(self): |
181 pass | |
182 | |
183 def testMovImm8(self): | |
206 | 184 self.feed('mov r4, 100') |
185 self.check('6424') | |
202 | 186 |
277 | 187 @unittest.skip |
188 def testMovExt(self): | |
189 self.feed('mov r3, sp') | |
190 self.check('') | |
191 | |
202 | 192 def testYield(self): |
206 | 193 self.feed('yield') |
194 self.check('10bf') | |
195 | |
196 def testPush(self): | |
197 self.feed('push {r2,r3,lr}') | |
198 self.check('0cb5') | |
199 | |
200 def testPop(self): | |
201 self.feed('pop {r4-r6, pc}') | |
202 self.check('70bd') | |
202 | 203 |
212 | 204 def testStr5(self): |
205 self.feed('str r4, [r1 + 0]') | |
206 self.check('0c60') | |
207 | |
208 def testLdr5(self): | |
209 self.feed('ldr r4, [r0 + 0]') | |
210 self.check('0468') | |
211 | |
219 | 212 def testLdrSpRel(self): |
213 self.feed('ldr r0, [sp + 4]') | |
214 self.check('0198') | |
215 | |
216 def testStrSpRel(self): | |
217 self.feed('str r0, [sp + 4]') | |
218 self.check('0190') | |
219 | |
234 | 220 def testLdrPcRel(self): |
237 | 221 self.feed('ldr r7, henkie') |
222 self.feed('ldr r6, henkie') | |
234 | 223 self.feed('ldr r1, henkie') |
236 | 224 self.feed('align 4') |
234 | 225 self.feed('dcd 1') |
226 self.feed('henkie: dcd 2') | |
237 | 227 self.check('024F024E 01490000 01000000 02000000') |
228 | |
229 def testBranch(self): | |
230 self.feed('start: b henkie') | |
231 self.feed('beq henkie') | |
232 self.feed('bne henkie') | |
233 self.feed('henkie: b start') | |
234 self.feed('eof: b eof') | |
235 self.check('01e000d0 ffd1fbe7 fee7') | |
236 | |
262 | 237 def testConditions(self): |
238 self.feed('blt x') | |
239 self.feed('bgt x') | |
240 self.feed('x:') | |
241 self.check('00dbffdc') | |
242 | |
237 | 243 def testBoff(self): |
244 self.feed('b henkie') | |
245 self.feed('b henkie') | |
246 self.feed('b henkie') | |
247 self.feed('b henkie') | |
248 self.feed('b henkie') | |
249 self.feed('b henkie') | |
250 self.feed('b henkie') | |
251 self.feed('henkie:') | |
252 self.feed('b henkie') | |
253 self.feed('b henkie') | |
254 self.feed('b henkie') | |
255 self.feed('b henkie') | |
256 self.check('05e004e0 03e002e0 01e000e0 ffe7fee7 fde7fce7 fbe7') | |
234 | 257 |
251
6ed3d3a82a63
Added another c3 example. First import attempt
Windel Bouwman
parents:
238
diff
changeset
|
258 def testBl(self): |
6ed3d3a82a63
Added another c3 example. First import attempt
Windel Bouwman
parents:
238
diff
changeset
|
259 self.feed('bl henkie') |
6ed3d3a82a63
Added another c3 example. First import attempt
Windel Bouwman
parents:
238
diff
changeset
|
260 self.feed('bl henkie') |
6ed3d3a82a63
Added another c3 example. First import attempt
Windel Bouwman
parents:
238
diff
changeset
|
261 self.feed('henkie:') |
6ed3d3a82a63
Added another c3 example. First import attempt
Windel Bouwman
parents:
238
diff
changeset
|
262 self.feed('bl henkie') |
6ed3d3a82a63
Added another c3 example. First import attempt
Windel Bouwman
parents:
238
diff
changeset
|
263 self.feed('bl henkie') |
6ed3d3a82a63
Added another c3 example. First import attempt
Windel Bouwman
parents:
238
diff
changeset
|
264 self.check('00f0 02f8 00f0 00f8 fff7 feff fff7 fcff') |
6ed3d3a82a63
Added another c3 example. First import attempt
Windel Bouwman
parents:
238
diff
changeset
|
265 |
218 | 266 def testCmpRegReg(self): |
267 self.feed('cmp r0, r1') | |
268 self.check('8842') | |
269 | |
276 | 270 def testAddimm3(self): |
271 self.feed('add r3, r5, 2') | |
272 self.feed('add r4, r1, 6') | |
273 self.check('ab1c8c1d') | |
274 | |
275 def testSubImm3(self): | |
276 self.feed('sub r3, r5, 2') | |
277 self.feed('sub r4, r1, 6') | |
278 self.check('ab1e8c1f') | |
279 | |
280 def testLeftShift(self): | |
232 | 281 self.feed('lsl r3, r5') |
282 self.check('ab40') | |
283 | |
276 | 284 def testAddSp(self): |
275 | 285 self.feed('add sp,sp,8') |
286 self.feed('add sp,sp,16') | |
276 | 287 self.check('02b004b0') |
288 | |
289 def testSubSp(self): | |
275 | 290 self.feed('sub sp,sp,32') |
291 self.feed('sub sp,sp,4') | |
276 | 292 self.check('88b081b0') |
275 | 293 |
203 | 294 def testSequence1(self): |
206 | 295 self.feed('mov r5, 3') |
296 self.feed('add r4, r5, 0') | |
297 self.feed('loop: add r6, r4, 7') | |
298 self.feed('cmp r6, 5') | |
207 | 299 self.check('0325 2c1c e61d 052e') |
262 | 300 |
238 | 301 def testSequence2(self): |
302 self.feed('henkie:') | |
303 self.feed('push {r1,r4,r5}') | |
304 self.feed('add r5, r2, r4') | |
305 self.feed('cmp r4, r2') | |
306 self.feed('ldr r0, [sp + 4]') | |
307 self.feed('str r3, [sp + 16]') | |
308 self.feed('pop {r1, r4, r5}') | |
309 self.feed('lsl r3, r4') | |
310 self.feed('cmp r3, r5') | |
311 self.feed('beq henkie') | |
312 self.feed('bne henkie') | |
313 self.feed('b henkie') | |
314 self.check('32b41519 94420198 049332bc a340ab42 f6d0f5d1 f4e7') | |
202 | 315 |
191 | 316 if __name__ == '__main__': |
317 unittest.main() |