Mercurial > lcfOS
comparison python/codegenarm.py @ 279:2ccd57b1d78c
Fix register allocator to do burn2 OK
author | Windel Bouwman |
---|---|
date | Sat, 12 Oct 2013 09:56:23 +0200 |
parents | 046017431c6a |
children | 02385f62f250 |
comparison
equal
deleted
inserted
replaced
278:9fca39eebe50 | 279:2ccd57b1d78c |
---|---|
68 Add code for the prologue and the epilogue. Add a label, the | 68 Add code for the prologue and the epilogue. Add a label, the |
69 return instruction and the stack pointer adjustment for the frame. | 69 return instruction and the stack pointer adjustment for the frame. |
70 """ | 70 """ |
71 self.instructions.insert(0, makeIns('{}:'.format(self.name))) | 71 self.instructions.insert(0, makeIns('{}:'.format(self.name))) |
72 self.instructions.insert(1, makeIns('push {lr, r7}')) | 72 self.instructions.insert(1, makeIns('push {lr, r7}')) |
73 self.instructions.insert(2, makeIns('mov r7, sp')) | 73 # Reserve stack space for locals: |
74 self.instructions.insert(3, makeIns('add sp, sp, {}'.format(self.stacksize))) | 74 self.instructions.insert(2, makeIns('sub sp, sp, {}'.format(self.stacksize))) |
75 self.instructions.append(makeIns('sub sp, sp, {}'.format(self.stacksize))) | 75 # Setup frame pointer: |
76 self.instructions.insert(3, makeIns('mov r7, sp')) | |
77 # Stack grows downwards | |
78 self.instructions.append(makeIns('add sp, sp, {}'.format(self.stacksize))) | |
76 self.instructions.append(makeIns('pop {pc,r7}')) | 79 self.instructions.append(makeIns('pop {pc,r7}')) |
77 # Add constant literals: | 80 # Add constant literals: |
81 self.instructions.append(makeIns('align 4')) # Align at 4 bytes | |
78 for ln, v in self.constants: | 82 for ln, v in self.constants: |
79 self.instructions.append(makeIns('{}:'.format(ln))) | 83 self.instructions.append(makeIns('{}:'.format(ln))) |
80 self.instructions.append(makeIns('dcd {}'.format(v))) | 84 self.instructions.append(makeIns('dcd {}'.format(v))) |
81 | 85 |
82 | 86 |
84 | 88 |
85 """ Instruction selector for the arm architecture """ | 89 """ Instruction selector for the arm architecture """ |
86 def munchExpr(self, e): | 90 def munchExpr(self, e): |
87 if isinstance(e, ir.Alloc): | 91 if isinstance(e, ir.Alloc): |
88 return 0 | 92 return 0 |
89 elif isinstance(e, ir.Binop) and e.operation == '+' and isinstance(e.b, ir.Const) and e.b.value < 8: | 93 elif isinstance(e, ir.Binop) and e.operation == '+' and \ |
94 isinstance(e.b, ir.Const) and e.b.value < 8: | |
90 a = self.munchExpr(e.a) | 95 a = self.munchExpr(e.a) |
91 d = self.newTmp() | 96 d = self.newTmp() |
92 self.emit('add %d0, %s0, {}'.format(e.b.value), dst=[d], src=[a]) | 97 self.emit('add %d0, %s0, {}'.format(e.b.value), dst=[d], src=[a]) |
93 return d | 98 return d |
94 elif isinstance(e, ir.Binop) and e.operation == '+': | 99 elif isinstance(e, ir.Binop) and e.operation == '+': |
95 a = self.munchExpr(e.a) | 100 a = self.munchExpr(e.a) |
96 b = self.munchExpr(e.b) | 101 b = self.munchExpr(e.b) |
97 d = self.newTmp() | 102 d = self.newTmp() |
98 self.emit('add %d0, %s0, %s1', dst=[d], src=[a, b]) | 103 self.emit('add %d0, %s0, %s1', dst=[d], src=[a, b]) |
99 return d | 104 return d |
100 elif isinstance(e, ir.Binop) and e.operation == '-' and isinstance(e.b, ir.Const) and e.b.value < 8: | 105 elif isinstance(e, ir.Binop) and e.operation == '-' and \ |
106 isinstance(e.b, ir.Const) and e.b.value < 8: | |
101 a = self.munchExpr(e.a) | 107 a = self.munchExpr(e.a) |
102 d = self.newTmp() | 108 d = self.newTmp() |
103 self.emit('sub %d0, %s0, {}'.format(e.b.value), dst=[d], src=[a]) | 109 self.emit('sub %d0, %s0, {}'.format(e.b.value), dst=[d], src=[a]) |
104 return d | 110 return d |
105 elif isinstance(e, ir.Binop) and e.operation == '-': | 111 elif isinstance(e, ir.Binop) and e.operation == '-': |
110 return d | 116 return d |
111 elif isinstance(e, ir.Binop) and e.operation == '|': | 117 elif isinstance(e, ir.Binop) and e.operation == '|': |
112 a = self.munchExpr(e.a) | 118 a = self.munchExpr(e.a) |
113 b = self.munchExpr(e.b) | 119 b = self.munchExpr(e.b) |
114 d = self.newTmp() | 120 d = self.newTmp() |
115 self.emit('mov %d0, %s0', src=[a], dst=[d]) | 121 self.move(d, a) |
116 self.emit('orr %d0, %s0', dst=[d], src=[b, d]) | 122 self.emit('orr %s1, %s0', dst=[], src=[b, d]) |
117 return d | 123 return d |
118 elif isinstance(e, ir.Binop) and e.operation == '<<': | 124 elif isinstance(e, ir.Binop) and e.operation == '<<': |
119 a = self.munchExpr(e.a) | 125 a = self.munchExpr(e.a) |
120 b = self.munchExpr(e.b) | 126 b = self.munchExpr(e.b) |
121 d = self.newTmp() | 127 d = self.newTmp() |
122 self.emit('mov %d0, %s0', src=[a], dst=[d]) | 128 self.move(d, a) |
123 self.emit('lsl %d0, %s0', dst=[d], src=[b, d]) # TODO: is d a source variable? | 129 self.emit('lsl %s1, %s0', dst=[], src=[b, d]) # TODO: is d a source variable? |
124 return d | 130 return d |
125 elif isinstance(e, ir.Binop) and e.operation == '*': | 131 elif isinstance(e, ir.Binop) and e.operation == '*': |
126 a = self.munchExpr(e.a) | 132 a = self.munchExpr(e.a) |
127 b = self.munchExpr(e.b) | 133 b = self.munchExpr(e.b) |
128 d = self.newTmp() | 134 d = self.newTmp() |
129 self.emit('mov %d0, %s0', src=[a], dst=[d]) | 135 self.move(d, a) |
130 self.emit('mul %d0, %s0', dst=[d], src=[b, d]) | 136 # this mul instruction has operands swapped: |
137 self.emit('mul %s0, %d0', dst=[d], src=[b, d]) | |
131 return d | 138 return d |
132 elif isinstance(e, ir.Const) and e.value < 256: | 139 elif isinstance(e, ir.Const) and e.value < 256: |
133 d = self.newTmp() | 140 d = self.newTmp() |
134 self.emit('mov %d0, {}'.format(e.value), dst=[d]) | 141 self.emit('mov %d0, {}'.format(e.value), dst=[d]) |
135 return d | 142 return d |
140 return d | 147 return d |
141 elif isinstance(e, ir.Mem) and isinstance(e.e, ir.Binop) and \ | 148 elif isinstance(e, ir.Mem) and isinstance(e.e, ir.Binop) and \ |
142 e.e.operation == '+' and isinstance(e.e.b, ir.Const): | 149 e.e.operation == '+' and isinstance(e.e.b, ir.Const): |
143 base = self.munchExpr(e.e.a) | 150 base = self.munchExpr(e.e.a) |
144 d = self.newTmp() | 151 d = self.newTmp() |
145 self.emit('ldr %d0, [%s0 + {}]'.format(e.e.b.value), src=[base], dst=[d]) | 152 c = e.e.b.value |
153 self.emit('ldr %d0, [%s0 + {}]'.format(c), src=[base], dst=[d]) | |
146 return d | 154 return d |
147 elif isinstance(e, ir.Mem): | 155 elif isinstance(e, ir.Mem): |
148 # Load from memory | 156 # Load from memory |
149 base = self.munchExpr(e.e) | 157 base = self.munchExpr(e.e) |
150 d = self.newTmp() | 158 d = self.newTmp() |
169 raise NotImplementedError('Expr --> {}'.format(e)) | 177 raise NotImplementedError('Expr --> {}'.format(e)) |
170 | 178 |
171 def munchStm(self, s): | 179 def munchStm(self, s): |
172 if isinstance(s, ir.Terminator): | 180 if isinstance(s, ir.Terminator): |
173 pass | 181 pass |
174 elif isinstance(s, ir.Move) and isinstance(s.dst, ir.Mem) and isinstance(s.dst.e, ir.Binop) and s.dst.e.operation == '+' and isinstance(s.dst.e.a, ir.Temp) and isinstance(s.dst.e.b, ir.Const): | 182 elif isinstance(s, ir.Move) and isinstance(s.dst, ir.Mem) and \ |
183 isinstance(s.dst.e, ir.Binop) and s.dst.e.operation == '+' and \ | |
184 isinstance(s.dst.e.b, ir.Const): | |
185 a = self.munchExpr(s.dst.e.a) | |
175 val = self.munchExpr(s.src) | 186 val = self.munchExpr(s.src) |
176 self.emit('str %s1, [%s0 + {}]'.format(s.dst.e.b.value), src=[s.dst.e.a, val]) | 187 c = s.dst.e.b.value |
188 self.emit('str %s1, [%s0 + {}]'.format(c), src=[a, val]) | |
177 elif isinstance(s, ir.Move) and isinstance(s.dst, ir.Mem): | 189 elif isinstance(s, ir.Move) and isinstance(s.dst, ir.Mem): |
178 memloc = self.munchExpr(s.dst.e) | 190 memloc = self.munchExpr(s.dst.e) |
179 val = self.munchExpr(s.src) | 191 val = self.munchExpr(s.src) |
180 self.emit('str %s1, [%s0]', src=[memloc, val]) | 192 self.emit('str %s1, [%s0]', src=[memloc, val]) |
181 elif isinstance(s, ir.Move) and isinstance(s.dst, ir.Temp): | 193 elif isinstance(s, ir.Move) and isinstance(s.dst, ir.Temp): |
183 dreg = s.dst | 195 dreg = s.dst |
184 self.emit('mov %d0, %s0', dst=[dreg], src=[val]) | 196 self.emit('mov %d0, %s0', dst=[dreg], src=[val]) |
185 elif isinstance(s, ir.Exp): | 197 elif isinstance(s, ir.Exp): |
186 # Generate expression code and discard the result. | 198 # Generate expression code and discard the result. |
187 x = self.munchExpr(s.e) | 199 x = self.munchExpr(s.e) |
188 self.emit('mov r0, r0', src=[x]) | 200 self.emit('nop', src=[x]) |
189 elif isinstance(s, ir.Jump): | 201 elif isinstance(s, ir.Jump): |
190 tgt = self.targets[s.target] | 202 tgt = self.targets[s.target] |
191 self.emit('b {}'.format(s.target.name), jumps=[tgt]) | 203 self.emit('b {}'.format(s.target.name), jumps=[tgt]) |
192 elif isinstance(s, ir.CJump): | 204 elif isinstance(s, ir.CJump): |
193 a = self.munchExpr(s.a) | 205 a = self.munchExpr(s.a) |
246 # real instructions. | 258 # real instructions. |
247 # TODO: this is ugly via string representations. This could be | 259 # TODO: this is ugly via string representations. This could be |
248 # another interface? | 260 # another interface? |
249 assembler = asm.Assembler(target=arm.armtarget, stream=self.outs) | 261 assembler = asm.Assembler(target=arm.armtarget, stream=self.outs) |
250 self.outs.selectSection('code') | 262 self.outs.selectSection('code') |
263 # assembly glue to make it work: | |
264 self.outs.emit(arm.dcd_ins(Imm32(0x20000678))) # initial SP | |
265 self.outs.emit(arm.dcd_ins(Imm32(0x08000009))) # reset vector | |
266 self.outs.emit(arm.b_ins(LabelRef('main'))) | |
251 for frame in self.frames: | 267 for frame in self.frames: |
252 for i in frame.instructions: | 268 for i in frame.instructions: |
253 assembler.assemble_line(str(i)) | 269 assembler.assemble_line(str(i)) |
254 | 270 |
255 # TODO: fixup references, do this in another way? | 271 # TODO: fixup references, do this in another way? |