git @ Cat's Eye Technologies ZOWIE / 34ab1f2
Clean up how References and Instructions work. Needs more tests. Chris Pressey 7 years ago
2 changed file(s) with 52 addition(s) and 65 deletion(s). Raw diff Collapse all Expand all
189189
190190
191191 class Reference(object): # abstract
192 def get_register_number(self):
192 def get_value(self, state):
193193 raise NotImplementedError
194194
195 def set_value(self, state, value):
196 raise NotImplementedError
197
195198
196199 class ImmediateReference(Reference):
197 def __init__(self, number):
198 self.number = number
200 def __init__(self, value):
201 self.value = value
202
203 def get_value(self, state):
204 return self.value
205
206 def __str__(self):
207 return str(self.number)
199208
200209
201210 class DirectRegisterReference(Reference):
202 def __init__(self, number):
203 self.number = number
204
205 def get_register_number(self):
206 return self.number
211 def __init__(self, index):
212 self.index = index
213
214 def get_value(self, state):
215 return state[self.index]
216
217 def set_value(self, state, value):
218 state[self.index] = value
219
220 def __str__(self):
221 return "R%d" % self.number
207222
208223
209224 class IndirectRegisterReference(Reference):
211226 assert isinstance(ref, Reference)
212227 self.ref = ref
213228
214 def get_register_number(self):
215 return self.ref.get_register_number()
229 def get_value(self, state):
230 return state[self.ref.get_value(state)]
231
232 def set_value(self, state, value):
233 state[self.ref.get_value(state)] = value
234
235 def __str__(self):
236 return "R[%s]" % self.ref
216237
217238
218239 class Scanner(object):
239260 self.line = self.line[1:]
240261 if self.line[0] == '[':
241262 self.line = self.line[1:]
242 inner = self.scan_register()
263 inner = self.scan_reference()
243264 self.expect(']')
244265 return IndirectRegisterReference(inner)
245266 else:
252273
253274 class Instruction(object):
254275 def __init__(self):
255 self.source_register = 0
256 self.destination_register = 0
257 self.source_is_immediate = False
258 self.source_is_indirect = False
259 self.destination_is_indirect = False
276 self.source_register = None
277 self.destination_register = None
260278
261279 def parse(self, line):
262280 line = line.strip()
265283
266284 scanner = Scanner(line)
267285 scanner.expect('MOV')
268 line = scanner.line
269
270 dest = scanner.scan_reference()
286
287 self.destination_register = scanner.scan_reference()
288
289 assert not isinstance(self.destination_register, ImmediateReference)
290
271291 scanner.expect(',')
272 source = scanner.scan_reference()
292 self.source_register = scanner.scan_reference()
273293
274294 if scanner.line and scanner.line[0] != ';':
275295 raise SyntaxError("Expected EOL or comment")
276
277 assert not isinstance(dest, ImmediateReference)
278
279 if isinstance(source, ImmediateReference):
280 assert isinstance(dest, DirectRegisterReference)
281
282 self.source_is_immediate = True
283 self.destination_register = dest.get_register_number()
284 self.source_register = source.number
285 return True
286
287 if isinstance(dest, IndirectRegisterReference):
288 self.destination_is_indirect = True
289 self.destination_register = dest.get_register_number()
290
291 if isinstance(source, IndirectRegisterReference):
292 self.source_is_indirect = True
293 self.source_register = source.get_register_number()
294296
295297 return True
296298
297299 def apply(self, state):
298 if self.source_is_indirect:
299 source_register = state[self.source_register]
300 else:
301 source_register = self.source_register
302
303 if self.source_is_immediate:
304 contents = source_register
305 else:
306 contents = state[source_register]
307
308 if self.destination_is_indirect:
309 destination_register = state[self.destination_register]
310 else:
311 destination_register = self.destination_register
312 state[destination_register] = contents
313
314 def __str__(self):
315 dest_fmt = "R%d"
316 if self.destination_is_indirect:
317 dest_fmt = "R[R%d]"
318 src_fmt = "R%d"
319 if self.source_is_indirect:
320 src_fmt = "R[R%d]"
321 if self.source_is_immediate:
322 src_fmt = "%d"
323 return "MOV %s, %s" % (dest_fmt % self.destination_register,
324 src_fmt % self.source_register)
300 value = self.source_register.get_value(state)
301 self.destination_register.set_value(state, value)
302
303 def __str__(self):
304 return "MOV %s, %s" % (self.destination_register, self.source_register)
325305
326306
327307 class Processor(object):
5858
5959 | MOV r11, 5
6060 ?
61
62 The destination cannot be an immediate.
63
64 | MOV 5, R11
65 ?
66
67 TODO need tests for indirect references here.