isa_parser.py revision 2
1#! /usr/bin/env python
2
3# $Id$
4
5# Copyright (c) 2003 The Regents of The University of Michigan
6# All rights reserved.
7#
8# Redistribution and use in source and binary forms, with or without
9# modification, are permitted provided that the following conditions are
10# met: redistributions of source code must retain the above copyright
11# notice, this list of conditions and the following disclaimer;
12# redistributions in binary form must reproduce the above copyright
13# notice, this list of conditions and the following disclaimer in the
14# documentation and/or other materials provided with the distribution;
15# neither the name of the copyright holders nor the names of its
16# contributors may be used to endorse or promote products derived from
17# this software without specific prior written permission.
18#
19# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31import os
32import sys
33import re
34import string
35# get type names
36from types import *
37
38# Check arguments.  Right now there are only two: the name of the ISA
39# description (input) file and the name of the C++ decoder (output) file.
40isa_desc_filename = sys.argv[1]
41decoder_filename = sys.argv[2]
42
43# Might as well suck the file in while we're here.  This way if it's a
44# bad filename we don't waste a lot of time building the parser :-).
45input = open(isa_desc_filename)
46isa_desc = input.read()
47input.close()
48
49# Prepend the directory where the PLY lex & yacc modules are found
50# to the search path.  Assumes we're compiling in a subdirectory
51# of 'build' in the current tree.
52sys.path[0:0] = [os.environ['M5_EXT'] + '/ply']
53
54import lex
55import yacc
56
57#####################################################################
58#
59#                                Lexer
60#
61# The PLY lexer module takes two things as input:
62# - A list of token names (the string list 'tokens')
63# - A regular expression describing a match for each token.  The
64#   regexp for token FOO can be provided in two ways:
65#   - as a string variable named t_FOO
66#   - as the doc string for a function named t_FOO.  In this case,
67#     the function is also executed, allowing an action to be
68#     associated with each token match.
69#
70#####################################################################
71
72# Reserved words.  These are listed separately as they are matched
73# using the same regexp as generic IDs, but distinguished in the
74# t_ID() function.  The PLY documentation suggests this approach.
75reserved = (
76    'BITFIELD', 'DECLARE', 'DECODE', 'DEFAULT', 'DEF', 'FORMAT',
77    'LET', 'NAMESPACE', 'SIGNED', 'TEMPLATE'
78    )
79
80# List of tokens.  The lex module requires this.
81tokens = reserved + (
82    # identifier
83    'ID',
84
85    # integer literal
86    'INTLIT',
87
88    # string literal
89    'STRLIT',
90
91    # code literal
92    'CODELIT',
93
94    # ( ) [ ] { } < > , ; : :: *
95    'LPAREN', 'RPAREN',
96# not used any more... commented out to suppress PLY warning
97#    'LBRACKET', 'RBRACKET',
98    'LBRACE', 'RBRACE',
99    'LESS', 'GREATER',
100    'COMMA', 'SEMI', 'COLON', 'DBLCOLON',
101    'ASTERISK',
102
103    # C preprocessor directives
104    'CPPDIRECTIVE'
105)
106
107# Regular expressions for token matching
108t_LPAREN           = r'\('
109t_RPAREN           = r'\)'
110# not used any more... commented out to suppress PLY warning
111# t_LBRACKET         = r'\['
112# t_RBRACKET         = r'\]'
113t_LBRACE           = r'\{'
114t_RBRACE           = r'\}'
115t_LESS             = r'\<'
116t_GREATER          = r'\>'
117t_COMMA            = r','
118t_SEMI             = r';'
119t_COLON            = r':'
120t_DBLCOLON         = r'::'
121t_ASTERISK	   = r'\*'
122
123# Identifiers and reserved words
124reserved_map = { }
125for r in reserved:
126    reserved_map[r.lower()] = r
127
128def t_ID(t):
129    r'[A-Za-z_]\w*'
130    t.type = reserved_map.get(t.value,'ID')
131    return t
132
133# Integer literal
134def t_INTLIT(t):
135    r'(0x[\da-fA-F]+)|\d+'
136    try:
137        t.value = int(t.value,0)
138    except ValueError:
139        error(t.lineno, 'Integer value "%s" too large' % t.value)
140        t.value = 0
141    return t
142
143# String literal.  Note that these use only single quotes, and
144# can span multiple lines.
145def t_STRLIT(t):
146    r"(?m)'([^'])+'"
147    # strip off quotes
148    t.value = t.value[1:-1]
149    t.lineno += t.value.count('\n')
150    return t
151
152
153# "Code literal"... like a string literal, but delimiters are
154# '{{' and '}}' so they get formatted nicely under emacs c-mode
155def t_CODELIT(t):
156    r"(?m)\{\{([^\}]|}(?!\}))+\}\}"
157    # strip off {{ & }}
158    t.value = t.value[2:-2]
159    t.lineno += t.value.count('\n')
160    return t
161
162def t_CPPDIRECTIVE(t):
163    r'^\#.*\n'
164    t.lineno += t.value.count('\n')
165    return t
166
167#
168# The functions t_NEWLINE, t_ignore, and t_error are
169# special for the lex module.
170#
171
172# Newlines
173def t_NEWLINE(t):
174    r'\n+'
175    t.lineno += t.value.count('\n')
176
177# Comments
178def t_comment(t):
179    r'//.*'
180
181# Completely ignored characters
182t_ignore           = ' \t\x0c'
183
184# Error handler
185def t_error(t):
186    error(t.lineno, "illegal character '%s'" % t.value[0])
187    t.skip(1)
188
189# Build the lexer
190lex.lex()
191
192#####################################################################
193#
194#                                Parser
195#
196# Every function whose name starts with 'p_' defines a grammar rule.
197# The rule is encoded in the function's doc string, while the
198# function body provides the action taken when the rule is matched.
199# The argument to each function is a list of the values of the
200# rule's symbols: t[0] for the LHS, and t[1..n] for the symbols
201# on the RHS.  For tokens, the value is copied from the t.value
202# attribute provided by the lexer.  For non-terminals, the value
203# is assigned by the producing rule; i.e., the job of the grammar
204# rule function is to set the value for the non-terminal on the LHS
205# (by assigning to t[0]).
206#####################################################################
207
208# Not sure why, but we get a handful of shift/reduce conflicts on DECLARE.
209# By default these get resolved as shifts, which is correct, but
210# warnings are printed.  Explicitly marking DECLARE as right-associative
211# suppresses the warnings.
212precedence = (
213    ('right', 'DECLARE'),
214    )
215
216# The LHS of the first grammar rule is used as the start symbol
217# (in this case, 'specification').  Note that this rule enforces
218# that there will be exactly one namespace declaration, with 0 or more
219# global defs/decls before and after it.  The defs & decls before
220# the namespace decl will be outside the namespace; those after
221# will be inside.  The decoder function is always inside the namespace.
222def p_specification(t):
223    'specification : opt_defs_and_declares name_decl opt_defs_and_declares decode_block'
224    global_decls1 = t[1]
225    isa_name = t[2]
226    namespace = isa_name + "Inst"
227    global_decls2 = t[3]
228    (inst_decls, code) = t[4]
229    code = indent(code)
230    # grab the last three path components of isa_desc_filename
231    filename = '/'.join(isa_desc_filename.split('/')[-3:])
232    # if the isa_desc file defines a 'rcs_id' string,
233    # echo that into the output too
234    try:
235        local_rcs_id = rcs_id
236        # strip $s out of ID so it doesn't get re-substituted
237        local_rcs_id = re.sub(r'\$', '', local_rcs_id)
238    except NameError:
239        local_rcs_id = 'Id: no RCS id found'
240    output = open(decoder_filename, 'w')
241    # split string to keep rcs from substituting this file's RCS id in
242    print >> output, '/* $Id' + '''$ */
243
244/*
245 * Copyright (c) 2003
246 * The Regents of The University of Michigan
247 * All Rights Reserved
248 *
249 * Permission is granted to use, copy, create derivative works and
250 * redistribute this software and such derivative works for any
251 * purpose, so long as the copyright notice above, this grant of
252 * permission, and the disclaimer below appear in all copies made; and
253 * so long as the name of The University of Michigan is not used in
254 * any advertising or publicity pertaining to the use or distribution
255 * of this software without specific, written prior authorization.
256 *
257 * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION FROM THE
258 * UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY PURPOSE, AND
259 * WITHOUT WARRANTY BY THE UNIVERSITY OF MICHIGAN OF ANY KIND, EITHER
260 * EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
261 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
262 * PURPOSE. THE REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE
263 * LIABLE FOR ANY DAMAGES, INCLUDING DIRECT, SPECIAL, INDIRECT,
264 * INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM
265 * ARISING OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN
266 * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF SUCH
267 * DAMAGES.
268 */
269
270/*
271 * DO NOT EDIT THIS FILE!!!
272 *
273 * It was automatically generated from this ISA description:
274 *  Filename: %(filename)s
275 *    RCS %(local_rcs_id)s
276 */
277
278#include "bitfield.hh"	// required for bitfield support
279
280
281/////////////////////////////////////
282// Global defs (outside namespace) //
283/////////////////////////////////////
284
285%(global_decls1)s
286
287/**
288 * Namespace for %(isa_name)s static instruction objects.
289 */
290namespace %(namespace)s
291{
292
293/////////////////////////////////////
294// Global defs  (within namespace) //
295/////////////////////////////////////
296
297%(global_decls2)s
298
299////////////////////////////////////
300// Declares from inst definitions //
301////////////////////////////////////
302
303%(inst_decls)s
304
305} // namespace %(namespace)s
306
307//////////////////////
308// Decoder function //
309//////////////////////
310
311StaticInstPtr<%(isa_name)s>
312%(isa_name)s::decodeInst(%(isa_name)s::MachInst machInst)
313{
314    using namespace %(namespace)s;
315%(code)s
316} // decodeInst
317''' % vars()
318    output.close()
319
320# ISA name declaration looks like "namespace <foo>;"
321def p_name_decl(t):
322    'name_decl : NAMESPACE ID SEMI'
323    t[0] = t[2]
324
325# 'opt_defs_and_declares' is a possibly empty sequence of
326# defs and/or declares.
327def p_opt_defs_and_declares_0(t):
328    'opt_defs_and_declares : empty'
329    t[0] = ''
330
331def p_opt_defs_and_declares_1(t):
332    'opt_defs_and_declares : defs_and_declares'
333    t[0] = t[1]
334
335def p_defs_and_declares_0(t):
336    'defs_and_declares : def_or_declare'
337    t[0] = t[1]
338
339def p_defs_and_declares_1(t):
340    'defs_and_declares : defs_and_declares def_or_declare'
341    t[0] = t[1] + t[2]
342
343# The list of possible definition/declaration statements.
344def p_def_or_declare(t):
345    '''def_or_declare : def_format
346                      | def_bitfield
347                      | def_template
348                      | global_declare
349                      | global_let
350                      | cpp_directive'''
351    t[0] = t[1]
352
353# preprocessor directives are copied directly to the output.
354def p_cpp_directive(t):
355    '''cpp_directive : CPPDIRECTIVE'''
356    t[0] = t[1]
357
358# Global declares 'declare {{...}}' (C++ code blocks) are copied
359# directly to the output.
360def p_global_declare(t):
361    'global_declare : DECLARE CODELIT SEMI'
362    t[0] = substBitOps(t[2])
363
364# global let blocks 'let {{...}}' (Python code blocks) are executed
365# directly when seen.  These are typically used to initialize global
366# Python variables used in later format definitions.
367def p_global_let(t):
368    'global_let : LET CODELIT SEMI'
369    try:
370        exec(fixPythonIndentation(t[2]))
371    except:
372        error_bt(t.lineno(1), 'error in global let block "%s".' % t[2])
373    t[0] = '' # contributes nothing to the output C++ file
374
375# A bitfield definition looks like:
376# 'def [signed] bitfield <ID> [<first>:<last>]'
377# This generates a preprocessor macro in the output file.
378def p_def_bitfield_0(t):
379    'def_bitfield : DEF opt_signed BITFIELD ID LESS INTLIT COLON INTLIT GREATER SEMI'
380    expr = 'bits(machInst, %2d, %2d)' % (t[6], t[8])
381    if (t[2] == 'signed'):
382        expr = 'sext<%d>(%s)' % (t[6] - t[8] + 1, expr)
383    t[0] = '#undef %s\n#define %s\t%s\n' % (t[4], t[4], expr)
384
385# alternate form for single bit: 'def [signed] bitfield <ID> [<bit>]'
386def p_def_bitfield_1(t):
387    'def_bitfield : DEF opt_signed BITFIELD ID LESS INTLIT GREATER SEMI'
388    expr = 'bits(machInst, %2d, %2d)' % (t[6], t[6])
389    if (t[2] == 'signed'):
390        expr = 'sext<%d>(%s)' % (1, expr)
391    t[0] = '#undef %s\n#define %s\t%s\n' % (t[4], t[4], expr)
392
393def p_opt_signed_0(t):
394    'opt_signed : SIGNED'
395    t[0] = t[1]
396
397def p_opt_signed_1(t):
398    'opt_signed : empty'
399    t[0] = ''
400
401# Global map variable to hold templates
402templateMap = {}
403
404def p_def_template(t):
405    'def_template : DEF TEMPLATE ID CODELIT SEMI'
406    templateMap[t[3]] = t[4]
407    t[0] = ''
408
409# An instruction format definition looks like
410# "def format <fmt>(<params>) {{...}};"
411def p_def_format(t):
412    'def_format : DEF FORMAT ID LPAREN param_list RPAREN CODELIT SEMI'
413    (id, params, code) = (t[3], t[5], t[7])
414    defFormat(id, params, code, t.lineno(1))
415    # insert a comment into the output to note that the def was processed
416    t[0] = '''
417//
418// parser: format %s defined
419//
420''' % id
421
422# The formal parameter list for an instruction format is a possibly
423# empty list of comma-separated parameters.
424def p_param_list_0(t):
425    'param_list : empty'
426    t[0] = [ ]
427
428def p_param_list_1(t):
429    'param_list : param'
430    t[0] = [t[1]]
431
432def p_param_list_2(t):
433    'param_list : param_list COMMA param'
434    t[0] = t[1]
435    t[0].append(t[3])
436
437# Each formal parameter is either an identifier or an identifier
438# preceded by an asterisk.  As in Python, the latter (if present) gets
439# a tuple containing all the excess positional arguments, allowing
440# varargs functions.
441def p_param_0(t):
442    'param : ID'
443    t[0] = t[1]
444
445def p_param_1(t):
446    'param : ASTERISK ID'
447    # just concatenate them: '*ID'
448    t[0] = t[1] + t[2]
449
450# End of format definition-related rules.
451##############
452
453#
454# A decode block looks like:
455#	decode <field1> [, <field2>]* [default <inst>] { ... }
456#
457def p_decode_block(t):
458    'decode_block : DECODE ID opt_default LBRACE decode_stmt_list RBRACE'
459    default_defaults = defaultStack.pop()
460    (decls, code, has_default) = t[5]
461    # use the "default defaults" only if there was no explicit
462    # default statement in decode_stmt_list
463    if not has_default:
464        (default_decls, default_code) = default_defaults
465        decls += default_decls
466        code += default_code
467    t[0] = (decls,  '''
468switch (%s) {
469%s
470}
471''' % (t[2], indent(code)))
472
473# The opt_default statement serves only to push the "default defaults"
474# onto defaultStack.  This value will be used by nested decode blocks,
475# and used and popped off when the current decode_block is processed
476# (in p_decode_block() above).
477def p_opt_default_0(t):
478    'opt_default : empty'
479    # no default specified: reuse the one currently at the top of the stack
480    defaultStack.push(defaultStack.top())
481    # no meaningful value returned
482    t[0] = None
483
484def p_opt_default_1(t):
485    'opt_default : DEFAULT inst'
486    # push the new default
487    (decls, code) = t[2]
488    defaultStack.push((decls, '\ndefault:\n%sbreak;' % code))
489    # no meaningful value returned
490    t[0] = None
491
492def p_decode_stmt_list_0(t):
493    'decode_stmt_list : decode_stmt'
494    t[0] = t[1]
495
496def p_decode_stmt_list_1(t):
497    'decode_stmt_list : decode_stmt decode_stmt_list'
498    (decls1, code1, has_default1) = t[1]
499    (decls2, code2, has_default2) = t[2]
500    if (has_default1 and has_default2):
501        error(t.lineno(1), 'Two default cases in decode block')
502    t[0] = (decls1 + '\n' + decls2, code1 + '\n' + code2,
503            has_default1 or has_default2)
504
505#
506# Decode statement rules
507#
508# There are four types of statements allowed in a decode block:
509# 1. Format blocks 'format <foo> { ... }'
510# 2. Nested decode blocks
511# 3. Instruction definitions.
512# 4. C preprocessor directives.
513
514
515# Preprocessor directives found in a decode statement list are passed
516# through to the output, replicated to both the declaration and decode
517# streams.  This works well for ifdefs, so we can ifdef out both the
518# declarations and the decode cases generated by an instruction
519# definition.  Handling them as part of the grammar makes it easy to
520# keep them in the right place with respect to the code generated by
521# the other statements.
522def p_decode_stmt_cpp(t):
523    'decode_stmt : CPPDIRECTIVE'
524    t[0] = (t[1], t[1], 0)
525
526# A format block 'format <foo> { ... }' sets the default instruction
527# format used to handle instruction definitions inside the block.
528# This format can be overridden by using an explicit format on the
529# instruction definition or with a nested format block.
530def p_decode_stmt_format(t):
531    'decode_stmt : FORMAT push_format_id LBRACE decode_stmt_list RBRACE'
532    # The format will be pushed on the stack when 'push_format_id' is
533    # processed (see below).  Once the parser has recognized the full
534    # production (though the right brace), we're done with the format,
535    # so now we can pop it.
536    formatStack.pop()
537    t[0] = t[4]
538
539# This rule exists so we can set the current format (& push the stack)
540# when we recognize the format name part of the format block.
541def p_push_format_id(t):
542    'push_format_id : ID'
543    try:
544        formatStack.push(formatMap[t[1]])
545        t[0] = ('', '// format %s' % t[1])
546    except KeyError:
547        error(t.lineno(1), 'instruction format "%s" not defined.' % t[1])
548
549# Nested decode block: if the value of the current field matches the
550# specified constant, do a nested decode on some other field.
551def p_decode_stmt_decode(t):
552    'decode_stmt : case_label COLON decode_block'
553    (label, is_default) = t[1]
554    (decls, code) = t[3]
555    # just wrap the decoding code from the block as a case in the
556    # outer switch statement.
557    t[0] = (decls, '\n%s:\n%s' % (label, indent(code)), is_default)
558
559# Instruction definition (finally!).
560def p_decode_stmt_inst(t):
561    'decode_stmt : case_label COLON inst SEMI'
562    (label, is_default) = t[1]
563    (decls, code) = t[3]
564    t[0] = (decls, '\n%s:%sbreak;' % (label, indent(code)), is_default)
565
566# The case label is either a list of one or more constants or 'default'
567def p_case_label_0(t):
568    'case_label : intlit_list'
569    t[0] = (': '.join(map(lambda a: 'case %#x' % a, t[1])), 0)
570
571def p_case_label_1(t):
572    'case_label : DEFAULT'
573    t[0] = ('default', 1)
574
575#
576# The constant list for a decode case label must be non-empty, but may have
577# one or more comma-separated integer literals in it.
578#
579def p_intlit_list_0(t):
580    'intlit_list : INTLIT'
581    t[0] = [t[1]]
582
583def p_intlit_list_1(t):
584    'intlit_list : intlit_list COMMA INTLIT'
585    t[0] = t[1]
586    t[0].append(t[3])
587
588# Define an instruction using the current instruction format (specified
589# by an enclosing format block).
590# "<mnemonic>(<args>)"
591def p_inst_0(t):
592    'inst : ID LPAREN arg_list RPAREN'
593    # Pass the ID and arg list to the current format class to deal with.
594    currentFormat = formatStack.top()
595    (decls, code) = currentFormat.defineInst(t[1], t[3], t.lineno(1))
596    args = ','.join(map(str, t[3]))
597    args = re.sub('(?m)^', '//', args)
598    args = re.sub('^//', '', args)
599    comment = '// %s::%s(%s)\n' % (currentFormat.id, t[1], args)
600    t[0] = (comment + decls, comment + code)
601
602# Define an instruction using an explicitly specified format:
603# "<fmt>::<mnemonic>(<args>)"
604def p_inst_1(t):
605    'inst : ID DBLCOLON ID LPAREN arg_list RPAREN'
606    try:
607        format = formatMap[t[1]]
608    except KeyError:
609        error(t.lineno(1), 'instruction format "%s" not defined.' % t[1])
610    (decls, code) = format.defineInst(t[3], t[5], t.lineno(1))
611    comment = '// %s::%s(%s)\n' % (t[1], t[3], t[5])
612    t[0] = (comment + decls, comment + code)
613
614def p_arg_list_0(t):
615    'arg_list : empty'
616    t[0] = [ ]
617
618def p_arg_list_1(t):
619    'arg_list : arg'
620    t[0] = [t[1]]
621
622def p_arg_list_2(t):
623    'arg_list : arg_list COMMA arg'
624    t[0] = t[1]
625    t[0].append(t[3])
626
627def p_arg(t):
628    '''arg : ID
629           | INTLIT
630           | STRLIT
631           | CODELIT'''
632    t[0] = t[1]
633
634#
635# Empty production... use in other rules for readability.
636#
637def p_empty(t):
638    'empty :'
639    pass
640
641# Parse error handler.  Note that the argument here is the offending
642# *token*, not a grammar symbol (hence the need to use t.value)
643def p_error(t):
644    if t:
645        error(t.lineno, "syntax error at '%s'" % t.value)
646    else:
647        error_bt(0, "unknown syntax error")
648
649# END OF GRAMMAR RULES
650#
651# Now build the parser.
652yacc.yacc()
653
654################
655# Format object.
656#
657# A format object encapsulates an instruction format.  It must provide
658# a defineInst() method that generates the code for an instruction
659# definition.
660
661class Format:
662    def __init__(self, id, params, code):
663        # constructor: just save away arguments
664        self.id = id
665        self.params = params
666        # strip blank lines from code (ones at the end are troublesome)
667        code = re.sub(r'(?m)^\s*$', '', code);
668        if code == '':
669            code = '    pass\n'
670        param_list = string.join(params, ", ")
671        f = 'def defInst(name, Name, ' + param_list + '):\n' + code
672        exec(f)
673        self.func = defInst
674
675    def defineInst(self, name, args, lineno):
676        # automatically provide a capitalized version of mnemonic
677        Name = string.capitalize(name)
678        try:
679            retval = self.func(name, Name, *args)
680        except:
681            error_bt(lineno, 'error defining "%s".' % name)
682        return retval
683
684# Special null format to catch an implicit-format instruction
685# definition outside of any format block.
686class NoFormat:
687    def __init__(self):
688        self.defaultInst = ''
689
690    def defineInst(self, name, args, lineno):
691        error(lineno,
692              'instruction definition "%s" with no active format!' % name)
693
694# This dictionary maps format name strings to Format objects.
695formatMap = {}
696
697# Define a new format
698def defFormat(id, params, code, lineno):
699    # make sure we haven't already defined this one
700    if formatMap.get(id, None) != None:
701        error(lineno, 'format %s redefined.' % id)
702    # create new object and store in global map
703    formatMap[id] = Format(id, params, code)
704
705
706##############
707# Stack: a simple stack object.  Used for both formats (formatStack)
708# and default cases (defaultStack).
709
710class Stack:
711    def __init__(self, initItem):
712        self.stack = [ initItem ]
713
714    def push(self, item):
715        self.stack.append(item);
716
717    def pop(self):
718        return self.stack.pop()
719
720    def top(self):
721        return self.stack[-1]
722
723# The global format stack.
724formatStack = Stack(NoFormat())
725
726# The global default case stack.
727defaultStack = Stack( None )
728
729###################
730# Utility functions
731
732#
733# Indent every line in string 's' by two spaces
734# (except preprocessor directives).
735# Used to make nested code blocks look pretty.
736#
737def indent(s):
738    return re.sub(r'(?m)^(?!\#)', '  ', s)
739
740#
741# Munge a somewhat arbitrarily formatted piece of Python code
742# (e.g. from a format 'let' block) into something whose indentation
743# will get by the Python parser.
744#
745# The two keys here are that Python will give a syntax error if
746# there's any whitespace at the beginning of the first line, and that
747# all lines at the same lexical nesting level must have identical
748# indentation.  Unfortunately the way code literals work, an entire
749# let block tends to have some initial indentation.  Rather than
750# trying to figure out what that is and strip it off, we prepend 'if
751# 1:' to make the let code the nested block inside the if (and have
752# the parser automatically deal with the indentation for us).
753#
754# We don't want to do this if (1) the code block is empty or (2) the
755# first line of the block doesn't have any whitespace at the front.
756
757def fixPythonIndentation(s):
758    # get rid of blank lines first
759    s = re.sub(r'(?m)^\s*\n', '', s);
760    if (s != '' and re.match(r'[ \t]', s[0])):
761        s = 'if 1:\n' + s
762    return s
763
764# Error handler.  Just call exit.  Output formatted to work under
765# Emacs compile-mode.
766def error(lineno, string):
767    sys.exit("%s:%d: %s" % (isa_desc_filename, lineno, string))
768
769# Like error(), but include a Python stack backtrace (for processing
770# Python exceptions).
771def error_bt(lineno, string):
772    print >> sys.stderr, "%s:%d: %s" % (isa_desc_filename, lineno, string)
773    raise
774
775
776#####################################################################
777#
778#                      Bitfield Operator Support
779#
780#####################################################################
781
782bitOp1ArgRE = re.compile(r'<\s*(\w+)\s*:\s*>')
783
784bitOpWordRE = re.compile(r'(?<![\w\.])([\w\.]+)<\s*(\w+)\s*:\s*(\w+)\s*>')
785bitOpExprRE = re.compile(r'\)<\s*(\w+)\s*:\s*(\w+)\s*>')
786
787def substBitOps(code):
788    # first convert single-bit selectors to two-index form
789    # i.e., <n> --> <n:n>
790    code = bitOp1ArgRE.sub(r'<\1:\1>', code)
791    # simple case: selector applied to ID (name)
792    # i.e., foo<a:b> --> bits(foo, a, b)
793    code = bitOpWordRE.sub(r'bits(\1, \2, \3)', code)
794    # if selector is applied to expression (ending in ')'),
795    # we need to search backward for matching '('
796    match = bitOpExprRE.search(code)
797    while match:
798        exprEnd = match.start()
799        here = exprEnd - 1
800        nestLevel = 1
801        while nestLevel > 0:
802            if code[here] == '(':
803                nestLevel -= 1
804            elif code[here] == ')':
805                nestLevel += 1
806            here -= 1
807            if here < 0:
808                sys.exit("Didn't find '('!")
809        exprStart = here+1
810        newExpr = r'bits(%s, %s, %s)' % (code[exprStart:exprEnd+1],
811                                         match.group(1), match.group(2))
812        code = code[:exprStart] + newExpr + code[match.end():]
813        match = bitOpExprRE.search(code)
814    return code
815
816
817#####################################################################
818#
819#                             Code Parser
820#
821# The remaining code is the support for automatically extracting
822# instruction characteristics from pseudocode.
823#
824#####################################################################
825
826# Force the argument to be a list
827def makeList(list_or_item):
828    if not list_or_item:
829        return []
830    elif type(list_or_item) == ListType:
831        return list_or_item
832    else:
833        return [ list_or_item ]
834
835# generate operandSizeMap based on provided operandTypeMap:
836# basically generate equiv. C++ type and make is_signed flag
837def buildOperandSizeMap():
838    global operandSizeMap
839    operandSizeMap = {}
840    for ext in operandTypeMap.keys():
841        (desc, size) = operandTypeMap[ext]
842        if desc == 'signed int':
843            type = 'int%d_t' % size
844            is_signed = 1
845        elif desc == 'unsigned int':
846            type = 'uint%d_t' % size
847            is_signed = 0
848        elif desc == 'float':
849            is_signed = 1	# shouldn't really matter
850            if size == 32:
851                type = 'float'
852            elif size == 64:
853                type = 'double'
854        if type == '':
855            error(0, 'Unrecognized type description "%s" in operandTypeMap')
856        operandSizeMap[ext] = (size, type, is_signed)
857
858#
859# Base class for operand traits.  An instance of this class (or actually
860# a class derived from this one) encapsulates the traits of a particular
861# operand type (e.g., "32-bit integer register").
862#
863class OperandTraits:
864    def __init__(self, dflt_ext, reg_spec, flags, sort_pri):
865        # Force construction of operandSizeMap from operandTypeMap
866        # if it hasn't happened yet
867        if not globals().has_key('operandSizeMap'):
868            buildOperandSizeMap()
869        self.dflt_ext = dflt_ext
870        (self.dflt_size, self.dflt_type, self.dflt_is_signed) = \
871                         operandSizeMap[dflt_ext]
872        self.reg_spec = reg_spec
873        # Canonical flag structure is a triple of lists, where each list
874        # indicates the set of flags implied by this operand always, when
875        # used as a source, and when used as a dest, respectively.
876        # For simplicity this can be initialized using a variety of fairly
877        # obvious shortcuts; we convert these to canonical form here.
878        if not flags:
879            # no flags specified (e.g., 'None')
880            self.flags = ( [], [], [] )
881        elif type(flags) == StringType:
882            # a single flag: assumed to be unconditional
883            self.flags = ( [ flags ], [], [] )
884        elif type(flags) == ListType:
885            # a list of flags: also assumed to be unconditional
886            self.flags = ( flags, [], [] )
887        elif type(flags) == TupleType:
888            # it's a tuple: it should be a triple,
889            # but each item could be a single string or a list
890            (uncond_flags, src_flags, dest_flags) = flags
891            self.flags = (makeList(uncond_flags),
892                          makeList(src_flags), makeList(dest_flags))
893        self.sort_pri = sort_pri
894
895    def isMem(self):
896        return 0
897
898    def isReg(self):
899        return 0
900
901    def isFloatReg(self):
902        return 0
903
904    def isIntReg(self):
905        return 0
906
907    def isControlReg(self):
908        return 0
909
910    def getFlags(self, op_desc):
911        # note the empty slice '[:]' gives us a copy of self.flags[0]
912        # instead of a reference to it
913        my_flags = self.flags[0][:]
914        if op_desc.is_src:
915            my_flags += self.flags[1]
916        if op_desc.is_dest:
917            my_flags += self.flags[2]
918        return my_flags
919
920    def makeDecl(self, op_desc):
921        (size, type, is_signed) = operandSizeMap[op_desc.eff_ext]
922        # Note that initializations in the declarations are solely
923        # to avoid 'uninitialized variable' errors from the compiler.
924        return type + ' ' + op_desc.munged_name + ' = 0;\n';
925
926class IntRegOperandTraits(OperandTraits):
927    def isReg(self):
928        return 1
929
930    def isIntReg(self):
931        return 1
932
933    def makeConstructor(self, op_desc):
934        c = ''
935        if op_desc.is_src:
936            c += '\n\t_srcRegIdx[%d] = %s;' % \
937                 (op_desc.src_reg_idx, self.reg_spec)
938        if op_desc.is_dest:
939            c += '\n\t_destRegIdx[%d] = %s;' % \
940                 (op_desc.dest_reg_idx, self.reg_spec)
941        return c
942
943    def makeRead(self, op_desc, cpu_model):
944        (size, type, is_signed) = operandSizeMap[op_desc.eff_ext]
945        if (type == 'float' or type == 'double'):
946            error(0, 'Attempt to read integer register as FP')
947        if (size == self.dflt_size):
948            return '%s = xc->readIntReg(_srcRegIdx[%d]);\n' % \
949                   (op_desc.munged_name, op_desc.src_reg_idx)
950        else:
951            return '%s = bits(xc->readIntReg(_srcRegIdx[%d]), %d, 0);\n' % \
952                   (op_desc.munged_name, op_desc.src_reg_idx, size-1)
953
954    def makeWrite(self, op_desc, cpu_model):
955        (size, type, is_signed) = operandSizeMap[op_desc.eff_ext]
956        if (type == 'float' or type == 'double'):
957            error(0, 'Attempt to write integer register as FP')
958        if (size != self.dflt_size and is_signed):
959            final_val = 'sext<%d>(%s)' % (size, op_desc.munged_name)
960        else:
961            final_val = op_desc.munged_name
962        wb = '''
963        {
964            %s final_val = %s;
965            xc->setIntReg(_destRegIdx[%d], final_val);\n
966            if (traceData) { traceData->setData(final_val); }
967        }''' % (self.dflt_type, final_val, op_desc.dest_reg_idx)
968        return wb
969
970class FloatRegOperandTraits(OperandTraits):
971    def isReg(self):
972        return 1
973
974    def isFloatReg(self):
975        return 1
976
977    def makeConstructor(self, op_desc):
978        c = ''
979        if op_desc.is_src:
980            c += '\n\t_srcRegIdx[%d] = %s + FP_Base_DepTag;' % \
981                 (op_desc.src_reg_idx, self.reg_spec)
982        if op_desc.is_dest:
983            c += '\n\t_destRegIdx[%d] = %s + FP_Base_DepTag;' % \
984                 (op_desc.dest_reg_idx, self.reg_spec)
985        return c
986
987    def makeRead(self, op_desc, cpu_model):
988        (size, type, is_signed) = operandSizeMap[op_desc.eff_ext]
989        bit_select = 0
990        if (type == 'float'):
991            func = 'readFloatRegSingle'
992        elif (type == 'double'):
993            func = 'readFloatRegDouble'
994        else:
995            func = 'readFloatRegInt'
996            if (size != self.dflt_size):
997                bit_select = 1
998        base = 'xc->%s(_srcRegIdx[%d] - FP_Base_DepTag)' % \
999               (func, op_desc.src_reg_idx)
1000        if bit_select:
1001            return '%s = bits(%s, %d, 0);\n' % \
1002                   (op_desc.munged_name, base, size-1)
1003        else:
1004            return '%s = %s;\n' % (op_desc.munged_name, base)
1005
1006    def makeWrite(self, op_desc, cpu_model):
1007        (size, type, is_signed) = operandSizeMap[op_desc.eff_ext]
1008        final_val = op_desc.munged_name
1009        if (type == 'float'):
1010            func = 'setFloatRegSingle'
1011        elif (type == 'double'):
1012            func = 'setFloatRegDouble'
1013        else:
1014            func = 'setFloatRegInt'
1015            type = 'uint%d_t' % self.dflt_size
1016            if (size != self.dflt_size and is_signed):
1017                final_val = 'sext<%d>(%s)' % (size, op_desc.munged_name)
1018        wb = '''
1019        {
1020            %s final_val = %s;
1021            xc->%s(_destRegIdx[%d] - FP_Base_DepTag, final_val);\n
1022            if (traceData) { traceData->setData(final_val); }
1023        }''' % (type, final_val, func, op_desc.dest_reg_idx)
1024        return wb
1025
1026class ControlRegOperandTraits(OperandTraits):
1027    def isReg(self):
1028        return 1
1029
1030    def isControlReg(self):
1031        return 1
1032
1033    def makeConstructor(self, op_desc):
1034        c = ''
1035        if op_desc.is_src:
1036            c += '\n\t_srcRegIdx[%d] = %s_DepTag;' % \
1037                 (op_desc.src_reg_idx, self.reg_spec)
1038        if op_desc.is_dest:
1039            c += '\n\t_destRegIdx[%d] = %s_DepTag;' % \
1040                 (op_desc.dest_reg_idx, self.reg_spec)
1041        return c
1042
1043    def makeRead(self, op_desc, cpu_model):
1044        (size, type, is_signed) = operandSizeMap[op_desc.eff_ext]
1045        bit_select = 0
1046        if (type == 'float' or type == 'double'):
1047            error(0, 'Attempt to read control register as FP')
1048        base = 'xc->read%s()' % self.reg_spec
1049        if size == self.dflt_size:
1050            return '%s = %s;\n' % (op_desc.munged_name, base)
1051        else:
1052            return '%s = bits(%s, %d, 0);\n' % \
1053                   (op_desc.munged_name, base, size-1)
1054
1055    def makeWrite(self, op_desc, cpu_model):
1056        (size, type, is_signed) = operandSizeMap[op_desc.eff_ext]
1057        if (type == 'float' or type == 'double'):
1058            error(0, 'Attempt to write control register as FP')
1059        wb = 'xc->set%s(%s);\n' % (self.reg_spec, op_desc.munged_name)
1060        wb += 'if (traceData) { traceData->setData(%s); }' % \
1061              op_desc.munged_name
1062        return wb
1063
1064class MemOperandTraits(OperandTraits):
1065    def isMem(self):
1066        return 1
1067
1068    def makeConstructor(self, op_desc):
1069        return ''
1070
1071    def makeDecl(self, op_desc):
1072        (size, type, is_signed) = operandSizeMap[op_desc.eff_ext]
1073        # Note that initializations in the declarations are solely
1074        # to avoid 'uninitialized variable' errors from the compiler.
1075        # Declare memory data variable.
1076        c = '%s %s = 0;\n' % (type, op_desc.munged_name)
1077        # Declare var to hold memory access flags.
1078        c += 'unsigned %s_flags = memAccessFlags;\n' % op_desc.base_name
1079        # If this operand is a dest (i.e., it's a store operation),
1080        # then we need to declare a variable for the write result code
1081        # as well.
1082        if op_desc.is_dest:
1083            c += 'uint64_t %s_write_result = 0;\n' % op_desc.base_name
1084        return c
1085
1086    def makeRead(self, op_desc, cpu_model):
1087        (size, type, is_signed) = operandSizeMap[op_desc.eff_ext]
1088        eff_type = 'uint%d_t' % size
1089        return 'fault = memAccessObj->read(EA, (%s&)%s, %s_flags);\n' \
1090               % (eff_type, op_desc.munged_name, op_desc.base_name)
1091
1092    def makeWrite(self, op_desc, cpu_model):
1093        (size, type, is_signed) = operandSizeMap[op_desc.eff_ext]
1094        eff_type = 'uint%d_t' % size
1095        return 'fault = memAccessObj->write((%s&)%s, EA, %s_flags,' \
1096               ' &%s_write_result);\n' \
1097               % (eff_type, op_desc.munged_name, op_desc.base_name,
1098                  op_desc.base_name)
1099
1100class NPCOperandTraits(OperandTraits):
1101    def makeConstructor(self, op_desc):
1102        return ''
1103
1104    def makeRead(self, op_desc, cpu_model):
1105        return '%s = xc->readPC() + 4;\n' % op_desc.munged_name
1106
1107    def makeWrite(self, op_desc, cpu_model):
1108        return 'xc->setNextPC(%s);\n' % op_desc.munged_name
1109
1110
1111#
1112# Define operand variables that get derived from the basic declaration
1113# of ISA-specific operands in operandTraitsMap.  This function must be
1114# called by the ISA description file explicitly after defining
1115# operandTraitsMap (in a 'let' block).
1116#
1117def defineDerivedOperandVars():
1118    global operands
1119    operands = operandTraitsMap.keys()
1120
1121    operandsREString = (r'''
1122    (?<![\w\.])	     # neg. lookbehind assertion: prevent partial matches
1123    ((%s)(?:\.(\w+))?)   # match: operand with optional '.' then suffix
1124    (?![\w\.])	     # neg. lookahead assertion: prevent partial matches
1125    '''
1126                        % string.join(operands, '|'))
1127
1128    global operandsRE
1129    operandsRE = re.compile(operandsREString, re.MULTILINE|re.VERBOSE)
1130
1131    # Same as operandsREString, but extension is mandatory, and only two
1132    # groups are returned (base and ext, not full name as above).
1133    # Used for subtituting '_' for '.' to make C++ identifiers.
1134    operandsWithExtREString = (r'(?<![\w\.])(%s)\.(\w+)(?![\w\.])'
1135                               % string.join(operands, '|'))
1136
1137    global operandsWithExtRE
1138    operandsWithExtRE = re.compile(operandsWithExtREString, re.MULTILINE)
1139
1140
1141#
1142# Operand descriptor class.  An instance of this class represents
1143# a specific operand for a code block.
1144#
1145class OperandDescriptor:
1146    def __init__(self, full_name, base_name, ext, is_src, is_dest):
1147        self.full_name = full_name
1148        self.base_name = base_name
1149        self.ext = ext
1150        self.is_src = is_src
1151        self.is_dest = is_dest
1152        self.traits = operandTraitsMap[base_name]
1153        # The 'effective extension' (eff_ext) is either the actual
1154        # extension, if one was explicitly provided, or the default.
1155        # The 'munged name' replaces the '.' between the base and
1156        # extension (if any) with a '_' to make a legal C++ variable name.
1157        if ext:
1158            self.eff_ext = ext
1159            self.munged_name = base_name + '_' + ext
1160        else:
1161            self.eff_ext = self.traits.dflt_ext
1162            self.munged_name = base_name
1163
1164    # Finalize additional fields (primarily code fields).  This step
1165    # is done separately since some of these fields may depend on the
1166    # register index enumeration that hasn't been performed yet at the
1167    # time of __init__().
1168    def finalize(self):
1169        self.flags = self.traits.getFlags(self)
1170        self.constructor = self.traits.makeConstructor(self)
1171        self.exec_decl = self.traits.makeDecl(self)
1172
1173        if self.is_src:
1174            self.simple_rd = self.traits.makeRead(self, 'simple')
1175            self.dtld_rd = self.traits.makeRead(self, 'dtld')
1176        else:
1177            self.simple_rd = ''
1178            self.dtld_rd = ''
1179
1180        if self.is_dest:
1181            self.simple_wb = self.traits.makeWrite(self, 'simple')
1182            self.dtld_wb = self.traits.makeWrite(self, 'dtld')
1183        else:
1184            self.simple_wb = ''
1185            self.dtld_wb = ''
1186
1187class OperandDescriptorList:
1188    def __init__(self):
1189        self.items = []
1190        self.bases = {}
1191
1192    def __len__(self):
1193        return len(self.items)
1194
1195    def __getitem__(self, index):
1196        return self.items[index]
1197
1198    def append(self, op_desc):
1199        self.items.append(op_desc)
1200        self.bases[op_desc.base_name] = op_desc
1201
1202    def find_base(self, base_name):
1203        # like self.bases[base_name], but returns None if not found
1204        # (rather than raising exception)
1205        return self.bases.get(base_name)
1206
1207    # internal helper function for concat[Some]Attr{Strings|Lists}
1208    def __internalConcatAttrs(self, attr_name, filter, result):
1209        for op_desc in self.items:
1210            if filter(op_desc):
1211                result += getattr(op_desc, attr_name)
1212        return result
1213
1214    # return a single string that is the concatenation of the (string)
1215    # values of the specified attribute for all operands
1216    def concatAttrStrings(self, attr_name):
1217        return self.__internalConcatAttrs(attr_name, lambda x: 1, '')
1218
1219    # like concatAttrStrings, but only include the values for the operands
1220    # for which the provided filter function returns true
1221    def concatSomeAttrStrings(self, filter, attr_name):
1222        return self.__internalConcatAttrs(attr_name, filter, '')
1223
1224    # return a single list that is the concatenation of the (list)
1225    # values of the specified attribute for all operands
1226    def concatAttrLists(self, attr_name):
1227        return self.__internalConcatAttrs(attr_name, lambda x: 1, [])
1228
1229    # like concatAttrLists, but only include the values for the operands
1230    # for which the provided filter function returns true
1231    def concatSomeAttrLists(self, filter, attr_name):
1232        return self.__internalConcatAttrs(attr_name, filter, [])
1233
1234    def sort(self):
1235        self.items.sort(lambda a, b: a.traits.sort_pri - b.traits.sort_pri)
1236
1237# Regular expression object to match C++ comments
1238# (used in findOperands())
1239commentRE = re.compile(r'//.*\n')
1240
1241# Regular expression object to match assignment statements
1242# (used in findOperands())
1243assignRE = re.compile(r'\s*=(?!=)', re.MULTILINE)
1244
1245#
1246# Find all the operands in the given code block.  Returns an operand
1247# descriptor list (instance of class OperandDescriptorList).
1248#
1249def findOperands(code):
1250    operands = OperandDescriptorList()
1251    # delete comments so we don't accidentally match on reg specifiers inside
1252    code = commentRE.sub('', code)
1253    # search for operands
1254    next_pos = 0
1255    while 1:
1256        match = operandsRE.search(code, next_pos)
1257        if not match:
1258            # no more matches: we're done
1259            break
1260        op = match.groups()
1261        # regexp groups are operand full name, base, and extension
1262        (op_full, op_base, op_ext) = op
1263        # if the token following the operand is an assignment, this is
1264        # a destination (LHS), else it's a source (RHS)
1265        is_dest = (assignRE.match(code, match.end()) != None)
1266        is_src = not is_dest
1267        # see if we've already seen this one
1268        op_desc = operands.find_base(op_base)
1269        if op_desc:
1270            if op_desc.ext != op_ext:
1271                error(0, 'Inconsistent extensions for operand %s' % op_base)
1272            op_desc.is_src = op_desc.is_src or is_src
1273            op_desc.is_dest = op_desc.is_dest or is_dest
1274        else:
1275            # new operand: create new descriptor
1276            op_desc = OperandDescriptor(op_full, op_base, op_ext,
1277                                        is_src, is_dest)
1278            operands.append(op_desc)
1279        # start next search after end of current match
1280        next_pos = match.end()
1281    operands.sort()
1282    # enumerate source & dest register operands... used in building
1283    # constructor later
1284    srcRegs = 0
1285    destRegs = 0
1286    operands.numFPDestRegs = 0
1287    operands.numIntDestRegs = 0
1288    for op_desc in operands:
1289        if op_desc.traits.isReg():
1290            if op_desc.is_src:
1291                op_desc.src_reg_idx = srcRegs
1292                srcRegs += 1
1293            if op_desc.is_dest:
1294                op_desc.dest_reg_idx = destRegs
1295                destRegs += 1
1296                if op_desc.traits.isFloatReg():
1297                    operands.numFPDestRegs += 1
1298                elif op_desc.traits.isIntReg():
1299                    operands.numIntDestRegs += 1
1300    operands.numSrcRegs = srcRegs
1301    operands.numDestRegs = destRegs
1302    # now make a final pass to finalize op_desc fields that may depend
1303    # on the register enumeration
1304    for op_desc in operands:
1305        op_desc.finalize()
1306    return operands
1307
1308# Munge operand names in code string to make legal C++ variable names.
1309# (Will match munged_name attribute of OperandDescriptor object.)
1310def substMungedOpNames(code):
1311    return operandsWithExtRE.sub(r'\1_\2', code)
1312
1313def joinLists(t):
1314    return map(string.join, t)
1315
1316def makeFlagConstructor(flag_list):
1317    if len(flag_list) == 0:
1318        return ''
1319    # filter out repeated flags
1320    flag_list.sort()
1321    i = 1
1322    while i < len(flag_list):
1323        if flag_list[i] == flag_list[i-1]:
1324            del flag_list[i]
1325        else:
1326            i += 1
1327    pre = '\n\tflags['
1328    post = '] = true;'
1329    code = pre + string.join(flag_list, post + pre) + post
1330    return code
1331
1332class CodeBlock:
1333    def __init__(self, code):
1334        self.orig_code = code
1335        self.operands = findOperands(code)
1336        self.code = substMungedOpNames(substBitOps(code))
1337        self.constructor = self.operands.concatAttrStrings('constructor')
1338        self.constructor += \
1339                 '\n\t_numSrcRegs = %d;' % self.operands.numSrcRegs
1340        self.constructor += \
1341                 '\n\t_numDestRegs = %d;' % self.operands.numDestRegs
1342        self.constructor += \
1343                 '\n\t_numFPDestRegs = %d;' % self.operands.numFPDestRegs
1344        self.constructor += \
1345                 '\n\t_numIntDestRegs = %d;' % self.operands.numIntDestRegs
1346
1347        self.exec_decl = self.operands.concatAttrStrings('exec_decl')
1348
1349        is_mem = lambda op: op.traits.isMem()
1350        not_mem = lambda op: not op.traits.isMem()
1351
1352        self.simple_rd = self.operands.concatAttrStrings('simple_rd')
1353        self.simple_wb = self.operands.concatAttrStrings('simple_wb')
1354        self.simple_mem_rd = \
1355                 self.operands.concatSomeAttrStrings(is_mem, 'simple_rd')
1356        self.simple_mem_wb = \
1357                 self.operands.concatSomeAttrStrings(is_mem, 'simple_wb')
1358        self.simple_nonmem_rd = \
1359                 self.operands.concatSomeAttrStrings(not_mem, 'simple_rd')
1360        self.simple_nonmem_wb = \
1361                 self.operands.concatSomeAttrStrings(not_mem, 'simple_wb')
1362
1363        self.dtld_rd = self.operands.concatAttrStrings('dtld_rd')
1364        self.dtld_wb = self.operands.concatAttrStrings('dtld_wb')
1365        self.dtld_mem_rd = \
1366                 self.operands.concatSomeAttrStrings(is_mem, 'dtld_rd')
1367        self.dtld_mem_wb = \
1368                 self.operands.concatSomeAttrStrings(is_mem, 'dtld_wb')
1369        self.dtld_nonmem_rd = \
1370                 self.operands.concatSomeAttrStrings(not_mem, 'dtld_rd')
1371        self.dtld_nonmem_wb = \
1372                 self.operands.concatSomeAttrStrings(not_mem, 'dtld_wb')
1373
1374        self.flags = self.operands.concatAttrLists('flags')
1375
1376        # Make a basic guess on the operand class (function unit type).
1377        # These are good enough for most cases, and will be overridden
1378        # later otherwise.
1379        if 'IsStore' in self.flags:
1380            self.op_class = 'WrPort'
1381        elif 'IsLoad' in self.flags or 'IsPrefetch' in self.flags:
1382            self.op_class = 'RdPort'
1383        elif 'IsFloating' in self.flags:
1384            self.op_class = 'FloatADD'
1385        else:
1386            self.op_class = 'IntALU'
1387
1388# Assume all instruction flags are of the form 'IsFoo'
1389instFlagRE = re.compile(r'Is.*')
1390
1391# OpClass constants are just a little more complicated
1392opClassRE = re.compile(r'Int.*|Float.*|.*Port|No_OpClass')
1393
1394class InstObjParams:
1395    def __init__(self, mnem, class_name, base_class = '',
1396                 code_block = None, opt_args = []):
1397        self.mnemonic = mnem
1398        self.class_name = class_name
1399        self.base_class = base_class
1400        if code_block:
1401            for code_attr in code_block.__dict__.keys():
1402                setattr(self, code_attr, getattr(code_block, code_attr))
1403        else:
1404            self.constructor = ''
1405            self.flags = []
1406        # Optional arguments are assumed to be either StaticInst flags
1407        # or an OpClass value.  To avoid having to import a complete
1408        # list of these values to match against, we do it ad-hoc
1409        # with regexps.
1410        for oa in opt_args:
1411            if instFlagRE.match(oa):
1412                self.flags.append(oa)
1413            elif opClassRE.match(oa):
1414                self.op_class = oa
1415            else:
1416                error(0, 'InstObjParams: optional arg "%s" not recognized '
1417                      'as StaticInst::Flag or OpClass.' % oa)
1418
1419        # add flag initialization to contructor here to include
1420        # any flags added via opt_args
1421        self.constructor += makeFlagConstructor(self.flags)
1422
1423        # if 'IsFloating' is set, add call to the FP enable check
1424        # function (which should be provided by isa_desc via a declare)
1425        if 'IsFloating' in self.flags:
1426            self.fp_enable_check = 'fault = checkFpEnableFault(xc);'
1427        else:
1428            self.fp_enable_check = ''
1429
1430    def subst(self, *args):
1431        result = []
1432        for t in args:
1433            if not templateMap.has_key(t):
1434                error(0, 'InstObjParams::subst: undefined template "%s"' % t)
1435            try:
1436                result.append(templateMap[t] % self.__dict__)
1437            except KeyError, key:
1438                error(0, 'InstObjParams::subst: no definition for "%s"' % key)
1439        if len(args) == 1:
1440            result = result[0]
1441        return result
1442
1443#
1444# All set... read in and parse the ISA description.
1445#
1446yacc.parse(isa_desc)
1447