| 1 | 
         2 | 
         sinclairrf | 
         ################################################################################
  | 
      
      
         | 2 | 
          | 
          | 
         #
  | 
      
      
         | 3 | 
         3 | 
         sinclairrf | 
         # Copyright 2012-2014, Sinclair R.F., Inc.
  | 
      
      
         | 4 | 
         2 | 
         sinclairrf | 
         #
  | 
      
      
         | 5 | 
          | 
          | 
         # Assembly language definitions for SSBCC 9x8.
  | 
      
      
         | 6 | 
          | 
          | 
         #
  | 
      
      
         | 7 | 
          | 
          | 
         ################################################################################
  | 
      
      
         | 8 | 
          | 
          | 
          
  | 
      
      
         | 9 | 
          | 
          | 
         import copy
  | 
      
      
         | 10 | 
         3 | 
         sinclairrf | 
         import os
  | 
      
      
         | 11 | 
          | 
          | 
         import re
  | 
      
      
         | 12 | 
         2 | 
         sinclairrf | 
         import string
  | 
      
      
         | 13 | 
         3 | 
         sinclairrf | 
         import sys
  | 
      
      
         | 14 | 
          | 
          | 
         import types
  | 
      
      
         | 15 | 
         2 | 
         sinclairrf | 
          
  | 
      
      
         | 16 | 
          | 
          | 
         import asmDef
  | 
      
      
         | 17 | 
          | 
          | 
          
  | 
      
      
         | 18 | 
          | 
          | 
         class asmDef_9x8:
  | 
      
      
         | 19 | 
          | 
          | 
           """
  | 
      
      
         | 20 | 
          | 
          | 
           Class for core-specific opcodes, macros, etc. for core/9x8.
  | 
      
      
         | 21 | 
          | 
          | 
           """
  | 
      
      
         | 22 | 
          | 
          | 
          
  | 
      
      
         | 23 | 
          | 
          | 
           ################################################################################
  | 
      
      
         | 24 | 
          | 
          | 
           #
  | 
      
      
         | 25 | 
          | 
          | 
           # External interface to the directives.
  | 
      
      
         | 26 | 
          | 
          | 
           #
  | 
      
      
         | 27 | 
          | 
          | 
           ################################################################################
  | 
      
      
         | 28 | 
          | 
          | 
          
  | 
      
      
         | 29 | 
          | 
          | 
           def IsDirective(self,name):
  | 
      
      
         | 30 | 
          | 
          | 
             """
  | 
      
      
         | 31 | 
          | 
          | 
             Indicate whether or not the string "name" is a directive.
  | 
      
      
         | 32 | 
          | 
          | 
             """
  | 
      
      
         | 33 | 
          | 
          | 
             return name in self.directives['list'];
  | 
      
      
         | 34 | 
          | 
          | 
          
  | 
      
      
         | 35 | 
          | 
          | 
           ################################################################################
  | 
      
      
         | 36 | 
          | 
          | 
           #
  | 
      
      
         | 37 | 
          | 
          | 
           # Record symbols
  | 
      
      
         | 38 | 
          | 
          | 
           #
  | 
      
      
         | 39 | 
          | 
          | 
           ################################################################################
  | 
      
      
         | 40 | 
          | 
          | 
          
  | 
      
      
         | 41 | 
          | 
          | 
           def AddSymbol(self,name,stype,body=None):
  | 
      
      
         | 42 | 
          | 
          | 
             """
  | 
      
      
         | 43 | 
          | 
          | 
             Add the named global symbol to the list of symbols including its mandatory
  | 
      
      
         | 44 | 
          | 
          | 
             type and an optional body.\n
  | 
      
      
         | 45 | 
          | 
          | 
             Note:  Symbols include memory names, variables, constants, functions,
  | 
      
      
         | 46 | 
          | 
          | 
                    parameters, inports, outports, ...
  | 
      
      
         | 47 | 
          | 
          | 
             """
  | 
      
      
         | 48 | 
          | 
          | 
             if self.IsSymbol(name):
  | 
      
      
         | 49 | 
          | 
          | 
               raise Exception('Program Bug -- name "%s" already exists is symbols' % name);
  | 
      
      
         | 50 | 
          | 
          | 
             self.symbols['list'].append(name);
  | 
      
      
         | 51 | 
          | 
          | 
             self.symbols['type'].append(stype);
  | 
      
      
         | 52 | 
          | 
          | 
             self.symbols['body'].append(body);
  | 
      
      
         | 53 | 
          | 
          | 
          
  | 
      
      
         | 54 | 
          | 
          | 
           def IsSymbol(self,name):
  | 
      
      
         | 55 | 
          | 
          | 
             return name in self.symbols['list'];
  | 
      
      
         | 56 | 
          | 
          | 
          
  | 
      
      
         | 57 | 
          | 
          | 
           def SymbolDict(self):
  | 
      
      
         | 58 | 
          | 
          | 
             """
  | 
      
      
         | 59 | 
          | 
          | 
             Return a dict object usable by the eval function with the currently defines
  | 
      
      
         | 60 | 
          | 
          | 
             symbols for constants, variables, memory lengths, stack lengths, and signal
  | 
      
      
         | 61 | 
          | 
          | 
             lengths.
  | 
      
      
         | 62 | 
          | 
          | 
             """
  | 
      
      
         | 63 | 
          | 
          | 
             t = dict();
  | 
      
      
         | 64 | 
          | 
          | 
             for ixSymbol in range(len(self.symbols['list'])):
  | 
      
      
         | 65 | 
          | 
          | 
               name = self.symbols['list'][ixSymbol];
  | 
      
      
         | 66 | 
          | 
          | 
               stype = self.symbols['type'][ixSymbol];
  | 
      
      
         | 67 | 
          | 
          | 
               if stype == 'constant':
  | 
      
      
         | 68 | 
          | 
          | 
                 t[name] = self.symbols['body'][ixSymbol][0];
  | 
      
      
         | 69 | 
          | 
          | 
               elif stype == 'variable':
  | 
      
      
         | 70 | 
          | 
          | 
                 t[name] = self.symbols['body'][ixSymbol]['start'];
  | 
      
      
         | 71 | 
          | 
          | 
             sizes=dict();
  | 
      
      
         | 72 | 
          | 
          | 
             for name in self.memoryLength:
  | 
      
      
         | 73 | 
          | 
          | 
               sizes[name] = self.memoryLength[name];
  | 
      
      
         | 74 | 
          | 
          | 
             for name in self.stackLength:
  | 
      
      
         | 75 | 
          | 
          | 
               sizes[name] = self.stackLength[name];
  | 
      
      
         | 76 | 
          | 
          | 
             t['size'] = sizes;
  | 
      
      
         | 77 | 
          | 
          | 
             return t;
  | 
      
      
         | 78 | 
          | 
          | 
          
  | 
      
      
         | 79 | 
          | 
          | 
           ################################################################################
  | 
      
      
         | 80 | 
          | 
          | 
           #
  | 
      
      
         | 81 | 
          | 
          | 
           # Configure the class for identifying and processing macros.
  | 
      
      
         | 82 | 
          | 
          | 
           #
  | 
      
      
         | 83 | 
          | 
          | 
           ################################################################################
  | 
      
      
         | 84 | 
          | 
          | 
          
  | 
      
      
         | 85 | 
          | 
          | 
           def AddMacro(self,name,macroLength,args):
  | 
      
      
         | 86 | 
          | 
          | 
             """
  | 
      
      
         | 87 | 
          | 
          | 
             Add a macro to the list of recognized macros.
  | 
      
      
         | 88 | 
          | 
          | 
               name              string with the name of the macro
  | 
      
      
         | 89 | 
          | 
          | 
               macroLength       number of instructions the macro expands to
  | 
      
      
         | 90 | 
          | 
          | 
                                 Note:  A negative value means that the macro has a
  | 
      
      
         | 91 | 
          | 
          | 
                                        variable length (see MacroLength below)
  | 
      
      
         | 92 | 
          | 
          | 
               args              list of the arguments
  | 
      
      
         | 93 | 
          | 
          | 
                                 each element of this list is an array of strings specifying the following:
  | 
      
      
         | 94 | 
          | 
          | 
                                   1.  If the first element is the empty string, then
  | 
      
      
         | 95 | 
          | 
          | 
                                       there is no default value for the argument,
  | 
      
      
         | 96 | 
          | 
          | 
                                       otherwise the listed string is the default
  | 
      
      
         | 97 | 
          | 
          | 
                                       value of the optional argument.
  | 
      
      
         | 98 | 
          | 
          | 
                                   2.  The remaining elements of the list are the types
  | 
      
      
         | 99 | 
          | 
          | 
                                       of arguments that can be accepted for the
  | 
      
      
         | 100 | 
          | 
          | 
                                       required or optional arguments.
  | 
      
      
         | 101 | 
          | 
          | 
                                 Note:  Only the last list in args is allowed to
  | 
      
      
         | 102 | 
          | 
          | 
                                        indicate an optional value for that argument.
  | 
      
      
         | 103 | 
          | 
          | 
          
  | 
      
      
         | 104 | 
          | 
          | 
             Also record the allowed number of allowed arguments to the macro.
  | 
      
      
         | 105 | 
          | 
          | 
             """
  | 
      
      
         | 106 | 
          | 
          | 
             if name in self.macros['list']:
  | 
      
      
         | 107 | 
          | 
          | 
               raise Exception('Program Bug -- name "%s" has already been listed as a macro' % name);
  | 
      
      
         | 108 | 
          | 
          | 
             self.macros['list'].append(name);
  | 
      
      
         | 109 | 
          | 
          | 
             self.macros['length'].append(macroLength);
  | 
      
      
         | 110 | 
          | 
          | 
             self.macros['args'].append(args);
  | 
      
      
         | 111 | 
          | 
          | 
             # Compute the range of the number of allowed arguments by first counting
  | 
      
      
         | 112 | 
          | 
          | 
             # the number of required arguments and then determining whether or not
  | 
      
      
         | 113 | 
          | 
          | 
             # there is at most one optional argument.
  | 
      
      
         | 114 | 
          | 
          | 
             nRequired = 0;
  | 
      
      
         | 115 | 
          | 
          | 
             while (nRequired < len(args)) and (args[nRequired][0] == ''):
  | 
      
      
         | 116 | 
          | 
          | 
               nRequired = nRequired + 1;
  | 
      
      
         | 117 | 
          | 
          | 
             if nRequired < len(args)-1:
  | 
      
      
         | 118 | 
          | 
          | 
               raise Exception('Program Bug -- Only the last macro argument can be optional');
  | 
      
      
         | 119 | 
          | 
          | 
             self.macros['nArgs'].append(range(nRequired,len(args)+1));
  | 
      
      
         | 120 | 
          | 
          | 
          
  | 
      
      
         | 121 | 
         3 | 
         sinclairrf | 
           def AddMacroSearchPath(self,path):
  | 
      
      
         | 122 | 
          | 
          | 
             self.macroSearchPaths.append(path);
  | 
      
      
         | 123 | 
          | 
          | 
          
  | 
      
      
         | 124 | 
          | 
          | 
           def AddUserMacro(self,macroName,macroSearchPaths=None):
  | 
      
      
         | 125 | 
          | 
          | 
             """
  | 
      
      
         | 126 | 
          | 
          | 
             Add a user-defined macro by processing the associated Python script.
  | 
      
      
         | 127 | 
          | 
          | 
               macroName         name of the macro
  | 
      
      
         | 128 | 
          | 
          | 
                                 The associated Python script must be named
  | 
      
      
         | 129 | 
          | 
          | 
                                 <macroName>.py and must be in the project directory, an
  | 
      
      
         | 130 | 
          | 
          | 
                                 included directory, or must be one of the macros
  | 
      
      
         | 131 | 
          | 
          | 
                                 provided in "macros" subdirectory of this directory.
  | 
      
      
         | 132 | 
          | 
          | 
             """
  | 
      
      
         | 133 | 
          | 
          | 
             if not macroSearchPaths:
  | 
      
      
         | 134 | 
          | 
          | 
               macroSearchPaths = self.macroSearchPaths;
  | 
      
      
         | 135 | 
          | 
          | 
             for testPath in macroSearchPaths:
  | 
      
      
         | 136 | 
          | 
          | 
               fullMacro = os.path.join(testPath,'%s.py' % macroName);
  | 
      
      
         | 137 | 
          | 
          | 
               if os.path.isfile(fullMacro):
  | 
      
      
         | 138 | 
          | 
          | 
                 break;
  | 
      
      
         | 139 | 
          | 
          | 
             else:
  | 
      
      
         | 140 | 
          | 
          | 
               raise asmDef.AsmException('Definition for macro "%s" not found' % macroName);
  | 
      
      
         | 141 | 
          | 
          | 
             execfile(fullMacro);
  | 
      
      
         | 142 | 
          | 
          | 
             exec('%s(self)' % macroName);
  | 
      
      
         | 143 | 
          | 
          | 
          
  | 
      
      
         | 144 | 
          | 
          | 
           def IsBuiltInMacro(self,name):
  | 
      
      
         | 145 | 
          | 
          | 
             """
  | 
      
      
         | 146 | 
          | 
          | 
             Indicate if the macro is built-in to the assembler or is taken from the
  | 
      
      
         | 147 | 
          | 
          | 
             ./macros directory.
  | 
      
      
         | 148 | 
          | 
          | 
             """
  | 
      
      
         | 149 | 
          | 
          | 
             return name in self.macros['builtIn'];
  | 
      
      
         | 150 | 
          | 
          | 
          
  | 
      
      
         | 151 | 
         2 | 
         sinclairrf | 
           def IsMacro(self,name):
  | 
      
      
         | 152 | 
          | 
          | 
             """
  | 
      
      
         | 153 | 
          | 
          | 
             Indicate whether or not the string "name" is a recognized macro.
  | 
      
      
         | 154 | 
          | 
          | 
             """
  | 
      
      
         | 155 | 
          | 
          | 
             return name in self.macros['list'];
  | 
      
      
         | 156 | 
          | 
          | 
          
  | 
      
      
         | 157 | 
          | 
          | 
           def IsSingleMacro(self,name):
  | 
      
      
         | 158 | 
          | 
          | 
             """
  | 
      
      
         | 159 | 
          | 
          | 
             Indicate whether or not the macro is only one instruction long.
  | 
      
      
         | 160 | 
          | 
          | 
             """
  | 
      
      
         | 161 | 
          | 
          | 
             if name not in self.macros['list']:
  | 
      
      
         | 162 | 
          | 
          | 
               raise Exception('Program Bug -- name "%s" is not a macro' % name);
  | 
      
      
         | 163 | 
          | 
          | 
             ix = self.macros['list'].index(name);
  | 
      
      
         | 164 | 
          | 
          | 
             return (self.macros['length'][ix] == 1);
  | 
      
      
         | 165 | 
          | 
          | 
          
  | 
      
      
         | 166 | 
          | 
          | 
           def MacroArgTypes(self,name,ixArg):
  | 
      
      
         | 167 | 
          | 
          | 
             """
  | 
      
      
         | 168 | 
          | 
          | 
             Return the list of allowed types for the macro name for argument ixArg.
  | 
      
      
         | 169 | 
          | 
          | 
             """
  | 
      
      
         | 170 | 
          | 
          | 
             if name not in self.macros['list']:
  | 
      
      
         | 171 | 
          | 
          | 
               raise Exception('Program Bug -- name "%s" is not a macro' % name);
  | 
      
      
         | 172 | 
          | 
          | 
             ix = self.macros['list'].index(name);
  | 
      
      
         | 173 | 
          | 
          | 
             return self.macros['args'][ix][ixArg][1:];
  | 
      
      
         | 174 | 
          | 
          | 
          
  | 
      
      
         | 175 | 
          | 
          | 
           def MacroDefault(self,name,ixArg):
  | 
      
      
         | 176 | 
          | 
          | 
             """
  | 
      
      
         | 177 | 
          | 
          | 
             Return the default argument for the macro name for argument ixArg.
  | 
      
      
         | 178 | 
          | 
          | 
             """
  | 
      
      
         | 179 | 
          | 
          | 
             if name not in self.macros['list']:
  | 
      
      
         | 180 | 
          | 
          | 
               raise Exception('Program Bug -- name "%s" is not a macro' % name);
  | 
      
      
         | 181 | 
          | 
          | 
             ix = self.macros['list'].index(name);
  | 
      
      
         | 182 | 
          | 
          | 
             return self.macros['args'][ix][ixArg][0];
  | 
      
      
         | 183 | 
          | 
          | 
          
  | 
      
      
         | 184 | 
          | 
          | 
           def MacroLength(self,token):
  | 
      
      
         | 185 | 
          | 
          | 
             """
  | 
      
      
         | 186 | 
          | 
          | 
             Return the length of fixed-length macros or compute and return the length
  | 
      
      
         | 187 | 
         3 | 
         sinclairrf | 
             of variable-length macros.
  | 
      
      
         | 188 | 
         2 | 
         sinclairrf | 
             """
  | 
      
      
         | 189 | 
          | 
          | 
             if token['value'] not in self.macros['list']:
  | 
      
      
         | 190 | 
          | 
          | 
               raise Exception('Program Bug -- name "%s" is not a macro' % token['value']);
  | 
      
      
         | 191 | 
          | 
          | 
             ix = self.macros['list'].index(token['value']);
  | 
      
      
         | 192 | 
          | 
          | 
             length = self.macros['length'][ix];
  | 
      
      
         | 193 | 
         3 | 
         sinclairrf | 
             if type(length) == int:
  | 
      
      
         | 194 | 
         2 | 
         sinclairrf | 
               return length;
  | 
      
      
         | 195 | 
         3 | 
         sinclairrf | 
             elif type(length) == types.FunctionType:
  | 
      
      
         | 196 | 
          | 
          | 
               return length(self,token['argument']);
  | 
      
      
         | 197 | 
          | 
          | 
             else:
  | 
      
      
         | 198 | 
          | 
          | 
               raise Exception('Program Bug -- Unrecognized variable length macro "%s"' % token['value']);
  | 
      
      
         | 199 | 
         2 | 
         sinclairrf | 
          
  | 
      
      
         | 200 | 
          | 
          | 
           def MacroNumberArgs(self,name):
  | 
      
      
         | 201 | 
          | 
          | 
             """
  | 
      
      
         | 202 | 
          | 
          | 
             Return the range of the number of allowed arguments to the named macro.
  | 
      
      
         | 203 | 
          | 
          | 
             """
  | 
      
      
         | 204 | 
          | 
          | 
             if name not in self.macros['list']:
  | 
      
      
         | 205 | 
          | 
          | 
               raise Exception('Program bug -- name "%s" is not a macro' % name);
  | 
      
      
         | 206 | 
          | 
          | 
             ix = self.macros['list'].index(name);
  | 
      
      
         | 207 | 
          | 
          | 
             return self.macros['nArgs'][ix];
  | 
      
      
         | 208 | 
          | 
          | 
          
  | 
      
      
         | 209 | 
          | 
          | 
           ################################################################################
  | 
      
      
         | 210 | 
          | 
          | 
           #
  | 
      
      
         | 211 | 
          | 
          | 
           # Configure the class for processing instructions.
  | 
      
      
         | 212 | 
          | 
          | 
           #
  | 
      
      
         | 213 | 
          | 
          | 
           ################################################################################
  | 
      
      
         | 214 | 
          | 
          | 
          
  | 
      
      
         | 215 | 
          | 
          | 
           def AddInstruction(self,name,opcode):
  | 
      
      
         | 216 | 
          | 
          | 
             """
  | 
      
      
         | 217 | 
          | 
          | 
             Add an instruction to the list of recognized instructions.
  | 
      
      
         | 218 | 
          | 
          | 
             """
  | 
      
      
         | 219 | 
          | 
          | 
             self.instructions['list'].append(name);
  | 
      
      
         | 220 | 
          | 
          | 
             self.instructions['opcode'].append(opcode);
  | 
      
      
         | 221 | 
          | 
          | 
          
  | 
      
      
         | 222 | 
          | 
          | 
           def IsInstruction(self,name):
  | 
      
      
         | 223 | 
          | 
          | 
             """
  | 
      
      
         | 224 | 
          | 
          | 
             Indicate whether or not the argument is an instruction.
  | 
      
      
         | 225 | 
          | 
          | 
             """
  | 
      
      
         | 226 | 
          | 
          | 
             return name in self.instructions['list'];
  | 
      
      
         | 227 | 
          | 
          | 
          
  | 
      
      
         | 228 | 
          | 
          | 
           def InstructionOpcode(self,name):
  | 
      
      
         | 229 | 
          | 
          | 
             """
  | 
      
      
         | 230 | 
          | 
          | 
             Return the opcode for the specified instruction.
  | 
      
      
         | 231 | 
          | 
          | 
             """
  | 
      
      
         | 232 | 
          | 
          | 
             if not self.IsInstruction(name):
  | 
      
      
         | 233 | 
          | 
          | 
               raise Exception('Program Bug:  "%s" not in instruction list' % name);
  | 
      
      
         | 234 | 
          | 
          | 
             ix = self.instructions['list'].index(name);
  | 
      
      
         | 235 | 
          | 
          | 
             return self.instructions['opcode'][ix];
  | 
      
      
         | 236 | 
          | 
          | 
          
  | 
      
      
         | 237 | 
          | 
          | 
           ################################################################################
  | 
      
      
         | 238 | 
          | 
          | 
           #
  | 
      
      
         | 239 | 
          | 
          | 
           # Register input and output port names and addresses.
  | 
      
      
         | 240 | 
          | 
          | 
           #
  | 
      
      
         | 241 | 
          | 
          | 
           ################################################################################
  | 
      
      
         | 242 | 
          | 
          | 
          
  | 
      
      
         | 243 | 
          | 
          | 
           def IsConstant(self,name):
  | 
      
      
         | 244 | 
          | 
          | 
             """
  | 
      
      
         | 245 | 
          | 
          | 
             Indicate whether or not the named symbol is an inport.
  | 
      
      
         | 246 | 
          | 
          | 
             """
  | 
      
      
         | 247 | 
          | 
          | 
             if not self.IsSymbol(name):
  | 
      
      
         | 248 | 
          | 
          | 
               return False;
  | 
      
      
         | 249 | 
          | 
          | 
             ix = self.symbols['list'].index(name);
  | 
      
      
         | 250 | 
          | 
          | 
             return self.symbols['type'][ix] == 'constant';
  | 
      
      
         | 251 | 
          | 
          | 
          
  | 
      
      
         | 252 | 
          | 
          | 
           def IsInport(self,name):
  | 
      
      
         | 253 | 
          | 
          | 
             """
  | 
      
      
         | 254 | 
          | 
          | 
             Indicate whether or not the named symbol is an inport.
  | 
      
      
         | 255 | 
          | 
          | 
             """
  | 
      
      
         | 256 | 
          | 
          | 
             if not self.IsSymbol(name):
  | 
      
      
         | 257 | 
          | 
          | 
               return False;
  | 
      
      
         | 258 | 
          | 
          | 
             ix = self.symbols['list'].index(name);
  | 
      
      
         | 259 | 
          | 
          | 
             return self.symbols['type'][ix] == 'inport';
  | 
      
      
         | 260 | 
          | 
          | 
          
  | 
      
      
         | 261 | 
          | 
          | 
           def IsOutport(self,name):
  | 
      
      
         | 262 | 
          | 
          | 
             """
  | 
      
      
         | 263 | 
          | 
          | 
             Indicate whether or not the named symbol is an outport.
  | 
      
      
         | 264 | 
          | 
          | 
             """
  | 
      
      
         | 265 | 
          | 
          | 
             if not self.IsSymbol(name):
  | 
      
      
         | 266 | 
          | 
          | 
               return False;
  | 
      
      
         | 267 | 
          | 
          | 
             ix = self.symbols['list'].index(name);
  | 
      
      
         | 268 | 
          | 
          | 
             return self.symbols['type'][ix] == 'outport';
  | 
      
      
         | 269 | 
          | 
          | 
          
  | 
      
      
         | 270 | 
          | 
          | 
           def IsOutstrobe(self,name):
  | 
      
      
         | 271 | 
          | 
          | 
             """
  | 
      
      
         | 272 | 
          | 
          | 
             Indicate whether or not the named symbol is a strobe-only outport.
  | 
      
      
         | 273 | 
          | 
          | 
             """
  | 
      
      
         | 274 | 
          | 
          | 
             if not self.IsSymbol(name):
  | 
      
      
         | 275 | 
          | 
          | 
               return False;
  | 
      
      
         | 276 | 
          | 
          | 
             ix = self.symbols['list'].index(name);
  | 
      
      
         | 277 | 
          | 
          | 
             return self.symbols['type'][ix] == 'outstrobe';
  | 
      
      
         | 278 | 
          | 
          | 
          
  | 
      
      
         | 279 | 
          | 
          | 
           def IsParameter(self,name):
  | 
      
      
         | 280 | 
          | 
          | 
             """
  | 
      
      
         | 281 | 
          | 
          | 
             Indicate whether or not the named symbol is a parameter.
  | 
      
      
         | 282 | 
          | 
          | 
             """
  | 
      
      
         | 283 | 
          | 
          | 
             if not self.IsSymbol(name):
  | 
      
      
         | 284 | 
          | 
          | 
               return False;
  | 
      
      
         | 285 | 
          | 
          | 
             ix = self.symbols['list'].index(name);
  | 
      
      
         | 286 | 
          | 
          | 
             return self.symbols['type'][ix] == 'parameter';
  | 
      
      
         | 287 | 
          | 
          | 
          
  | 
      
      
         | 288 | 
          | 
          | 
           def InportAddress(self,name):
  | 
      
      
         | 289 | 
          | 
          | 
             """
  | 
      
      
         | 290 | 
          | 
          | 
             Return the address of the named inport.
  | 
      
      
         | 291 | 
          | 
          | 
             """
  | 
      
      
         | 292 | 
          | 
          | 
             if not self.IsInport(name):
  | 
      
      
         | 293 | 
          | 
          | 
               raise Exception('Program Bug -- "%s" is not an inport' % name);
  | 
      
      
         | 294 | 
          | 
          | 
             ix = self.symbols['list'].index(name);
  | 
      
      
         | 295 | 
          | 
          | 
             return self.symbols['body'][ix];
  | 
      
      
         | 296 | 
          | 
          | 
          
  | 
      
      
         | 297 | 
          | 
          | 
           def OutportAddress(self,name):
  | 
      
      
         | 298 | 
          | 
          | 
             """
  | 
      
      
         | 299 | 
          | 
          | 
             Return the address of the named outport.
  | 
      
      
         | 300 | 
          | 
          | 
             """
  | 
      
      
         | 301 | 
          | 
          | 
             if not self.IsOutport(name) and not self.IsOutstrobe(name):
  | 
      
      
         | 302 | 
          | 
          | 
               raise Exception('Program Bug -- "%s" is not an outport' % name);
  | 
      
      
         | 303 | 
          | 
          | 
             ix = self.symbols['list'].index(name);
  | 
      
      
         | 304 | 
          | 
          | 
             return self.symbols['body'][ix];
  | 
      
      
         | 305 | 
          | 
          | 
          
  | 
      
      
         | 306 | 
          | 
          | 
           def RegisterInport(self,name,address):
  | 
      
      
         | 307 | 
          | 
          | 
             """
  | 
      
      
         | 308 | 
          | 
          | 
             Add the named inport to the list of recognized symbols and record its
  | 
      
      
         | 309 | 
          | 
          | 
             address as the body of the inport.
  | 
      
      
         | 310 | 
          | 
          | 
             """
  | 
      
      
         | 311 | 
          | 
          | 
             if self.IsSymbol(name):
  | 
      
      
         | 312 | 
          | 
          | 
               raise Exception('Program Bug -- repeated symbol name "%s"' % name);
  | 
      
      
         | 313 | 
          | 
          | 
             self.AddSymbol(name,'inport',address);
  | 
      
      
         | 314 | 
          | 
          | 
          
  | 
      
      
         | 315 | 
          | 
          | 
           def RegisterOutport(self,name,address):
  | 
      
      
         | 316 | 
          | 
          | 
             """
  | 
      
      
         | 317 | 
          | 
          | 
             Add the named outport to the list of recognized symbols and record its
  | 
      
      
         | 318 | 
          | 
          | 
             address as the body of the outport.
  | 
      
      
         | 319 | 
          | 
          | 
             """
  | 
      
      
         | 320 | 
          | 
          | 
             if self.IsSymbol(name):
  | 
      
      
         | 321 | 
          | 
          | 
               raise Exception('Program Bug -- repeated symbol name "%s"' % name);
  | 
      
      
         | 322 | 
          | 
          | 
             self.AddSymbol(name,'outport',address);
  | 
      
      
         | 323 | 
          | 
          | 
          
  | 
      
      
         | 324 | 
          | 
          | 
           def RegisterOutstrobe(self,name,address):
  | 
      
      
         | 325 | 
          | 
          | 
             """
  | 
      
      
         | 326 | 
          | 
          | 
             Add the named outport to the list of recognized symbols and record its
  | 
      
      
         | 327 | 
          | 
          | 
             address as the body of the strobe-only outports.
  | 
      
      
         | 328 | 
          | 
          | 
             """
  | 
      
      
         | 329 | 
          | 
          | 
             if self.IsSymbol(name):
  | 
      
      
         | 330 | 
          | 
          | 
               raise Exception('Program Bug -- repeated symbol name "%s"' % name);
  | 
      
      
         | 331 | 
          | 
          | 
             self.AddSymbol(name,'outstrobe',address);
  | 
      
      
         | 332 | 
          | 
          | 
          
  | 
      
      
         | 333 | 
          | 
          | 
           def RegisterParameterName(self,name):
  | 
      
      
         | 334 | 
          | 
          | 
             """
  | 
      
      
         | 335 | 
          | 
          | 
             Add the named parameter to the list of regognized symbols.\n
  | 
      
      
         | 336 | 
          | 
          | 
             Note:  Parameters do not have a body.
  | 
      
      
         | 337 | 
          | 
          | 
             """
  | 
      
      
         | 338 | 
          | 
          | 
             if self.IsSymbol(name):
  | 
      
      
         | 339 | 
          | 
          | 
               raise Exception('Program Bug -- repeated symbol name "%s"' % name);
  | 
      
      
         | 340 | 
          | 
          | 
             self.AddSymbol(name,'parameter');
  | 
      
      
         | 341 | 
          | 
          | 
          
  | 
      
      
         | 342 | 
          | 
          | 
           def RegisterMemoryLength(self,name,length):
  | 
      
      
         | 343 | 
          | 
          | 
             """
  | 
      
      
         | 344 | 
          | 
          | 
             Record the length of the specified memory.\n
  | 
      
      
         | 345 | 
          | 
          | 
             Note:  This is used to evaluate "size[name]" in "${...}" expressions.
  | 
      
      
         | 346 | 
          | 
          | 
             """
  | 
      
      
         | 347 | 
          | 
          | 
             self.memoryLength[name] = length;
  | 
      
      
         | 348 | 
          | 
          | 
          
  | 
      
      
         | 349 | 
          | 
          | 
           def RegisterStackLength(self,name,length):
  | 
      
      
         | 350 | 
          | 
          | 
             """
  | 
      
      
         | 351 | 
          | 
          | 
             Record the length of the specified stack.\n
  | 
      
      
         | 352 | 
          | 
          | 
             Note:  This is used to evaluate "size[name]" in "${...}" expressions.
  | 
      
      
         | 353 | 
          | 
          | 
             """
  | 
      
      
         | 354 | 
          | 
          | 
             self.stackLength[name] = length;
  | 
      
      
         | 355 | 
          | 
          | 
          
  | 
      
      
         | 356 | 
          | 
          | 
           ################################################################################
  | 
      
      
         | 357 | 
          | 
          | 
           #
  | 
      
      
         | 358 | 
          | 
          | 
           # Check a list of raw tokens to ensure their proper format.
  | 
      
      
         | 359 | 
          | 
          | 
           #
  | 
      
      
         | 360 | 
          | 
          | 
           ################################################################################
  | 
      
      
         | 361 | 
          | 
          | 
          
  | 
      
      
         | 362 | 
          | 
          | 
           def CheckSymbolToken(self,name,allowableTypes,loc):
  | 
      
      
         | 363 | 
          | 
          | 
             """
  | 
      
      
         | 364 | 
          | 
          | 
             Syntax check for symbols, either by themselves or as a macro argument.\n
  | 
      
      
         | 365 | 
          | 
          | 
             Note:  This is used by CheckRawTokens.
  | 
      
      
         | 366 | 
          | 
          | 
             """
  | 
      
      
         | 367 | 
          | 
          | 
             if not self.IsSymbol(name):
  | 
      
      
         | 368 | 
          | 
          | 
               raise asmDef.AsmException('Undefined symbol "%s" at %s' % (name,loc));
  | 
      
      
         | 369 | 
          | 
          | 
             ixName = self.symbols['list'].index(name);
  | 
      
      
         | 370 | 
          | 
          | 
             if self.symbols['type'][ixName] not in allowableTypes:
  | 
      
      
         | 371 | 
          | 
          | 
               raise asmDef.AsmException('Illegal symbol at %s' % loc);
  | 
      
      
         | 372 | 
          | 
          | 
          
  | 
      
      
         | 373 | 
          | 
          | 
           def CheckRawTokens(self,rawTokens):
  | 
      
      
         | 374 | 
          | 
          | 
             """
  | 
      
      
         | 375 | 
          | 
          | 
             Syntax check for directive bodies.\n
  | 
      
      
         | 376 | 
          | 
          | 
             Note:  This core-specific method is called by the top-level assembler after
  | 
      
      
         | 377 | 
          | 
          | 
                    the RawTokens method.
  | 
      
      
         | 378 | 
          | 
          | 
             """
  | 
      
      
         | 379 | 
          | 
          | 
             # Ensure the first token is a directive.
  | 
      
      
         | 380 | 
          | 
          | 
             firstToken = rawTokens[0];
  | 
      
      
         | 381 | 
          | 
          | 
             if firstToken['type'] != 'directive':
  | 
      
      
         | 382 | 
          | 
          | 
               raise Exception('Program Bug triggered at %s' % firstToken['loc']);
  | 
      
      
         | 383 | 
          | 
          | 
             # Ensure the directive bodies are not too short.
  | 
      
      
         | 384 | 
          | 
          | 
             if (firstToken['value'] in ('.main','.interrupt',)) and not (len(rawTokens) > 1):
  | 
      
      
         | 385 | 
          | 
          | 
               raise asmDef.AsmException('"%s" missing body at %s' % (firstToken['value'],firstToken['loc'],));
  | 
      
      
         | 386 | 
         3 | 
         sinclairrf | 
             if (firstToken['value'] in ('.macro',)) and not (len(rawTokens) == 2):
  | 
      
      
         | 387 | 
          | 
          | 
               raise asmDef.AsmException('body for "%s" directive must have exactly one argument at %s' % (firstToken['value'],firstToken['loc'],));
  | 
      
      
         | 388 | 
         2 | 
         sinclairrf | 
             if (firstToken['value'] in ('.constant','.function','.memory','.variable',)) and not (len(rawTokens) >= 3):
  | 
      
      
         | 389 | 
          | 
          | 
               raise asmDef.AsmException('body for "%s" directive too short at %s' % (firstToken['value'],firstToken['loc'],));
  | 
      
      
         | 390 | 
          | 
          | 
             # Ensure the main body ends in a ".jump".
  | 
      
      
         | 391 | 
          | 
          | 
             lastToken = rawTokens[-1];
  | 
      
      
         | 392 | 
          | 
          | 
             if firstToken['value'] == '.main':
  | 
      
      
         | 393 | 
          | 
          | 
               if (lastToken['type'] != 'macro') or (lastToken['value'] != '.jump'):
  | 
      
      
         | 394 | 
          | 
          | 
                 raise asmDef.AsmException('.main body does not end in ".jump" at %s' % lastToken['loc']);
  | 
      
      
         | 395 | 
          | 
          | 
             # Ensure functions and interrupts end in a ".jump" or ".return".
  | 
      
      
         | 396 | 
          | 
          | 
             if firstToken['value'] in ('.function','.interrupt',):
  | 
      
      
         | 397 | 
          | 
          | 
               if (lastToken['type'] != 'macro') or (lastToken['value'] not in ('.jump','.return',)):
  | 
      
      
         | 398 | 
          | 
          | 
                 raise asmDef.AsmException('Last entry in ".function" or ".interrupt" must be a ".jump" or ".return" at %s' % lastToken['loc']);
  | 
      
      
         | 399 | 
          | 
          | 
             # Ensure no macros and no instructions in non-"functions".
  | 
      
      
         | 400 | 
          | 
          | 
             # Byproduct:  No labels allowed in non-"functions".
  | 
      
      
         | 401 | 
          | 
          | 
             if firstToken['value'] not in ('.function','.interrupt','.main',):
  | 
      
      
         | 402 | 
          | 
          | 
               for token in rawTokens[2:]:
  | 
      
      
         | 403 | 
          | 
          | 
                 if (token['type'] == 'macro'):
  | 
      
      
         | 404 | 
          | 
          | 
                   raise asmDef.AsmException('Macro not allowed in directive at %s' % token['loc']);
  | 
      
      
         | 405 | 
          | 
          | 
                 if token['type'] == 'instruction':
  | 
      
      
         | 406 | 
          | 
          | 
                   raise asmDef.AsmException('Instruction not allowed in directive at %s' % token['loc']);
  | 
      
      
         | 407 | 
          | 
          | 
             # Ensure local labels are defined and used.
  | 
      
      
         | 408 | 
          | 
          | 
             labelDefs = list();
  | 
      
      
         | 409 | 
          | 
          | 
             for token in rawTokens:
  | 
      
      
         | 410 | 
          | 
          | 
               if token['type'] == 'label':
  | 
      
      
         | 411 | 
          | 
          | 
                 name = token['value'];
  | 
      
      
         | 412 | 
          | 
          | 
                 if name in labelDefs:
  | 
      
      
         | 413 | 
          | 
          | 
                   raise asmDef.AsmException('Repeated label definition "%s" at %s' % (name,token['loc'],));
  | 
      
      
         | 414 | 
          | 
          | 
                 labelDefs.append(name);
  | 
      
      
         | 415 | 
          | 
          | 
             labelsUsed = list();
  | 
      
      
         | 416 | 
          | 
          | 
             for token in rawTokens:
  | 
      
      
         | 417 | 
          | 
          | 
               if (token['type'] == 'macro') and (token['value'] in ('.jump','.jumpc',)):
  | 
      
      
         | 418 | 
          | 
          | 
                 target = token['argument'][0]['value'];
  | 
      
      
         | 419 | 
          | 
          | 
                 if target not in labelDefs:
  | 
      
      
         | 420 | 
          | 
          | 
                   raise asmDef.AsmException('label definition for target missing at %s' % token['loc']);
  | 
      
      
         | 421 | 
          | 
          | 
                 labelsUsed.append(target);
  | 
      
      
         | 422 | 
          | 
          | 
             labelsUnused = set(labelDefs) - set(labelsUsed);
  | 
      
      
         | 423 | 
          | 
          | 
             if labelsUnused:
  | 
      
      
         | 424 | 
          | 
          | 
               raise asmDef.AsmException('Unused label(s) %s in body %s' % (labelsUnused,firstToken['loc']));
  | 
      
      
         | 425 | 
          | 
          | 
             # Ensure referenced symbols are already defined (other than labels and
  | 
      
      
         | 426 | 
          | 
          | 
             # function names for call and jump macros).
  | 
      
      
         | 427 | 
          | 
          | 
             checkBody = False;
  | 
      
      
         | 428 | 
          | 
          | 
             if (rawTokens[0]['type'] == 'directive') and (rawTokens[0]['value'] in ('.function','.interrupt','.main',)):
  | 
      
      
         | 429 | 
          | 
          | 
               checkBody = True;
  | 
      
      
         | 430 | 
          | 
          | 
             if checkBody:
  | 
      
      
         | 431 | 
          | 
          | 
               for token in rawTokens[2:]:
  | 
      
      
         | 432 | 
          | 
          | 
                 if token['type'] == 'symbol':
  | 
      
      
         | 433 | 
          | 
          | 
                   allowableTypes = ('constant','inport','macro','outport','outstrobe','parameter','variable',);
  | 
      
      
         | 434 | 
          | 
          | 
                   self.CheckSymbolToken(token['value'],allowableTypes,token['loc']);
  | 
      
      
         | 435 | 
          | 
          | 
                 elif token['type'] == 'macro':
  | 
      
      
         | 436 | 
          | 
          | 
                   allowableTypes = ('RAM','ROM','constant','inport','outport','outstrobe','parameter','variable',);
  | 
      
      
         | 437 | 
          | 
          | 
                   ixFirst = 1 if token['value'] in self.MacrosWithSpecialFirstSymbol else 0;
  | 
      
      
         | 438 | 
          | 
          | 
                   for arg in  token['argument'][ixFirst:]:
  | 
      
      
         | 439 | 
          | 
          | 
                     if arg['type'] == 'symbol':
  | 
      
      
         | 440 | 
          | 
          | 
                       self.CheckSymbolToken(arg['value'],allowableTypes,arg['loc']);
  | 
      
      
         | 441 | 
          | 
          | 
          
  | 
      
      
         | 442 | 
          | 
          | 
           ################################################################################
  | 
      
      
         | 443 | 
          | 
          | 
           #
  | 
      
      
         | 444 | 
          | 
          | 
           # fill in symbols, etc. in the list of raw tokens.
  | 
      
      
         | 445 | 
          | 
          | 
           #
  | 
      
      
         | 446 | 
          | 
          | 
           ################################################################################
  | 
      
      
         | 447 | 
          | 
          | 
          
  | 
      
      
         | 448 | 
          | 
          | 
           def ByteList(self,rawTokens,limit=False):
  | 
      
      
         | 449 | 
          | 
          | 
             """
  | 
      
      
         | 450 | 
          | 
          | 
             Return either (1) a list comprised of a single token which may not be a
  | 
      
      
         | 451 | 
          | 
          | 
             byte or (2) a list comprised of multiple tokens, each of which is a single
  | 
      
      
         | 452 | 
          | 
          | 
             byte.\n
  | 
      
      
         | 453 | 
          | 
          | 
             Note:  This is called by FillRawTokens.
  | 
      
      
         | 454 | 
          | 
          | 
             """
  | 
      
      
         | 455 | 
          | 
          | 
             if len(rawTokens) > 1:
  | 
      
      
         | 456 | 
          | 
          | 
               limit = True;
  | 
      
      
         | 457 | 
          | 
          | 
             values = list();
  | 
      
      
         | 458 | 
          | 
          | 
             try:
  | 
      
      
         | 459 | 
          | 
          | 
               for token in rawTokens:
  | 
      
      
         | 460 | 
          | 
          | 
                 if token['type'] == 'value':
  | 
      
      
         | 461 | 
          | 
          | 
                   v = token['value'];
  | 
      
      
         | 462 | 
          | 
          | 
                   if type(v) == int:
  | 
      
      
         | 463 | 
          | 
          | 
                     if limit and not (-128 <= v < 256):
  | 
      
      
         | 464 | 
          | 
          | 
                       raise Exception('Program Bug -- unexpected out-of-range value');
  | 
      
      
         | 465 | 
          | 
          | 
                     values.append(v);
  | 
      
      
         | 466 | 
          | 
          | 
                   else:
  | 
      
      
         | 467 | 
          | 
          | 
                     for v in token['value']:
  | 
      
      
         | 468 | 
          | 
          | 
                       if not (-128 <= v < 256):
  | 
      
      
         | 469 | 
          | 
          | 
                         raise Exception('Program Bug -- unexpected out-of-range value');
  | 
      
      
         | 470 | 
          | 
          | 
                       values.append(v);
  | 
      
      
         | 471 | 
          | 
          | 
                 else:
  | 
      
      
         | 472 | 
          | 
          | 
                   raise asmDef.AsmException('Illegal token "%s" at %s:%d:%d', (token['type'],token['loc']));
  | 
      
      
         | 473 | 
          | 
          | 
             except:
  | 
      
      
         | 474 | 
          | 
          | 
               raise asmDef.AsmException('Out-of-range token "%s" at %s:%d:%d', (token['type'],token['loc']));
  | 
      
      
         | 475 | 
          | 
          | 
             return values;
  | 
      
      
         | 476 | 
          | 
          | 
          
  | 
      
      
         | 477 | 
          | 
          | 
           def ExpandSymbol(self,token,singleValue):
  | 
      
      
         | 478 | 
          | 
          | 
             """
  | 
      
      
         | 479 | 
          | 
          | 
             Convert the token for a symbol into a token for its specific type.
  | 
      
      
         | 480 | 
          | 
          | 
             Optionally ensure constants expand to a single byte.  For parameters,
  | 
      
      
         | 481 | 
          | 
          | 
             ensure that a range is provided.\n
  | 
      
      
         | 482 | 
          | 
          | 
             Note:  Symbols must be defined before the directive bodies in which they
  | 
      
      
         | 483 | 
          | 
          | 
                    are used.\n
  | 
      
      
         | 484 | 
          | 
          | 
             Note:  This is called in two spots.  The first is ExpandTokens, where
  | 
      
      
         | 485 | 
          | 
          | 
                    isolated symbols are processed, for example to get the value of a
  | 
      
      
         | 486 | 
          | 
          | 
                    constant.  The second is in EmitOptArg where symbols in arguments to
  | 
      
      
         | 487 | 
          | 
          | 
                    macros are expanded (this allows the macro-specific processing to
  | 
      
      
         | 488 | 
          | 
          | 
                    identify labels vs. symbols).
  | 
      
      
         | 489 | 
          | 
          | 
             """
  | 
      
      
         | 490 | 
          | 
          | 
             if not self.IsSymbol(token['value']):
  | 
      
      
         | 491 | 
          | 
          | 
               raise asmDef.AsmException('Symbol "%s" not in symbol list at %s' %(token['value'],token['loc'],));
  | 
      
      
         | 492 | 
          | 
          | 
             ix = self.symbols['list'].index(token['value']);
  | 
      
      
         | 493 | 
          | 
          | 
             symbolType = self.symbols['type'][ix];
  | 
      
      
         | 494 | 
          | 
          | 
             if symbolType == 'RAM':
  | 
      
      
         | 495 | 
          | 
          | 
               return dict(type='RAM', value=token['value'], loc=token['loc']);
  | 
      
      
         | 496 | 
          | 
          | 
             elif symbolType == 'ROM':
  | 
      
      
         | 497 | 
          | 
          | 
               return dict(type='ROM', value=token['value'], loc=token['loc']);
  | 
      
      
         | 498 | 
          | 
          | 
             elif symbolType == 'constant':
  | 
      
      
         | 499 | 
          | 
          | 
               if singleValue:
  | 
      
      
         | 500 | 
          | 
          | 
                 thisBody = self.symbols['body'][ix];
  | 
      
      
         | 501 | 
          | 
          | 
                 if len(thisBody) != 1:
  | 
      
      
         | 502 | 
          | 
          | 
                   raise asmDef.AsmException('Constant "%s" must evaluate to a single byte at %s' % (token['value'],token['loc'],))
  | 
      
      
         | 503 | 
          | 
          | 
                 thisBody = thisBody[0];
  | 
      
      
         | 504 | 
          | 
          | 
                 if not (-128 <= thisBody < 256):
  | 
      
      
         | 505 | 
          | 
          | 
                   raise asmDef.AsmException('Constant "%s" must be a byte value at %s' % (token['value'],token['loc'],));
  | 
      
      
         | 506 | 
          | 
          | 
               return dict(type='constant', value=token['value'], loc=token['loc']);
  | 
      
      
         | 507 | 
          | 
          | 
             elif symbolType == 'inport':
  | 
      
      
         | 508 | 
          | 
          | 
               return dict(type='inport', value=token['value'], loc=token['loc']);
  | 
      
      
         | 509 | 
          | 
          | 
             elif symbolType == 'outport':
  | 
      
      
         | 510 | 
          | 
          | 
               return dict(type='outport', value=token['value'], loc=token['loc']);
  | 
      
      
         | 511 | 
          | 
          | 
             elif symbolType == 'outstrobe':
  | 
      
      
         | 512 | 
          | 
          | 
               return dict(type='outstrobe', value=token['value'], loc=token['loc']);
  | 
      
      
         | 513 | 
          | 
          | 
             elif symbolType == 'parameter':
  | 
      
      
         | 514 | 
          | 
          | 
               if 'range' in token:
  | 
      
      
         | 515 | 
          | 
          | 
                 trange = token['range'];
  | 
      
      
         | 516 | 
          | 
          | 
               else:
  | 
      
      
         | 517 | 
          | 
          | 
                 trange = '[0+:8]';
  | 
      
      
         | 518 | 
          | 
          | 
               return dict(type='parameter', value=token['value'], range=trange, loc=token['loc']);
  | 
      
      
         | 519 | 
          | 
          | 
             elif symbolType == 'variable':
  | 
      
      
         | 520 | 
          | 
          | 
               return dict(type='variable', value=token['value'], loc=token['loc']);
  | 
      
      
         | 521 | 
          | 
          | 
             else:
  | 
      
      
         | 522 | 
          | 
          | 
               raise Exception('Program Bug -- unrecognized symbol type "%s"' % symbolType);
  | 
      
      
         | 523 | 
          | 
          | 
          
  | 
      
      
         | 524 | 
          | 
          | 
           def ExpandTokens(self,rawTokens):
  | 
      
      
         | 525 | 
          | 
          | 
             """
  | 
      
      
         | 526 | 
          | 
          | 
             Compute the relative addresses for tokens within function bodies.\n
  | 
      
      
         | 527 | 
          | 
          | 
             The return is a list of the tokens in the function body, each of which has
  | 
      
      
         | 528 | 
          | 
          | 
             a type, value, offset (relative address), and location within the source
  | 
      
      
         | 529 | 
          | 
          | 
             code.  Macro types also have the list of arguments provided to the macro.
  | 
      
      
         | 530 | 
          | 
          | 
             """
  | 
      
      
         | 531 | 
          | 
          | 
             tokens = list();
  | 
      
      
         | 532 | 
          | 
          | 
             offset = 0;
  | 
      
      
         | 533 | 
          | 
          | 
             for token in rawTokens:
  | 
      
      
         | 534 | 
          | 
          | 
               # insert labels
  | 
      
      
         | 535 | 
          | 
          | 
               if token['type'] == 'label':
  | 
      
      
         | 536 | 
          | 
          | 
                 tokens.append(dict(type=token['type'], value=token['value'], offset=offset, loc=token['loc']));
  | 
      
      
         | 537 | 
          | 
          | 
                 # labels don't change the offset
  | 
      
      
         | 538 | 
          | 
          | 
               # append instructions
  | 
      
      
         | 539 | 
          | 
          | 
               elif token['type'] == 'instruction':
  | 
      
      
         | 540 | 
          | 
          | 
                 tokens.append(dict(type=token['type'], value=token['value'], offset=offset, loc=token['loc']));
  | 
      
      
         | 541 | 
          | 
          | 
                 offset = offset + 1;
  | 
      
      
         | 542 | 
          | 
          | 
               # append values
  | 
      
      
         | 543 | 
          | 
          | 
               elif token['type'] == 'value':
  | 
      
      
         | 544 | 
          | 
          | 
                 if type(token['value']) == int:
  | 
      
      
         | 545 | 
          | 
          | 
                   tokens.append(dict(type=token['type'], value=token['value'], offset=offset, loc=token['loc']));
  | 
      
      
         | 546 | 
          | 
          | 
                   offset = offset + 1;
  | 
      
      
         | 547 | 
          | 
          | 
                 else:
  | 
      
      
         | 548 | 
          | 
          | 
                   revTokens = copy.copy(token['value']);
  | 
      
      
         | 549 | 
          | 
          | 
                   revTokens.reverse();
  | 
      
      
         | 550 | 
          | 
          | 
                   for lToken in revTokens:
  | 
      
      
         | 551 | 
          | 
          | 
                     tokens.append(dict(type=token['type'], value=lToken, offset=offset, loc=token['loc']));
  | 
      
      
         | 552 | 
          | 
          | 
                     offset = offset + 1;
  | 
      
      
         | 553 | 
          | 
          | 
               # append macros
  | 
      
      
         | 554 | 
          | 
          | 
               elif token['type'] == 'macro':
  | 
      
      
         | 555 | 
          | 
          | 
                 tokens.append(dict(type=token['type'], value=token['value'], offset=offset, argument=token['argument'], loc=token['loc']));
  | 
      
      
         | 556 | 
          | 
          | 
                 offset = offset + self.MacroLength(token);
  | 
      
      
         | 557 | 
          | 
          | 
               # interpret and append symbols
  | 
      
      
         | 558 | 
          | 
          | 
               elif token['type'] == 'symbol':
  | 
      
      
         | 559 | 
          | 
          | 
                 newToken = self.ExpandSymbol(token,singleValue=False);
  | 
      
      
         | 560 | 
          | 
          | 
                 newToken['offset'] = offset;
  | 
      
      
         | 561 | 
          | 
          | 
                 newToken['loc'] = token['loc'];
  | 
      
      
         | 562 | 
          | 
          | 
                 tokens.append(newToken);
  | 
      
      
         | 563 | 
          | 
          | 
                 if token['type'] == 'constant':
  | 
      
      
         | 564 | 
          | 
          | 
                   ix = self.symbols['list'].index(newToken['value']);
  | 
      
      
         | 565 | 
          | 
          | 
                   offset = offset + len(self.symbols['body'][ix]);
  | 
      
      
         | 566 | 
          | 
          | 
                 else:
  | 
      
      
         | 567 | 
          | 
          | 
                   offset = offset + 1;
  | 
      
      
         | 568 | 
          | 
          | 
               # anything else is a program bug
  | 
      
      
         | 569 | 
          | 
          | 
               else:
  | 
      
      
         | 570 | 
          | 
          | 
                 raise Exception('Program bug:  unexpected token type "%s"' % token['type']);
  | 
      
      
         | 571 | 
          | 
          | 
             return dict(tokens=tokens, length=offset);
  | 
      
      
         | 572 | 
          | 
          | 
          
  | 
      
      
         | 573 | 
          | 
          | 
           def FillRawTokens(self,rawTokens):
  | 
      
      
         | 574 | 
          | 
          | 
             """
  | 
      
      
         | 575 | 
          | 
          | 
             Do one of the following as required for the specified directive:
  | 
      
      
         | 576 | 
          | 
          | 
               .constant         add the constant and its body to the list of symbols
  | 
      
      
         | 577 | 
          | 
          | 
               .function         add the function and its body, along with the relative
  | 
      
      
         | 578 | 
          | 
          | 
                                 addresses, to the list of symbols
  | 
      
      
         | 579 | 
          | 
          | 
               .interrupt        record the function body and relative addresses
  | 
      
      
         | 580 | 
         3 | 
         sinclairrf | 
               .macro            register the user-defined macro
  | 
      
      
         | 581 | 
         2 | 
         sinclairrf | 
               .main             record the function body and relative addresses
  | 
      
      
         | 582 | 
          | 
          | 
               .memory           record the definition of the memory and make it current
  | 
      
      
         | 583 | 
          | 
          | 
                                 for subsequent variable definitions.
  | 
      
      
         | 584 | 
          | 
          | 
               .variable         add the variable and its associated memory, length, and
  | 
      
      
         | 585 | 
          | 
          | 
                                 initial values to the list of symbols
  | 
      
      
         | 586 | 
          | 
          | 
             """
  | 
      
      
         | 587 | 
          | 
          | 
             firstToken = rawTokens[0];
  | 
      
      
         | 588 | 
          | 
          | 
             secondToken = rawTokens[1];
  | 
      
      
         | 589 | 
          | 
          | 
             # Perform syntax check common to several directives.
  | 
      
      
         | 590 | 
          | 
          | 
             if firstToken['value'] in ('.constant','.function','.variable',):
  | 
      
      
         | 591 | 
          | 
          | 
               if secondToken['type'] != 'symbol':
  | 
      
      
         | 592 | 
          | 
          | 
                 raise asmDef.AsmException('Expected symbol, not "%s", at %s' % (secondToken['value'],secondToken['loc'],));
  | 
      
      
         | 593 | 
          | 
          | 
               if self.IsSymbol(secondToken['value']):
  | 
      
      
         | 594 | 
          | 
          | 
                 raise asmDef.AsmException('Symbol "%s" already defined at %s' % (secondToken['value'],secondToken['loc'],));
  | 
      
      
         | 595 | 
          | 
          | 
             # Perform syntax-specific processing.
  | 
      
      
         | 596 | 
          | 
          | 
             if firstToken['value'] == '.constant':
  | 
      
      
         | 597 | 
          | 
          | 
               byteList = self.ByteList(rawTokens[2:]);
  | 
      
      
         | 598 | 
          | 
          | 
               self.AddSymbol(secondToken['value'],'constant',body=byteList);
  | 
      
      
         | 599 | 
          | 
          | 
             # Process ".function" definition.
  | 
      
      
         | 600 | 
          | 
          | 
             elif firstToken['value'] == '.function':
  | 
      
      
         | 601 | 
          | 
          | 
               self.AddSymbol(secondToken['value'],'function',self.ExpandTokens(rawTokens[2:]));
  | 
      
      
         | 602 | 
          | 
          | 
             # Process ".interrupt" definition.
  | 
      
      
         | 603 | 
          | 
          | 
             elif firstToken['value'] == '.interrupt':
  | 
      
      
         | 604 | 
          | 
          | 
               if self.interrupt:
  | 
      
      
         | 605 | 
          | 
          | 
                 raise asmDef.AsmException('Second definition of ".interrupt" at %s' % firstToken['loc']);
  | 
      
      
         | 606 | 
          | 
          | 
               self.interrupt = self.ExpandTokens(rawTokens[1:]);
  | 
      
      
         | 607 | 
         3 | 
         sinclairrf | 
             # Process user-defined macros (the ".macro XXX" directive can be repeated for non-built-in macros).
  | 
      
      
         | 608 | 
          | 
          | 
             elif firstToken['value'] == '.macro':
  | 
      
      
         | 609 | 
          | 
          | 
               macroName = secondToken['value'];
  | 
      
      
         | 610 | 
          | 
          | 
               fullMacroName = '.' + macroName;
  | 
      
      
         | 611 | 
          | 
          | 
               if fullMacroName in self.directives:
  | 
      
      
         | 612 | 
          | 
          | 
                 raise asmDef.AsmException('Macro "%s" is a directive at %s' % (fullMacroName,secondToken['loc'],));
  | 
      
      
         | 613 | 
          | 
          | 
               if fullMacroName in self.instructions:
  | 
      
      
         | 614 | 
          | 
          | 
                 raise asmDef.AsmException('Macro "%s" is an instruction at %s' % (fullMacroName,secondToken['loc'],));
  | 
      
      
         | 615 | 
          | 
          | 
               if self.IsBuiltInMacro(fullMacroName):
  | 
      
      
         | 616 | 
          | 
          | 
                 raise asmDef.AsmException('Macro "%s" is a built-in macro at %s' % (fullMacroName,secondToken['loc'],));
  | 
      
      
         | 617 | 
          | 
          | 
               if fullMacroName not in self.macros['list']:
  | 
      
      
         | 618 | 
          | 
          | 
                 self.AddUserMacro(macroName);
  | 
      
      
         | 619 | 
         2 | 
         sinclairrf | 
             # Process ".main" definition.
  | 
      
      
         | 620 | 
          | 
          | 
             elif firstToken['value'] == '.main':
  | 
      
      
         | 621 | 
          | 
          | 
               if self.main:
  | 
      
      
         | 622 | 
          | 
          | 
                 raise asmDef.AsmException('Second definition of ".main" at %s' % firstToken['loc']);
  | 
      
      
         | 623 | 
          | 
          | 
               self.main = self.ExpandTokens(rawTokens[1:]);
  | 
      
      
         | 624 | 
          | 
          | 
             # Process ".memory" declaration.
  | 
      
      
         | 625 | 
          | 
          | 
             elif firstToken['value'] == '.memory':
  | 
      
      
         | 626 | 
          | 
          | 
               if len(rawTokens) != 3:
  | 
      
      
         | 627 | 
          | 
          | 
                 raise asmDef.AsmException('".memory" directive requires exactly two arguments at %s' % firstToken['loc']);
  | 
      
      
         | 628 | 
          | 
          | 
               if (secondToken['type'] != 'symbol') or (secondToken['value'] not in ('RAM','ROM',)):
  | 
      
      
         | 629 | 
          | 
          | 
                 raise asmDef.AsmException('First argument to ".memory" directive must be "RAM" or "RAM" at %s' % secondToken['loc']);
  | 
      
      
         | 630 | 
          | 
          | 
               thirdToken = rawTokens[2];
  | 
      
      
         | 631 | 
          | 
          | 
               if thirdToken['type'] != 'symbol':
  | 
      
      
         | 632 | 
          | 
          | 
                 raise asmDef.AsmException('".memory" directive requires name for second argument at %s' % thirdToken['loc']);
  | 
      
      
         | 633 | 
          | 
          | 
               if self.IsSymbol(thirdToken['value']):
  | 
      
      
         | 634 | 
          | 
          | 
                 ix = self.symbols['list'].index(thirdToken['value']);
  | 
      
      
         | 635 | 
          | 
          | 
                 if self.symbols['type'] != secondToken['value']:
  | 
      
      
         | 636 | 
          | 
          | 
                   raise asmDef.AsmException('Redefinition of ".memory %s %s" not allowed at %s' % (secondToken['value'],thirdToken['value'],firstToken['loc']));
  | 
      
      
         | 637 | 
          | 
          | 
               else:
  | 
      
      
         | 638 | 
          | 
          | 
                 self.AddSymbol(thirdToken['value'],secondToken['value'],dict(length=0));
  | 
      
      
         | 639 | 
          | 
          | 
               self.currentMemory = thirdToken['value'];
  | 
      
      
         | 640 | 
          | 
          | 
             # Process ".variable" declaration.
  | 
      
      
         | 641 | 
          | 
          | 
             elif firstToken['value'] == '.variable':
  | 
      
      
         | 642 | 
          | 
          | 
               if not self.currentMemory:
  | 
      
      
         | 643 | 
          | 
          | 
                 raise asmDef.AsmException('".memory" directive required before ".variable" directive at %s' % firstToken['line']);
  | 
      
      
         | 644 | 
          | 
          | 
               ixMem = self.symbols['list'].index(self.currentMemory);
  | 
      
      
         | 645 | 
          | 
          | 
               currentMemoryBody = self.symbols['body'][ixMem];
  | 
      
      
         | 646 | 
          | 
          | 
               byteList = self.ByteList(rawTokens[2:],limit=True);
  | 
      
      
         | 647 | 
          | 
          | 
               body = dict(memory=self.currentMemory, start=currentMemoryBody['length'], value=byteList);
  | 
      
      
         | 648 | 
          | 
          | 
               self.AddSymbol(secondToken['value'], 'variable', body=body);
  | 
      
      
         | 649 | 
          | 
          | 
               currentMemoryBody['length'] = currentMemoryBody['length'] + len(byteList);
  | 
      
      
         | 650 | 
          | 
          | 
               if currentMemoryBody['length'] > 256:
  | 
      
      
         | 651 | 
          | 
          | 
                 raise asmDef.AsmException('Memory "%s" becomes too long at %s' % (self.currentMemory,firstToken['loc']));
  | 
      
      
         | 652 | 
          | 
          | 
             # Everything else is an error.
  | 
      
      
         | 653 | 
          | 
          | 
             else:
  | 
      
      
         | 654 | 
          | 
          | 
               raise Exception('Program Bug:  Unrecognized directive %s at %s' % (firstToken['value'],firstToken['loc']));
  | 
      
      
         | 655 | 
          | 
          | 
          
  | 
      
      
         | 656 | 
          | 
          | 
           def Main(self):
  | 
      
      
         | 657 | 
          | 
          | 
             """
  | 
      
      
         | 658 | 
          | 
          | 
             Return the body of the .main function.
  | 
      
      
         | 659 | 
          | 
          | 
             Note:  This is used by the top-level assembler to verify that the .main
  | 
      
      
         | 660 | 
          | 
          | 
                    function has been defined.
  | 
      
      
         | 661 | 
          | 
          | 
             """
  | 
      
      
         | 662 | 
          | 
          | 
             return self.main;
  | 
      
      
         | 663 | 
          | 
          | 
          
  | 
      
      
         | 664 | 
          | 
          | 
           def Interrupt(self):
  | 
      
      
         | 665 | 
          | 
          | 
             """
  | 
      
      
         | 666 | 
          | 
          | 
             Return the body of the .interrupt function.
  | 
      
      
         | 667 | 
          | 
          | 
             Note:  This is used by the top-level assembler to verify that the .interrupt
  | 
      
      
         | 668 | 
          | 
          | 
                    function has or has not been defined.
  | 
      
      
         | 669 | 
          | 
          | 
             """
  | 
      
      
         | 670 | 
          | 
          | 
             return self.interrupt;
  | 
      
      
         | 671 | 
          | 
          | 
          
  | 
      
      
         | 672 | 
          | 
          | 
           ################################################################################
  | 
      
      
         | 673 | 
          | 
          | 
           #
  | 
      
      
         | 674 | 
          | 
          | 
           # Compute the memory bank indices.
  | 
      
      
         | 675 | 
          | 
          | 
           #
  | 
      
      
         | 676 | 
          | 
          | 
           ################################################################################
  | 
      
      
         | 677 | 
          | 
          | 
          
  | 
      
      
         | 678 | 
          | 
          | 
           def EvaluateMemoryTree(self):
  | 
      
      
         | 679 | 
          | 
          | 
             """
  | 
      
      
         | 680 | 
          | 
          | 
             Ensure defined memories are used.  Add the memory name, type, and length to
  | 
      
      
         | 681 | 
          | 
          | 
             the list of memories.  Compute the bank index ascending from 0 for RAMs and
  | 
      
      
         | 682 | 
          | 
          | 
             descending from 3 for ROMs and add that index to the memory attributes.
  | 
      
      
         | 683 | 
          | 
          | 
             Ensure that no more than 4 memories are listed.
  | 
      
      
         | 684 | 
          | 
          | 
             """
  | 
      
      
         | 685 | 
          | 
          | 
             self.memories = dict(list=list(), type=list(), length=list(), bank=list());
  | 
      
      
         | 686 | 
          | 
          | 
             ramBank = 0;
  | 
      
      
         | 687 | 
          | 
          | 
             romBank = 3;
  | 
      
      
         | 688 | 
          | 
          | 
             for ix in range(len(self.symbols['list'])):
  | 
      
      
         | 689 | 
          | 
          | 
               if self.symbols['type'][ix] in ('RAM','ROM',):
  | 
      
      
         | 690 | 
          | 
          | 
                 memBody = self.symbols['body'][ix];
  | 
      
      
         | 691 | 
          | 
          | 
                 if memBody['length'] == 0:
  | 
      
      
         | 692 | 
          | 
          | 
                   raise asmDef.AsmException('Empty memory:  %s' % self.symbols['list'][ix]);
  | 
      
      
         | 693 | 
          | 
          | 
                 self.memories['list'].append(self.symbols['list'][ix]);
  | 
      
      
         | 694 | 
          | 
          | 
                 self.memories['type'].append(self.symbols['type'][ix]);
  | 
      
      
         | 695 | 
          | 
          | 
                 self.memories['length'].append(memBody['length']);
  | 
      
      
         | 696 | 
          | 
          | 
                 if self.symbols['type'][ix] == 'RAM':
  | 
      
      
         | 697 | 
          | 
          | 
                   self.memories['bank'].append(ramBank);
  | 
      
      
         | 698 | 
          | 
          | 
                   ramBank = ramBank + 1;
  | 
      
      
         | 699 | 
          | 
          | 
                 else:
  | 
      
      
         | 700 | 
          | 
          | 
                   self.memories['bank'].append(romBank);
  | 
      
      
         | 701 | 
          | 
          | 
                   romBank = romBank - 1;
  | 
      
      
         | 702 | 
          | 
          | 
             if len(self.memories['list']) > 4:
  | 
      
      
         | 703 | 
          | 
          | 
               raise asmDef.AsmException('Too many memory banks');
  | 
      
      
         | 704 | 
          | 
          | 
          
  | 
      
      
         | 705 | 
          | 
          | 
           ################################################################################
  | 
      
      
         | 706 | 
          | 
          | 
           #
  | 
      
      
         | 707 | 
          | 
          | 
           # Generate the list of required functions from the ".main" and ".interrupt"
  | 
      
      
         | 708 | 
          | 
          | 
           # bodies.
  | 
      
      
         | 709 | 
          | 
          | 
           #
  | 
      
      
         | 710 | 
          | 
          | 
           # Look for function calls with the bodies of the required functions.  If the
  | 
      
      
         | 711 | 
          | 
          | 
           # function has not already been identified as a required function then (1)
  | 
      
      
         | 712 | 
          | 
          | 
           # ensure it exists and is a function and then (2) add it to the list of
  | 
      
      
         | 713 | 
          | 
          | 
           # required functions.
  | 
      
      
         | 714 | 
          | 
          | 
           #
  | 
      
      
         | 715 | 
          | 
          | 
           # Whenever a function is added to the list, set its start address and get its
  | 
      
      
         | 716 | 
          | 
          | 
           # length.
  | 
      
      
         | 717 | 
          | 
          | 
           #
  | 
      
      
         | 718 | 
          | 
          | 
           ################################################################################
  | 
      
      
         | 719 | 
          | 
          | 
          
  | 
      
      
         | 720 | 
          | 
          | 
           def EvaluateFunctionTree(self):
  | 
      
      
         | 721 | 
          | 
          | 
             """
  | 
      
      
         | 722 | 
          | 
          | 
             Create a list of the functions required by the program, starting with the
  | 
      
      
         | 723 | 
          | 
          | 
             required .main function and the optional .interrupt function.\n
  | 
      
      
         | 724 | 
          | 
          | 
             Record the length of each function, its body, and its start address and
  | 
      
      
         | 725 | 
          | 
          | 
             calculate the addresses of the labels within each function body.\n
  | 
      
      
         | 726 | 
          | 
          | 
             Finally, ensure the function address space does not exceed the absolute
  | 
      
      
         | 727 | 
          | 
          | 
             8192 address limit.
  | 
      
      
         | 728 | 
          | 
          | 
             """
  | 
      
      
         | 729 | 
          | 
          | 
             self.functionEvaluation = dict(list=list(), length=list(), body=list(), address=list());
  | 
      
      
         | 730 | 
          | 
          | 
             nextStart = 0;
  | 
      
      
         | 731 | 
          | 
          | 
             # ".main" is always required.
  | 
      
      
         | 732 | 
          | 
          | 
             self.functionEvaluation['list'].append('.main');
  | 
      
      
         | 733 | 
          | 
          | 
             self.functionEvaluation['length'].append(self.main['length']);
  | 
      
      
         | 734 | 
          | 
          | 
             self.functionEvaluation['body'].append(self.main['tokens']);
  | 
      
      
         | 735 | 
          | 
          | 
             self.functionEvaluation['address'].append(nextStart);
  | 
      
      
         | 736 | 
          | 
          | 
             nextStart = nextStart + self.functionEvaluation['length'][-1];
  | 
      
      
         | 737 | 
          | 
          | 
             # ".interrupt" is optionally required (and is sure to exist by this function
  | 
      
      
         | 738 | 
          | 
          | 
             # call if it is required).
  | 
      
      
         | 739 | 
          | 
          | 
             if self.interrupt:
  | 
      
      
         | 740 | 
          | 
          | 
               self.functionEvaluation['list'].append('.interrupt');
  | 
      
      
         | 741 | 
          | 
          | 
               self.functionEvaluation['length'].append(self.interrupt['length']);
  | 
      
      
         | 742 | 
          | 
          | 
               self.functionEvaluation['body'].append(self.interrupt['tokens']);
  | 
      
      
         | 743 | 
          | 
          | 
               self.functionEvaluation['address'].append(nextStart);
  | 
      
      
         | 744 | 
          | 
          | 
               nextStart = nextStart + self.functionEvaluation['length'][-1];
  | 
      
      
         | 745 | 
          | 
          | 
             # Loop through the required function bodies as they are identified.
  | 
      
      
         | 746 | 
          | 
          | 
             ix = 0;
  | 
      
      
         | 747 | 
          | 
          | 
             while ix < len(self.functionEvaluation['body']):
  | 
      
      
         | 748 | 
          | 
          | 
               for token in self.functionEvaluation['body'][ix]:
  | 
      
      
         | 749 | 
          | 
          | 
                 if (token['type'] == 'macro') and (token['value'] in ('.call','.callc',)):
  | 
      
      
         | 750 | 
          | 
          | 
                   callName = token['argument'][0]['value'];
  | 
      
      
         | 751 | 
          | 
          | 
                   if callName not in self.functionEvaluation['list']:
  | 
      
      
         | 752 | 
          | 
          | 
                     if not self.IsSymbol(callName):
  | 
      
      
         | 753 | 
          | 
          | 
                       raise asmDef.AsmException('Function "%s" not defined for function "%s"' % (callName,self.functionEvaluation['list'][ix],));
  | 
      
      
         | 754 | 
          | 
          | 
                     ixName = self.symbols['list'].index(callName);
  | 
      
      
         | 755 | 
          | 
          | 
                     if self.symbols['type'][ixName] != 'function':
  | 
      
      
         | 756 | 
          | 
          | 
                       raise asmDef.AsmException('Function "%s" called by "%s" is not a function', (callName, self.functionEvaluation['list'][ix],));
  | 
      
      
         | 757 | 
          | 
          | 
                     self.functionEvaluation['list'].append(callName);
  | 
      
      
         | 758 | 
          | 
          | 
                     self.functionEvaluation['length'].append(self.symbols['body'][ixName]['length']);
  | 
      
      
         | 759 | 
          | 
          | 
                     self.functionEvaluation['body'].append(self.symbols['body'][ixName]['tokens']);
  | 
      
      
         | 760 | 
          | 
          | 
                     self.functionEvaluation['address'].append(nextStart);
  | 
      
      
         | 761 | 
          | 
          | 
                     nextStart = nextStart + self.functionEvaluation['length'][-1];
  | 
      
      
         | 762 | 
          | 
          | 
               ix = ix + 1;
  | 
      
      
         | 763 | 
          | 
          | 
             # Within each function, compute the list of label addresses and then fill in
  | 
      
      
         | 764 | 
          | 
          | 
             # the address for all jumps and calls.
  | 
      
      
         | 765 | 
          | 
          | 
             for ix in range(len(self.functionEvaluation['list'])):
  | 
      
      
         | 766 | 
          | 
          | 
               startAddress = self.functionEvaluation['address'][ix];
  | 
      
      
         | 767 | 
          | 
          | 
               labelAddress = dict(list=list(), address=list());
  | 
      
      
         | 768 | 
          | 
          | 
               for token in self.functionEvaluation['body'][ix]:
  | 
      
      
         | 769 | 
          | 
          | 
                 if token['type'] == 'label':
  | 
      
      
         | 770 | 
          | 
          | 
                   labelAddress['list'].append(token['value']);
  | 
      
      
         | 771 | 
          | 
          | 
                   labelAddress['address'].append(startAddress + token['offset']);
  | 
      
      
         | 772 | 
          | 
          | 
               for token in self.functionEvaluation['body'][ix]:
  | 
      
      
         | 773 | 
          | 
          | 
                 if token['type'] != 'macro':
  | 
      
      
         | 774 | 
          | 
          | 
                   continue;
  | 
      
      
         | 775 | 
          | 
          | 
                 if token['value'] in ('.jump','.jumpc',):
  | 
      
      
         | 776 | 
          | 
          | 
                   ix = labelAddress['list'].index(token['argument'][0]['value']);
  | 
      
      
         | 777 | 
          | 
          | 
                   token['address'] = labelAddress['address'][ix];
  | 
      
      
         | 778 | 
          | 
          | 
                 elif token['value'] in ('.call','.callc',):
  | 
      
      
         | 779 | 
          | 
          | 
                   ix = self.functionEvaluation['list'].index(token['argument'][0]['value']);
  | 
      
      
         | 780 | 
          | 
          | 
                   token['address'] = self.functionEvaluation['address'][ix];
  | 
      
      
         | 781 | 
          | 
          | 
             # Sanity checks for address range
  | 
      
      
         | 782 | 
          | 
          | 
             if self.functionEvaluation['address'][-1] + self.functionEvaluation['length'][-1] >= 2**13:
  | 
      
      
         | 783 | 
          | 
          | 
               raise asmDef.AsmException('Max address for program requires more than 13 bits');
  | 
      
      
         | 784 | 
          | 
          | 
          
  | 
      
      
         | 785 | 
          | 
          | 
           ################################################################################
  | 
      
      
         | 786 | 
          | 
          | 
           #
  | 
      
      
         | 787 | 
          | 
          | 
           # Emit the meta code for the memories.
  | 
      
      
         | 788 | 
          | 
          | 
           #
  | 
      
      
         | 789 | 
          | 
          | 
           ################################################################################
  | 
      
      
         | 790 | 
          | 
          | 
          
  | 
      
      
         | 791 | 
          | 
          | 
           def EmitMemories(self,fp):
  | 
      
      
         | 792 | 
          | 
          | 
             """
  | 
      
      
         | 793 | 
          | 
          | 
             Print the memories to the metacode file.\n
  | 
      
      
         | 794 | 
          | 
          | 
             The first line for each memory has the format
  | 
      
      
         | 795 | 
          | 
          | 
               :memory type mem_name bank length
  | 
      
      
         | 796 | 
          | 
          | 
             where
  | 
      
      
         | 797 | 
          | 
          | 
               type              is RAM or ROM
  | 
      
      
         | 798 | 
          | 
          | 
               mem_name          is the name of the memory
  | 
      
      
         | 799 | 
          | 
          | 
               bank              is the assigned bank address
  | 
      
      
         | 800 | 
          | 
          | 
               length            is the number of bytes used by the memory\n
  | 
      
      
         | 801 | 
          | 
          | 
             The subsequent lines are sequences of
  | 
      
      
         | 802 | 
          | 
          | 
               - variable_name
  | 
      
      
         | 803 | 
          | 
          | 
               value(s)
  | 
      
      
         | 804 | 
          | 
          | 
             where
  | 
      
      
         | 805 | 
          | 
          | 
               '-'               indicates a variable name is present
  | 
      
      
         | 806 | 
          | 
          | 
               variable_name     is the name of the variable
  | 
      
      
         | 807 | 
          | 
          | 
               values(s)         is one or more lines for the values with one byte per line
  | 
      
      
         | 808 | 
          | 
          | 
                                 Note:  because the lines with variable names start with
  | 
      
      
         | 809 | 
          | 
          | 
                                        '-', negative values are converted to unsigned
  | 
      
      
         | 810 | 
          | 
          | 
                                        values\n
  | 
      
      
         | 811 | 
          | 
          | 
             """
  | 
      
      
         | 812 | 
          | 
          | 
             # Emit the individual memories.
  | 
      
      
         | 813 | 
          | 
          | 
             for ixMem in range(len(self.memories['list'])):
  | 
      
      
         | 814 | 
          | 
          | 
               fp.write(':memory %s %s %d %d\n' % (self.memories['type'][ixMem],self.memories['list'][ixMem],self.memories['bank'][ixMem],self.memories['length'][ixMem]));
  | 
      
      
         | 815 | 
          | 
          | 
               memName = self.memories['list'][ixMem];
  | 
      
      
         | 816 | 
          | 
          | 
               address = 0;
  | 
      
      
         | 817 | 
          | 
          | 
               for ixSymbol in range(len(self.symbols['list'])):
  | 
      
      
         | 818 | 
          | 
          | 
                 if self.symbols['type'][ixSymbol] != 'variable':
  | 
      
      
         | 819 | 
          | 
          | 
                   continue;
  | 
      
      
         | 820 | 
          | 
          | 
                 vBody = self.symbols['body'][ixSymbol];
  | 
      
      
         | 821 | 
          | 
          | 
                 if vBody['memory'] != memName:
  | 
      
      
         | 822 | 
          | 
          | 
                   continue;
  | 
      
      
         | 823 | 
          | 
          | 
                 fp.write('- %s\n' % self.symbols['list'][ixSymbol]);
  | 
      
      
         | 824 | 
          | 
          | 
                 for v in vBody['value']:
  | 
      
      
         | 825 | 
          | 
          | 
                   if not (-128 <=v < 256):
  | 
      
      
         | 826 | 
          | 
          | 
                     raise Exception('Program Bug -- value not representable by a byte');
  | 
      
      
         | 827 | 
          | 
          | 
                   fp.write('%02X\n' % (v % 0x100,));
  | 
      
      
         | 828 | 
          | 
          | 
               fp.write('\n');
  | 
      
      
         | 829 | 
          | 
          | 
          
  | 
      
      
         | 830 | 
          | 
          | 
           ################################################################################
  | 
      
      
         | 831 | 
          | 
          | 
           #
  | 
      
      
         | 832 | 
          | 
          | 
           # Emit the metacode for the program.
  | 
      
      
         | 833 | 
          | 
          | 
           #
  | 
      
      
         | 834 | 
          | 
          | 
           ################################################################################
  | 
      
      
         | 835 | 
          | 
          | 
          
  | 
      
      
         | 836 | 
          | 
          | 
           #
  | 
      
      
         | 837 | 
          | 
          | 
           # Utilities for building opcodes or the associated description strings.
  | 
      
      
         | 838 | 
          | 
          | 
           #
  | 
      
      
         | 839 | 
          | 
          | 
           # Note:  These utilities do not write to the metacode file.
  | 
      
      
         | 840 | 
          | 
          | 
           #
  | 
      
      
         | 841 | 
          | 
          | 
          
  | 
      
      
         | 842 | 
          | 
          | 
           def Emit_AddLabel(self,name):
  | 
      
      
         | 843 | 
          | 
          | 
             """
  | 
      
      
         | 844 | 
          | 
          | 
             Append the label to the labels associated with the current program address.
  | 
      
      
         | 845 | 
          | 
          | 
             """
  | 
      
      
         | 846 | 
          | 
          | 
             self.emitLabelList += ':' + name + ' ';
  | 
      
      
         | 847 | 
          | 
          | 
          
  | 
      
      
         | 848 | 
          | 
          | 
           def Emit_EvalSingleValue(self,token):
  | 
      
      
         | 849 | 
          | 
          | 
             """
  | 
      
      
         | 850 | 
          | 
          | 
             Evaluate the optional single-byte value for a macro.
  | 
      
      
         | 851 | 
          | 
          | 
             """
  | 
      
      
         | 852 | 
          | 
          | 
             if token['type'] == 'symbol':
  | 
      
      
         | 853 | 
          | 
          | 
               token = self.ExpandSymbol(token,singleValue=True);
  | 
      
      
         | 854 | 
          | 
          | 
             if token['type'] == 'constant':
  | 
      
      
         | 855 | 
          | 
          | 
               name = token['value'];
  | 
      
      
         | 856 | 
          | 
          | 
               if not self.IsSymbol(name):
  | 
      
      
         | 857 | 
          | 
          | 
                 raise Exception('Program Bug');
  | 
      
      
         | 858 | 
          | 
          | 
               ix = self.symbols['list'].index(name);
  | 
      
      
         | 859 | 
          | 
          | 
               if len(self.symbols['body'][ix]) != 1:
  | 
      
      
         | 860 | 
          | 
          | 
                 raise asmDef.AsmException('Optional constant can only be one byte at %s' % token['loc']);
  | 
      
      
         | 861 | 
          | 
          | 
               return self.symbols['body'][ix][0]
  | 
      
      
         | 862 | 
          | 
          | 
             elif token['type'] == 'value':
  | 
      
      
         | 863 | 
          | 
          | 
               return token['value']
  | 
      
      
         | 864 | 
          | 
          | 
             else:
  | 
      
      
         | 865 | 
          | 
          | 
               raise asmDef.AsmException('Unrecognized optional argument "%s"' % token['value']);
  | 
      
      
         | 866 | 
          | 
          | 
          
  | 
      
      
         | 867 | 
          | 
          | 
           def Emit_GetAddrAndBank(self,name):
  | 
      
      
         | 868 | 
          | 
          | 
             """
  | 
      
      
         | 869 | 
          | 
          | 
             For the specified variable, return an ordered tuple of the memory address
  | 
      
      
         | 870 | 
          | 
          | 
             within its bank, the corresponding bank index, and the corresponding bank
  | 
      
      
         | 871 | 
          | 
          | 
             name.\n
  | 
      
      
         | 872 | 
         3 | 
         sinclairrf | 
             Note:  This is used by several user-defined macros that fetch from or store
  | 
      
      
         | 873 | 
          | 
          | 
                    to variables.
  | 
      
      
         | 874 | 
         2 | 
         sinclairrf | 
             """
  | 
      
      
         | 875 | 
          | 
          | 
             if not self.IsSymbol(name):
  | 
      
      
         | 876 | 
          | 
          | 
               raise asmDef.AsmException('"%s" is not a recognized symbol' % name);
  | 
      
      
         | 877 | 
          | 
          | 
             ixName = self.symbols['list'].index(name);
  | 
      
      
         | 878 | 
          | 
          | 
             if self.symbols['type'][ixName] != 'variable':
  | 
      
      
         | 879 | 
          | 
          | 
               raise asmDef.AsmException('"%s" is not a variable' % name);
  | 
      
      
         | 880 | 
          | 
          | 
             body = self.symbols['body'][ixName];
  | 
      
      
         | 881 | 
          | 
          | 
             bankName = body['memory'];
  | 
      
      
         | 882 | 
          | 
          | 
             ixMem = self.memories['list'].index(bankName);
  | 
      
      
         | 883 | 
          | 
          | 
             return (body['start'],self.memories['bank'][ixMem],bankName,);
  | 
      
      
         | 884 | 
          | 
          | 
          
  | 
      
      
         | 885 | 
          | 
          | 
           def Emit_GetBank(self,name):
  | 
      
      
         | 886 | 
          | 
          | 
             """
  | 
      
      
         | 887 | 
          | 
          | 
             For the specified variable, return the memory bank index.\n
  | 
      
      
         | 888 | 
         3 | 
         sinclairrf | 
             Note:  This is used by the .fetch, .fetch+, .fetch-, .store, .store+, and
  | 
      
      
         | 889 | 
         2 | 
         sinclairrf | 
                    .store- macros.
  | 
      
      
         | 890 | 
          | 
          | 
             """
  | 
      
      
         | 891 | 
          | 
          | 
             if name not in self.memories['list']:
  | 
      
      
         | 892 | 
          | 
          | 
               raise asmDef.AsmException('"%s" not a memory' % name);
  | 
      
      
         | 893 | 
          | 
          | 
             ixMem = self.memories['list'].index(name);
  | 
      
      
         | 894 | 
          | 
          | 
             return self.memories['bank'][ixMem];
  | 
      
      
         | 895 | 
          | 
          | 
          
  | 
      
      
         | 896 | 
          | 
          | 
           def Emit_String(self,name=''):
  | 
      
      
         | 897 | 
          | 
          | 
             """
  | 
      
      
         | 898 | 
          | 
          | 
             Append the specified string to the list of labels for the current
  | 
      
      
         | 899 | 
          | 
          | 
             instruction, restart the list of labels, and return the composite string.
  | 
      
      
         | 900 | 
          | 
          | 
             """
  | 
      
      
         | 901 | 
          | 
          | 
             name = self.emitLabelList + name;
  | 
      
      
         | 902 | 
          | 
          | 
             self.emitLabelList = '';
  | 
      
      
         | 903 | 
          | 
          | 
             return name;
  | 
      
      
         | 904 | 
          | 
          | 
          
  | 
      
      
         | 905 | 
         4 | 
         sinclairrf | 
           def Emit_IntegerValue(self,token):
  | 
      
      
         | 906 | 
          | 
          | 
             """
  | 
      
      
         | 907 | 
          | 
          | 
             Return the integer value associated with a constant or a numeric expression.
  | 
      
      
         | 908 | 
          | 
          | 
             """
  | 
      
      
         | 909 | 
          | 
          | 
             if token['type'] == 'value':
  | 
      
      
         | 910 | 
          | 
          | 
               v = token['value'];
  | 
      
      
         | 911 | 
          | 
          | 
             elif token['type'] == 'symbol':
  | 
      
      
         | 912 | 
          | 
          | 
               name = token['value'];
  | 
      
      
         | 913 | 
          | 
          | 
               if not self.IsSymbol(name):
  | 
      
      
         | 914 | 
          | 
          | 
                 raise asmDef.AsmException('Symbol "%s" not recognized at %s' % (token['value'],token['loc'],));
  | 
      
      
         | 915 | 
          | 
          | 
               ix = self.symbols['list'].index(name);
  | 
      
      
         | 916 | 
          | 
          | 
               v = self.symbols['body'][ix];
  | 
      
      
         | 917 | 
          | 
          | 
               if len(v) != 1:
  | 
      
      
         | 918 | 
          | 
          | 
                 raise asmDef.AsmException('Argument can only be one value at %s' % token['loc']);
  | 
      
      
         | 919 | 
          | 
          | 
               v = v[0];
  | 
      
      
         | 920 | 
          | 
          | 
             else:
  | 
      
      
         | 921 | 
          | 
          | 
               raise asmDef.AsmException('Argument "%s" of type "%s" not recognized at %s' % (token['value'],token['type'],token['loc'],));
  | 
      
      
         | 922 | 
          | 
          | 
             if type(v) != int:
  | 
      
      
         | 923 | 
          | 
          | 
               raise Exception('Program Bug -- value should be an "int"');
  | 
      
      
         | 924 | 
          | 
          | 
             return v;
  | 
      
      
         | 925 | 
          | 
          | 
          
  | 
      
      
         | 926 | 
         2 | 
         sinclairrf | 
           #
  | 
      
      
         | 927 | 
          | 
          | 
           # Utilities to write single instructions to the metacode file.
  | 
      
      
         | 928 | 
          | 
          | 
           #
  | 
      
      
         | 929 | 
          | 
          | 
           # Note:  Other than the program header and the function names, these
  | 
      
      
         | 930 | 
          | 
          | 
           #        utilities write the function bodies.
  | 
      
      
         | 931 | 
          | 
          | 
           #
  | 
      
      
         | 932 | 
          | 
          | 
          
  | 
      
      
         | 933 | 
          | 
          | 
           def EmitOpcode(self,fp,opcode,name):
  | 
      
      
         | 934 | 
          | 
          | 
             """
  | 
      
      
         | 935 | 
          | 
          | 
             Write the specified opcode and the associated comment string.\n
  | 
      
      
         | 936 | 
          | 
          | 
             The leading bit for an opcode is always a '0'.
  | 
      
      
         | 937 | 
          | 
          | 
             """
  | 
      
      
         | 938 | 
          | 
          | 
             if not (0 <= opcode < 256):
  | 
      
      
         | 939 | 
          | 
          | 
               raise Exception('Program Bug -- opcode "0x%X" out of range');
  | 
      
      
         | 940 | 
          | 
          | 
             fp.write('0%02X %s\n' % (opcode,self.Emit_String(name)));
  | 
      
      
         | 941 | 
          | 
          | 
          
  | 
      
      
         | 942 | 
          | 
          | 
           def EmitParameter(self,fp,token):
  | 
      
      
         | 943 | 
          | 
          | 
             """
  | 
      
      
         | 944 | 
          | 
          | 
             Write the name (and range) of the specified parameter and the optional
  | 
      
      
         | 945 | 
          | 
          | 
             associated comment string.\n
  | 
      
      
         | 946 | 
          | 
          | 
             The string 'p' specifies that the parameter is to be inserted into the
  | 
      
      
         | 947 | 
          | 
          | 
             instruction body.\n
  | 
      
      
         | 948 | 
          | 
          | 
             Note:  The comment string may be the empty string if there were no labels
  | 
      
      
         | 949 | 
          | 
          | 
                    immediately preceding the parameter.
  | 
      
      
         | 950 | 
          | 
          | 
             """
  | 
      
      
         | 951 | 
          | 
          | 
             name = token['value'];
  | 
      
      
         | 952 | 
          | 
          | 
             if not self.IsParameter(name):
  | 
      
      
         | 953 | 
          | 
          | 
               raise Exception('Program Bug');
  | 
      
      
         | 954 | 
          | 
          | 
             commentString = self.Emit_String();
  | 
      
      
         | 955 | 
          | 
          | 
             if commentString:
  | 
      
      
         | 956 | 
          | 
          | 
               fp.write('p %s%s %s\n' % (name,token['range'],commentString,));
  | 
      
      
         | 957 | 
          | 
          | 
             else:
  | 
      
      
         | 958 | 
          | 
          | 
               fp.write('p %s%s\n' % (name,token['range'],));
  | 
      
      
         | 959 | 
          | 
          | 
          
  | 
      
      
         | 960 | 
          | 
          | 
           def EmitPush(self,fp,value,name=None,tokenLoc=None):
  | 
      
      
         | 961 | 
          | 
          | 
             """
  | 
      
      
         | 962 | 
          | 
          | 
             Write the opcode to push a value onto the data stack.  Include the comment
  | 
      
      
         | 963 | 
          | 
          | 
             string including either the optionally provided symbol name or a printable
  | 
      
      
         | 964 | 
          | 
          | 
             representation of the value being pushed onto the stack.\n
  | 
      
      
         | 965 | 
          | 
          | 
             Note:  The printable value is included when a name is not provided so that
  | 
      
      
         | 966 | 
          | 
          | 
                    the contents of single characters or of strings being pushed onto
  | 
      
      
         | 967 | 
          | 
          | 
                    the stack can be read.\n
  | 
      
      
         | 968 | 
          | 
          | 
             Note:  The token location is an optional input required when the range of
  | 
      
      
         | 969 | 
          | 
          | 
                    the provided value may not have been previously ensured to fit in
  | 
      
      
         | 970 | 
          | 
          | 
                    one byte.
  | 
      
      
         | 971 | 
          | 
          | 
             """
  | 
      
      
         | 972 | 
          | 
          | 
             if not (-128 <= value < 256):
  | 
      
      
         | 973 | 
          | 
          | 
               if tokenLoc == None:
  | 
      
      
         | 974 | 
          | 
          | 
                 raise Exception('Program Bug -- untrapped out-of-range token "%s"' % value);
  | 
      
      
         | 975 | 
          | 
          | 
               else:
  | 
      
      
         | 976 | 
          | 
          | 
                 raise asmDef.AsmException('Value not representable by a byte at "%s"' % tokenLoc);
  | 
      
      
         | 977 | 
          | 
          | 
             if value < 0:
  | 
      
      
         | 978 | 
          | 
          | 
               value = value + 256;
  | 
      
      
         | 979 | 
          | 
          | 
             if type(name) == str:
  | 
      
      
         | 980 | 
          | 
          | 
               fp.write('1%02X %s\n' % ((value % 0x100),self.Emit_String(name)));
  | 
      
      
         | 981 | 
          | 
          | 
             elif (chr(value) in string.printable) and (chr(value) not in string.whitespace):
  | 
      
      
         | 982 | 
          | 
          | 
               fp.write('1%02X %s\n' % ((value % 0x100),self.Emit_String('%02X \'%c\'' % (value,value,))));
  | 
      
      
         | 983 | 
          | 
          | 
             else:
  | 
      
      
         | 984 | 
          | 
          | 
               fp.write('1%02X %s\n' % ((value % 0x100),self.Emit_String('0x%02X' % value)));
  | 
      
      
         | 985 | 
          | 
          | 
          
  | 
      
      
         | 986 | 
          | 
          | 
           def EmitVariable(self,fp,name):
  | 
      
      
         | 987 | 
          | 
          | 
             """
  | 
      
      
         | 988 | 
          | 
          | 
             Use the EmitPush method to push the address of a variable onto the data
  | 
      
      
         | 989 | 
          | 
          | 
             stack.
  | 
      
      
         | 990 | 
          | 
          | 
             """
  | 
      
      
         | 991 | 
          | 
          | 
             if not self.IsSymbol(name):
  | 
      
      
         | 992 | 
          | 
          | 
               raise asmDef.AsmException('Variable "%s" not recognized' % name);
  | 
      
      
         | 993 | 
          | 
          | 
             ixName = self.symbols['list'].index(name);
  | 
      
      
         | 994 | 
          | 
          | 
             if self.symbols['type'][ixName] != 'variable':
  | 
      
      
         | 995 | 
          | 
          | 
               raise asmDef.AsmException('"%s" is not a variable' % name);
  | 
      
      
         | 996 | 
          | 
          | 
             self.EmitPush(fp,self.symbols['body'][ixName]['start'],name);
  | 
      
      
         | 997 | 
          | 
          | 
          
  | 
      
      
         | 998 | 
          | 
          | 
           #
  | 
      
      
         | 999 | 
          | 
          | 
           # EmitOpcode, EmitMacro, and EmitProgram emit composite or more complicated
  | 
      
      
         | 1000 | 
          | 
          | 
           # bodies.
  | 
      
      
         | 1001 | 
          | 
          | 
           #
  | 
      
      
         | 1002 | 
          | 
          | 
          
  | 
      
      
         | 1003 | 
          | 
          | 
           def EmitOptArg(self,fp,token):
  | 
      
      
         | 1004 | 
          | 
          | 
             """
  | 
      
      
         | 1005 | 
          | 
          | 
             Write the metacode for optional arguments to macros.\n
  | 
      
      
         | 1006 | 
          | 
          | 
             These must be single-instruction arguments.
  | 
      
      
         | 1007 | 
          | 
          | 
             """
  | 
      
      
         | 1008 | 
          | 
          | 
             # Symbols encountered in macros are expanded here instead of the
  | 
      
      
         | 1009 | 
          | 
          | 
             # ExpandTokens method -- the code is much simpler this way even though the
  | 
      
      
         | 1010 | 
          | 
          | 
             # associated error detection was deferred in the processing.  The symbol
  | 
      
      
         | 1011 | 
          | 
          | 
             # must expand to a single value.
  | 
      
      
         | 1012 | 
          | 
          | 
             if token['type'] == 'symbol':
  | 
      
      
         | 1013 | 
          | 
          | 
               token = self.ExpandSymbol(token,singleValue=True);
  | 
      
      
         | 1014 | 
          | 
          | 
             if token['type'] == 'constant':
  | 
      
      
         | 1015 | 
          | 
          | 
               name = token['value'];
  | 
      
      
         | 1016 | 
          | 
          | 
               if not self.IsSymbol(name):
  | 
      
      
         | 1017 | 
          | 
          | 
                 raise Exception('Program Bug');
  | 
      
      
         | 1018 | 
          | 
          | 
               ix = self.symbols['list'].index(name);
  | 
      
      
         | 1019 | 
          | 
          | 
               if len(self.symbols['body'][ix]) != 1:
  | 
      
      
         | 1020 | 
          | 
          | 
                 raise asmDef.AsmException('Optional constant can only be one byte at %s' % token['loc']);
  | 
      
      
         | 1021 | 
          | 
          | 
               self.EmitPush(fp,self.symbols['body'][ix][0],self.Emit_String(name),tokenLoc=token['loc']);
  | 
      
      
         | 1022 | 
          | 
          | 
             elif token['type'] in ('inport','outport','outstrobe'):
  | 
      
      
         | 1023 | 
          | 
          | 
               name = token['value'];
  | 
      
      
         | 1024 | 
          | 
          | 
               if not self.IsSymbol(name):
  | 
      
      
         | 1025 | 
          | 
          | 
                 raise Exception('Program Bug -- unrecognized inport/outport name "%s"');
  | 
      
      
         | 1026 | 
          | 
          | 
               ix = self.symbols['list'].index(name);
  | 
      
      
         | 1027 | 
          | 
          | 
               self.EmitPush(fp,self.symbols['body'][ix],self.Emit_String(name));
  | 
      
      
         | 1028 | 
          | 
          | 
             elif token['type'] == 'instruction':
  | 
      
      
         | 1029 | 
          | 
          | 
               self.EmitOpcode(fp,self.InstructionOpcode(token['value']),token['value']);
  | 
      
      
         | 1030 | 
          | 
          | 
             elif token['type'] == 'parameter':
  | 
      
      
         | 1031 | 
          | 
          | 
               self.EmitParameter(fp,token);
  | 
      
      
         | 1032 | 
          | 
          | 
             elif token['type'] == 'value':
  | 
      
      
         | 1033 | 
          | 
          | 
               self.EmitPush(fp,token['value'],tokenLoc=token['loc']);
  | 
      
      
         | 1034 | 
          | 
          | 
             elif token['type'] == 'variable':
  | 
      
      
         | 1035 | 
          | 
          | 
               self.EmitVariable(fp,token['value']);
  | 
      
      
         | 1036 | 
          | 
          | 
             elif token['type'] == 'macro':
  | 
      
      
         | 1037 | 
          | 
          | 
               self.EmitMacro(fp,token);
  | 
      
      
         | 1038 | 
          | 
          | 
             else:
  | 
      
      
         | 1039 | 
          | 
          | 
               raise asmDef.AsmException('Unrecognized optional argument "%s"' % token['value']);
  | 
      
      
         | 1040 | 
          | 
          | 
          
  | 
      
      
         | 1041 | 
          | 
          | 
           def EmitMacro(self,fp,token):
  | 
      
      
         | 1042 | 
          | 
          | 
             """
  | 
      
      
         | 1043 | 
         3 | 
         sinclairrf | 
             Write the metacode for a macro.\n
  | 
      
      
         | 1044 | 
          | 
          | 
             The macros coded here are required to access intrinsics.
  | 
      
      
         | 1045 | 
         2 | 
         sinclairrf | 
             """
  | 
      
      
         | 1046 | 
          | 
          | 
             # .call
  | 
      
      
         | 1047 | 
          | 
          | 
             if token['value'] == '.call':
  | 
      
      
         | 1048 | 
          | 
          | 
               self.EmitPush(fp,token['address'] & 0xFF,'');
  | 
      
      
         | 1049 | 
          | 
          | 
               self.EmitOpcode(fp,self.specialInstructions['call'] | (token['address'] >> 8),'call '+token['argument'][0]['value']);
  | 
      
      
         | 1050 | 
          | 
          | 
               self.EmitOptArg(fp,token['argument'][1]);
  | 
      
      
         | 1051 | 
          | 
          | 
             # .callc
  | 
      
      
         | 1052 | 
          | 
          | 
             elif token['value'] == '.callc':
  | 
      
      
         | 1053 | 
          | 
          | 
               self.EmitPush(fp,token['address'] & 0xFF,'');
  | 
      
      
         | 1054 | 
          | 
          | 
               self.EmitOpcode(fp,self.specialInstructions['callc'] | (token['address'] >> 8),'callc '+token['argument'][0]['value']);
  | 
      
      
         | 1055 | 
          | 
          | 
               self.EmitOptArg(fp,token['argument'][1]);
  | 
      
      
         | 1056 | 
          | 
          | 
             # .fetch
  | 
      
      
         | 1057 | 
          | 
          | 
             elif token['value'] == '.fetch':
  | 
      
      
         | 1058 | 
          | 
          | 
               name = token['argument'][0]['value'];
  | 
      
      
         | 1059 | 
          | 
          | 
               ixBank = self.Emit_GetBank(name);
  | 
      
      
         | 1060 | 
          | 
          | 
               self.EmitOpcode(fp,self.specialInstructions['fetch'] | ixBank,'fetch '+name);
  | 
      
      
         | 1061 | 
          | 
          | 
             # .fetch+
  | 
      
      
         | 1062 | 
          | 
          | 
             elif token['value'] == '.fetch+':
  | 
      
      
         | 1063 | 
          | 
          | 
               name = token['argument'][0]['value'];
  | 
      
      
         | 1064 | 
          | 
          | 
               ixBank = self.Emit_GetBank(name);
  | 
      
      
         | 1065 | 
          | 
          | 
               self.EmitOpcode(fp,self.specialInstructions['fetch+'] | ixBank,'fetch+('+name+')');
  | 
      
      
         | 1066 | 
          | 
          | 
             # .fetch-
  | 
      
      
         | 1067 | 
          | 
          | 
             elif token['value'] == '.fetch-':
  | 
      
      
         | 1068 | 
          | 
          | 
               name = token['argument'][0]['value'];
  | 
      
      
         | 1069 | 
          | 
          | 
               ixBank = self.Emit_GetBank(name);
  | 
      
      
         | 1070 | 
          | 
          | 
               self.EmitOpcode(fp,self.specialInstructions['fetch-'] | ixBank,'fetch-('+name+')');
  | 
      
      
         | 1071 | 
          | 
          | 
             # .jump
  | 
      
      
         | 1072 | 
          | 
          | 
             elif token['value'] == '.jump':
  | 
      
      
         | 1073 | 
          | 
          | 
               self.EmitPush(fp,token['address'] & 0xFF,'');
  | 
      
      
         | 1074 | 
          | 
          | 
               self.EmitOpcode(fp,self.specialInstructions['jump'] | (token['address'] >> 8),'jump '+token['argument'][0]['value']);
  | 
      
      
         | 1075 | 
          | 
          | 
               self.EmitOptArg(fp,token['argument'][1]);
  | 
      
      
         | 1076 | 
          | 
          | 
             # .jumpc
  | 
      
      
         | 1077 | 
          | 
          | 
             elif token['value'] == '.jumpc':
  | 
      
      
         | 1078 | 
          | 
          | 
               self.EmitPush(fp,token['address'] & 0xFF,'');
  | 
      
      
         | 1079 | 
          | 
          | 
               self.EmitOpcode(fp,self.specialInstructions['jumpc'] | (token['address'] >> 8),'jumpc '+token['argument'][0]['value']);
  | 
      
      
         | 1080 | 
          | 
          | 
               self.EmitOptArg(fp,token['argument'][1]);
  | 
      
      
         | 1081 | 
          | 
          | 
             # .return
  | 
      
      
         | 1082 | 
          | 
          | 
             elif token['value'] == '.return':
  | 
      
      
         | 1083 | 
          | 
          | 
               self.EmitOpcode(fp,self.specialInstructions['return'],'return');
  | 
      
      
         | 1084 | 
          | 
          | 
               self.EmitOptArg(fp,token['argument'][0]);
  | 
      
      
         | 1085 | 
          | 
          | 
             # .store
  | 
      
      
         | 1086 | 
          | 
          | 
             elif token['value'] == '.store':
  | 
      
      
         | 1087 | 
          | 
          | 
               name = token['argument'][0]['value'];
  | 
      
      
         | 1088 | 
          | 
          | 
               ixBank = self.Emit_GetBank(name);
  | 
      
      
         | 1089 | 
          | 
          | 
               self.EmitOpcode(fp,self.specialInstructions['store'] | ixBank,'store '+name);
  | 
      
      
         | 1090 | 
          | 
          | 
             # .store+
  | 
      
      
         | 1091 | 
          | 
          | 
             elif token['value'] == '.store+':
  | 
      
      
         | 1092 | 
          | 
          | 
               name = token['argument'][0]['value'];
  | 
      
      
         | 1093 | 
          | 
          | 
               ixBank = self.Emit_GetBank(name);
  | 
      
      
         | 1094 | 
          | 
          | 
               self.EmitOpcode(fp,self.specialInstructions['store+'] | ixBank,'store+ '+name);
  | 
      
      
         | 1095 | 
          | 
          | 
             # .store-
  | 
      
      
         | 1096 | 
          | 
          | 
             elif token['value'] == '.store-':
  | 
      
      
         | 1097 | 
          | 
          | 
               name = token['argument'][0]['value'];
  | 
      
      
         | 1098 | 
          | 
          | 
               ixBank = self.Emit_GetBank(name);
  | 
      
      
         | 1099 | 
          | 
          | 
               self.EmitOpcode(fp,self.specialInstructions['store-'] | ixBank,'store- '+name);
  | 
      
      
         | 1100 | 
         3 | 
         sinclairrf | 
             # user-defined macro
  | 
      
      
         | 1101 | 
          | 
          | 
             elif token['value'] in self.EmitFunction:
  | 
      
      
         | 1102 | 
          | 
          | 
               self.EmitFunction[token['value']](self,fp,token['argument']);
  | 
      
      
         | 1103 | 
         2 | 
         sinclairrf | 
             # error
  | 
      
      
         | 1104 | 
          | 
          | 
             else:
  | 
      
      
         | 1105 | 
          | 
          | 
               raise Exception('Program Bug -- Unrecognized macro "%s"' % token['value']);
  | 
      
      
         | 1106 | 
          | 
          | 
          
  | 
      
      
         | 1107 | 
          | 
          | 
           def EmitProgram(self,fp):
  | 
      
      
         | 1108 | 
          | 
          | 
             """
  | 
      
      
         | 1109 | 
          | 
          | 
             Write the program to the metacode file.\n
  | 
      
      
         | 1110 | 
          | 
          | 
             The frist line for the program has the format
  | 
      
      
         | 1111 | 
          | 
          | 
               :program address_main address_interrupt
  | 
      
      
         | 1112 | 
          | 
          | 
             where
  | 
      
      
         | 1113 | 
          | 
          | 
               address_main      is the address of the .main function (this should be 0)
  | 
      
      
         | 1114 | 
          | 
          | 
               address_interrupt is either the address of the optional interrupt
  | 
      
      
         | 1115 | 
          | 
          | 
                                 function if it was defined or the 2-character string
  | 
      
      
         | 1116 | 
          | 
          | 
                                 '[]'\n
  | 
      
      
         | 1117 | 
          | 
          | 
             The subsequent lines are sequences of
  | 
      
      
         | 1118 | 
          | 
          | 
               - function_name   indicates the start of a new function body and the name
  | 
      
      
         | 1119 | 
          | 
          | 
                                 of the function
  | 
      
      
         | 1120 | 
          | 
          | 
               instructions      is multiple lines, one for each instruction in the
  | 
      
      
         | 1121 | 
          | 
          | 
                                 function\n
  | 
      
      
         | 1122 | 
          | 
          | 
             The formats of the instruction lines are as follows:
  | 
      
      
         | 1123 | 
          | 
          | 
               value string      value is the next instruction to store and string is an
  | 
      
      
         | 1124 | 
          | 
          | 
                                 optional string describing the instruction
  | 
      
      
         | 1125 | 
          | 
          | 
                                 Note:  "value" must be a 3-digit hex string
  | 
      
      
         | 1126 | 
          | 
          | 
                                        representing a 9-bit value
  | 
      
      
         | 1127 | 
          | 
          | 
                                 Note:  The only place string should be empty is when
  | 
      
      
         | 1128 | 
          | 
          | 
                                        pushing the 8 lsb of an address onto the start
  | 
      
      
         | 1129 | 
          | 
          | 
                                        prior to a call, callc, jump, or jumpc
  | 
      
      
         | 1130 | 
          | 
          | 
                                        instruction
  | 
      
      
         | 1131 | 
          | 
          | 
               p name            the single 'p' means that the name of a parameter and
  | 
      
      
         | 1132 | 
          | 
          | 
                                 its range are to be converted into an instruction
  | 
      
      
         | 1133 | 
          | 
          | 
             """
  | 
      
      
         | 1134 | 
          | 
          | 
             # Write the program marker, address of .main, address or "[]" of .interrupt,
  | 
      
      
         | 1135 | 
          | 
          | 
             # and the total program length.
  | 
      
      
         | 1136 | 
          | 
          | 
             fp.write(':program');
  | 
      
      
         | 1137 | 
          | 
          | 
             fp.write(' %d' % self.functionEvaluation['address'][0]);
  | 
      
      
         | 1138 | 
          | 
          | 
             if self.interrupt:
  | 
      
      
         | 1139 | 
          | 
          | 
               fp.write(' %d' % self.functionEvaluation['address'][1]);
  | 
      
      
         | 1140 | 
          | 
          | 
             else:
  | 
      
      
         | 1141 | 
          | 
          | 
               fp.write(' []');
  | 
      
      
         | 1142 | 
          | 
          | 
             fp.write(' %d' % (self.functionEvaluation['address'][-1] + self.functionEvaluation['length'][-1]));
  | 
      
      
         | 1143 | 
          | 
          | 
             fp.write('\n');
  | 
      
      
         | 1144 | 
          | 
          | 
             # Emit the bodies
  | 
      
      
         | 1145 | 
          | 
          | 
             for ix in range(len(self.functionEvaluation['list'])):
  | 
      
      
         | 1146 | 
          | 
          | 
               fp.write('- %s\n' % self.functionEvaluation['list'][ix]);
  | 
      
      
         | 1147 | 
          | 
          | 
               self.emitLabelList = '';
  | 
      
      
         | 1148 | 
          | 
          | 
               for token in self.functionEvaluation['body'][ix]:
  | 
      
      
         | 1149 | 
          | 
          | 
                 if token['type'] == 'value':
  | 
      
      
         | 1150 | 
          | 
          | 
                   self.EmitPush(fp,token['value'],tokenLoc=token['loc']);
  | 
      
      
         | 1151 | 
          | 
          | 
                 elif token['type'] == 'label':
  | 
      
      
         | 1152 | 
          | 
          | 
                   self.Emit_AddLabel(token['value']);
  | 
      
      
         | 1153 | 
          | 
          | 
                 elif token['type'] == 'constant':
  | 
      
      
         | 1154 | 
          | 
          | 
                   if not self.IsSymbol(token['value']):
  | 
      
      
         | 1155 | 
          | 
          | 
                     raise Exception('Program Bug');
  | 
      
      
         | 1156 | 
          | 
          | 
                   ix = self.symbols['list'].index(token['value']);
  | 
      
      
         | 1157 | 
          | 
          | 
                   body = self.symbols['body'][ix];
  | 
      
      
         | 1158 | 
          | 
          | 
                   self.EmitPush(fp,body[-1],token['value'],tokenLoc=token['loc']);
  | 
      
      
         | 1159 | 
          | 
          | 
                   for v in body[-2::-1]:
  | 
      
      
         | 1160 | 
          | 
          | 
                     self.EmitPush(fp,v,tokenLoc=token['loc']);
  | 
      
      
         | 1161 | 
          | 
          | 
                 elif token['type'] in ('inport','outport','outstrobe',):
  | 
      
      
         | 1162 | 
          | 
          | 
                   if not self.IsSymbol(token['value']):
  | 
      
      
         | 1163 | 
          | 
          | 
                     raise Exception('Program Bug');
  | 
      
      
         | 1164 | 
          | 
          | 
                   ix = self.symbols['list'].index(token['value']);
  | 
      
      
         | 1165 | 
          | 
          | 
                   self.EmitPush(fp,self.symbols['body'][ix],token['value'],tokenLoc=token['loc']);
  | 
      
      
         | 1166 | 
          | 
          | 
                 elif token['type'] == 'instruction':
  | 
      
      
         | 1167 | 
          | 
          | 
                   self.EmitOpcode(fp,self.InstructionOpcode(token['value']),token['value']);
  | 
      
      
         | 1168 | 
          | 
          | 
                 elif token['type'] == 'macro':
  | 
      
      
         | 1169 | 
          | 
          | 
                   self.EmitMacro(fp,token);
  | 
      
      
         | 1170 | 
          | 
          | 
                 elif token['type'] == 'parameter':
  | 
      
      
         | 1171 | 
          | 
          | 
                   self.EmitParameter(fp,token);
  | 
      
      
         | 1172 | 
          | 
          | 
                 elif token['type'] == 'symbol':
  | 
      
      
         | 1173 | 
          | 
          | 
                   self.EmitPush(fp,token['value'],token['name'],tokenLoc=token['loc']);
  | 
      
      
         | 1174 | 
          | 
          | 
                 elif token['type'] == 'variable':
  | 
      
      
         | 1175 | 
          | 
          | 
                   self.EmitVariable(fp,token['value']);
  | 
      
      
         | 1176 | 
          | 
          | 
                 else:
  | 
      
      
         | 1177 | 
          | 
          | 
                   raise Exception('Program Bug:  Unrecognized type "%s"' % token['type']);
  | 
      
      
         | 1178 | 
          | 
          | 
          
  | 
      
      
         | 1179 | 
          | 
          | 
           ################################################################################
  | 
      
      
         | 1180 | 
          | 
          | 
           #
  | 
      
      
         | 1181 | 
          | 
          | 
           # Initialize the object.
  | 
      
      
         | 1182 | 
          | 
          | 
           #
  | 
      
      
         | 1183 | 
          | 
          | 
           ################################################################################
  | 
      
      
         | 1184 | 
          | 
          | 
          
  | 
      
      
         | 1185 | 
          | 
          | 
           def __init__(self):
  | 
      
      
         | 1186 | 
          | 
          | 
             """
  | 
      
      
         | 1187 | 
          | 
          | 
             Initialize the tables definining the following:
  | 
      
      
         | 1188 | 
          | 
          | 
               directly invokable instruction mnemonics and the associated opcodes
  | 
      
      
         | 1189 | 
          | 
          | 
               indirectly inivoked instruction mnemonics and the associated opcodes
  | 
      
      
         | 1190 | 
          | 
          | 
                 Note:  These are accessed through macros since they require an argument
  | 
      
      
         | 1191 | 
          | 
          | 
                        or are part of multi-instruction sequences.
  | 
      
      
         | 1192 | 
          | 
          | 
               directives (other than ".include")
  | 
      
      
         | 1193 | 
          | 
          | 
               macros with type restrictions for required arguments and defaults and
  | 
      
      
         | 1194 | 
          | 
          | 
                 restrictions for optional arguments\n
  | 
      
      
         | 1195 | 
          | 
          | 
             Initialize lists and members to record memory attributes, stack lengths,
  | 
      
      
         | 1196 | 
          | 
          | 
             body of the .main function, body of the optional .interrupt function,
  | 
      
      
         | 1197 | 
          | 
          | 
             current memory for variable definitions, etc.
  | 
      
      
         | 1198 | 
          | 
          | 
             """
  | 
      
      
         | 1199 | 
          | 
          | 
          
  | 
      
      
         | 1200 | 
          | 
          | 
             #
  | 
      
      
         | 1201 | 
         3 | 
         sinclairrf | 
             # Enumerate the directives
  | 
      
      
         | 1202 | 
          | 
          | 
             # Note:  The ".include" directive is handled within asmDef.FileBodyIterator.
  | 
      
      
         | 1203 | 
          | 
          | 
             #
  | 
      
      
         | 1204 | 
          | 
          | 
          
  | 
      
      
         | 1205 | 
          | 
          | 
             self.directives = dict();
  | 
      
      
         | 1206 | 
          | 
          | 
          
  | 
      
      
         | 1207 | 
          | 
          | 
             self.directives['list']= list();
  | 
      
      
         | 1208 | 
          | 
          | 
             self.directives['list'].append('.constant');
  | 
      
      
         | 1209 | 
          | 
          | 
             self.directives['list'].append('.function');
  | 
      
      
         | 1210 | 
          | 
          | 
             self.directives['list'].append('.interrupt');
  | 
      
      
         | 1211 | 
          | 
          | 
             self.directives['list'].append('.macro');
  | 
      
      
         | 1212 | 
          | 
          | 
             self.directives['list'].append('.main');
  | 
      
      
         | 1213 | 
          | 
          | 
             self.directives['list'].append('.memory');
  | 
      
      
         | 1214 | 
          | 
          | 
             self.directives['list'].append('.variable');
  | 
      
      
         | 1215 | 
          | 
          | 
          
  | 
      
      
         | 1216 | 
          | 
          | 
             #
  | 
      
      
         | 1217 | 
         2 | 
         sinclairrf | 
             # Configure the instructions.
  | 
      
      
         | 1218 | 
          | 
          | 
             #
  | 
      
      
         | 1219 | 
          | 
          | 
          
  | 
      
      
         | 1220 | 
          | 
          | 
             self.instructions = dict(list=list(), opcode=list());
  | 
      
      
         | 1221 | 
          | 
          | 
             self.AddInstruction('&',            0x050);
  | 
      
      
         | 1222 | 
          | 
          | 
             self.AddInstruction('+',            0x018);
  | 
      
      
         | 1223 | 
          | 
          | 
             self.AddInstruction('-',            0x01C);
  | 
      
      
         | 1224 | 
          | 
          | 
             self.AddInstruction('-1<>',         0x023);
  | 
      
      
         | 1225 | 
          | 
          | 
             self.AddInstruction('-1=',          0x022);
  | 
      
      
         | 1226 | 
          | 
          | 
             self.AddInstruction('0<>',          0x021);
  | 
      
      
         | 1227 | 
          | 
          | 
             self.AddInstruction('0=',           0x020);
  | 
      
      
         | 1228 | 
          | 
          | 
             self.AddInstruction('0>>',          0x004);
  | 
      
      
         | 1229 | 
          | 
          | 
             self.AddInstruction('1+',           0x058);
  | 
      
      
         | 1230 | 
          | 
          | 
             self.AddInstruction('1-',           0x05C);
  | 
      
      
         | 1231 | 
          | 
          | 
             self.AddInstruction('1>>',          0x005);
  | 
      
      
         | 1232 | 
          | 
          | 
             self.AddInstruction('<<0',          0x001);
  | 
      
      
         | 1233 | 
          | 
          | 
             self.AddInstruction('<<1',          0x002);
  | 
      
      
         | 1234 | 
          | 
          | 
             self.AddInstruction('<<msb',        0x003);
  | 
      
      
         | 1235 | 
          | 
          | 
             self.AddInstruction('>r',           0x040);
  | 
      
      
         | 1236 | 
          | 
          | 
             self.AddInstruction('^',            0x052);
  | 
      
      
         | 1237 | 
          | 
          | 
             #self.AddInstruction('dis',          0x01C);
  | 
      
      
         | 1238 | 
          | 
          | 
             self.AddInstruction('drop',         0x054);
  | 
      
      
         | 1239 | 
          | 
          | 
             self.AddInstruction('dup',          0x008);
  | 
      
      
         | 1240 | 
          | 
          | 
             #self.AddInstruction('ena',          0x019);
  | 
      
      
         | 1241 | 
          | 
          | 
             self.AddInstruction('inport',       0x030);
  | 
      
      
         | 1242 | 
          | 
          | 
             self.AddInstruction('lsb>>',        0x007);
  | 
      
      
         | 1243 | 
          | 
          | 
             self.AddInstruction('msb>>',        0x006);
  | 
      
      
         | 1244 | 
          | 
          | 
             self.AddInstruction('nip',          0x053);
  | 
      
      
         | 1245 | 
          | 
          | 
             self.AddInstruction('nop',          0x000);
  | 
      
      
         | 1246 | 
          | 
          | 
             self.AddInstruction('or',           0x051);
  | 
      
      
         | 1247 | 
          | 
          | 
             self.AddInstruction('outport',      0x038);
  | 
      
      
         | 1248 | 
          | 
          | 
             self.AddInstruction('over',         0x00A);
  | 
      
      
         | 1249 | 
          | 
          | 
             self.AddInstruction('r>',           0x049);
  | 
      
      
         | 1250 | 
          | 
          | 
             self.AddInstruction('r@',           0x009);
  | 
      
      
         | 1251 | 
          | 
          | 
             self.AddInstruction('swap',         0x012);
  | 
      
      
         | 1252 | 
          | 
          | 
          
  | 
      
      
         | 1253 | 
          | 
          | 
             self.specialInstructions = dict();
  | 
      
      
         | 1254 | 
          | 
          | 
             self.specialInstructions['call']    = 0x0C0;
  | 
      
      
         | 1255 | 
          | 
          | 
             self.specialInstructions['callc']   = 0x0E0;
  | 
      
      
         | 1256 | 
          | 
          | 
             self.specialInstructions['fetch']   = 0x068;
  | 
      
      
         | 1257 | 
          | 
          | 
             self.specialInstructions['fetch+']  = 0x078;
  | 
      
      
         | 1258 | 
          | 
          | 
             self.specialInstructions['fetch-']  = 0x07C;
  | 
      
      
         | 1259 | 
          | 
          | 
             self.specialInstructions['jump']    = 0x080;
  | 
      
      
         | 1260 | 
          | 
          | 
             self.specialInstructions['jumpc']   = 0x0A0;
  | 
      
      
         | 1261 | 
          | 
          | 
             self.specialInstructions['return']  = 0x028;
  | 
      
      
         | 1262 | 
          | 
          | 
             self.specialInstructions['store']   = 0x060;
  | 
      
      
         | 1263 | 
          | 
          | 
             self.specialInstructions['store+']  = 0x070;
  | 
      
      
         | 1264 | 
          | 
          | 
             self.specialInstructions['store-']  = 0x074;
  | 
      
      
         | 1265 | 
          | 
          | 
          
  | 
      
      
         | 1266 | 
          | 
          | 
             #
  | 
      
      
         | 1267 | 
          | 
          | 
             # Configure the pre-defined macros
  | 
      
      
         | 1268 | 
          | 
          | 
             # Note:  'symbol' is a catch-call for functions, labels, variables, etc.
  | 
      
      
         | 1269 | 
          | 
          | 
             #        These are restricted to the appropriate types when the macros are
  | 
      
      
         | 1270 | 
          | 
          | 
             #        expanded.
  | 
      
      
         | 1271 | 
          | 
          | 
             #
  | 
      
      
         | 1272 | 
          | 
          | 
          
  | 
      
      
         | 1273 | 
         3 | 
         sinclairrf | 
             self.macros = dict(list=list(), length=list(), args=list(), nArgs=list(), builtIn = list());
  | 
      
      
         | 1274 | 
          | 
          | 
             self.EmitFunction = dict();
  | 
      
      
         | 1275 | 
          | 
          | 
          
  | 
      
      
         | 1276 | 
          | 
          | 
             # Macros built in to the assembler (to access primitives).
  | 
      
      
         | 1277 | 
         2 | 
         sinclairrf | 
             self.AddMacro('.call',              3, [
  | 
      
      
         | 1278 | 
          | 
          | 
                                                      ['','symbol'],
  | 
      
      
         | 1279 | 
          | 
          | 
                                                      ['nop','instruction','singlemacro','singlevalue','symbol']
  | 
      
      
         | 1280 | 
          | 
          | 
                                                    ]);
  | 
      
      
         | 1281 | 
          | 
          | 
             self.AddMacro('.callc',             3, [
  | 
      
      
         | 1282 | 
          | 
          | 
                                                      ['','symbol'],
  | 
      
      
         | 1283 | 
          | 
          | 
                                                      ['drop','instruction','singlevalue','symbol']
  | 
      
      
         | 1284 | 
          | 
          | 
                                                    ]);
  | 
      
      
         | 1285 | 
          | 
          | 
             self.AddMacro('.fetch',             1, [ ['','symbol'] ]);
  | 
      
      
         | 1286 | 
          | 
          | 
             self.AddMacro('.fetch+',            1, [ ['','symbol'] ]);
  | 
      
      
         | 1287 | 
          | 
          | 
             self.AddMacro('.fetch-',            1, [ ['','symbol'] ]);
  | 
      
      
         | 1288 | 
          | 
          | 
             self.AddMacro('.jump',              3, [
  | 
      
      
         | 1289 | 
          | 
          | 
                                                      ['','symbol'],
  | 
      
      
         | 1290 | 
          | 
          | 
                                                      ['nop','instruction','singlemacro','singlevalue','symbol']
  | 
      
      
         | 1291 | 
          | 
          | 
                                                    ]);
  | 
      
      
         | 1292 | 
          | 
          | 
             self.AddMacro('.jumpc',             3, [
  | 
      
      
         | 1293 | 
          | 
          | 
                                                      ['','symbol'],
  | 
      
      
         | 1294 | 
          | 
          | 
                                                      ['drop','instruction','singlemacro','singlevalue','symbol']
  | 
      
      
         | 1295 | 
          | 
          | 
                                                    ]);
  | 
      
      
         | 1296 | 
         4 | 
         sinclairrf | 
             self.AddMacro('.return',            2, [ ['nop','instruction','singlemacro','singlevalue','symbol'] ]);
  | 
      
      
         | 1297 | 
         2 | 
         sinclairrf | 
             self.AddMacro('.store',             1, [ ['','symbol'] ]);
  | 
      
      
         | 1298 | 
          | 
          | 
             self.AddMacro('.store+',            1, [ ['','symbol'] ]);
  | 
      
      
         | 1299 | 
          | 
          | 
             self.AddMacro('.store-',            1, [ ['','symbol'] ]);
  | 
      
      
         | 1300 | 
          | 
          | 
          
  | 
      
      
         | 1301 | 
         3 | 
         sinclairrf | 
             # User-defined macros in ./macros that are "built in" to the assembler.
  | 
      
      
         | 1302 | 
          | 
          | 
             macroSearchPath = os.path.join(sys.path[0],'macros');
  | 
      
      
         | 1303 | 
          | 
          | 
             for macroName in os.listdir(macroSearchPath):
  | 
      
      
         | 1304 | 
          | 
          | 
               if not re.match(r'.*\.py$',macroName):
  | 
      
      
         | 1305 | 
          | 
          | 
                 continue;
  | 
      
      
         | 1306 | 
          | 
          | 
               self.AddUserMacro(macroName[:-3],macroSearchPaths=[macroSearchPath]);
  | 
      
      
         | 1307 | 
          | 
          | 
             for macroName in self.macros['list']:
  | 
      
      
         | 1308 | 
          | 
          | 
               self.macros['builtIn'].append(macroName);
  | 
      
      
         | 1309 | 
          | 
          | 
          
  | 
      
      
         | 1310 | 
         2 | 
         sinclairrf | 
             #
  | 
      
      
         | 1311 | 
          | 
          | 
             # List the macros that have special symbols for their first argument.
  | 
      
      
         | 1312 | 
          | 
          | 
             #
  | 
      
      
         | 1313 | 
          | 
          | 
          
  | 
      
      
         | 1314 | 
          | 
          | 
             self.MacrosWithSpecialFirstSymbol = ('.call','.callc','.jump','.jumpc',);
  | 
      
      
         | 1315 | 
          | 
          | 
          
  | 
      
      
         | 1316 | 
          | 
          | 
             #
  | 
      
      
         | 1317 | 
          | 
          | 
             # Externally defined parameters.
  | 
      
      
         | 1318 | 
          | 
          | 
             #
  | 
      
      
         | 1319 | 
          | 
          | 
          
  | 
      
      
         | 1320 | 
          | 
          | 
             self.memoryLength = dict();
  | 
      
      
         | 1321 | 
          | 
          | 
             self.stackLength = dict();
  | 
      
      
         | 1322 | 
          | 
          | 
          
  | 
      
      
         | 1323 | 
          | 
          | 
             #
  | 
      
      
         | 1324 | 
          | 
          | 
             # Configure the containers for the expanded main, interrupt, function,
  | 
      
      
         | 1325 | 
          | 
          | 
             # macro, etc. definitions.
  | 
      
      
         | 1326 | 
          | 
          | 
             #
  | 
      
      
         | 1327 | 
          | 
          | 
          
  | 
      
      
         | 1328 | 
         3 | 
         sinclairrf | 
             self.currentMemory = None;
  | 
      
      
         | 1329 | 
         2 | 
         sinclairrf | 
             self.interrupt = None;
  | 
      
      
         | 1330 | 
          | 
          | 
             self.main = None;
  | 
      
      
         | 1331 | 
         3 | 
         sinclairrf | 
             self.macroSearchPaths = ['.','./macros'];
  | 
      
      
         | 1332 | 
         2 | 
         sinclairrf | 
             self.symbols = dict(list=list(), type=list(), body=list());
  |