OpenCores
URL https://opencores.org/ocsvn/ssbcc/ssbcc/trunk

Subversion Repositories ssbcc

[/] [ssbcc/] [trunk/] [core/] [9x8/] [asm] - Blame information for rev 11

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 sinclairrf
#!/usr/bin/python2.7
2
 
3
################################################################################
4
#
5
# Copyright 2012, Sinclair R.F., Inc.
6
#
7
# Assembler for SSBCC 9x8 processor
8
#
9
################################################################################
10
 
11
# global modules
12
import argparse
13 11 sinclairrf
import os
14 2 sinclairrf
import re
15
import sys
16
 
17
# User defined modules
18
import asmDef
19
 
20
################################################################################
21
#
22
# Surround the program with a try ... except clause
23
#
24
################################################################################
25
 
26
try:
27
 
28
  ################################################################################
29
  #
30
  # The main loop:
31
  #
32
  # - Process the command line arguments.
33
  #
34
  ################################################################################
35
 
36
  #
37
  # Construct the command-line argument list parser
38
  #
39
 
40
  def validateFile(filename):
41
    try:
42
      return file(filename,'r');
43
    except:
44
      raise asmDef.AsmException('Error opening "%s"' % filename);
45
 
46
  argListParser = argparse.ArgumentParser(description='SSBCC 9x8 assembler');
47
  argListParser.add_argument('-C', metavar='CONSTANT=value', action='append', help='Constant definition');
48 9 sinclairrf
  argListParser.add_argument('-D', metavar='define', type=str, action='append', help='Define symbol (must start with "D_")');
49 2 sinclairrf
  argListParser.add_argument('-G', metavar='parametername', action='append', help='parameter names');
50
  argListParser.add_argument('-I', metavar='PORT=index', action='append', help='Input port names');
51
  argListParser.add_argument('-L', metavar='librarypath', action='append', help='Library search path');
52 3 sinclairrf
  argListParser.add_argument('-M', metavar='macropath', action='append', help='Macro search path');
53 2 sinclairrf
  argListParser.add_argument('-O', metavar='PORT=index', action='append', help='Output port names');
54
  argListParser.add_argument('-R', metavar='PORT=index', action='append', help='Strobe-only output port names');
55
  argListParser.add_argument('-S', metavar='MEMORY=length', action='append', help='Memory length');
56 11 sinclairrf
  argListParser.add_argument('--help-macro', metavar='macroName', type=str, help='Display usage message for the specified macro');
57 2 sinclairrf
  argListParser.add_argument('-i', action='store_true', help='enable/require interrupt');
58 11 sinclairrf
  argListParser.add_argument('--list-macros', action='store_true', help='list the built-in and user-defined macros');
59 2 sinclairrf
  argListParser.add_argument('-o', metavar='outfile', type=argparse.FileType('w'), required =True, help='output metafile');
60
  argListParser.add_argument('-s', metavar='STACK_NAME=length', action='append', help='Stack length');
61
  argListParser.add_argument('filename', metavar='filename', nargs='+', type=validateFile, help='required list of files');
62
  argList = argListParser.parse_args();
63
 
64
  # Construct the keyword parser
65
  from asmDef_9x8 import asmDef_9x8
66
  ad = asmDef_9x8();
67
 
68
  # Record the constants in the program symbol table.
69
  if argList.C:
70
    for constant in argList.C:
71 9 sinclairrf
      a=re.findall(r'^(C_\w+)=(-?[1-9]\d*|\w+)$',constant);
72 2 sinclairrf
      if not a:
73
        raise asmDef.AsmException('Malformed -C argument: "%s"' % constant);
74
      a = list(a[0]);
75
      try:
76
        a[1] = eval(a[1]);
77
      except:
78
        raise asmDef.AsmException('Cannot evaluate "%s"' % a[1]);
79
      if ad.IsSymbol(a[0]):
80
        raise asmDef.AsmException('Command line constant "%s" already defined' % a[0]);
81
      ad.AddSymbol(a[0], 'constant', body=[a[1]]);
82
 
83 9 sinclairrf
  # Record the defines.
84
  if argList.D:
85
    for name in argList.D:
86
      if not re.match('D_',name):
87
        raise SSBCCException('Bad define name "%s" should start with "D_"' % name);
88
      ad.AddSymbol(name, 'define');
89
 
90 2 sinclairrf
  # Record the input names and values in the appropriate record type
91
  if argList.G:
92
    for parameter in argList.G:
93
      a = re.findall(r'^([LG]_\w+)$',parameter);
94
      if not a:
95
        raise asmDef.AsmException('Malformed -G argument: "%s"' % parameter);
96
      if ad.IsSymbol(a[0]):
97
        raise asmDef.AsmException('Program Bug -- repeated symbol "%s"' % a[0]);
98
      ad.RegisterParameterName(a[0]);
99
  if argList.I:
100
    for inport in argList.I:
101
      a=re.findall(r'^(I_\w+)=(0|[1-9]\d*)$',inport);
102
      if not a:
103
        raise asmDef.AsmException('Malformed -I argument: "%s"' % inport);
104
      a = a[0];
105
      if ad.IsSymbol(a[0]):
106
        raise Exception('Program Bug -- repeated symbol "%s"' % a[0]);
107
      ix = int(a[1]);
108
      if not (0 <= ix < 256):
109
        raise asmDef.AsmException('Out-of-range inport index:  "%s"' % inport);
110
      ad.RegisterInport(a[0],ix);
111
  if argList.O:
112
    for outport in argList.O:
113
      a=re.findall(r'^(O_\w+)=(0|[1-9]\d*)$',outport);
114
      if not a:
115
        raise asmDef.AsmException('Malformed -O argument: "%s"' % outport);
116
      a = a[0];
117
      if ad.IsSymbol(a[0]):
118
        raise asmDef.AsmException('Program Bug -- repeated symbol "%s"' % a[0]);
119
      ix = int(a[1]);
120
      if not (0 <= ix < 256):
121
        raise asmDef.AsmException('Out-of-range outport index:  "%s"' % outport);
122
      ad.RegisterOutport(a[0],ix);
123
  if argList.R:
124
    for outstrobe in argList.R:
125
      a=re.findall(r'^(O_\w+)=(0|[1-9]\d*)$',outstrobe);
126
      if not a:
127
        raise asmDef.AsmException('Malformed -R argument: "%s"' % outstrobe);
128
      a = a[0];
129
      if ad.IsSymbol(a[0]):
130
        raise asmDef.AsmException('Program Bug -- repeated symbol "%s"' % a[0]);
131
      ix = int(a[1]);
132
      if not (0 <= ix < 256):
133
        raise asmDef.AsmException('Out-of-range strobe-only outport index:  "%s"' % outstrobe);
134
      ad.RegisterOutstrobe(a[0],ix);
135
  if argList.S:
136
    for memory in argList.S:
137
      a=re.findall(r'^(\w+)=(0|[1-9]\d*)$',memory);
138
      if not a:
139
        raise asmDef.AsmException('Malformed -S argument: "%s"' % memory);
140
      a=a[0];
141
      length = int(a[1]);
142
      if not (0 < length <= 256):
143
        raise asmDef.AsmException('Out-of-range memory length:  "%s"' % outport);
144
      ad.RegisterMemoryLength(a[0],length);
145
  if argList.s:
146
    for stack in argList.s:
147
      a=re.findall(r'^(\w+)=(0|[1-9]\d*)$',stack);
148
      if not a:
149
        raise asmDef.AsmException('Malformed -s argument: "%s"' % stack);
150
      a = a[0];
151
      ad.RegisterStackLength(a[0],int(a[1]));
152
 
153
  # Construct the iterator that loops through the code bodies.
154
  fbi = asmDef.FileBodyIterator(argList.filename,ad);
155 3 sinclairrf
 
156
  # Add paths for the ".include" directive.
157 2 sinclairrf
  if argList.L:
158
    for path in argList.L:
159
      fbi.AddSearchPath(path);
160
 
161 3 sinclairrf
  # Add paths for the ".macro" directive.
162
  if argList.M:
163
    for path in argList.M:
164
      ad.AddMacroSearchPath(path);
165
 
166 11 sinclairrf
  ##############################################################################
167
  #
168
  # Terminating help messages
169
  #
170
  ##############################################################################
171
 
172
  # If asked, print the usage for the specified macro.
173
  if argList.help_macro:
174
    macroName = argList.help_macro
175
    if macroName[0] != '.':
176
      macroName = '.%s' % macroName
177
    if macroName not in ad.macros['list']:
178
      try:
179
        ad.AddUserMacro(macroName[1:])
180
      except:
181
        pass
182
    if macroName in ad.macros['list']:
183
      ix = ad.macros['list'].index(macroName)
184
      if ad.macros['doc'][ix]:
185
        print '\n%s usage message:' % macroName
186
        print ad.macros['doc'][ix]
187
      else:
188
        print '\nNo usage message for %s\n' % macroName
189
    else:
190
      print 'Macro "%s" not recognized or malformed' % macroName
191
    print 'Assembler terminated by "--help-macro" option'
192
    sys.exit(1)
193
 
194
  # If asked, list the available macros.
195
  if argList.list_macros:
196
    print '\nBuilt-in macros\n'
197
    tmp = [name for name in ad.macros['builtIn']]
198
    tmp.sort()
199
    for name in tmp:
200
      print name
201
    for testPath in ad.macroSearchPaths:
202
      if not os.path.isdir(testPath):
203
        continue
204
      for testName in os.listdir(testPath):
205
        if not re.match(r'.*\.py$',testName):
206
          continue;
207
        fullFile = os.path.join(testPath,testName);
208
        if not os.path.isfile(fullFile):
209
          continue
210
        try:
211
          execfile(fullFile)
212
          exec('%s(ad)' % testName[:-3])
213
        except:
214
          pass
215
    print '\nUser-defined macros\n'
216
    tmp = [name for name in ad.macros['list'] if name not in ad.macros['builtIn']]
217
    tmp.sort()
218
    for name in tmp:
219
      print name
220
    print
221
    print 'Assembler terminated by "--list-macros" option'
222
    sys.exit(1)
223
 
224 2 sinclairrf
  ################################################################################
225
  #
226
  # Stage 1:  Parse the files.
227
  #
228
  # Read the entire file, doing the following while reading the file:
229
  # - Store the raw content of each line or group of lines for output to the
230
  #   assembled memory initialization.
231
  #   Note: A group of lines consists the comment lines preceding a directive and
232
  #         the body of the directive.
233
  # - Convert group of lines into an array of the raw tokens.
234
  # - Check the integrity of the bodies defined by the list of raw tokens.
235
  # - For each array of raw tokens, incorporate already-defined symbols and update
236
  #   the assembler dictionaries.
237
  #   Note: At this point the space required for the function or main program
238
  #     is fully computed.
239
  #
240
  ################################################################################
241
 
242
  #
243
  # Loop through the directive bodies in the input files (including ".include"d
244
  # files).
245
  #
246
 
247
  ifstackStack = list();
248
  ifstack = None;
249
  for bl in fbi:
250
    filename = bl[0];
251
    startLine = bl[1];
252
    body = bl[2:];
253
    flc_loc = filename + ' at line ' + str(startLine+len(body)-1);
254
    # Start-of-file processing.
255
    if startLine == 0:
256
      if ifstack != None:
257
        ifstackStack.append(ifstack);
258
      ifstack = list();
259
    # End-of-file processing.
260
    elif startLine == -1:
261
      if len(ifstack) != 0:
262
        raise asmDef.AsmException('%d unmatched .IFDEF/.IFNDEF(s) at the end of %s' % (len(ifstack),filename,));
263
      if ifstackStack:
264
        ifstack = ifstackStack.pop();
265
      else:
266
        ifstack = None;
267
    # Handle conditional compilation directives.
268
    elif re.match(r'\s*\.ELSE\b',body[-1]):
269
      if not re.match(r'\s*\.ELSE\s*(;.*)?$',body[-1]):
270
        raise asmDef.AsmException('Malformed ".ELSE" in %s' % flc_loc);
271
      if not ifstack:
272
        raise asmDef.AsmException('Unmatched ".ELSE" in %s' % flc_loc);
273
      ifstack[-1] ^= True;
274
    elif re.match(r'\s*\.ENDIF\b',body[-1]):
275
      if not re.match(r'\s*\.ENDIF\s*(;.*)?$',body[-1]):
276
        raise asmDef.AsmException('Malformed ".ENDIF" in %s' % flc_loc);
277
      if not ifstack:
278
        raise asmDef.AsmException('Unmatched ".ENDIF" in %s' % flc_loc);
279
      ifstack.pop();
280
    elif re.match(r'\s*\.IFN?DEF\b',body[-1]):
281
      a = re.findall(r'\s*(\.IFN?DEF)\s*(\S+)\b\s*(;.*)?$',body[-1]);
282
      if not a:
283
        raise asmDef.AsmException('Malformed .IFDEF or .IFNDEF in %s' % flc_loc);
284
      a = a[0];
285
      ifstack.append(ad.IsSymbol(a[1]));
286
      if a[0] == '.IFNDEF':
287
        ifstack[-1] ^= True;
288
    # Ignore bodies rejected by conditional compilation.
289
    elif ifstack and not ifstack[-1]:
290
      pass;
291
    # ".include" directives don't have an associated body
292
    elif re.match(r'\s*\.include\s',body[-1]):
293
      a = re.findall(r'\s*\.include\s+(\S+)(\s*|\s*;.*)$',body[-1]);
294
      if not a:
295
        raise asmDef.AsmException('Malformed .include directive in %s' % flc_loc);
296
      a = a[0];
297
      fbi.Include(a[0]);
298
    # Parse the body of all other directives and ensure that only one ".main"
299
    # and one ".interrupt" are defined.
300
    else:
301
      rawTokens = asmDef.RawTokens(ad,filename,startLine,body);
302
      if not rawTokens:
303
        continue;
304
      ad.CheckRawTokens(rawTokens);
305
      ad.FillRawTokens(rawTokens);
306
 
307
  #
308
  # Ensure a ".main" body was declared.
309
  #
310
 
311
  if not ad.Main():
312
    raise asmDef.AsmException('Required ".main" body not provided');
313
 
314
  #
315
  # Enforce consistency between the command-line "-i" flag and whether or not an
316
  # ".interrupt" body was declared.
317
  #
318
 
319
  if argList.i and not ad.Interrupt():
320
    raise asmDef.AsmException('Required ".interrupt" body not provided');
321
  if not argList.i and ad.Interrupt():
322
    raise asmDef.AsmException('".interrupt" body not allowed near %s' % ad.Interrupt()[0]['loc']);
323
 
324
  ################################################################################
325
  #
326
  # Stage 2:  Identify the required functions, compute their addresses, and set
327
  # the addresses for all "jump" and "call" macros.
328
  #
329
  ################################################################################
330
 
331
  ad.EvaluateMemoryTree();
332
  ad.EvaluateFunctionTree();
333
 
334
  ################################################################################
335
  #
336
  # Stage 3:  Emit the program
337
  #
338
  # Do the following:
339
  # - If interrupts are enabled, then set the first 4 instructions to be a "dis"
340
  #   and a ".jump" instruction to the ".interrupt" function.
341
  # - Write the instructions for the ".main" body.
342
  # - Loop through the ".function" list in the order in which they were defined
343
  #   and write their instructions.
344
  # - Print the memory and instruction usage statistics.
345
  #
346
  ################################################################################
347
 
348
  ad.EmitMemories(argList.o);
349
  ad.EmitProgram(argList.o);
350
  argList.o.close();
351
 
352
################################################################################
353
#
354
# Terminating except clause -- print fatal error message and indicate failure to
355
# the invoking program.
356
#
357
################################################################################
358
 
359
except asmDef.AsmException, msg:
360
  print >> sys.stderr, 'FATAL ERROR:  ' + str(msg);
361
  exit(1);

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.