255
|
1 import logging
|
211
|
2 import ir
|
249
|
3 from target import Label, Comment, Alignment, LabelRef, Imm32, DebugInfo
|
218
|
4 import cortexm3 as arm
|
211
|
5 from ppci import CompilerError
|
269
|
6 import flowgraph
|
|
7 import registerallocator
|
|
8 from instructionselector import InstructionSelector
|
262
|
9
|
|
10
|
268
|
11 class ArmInstructionSelector(InstructionSelector):
|
269
|
12 """ Instruction selector for the arm architecture """
|
268
|
13 def munchExpr(self, e):
|
|
14 if isinstance(e, ir.Alloc):
|
|
15 return 0
|
|
16 elif isinstance(e, ir.Binop) and e.operation == '+':
|
|
17 a = self.munchExpr(e.value1)
|
|
18 b = self.munchExpr(e.value2)
|
|
19 d = self.newTmp()
|
|
20 self.emit('add %d0, %s0, %s1', dst=[d], src=[a, b])
|
|
21 return d
|
269
|
22 elif isinstance(e, ir.Binop) and e.operation == '-':
|
|
23 a = self.munchExpr(e.value1)
|
|
24 b = self.munchExpr(e.value2)
|
|
25 d = self.newTmp()
|
|
26 self.emit('sub %d0, %s0, %s1', dst=[d], src=[a, b])
|
|
27 return d
|
268
|
28 elif isinstance(e, ir.Binop) and e.operation == '|':
|
|
29 a = self.munchExpr(e.value1)
|
|
30 b = self.munchExpr(e.value2)
|
|
31 d = self.newTmp()
|
269
|
32 self.emit('or %d0, %s0, %s1', dst=[d], src=[a, b])
|
268
|
33 return d
|
|
34 elif isinstance(e, ir.Binop) and e.operation == '<<':
|
|
35 a = self.munchExpr(e.value1)
|
|
36 b = self.munchExpr(e.value2)
|
|
37 d = self.newTmp()
|
|
38 self.emit('lsl %d0, %s0, %s1', dst=[d], src=[a, b])
|
|
39 return d
|
|
40 elif isinstance(e, ir.Binop) and e.operation == '*':
|
|
41 a = self.munchExpr(e.value1)
|
|
42 b = self.munchExpr(e.value2)
|
|
43 d = self.newTmp()
|
269
|
44 self.emit('mul %d0, %s0, %s1', dst=[d], src=[a, b])
|
268
|
45 return d
|
|
46 elif isinstance(e, ir.Const):
|
|
47 d = self.newTmp()
|
|
48 if e.value < 256:
|
|
49 self.emit('ldr %d0, {}'.format(e.value), dst=[d])
|
|
50 else:
|
269
|
51 self.emit('ldrpcrel TODO', dst=[d])
|
268
|
52 return d
|
|
53 elif isinstance(e, ir.Mem):
|
|
54 # Load from memory
|
|
55 loc = self.munchExpr(e.e)
|
|
56 d = self.newTmp()
|
|
57 self.emit('ldr %d0, [%s0]', src=[loc], dst=[d])
|
|
58 return d
|
|
59 elif isinstance(e, ir.Temp):
|
269
|
60 return self.getTempReg(e)
|
268
|
61 else:
|
|
62 raise NotImplementedError('--> {}'.format(e))
|
|
63
|
|
64 def munchStm(self, s):
|
|
65 if isinstance(s, ir.Move) and isinstance(s.dst, ir.Mem):
|
|
66 memloc = self.munchExpr(s.dst.e)
|
|
67 val = self.munchExpr(s.src)
|
|
68 self.emit('str [%s0], %s1')
|
|
69 elif isinstance(s, ir.Move) and isinstance(s.dst, ir.Temp):
|
|
70 val = self.munchExpr(s.src)
|
269
|
71 dreg = self.getTempReg(s.dst)
|
|
72 self.emit('mov %d0, %s0', dst=[dreg], src=[val])
|
268
|
73 elif isinstance(s, ir.Return):
|
269
|
74 #etgt = self.targets[
|
|
75 self.emit('jmp exit', jumps=[])
|
268
|
76 elif isinstance(s, ir.Jump):
|
269
|
77 tgt = self.targets[s.target]
|
|
78 self.emit('jmp {}'.format(s), jumps=[tgt])
|
268
|
79 elif isinstance(s, ir.CJump):
|
269
|
80 a = self.munchExpr(s.a)
|
|
81 b = self.munchExpr(s.b)
|
|
82 self.emit('cmp %s0, %s1', src=[a, b])
|
|
83 ntgt = self.targets[s.lab_no]
|
|
84 ytgt = self.targets[s.lab_yes]
|
|
85 jmp_ins = self.makeIns('jmp {}'.format(s.lab_no), jumps=[ntgt])
|
|
86 # Explicitely add fallthrough:
|
|
87 self.emit('jeq {}'.format(s.lab_yes), jumps=[ytgt, jmp_ins])
|
|
88 self.emit2(jmp_ins)
|
268
|
89 else:
|
|
90 raise NotImplementedError('--> {}'.format(s))
|
|
91
|
|
92
|
211
|
93 class ArmCodeGenerator:
|
268
|
94 def __init__(self, outs):
|
269
|
95 # TODO: schedule traces in better order.
|
|
96 # This is optional!
|
268
|
97 self.ins_sel = ArmInstructionSelector()
|
|
98 self.outs = outs
|
|
99 self.outs.getSection('code').address = 0x08000000
|
|
100 self.outs.getSection('data').address = 0x20000000
|
|
101
|
270
|
102 def useUnused(self, inslist):
|
|
103 # Use unused temporaries at the end of the list
|
|
104 defTemps = []
|
|
105 for d in (i.dst for i in inslist):
|
|
106 print(d)
|
|
107 defTemps.append(d)
|
|
108 useTemps = [d for d in ([i.src] for i in inslist)]
|
|
109 print(defTemps)
|
|
110 print(useTemps)
|
|
111
|
269
|
112 def generate(self, ircode, cfg_file=None, ig_file=None):
|
270
|
113 ir2 = self.ins_sel.munchProgram(ircode)
|
|
114 self.useUnused(ir2)
|
|
115 cfg = flowgraph.FlowGraph(ir2)
|
269
|
116 if cfg_file:
|
|
117 cfg.to_dot(cfg_file)
|
|
118 ig = registerallocator.InterferenceGraph(cfg)
|
|
119 if ig_file:
|
|
120 ig.to_dot(ig_file)
|
|
121
|
|
122 regs = ['r0', 'r1', 'r2', 'r3', 'r4', 'r5', 'r6', 'r7']
|
|
123 ra = registerallocator.RegisterAllocator()
|
270
|
124 regMap = ra.registerAllocate(ig, regs)
|
|
125 print(regMap)
|
|
126 for i in ir2:
|
|
127 i.src = tuple(regMap[t] for t in i.src)
|
|
128 i.dst = tuple(regMap[t] for t in i.dst)
|
|
129 print(i)
|
268
|
130
|
|
131
|
270
|
132
|