Dodal tabelo opcodeu, main, mal prilagodil strukturo
This commit is contained in:
parent
4b2a7a3cc2
commit
195ca3c9fa
13 changed files with 216 additions and 39 deletions
|
|
@ -1,6 +1,10 @@
|
||||||
class EmitContext:
|
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.opcodes = opcodes
|
||||||
self.registers = registers
|
|
||||||
self.symtab = symtab
|
self.symtab = symtab
|
||||||
self.base = None
|
self.base = None
|
||||||
|
|
|
||||||
Binary file not shown.
BIN
ass3/zbirnik/src/zbirnik/__pycache__/code.cpython-310.pyc
Normal file
BIN
ass3/zbirnik/src/zbirnik/__pycache__/code.cpython-310.pyc
Normal file
Binary file not shown.
|
|
@ -2,17 +2,14 @@ from zbirnik.ukazi.node import Node
|
||||||
|
|
||||||
class Code:
|
class Code:
|
||||||
|
|
||||||
REGISTERS = {'A': 0, 'X': 1, 'L': 2, 'B': 3, 'S': 4, 'T': 5, 'F': 6 }
|
|
||||||
|
|
||||||
def __init__(self, name: str | None = None):
|
def __init__(self, name: str | None = None):
|
||||||
self.name = name
|
self.name = name
|
||||||
self.nodes = []
|
self.nodes = []
|
||||||
self.locctr = 0
|
self.locctr = 0
|
||||||
self.symtab = {}
|
self.symtab = {}
|
||||||
self.start_adress = 0
|
self.start_address = 0
|
||||||
self.entry_point = 0
|
self.entry_point = None
|
||||||
self.program_length = 0
|
self.program_length = 0
|
||||||
self.obj = ""
|
|
||||||
|
|
||||||
def add(self, node: Node):
|
def add(self, node: Node):
|
||||||
self.nodes.append(node)
|
self.nodes.append(node)
|
||||||
|
|
|
||||||
32
ass3/zbirnik/src/zbirnik/main.py
Normal file
32
ass3/zbirnik/src/zbirnik/main.py
Normal file
|
|
@ -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())
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
from mnemoniki import (
|
from zbirnik.mnemoniki import (
|
||||||
mnemonicD, mnemonicDn,
|
mnemonicD, mnemonicDn,
|
||||||
mnemonicF1, mnemonicF2n, mnemonicF2r, mnemonicF2rn, mnemonicF2rr,
|
mnemonicF1, mnemonicF2n, mnemonicF2r, mnemonicF2rn, mnemonicF2rr,
|
||||||
mnemonicF3, mnemonicF3m, mnemonicF4m,
|
mnemonicF3, mnemonicF3m, mnemonicF4m,
|
||||||
|
|
|
||||||
61
ass3/zbirnik/src/zbirnik/opcodes.py
Normal file
61
ass3/zbirnik/src/zbirnik/opcodes.py
Normal file
|
|
@ -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,
|
||||||
|
}
|
||||||
|
|
@ -1,8 +1,10 @@
|
||||||
import ply.lex
|
import ply.lex
|
||||||
import ply.yacc
|
import ply.yacc
|
||||||
import sys
|
from zbirnik.parserctx import ParserContext
|
||||||
|
|
||||||
# Lexer.
|
# --------------------
|
||||||
|
# Lexer
|
||||||
|
# --------------------
|
||||||
tokens = (
|
tokens = (
|
||||||
'AT',
|
'AT',
|
||||||
'COMMA',
|
'COMMA',
|
||||||
|
|
@ -36,54 +38,85 @@ def t_COMMENT(t):
|
||||||
t_ignore = ' \t\n'
|
t_ignore = ' \t\n'
|
||||||
|
|
||||||
def t_error(t):
|
def t_error(t):
|
||||||
print(f'illegal character {t}')
|
print(f"Illegal character {t.value[0]!r}")
|
||||||
t.lexer.skip(1)
|
t.lexer.skip(1)
|
||||||
|
|
||||||
lexer = ply.lex.lex()
|
lexer = ply.lex.lex()
|
||||||
|
|
||||||
# Parser.
|
# --------------------
|
||||||
|
# Parser
|
||||||
|
# --------------------
|
||||||
|
|
||||||
def p_start(p):
|
def p_start(p):
|
||||||
r'''start : LABEL command
|
r'''start : LABEL command
|
||||||
|
| command
|
||||||
| COMMENT
|
| COMMENT
|
||||||
| command'''
|
'''
|
||||||
|
# komentar
|
||||||
|
if len(p) == 2 and isinstance(p[1], str):
|
||||||
|
p[0] = None
|
||||||
|
return
|
||||||
|
|
||||||
|
# brez labela
|
||||||
if len(p) == 2:
|
if len(p) == 2:
|
||||||
if isinstance(p[1], str):
|
label = None
|
||||||
p[0] = ('COMMENT', p[1])
|
mnemonic, operands = p[1]
|
||||||
else:
|
else:
|
||||||
p[0] = (None, p[1])
|
label = p[1]
|
||||||
else:
|
mnemonic, operands = p[2]
|
||||||
p[0] = tuple(p[1:])
|
|
||||||
|
p[0] = ParserContext(label, mnemonic, operands)
|
||||||
|
|
||||||
|
|
||||||
def p_command(p):
|
def p_command(p):
|
||||||
r'''command : MNEMONIC
|
r'''command : MNEMONIC
|
||||||
| MNEMONIC args'''
|
| MNEMONIC args
|
||||||
p[0] = p[1:]
|
'''
|
||||||
|
if len(p) == 2:
|
||||||
|
p[0] = (p[1], [])
|
||||||
|
else:
|
||||||
|
p[0] = (p[1], list(p[2]))
|
||||||
|
|
||||||
|
|
||||||
def p_args(p):
|
def p_args(p):
|
||||||
r'''args : operand
|
r'''args : operand
|
||||||
| operand COMMA operand'''
|
| operand COMMA operand
|
||||||
match len(p):
|
'''
|
||||||
case 2: p[0] = (p[1],)
|
if len(p) == 2:
|
||||||
case 4: p[0] = (p[1], p[3])
|
p[0] = [p[1]]
|
||||||
|
else:
|
||||||
|
p[0] = [p[1], p[3]]
|
||||||
|
|
||||||
|
|
||||||
def p_operand(p):
|
def p_operand(p):
|
||||||
r'''operand : REGISTER
|
r'''operand : REGISTER
|
||||||
| AT address
|
| AT address
|
||||||
| HASH address
|
| HASH address
|
||||||
| address'''
|
| address
|
||||||
p[0] = p[1:]
|
'''
|
||||||
|
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):
|
def p_address(p):
|
||||||
r'''address : NUMBER
|
r'''address : NUMBER
|
||||||
| SYMBOL'''
|
| SYMBOL
|
||||||
|
'''
|
||||||
p[0] = p[1]
|
p[0] = p[1]
|
||||||
|
|
||||||
|
|
||||||
def p_error(p):
|
def p_error(p):
|
||||||
if p:
|
if p:
|
||||||
print('Syntax error at token', p)
|
raise SyntaxError(f"Syntax error at token {p}")
|
||||||
parser.errok()
|
|
||||||
else:
|
else:
|
||||||
print('Syntax error at EOF')
|
raise SyntaxError("Syntax error at EOF")
|
||||||
|
|
||||||
|
|
||||||
|
parser = ply.yacc.yacc()
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
import sys
|
import sys
|
||||||
|
|
|
||||||
Binary file not shown.
|
|
@ -14,14 +14,14 @@ class f2(Node):
|
||||||
opcode = ctx.opcodes[self.mnemonic]
|
opcode = ctx.opcodes[self.mnemonic]
|
||||||
|
|
||||||
if isinstance(self.r1, str):
|
if isinstance(self.r1, str):
|
||||||
r1_val = ctx.registers[self.r1]
|
r1_val = ctx.REGISTERS[self.r1]
|
||||||
else:
|
else:
|
||||||
r1_val = self.r1
|
r1_val = self.r1
|
||||||
|
|
||||||
if self.r2 is None:
|
if self.r2 is None:
|
||||||
r2_val = 0
|
r2_val = 0
|
||||||
elif isinstance(self.r2, str):
|
elif isinstance(self.r2, str):
|
||||||
r2_val = ctx.registers[self.r2]
|
r2_val = ctx.REGISTERS[self.r2]
|
||||||
else:
|
else:
|
||||||
r2_val = self.r2
|
r2_val = self.r2
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,23 @@
|
||||||
from zbirnik.ukazi.node import Node
|
from zbirnik.ukazi.node import Node
|
||||||
|
|
||||||
class storage(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)
|
super().__init__(label)
|
||||||
self.val = val
|
self.value = value
|
||||||
self.name = name
|
self.name = name
|
||||||
|
|
||||||
def size(self) -> int:
|
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
|
return 0
|
||||||
|
|
||||||
|
|
||||||
def emit(self, ctx):
|
def emit(self, ctx):
|
||||||
if self.name == "WORD":
|
if self.name == "WORD":
|
||||||
if isinstance(self.value, str):
|
if isinstance(self.value, str):
|
||||||
|
|
|
||||||
41
ass3/zbirnik/tests/test_passes.py
Normal file
41
ass3/zbirnik/tests/test_passes.py
Normal file
|
|
@ -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())
|
||||||
Loading…
Add table
Add a link
Reference in a new issue