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