Mercurial > lcfOS
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: |