Assembler working
This commit is contained in:
parent
9460e94ed0
commit
7164a70f81
|
@ -0,0 +1,62 @@
|
||||||
|
# YTD 12-bit Computer
|
||||||
|
*Yeahbut, aka Kyler Olsen*
|
||||||
|
|
||||||
|
It is a custom computer and instruction set architecture. It also has its own
|
||||||
|
assembly language with assembler. Custom high level language coming soon!
|
||||||
|
|
||||||
|
## ISA
|
||||||
|
*WIP*
|
||||||
|
|
||||||
|
## Assembly Language
|
||||||
|
*WIP*
|
||||||
|
|
||||||
|
### Registers
|
||||||
|
|
||||||
|
- `ZR`
|
||||||
|
- `PC`
|
||||||
|
- `SP`
|
||||||
|
- `MP`
|
||||||
|
- `D0`
|
||||||
|
- `D1`
|
||||||
|
- `D2`
|
||||||
|
- `D3`
|
||||||
|
|
||||||
|
### Zero Operand Instructions
|
||||||
|
|
||||||
|
- `NOP`
|
||||||
|
- `HLT`
|
||||||
|
- `INT`
|
||||||
|
- `BNZ`
|
||||||
|
- `BLK`
|
||||||
|
- `ENB`
|
||||||
|
|
||||||
|
### One Operand Instructions
|
||||||
|
|
||||||
|
- `GLA` `Destination Register`
|
||||||
|
- `GET` `Destination Register`
|
||||||
|
- `LOD` `Destination Register`
|
||||||
|
- `STR` `Source Register`
|
||||||
|
- `PSH` `Source Register`
|
||||||
|
- `POP` `Destination Register`
|
||||||
|
- `LDI` `Immediate Value`
|
||||||
|
- `LDI` :`Label`
|
||||||
|
|
||||||
|
### Two Operand Instructions
|
||||||
|
|
||||||
|
- `LSH` `Destination Register` `Source Register`
|
||||||
|
- `RSH` `Destination Register` `Source Register`
|
||||||
|
- `INC` `Destination Register` `Source Register`
|
||||||
|
- `DEC` `Destination Register` `Source Register`
|
||||||
|
|
||||||
|
### Three Operand Instructions
|
||||||
|
|
||||||
|
- `AND` `Destination Register` `Source Register A` `Source Register B`
|
||||||
|
- `OR` `Destination Register` `Source Register A` `Source Register B`
|
||||||
|
- `NAD` `Destination Register` `Source Register A` `Source Register B`
|
||||||
|
- `SUB` `Destination Register` `Source Register A` `Source Register B`
|
||||||
|
- `XOR` `Destination Register` `Source Register A` `Source Register B`
|
||||||
|
- `NOR` `Destination Register` `Source Register A` `Source Register B`
|
||||||
|
- `ADD` `Destination Register` `Source Register A` `Source Register B`
|
||||||
|
|
||||||
|
## High Level Language
|
||||||
|
*WIP*
|
|
@ -1,12 +1,98 @@
|
||||||
# Kyler Olsen
|
# Kyler Olsen
|
||||||
# Feb 2024
|
# Feb 2024
|
||||||
|
|
||||||
|
import argparse
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
|
from typing import TypeVar, Generic, Iterable
|
||||||
|
|
||||||
|
INSTRUCTIONS_COUNT = 0x700
|
||||||
|
|
||||||
class AssemblerError(Exception): pass
|
class AssemblerError(Exception): pass
|
||||||
class LinkerError(Exception): pass
|
class LinkerError(Exception): pass
|
||||||
|
|
||||||
|
KEY = TypeVar("KEY")
|
||||||
|
ANTIKEY = TypeVar("ANTIKEY")
|
||||||
|
|
||||||
|
|
||||||
|
class TwoWayDictionary(Generic[KEY, ANTIKEY]):
|
||||||
|
|
||||||
|
_dict: dict[KEY, ANTIKEY]
|
||||||
|
_antidict: dict[ANTIKEY, KEY]
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
keys: Iterable[KEY] | None = None,
|
||||||
|
antikeys: Iterable[ANTIKEY] | None = None,
|
||||||
|
):
|
||||||
|
if (keys is None) and (antikeys is None):
|
||||||
|
self._dict = {}
|
||||||
|
self._antidict = {}
|
||||||
|
elif (
|
||||||
|
(keys is None) or
|
||||||
|
(antikeys is None) or
|
||||||
|
len(keys) != len(antikeys) # type: ignore
|
||||||
|
):
|
||||||
|
raise ValueError
|
||||||
|
else:
|
||||||
|
self._dict = dict(zip(keys, antikeys)) # type: ignore
|
||||||
|
self._antidict = dict(zip(antikeys, keys)) # type: ignore
|
||||||
|
|
||||||
|
def get_forwards(self, key: KEY, default: None | ANTIKEY = None) -> ANTIKEY:
|
||||||
|
if key not in self._dict:
|
||||||
|
if default is None: raise KeyError("Key not in dictionary")
|
||||||
|
else: return default
|
||||||
|
else: return self._dict[key]
|
||||||
|
|
||||||
|
def get_backwards(
|
||||||
|
self,
|
||||||
|
antikey: ANTIKEY,
|
||||||
|
default: None | KEY = None,
|
||||||
|
) -> KEY:
|
||||||
|
if antikey not in self._antidict:
|
||||||
|
if default is None: raise KeyError("Anti-Key not in dictionary")
|
||||||
|
else: return default
|
||||||
|
else: return self._antidict[antikey]
|
||||||
|
|
||||||
|
def set_forwards(self, key: KEY, antikey: ANTIKEY):
|
||||||
|
if antikey in self._antidict:
|
||||||
|
raise KeyError("Anti-Key already in dictionary.")
|
||||||
|
if key in self._dict:
|
||||||
|
del self._antidict[self._dict[key]]
|
||||||
|
self._dict[key] = antikey
|
||||||
|
self._antidict[antikey] = key
|
||||||
|
|
||||||
|
def set_backwards(self, antikey: ANTIKEY, key: KEY):
|
||||||
|
if key in self._dict:
|
||||||
|
raise KeyError("Key already in dictionary.")
|
||||||
|
if antikey in self._antidict:
|
||||||
|
del self._dict[self._antidict[antikey]]
|
||||||
|
self._antidict[antikey] = key
|
||||||
|
self._dict[key] = antikey
|
||||||
|
|
||||||
|
def del_forwards(self, key: KEY):
|
||||||
|
if key not in self._dict:
|
||||||
|
raise KeyError("Key not in dictionary.")
|
||||||
|
del self._antidict[self._dict[key]]
|
||||||
|
del self._dict[key]
|
||||||
|
|
||||||
|
def del_backwards(self, antikey: ANTIKEY):
|
||||||
|
if antikey not in self._antidict:
|
||||||
|
raise KeyError("Anti-Key not in dictionary.")
|
||||||
|
del self._dict[self._antidict[antikey]]
|
||||||
|
del self._antidict[antikey]
|
||||||
|
|
||||||
|
def keys(self) -> Iterable[KEY]:
|
||||||
|
return self._dict.keys()
|
||||||
|
|
||||||
|
def antikeys(self) -> Iterable[ANTIKEY]:
|
||||||
|
return self._antidict.keys()
|
||||||
|
|
||||||
|
def items(self) -> Iterable[tuple[KEY, ANTIKEY]]:
|
||||||
|
return self._dict.items()
|
||||||
|
|
||||||
|
def antiitems(self) -> Iterable[tuple[ANTIKEY, KEY]]:
|
||||||
|
return self._antidict.items()
|
||||||
|
|
||||||
|
|
||||||
class Instruction(namedtuple('Instruction', ['bb', 'bl', 'lb', 'll'])):
|
class Instruction(namedtuple('Instruction', ['bb', 'bl', 'lb', 'll'])):
|
||||||
|
|
||||||
|
@ -34,49 +120,193 @@ class Instruction(namedtuple('Instruction', ['bb', 'bl', 'lb', 'll'])):
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class Label:
|
class Directive:
|
||||||
|
|
||||||
value: str
|
@staticmethod
|
||||||
|
def directive(line: str, line_number: int) -> "Directive":
|
||||||
|
value = int(line[1:], base=0)
|
||||||
|
return MemoryLocation(value)
|
||||||
|
|
||||||
|
|
||||||
|
class MemoryLocation(Directive):
|
||||||
|
|
||||||
|
_value: int
|
||||||
|
|
||||||
|
def __init__(self, value: int):
|
||||||
|
self._value = value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def value(self) -> int:
|
||||||
|
return self._value
|
||||||
|
|
||||||
|
|
||||||
|
class Label(Directive):
|
||||||
|
|
||||||
|
_value: str
|
||||||
|
|
||||||
def __init__(self, value: str):
|
def __init__(self, value: str):
|
||||||
self.value = value
|
self._value = value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def value(self) -> str:
|
||||||
|
return self._value
|
||||||
|
|
||||||
|
|
||||||
class Immediate(Label): pass
|
class Immediate(Directive):
|
||||||
|
|
||||||
|
_value: str
|
||||||
|
|
||||||
|
def __init__(self, value: str):
|
||||||
|
self._value = value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def value(self) -> str:
|
||||||
|
return self._value
|
||||||
|
|
||||||
|
|
||||||
class Program:
|
class Program:
|
||||||
|
|
||||||
_instructions: list[Instruction | Label]
|
instruction_set = {
|
||||||
_labels: list[tuple[int, Label]]
|
"NOP": lambda *_: Instruction(0, 0, 0, 0),
|
||||||
|
"HLT": lambda *_: Instruction(0, 0, 0, 1),
|
||||||
|
"INT": lambda *_: Instruction(0, 0, 0, 2),
|
||||||
|
"BNZ": lambda *_: Instruction(0, 0, 0, 3),
|
||||||
|
"BLK": lambda *_: Instruction(0, 0, 0, 4),
|
||||||
|
"ENB": lambda *_: Instruction(0, 0, 0, 5),
|
||||||
|
|
||||||
|
"GLA": lambda l, i: Instruction(0, 0, 2, reg1(l, i)),
|
||||||
|
"GET": lambda l, i: Instruction(0, 0, 3, reg1(l, i)),
|
||||||
|
"LOD": lambda l, i: Instruction(0, 0, 4, reg1(l, i)),
|
||||||
|
"STR": lambda l, i: Instruction(0, 0, 5, reg1(l, i)),
|
||||||
|
"PSH": lambda l, i: Instruction(0, 0, 6, reg1(l, i)),
|
||||||
|
"POP": lambda l, i: Instruction(0, 0, 7, reg1(l, i)),
|
||||||
|
|
||||||
|
"LDI": lambda l, i: immediate(l, i),
|
||||||
|
|
||||||
|
"LSH": lambda l, i: Instruction(0, 4, *reg2(l, i)),
|
||||||
|
"RSH": lambda l, i: Instruction(0, 5, *reg2(l, i)),
|
||||||
|
"INC": lambda l, i: Instruction(0, 6, *reg2(l, i)),
|
||||||
|
"DEC": lambda l, i: Instruction(0, 7, *reg2(l, i)),
|
||||||
|
|
||||||
|
"AND": lambda l, i: Instruction(1, *reg3(l, i)),
|
||||||
|
"OR": lambda l, i: Instruction(2, *reg3(l, i)),
|
||||||
|
"NAD": lambda l, i: Instruction(3, *reg3(l, i)),
|
||||||
|
"SUB": lambda l, i: Instruction(4, *reg3(l, i)),
|
||||||
|
"XOR": lambda l, i: Instruction(5, *reg3(l, i)),
|
||||||
|
"NOR": lambda l, i: Instruction(6, *reg3(l, i)),
|
||||||
|
"ADD": lambda l, i: Instruction(7, *reg3(l, i)),
|
||||||
|
}
|
||||||
|
|
||||||
|
_program: str
|
||||||
|
_instructions: list[tuple[int, Instruction | Directive]]
|
||||||
_immediate: list[tuple[int, Immediate]]
|
_immediate: list[tuple[int, Immediate]]
|
||||||
|
|
||||||
def __init__(self, instructions: list[Instruction | Label]):
|
_instruction_map: TwoWayDictionary[int, int]
|
||||||
self._instructions = instructions
|
_label_map: dict[str, int]
|
||||||
self._labels = []
|
|
||||||
|
def __init__(self, program: str):
|
||||||
|
self._program = program
|
||||||
|
|
||||||
|
self._instructions = self.parse(self._program)
|
||||||
self._immediate = []
|
self._immediate = []
|
||||||
for index, item in enumerate(self._instructions):
|
self._label_map = {}
|
||||||
if isinstance(item, Label) and not isinstance(item, Immediate):
|
self._instruction_map = TwoWayDictionary()
|
||||||
self._labels.append((index, item))
|
|
||||||
elif isinstance(item, Immediate):
|
self._link()
|
||||||
self._immediate.append((index, item))
|
|
||||||
|
|
||||||
def __bytes__(self) -> bytes:
|
def __bytes__(self) -> bytes:
|
||||||
if self._labels or self._immediate:
|
|
||||||
raise LinkerError("Program Not Linked Properly.")
|
|
||||||
for item in self._instructions:
|
|
||||||
if not isinstance(item, Instruction):
|
|
||||||
raise LinkerError("Program Not Linked Properly.")
|
|
||||||
|
|
||||||
output = bytearray()
|
output = bytearray()
|
||||||
for i in self._instructions:
|
for i in range(INSTRUCTIONS_COUNT):
|
||||||
output += bytes(i) # type: ignore
|
instruction = self._get_instruction(i)
|
||||||
return output
|
output += bytes(instruction)
|
||||||
|
return bytes(output)
|
||||||
|
|
||||||
def link(self):
|
def labels(self) -> dict[str, int]:
|
||||||
pass
|
return self._label_map.copy()
|
||||||
|
|
||||||
def reg(reg: str) -> int:
|
def _get_instruction(self, index: int) -> Instruction:
|
||||||
|
new_index = self._instruction_map.get_forwards(index, -1)
|
||||||
|
if new_index == -1: value = self.instruction_set["NOP"]("NOP", -1)
|
||||||
|
else: _, value = self._instructions[new_index]
|
||||||
|
if isinstance(value, Immediate):
|
||||||
|
return self.instruction_set["LDI"](
|
||||||
|
f"LDI {self._label_map[value.value]}", -1)
|
||||||
|
elif isinstance(value, Directive):
|
||||||
|
raise LinkerError("Unexpected directive!")
|
||||||
|
else:
|
||||||
|
return value
|
||||||
|
|
||||||
|
def _get_instruction_line(self, index: int) -> int:
|
||||||
|
return self._instruction_map.get_backwards(index)
|
||||||
|
|
||||||
|
def _link(self):
|
||||||
|
instruction_line = 0
|
||||||
|
for index, (line_number, item) in enumerate(self._instructions):
|
||||||
|
if isinstance(item, MemoryLocation):
|
||||||
|
instruction_line = item.value
|
||||||
|
elif isinstance(item, Label):
|
||||||
|
if item.value in self._label_map:
|
||||||
|
raise LinkerError(
|
||||||
|
"Label already declared on line"
|
||||||
|
f" {line_number}: {item.value}"
|
||||||
|
)
|
||||||
|
self._label_map[item.value] = instruction_line
|
||||||
|
elif isinstance(item, Immediate):
|
||||||
|
self._immediate.append((index, item))
|
||||||
|
self._instruction_map.set_forwards(instruction_line, index)
|
||||||
|
instruction_line += 1
|
||||||
|
elif isinstance(item, Directive):
|
||||||
|
raise LinkerError(
|
||||||
|
f"Unknown or Invalid Directive! on line {line_number}.")
|
||||||
|
else:
|
||||||
|
self._instruction_map.set_forwards(instruction_line, index)
|
||||||
|
instruction_line += 1
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def parse(cls, s: str) -> list[tuple[int, Instruction | Directive]]:
|
||||||
|
instructions: list[tuple[int, Instruction | Directive]] = []
|
||||||
|
|
||||||
|
last_error = None
|
||||||
|
|
||||||
|
for raw_line_number, raw_line in enumerate(s.splitlines(False)):
|
||||||
|
try:
|
||||||
|
line_number = raw_line_number + 1
|
||||||
|
line = raw_line.strip().upper()
|
||||||
|
if len(line) == 0 or line[0] == ";":
|
||||||
|
pass
|
||||||
|
elif line[:3] in cls.instruction_set:
|
||||||
|
instructions.append((
|
||||||
|
line_number,
|
||||||
|
cls.instruction_set[line[:3]](line, line_number),
|
||||||
|
))
|
||||||
|
elif line[:2] in cls.instruction_set:
|
||||||
|
instructions.append((
|
||||||
|
line_number,
|
||||||
|
cls.instruction_set[line[:2]](line, line_number),
|
||||||
|
))
|
||||||
|
elif line[-1] == ":":
|
||||||
|
instructions.append((
|
||||||
|
line_number,
|
||||||
|
Label(line[:-1]),
|
||||||
|
))
|
||||||
|
elif line[0] == ".":
|
||||||
|
instructions.append((
|
||||||
|
line_number,
|
||||||
|
Directive.directive(line, line_number),
|
||||||
|
))
|
||||||
|
elif line:
|
||||||
|
raise AssemblerError(
|
||||||
|
f"Invalid Instruction on line {line_number}: '{line}'")
|
||||||
|
except (AssemblerError, LinkerError) as e:
|
||||||
|
last_error = e
|
||||||
|
print(f"Error:\n\t{e}")
|
||||||
|
if last_error is not None:
|
||||||
|
raise last_error
|
||||||
|
|
||||||
|
return instructions
|
||||||
|
|
||||||
|
|
||||||
|
def reg(reg: str, line_number: int) -> int:
|
||||||
register_names = [
|
register_names = [
|
||||||
"ZR",
|
"ZR",
|
||||||
"PC",
|
"PC",
|
||||||
|
@ -102,42 +332,44 @@ def reg(reg: str) -> int:
|
||||||
elif reg in register_numbers:
|
elif reg in register_numbers:
|
||||||
return register_numbers.index(reg)
|
return register_numbers.index(reg)
|
||||||
else:
|
else:
|
||||||
raise AssemblerError(f"Invalid Register: {reg}")
|
raise AssemblerError(
|
||||||
|
f"Invalid Register on line {line_number}: {reg}")
|
||||||
|
|
||||||
def reg1(l: str) -> int:
|
def reg1(line: str, line_number: int) -> int:
|
||||||
args = l.split(' ')
|
args = line.split(' ')
|
||||||
if len(args) == 2:
|
if len(args) == 2:
|
||||||
return reg(args[1])
|
return reg(args[1], line_number)
|
||||||
else:
|
else:
|
||||||
raise AssemblerError(f"Invalid number of arguments: {args[0]}")
|
raise AssemblerError(
|
||||||
|
f"Invalid number of arguments on line {line_number}: {args[0]}")
|
||||||
|
|
||||||
def reg2(l: str) -> tuple[int, int]:
|
def reg2(line: str, line_number: int) -> tuple[int, int]:
|
||||||
args = l.split(' ')
|
args = line.split(' ')
|
||||||
if len(args) == 3:
|
if len(args) == 3:
|
||||||
return reg(args[2]), reg(args[1])
|
return reg(args[2], line_number), reg(args[1], line_number)
|
||||||
else:
|
else:
|
||||||
raise AssemblerError(f"Invalid number of arguments: {args[0]}")
|
raise AssemblerError(
|
||||||
|
f"Invalid number of arguments on line {line_number}: {args[0]}")
|
||||||
|
|
||||||
def reg3(l: str) -> tuple[int, int, int]:
|
def reg3(line: str, line_number: int) -> tuple[int, int, int]:
|
||||||
args = l.split(' ')
|
args = line.split(' ')
|
||||||
if len(args) == 4:
|
if len(args) == 4:
|
||||||
return reg(args[2]), reg(args[3]), reg(args[1])
|
return (
|
||||||
|
reg(args[2], line_number),
|
||||||
|
reg(args[3], line_number),
|
||||||
|
reg(args[1], line_number),
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
raise AssemblerError(f"Invalid number of arguments: {args[0]}")
|
raise AssemblerError(
|
||||||
|
f"Invalid number of arguments on line {line_number}: {args[0]}")
|
||||||
|
|
||||||
def immediate(l: str) -> Instruction | Immediate:
|
def immediate(line: str, line_number: int) -> Instruction | Immediate:
|
||||||
args = l.split(' ')
|
args = line.split(' ')
|
||||||
if len(args) == 2:
|
if len(args) == 2:
|
||||||
if ':' in args[1]:
|
if ':' in args[1]:
|
||||||
return Immediate(args[1][1:])
|
return Immediate(args[1][1:])
|
||||||
elif 'b' in args[1]:
|
|
||||||
value = int(args[1].split('b')[1], base=2)
|
|
||||||
elif 'o' in args[1]:
|
|
||||||
value = int(args[1].split('o')[1], base=8)
|
|
||||||
elif 'x' in args[1]:
|
|
||||||
value = int(args[1].split('x')[1], base=16)
|
|
||||||
else:
|
else:
|
||||||
value = int(args[1])
|
value = int(args[1], base=0)
|
||||||
|
|
||||||
return Instruction(
|
return Instruction(
|
||||||
0,
|
0,
|
||||||
|
@ -146,52 +378,32 @@ def immediate(l: str) -> Instruction | Immediate:
|
||||||
value & 0x007,
|
value & 0x007,
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
raise AssemblerError(f"Invalid number of arguments: {args[0]}")
|
raise AssemblerError(
|
||||||
|
f"Invalid number of arguments on line {line_number}: {args[0]}")
|
||||||
|
|
||||||
def parse(s: str) -> list[Instruction | Label]:
|
def main():
|
||||||
instruction_set = {
|
parser = argparse.ArgumentParser(
|
||||||
"NOP": lambda _: Instruction(0,0,0,0),
|
prog='ytd12LA',
|
||||||
"HLT": lambda _: Instruction(0,0,0,1),
|
description='ytd 12-bit Linker and Assembler',
|
||||||
"INT": lambda _: Instruction(0,0,0,2),
|
# epilog='Text at the bottom of help',
|
||||||
"BNZ": lambda _: Instruction(0,0,0,3),
|
)
|
||||||
"BLK": lambda _: Instruction(0,0,0,4),
|
parser.add_argument('input_file')
|
||||||
"ENB": lambda _: Instruction(0,0,0,5),
|
parser.add_argument('-o', '--output_file')
|
||||||
|
parser.add_argument('-l', '--labels_file')
|
||||||
|
|
||||||
"GLA": lambda l: Instruction(0,0,2,reg1(l)),
|
args = parser.parse_args()
|
||||||
"GET": lambda l: Instruction(0,0,3,reg1(l)),
|
|
||||||
"LOD": lambda l: Instruction(0,0,4,reg1(l)),
|
|
||||||
"STR": lambda l: Instruction(0,0,5,reg1(l)),
|
|
||||||
"PSH": lambda l: Instruction(0,0,6,reg1(l)),
|
|
||||||
"POP": lambda l: Instruction(0,0,7,reg1(l)),
|
|
||||||
|
|
||||||
"LDI": lambda l: immediate(l),
|
with open(args.input_file) as ifile:
|
||||||
|
program = Program(ifile.read())
|
||||||
|
|
||||||
"LSH": lambda l: Instruction(0,4,*reg2(l)),
|
if args.output_file:
|
||||||
"RSH": lambda l: Instruction(0,5,*reg2(l)),
|
with open(args.output_file, 'wb') as ofile:
|
||||||
"INC": lambda l: Instruction(0,6,*reg2(l)),
|
ofile.write(bytes(program))
|
||||||
"DEC": lambda l: Instruction(0,7,*reg2(l)),
|
|
||||||
|
|
||||||
"AND": lambda l: Instruction(1,*reg3(l)),
|
if args.labels_file:
|
||||||
"OR": lambda l: Instruction(2,*reg3(l)),
|
with open(args.labels_file, 'w') as lfile:
|
||||||
"NAD": lambda l: Instruction(3,*reg3(l)),
|
for label, location in program.labels().items():
|
||||||
"SUB": lambda l: Instruction(4,*reg3(l)),
|
lfile.write(f"{hex(location)}, {label}\n")
|
||||||
"XOR": lambda l: Instruction(5,*reg3(l)),
|
|
||||||
"NOR": lambda l: Instruction(6,*reg3(l)),
|
|
||||||
"ADD": lambda l: Instruction(7,*reg3(l)),
|
|
||||||
}
|
|
||||||
instructions = []
|
|
||||||
|
|
||||||
for rl in s.splitlines(False):
|
if __name__ == '__main__':
|
||||||
l = rl.strip()
|
main()
|
||||||
if l[0] == ";":
|
|
||||||
pass
|
|
||||||
elif l[:3] in instruction_set:
|
|
||||||
instructions.append(instruction_set[l[:3]](l))
|
|
||||||
elif l[:2] in instruction_set:
|
|
||||||
instructions.append(instruction_set[l[:2]](l))
|
|
||||||
elif l[-1] == ":":
|
|
||||||
instructions.append(Label(l[:-1]))
|
|
||||||
elif l.strip():
|
|
||||||
raise AssemblerError(f"Invalid Instruction: '{l.strip()}'")
|
|
||||||
|
|
||||||
return instructions
|
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
; Yeahbut - Feb 2024
|
||||||
|
; Example 1 - ytd 12-bit Computer
|
||||||
|
; Fibonacci
|
||||||
|
|
||||||
|
.0x5
|
||||||
|
main:
|
||||||
|
; Initialize values
|
||||||
|
ldi 1
|
||||||
|
or D0 MP ZR
|
||||||
|
or D1 ZR ZR
|
||||||
|
or D2 ZR ZR
|
||||||
|
|
||||||
|
loop:
|
||||||
|
; Output current value
|
||||||
|
ldi 0x7FE
|
||||||
|
str D0
|
||||||
|
|
||||||
|
; Move values down
|
||||||
|
or D2 D1 ZR
|
||||||
|
or D1 D0 ZR
|
||||||
|
|
||||||
|
; Add last two values to get the next value
|
||||||
|
add D0 D1 D2
|
||||||
|
|
||||||
|
ldi :loop
|
||||||
|
or PC MP ZR
|
Loading…
Reference in New Issue