200
|
1 from asmnodes import ASymbol, AInstruction
|
|
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
|
|
13 class Register(Operand):
|
|
14 def __init__(self, name):
|
|
15 self.name = name
|
|
16
|
|
17 class Instruction:
|
201
|
18 def encode(self):
|
|
19 raise NotImplementedError('TODO')
|
199
|
20
|
|
21 class Target:
|
201
|
22 def __init__(self, name, desc=''):
|
|
23 self.name = name
|
|
24 self.desc = desc
|
200
|
25 self.registers = []
|
199
|
26 self.instructions = []
|
200
|
27
|
201
|
28 def instruction(self, cls):
|
|
29 """ Decorator function that registers an instruction to this target """
|
202
|
30 self.addInstruction(cls)
|
201
|
31 return cls
|
|
32
|
202
|
33 def addInstruction(self, ins_class):
|
|
34 self.instructions.append(ins_class)
|
|
35
|
200
|
36 def mapOperand(self, operand):
|
|
37 """ Try to map an operand to a target type """
|
|
38 if type(operand) is ASymbol:
|
|
39 # Try to map to register:
|
|
40 regs = {}
|
|
41 for r in self.registers:
|
|
42 regs[r.name] = r
|
|
43 if operand.name in regs:
|
|
44 return regs[operand.name]
|
201
|
45 raise CompilerError('Cannot map {0}'.format(operand))
|
199
|
46
|
200
|
47 def mapInstruction(self, vi):
|
|
48 """ Map ast tree to real instruction for this target """
|
199
|
49
|
200
|
50 # map to real operands:
|
|
51 rops = tuple(map(self.mapOperand, vi.operands))
|
|
52 optypes = tuple(map(type, rops))
|
|
53
|
|
54 # look for a suitable instruction
|
|
55 for ic in self.instructions:
|
|
56 if ic.mnemonic == vi.opcode and ic.operands == optypes:
|
|
57 ri = ic(*rops)
|
|
58 return ri
|
201
|
59 raise CompilerError('No suitable instruction found for "{0}"'.format(vi))
|
200
|
60
|