301
|
1 from ppci import ir
|
290
|
2 from .basetarget import Label, Comment, Alignment, LabelRef, DebugInfo, Nop
|
292
|
3 from .basetarget import Imm7
|
301
|
4 from ppci.irmach import makeIns, Frame
|
292
|
5 from .arminstructions import Dcd, AddSp, SubSp, Push, Pop, Mov2
|
|
6 from .arminstructions import R0, R1, R2, R3, R4, R5, R6, R7, LR, PC, SP
|
274
|
7
|
290
|
8
|
292
|
9 class ArmFrame(Frame):
|
|
10 """ Arm specific frame for functions. """
|
275
|
11 def __init__(self, name):
|
|
12 # We use r7 as frame pointer.
|
|
13 super().__init__(name)
|
292
|
14 self.regs = [R0, R1, R2, R3, R4, R5, R6]
|
275
|
15 self.rv = ir.Temp('special_RV')
|
|
16 self.p1 = ir.Temp('special_P1')
|
|
17 self.p2 = ir.Temp('special_P2')
|
|
18 self.p3 = ir.Temp('special_P3')
|
|
19 self.p4 = ir.Temp('special_P4')
|
|
20 self.fp = ir.Temp('special_FP')
|
|
21 # Pre-colored registers:
|
|
22 self.tempMap = {}
|
292
|
23 self.tempMap[self.rv] = R0
|
|
24 self.tempMap[self.p1] = R1
|
|
25 self.tempMap[self.p2] = R2
|
|
26 self.tempMap[self.p3] = R3
|
|
27 self.tempMap[self.p4] = R4
|
|
28 self.tempMap[self.fp] = R7
|
275
|
29 self.locVars = {}
|
|
30 self.parMap = {}
|
276
|
31 # Literal pool:
|
|
32 self.constants = []
|
275
|
33
|
|
34 def argLoc(self, pos):
|
|
35 """
|
|
36 Gets the function parameter location in IR-code format.
|
|
37 """
|
|
38 if pos == 0:
|
|
39 return self.p1
|
|
40 elif pos == 1:
|
|
41 return self.p2
|
|
42 elif pos == 2:
|
|
43 return self.p3
|
|
44 elif pos == 3:
|
|
45 return self.p4
|
|
46 else:
|
|
47 raise NotImplementedError('No more than 4 parameters implemented')
|
|
48
|
|
49 def allocVar(self, lvar):
|
|
50 if lvar not in self.locVars:
|
|
51 self.locVars[lvar] = self.stacksize
|
|
52 self.stacksize = self.stacksize + 4
|
|
53 return self.locVars[lvar]
|
|
54
|
276
|
55 def addConstant(self, value):
|
|
56 lab_name = '{}_literal_{}'.format(self.name, len(self.constants))
|
|
57 self.constants.append((lab_name, value))
|
|
58 return lab_name
|
|
59
|
322
|
60 def prologue(self):
|
|
61 """ Returns prologue instruction sequence """
|
|
62 pre = [
|
|
63 Label(self.name), # Label indication function
|
323
|
64 Push({LR, R7})
|
|
65 ]
|
|
66 if self.stacksize > 0:
|
|
67 pre.append(SubSp(SP, SP, Imm7(self.stacksize))) # Reserve stack space
|
|
68 pre += [
|
322
|
69 Mov2(R7, SP) # Setup frame pointer
|
|
70 ]
|
|
71 return pre
|
|
72
|
|
73 def epilogue(self):
|
|
74 """ Return epilogue sequence for a frame. Adjust frame pointer and add constant pool """
|
323
|
75 post = []
|
|
76 if self.stacksize > 0:
|
|
77 post.append(AddSp(SP, SP, Imm7(self.stacksize)))
|
|
78 post += [
|
322
|
79 Pop({PC, R7}),
|
|
80 Alignment(4) # Align at 4 bytes
|
|
81 ]
|
|
82 # Add constant literals:
|
|
83 for ln, v in self.constants:
|
|
84 post.extend([Label(ln), Dcd(v)])
|
|
85 return post
|
|
86
|
275
|
87 def EntryExitGlue3(self):
|
|
88 """
|
|
89 Add code for the prologue and the epilogue. Add a label, the
|
|
90 return instruction and the stack pointer adjustment for the frame.
|
|
91 """
|
322
|
92 for index, ins in enumerate(self.prologue()):
|
|
93 self.instructions.insert(index, makeIns(ins))
|
|
94
|
|
95 # Postfix code:
|
|
96 for ins in self.epilogue():
|
|
97 self.instructions.append(makeIns(ins))
|