346
|
1 from ... import ir
|
364
|
2 from ..basetarget import Label, Alignment, LabelAddress
|
346
|
3 from ...irmach import AbstractInstruction, Frame
|
353
|
4 from .instructions import Dcd, Add, Sub, Push, Pop, Mov, Db
|
346
|
5 from .registers import R0, R1, R2, R3, R4, R5, R6, R7, R8, R11, LR, PC, SP
|
|
6
|
|
7
|
|
8 class ArmFrame(Frame):
|
|
9 """ Arm specific frame for functions. """
|
|
10 def __init__(self, name):
|
|
11 # We use r7 as frame pointer.
|
|
12 super().__init__(name)
|
|
13 self.regs = [R0, R1, R2, R3, R4, R5, R6, R7, R8]
|
|
14 self.rv = ir.Temp('special_RV')
|
|
15 self.p1 = ir.Temp('special_P1')
|
|
16 self.p2 = ir.Temp('special_P2')
|
|
17 self.p3 = ir.Temp('special_P3')
|
|
18 self.p4 = ir.Temp('special_P4')
|
|
19 self.fp = ir.Temp('special_FP')
|
|
20 # Pre-colored registers:
|
|
21 self.tempMap = {}
|
|
22 self.tempMap[self.rv] = R0
|
|
23 self.tempMap[self.p1] = R1
|
|
24 self.tempMap[self.p2] = R2
|
|
25 self.tempMap[self.p3] = R3
|
|
26 self.tempMap[self.p4] = R4
|
|
27 self.tempMap[self.fp] = R11
|
|
28 self.locVars = {}
|
|
29 self.parMap = {}
|
|
30 # Literal pool:
|
|
31 self.constants = []
|
|
32
|
|
33 def argLoc(self, pos):
|
|
34 """
|
|
35 Gets the function parameter location in IR-code format.
|
|
36 """
|
|
37 if pos == 0:
|
|
38 return self.p1
|
|
39 elif pos == 1:
|
|
40 return self.p2
|
|
41 elif pos == 2:
|
|
42 return self.p3
|
|
43 elif pos == 3:
|
|
44 return self.p4
|
|
45 else:
|
|
46 raise NotImplementedError('No more than 4 parameters implemented')
|
|
47
|
|
48 def allocVar(self, lvar):
|
|
49 if lvar not in self.locVars:
|
|
50 self.locVars[lvar] = self.stacksize
|
|
51 self.stacksize = self.stacksize + 4
|
|
52 return self.locVars[lvar]
|
|
53
|
353
|
54 def add_constant(self, value):
|
364
|
55 assert type(value) in [int, bytes, LabelAddress]
|
346
|
56 lab_name = '{}_literal_{}'.format(self.name, len(self.constants))
|
|
57 self.constants.append((lab_name, value))
|
|
58 return lab_name
|
|
59
|
|
60 def prologue(self):
|
|
61 """ Returns prologue instruction sequence """
|
|
62 pre = [
|
|
63 Label(self.name), # Label indication function
|
|
64 Push({LR, R11})
|
|
65 ]
|
|
66 if self.stacksize > 0:
|
|
67 pre.append(Sub(SP, SP, self.stacksize)) # Reserve stack space
|
|
68 pre += [
|
|
69 Mov(R11, 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 """
|
|
75 post = []
|
|
76 if self.stacksize > 0:
|
|
77 post.append(Add(SP, SP, self.stacksize))
|
|
78 post += [
|
|
79 Pop({PC, R11}),
|
|
80 Alignment(4) # Align at 4 bytes
|
|
81 ]
|
353
|
82
|
346
|
83 # Add constant literals:
|
|
84 for ln, v in self.constants:
|
353
|
85 if isinstance(v, int):
|
|
86 post.extend([Label(ln), Dcd(v)])
|
364
|
87 elif isinstance(v, LabelAddress):
|
|
88 post.extend([Label(ln), Dcd(v)])
|
354
|
89 elif isinstance(v, bytes):
|
|
90 post.append(Label(ln))
|
353
|
91 for c in v:
|
354
|
92 post.append(Db(c))
|
353
|
93 post.append(Alignment(4)) # Align at 4 bytes
|
|
94 else:
|
354
|
95 raise Exception('Constant of type {} not supported'.format(v))
|
346
|
96 return post
|
|
97
|
|
98 def EntryExitGlue3(self):
|
|
99 """
|
|
100 Add code for the prologue and the epilogue. Add a label, the
|
|
101 return instruction and the stack pointer adjustment for the frame.
|
|
102 """
|
|
103 for index, ins in enumerate(self.prologue()):
|
|
104 self.instructions.insert(index, AbstractInstruction(ins))
|
|
105
|
|
106 # Postfix code:
|
|
107 for ins in self.epilogue():
|
|
108 self.instructions.append(AbstractInstruction(ins))
|