Line 1... |
Line 1... |
################################################################################
|
################################################################################
|
#
|
#
|
# Copyright 2012, Sinclair R.F., Inc.
|
# Copyright 2012-2014, Sinclair R.F., Inc.
|
#
|
#
|
# Assembly language definitions for SSBCC 9x8.
|
# Assembly language definitions for SSBCC 9x8.
|
#
|
#
|
################################################################################
|
################################################################################
|
|
|
import copy
|
import copy
|
|
import os
|
|
import re
|
import string
|
import string
|
|
import sys
|
|
import types
|
|
|
import asmDef
|
import asmDef
|
|
|
class asmDef_9x8:
|
class asmDef_9x8:
|
"""
|
"""
|
Line 112... |
Line 116... |
nRequired = nRequired + 1;
|
nRequired = nRequired + 1;
|
if nRequired < len(args)-1:
|
if nRequired < len(args)-1:
|
raise Exception('Program Bug -- Only the last macro argument can be optional');
|
raise Exception('Program Bug -- Only the last macro argument can be optional');
|
self.macros['nArgs'].append(range(nRequired,len(args)+1));
|
self.macros['nArgs'].append(range(nRequired,len(args)+1));
|
|
|
|
def AddMacroSearchPath(self,path):
|
|
self.macroSearchPaths.append(path);
|
|
|
|
def AddUserMacro(self,macroName,macroSearchPaths=None):
|
|
"""
|
|
Add a user-defined macro by processing the associated Python script.
|
|
macroName name of the macro
|
|
The associated Python script must be named
|
|
<macroName>.py and must be in the project directory, an
|
|
included directory, or must be one of the macros
|
|
provided in "macros" subdirectory of this directory.
|
|
"""
|
|
if not macroSearchPaths:
|
|
macroSearchPaths = self.macroSearchPaths;
|
|
for testPath in macroSearchPaths:
|
|
fullMacro = os.path.join(testPath,'%s.py' % macroName);
|
|
if os.path.isfile(fullMacro):
|
|
break;
|
|
else:
|
|
raise asmDef.AsmException('Definition for macro "%s" not found' % macroName);
|
|
execfile(fullMacro);
|
|
exec('%s(self)' % macroName);
|
|
|
|
def IsBuiltInMacro(self,name):
|
|
"""
|
|
Indicate if the macro is built-in to the assembler or is taken from the
|
|
./macros directory.
|
|
"""
|
|
return name in self.macros['builtIn'];
|
|
|
def IsMacro(self,name):
|
def IsMacro(self,name):
|
"""
|
"""
|
Indicate whether or not the string "name" is a recognized macro.
|
Indicate whether or not the string "name" is a recognized macro.
|
"""
|
"""
|
return name in self.macros['list'];
|
return name in self.macros['list'];
|
Line 148... |
Line 182... |
return self.macros['args'][ix][ixArg][0];
|
return self.macros['args'][ix][ixArg][0];
|
|
|
def MacroLength(self,token):
|
def MacroLength(self,token):
|
"""
|
"""
|
Return the length of fixed-length macros or compute and return the length
|
Return the length of fixed-length macros or compute and return the length
|
of variable-length macros.\n
|
of variable-length macros.
|
Note: The only variable length macros recognized are fetchvector and
|
|
storevector.
|
|
"""
|
"""
|
if token['value'] not in self.macros['list']:
|
if token['value'] not in self.macros['list']:
|
raise Exception('Program Bug -- name "%s" is not a macro' % token['value']);
|
raise Exception('Program Bug -- name "%s" is not a macro' % token['value']);
|
ix = self.macros['list'].index(token['value']);
|
ix = self.macros['list'].index(token['value']);
|
length = self.macros['length'][ix];
|
length = self.macros['length'][ix];
|
if length >= 0:
|
if type(length) == int:
|
return length;
|
return length;
|
if token['value'] == '.fetchvector':
|
elif type(length) == types.FunctionType:
|
return int(token['argument'][1]['value']) + 1;
|
return length(self,token['argument']);
|
if token['value'] == '.storevector':
|
else:
|
return int(token['argument'][1]['value']) + 2;
|
|
raise Exception('Program Bug -- Unrecognized variable length macro "%s"' % token['value']);
|
raise Exception('Program Bug -- Unrecognized variable length macro "%s"' % token['value']);
|
|
|
def MacroNumberArgs(self,name):
|
def MacroNumberArgs(self,name):
|
"""
|
"""
|
Return the range of the number of allowed arguments to the named macro.
|
Return the range of the number of allowed arguments to the named macro.
|
Line 350... |
Line 381... |
if firstToken['type'] != 'directive':
|
if firstToken['type'] != 'directive':
|
raise Exception('Program Bug triggered at %s' % firstToken['loc']);
|
raise Exception('Program Bug triggered at %s' % firstToken['loc']);
|
# Ensure the directive bodies are not too short.
|
# Ensure the directive bodies are not too short.
|
if (firstToken['value'] in ('.main','.interrupt',)) and not (len(rawTokens) > 1):
|
if (firstToken['value'] in ('.main','.interrupt',)) and not (len(rawTokens) > 1):
|
raise asmDef.AsmException('"%s" missing body at %s' % (firstToken['value'],firstToken['loc'],));
|
raise asmDef.AsmException('"%s" missing body at %s' % (firstToken['value'],firstToken['loc'],));
|
|
if (firstToken['value'] in ('.macro',)) and not (len(rawTokens) == 2):
|
|
raise asmDef.AsmException('body for "%s" directive must have exactly one argument at %s' % (firstToken['value'],firstToken['loc'],));
|
if (firstToken['value'] in ('.constant','.function','.memory','.variable',)) and not (len(rawTokens) >= 3):
|
if (firstToken['value'] in ('.constant','.function','.memory','.variable',)) and not (len(rawTokens) >= 3):
|
raise asmDef.AsmException('body for "%s" directive too short at %s' % (firstToken['value'],firstToken['loc'],));
|
raise asmDef.AsmException('body for "%s" directive too short at %s' % (firstToken['value'],firstToken['loc'],));
|
# Ensure the main body ends in a ".jump".
|
# Ensure the main body ends in a ".jump".
|
lastToken = rawTokens[-1];
|
lastToken = rawTokens[-1];
|
if firstToken['value'] == '.main':
|
if firstToken['value'] == '.main':
|
Line 387... |
Line 420... |
raise asmDef.AsmException('label definition for target missing at %s' % token['loc']);
|
raise asmDef.AsmException('label definition for target missing at %s' % token['loc']);
|
labelsUsed.append(target);
|
labelsUsed.append(target);
|
labelsUnused = set(labelDefs) - set(labelsUsed);
|
labelsUnused = set(labelDefs) - set(labelsUsed);
|
if labelsUnused:
|
if labelsUnused:
|
raise asmDef.AsmException('Unused label(s) %s in body %s' % (labelsUnused,firstToken['loc']));
|
raise asmDef.AsmException('Unused label(s) %s in body %s' % (labelsUnused,firstToken['loc']));
|
# Ensure symbols referenced by ".input", ".outport", and ".outstrobe" are defined.
|
|
for token in rawTokens:
|
|
if (token['type'] == 'macro') and (token['value'] == '.inport'):
|
|
if not self.IsInport(token['argument'][0]['value']):
|
|
raise asmDef.AsmException('Symbol "%s is not an input port at %s' % (token['argument'][0]['value'],token['loc']));
|
|
if (token['type'] == 'macro') and (token['value'] == '.outport'):
|
|
if not self.IsOutport(token['argument'][0]['value']):
|
|
raise asmDef.AsmException('Symbol "%s" is either not an output port or is a strobe-only outport at %s' % (token['argument'][0]['value'],token['loc']));
|
|
if (token['type'] == 'macro') and (token['value'] == '.outstrobe'):
|
|
if not self.IsOutstrobe(token['argument'][0]['value']):
|
|
raise asmDef.AsmException('Symbol "%s" is not a strobe-only output port at %s' % (token['argument'][0]['value'],token['loc']));
|
|
# Ensure referenced symbols are already defined (other than labels and
|
# Ensure referenced symbols are already defined (other than labels and
|
# function names for call and jump macros).
|
# function names for call and jump macros).
|
checkBody = False;
|
checkBody = False;
|
if (rawTokens[0]['type'] == 'directive') and (rawTokens[0]['value'] in ('.function','.interrupt','.main',)):
|
if (rawTokens[0]['type'] == 'directive') and (rawTokens[0]['value'] in ('.function','.interrupt','.main',)):
|
checkBody = True;
|
checkBody = True;
|
Line 553... |
Line 575... |
Do one of the following as required for the specified directive:
|
Do one of the following as required for the specified directive:
|
.constant add the constant and its body to the list of symbols
|
.constant add the constant and its body to the list of symbols
|
.function add the function and its body, along with the relative
|
.function add the function and its body, along with the relative
|
addresses, to the list of symbols
|
addresses, to the list of symbols
|
.interrupt record the function body and relative addresses
|
.interrupt record the function body and relative addresses
|
|
.macro register the user-defined macro
|
.main record the function body and relative addresses
|
.main record the function body and relative addresses
|
.memory record the definition of the memory and make it current
|
.memory record the definition of the memory and make it current
|
for subsequent variable definitions.
|
for subsequent variable definitions.
|
.variable add the variable and its associated memory, length, and
|
.variable add the variable and its associated memory, length, and
|
initial values to the list of symbols
|
initial values to the list of symbols
|
Line 579... |
Line 602... |
# Process ".interrupt" definition.
|
# Process ".interrupt" definition.
|
elif firstToken['value'] == '.interrupt':
|
elif firstToken['value'] == '.interrupt':
|
if self.interrupt:
|
if self.interrupt:
|
raise asmDef.AsmException('Second definition of ".interrupt" at %s' % firstToken['loc']);
|
raise asmDef.AsmException('Second definition of ".interrupt" at %s' % firstToken['loc']);
|
self.interrupt = self.ExpandTokens(rawTokens[1:]);
|
self.interrupt = self.ExpandTokens(rawTokens[1:]);
|
|
# Process user-defined macros (the ".macro XXX" directive can be repeated for non-built-in macros).
|
|
elif firstToken['value'] == '.macro':
|
|
macroName = secondToken['value'];
|
|
fullMacroName = '.' + macroName;
|
|
if fullMacroName in self.directives:
|
|
raise asmDef.AsmException('Macro "%s" is a directive at %s' % (fullMacroName,secondToken['loc'],));
|
|
if fullMacroName in self.instructions:
|
|
raise asmDef.AsmException('Macro "%s" is an instruction at %s' % (fullMacroName,secondToken['loc'],));
|
|
if self.IsBuiltInMacro(fullMacroName):
|
|
raise asmDef.AsmException('Macro "%s" is a built-in macro at %s' % (fullMacroName,secondToken['loc'],));
|
|
if fullMacroName not in self.macros['list']:
|
|
self.AddUserMacro(macroName);
|
# Process ".main" definition.
|
# Process ".main" definition.
|
elif firstToken['value'] == '.main':
|
elif firstToken['value'] == '.main':
|
if self.main:
|
if self.main:
|
raise asmDef.AsmException('Second definition of ".main" at %s' % firstToken['loc']);
|
raise asmDef.AsmException('Second definition of ".main" at %s' % firstToken['loc']);
|
self.main = self.ExpandTokens(rawTokens[1:]);
|
self.main = self.ExpandTokens(rawTokens[1:]);
|
Line 832... |
Line 867... |
def Emit_GetAddrAndBank(self,name):
|
def Emit_GetAddrAndBank(self,name):
|
"""
|
"""
|
For the specified variable, return an ordered tuple of the memory address
|
For the specified variable, return an ordered tuple of the memory address
|
within its bank, the corresponding bank index, and the corresponding bank
|
within its bank, the corresponding bank index, and the corresponding bank
|
name.\n
|
name.\n
|
Note: This is used for the .fetchvector and .storevector macro generation.
|
Note: This is used by several user-defined macros that fetch from or store
|
|
to variables.
|
"""
|
"""
|
if not self.IsSymbol(name):
|
if not self.IsSymbol(name):
|
raise asmDef.AsmException('"%s" is not a recognized symbol' % name);
|
raise asmDef.AsmException('"%s" is not a recognized symbol' % name);
|
ixName = self.symbols['list'].index(name);
|
ixName = self.symbols['list'].index(name);
|
if self.symbols['type'][ixName] != 'variable':
|
if self.symbols['type'][ixName] != 'variable':
|
Line 847... |
Line 883... |
return (body['start'],self.memories['bank'][ixMem],bankName,);
|
return (body['start'],self.memories['bank'][ixMem],bankName,);
|
|
|
def Emit_GetBank(self,name):
|
def Emit_GetBank(self,name):
|
"""
|
"""
|
For the specified variable, return the memory bank index.\n
|
For the specified variable, return the memory bank index.\n
|
Note: This is used for the .fetch, .fetch+, .fetch-, .store, .store+, and
|
Note: This is used by the .fetch, .fetch+, .fetch-, .store, .store+, and
|
.store- macros.
|
.store- macros.
|
"""
|
"""
|
if name not in self.memories['list']:
|
if name not in self.memories['list']:
|
raise asmDef.AsmException('"%s" not a memory' % name);
|
raise asmDef.AsmException('"%s" not a memory' % name);
|
ixMem = self.memories['list'].index(name);
|
ixMem = self.memories['list'].index(name);
|
Line 981... |
Line 1017... |
else:
|
else:
|
raise asmDef.AsmException('Unrecognized optional argument "%s"' % token['value']);
|
raise asmDef.AsmException('Unrecognized optional argument "%s"' % token['value']);
|
|
|
def EmitMacro(self,fp,token):
|
def EmitMacro(self,fp,token):
|
"""
|
"""
|
Write the metacode for a macro.
|
Write the metacode for a macro.\n
|
|
The macros coded here are required to access intrinsics.
|
"""
|
"""
|
# .call
|
# .call
|
if token['value'] == '.call':
|
if token['value'] == '.call':
|
self.EmitPush(fp,token['address'] & 0xFF,'');
|
self.EmitPush(fp,token['address'] & 0xFF,'');
|
self.EmitOpcode(fp,self.specialInstructions['call'] | (token['address'] >> 8),'call '+token['argument'][0]['value']);
|
self.EmitOpcode(fp,self.specialInstructions['call'] | (token['address'] >> 8),'call '+token['argument'][0]['value']);
|
Line 1008... |
Line 1045... |
# .fetch-
|
# .fetch-
|
elif token['value'] == '.fetch-':
|
elif token['value'] == '.fetch-':
|
name = token['argument'][0]['value'];
|
name = token['argument'][0]['value'];
|
ixBank = self.Emit_GetBank(name);
|
ixBank = self.Emit_GetBank(name);
|
self.EmitOpcode(fp,self.specialInstructions['fetch-'] | ixBank,'fetch-('+name+')');
|
self.EmitOpcode(fp,self.specialInstructions['fetch-'] | ixBank,'fetch-('+name+')');
|
# .fetchindexed
|
|
elif token['value'] == '.fetchindexed':
|
|
name = token['argument'][0]['value'];
|
|
(addr,ixBank,bankName) = self.Emit_GetAddrAndBank(name);
|
|
self.EmitPush(fp,addr,self.Emit_String(name),token['loc']);
|
|
self.EmitOpcode(fp,self.InstructionOpcode('+'),'+');
|
|
self.EmitOpcode(fp,self.specialInstructions['fetch'] | ixBank,'fetch '+bankName);
|
|
# .fetchoffset
|
|
elif token['value'] == '.fetchoffset':
|
|
name = token['argument'][0]['value'];
|
|
(addr,ixBank,bankName) = self.Emit_GetAddrAndBank(name);
|
|
offset = self.Emit_EvalSingleValue(token['argument'][1]);
|
|
self.EmitPush(fp,addr+offset,self.Emit_String('%s+%s' % (name,offset,)),token['loc']);
|
|
self.EmitOpcode(fp,self.specialInstructions['fetch'] | ixBank,'fetch '+bankName);
|
|
# .fetchvalue
|
|
elif token['value'] == '.fetchvalue':
|
|
name = token['argument'][0]['value'];
|
|
(addr,ixBank,bankName) = self.Emit_GetAddrAndBank(name);
|
|
self.EmitPush(fp,addr,self.Emit_String(name),token['loc']);
|
|
self.EmitOpcode(fp,self.specialInstructions['fetch'] | ixBank,'fetch '+bankName);
|
|
# .fetchvector
|
|
elif token['value'] == '.fetchvector':
|
|
name = token['argument'][0]['value'];
|
|
(addr,ixBank,bankName) = self.Emit_GetAddrAndBank(name);
|
|
N = int(token['argument'][1]['value']);
|
|
self.EmitPush(fp,addr+N-1,'%s+%d' % (name,N-1));
|
|
for dummy in range(N-1):
|
|
self.EmitOpcode(fp,self.specialInstructions['fetch-'] | ixBank,'fetch- '+bankName);
|
|
self.EmitOpcode(fp,self.specialInstructions['fetch'] | ixBank,'fetch '+bankName);
|
|
# .inport
|
|
elif token['value'] == '.inport':
|
|
name = token['argument'][0]['value'];
|
|
self.EmitPush(fp,self.InportAddress(name) & 0xFF,name);
|
|
self.EmitOpcode(fp,self.InstructionOpcode('inport'),'inport');
|
|
# .jump
|
# .jump
|
elif token['value'] == '.jump':
|
elif token['value'] == '.jump':
|
self.EmitPush(fp,token['address'] & 0xFF,'');
|
self.EmitPush(fp,token['address'] & 0xFF,'');
|
self.EmitOpcode(fp,self.specialInstructions['jump'] | (token['address'] >> 8),'jump '+token['argument'][0]['value']);
|
self.EmitOpcode(fp,self.specialInstructions['jump'] | (token['address'] >> 8),'jump '+token['argument'][0]['value']);
|
self.EmitOptArg(fp,token['argument'][1]);
|
self.EmitOptArg(fp,token['argument'][1]);
|
# .jumpc
|
# .jumpc
|
elif token['value'] == '.jumpc':
|
elif token['value'] == '.jumpc':
|
self.EmitPush(fp,token['address'] & 0xFF,'');
|
self.EmitPush(fp,token['address'] & 0xFF,'');
|
self.EmitOpcode(fp,self.specialInstructions['jumpc'] | (token['address'] >> 8),'jumpc '+token['argument'][0]['value']);
|
self.EmitOpcode(fp,self.specialInstructions['jumpc'] | (token['address'] >> 8),'jumpc '+token['argument'][0]['value']);
|
self.EmitOptArg(fp,token['argument'][1]);
|
self.EmitOptArg(fp,token['argument'][1]);
|
# .outport
|
|
elif token['value'] == '.outport':
|
|
name = token['argument'][0]['value'];
|
|
self.EmitPush(fp,self.OutportAddress(name) & 0xFF,name);
|
|
self.EmitOpcode(fp,self.InstructionOpcode('outport'),'outport');
|
|
self.EmitOptArg(fp,token['argument'][1]);
|
|
# .outstrobe
|
|
elif token['value'] == '.outstrobe':
|
|
name = token['argument'][0]['value'];
|
|
self.EmitPush(fp,self.OutportAddress(name) & 0xFF,name);
|
|
self.EmitOpcode(fp,self.InstructionOpcode('outport'),'outport');
|
|
# .return
|
# .return
|
elif token['value'] == '.return':
|
elif token['value'] == '.return':
|
self.EmitOpcode(fp,self.specialInstructions['return'],'return');
|
self.EmitOpcode(fp,self.specialInstructions['return'],'return');
|
self.EmitOptArg(fp,token['argument'][0]);
|
self.EmitOptArg(fp,token['argument'][0]);
|
# .store
|
# .store
|
Line 1082... |
Line 1074... |
# .store-
|
# .store-
|
elif token['value'] == '.store-':
|
elif token['value'] == '.store-':
|
name = token['argument'][0]['value'];
|
name = token['argument'][0]['value'];
|
ixBank = self.Emit_GetBank(name);
|
ixBank = self.Emit_GetBank(name);
|
self.EmitOpcode(fp,self.specialInstructions['store-'] | ixBank,'store- '+name);
|
self.EmitOpcode(fp,self.specialInstructions['store-'] | ixBank,'store- '+name);
|
# .storeindexed
|
# user-defined macro
|
elif token['value'] == '.storeindexed':
|
elif token['value'] in self.EmitFunction:
|
name = token['argument'][0]['value'];
|
self.EmitFunction[token['value']](self,fp,token['argument']);
|
(addr,ixBank,bankName) = self.Emit_GetAddrAndBank(name);
|
|
self.EmitPush(fp,addr,self.Emit_String(name),token['loc']);
|
|
self.EmitOpcode(fp,self.InstructionOpcode('+'),'+');
|
|
self.EmitOpcode(fp,self.specialInstructions['store'] | ixBank,'store '+bankName);
|
|
self.EmitOptArg(fp,token['argument'][1]);
|
|
# .storeoffset
|
|
elif token['value'] == '.storeoffset':
|
|
name = token['argument'][0]['value'];
|
|
(addr,ixBank,bankName) = self.Emit_GetAddrAndBank(name);
|
|
offset = self.Emit_EvalSingleValue(token['argument'][1]);
|
|
self.EmitPush(fp,addr+offset,self.Emit_String('%s+%s' % (name,offset,)),token['loc']);
|
|
self.EmitOpcode(fp,self.specialInstructions['store'] | ixBank,'store '+bankName);
|
|
self.EmitOptArg(fp,token['argument'][2]);
|
|
# .storevalue
|
|
elif token['value'] == '.storevalue':
|
|
name = token['argument'][0]['value'];
|
|
(addr,ixBank,bankName) = self.Emit_GetAddrAndBank(name);
|
|
self.EmitPush(fp,addr,self.Emit_String(name),token['loc']);
|
|
self.EmitOpcode(fp,self.specialInstructions['store'] | ixBank,'store '+bankName);
|
|
self.EmitOptArg(fp,token['argument'][1]);
|
|
# .storevector
|
|
elif token['value'] == '.storevector':
|
|
(addr,ixBank,bankName) = self.Emit_GetAddrAndBank(token['argument'][0]['value']);
|
|
N = int(token['argument'][1]['value']);
|
|
self.EmitPush(fp,addr,token['argument'][0]['value']);
|
|
for dummy in range(N):
|
|
self.EmitOpcode(fp,self.specialInstructions['store+'] | ixBank,'store+ '+bankName);
|
|
self.EmitOpcode(fp,self.InstructionOpcode('drop'),'drop');
|
|
# error
|
# error
|
else:
|
else:
|
raise Exception('Program Bug -- Unrecognized macro "%s"' % token['value']);
|
raise Exception('Program Bug -- Unrecognized macro "%s"' % token['value']);
|
|
|
def EmitProgram(self,fp):
|
def EmitProgram(self,fp):
|
Line 1211... |
Line 1175... |
body of the .main function, body of the optional .interrupt function,
|
body of the .main function, body of the optional .interrupt function,
|
current memory for variable definitions, etc.
|
current memory for variable definitions, etc.
|
"""
|
"""
|
|
|
#
|
#
|
|
# Enumerate the directives
|
|
# Note: The ".include" directive is handled within asmDef.FileBodyIterator.
|
|
#
|
|
|
|
self.directives = dict();
|
|
|
|
self.directives['list']= list();
|
|
self.directives['list'].append('.constant');
|
|
self.directives['list'].append('.function');
|
|
self.directives['list'].append('.interrupt');
|
|
self.directives['list'].append('.macro');
|
|
self.directives['list'].append('.main');
|
|
self.directives['list'].append('.memory');
|
|
self.directives['list'].append('.variable');
|
|
|
|
#
|
# Configure the instructions.
|
# Configure the instructions.
|
#
|
#
|
|
|
self.instructions = dict(list=list(), opcode=list());
|
self.instructions = dict(list=list(), opcode=list());
|
self.AddInstruction('&', 0x050);
|
self.AddInstruction('&', 0x050);
|
Line 1261... |
Line 1241... |
self.specialInstructions['store'] = 0x060;
|
self.specialInstructions['store'] = 0x060;
|
self.specialInstructions['store+'] = 0x070;
|
self.specialInstructions['store+'] = 0x070;
|
self.specialInstructions['store-'] = 0x074;
|
self.specialInstructions['store-'] = 0x074;
|
|
|
#
|
#
|
# Enumerate the directives
|
|
# Note: The ".include" directive is handled within asmDef.FileBodyIterator.
|
|
#
|
|
|
|
self.directives = dict();
|
|
|
|
self.directives['list']= list();
|
|
self.directives['list'].append('.constant');
|
|
self.directives['list'].append('.function');
|
|
self.directives['list'].append('.interrupt');
|
|
self.directives['list'].append('.main');
|
|
self.directives['list'].append('.memory');
|
|
self.directives['list'].append('.variable');
|
|
|
|
#
|
|
#
|
|
# Configure the pre-defined macros
|
# Configure the pre-defined macros
|
# Note: 'symbol' is a catch-call for functions, labels, variables, etc.
|
# Note: 'symbol' is a catch-call for functions, labels, variables, etc.
|
# These are restricted to the appropriate types when the macros are
|
# These are restricted to the appropriate types when the macros are
|
# expanded.
|
# expanded.
|
#
|
#
|
|
|
self.macros = dict(list=list(), length=list(), args=list(), nArgs=list());
|
self.macros = dict(list=list(), length=list(), args=list(), nArgs=list(), builtIn = list());
|
|
self.EmitFunction = dict();
|
|
|
|
# Macros built in to the assembler (to access primitives).
|
self.AddMacro('.call', 3, [
|
self.AddMacro('.call', 3, [
|
['','symbol'],
|
['','symbol'],
|
['nop','instruction','singlemacro','singlevalue','symbol']
|
['nop','instruction','singlemacro','singlevalue','symbol']
|
]);
|
]);
|
self.AddMacro('.callc', 3, [
|
self.AddMacro('.callc', 3, [
|
Line 1295... |
Line 1262... |
['drop','instruction','singlevalue','symbol']
|
['drop','instruction','singlevalue','symbol']
|
]);
|
]);
|
self.AddMacro('.fetch', 1, [ ['','symbol'] ]);
|
self.AddMacro('.fetch', 1, [ ['','symbol'] ]);
|
self.AddMacro('.fetch+', 1, [ ['','symbol'] ]);
|
self.AddMacro('.fetch+', 1, [ ['','symbol'] ]);
|
self.AddMacro('.fetch-', 1, [ ['','symbol'] ]);
|
self.AddMacro('.fetch-', 1, [ ['','symbol'] ]);
|
self.AddMacro('.fetchindexed', 3, [ ['','symbol'] ]);
|
|
self.AddMacro('.fetchoffset', 2, [
|
|
['','symbol'],
|
|
['','singlevalue','symbol']
|
|
]);
|
|
self.AddMacro('.fetchvalue', 2, [ ['','symbol'] ]);
|
|
self.AddMacro('.fetchvector', -1, [
|
|
['','symbol'],
|
|
['','singlevalue','symbol']
|
|
]);
|
|
self.AddMacro('.inport', 2, [ ['','symbol'] ]);
|
|
self.AddMacro('.jump', 3, [
|
self.AddMacro('.jump', 3, [
|
['','symbol'],
|
['','symbol'],
|
['nop','instruction','singlemacro','singlevalue','symbol']
|
['nop','instruction','singlemacro','singlevalue','symbol']
|
]);
|
]);
|
self.AddMacro('.jumpc', 3, [
|
self.AddMacro('.jumpc', 3, [
|
['','symbol'],
|
['','symbol'],
|
['drop','instruction','singlemacro','singlevalue','symbol']
|
['drop','instruction','singlemacro','singlevalue','symbol']
|
]);
|
]);
|
self.AddMacro('.outport', 3, [
|
|
['','symbol'],
|
|
['drop','instruction','singlemacro','singlevalue','symbol']
|
|
]);
|
|
self.AddMacro('.outstrobe', 2, [ ['','symbol'] ]);
|
|
self.AddMacro('.return', 2, [ ['nop','instruction','singlevalue','symbol'] ]);
|
self.AddMacro('.return', 2, [ ['nop','instruction','singlevalue','symbol'] ]);
|
self.AddMacro('.store', 1, [ ['','symbol'] ]);
|
self.AddMacro('.store', 1, [ ['','symbol'] ]);
|
self.AddMacro('.store+', 1, [ ['','symbol'] ]);
|
self.AddMacro('.store+', 1, [ ['','symbol'] ]);
|
self.AddMacro('.store-', 1, [ ['','symbol'] ]);
|
self.AddMacro('.store-', 1, [ ['','symbol'] ]);
|
self.AddMacro('.storeindexed', 4, [
|
|
['','symbol'],
|
# User-defined macros in ./macros that are "built in" to the assembler.
|
['drop','instruction','singlemacro','singlevalue','symbol']
|
macroSearchPath = os.path.join(sys.path[0],'macros');
|
]);
|
for macroName in os.listdir(macroSearchPath):
|
self.AddMacro('.storeoffset', 3, [
|
if not re.match(r'.*\.py$',macroName):
|
['','symbol'],
|
continue;
|
['','singlevalue','symbol'],
|
self.AddUserMacro(macroName[:-3],macroSearchPaths=[macroSearchPath]);
|
['drop','instruction','singlemacro','singlevalue','symbol']
|
for macroName in self.macros['list']:
|
]);
|
self.macros['builtIn'].append(macroName);
|
self.AddMacro('.storevalue', 3, [
|
|
['','symbol'],
|
|
['drop','instruction','singlemacro','singlevalue','symbol']
|
|
]);
|
|
self.AddMacro('.storevector', -1, [
|
|
['','symbol'],
|
|
['','singlevalue','symbol'],
|
|
]);
|
|
|
|
#
|
#
|
# List the macros that have special symbols for their first argument.
|
# List the macros that have special symbols for their first argument.
|
#
|
#
|
|
|
Line 1359... |
Line 1302... |
#
|
#
|
# Configure the containers for the expanded main, interrupt, function,
|
# Configure the containers for the expanded main, interrupt, function,
|
# macro, etc. definitions.
|
# macro, etc. definitions.
|
#
|
#
|
|
|
|
self.currentMemory = None;
|
self.interrupt = None;
|
self.interrupt = None;
|
self.main = None;
|
self.main = None;
|
|
self.macroSearchPaths = ['.','./macros'];
|
self.symbols = dict(list=list(), type=list(), body=list());
|
self.symbols = dict(list=list(), type=list(), body=list());
|
self.currentMemory = None;
|
|
|
|
No newline at end of file
|
No newline at end of file
|