Mercurial > lcfOS
annotate python/target/basetarget.py @ 299:674789d9ff37
Added a doc
author | Windel Bouwman |
---|---|
date | Sun, 01 Dec 2013 18:37:23 +0100 |
parents | 534b94b40aa8 |
children | b145f8e6050b |
rev | line source |
---|---|
235 | 1 from asmnodes import ASymbol, AInstruction, 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 | |
292 | 15 class ImmBase: |
206 | 16 def __init__(self, imm): |
292 | 17 assert type(imm) is int |
18 assert imm < self.Max() | |
206 | 19 self.imm = imm |
20 | |
21 @classmethod | |
292 | 22 def Max(cls): |
23 return 2**cls.bits | |
275 | 24 |
25 @classmethod | |
26 def Create(cls, vop): | |
292 | 27 if type(vop) is ANumber and vop.number < cls.Max(): |
275 | 28 return cls(vop.number) |
29 | |
292 | 30 |
31 class Imm3(ImmBase): | |
32 bits = 3 | |
206 | 33 |
292 | 34 |
35 class Imm7(ImmBase): | |
36 bits = 7 | |
206 | 37 |
292 | 38 |
39 class Imm8(ImmBase): | |
40 bits = 8 | |
235 | 41 |
292 | 42 |
43 class Imm32(ImmBase): | |
44 bits = 32 | |
235 | 45 |
46 | |
47 class LabelRef: | |
48 def __init__(self, name): | |
280
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
277
diff
changeset
|
49 assert type(name) is str |
235 | 50 self.name = name |
51 | |
52 @classmethod | |
53 def Create(cls, vop): | |
54 if type(vop) is ASymbol: | |
55 return cls(vop.name) | |
56 | |
292 | 57 |
234 | 58 class Instruction: |
292 | 59 """ Base instruction class """ |
234 | 60 def encode(self): |
61 raise NotImplementedError('Instruction {0} has no encode yet, TODO'.format(type(self))) | |
292 | 62 |
234 | 63 def resolve(self, f): |
64 pass | |
65 | |
66 | |
280
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
277
diff
changeset
|
67 class Nop(Instruction): |
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
277
diff
changeset
|
68 """ Instruction that does nothing and has zero size """ |
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
277
diff
changeset
|
69 def encode(self): |
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
277
diff
changeset
|
70 return bytes() |
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
277
diff
changeset
|
71 |
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
277
diff
changeset
|
72 |
234 | 73 class PseudoInstruction(Instruction): |
74 pass | |
75 | |
76 | |
77 class Label(PseudoInstruction): | |
206 | 78 def __init__(self, name): |
79 self.name = name | |
234 | 80 self.address = 0 |
206 | 81 |
235 | 82 def __repr__(self): |
83 return '{}:'.format(self.name) | |
84 | |
85 def encode(self): | |
86 return bytes() | |
87 | |
206 | 88 @classmethod |
89 def Create(cls, vop): | |
90 if type(vop) is ASymbol: | |
91 name = vop.name | |
92 return cls(name) | |
93 | |
235 | 94 |
234 | 95 class Comment(PseudoInstruction): |
96 def __init__(self, txt): | |
97 self.txt = txt | |
249 | 98 |
235 | 99 def encode(self): |
100 return bytes() | |
249 | 101 |
234 | 102 def __repr__(self): |
103 return '; {}'.format(self.txt) | |
104 | |
235 | 105 |
234 | 106 class Alignment(PseudoInstruction): |
107 def __init__(self, a): | |
108 self.align = a | |
235 | 109 |
110 def __repr__(self): | |
111 return 'ALIGN({})'.format(self.align) | |
112 | |
234 | 113 def encode(self): |
114 pad = [] | |
115 address = self.address | |
235 | 116 while (address % self.align) != 0: |
234 | 117 address += 1 |
118 pad.append(0) | |
119 return bytes(pad) | |
120 | |
292 | 121 |
249 | 122 class DebugInfo(PseudoInstruction): |
123 def __init__(self, i): | |
124 self.info = i | |
125 | |
126 def __repr__(self): | |
127 return 'DebugInfo: {}'.format(self.info) | |
128 | |
129 def encode(self): | |
130 return bytes() | |
234 | 131 |
292 | 132 |
199 | 133 class Register(Operand): |
134 def __init__(self, name): | |
135 self.name = name | |
136 | |
137 | |
138 class Target: | |
201 | 139 def __init__(self, name, desc=''): |
140 self.name = name | |
141 self.desc = desc | |
200 | 142 self.registers = [] |
199 | 143 self.instructions = [] |
200 | 144 |
201 | 145 def instruction(self, cls): |
146 """ Decorator function that registers an instruction to this target """ | |
202 | 147 self.addInstruction(cls) |
201 | 148 return cls |
149 | |
206 | 150 def check(self): |
151 """ Check target """ | |
152 for i in self.instructions: | |
153 assert hasattr(i, 'mnemonic') | |
154 assert hasattr(i, 'operands'), str(i) | |
155 assert type(i.mnemonic) is str | |
156 assert type(i.operands) is tuple, str(i) | |
157 | |
202 | 158 def addInstruction(self, ins_class): |
159 self.instructions.append(ins_class) | |
160 | |
200 | 161 def mapOperand(self, operand): |
162 """ Try to map an operand to a target type """ | |
163 if type(operand) is ASymbol: | |
164 # Try to map to register: | |
165 regs = {} | |
166 for r in self.registers: | |
167 regs[r.name] = r | |
168 if operand.name in regs: | |
169 return regs[operand.name] | |
201 | 170 raise CompilerError('Cannot map {0}'.format(operand)) |
199 | 171 |
200 | 172 def mapInstruction(self, vi): |
203 | 173 assert type(vi) is AInstruction |
200 | 174 """ Map ast tree to real instruction for this target """ |
199 | 175 |
200 | 176 # map to real operands: |
236 | 177 if vi.mnemonic.upper() == 'ALIGN' and len(vi.operands) == 1: |
178 if type(vi.operands[0]) == ANumber: | |
179 return Alignment(vi.operands[0].number) | |
200 | 180 |
181 # look for a suitable instruction | |
182 for ic in self.instructions: | |
219 | 183 if ic.mnemonic.upper() == vi.mnemonic.upper() and len(ic.operands) == len(vi.operands): |
203 | 184 # Try to map operands to the correct operand types: |
185 rops = [roptype.Create(vop) for roptype, vop in zip(ic.operands, vi.operands)] | |
186 | |
187 # Check if we succeeded: | |
277 | 188 if all(isinstance(rop, optype) for rop, optype in zip(rops, ic.operands)): |
203 | 189 return ic(*rops) |
201 | 190 raise CompilerError('No suitable instruction found for "{0}"'.format(vi)) |