From bef1aba8ceb5439b4cde834690e14969775816b3 Mon Sep 17 00:00:00 2001 From: Chris Pressey Date: Mon, 11 Dec 2017 10:42:42 +0000 Subject: [PATCH] Do not assume every label refers to a word-sized chunk of memory. --- src/sixtypical/compiler.py | 26 ++++++++++++++++++++------ src/sixtypical/emitter.py | 18 ++++++++++++++---- src/sixtypical/model.py | 1 + 3 files changed, 35 insertions(+), 10 deletions(-) diff --git a/src/sixtypical/compiler.py b/src/sixtypical/compiler.py index fa633fc..11a0cb6 100644 --- a/src/sixtypical/compiler.py +++ b/src/sixtypical/compiler.py @@ -3,7 +3,7 @@ from sixtypical.ast import Program, Routine, Block, Instr from sixtypical.model import ( ConstantRef, LocationRef, IndexedRef, IndirectRef, AddressRef, - TYPE_BIT, TYPE_BYTE, TYPE_WORD, TYPE_WORD_TABLE, BufferType, PointerType, RoutineType, VectorType, + TYPE_BIT, TYPE_BYTE, TYPE_BYTE_TABLE, TYPE_WORD, TYPE_WORD_TABLE, BufferType, PointerType, RoutineType, VectorType, REG_A, REG_X, REG_Y, FLAG_C ) from sixtypical.emitter import Byte, Label, Offset, LowAddressByte, HighAddressByte @@ -35,10 +35,22 @@ class Compiler(object): assert isinstance(program, Program) for defn in program.defns: - label = Label(defn.name) - if defn.addr is not None: - label.set_addr(defn.addr) - self.labels[defn.name] = label + # compute length of memory pointed to. this is awful. + length = None + type_ = defn.location.type + if type_ == TYPE_BYTE: + length = 1 + elif type_ == TYPE_WORD or isinstance(type_, (PointerType, VectorType)): + length = 2 + elif type_ == TYPE_BYTE_TABLE: + length = 256 + elif type_ == TYPE_WORD_TABLE: + length = 512 + elif isinstance(type_, BufferType): + length = type_.size + if length is None: + raise NotImplementedError("Need size for type {}".format(type_)) + self.labels[defn.name] = Label(defn.name, addr=defn.addr, length=length) for routine in program.routines: self.routines[routine.name] = routine @@ -60,8 +72,10 @@ class Compiler(object): for defn in program.defns: if defn.initial is not None: label = self.labels[defn.name] + initial_data = Byte(defn.initial) # TODO: support other types than Byte + label.set_length(initial_data.size()) self.emitter.resolve_label(label) - self.emitter.emit(Byte(defn.initial)) + self.emitter.emit(initial_data) # uninitialized, "BSS" data for defn in program.defns: diff --git a/src/sixtypical/emitter.py b/src/sixtypical/emitter.py index 418ffc2..ffa899c 100644 --- a/src/sixtypical/emitter.py +++ b/src/sixtypical/emitter.py @@ -1,3 +1,8 @@ +"""Binary machine code emitter. Used in SixtyPical to emit 6502 machine code, +but not specific to SixtyPical, or 6502. Not even necessarily machine code - +though some parts are written around the assumptions of 8-bit architectures.""" + + class Emittable(object): def size(self): raise NotImplementedError @@ -54,13 +59,17 @@ class Table(Emittable): class Label(Emittable): - def __init__(self, name, addr=None): + def __init__(self, name, addr=None, length=None): self.name = name self.addr = addr + self.length = length def set_addr(self, addr): self.addr = addr + def set_length(self, length): + self.length = length + def size(self): return 2 @@ -77,8 +86,9 @@ class Label(Emittable): return Byte(self.addr + offset).serialize() def __repr__(self): - addrs = ', addr=%r' % self.addr if self.addr is not None else '' - return "%s(%r%s)" % (self.__class__.__name__, self.name, addrs) + addr_s = ', addr=%r' % self.addr if self.addr is not None else '' + length_s = ', length=%r' % self.length if self.length is not None else '' + return "%s(%r%s%s)" % (self.__class__.__name__, self.name, addr_s, length_s) class Offset(Emittable): @@ -165,4 +175,4 @@ class Emitter(object): """Set the given label to be at the current address and advance the address for the next label, but don't emit anything.""" self.resolve_label(label) - self.addr += label.size() + self.addr += label.length diff --git a/src/sixtypical/model.py b/src/sixtypical/model.py index 49ad716..2c4e730 100644 --- a/src/sixtypical/model.py +++ b/src/sixtypical/model.py @@ -1,5 +1,6 @@ """Data/storage model for SixtyPical.""" + class Type(object): def __init__(self, name): self.name = name