203 lines
5.8 KiB
Python
203 lines
5.8 KiB
Python
"""Core pragmas
|
|
|
|
Provides the core assembler directives. It does not guarantee
|
|
compatibility with older versions of P65-Perl."""
|
|
|
|
# Copyright 2002 Michael C. Martin.
|
|
# You may use, modify, and distribute this file under the BSD
|
|
# license: See LICENSE.txt for details.
|
|
|
|
from __future__ import nested_scopes
|
|
|
|
import Ophis.IR as IR
|
|
import Ophis.Frontend as FE
|
|
import Ophis.Errors as Err
|
|
|
|
loadedfiles={}
|
|
basecharmap = "".join([chr(x) for x in range(256)])
|
|
currentcharmap = basecharmap
|
|
|
|
def reset():
|
|
global loadedfiles, currentcharmap, basecharmap
|
|
loadedfiles={}
|
|
currentcharmap = basecharmap
|
|
|
|
def pragmaInclude(ppt, line, result):
|
|
"Includes a source file"
|
|
filename = line.expect("STRING").value
|
|
line.expect("EOL")
|
|
if type(filename)==str: result.append(FE.parse_file(ppt, filename))
|
|
|
|
def pragmaRequire(ppt, line, result):
|
|
"Includes a source file at most one time"
|
|
filename = line.expect("STRING").value
|
|
line.expect("EOL")
|
|
if type(filename)==str:
|
|
global loadedfiles
|
|
if filename not in loadedfiles:
|
|
loadedfiles[filename]=1
|
|
result.append(FE.parse_file(ppt, filename))
|
|
|
|
def pragmaIncbin(ppt, line, result):
|
|
"Includes a binary file"
|
|
filename = line.expect("STRING").value
|
|
line.expect("EOL")
|
|
if type(filename)==str:
|
|
f = file(filename, "rb")
|
|
bytes = f.read()
|
|
f.close()
|
|
bytes = [IR.ConstantExpr(ord(x)) for x in bytes]
|
|
result.append(IR.Node(ppt, "Byte", *bytes))
|
|
|
|
def pragmaCharmap(ppt, line, result):
|
|
"Modify the character map."
|
|
global currentcharmap, basecharmap
|
|
bytes = readData(line)
|
|
if len(bytes) == 0:
|
|
currentcharmap = basecharmap
|
|
else:
|
|
try:
|
|
base = bytes[0].data
|
|
newsubstr = "".join([chr(x.data) for x in bytes[1:]])
|
|
currentcharmap = currentcharmap[:base] + newsubstr + currentcharmap[base+len(newsubstr):]
|
|
if len(currentcharmap) != 256 or base < 0 or base > 255:
|
|
Err.log("Charmap replacement out of range")
|
|
currentcharmap = currentcharmap[:256]
|
|
except ValueError:
|
|
Err.log("Illegal character in .charmap directive")
|
|
|
|
def pragmaCharmapbin(ppt, line, result):
|
|
"Load a new character map from a file"
|
|
global currentcharmap
|
|
filename = line.expect("STRING").value
|
|
line.expect("EOL")
|
|
if type(filename)==str:
|
|
f = file(filename, "rb")
|
|
bytes = f.read()
|
|
f.close()
|
|
if len(bytes)==256:
|
|
currentcharmap = bytes
|
|
else:
|
|
Err.log("Character map "+filename+" not 256 bytes long")
|
|
|
|
def pragmaOrg(ppt, line, result):
|
|
"Relocates the PC with no output"
|
|
newPC = FE.parse_expr(line)
|
|
line.expect("EOL")
|
|
result.append(IR.Node(ppt, "SetPC", newPC))
|
|
|
|
def pragmaAdvance(ppt, line, result):
|
|
"Outputs filler until reaching the target PC"
|
|
newPC = FE.parse_expr(line)
|
|
line.expect("EOL")
|
|
result.append(IR.Node(ppt, "Advance", newPC))
|
|
|
|
def pragmaCheckpc(ppt, line, result):
|
|
"Enforces that the PC has not exceeded a certain point"
|
|
target = FE.parse_expr(line)
|
|
line.expect("EOL")
|
|
result.append(IR.Node(ppt, "CheckPC", target))
|
|
|
|
def pragmaAlias(ppt, line, result):
|
|
"Assigns an arbitrary label"
|
|
lbl = line.expect("LABEL").value
|
|
target = FE.parse_expr(line)
|
|
result.append(IR.Node(ppt, "Label", lbl, target))
|
|
|
|
def pragmaSpace(ppt, line, result):
|
|
"Reserves space in a data segment for a variable"
|
|
lbl = line.expect("LABEL").value
|
|
size = line.expect("NUM").value
|
|
line.expect("EOL")
|
|
result.append(IR.Node(ppt, "Label", lbl, IR.PCExpr()))
|
|
result.append(IR.Node(ppt, "SetPC", IR.SequenceExpr([IR.PCExpr(), "+", IR.ConstantExpr(size)])))
|
|
|
|
def pragmaText(ppt, line, result):
|
|
"Switches to a text segment"
|
|
next = line.expect("LABEL", "EOL")
|
|
if next.type == "LABEL":
|
|
line.expect("EOL")
|
|
segment = next.value
|
|
else:
|
|
segment = "*text-default*"
|
|
result.append(IR.Node(ppt, "TextSegment", segment))
|
|
|
|
def pragmaData(ppt, line, result):
|
|
"Switches to a data segment (no output allowed)"
|
|
next = line.expect("LABEL", "EOL")
|
|
if next.type == "LABEL":
|
|
line.expect("EOL")
|
|
segment = next.value
|
|
else:
|
|
segment = "*data-default*"
|
|
result.append(IR.Node(ppt, "DataSegment", segment))
|
|
|
|
def readData(line):
|
|
"Read raw data from a comma-separated list"
|
|
if line.lookahead(0).type == "STRING":
|
|
data = [IR.ConstantExpr(ord(x)) for x in line.expect("STRING").value.translate(currentcharmap)]
|
|
else:
|
|
data = [FE.parse_expr(line)]
|
|
next = line.expect(',', 'EOL').type
|
|
while next == ',':
|
|
if line.lookahead(0).type == "STRING":
|
|
data.extend([IR.ConstantExpr(ord(x)) for x in line.expect("STRING").value])
|
|
else:
|
|
data.append(FE.parse_expr(line))
|
|
next = line.expect(',', 'EOL').type
|
|
return data
|
|
|
|
def pragmaByte(ppt, line, result):
|
|
"Raw data, a byte at a time"
|
|
bytes = readData(line)
|
|
result.append(IR.Node(ppt, "Byte", *bytes))
|
|
|
|
def pragmaWord(ppt, line, result):
|
|
"Raw data, a word at a time, little-endian"
|
|
words = readData(line)
|
|
result.append(IR.Node(ppt, "Word", *words))
|
|
|
|
def pragmaDword(ppt, line, result):
|
|
"Raw data, a double-word at a time, little-endian"
|
|
dwords = readData(line)
|
|
result.append(IR.Node(ppt, "Dword", *dwords))
|
|
|
|
def pragmaWordbe(ppt, line, result):
|
|
"Raw data, a word at a time, big-endian"
|
|
words = readData(line)
|
|
result.append(IR.Node(ppt, "WordBE", *words))
|
|
|
|
def pragmaDwordbe(ppt, line, result):
|
|
"Raw data, a dword at a time, big-endian"
|
|
dwords = readData(line)
|
|
result.append(IR.Node(ppt, "DwordBE", *dwords))
|
|
|
|
def pragmaScope(ppt, line, result):
|
|
"Create a new lexical scoping block"
|
|
line.expect("EOL")
|
|
result.append(IR.Node(ppt, "ScopeBegin"))
|
|
|
|
def pragmaScend(ppt, line, result):
|
|
"End the innermost lexical scoping block"
|
|
line.expect("EOL")
|
|
result.append(IR.Node(ppt, "ScopeEnd"))
|
|
|
|
def pragmaMacro(ppt, line, result):
|
|
"Begin a macro definition"
|
|
lbl = line.expect("LABEL").value
|
|
line.expect("EOL")
|
|
result.append(IR.Node(ppt, "MacroBegin", lbl))
|
|
|
|
def pragmaMacend(ppt, line, result):
|
|
"End a macro definition"
|
|
line.expect("EOL")
|
|
result.append(IR.Node(ppt, "MacroEnd"))
|
|
|
|
def pragmaInvoke(ppt, line, result):
|
|
macro = line.expect("LABEL").value
|
|
if line.lookahead(0).type == "EOL":
|
|
args = []
|
|
else:
|
|
args = readData(line)
|
|
result.append(IR.Node(ppt, "MacroInvoke", macro, *args))
|