Mercurial > lcfOS
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]) |