diff --git a/ass3/zbirnik/src/zbirnik/EmitCtx.py b/ass3/zbirnik/src/zbirnik/EmitCtx.py index 35bf24f..d60955a 100644 --- a/ass3/zbirnik/src/zbirnik/EmitCtx.py +++ b/ass3/zbirnik/src/zbirnik/EmitCtx.py @@ -1,6 +1,10 @@ class EmitContext: - def __init__(self, opcodes, registers, symtab): + REGISTERS = { + 'A': 0, 'X': 1, 'L': 2, + 'B': 3, 'S': 4, 'T': 5, 'F': 6 + } + + def __init__(self, opcodes, symtab): self.opcodes = opcodes - self.registers = registers self.symtab = symtab self.base = None diff --git a/ass3/zbirnik/src/zbirnik/__pycache__/EmitCtx.cpython-310.pyc b/ass3/zbirnik/src/zbirnik/__pycache__/EmitCtx.cpython-310.pyc index 91fac21..f1955e1 100644 Binary files a/ass3/zbirnik/src/zbirnik/__pycache__/EmitCtx.cpython-310.pyc and b/ass3/zbirnik/src/zbirnik/__pycache__/EmitCtx.cpython-310.pyc differ diff --git a/ass3/zbirnik/src/zbirnik/__pycache__/code.cpython-310.pyc b/ass3/zbirnik/src/zbirnik/__pycache__/code.cpython-310.pyc new file mode 100644 index 0000000..02db896 Binary files /dev/null and b/ass3/zbirnik/src/zbirnik/__pycache__/code.cpython-310.pyc differ diff --git a/ass3/zbirnik/src/zbirnik/code.py b/ass3/zbirnik/src/zbirnik/code.py index b3e9fdc..5ed7455 100644 --- a/ass3/zbirnik/src/zbirnik/code.py +++ b/ass3/zbirnik/src/zbirnik/code.py @@ -2,17 +2,14 @@ from zbirnik.ukazi.node import Node class Code: - REGISTERS = {'A': 0, 'X': 1, 'L': 2, 'B': 3, 'S': 4, 'T': 5, 'F': 6 } - def __init__(self, name: str | None = None): self.name = name self.nodes = [] self.locctr = 0 self.symtab = {} - self.start_adress = 0 - self.entry_point = 0 + self.start_address = 0 + self.entry_point = None self.program_length = 0 - self.obj = "" def add(self, node: Node): self.nodes.append(node) diff --git a/ass3/zbirnik/src/zbirnik/main.py b/ass3/zbirnik/src/zbirnik/main.py new file mode 100644 index 0000000..929cb4d --- /dev/null +++ b/ass3/zbirnik/src/zbirnik/main.py @@ -0,0 +1,32 @@ +from zbirnik.parser import parser +from zbirnik.code import Code +from zbirnik.EmitCtx import EmitContext +from zbirnik.mnemoniki.mnemoniki_tabela import MNEMONICS +from zbirnik.opcodes import OPCODES + +print("Vnesite ime programa (.asm), ki je v istem direktoriju kakor main.py: ") +ime = input() + +if not ime.endswith(".asm"): + raise ValueError("Ime programa ni v pravi obliki, mora biti: ime.asm") + +code = Code() + +with open(ime) as f: + for line in f: + ctx = parser.parse(line) + + if ctx is None: + continue + + mnemonic = MNEMONICS[ctx.mnemonic] + node = mnemonic.parse(ctx) + code.add(node) + + +code.pass1() + +ctx_emit = EmitContext(opcodes=OPCODES,symtab=code.symtab) + +binary = code.pass2(ctx_emit) +print(binary.hex()) diff --git a/ass3/zbirnik/src/zbirnik/mnemoniki/mnemoniki_tabela.py b/ass3/zbirnik/src/zbirnik/mnemoniki/mnemoniki_tabela.py index a1d4312..d51f052 100644 --- a/ass3/zbirnik/src/zbirnik/mnemoniki/mnemoniki_tabela.py +++ b/ass3/zbirnik/src/zbirnik/mnemoniki/mnemoniki_tabela.py @@ -1,4 +1,4 @@ -from mnemoniki import ( +from zbirnik.mnemoniki import ( mnemonicD, mnemonicDn, mnemonicF1, mnemonicF2n, mnemonicF2r, mnemonicF2rn, mnemonicF2rr, mnemonicF3, mnemonicF3m, mnemonicF4m, diff --git a/ass3/zbirnik/src/zbirnik/opcodes.py b/ass3/zbirnik/src/zbirnik/opcodes.py new file mode 100644 index 0000000..887686f --- /dev/null +++ b/ass3/zbirnik/src/zbirnik/opcodes.py @@ -0,0 +1,61 @@ +OPCODES = { + "FIX": 0xC4, + "FLOAT": 0xC0, + "HIO": 0xF4, + "NORM": 0xC8, + "SIO": 0xF0, + "TIO": 0xF8, + "ADDR": 0x90, + "CLEAR": 0xB4, + "COMPR": 0xA0, + "DIVR": 0x9C, + "MULR": 0x98, + "RMO": 0xAC, + "SHIFTL": 0xA4, + "SHIFTR": 0xA8, + "SUBR": 0x94, + "SVC": 0xB0, + "TIXR": 0xB8, + "ADD": 0x18, + "ADDF": 0x58, + "AND": 0x40, + "COMP": 0x28, + "COMPF": 0x88, + "DIV": 0x24, + "DIVF": 0x64, + "J": 0x3C, + "JEQ": 0x30, + "JGT": 0x34, + "JLT": 0x38, + "JSUB": 0x48, + "LDA": 0x00, + "LDB": 0x68, + "LDCH": 0x50, + "LDF": 0x70, + "LDL": 0x08, + "LDS": 0x6C, + "LDT": 0x74, + "LDX": 0x04, + "LPS": 0xD0, + "MUL": 0x20, + "MULF": 0x60, + "OR": 0x44, + "RD": 0xD8, + "RSUB": 0x4C, + "SSK": 0xEC, + "STA": 0x0C, + "STB": 0x78, + "STCH": 0x54, + "STF": 0x80, + "STI": 0xD4, + "STL": 0x14, + "STS": 0x7C, + "STSW": 0xE8, + "STT": 0x84, + "STX": 0x10, + "SUB": 0x1C, + "SUBF": 0x5C, + "TD": 0xE0, + "TIX": 0x2C, + "WD": 0xDC, +} diff --git a/ass3/zbirnik/src/zbirnik/parser.py b/ass3/zbirnik/src/zbirnik/parser.py index 4aa211b..db9617f 100644 --- a/ass3/zbirnik/src/zbirnik/parser.py +++ b/ass3/zbirnik/src/zbirnik/parser.py @@ -1,8 +1,10 @@ import ply.lex import ply.yacc -import sys +from zbirnik.parserctx import ParserContext -# Lexer. +# -------------------- +# Lexer +# -------------------- tokens = ( 'AT', 'COMMA', @@ -30,60 +32,91 @@ def t_NUMBER(t): def t_COMMENT(t): r'\..*' - t.value = t.value[1:].strip() + t.value = t.value[1:].strip() return t -t_ignore = ' \t\n' +t_ignore = ' \t\n' def t_error(t): - print(f'illegal character {t}') + print(f"Illegal character {t.value[0]!r}") t.lexer.skip(1) lexer = ply.lex.lex() -# Parser. +# -------------------- +# Parser +# -------------------- + def p_start(p): r'''start : LABEL command - | COMMENT - | command''' + | command + | COMMENT + ''' + # komentar + if len(p) == 2 and isinstance(p[1], str): + p[0] = None + return + + # brez labela if len(p) == 2: - if isinstance(p[1], str): - p[0] = ('COMMENT', p[1]) - else: - p[0] = (None, p[1]) + label = None + mnemonic, operands = p[1] else: - p[0] = tuple(p[1:]) + label = p[1] + mnemonic, operands = p[2] + + p[0] = ParserContext(label, mnemonic, operands) + def p_command(p): r'''command : MNEMONIC - | MNEMONIC args''' - p[0] = p[1:] + | MNEMONIC args + ''' + if len(p) == 2: + p[0] = (p[1], []) + else: + p[0] = (p[1], list(p[2])) + def p_args(p): r'''args : operand - | operand COMMA operand''' - match len(p): - case 2: p[0] = (p[1],) - case 4: p[0] = (p[1], p[3]) + | operand COMMA operand + ''' + if len(p) == 2: + p[0] = [p[1]] + else: + p[0] = [p[1], p[3]] + def p_operand(p): r'''operand : REGISTER - | AT address - | HASH address - | address''' - p[0] = p[1:] + | AT address + | HASH address + | address + ''' + if len(p) == 2: + p[0] = p[1] + else: + # @X ali #5 → zadrži znak + p[0] = (p[1], p[2]) + def p_address(p): r'''address : NUMBER - | SYMBOL''' + | SYMBOL + ''' p[0] = p[1] + def p_error(p): if p: - print('Syntax error at token', p) - parser.errok() + raise SyntaxError(f"Syntax error at token {p}") else: - print('Syntax error at EOF') + raise SyntaxError("Syntax error at EOF") + + +parser = ply.yacc.yacc() + if __name__ == '__main__': import sys diff --git a/ass3/zbirnik/src/zbirnik/ukazi/__pycache__/storage.cpython-310.pyc b/ass3/zbirnik/src/zbirnik/ukazi/__pycache__/storage.cpython-310.pyc new file mode 100644 index 0000000..e155d04 Binary files /dev/null and b/ass3/zbirnik/src/zbirnik/ukazi/__pycache__/storage.cpython-310.pyc differ diff --git a/ass3/zbirnik/src/zbirnik/ukazi/f2.py b/ass3/zbirnik/src/zbirnik/ukazi/f2.py index f9f7e7d..f686434 100644 --- a/ass3/zbirnik/src/zbirnik/ukazi/f2.py +++ b/ass3/zbirnik/src/zbirnik/ukazi/f2.py @@ -14,14 +14,14 @@ class f2(Node): opcode = ctx.opcodes[self.mnemonic] if isinstance(self.r1, str): - r1_val = ctx.registers[self.r1] + r1_val = ctx.REGISTERS[self.r1] else: r1_val = self.r1 if self.r2 is None: r2_val = 0 elif isinstance(self.r2, str): - r2_val = ctx.registers[self.r2] + r2_val = ctx.REGISTERS[self.r2] else: r2_val = self.r2 diff --git a/ass3/zbirnik/src/zbirnik/ukazi/storage.py b/ass3/zbirnik/src/zbirnik/ukazi/storage.py index 9a488e5..1e1ca8a 100644 --- a/ass3/zbirnik/src/zbirnik/ukazi/storage.py +++ b/ass3/zbirnik/src/zbirnik/ukazi/storage.py @@ -1,13 +1,22 @@ from zbirnik.ukazi.node import Node class storage(Node): - def __init__(self, val : str | int, name : str, label : str | None = None): + def __init__(self, value : str | int, name : str, label : str | None = None): super().__init__(label) - self.val = val + self.value = value self.name = name def size(self) -> int: + if self.name == "WORD": + return 3 + if self.name == "BYTE": + return len(self.emit(None)) + if self.name == "RESB": + return self.value + if self.name == "RESW": + return 3 * self.value return 0 + def emit(self, ctx): if self.name == "WORD": diff --git a/ass3/zbirnik/src/zbirnik/test_emit.py b/ass3/zbirnik/tests/test_emit.py similarity index 100% rename from ass3/zbirnik/src/zbirnik/test_emit.py rename to ass3/zbirnik/tests/test_emit.py diff --git a/ass3/zbirnik/tests/test_passes.py b/ass3/zbirnik/tests/test_passes.py new file mode 100644 index 0000000..a0f7913 --- /dev/null +++ b/ass3/zbirnik/tests/test_passes.py @@ -0,0 +1,41 @@ +from zbirnik.code import Code +from zbirnik.EmitCtx import EmitContext +from zbirnik.ukazi.f3 import f3 +from zbirnik.ukazi.storage import storage +from zbirnik.adressing import AddrMode + +OPCODES = { + "LDA": 0x00, + "STA": 0x0C, +} + +REGISTERS = { + "A": 0, "X": 1, "L": 2, + "B": 3, "S": 4, "T": 5, "F": 6 +} + +code = Code("TEST") + +code.add(f3( + operand="A", + mnemonic="LDA", + label=None, + index=False, + adr_mode=AddrMode.SIMPLE +)) + +code.add(storage( + name="WORD", + value=5, + label="A" +)) + +code.pass1() +print("SYMTAB:", code.symtab) +print("START:", hex(code.start_address)) +print("LENGTH:", code.program_length) + +ctx = EmitContext(opcodes=OPCODES, symtab=code.symtab) +binary = code.pass2(ctx) + +print("BINARY:", binary.hex())