comparison python/codegenarm.py @ 258:04c19282a5aa

Added register allocator
author Windel Bouwman
date Mon, 05 Aug 2013 19:46:11 +0200
parents 225f444019b1
children ac603eb66b63
comparison
equal deleted inserted replaced
257:703321743e8a 258:04c19282a5aa
9 Simple code generator 9 Simple code generator
10 Ad hoc implementation 10 Ad hoc implementation
11 """ 11 """
12 def __init__(self, out): 12 def __init__(self, out):
13 self.outs = out 13 self.outs = out
14 self.logger = logging.getLogger('cgarm') 14 self.logger = logging.getLogger('codegenarm')
15 15
16 def emit(self, item): 16 def emit(self, item):
17 self.outs.emit(item) 17 self.outs.emit(item)
18 18
19 def generate(self, ircode): 19 def generate(self, ircode):
20 assert isinstance(ircode, ir.Module) 20 assert isinstance(ircode, ir.Module)
21 self.logger.info('Generating arm code for {}'.format(ircode.name)) 21 self.logger.info('Generating arm code for {}'.format(ircode.name))
22 self.available_regs = {arm.r2, arm.r3, arm.r4, arm.r5, arm.r6, arm.r7}
23 self.regmap = {}
22 # TODO: get these from linker descriptor? 24 # TODO: get these from linker descriptor?
23 self.outs.getSection('code').address = 0x08000000 25 self.outs.getSection('code').address = 0x08000000
24 self.outs.getSection('data').address = 0x20000000 26 self.outs.getSection('data').address = 0x20000000
25 self.outs.selectSection('data') 27 self.outs.selectSection('data')
26 28
60 self.emit(Label(l)) 62 self.emit(Label(l))
61 self.dcd(v) 63 self.dcd(v)
62 self.align() 64 self.align()
63 self.outs.backpatch() 65 self.outs.backpatch()
64 self.outs.backpatch() 66 self.outs.backpatch()
65 code = self.outs.getSection('code').to_bytes() 67 codesize = self.outs.getSection('code').Size
66 self.logger.info('Generated {} bytes code'.format(len(code))) 68 self.logger.info('Generated {} bytes code'.format(codesize))
67 69
68 def dcd(self, x): 70 def dcd(self, x):
69 self.emit(arm.dcd_ins(Imm32(x))) 71 self.emit(arm.dcd_ins(Imm32(x)))
70 72
71 def align(self): 73 def align(self):
85 self.emit(arm.ldr_pcrel(r, LabelRef(_global_address))) 87 self.emit(arm.ldr_pcrel(r, LabelRef(_global_address)))
86 88
87 def loadStack(self, reg, val): 89 def loadStack(self, reg, val):
88 self.emit(arm.ldr_sprel(reg, arm.MemSpRel(self.getStack(val)))) 90 self.emit(arm.ldr_sprel(reg, arm.MemSpRel(self.getStack(val))))
89 91
92 def getreg(self, v):
93 if not v in self.regmap:
94 self.regmap[v] = self.available_regs.pop()
95 return self.regmap[v]
96
97 def freereg(self, v, ins):
98 if v.lastUse(ins):
99 r = self.regmap.pop(v)
100 assert r not in self.regmap.values()
101 self.available_regs.add(r)
102
90 def comment(self, txt): 103 def comment(self, txt):
91 self.emit(Comment(txt)) 104 self.emit(Comment(txt))
92 105
93 def debugInfo(self, loc): 106 def debugInfo(self, loc):
94 if loc: 107 if loc:
101 if type(ins) is ir.Branch: 114 if type(ins) is ir.Branch:
102 tgt = LabelRef(ins.target.name) 115 tgt = LabelRef(ins.target.name)
103 self.emit(arm.b_ins(tgt)) 116 self.emit(arm.b_ins(tgt))
104 elif type(ins) is ir.ImmLoad: 117 elif type(ins) is ir.ImmLoad:
105 lname = ins.target.name + '_ivalue' 118 lname = ins.target.name + '_ivalue'
106 self.emit(arm.ldr_pcrel(arm.r0, LabelRef(lname))) 119 r0 = self.getreg(ins.target)
120 self.emit(arm.ldr_pcrel(r0, LabelRef(lname)))
107 self.imms.append((lname, ins.value)) 121 self.imms.append((lname, ins.value))
108 self.emit(arm.str_sprel(arm.r0, arm.MemSpRel(self.addStack(ins.target))))
109 elif type(ins) is ir.Store: 122 elif type(ins) is ir.Store:
110 # Load value in r0: 123 # Load value in r0:
111 self.loadStack(arm.r0, ins.value) 124 r0 = self.getreg(ins.value)
112 # store in memory: 125 # store in memory:
113 # TODO: split globals and locals?? 126 # TODO: split globals and locals??
114 #self.getGlobal(arm.r1, ins.location) 127 #self.getGlobal(arm.r1, ins.location)
115 # Horrible hack with localVars 128 # Horrible hack with localVars
116 if ins.location in self.localVars: 129 if ins.location in self.localVars:
117 # The value was alloc'ed 130 # The value was alloc'ed
118 self.emit(arm.str_sprel(arm.r0, arm.MemSpRel(self.getStack(ins.location)))) 131 self.emit(arm.str_sprel(r0, arm.MemSpRel(self.getStack(ins.location))))
119 else: 132 else:
120 self.loadStack(arm.r1, ins.location) 133 r1 = self.getreg(ins.location)
121 self.emit(arm.storeimm5_ins(arm.r0, arm.MemR8Rel(arm.r1, 0))) 134 self.emit(arm.storeimm5_ins(r0, arm.MemR8Rel(r1, 0)))
135 self.freereg(ins.location, ins)
136 self.freereg(ins.value, ins)
122 elif type(ins) is ir.Load: 137 elif type(ins) is ir.Load:
123 # TODO: differ global and local?? 138 # TODO: differ global and local??
124 #self.getGlobal(arm.r0, ins.location) 139 #self.getGlobal(arm.r0, ins.location)
140 r0 = self.getreg(ins.value)
125 if ins.location in self.localVars: 141 if ins.location in self.localVars:
126 self.emit(arm.ldr_sprel(arm.r0, arm.MemSpRel(self.getStack(ins.location)))) 142 self.emit(arm.ldr_sprel(r0, arm.MemSpRel(self.getStack(ins.location))))
127 else: 143 else:
128 self.loadStack(arm.r0, ins.location) 144 r2 = self.getreg(ins.location)
129 self.emit(arm.loadimm5_ins(arm.r0, arm.MemR8Rel(arm.r0, 0))) 145 self.emit(arm.loadimm5_ins(r0, arm.MemR8Rel(r2, 0)))
130 # Store value on stack: 146 self.freereg(ins.location, ins)
131 self.emit(arm.str_sprel(arm.r0, arm.MemSpRel(self.addStack(ins.value))))
132 elif type(ins) is ir.BinaryOperator: 147 elif type(ins) is ir.BinaryOperator:
133 # Load operands: 148 # Load operands:
134 self.loadStack(arm.r0, ins.value1) 149 r0 = self.getreg(ins.value1)
135 self.loadStack(arm.r1, ins.value2) 150 r1 = self.getreg(ins.value2)
151 r2 = self.getreg(ins.result)
136 # do operation: 152 # do operation:
137 if ins.operation == '+': 153 if ins.operation == '+':
138 self.emit(arm.addregs_ins(arm.r0, arm.r0, arm.r1)) 154 self.emit(arm.addregs_ins(r2, r0, r1))
139 elif ins.operation == '<<': 155 elif ins.operation == '<<':
140 self.emit(arm.lslregs_ins(arm.r0, arm.r1)) 156 self.emit(arm.movregreg_ins(r2, r0))
157 self.emit(arm.lslregs_ins(r2, r1))
141 elif ins.operation == '|': 158 elif ins.operation == '|':
142 self.emit(arm.orrregs_ins(arm.r0, arm.r1)) 159 self.emit(arm.movregreg_ins(r2, r0))
160 self.emit(arm.orrregs_ins(r2, r1))
143 else: 161 else:
144 raise NotImplementedError('operation {} not implemented'.format(ins.operation)) 162 raise NotImplementedError('operation {} not implemented'.format(ins.operation))
145 # Store value back: 163 self.freereg(ins.value1, ins)
146 self.emit(arm.str_sprel(arm.r0, arm.MemSpRel(self.addStack(ins.result)))) 164 self.freereg(ins.value2, ins)
147 elif type(ins) is ir.Return: 165 elif type(ins) is ir.Return:
148 self.emit(arm.pop_ins(arm.RegisterSet({arm.r4, arm.r5, arm.r6, arm.r7, arm.pc}))) 166 self.emit(arm.pop_ins(arm.RegisterSet({arm.r4, arm.r5, arm.r6, arm.r7, arm.pc})))
149 elif type(ins) is ir.ConditionalBranch: 167 elif type(ins) is ir.ConditionalBranch:
150 self.loadStack(arm.r0, ins.a) 168 r0 = self.getreg(ins.a)
151 self.loadStack(arm.r1, ins.b) 169 r1 = self.getreg(ins.b)
152 self.emit(arm.cmp_ins(arm.r1, arm.r0)) 170 self.emit(arm.cmp_ins(r1, r0))
153 tgt_yes = Label(ins.lab1.name) 171 tgt_yes = Label(ins.lab1.name)
154 if ins.cond == '==': 172 if ins.cond == '==':
155 self.emit(arm.beq_ins(tgt_yes)) 173 self.emit(arm.beq_ins(tgt_yes))
156 else: 174 else:
157 raise NotImplementedError('"{}" not covered'.format(ins.cond)) 175 raise NotImplementedError('"{}" not covered'.format(ins.cond))
158 tgt_no = Label(ins.lab2.name) 176 tgt_no = Label(ins.lab2.name)
159 self.emit(arm.jmp_ins(tgt_no)) 177 self.emit(arm.jmp_ins(tgt_no))
178 self.freereg(ins.a, ins)
179 self.freereg(ins.b, ins)
160 elif type(ins) is ir.Alloc: 180 elif type(ins) is ir.Alloc:
161 # Local variables are added to stack 181 # Local variables are added to stack
162 self.addStack(ins.value) 182 self.addStack(ins.value)
163 self.localVars.append(ins.value) 183 self.localVars.append(ins.value)
164 # load address into variable: 184 # load address into variable: