206
|
1 from asmnodes import ASymbol, AInstruction, ALabel, ANumber
|
200
|
2 from ppci import CompilerError
|
199
|
3
|
|
4 """
|
|
5 Base classes for defining a target
|
|
6 """
|
|
7
|
|
8 # Machine code interface:
|
|
9 class Operand:
|
|
10 """ Single machine operand """
|
|
11 pass
|
|
12
|
206
|
13 # standard immediates:
|
|
14
|
|
15 class Imm8:
|
|
16 def __init__(self, imm):
|
|
17 assert imm < 256
|
|
18 self.imm = imm
|
|
19
|
|
20 @classmethod
|
|
21 def Create(cls, vop):
|
|
22 if type(vop) is ANumber and vop.number < 256:
|
|
23 return cls(vop.number)
|
|
24
|
|
25 class Imm3:
|
|
26 def __init__(self, imm):
|
|
27 assert imm < 8
|
|
28 assert type(imm) is int
|
|
29 self.imm = imm
|
|
30
|
|
31 @classmethod
|
|
32 def Create(cls, vop):
|
|
33 if type(vop) is ANumber and vop.number < 8:
|
|
34 return cls(vop.number)
|
|
35
|
|
36 class Label:
|
|
37 def __init__(self, name):
|
|
38 self.name = name
|
|
39
|
|
40 @classmethod
|
|
41 def Create(cls, vop):
|
|
42 if type(vop) is ASymbol:
|
|
43 name = vop.name
|
|
44 return cls(name)
|
|
45
|
199
|
46 class Register(Operand):
|
|
47 def __init__(self, name):
|
|
48 self.name = name
|
|
49
|
|
50 class Instruction:
|
201
|
51 def encode(self):
|
205
|
52 raise NotImplementedError('Instruction {0} has no encode yet, TODO'.format(type(self)))
|
199
|
53
|
|
54 class Target:
|
201
|
55 def __init__(self, name, desc=''):
|
|
56 self.name = name
|
|
57 self.desc = desc
|
200
|
58 self.registers = []
|
199
|
59 self.instructions = []
|
200
|
60
|
201
|
61 def instruction(self, cls):
|
|
62 """ Decorator function that registers an instruction to this target """
|
202
|
63 self.addInstruction(cls)
|
201
|
64 return cls
|
|
65
|
206
|
66 def check(self):
|
|
67 """ Check target """
|
|
68 for i in self.instructions:
|
|
69 assert hasattr(i, 'mnemonic')
|
|
70 assert hasattr(i, 'operands'), str(i)
|
|
71 assert type(i.mnemonic) is str
|
|
72 assert type(i.operands) is tuple, str(i)
|
|
73
|
202
|
74 def addInstruction(self, ins_class):
|
|
75 self.instructions.append(ins_class)
|
|
76
|
200
|
77 def mapOperand(self, operand):
|
|
78 """ Try to map an operand to a target type """
|
|
79 if type(operand) is ASymbol:
|
|
80 # Try to map to register:
|
|
81 regs = {}
|
|
82 for r in self.registers:
|
|
83 regs[r.name] = r
|
|
84 if operand.name in regs:
|
|
85 return regs[operand.name]
|
201
|
86 raise CompilerError('Cannot map {0}'.format(operand))
|
199
|
87
|
200
|
88 def mapInstruction(self, vi):
|
203
|
89 assert type(vi) is AInstruction
|
200
|
90 """ Map ast tree to real instruction for this target """
|
199
|
91
|
200
|
92 # map to real operands:
|
|
93
|
|
94 # look for a suitable instruction
|
|
95 for ic in self.instructions:
|
203
|
96 if ic.mnemonic == vi.mnemonic and len(ic.operands) == len(vi.operands):
|
|
97 # Try to map operands to the correct operand types:
|
|
98 rops = [roptype.Create(vop) for roptype, vop in zip(ic.operands, vi.operands)]
|
|
99
|
|
100 # Check if we succeeded:
|
|
101 optypes = tuple(map(type, rops))
|
|
102 if ic.operands == optypes:
|
|
103 return ic(*rops)
|
201
|
104 raise CompilerError('No suitable instruction found for "{0}"'.format(vi))
|
200
|
105
|