comparison python/target/arminstructionselector.py @ 292:534b94b40aa8

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