Projet-Systemes-Informatiques/cross-Compiler/cross-compiler.py
Raphaël LACROIX 5e4be22e3d big overhaul
2023-05-31 23:20:18 +02:00

182 lines
5.8 KiB
Python

import re
opToBinOP = {
"ADD": "01",
"MUL": "02",
"SUB": "03",
"DIV": "04",
"COP": "05",
"AFC": "06",
"LOAD": "07",
"STORE": "08",
"INF": "09",
"SUP": "0A",
"EQ": "0B",
"NOT": "0C",
"AND": "0D",
"OR": "0E",
"JMP": "0F",
"JMF": "10",
"CAL": "11",
"RET": "12",
"PRI": "13",
"NOP": "FF"
}
def output(s, num, oneline=False):
fileOutput = open(f'asm{num}', 'w')
if oneline:
fileOutput.write(s)
else :
fileOutput.write("\n".join(s))
fileOutput.close()
def convertToRegister(s):
l = []
if not re.match(r"\d_LABEL", s[0]):
optionalFlag = ""
incr = 0
op = s[0]
else:
optionalFlag = s[0] + " "
incr = 1
op = s[1]
match op:
case "ADD":
l.append(optionalFlag + "LOAD 0 " + s[2 + incr])
l.append("LOAD 1 " + s[3 + incr])
l.append("ADD 0 0 1")
l.append("STORE " + s[1 + incr] + " 0")
case "MUL":
l.append(optionalFlag + "LOAD 0 " + s[2 + incr])
l.append("LOAD 1 " + s[3 + incr])
l.append("MUL 0 0 1")
l.append("STORE " + s[1 + incr] + " 0")
case "SUB":
l.append(optionalFlag + "LOAD 0 " + s[2 + incr])
l.append("LOAD 1 " + s[3 + incr])
l.append("SUB 0 0 1")
l.append("STORE " + s[1 + incr] + " 0")
case "DIV_INT":
l.append(optionalFlag + "LOAD 0 " + s[2 + incr])
l.append("LOAD 1 " + s[3 + incr])
l.append("DIV 0 0 1")
l.append("STORE " + s[1 + incr] + " 0")
case "COP":
l.append(optionalFlag + "LOAD 0 " + s[2 + incr])
l.append("STORE " + s[1 + incr] + " 0")
case "AFC":
l.append(optionalFlag + "AFC 0 " + s[2 + incr])
l.append("STORE " + s[1 + incr] + " 0")
case "JMP":
l.append(" ".join(s))
case "JMF":
if len(s) == 3:
l.append(" ".join(s))
else :
l.append(s[0]+ " 0 " + s[1])
case "INF":
l.append(optionalFlag + "LOAD 0 " + s[2 + incr])
l.append("LOAD 1 " + s[3 + incr])
l.append("INF 2 0 1")
l.append("STORE " + s[1 + incr] + " 2")
case "SUP":
l.append(optionalFlag + "LOAD 0 " + s[2 + incr])
l.append("LOAD 1 " + s[3 + incr])
l.append("SUP 2 1 0")
l.append("STORE " + s[1 + incr] + " 2")
case "EQ":
l.append(optionalFlag + "LOAD 0 " + s[2 + incr])
l.append("LOAD 1 " + s[3 + incr])
l.append("EQ 2 1 0")
l.append("STORE " + s[1 + incr] + " 2")
case "PRI":
l.append(optionalFlag + "PRI " + s[2 + incr])
case "AND":
l.append(optionalFlag + "LOAD 0 " + s[2 + incr])
l.append("LOAD 1 " + s[3 + incr])
l.append("AND 2 0 1")
l.append("STORE " + s[1 + incr] + " 2")
case "OR":
l.append(optionalFlag + "LOAD 0 " + s[2 + incr])
l.append("LOAD 1 " + s[3 + incr])
l.append("OR 2 0 1")
l.append("STORE " + s[1 + incr] + " 2")
case "NOT":
l.append(optionalFlag + "LOAD 0 " + s[2 + incr])
l.append("NOT 2 0")
l.append("STORE " + s[1 + incr] + " 2")
case default:
l.append(" ".join(s))
""" R2 will contain the information whether to jump or not"""
return l
totalLine = 0
labelCount = 0 # used to create a new label each time
fileInput = open("asm", "r")
ASMLines = list(map(lambda e: e.rstrip("\n"), fileInput.readlines()))
fileInput.close()
# added to prevent problems when cross compiling some code representing a jump to after the last line
ASMLines.append("NOP")
ASMLinesLabel = ASMLines[:] # will contain at the end of the first loop the code with labels inserted
ASMLinesRegister = [] # will contain at the end of the 2nd loop the registry-based code with labels
ASMLinesFinal = [] # will contain the output, register-based, code
for i, l in enumerate(ASMLines):
items = l.split(" ")
if items[0] in ["JMP", "JMF"]:
lineToJumpTo = int(items[-1])
if re.match(r"\d_LABEL .*", ASMLinesLabel[lineToJumpTo]):
ASMLinesLabel[i] = " ".join(ASMLines[i].split()[:-1] + [ASMLinesLabel[lineToJumpTo].split()[0]])
else:
ASMLinesLabel[lineToJumpTo] = f"{labelCount}_LABEL " + ASMLines[lineToJumpTo]
ASMLinesLabel[i] = " ".join(ASMLinesLabel[i].split()[:-1] + [f"{labelCount}_LABEL"])
labelCount += 1
print("labels : ", ASMLinesLabel)
for i, l in enumerate(ASMLinesLabel):
ASMLinesRegister.extend(convertToRegister(l.split()))
print("regs : ", ASMLinesRegister)
labels = {}
for i, l in enumerate(ASMLinesRegister):
if re.match(r"\d_LABEL .*", l):
labels[l.split()[0]] = i
ASMLinesRegister[i] = " ".join(ASMLinesRegister[i].split()[1:])
print(ASMLinesRegister)
for i, l in enumerate(ASMLinesRegister):
label = re.match(r"\d_LABEL", l.split()[-1])
if label:
ASMLinesFinal.append(" ".join(l.split()[:-1] + [str(labels[label[0]])]))
else:
ASMLinesFinal.append(l)
print(ASMLinesFinal)
output(ASMLinesFinal, 2)
lines = []
for i, l in enumerate(ASMLinesFinal):
arr = l.split()
while len(arr) < 4:
arr.append(0)
lines.append(f"(x\"{opToBinOP[arr[0]]}{int(arr[1]):02X}{int(arr[2]):02X}{int(arr[3]):02X}\")")
ASMLinesConverted = "(" + ",".join(lines) + ",others => (x\"ff000000\"))"
print("converted to VHDL-friendly format : " + ASMLinesConverted)
output(ASMLinesConverted, 3, True)
""" Used to generate the beautiful table in the report
for i in range(10):
print(f"{ASMLines[i]} & {ASMLinesFinal[i]} & {ASMLinesConverted.split(',')[i]} \\\\")
"""