301
|
1 from ppci import ir
|
|
2 from ppci.irmach import AbstractInstruction as makeIns
|
292
|
3 from .basetarget import Label, Comment, Alignment, LabelRef, DebugInfo, Nop
|
|
4 from .instructionselector import InstructionSelector
|
305
|
5 from .arminstructions import Orr, Lsl, Str2, Ldr2, Ldr3
|
|
6 from .arminstructions import B, Bl, Bgt, Blt, Beq, Bne
|
292
|
7 from .arminstructions import Mov2, Mov3
|
300
|
8 from .arminstructions import Add, Sub, Cmp, Sub2, Add2, Mul
|
292
|
9 from .basetarget import Imm8, Imm7, Imm3
|
|
10
|
|
11
|
|
12 class ArmInstructionSelector(InstructionSelector):
|
|
13 """ Instruction selector for the arm architecture """
|
|
14 def munchExpr(self, e):
|
318
|
15 if isinstance(e, ir.Binop) and e.operation == '+' and \
|
292
|
16 isinstance(e.b, ir.Const) and e.b.value < 8:
|
|
17 a = self.munchExpr(e.a)
|
|
18 d = self.newTmp()
|
|
19 c = Imm3(e.b.value)
|
300
|
20 self.emit(Add2, others=[c], dst=[d], src=[a])
|
292
|
21 return d
|
|
22 elif isinstance(e, ir.Binop) and e.operation == '+':
|
|
23 a = self.munchExpr(e.a)
|
|
24 b = self.munchExpr(e.b)
|
|
25 d = self.newTmp()
|
|
26 self.emit(Add, dst=[d], src=[a, b])
|
|
27 return d
|
|
28 elif isinstance(e, ir.Binop) and e.operation == '-' and \
|
|
29 isinstance(e.b, ir.Const) and e.b.value < 8:
|
|
30 a = self.munchExpr(e.a)
|
|
31 d = self.newTmp()
|
|
32 c = Imm3(e.b.value)
|
300
|
33 self.emit(Sub2, others=[c], dst=[d], src=[a])
|
292
|
34 return d
|
|
35 elif isinstance(e, ir.Binop) and e.operation == '-':
|
|
36 a = self.munchExpr(e.a)
|
|
37 b = self.munchExpr(e.b)
|
|
38 d = self.newTmp()
|
|
39 self.emit(Sub, dst=[d], src=[a, b])
|
|
40 return d
|
|
41 elif isinstance(e, ir.Binop) and e.operation == '|':
|
|
42 a = self.munchExpr(e.a)
|
|
43 b = self.munchExpr(e.b)
|
|
44 d = self.newTmp()
|
|
45 self.move(d, a)
|
316
|
46 self.emit(Orr, dst=[], src=[d, b])
|
292
|
47 return d
|
|
48 elif isinstance(e, ir.Binop) and e.operation == '<<':
|
|
49 a = self.munchExpr(e.a)
|
|
50 b = self.munchExpr(e.b)
|
|
51 d = self.newTmp()
|
|
52 self.move(d, a)
|
316
|
53 self.emit(Lsl, dst=[], src=[d, b]) # TODO: is d a source variable?
|
292
|
54 return d
|
|
55 elif isinstance(e, ir.Binop) and e.operation == '*':
|
|
56 a = self.munchExpr(e.a)
|
|
57 b = self.munchExpr(e.b)
|
|
58 d = self.newTmp()
|
|
59 self.move(d, a)
|
|
60 # this mul instruction has operands swapped:
|
300
|
61 self.emit(Mul, dst=[d], src=[b, d])
|
292
|
62 return d
|
|
63 elif isinstance(e, ir.Const) and e.value < 256:
|
|
64 d = self.newTmp()
|
|
65 self.emit(Mov3, others=[Imm8(e.value)], dst=[d])
|
|
66 return d
|
|
67 elif isinstance(e, ir.Const) and e.value < (2**31):
|
|
68 d = self.newTmp()
|
|
69 ln = LabelRef(self.frame.addConstant(e.value))
|
|
70 self.emit(Ldr3, others=[ln], dst=[d])
|
|
71 return d
|
|
72 elif isinstance(e, ir.Mem) and isinstance(e.e, ir.Binop) and \
|
|
73 e.e.operation == '+' and isinstance(e.e.b, ir.Const):
|
|
74 base = self.munchExpr(e.e.a)
|
|
75 d = self.newTmp()
|
|
76 c = e.e.b.value
|
|
77 self.emit(Ldr2, others=[c], src=[base], dst=[d])
|
|
78 return d
|
|
79 elif isinstance(e, ir.Mem):
|
|
80 # Load from memory
|
|
81 base = self.munchExpr(e.e)
|
|
82 d = self.newTmp()
|
|
83 self.emit(Ldr2, others=[0], src=[base], dst=[d])
|
|
84 return d
|
|
85 elif isinstance(e, ir.Temp):
|
|
86 return e
|
|
87 elif isinstance(e, ir.Call):
|
|
88 # Move arguments into proper locations:
|
|
89 reguses = []
|
|
90 for i, a in enumerate(e.arguments):
|
|
91 loc = self.frame.argLoc(i)
|
|
92 m = ir.Move(loc, a)
|
|
93 self.munchStm(m)
|
|
94 if isinstance(loc, ir.Temp):
|
|
95 reguses.append(loc)
|
305
|
96 self.emit(Bl(LabelRef(e.f)), src=reguses, dst=[self.frame.rv])
|
292
|
97 d = self.newTmp()
|
|
98 self.move(d, self.frame.rv)
|
|
99 return d
|
|
100 else:
|
|
101 raise NotImplementedError('Expr --> {}'.format(e))
|
|
102
|
|
103 def munchStm(self, s):
|
|
104 if isinstance(s, ir.Terminator):
|
|
105 pass
|
|
106 elif isinstance(s, ir.Move) and isinstance(s.dst, ir.Mem) and \
|
|
107 isinstance(s.dst.e, ir.Binop) and s.dst.e.operation == '+' and \
|
|
108 isinstance(s.dst.e.b, ir.Const):
|
|
109 a = self.munchExpr(s.dst.e.a)
|
|
110 val = self.munchExpr(s.src)
|
|
111 c = s.dst.e.b.value
|
|
112 self.emit(Str2, others=[c], src=[a, val])
|
|
113 elif isinstance(s, ir.Move) and isinstance(s.dst, ir.Mem):
|
|
114 memloc = self.munchExpr(s.dst.e)
|
|
115 val = self.munchExpr(s.src)
|
|
116 self.emit(Str2, others=[0], src=[memloc, val])
|
|
117 elif isinstance(s, ir.Move) and isinstance(s.dst, ir.Temp):
|
|
118 val = self.munchExpr(s.src)
|
|
119 dreg = s.dst
|
|
120 self.move(dreg, val)
|
|
121 elif isinstance(s, ir.Exp):
|
|
122 # Generate expression code and discard the result.
|
|
123 x = self.munchExpr(s.e)
|
|
124 self.emit(Nop(), src=[x])
|
|
125 elif isinstance(s, ir.Jump):
|
|
126 tgt = self.targets[s.target]
|
|
127 self.emit(B(LabelRef(s.target.name)), jumps=[tgt])
|
|
128 elif isinstance(s, ir.CJump):
|
|
129 a = self.munchExpr(s.a)
|
|
130 b = self.munchExpr(s.b)
|
|
131 self.emit(Cmp, src=[a, b])
|
|
132 ntgt = self.targets[s.lab_no]
|
|
133 ytgt = self.targets[s.lab_yes]
|
|
134 jmp_ins = makeIns(B(LabelRef(s.lab_no.name)), jumps=[ntgt])
|
305
|
135 opnames = {'<': Blt, '>':Bgt, '==':Beq, '!=':Bne}
|
292
|
136 op = opnames[s.cond](LabelRef(s.lab_yes.name))
|
|
137 self.emit(op, jumps=[ytgt, jmp_ins]) # Explicitely add fallthrough
|
|
138 self.emit2(jmp_ins)
|
|
139 else:
|
|
140 raise NotImplementedError('Stmt --> {}'.format(s))
|
|
141
|
|
142 def move(self, dst, src):
|
318
|
143 self.emit(Mov2, src=[src], dst=[dst], ismove=True)
|