322
|
1 import os
|
301
|
2 from ppci import ir
|
|
3 from ppci.irmach import AbstractInstruction as makeIns
|
322
|
4 from ppci.ir2tree import makeTree
|
|
5 import pyburg
|
292
|
6 from .basetarget import Label, Comment, Alignment, LabelRef, DebugInfo, Nop
|
|
7 from .instructionselector import InstructionSelector
|
305
|
8 from .arminstructions import Orr, Lsl, Str2, Ldr2, Ldr3
|
|
9 from .arminstructions import B, Bl, Bgt, Blt, Beq, Bne
|
292
|
10 from .arminstructions import Mov2, Mov3
|
300
|
11 from .arminstructions import Add, Sub, Cmp, Sub2, Add2, Mul
|
292
|
12 from .basetarget import Imm8, Imm7, Imm3
|
|
13
|
322
|
14 # Import BURG spec for arm:
|
|
15 spec_file = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'arm.brg')
|
|
16 arm_matcher = pyburg.load_as_module(spec_file)
|
|
17
|
323
|
18
|
322
|
19 class ArmMatcher(arm_matcher.Matcher):
|
323
|
20 """ Matcher that derives from a burg spec generated matcher """
|
|
21 def __init__(self, selector):
|
322
|
22 super().__init__()
|
323
|
23 self.newTmp = selector.newTmp
|
|
24 self.emit = selector.emit
|
|
25 self.selector = selector
|
322
|
26
|
292
|
27
|
|
28 class ArmInstructionSelector(InstructionSelector):
|
|
29 """ Instruction selector for the arm architecture """
|
322
|
30 def __init__(self):
|
|
31 super().__init__()
|
323
|
32 self.matcher = ArmMatcher(self)
|
322
|
33
|
292
|
34 def munchExpr(self, e):
|
323
|
35 # Use BURG system here:
|
|
36 t = makeTree(e)
|
|
37 return self.matcher.gen(t)
|
322
|
38
|
323
|
39 def munchCall(self, e):
|
|
40 """ Generate code for call sequence """
|
|
41 # Move arguments into proper locations:
|
|
42 reguses = []
|
|
43 for i, a in enumerate(e.arguments):
|
|
44 loc = self.frame.argLoc(i)
|
|
45 m = ir.Move(loc, a)
|
|
46 self.munchStm(m)
|
|
47 if isinstance(loc, ir.Temp):
|
|
48 reguses.append(loc)
|
|
49 self.emit(Bl(LabelRef(e.f)), src=reguses, dst=[self.frame.rv])
|
|
50 d = self.newTmp()
|
|
51 self.move(d, self.frame.rv)
|
|
52 return d
|
292
|
53
|
|
54 def munchStm(self, s):
|
|
55 if isinstance(s, ir.Terminator):
|
|
56 pass
|
|
57 elif isinstance(s, ir.Move) and isinstance(s.dst, ir.Mem) and \
|
|
58 isinstance(s.dst.e, ir.Binop) and s.dst.e.operation == '+' and \
|
|
59 isinstance(s.dst.e.b, ir.Const):
|
|
60 a = self.munchExpr(s.dst.e.a)
|
|
61 val = self.munchExpr(s.src)
|
|
62 c = s.dst.e.b.value
|
|
63 self.emit(Str2, others=[c], src=[a, val])
|
|
64 elif isinstance(s, ir.Move) and isinstance(s.dst, ir.Mem):
|
|
65 memloc = self.munchExpr(s.dst.e)
|
|
66 val = self.munchExpr(s.src)
|
|
67 self.emit(Str2, others=[0], src=[memloc, val])
|
|
68 elif isinstance(s, ir.Move) and isinstance(s.dst, ir.Temp):
|
|
69 val = self.munchExpr(s.src)
|
|
70 dreg = s.dst
|
|
71 self.move(dreg, val)
|
|
72 elif isinstance(s, ir.Exp):
|
|
73 # Generate expression code and discard the result.
|
|
74 x = self.munchExpr(s.e)
|
|
75 self.emit(Nop(), src=[x])
|
|
76 elif isinstance(s, ir.Jump):
|
|
77 tgt = self.targets[s.target]
|
|
78 self.emit(B(LabelRef(s.target.name)), jumps=[tgt])
|
|
79 elif isinstance(s, ir.CJump):
|
|
80 a = self.munchExpr(s.a)
|
|
81 b = self.munchExpr(s.b)
|
|
82 self.emit(Cmp, src=[a, b])
|
|
83 ntgt = self.targets[s.lab_no]
|
|
84 ytgt = self.targets[s.lab_yes]
|
|
85 jmp_ins = makeIns(B(LabelRef(s.lab_no.name)), jumps=[ntgt])
|
305
|
86 opnames = {'<': Blt, '>':Bgt, '==':Beq, '!=':Bne}
|
292
|
87 op = opnames[s.cond](LabelRef(s.lab_yes.name))
|
|
88 self.emit(op, jumps=[ytgt, jmp_ins]) # Explicitely add fallthrough
|
|
89 self.emit2(jmp_ins)
|
|
90 else:
|
|
91 raise NotImplementedError('Stmt --> {}'.format(s))
|
|
92
|
|
93 def move(self, dst, src):
|
318
|
94 self.emit(Mov2, src=[src], dst=[dst], ismove=True)
|