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