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

Subversion Repositories ssbcc

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

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

powered by: WebSVN 2.1.0

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