Add keyword parameters and list-valued arguments to

instruction format functions in ISA description language.

Take advantage of these features to clean up memory
instruction definitions in Alpha.

arch/alpha/isa/decoder.isa:
arch/alpha/isa/mem.isa:
arch/alpha/isa/pal.isa:
    Take advantage of new keyword parameters to disambiguate
    instruction vs. memory-request flags, and to provide
    a default EA calculation for memory ops (since 99% of them
    are the same).
arch/isa_parser.py:
    Add two new features to instruction format functions:
    - Keyword parameters, a la Python.
    - List-valued arguments.

    Also export makeList() function to Python code blocks,
    as this is handy for dealing with flags.

--HG--
extra : convert_revision : 99bbbaa2e765230aa96b6a06ed193793325f9fb0
This commit is contained in:
Steve Reinhardt 2006-02-11 15:11:00 -05:00
parent 59ba3d463c
commit 3cc6c59582
4 changed files with 199 additions and 98 deletions

View file

@ -34,47 +34,47 @@ decode OPCODE default Unknown::unknown() {
}
format LoadOrNop {
0x0a: ldbu({{ EA = Rb + disp; }}, {{ Ra.uq = Mem.ub; }});
0x0c: ldwu({{ EA = Rb + disp; }}, {{ Ra.uq = Mem.uw; }});
0x0b: ldq_u({{ EA = (Rb + disp) & ~7; }}, {{ Ra = Mem.uq; }});
0x23: ldt({{ EA = Rb + disp; }}, {{ Fa = Mem.df; }});
0x2a: ldl_l({{ EA = Rb + disp; }}, {{ Ra.sl = Mem.sl; }}, LOCKED);
0x2b: ldq_l({{ EA = Rb + disp; }}, {{ Ra.uq = Mem.uq; }}, LOCKED);
0x0a: ldbu({{ Ra.uq = Mem.ub; }});
0x0c: ldwu({{ Ra.uq = Mem.uw; }});
0x0b: ldq_u({{ Ra = Mem.uq; }}, ea_code = {{ EA = (Rb + disp) & ~7; }});
0x23: ldt({{ Fa = Mem.df; }});
0x2a: ldl_l({{ Ra.sl = Mem.sl; }}, mem_flags = LOCKED);
0x2b: ldq_l({{ Ra.uq = Mem.uq; }}, mem_flags = LOCKED);
0x20: MiscPrefetch::copy_load({{ EA = Ra; }},
{{ fault = xc->copySrcTranslate(EA); }},
IsMemRef, IsLoad, IsCopy);
inst_flags = [IsMemRef, IsLoad, IsCopy]);
}
format LoadOrPrefetch {
0x28: ldl({{ EA = Rb + disp; }}, {{ Ra.sl = Mem.sl; }});
0x29: ldq({{ EA = Rb + disp; }}, {{ Ra.uq = Mem.uq; }}, EVICT_NEXT);
0x28: ldl({{ Ra.sl = Mem.sl; }});
0x29: ldq({{ Ra.uq = Mem.uq; }}, pf_flags = EVICT_NEXT);
// IsFloating flag on lds gets the prefetch to disassemble
// using f31 instead of r31... funcitonally it's unnecessary
0x22: lds({{ EA = Rb + disp; }}, {{ Fa.uq = s_to_t(Mem.ul); }},
PF_EXCLUSIVE, IsFloating);
0x22: lds({{ Fa.uq = s_to_t(Mem.ul); }},
pf_flags = PF_EXCLUSIVE, inst_flags = IsFloating);
}
format Store {
0x0e: stb({{ EA = Rb + disp; }}, {{ Mem.ub = Ra<7:0>; }});
0x0d: stw({{ EA = Rb + disp; }}, {{ Mem.uw = Ra<15:0>; }});
0x2c: stl({{ EA = Rb + disp; }}, {{ Mem.ul = Ra<31:0>; }});
0x2d: stq({{ EA = Rb + disp; }}, {{ Mem.uq = Ra.uq; }});
0x0f: stq_u({{ EA = (Rb + disp) & ~7; }}, {{ Mem.uq = Ra.uq; }});
0x26: sts({{ EA = Rb + disp; }}, {{ Mem.ul = t_to_s(Fa.uq); }});
0x27: stt({{ EA = Rb + disp; }}, {{ Mem.df = Fa; }});
0x0e: stb({{ Mem.ub = Ra<7:0>; }});
0x0d: stw({{ Mem.uw = Ra<15:0>; }});
0x2c: stl({{ Mem.ul = Ra<31:0>; }});
0x2d: stq({{ Mem.uq = Ra.uq; }});
0x0f: stq_u({{ Mem.uq = Ra.uq; }}, {{ EA = (Rb + disp) & ~7; }});
0x26: sts({{ Mem.ul = t_to_s(Fa.uq); }});
0x27: stt({{ Mem.df = Fa; }});
0x24: MiscPrefetch::copy_store({{ EA = Rb; }},
{{ fault = xc->copy(EA); }},
IsMemRef, IsStore, IsCopy);
inst_flags = [IsMemRef, IsStore, IsCopy]);
}
format StoreCond {
0x2e: stl_c({{ EA = Rb + disp; }}, {{ Mem.ul = Ra<31:0>; }},
0x2e: stl_c({{ Mem.ul = Ra<31:0>; }},
{{
uint64_t tmp = write_result;
// see stq_c
Ra = (tmp == 0 || tmp == 1) ? tmp : Ra;
}}, LOCKED);
0x2f: stq_c({{ EA = Rb + disp; }}, {{ Mem.uq = Ra; }},
}}, mem_flags = LOCKED);
0x2f: stq_c({{ Mem.uq = Ra; }},
{{
uint64_t tmp = write_result;
// If the write operation returns 0 or 1, then
@ -85,7 +85,7 @@ decode OPCODE default Unknown::unknown() {
// mailbox access, and we don't update the
// result register at all.
Ra = (tmp == 0 || tmp == 1) ? tmp : Ra;
}}, LOCKED);
}}, mem_flags = LOCKED);
}
format IntegerOperate {
@ -607,8 +607,9 @@ decode OPCODE default Unknown::unknown() {
format MiscPrefetch {
0xf800: wh64({{ EA = Rb & ~ULL(63); }},
{{ xc->writeHint(EA, 64, memAccessFlags); }},
IsMemRef, IsDataPrefetch, IsStore, MemWriteOp,
NO_FAULT);
mem_flags = NO_FAULT,
inst_flags = [IsMemRef, IsDataPrefetch,
IsStore, MemWriteOp]);
}
format BasicOperate {

View file

@ -407,16 +407,12 @@ def template LoadPrefetchCheckDecode {{
let {{
def LoadStoreBase(name, Name, ea_code, memacc_code, postacc_code = '',
base_class = 'MemoryDisp32', flags = [],
def LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
postacc_code = '', base_class = 'MemoryDisp32',
decode_template = BasicDecode, exec_template_base = ''):
# Segregate flags into instruction flags (handled by InstObjParams)
# and memory access flags (handled here).
# Would be nice to autogenerate this list, but oh well.
valid_mem_flags = ['LOCKED', 'NO_FAULT', 'EVICT_NEXT', 'PF_EXCLUSIVE']
mem_flags = [f for f in flags if f in valid_mem_flags]
inst_flags = [f for f in flags if f not in valid_mem_flags]
# Make sure flags are in lists (convert to lists if not).
mem_flags = makeList(mem_flags)
inst_flags = makeList(inst_flags)
# add hook to get effective addresses into execution trace output.
ea_code += '\nif (traceData) { traceData->setAddr(EA); }\n'
@ -469,31 +465,39 @@ def LoadStoreBase(name, Name, ea_code, memacc_code, postacc_code = '',
}};
def format LoadOrNop(ea_code, memacc_code, *flags) {{
def format LoadOrNop(memacc_code, ea_code = {{ EA = Rb + disp; }},
mem_flags = [], inst_flags = []) {{
(header_output, decoder_output, decode_block, exec_output) = \
LoadStoreBase(name, Name, ea_code, memacc_code, flags = flags,
LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
decode_template = LoadNopCheckDecode,
exec_template_base = 'Load')
}};
// Note that the flags passed in apply only to the prefetch version
def format LoadOrPrefetch(ea_code, memacc_code, *pf_flags) {{
def format LoadOrPrefetch(memacc_code, ea_code = {{ EA = Rb + disp; }},
mem_flags = [], pf_flags = [], inst_flags = []) {{
# declare the load instruction object and generate the decode block
(header_output, decoder_output, decode_block, exec_output) = \
LoadStoreBase(name, Name, ea_code, memacc_code,
LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
decode_template = LoadPrefetchCheckDecode,
exec_template_base = 'Load')
# Declare the prefetch instruction object.
# convert flags from tuple to list to make them mutable
pf_flags = list(pf_flags) + ['IsMemRef', 'IsLoad', 'IsDataPrefetch', 'MemReadOp', 'NO_FAULT']
# Make sure flag args are lists so we can mess with them.
mem_flags = makeList(mem_flags)
pf_flags = makeList(pf_flags)
inst_flags = makeList(inst_flags)
pf_mem_flags = mem_flags + pf_flags + ['NO_FAULT']
pf_inst_flags = inst_flags + ['IsMemRef', 'IsLoad',
'IsDataPrefetch', 'MemReadOp']
(pf_header_output, pf_decoder_output, _, pf_exec_output) = \
LoadStoreBase(name, Name + 'Prefetch', ea_code,
'xc->prefetch(EA, memAccessFlags);',
flags = pf_flags, exec_template_base = 'Misc')
pf_mem_flags, pf_inst_flags, exec_template_base = 'Misc')
header_output += pf_header_output
decoder_output += pf_decoder_output
@ -501,24 +505,28 @@ def format LoadOrPrefetch(ea_code, memacc_code, *pf_flags) {{
}};
def format Store(ea_code, memacc_code, *flags) {{
def format Store(memacc_code, ea_code = {{ EA = Rb + disp; }},
mem_flags = [], inst_flags = []) {{
(header_output, decoder_output, decode_block, exec_output) = \
LoadStoreBase(name, Name, ea_code, memacc_code, flags = flags,
LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
exec_template_base = 'Store')
}};
def format StoreCond(ea_code, memacc_code, postacc_code, *flags) {{
def format StoreCond(memacc_code, postacc_code,
ea_code = {{ EA = Rb + disp; }},
mem_flags = [], inst_flags = []) {{
(header_output, decoder_output, decode_block, exec_output) = \
LoadStoreBase(name, Name, ea_code, memacc_code, postacc_code,
flags = flags, exec_template_base = 'Store')
LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
postacc_code, exec_template_base = 'Store')
}};
// Use 'MemoryNoDisp' as base: for wh64, fetch, ecb
def format MiscPrefetch(ea_code, memacc_code, *flags) {{
def format MiscPrefetch(ea_code, memacc_code,
mem_flags = [], inst_flags = []) {{
(header_output, decoder_output, decode_block, exec_output) = \
LoadStoreBase(name, Name, ea_code, memacc_code, flags = flags,
LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
base_class = 'MemoryNoDisp', exec_template_base = 'Misc')
}};

View file

@ -198,23 +198,25 @@ output decoder {{
def format HwLoad(ea_code, memacc_code, class_ext, *flags) {{
(header_output, decoder_output, decode_block, exec_output) = \
LoadStoreBase(name, Name + class_ext, ea_code, memacc_code,
flags = flags, base_class = 'HwLoadStore',
exec_template_base = 'Load')
mem_flags = [], inst_flags = flags,
base_class = 'HwLoadStore', exec_template_base = 'Load')
}};
def format HwStore(ea_code, memacc_code, class_ext, *flags) {{
(header_output, decoder_output, decode_block, exec_output) = \
LoadStoreBase(name, Name + class_ext, ea_code, memacc_code,
flags = flags, base_class = 'HwLoadStore',
exec_template_base = 'Store')
mem_flags = [], inst_flags = flags,
base_class = 'HwLoadStore', exec_template_base = 'Store')
}};
def format HwStoreCond(ea_code, memacc_code, postacc_code, class_ext, *flags) {{
def format HwStoreCond(ea_code, memacc_code, postacc_code, class_ext,
*flags) {{
(header_output, decoder_output, decode_block, exec_output) = \
LoadStoreBase(name, Name + class_ext, ea_code, memacc_code,
postacc_code, flags = flags, base_class = 'HwLoadStore')
postacc_code, mem_flags = [], inst_flags = flags,
base_class = 'HwLoadStore')
}};

View file

@ -82,10 +82,9 @@ tokens = reserved + (
# ( ) [ ] { } < > , ; : :: *
'LPAREN', 'RPAREN',
# not used any more... commented out to suppress PLY warning
# 'LBRACKET', 'RBRACKET',
'LBRACKET', 'RBRACKET',
'LBRACE', 'RBRACE',
'LESS', 'GREATER',
'LESS', 'GREATER', 'EQUALS',
'COMMA', 'SEMI', 'COLON', 'DBLCOLON',
'ASTERISK',
@ -104,13 +103,13 @@ tokens = reserved + (
# Regular expressions for token matching
t_LPAREN = r'\('
t_RPAREN = r'\)'
# not used any more... commented out to suppress PLY warning
# t_LBRACKET = r'\['
# t_RBRACKET = r'\]'
t_LBRACKET = r'\['
t_RBRACKET = r'\]'
t_LBRACE = r'\{'
t_RBRACE = r'\}'
t_LESS = r'\<'
t_GREATER = r'\>'
t_EQUALS = r'='
t_COMMA = r','
t_SEMI = r';'
t_COLON = r':'
@ -387,32 +386,66 @@ def p_def_format(t):
t[0] = GenCode()
# The formal parameter list for an instruction format is a possibly
# empty list of comma-separated parameters.
# empty list of comma-separated parameters. Positional (standard,
# non-keyword) parameters must come first, followed by keyword
# parameters, followed by a '*foo' parameter that gets excess
# positional arguments (as in Python). Each of these three parameter
# categories is optional.
#
# Note that we do not support the '**foo' parameter for collecting
# otherwise undefined keyword args. Otherwise the parameter list is
# (I believe) identical to what is supported in Python.
#
# The param list generates a tuple, where the first element is a list of
# the positional params and the second element is a dict containing the
# keyword params.
def p_param_list_0(t):
'param_list : empty'
t[0] = [ ]
'param_list : positional_param_list COMMA nonpositional_param_list'
t[0] = t[1] + t[3]
def p_param_list_1(t):
'param_list : param'
'''param_list : positional_param_list
| nonpositional_param_list'''
t[0] = t[1]
def p_positional_param_list_0(t):
'positional_param_list : empty'
t[0] = []
def p_positional_param_list_1(t):
'positional_param_list : ID'
t[0] = [t[1]]
def p_param_list_2(t):
'param_list : param_list COMMA param'
t[0] = t[1]
t[0].append(t[3])
def p_positional_param_list_2(t):
'positional_param_list : positional_param_list COMMA ID'
t[0] = t[1] + [t[3]]
# Each formal parameter is either an identifier or an identifier
# preceded by an asterisk. As in Python, the latter (if present) gets
# a tuple containing all the excess positional arguments, allowing
# varargs functions.
def p_param_0(t):
'param : ID'
def p_nonpositional_param_list_0(t):
'nonpositional_param_list : keyword_param_list COMMA excess_args_param'
t[0] = t[1] + t[3]
def p_nonpositional_param_list_1(t):
'''nonpositional_param_list : keyword_param_list
| excess_args_param'''
t[0] = t[1]
def p_param_1(t):
'param : ASTERISK ID'
# just concatenate them: '*ID'
t[0] = t[1] + t[2]
def p_keyword_param_list_0(t):
'keyword_param_list : keyword_param'
t[0] = [t[1]]
def p_keyword_param_list_1(t):
'keyword_param_list : keyword_param_list COMMA keyword_param'
t[0] = t[1] + [t[3]]
def p_keyword_param(t):
'keyword_param : ID EQUALS expr'
t[0] = t[1] + ' = ' + t[3].__repr__()
def p_excess_args_param(t):
'excess_args_param : ASTERISK ID'
# Just concatenate them: '*ID'. Wrap in list to be consistent
# with positional_param_list and keyword_param_list.
t[0] = [t[1] + t[2]]
# End of format definition-related rules.
##############
@ -577,26 +610,79 @@ def p_inst_1(t):
codeObj.prepend_all(comment)
t[0] = codeObj
# The arg list generates a tuple, where the first element is a list of
# the positional args and the second element is a dict containing the
# keyword args.
def p_arg_list_0(t):
'arg_list : empty'
t[0] = [ ]
'arg_list : positional_arg_list COMMA keyword_arg_list'
t[0] = ( t[1], t[3] )
def p_arg_list_1(t):
'arg_list : arg'
t[0] = [t[1]]
'arg_list : positional_arg_list'
t[0] = ( t[1], {} )
def p_arg_list_2(t):
'arg_list : arg_list COMMA arg'
t[0] = t[1]
t[0].append(t[3])
'arg_list : keyword_arg_list'
t[0] = ( [], t[1] )
def p_arg(t):
'''arg : ID
| INTLIT
| STRLIT
| CODELIT'''
def p_positional_arg_list_0(t):
'positional_arg_list : empty'
t[0] = []
def p_positional_arg_list_1(t):
'positional_arg_list : expr'
t[0] = [t[1]]
def p_positional_arg_list_2(t):
'positional_arg_list : positional_arg_list COMMA expr'
t[0] = t[1] + [t[3]]
def p_keyword_arg_list_0(t):
'keyword_arg_list : keyword_arg'
t[0] = t[1]
def p_keyword_arg_list_1(t):
'keyword_arg_list : keyword_arg_list COMMA keyword_arg'
t[0] = t[1]
t[0].update(t[3])
def p_keyword_arg(t):
'keyword_arg : ID EQUALS expr'
t[0] = { t[1] : t[3] }
#
# Basic expressions. These constitute the argument values of
# "function calls" (i.e. instruction definitions in the decode block)
# and default values for formal parameters of format functions.
#
# Right now, these are either strings, integers, or (recursively)
# lists of exprs (using Python square-bracket list syntax). Note that
# bare identifiers are trated as string constants here (since there
# isn't really a variable namespace to refer to).
#
def p_expr_0(t):
'''expr : ID
| INTLIT
| STRLIT
| CODELIT'''
t[0] = t[1]
def p_expr_1(t):
'''expr : LBRACKET list_expr RBRACKET'''
t[0] = t[2]
def p_list_expr_0(t):
'list_expr : expr'
t[0] = [t[1]]
def p_list_expr_1(t):
'list_expr : list_expr COMMA expr'
t[0] = t[1] + [t[3]]
def p_list_expr_2(t):
'list_expr : empty'
t[0] = []
#
# Empty production... use in other rules for readability.
#
@ -779,7 +865,7 @@ class Format:
context.update(exportContext)
context.update({ 'name': name, 'Name': string.capitalize(name) })
try:
vars = self.func(self.user_code, context, *args)
vars = self.func(self.user_code, context, *args[0], **args[1])
except Exception, exc:
error(lineno, 'error defining "%s": %s.' % (name, exc))
for k in vars.keys():
@ -974,14 +1060,18 @@ class Template:
#
#####################################################################
# Force the argument to be a list
def makeList(list_or_item):
if not list_or_item:
# Force the argument to be a list. Useful for flags, where a caller
# can specify a singleton flag or a list of flags. Also usful for
# converting tuples to lists so they can be modified.
def makeList(arg):
if isinstance(arg, list):
return arg
elif isinstance(arg, tuple):
return list(arg)
elif not arg:
return []
elif type(list_or_item) == ListType:
return list_or_item
else:
return [ list_or_item ]
return [ arg ]
# generate operandSizeMap based on provided operandTypeMap:
# basically generate equiv. C++ type and make is_signed flag
@ -1253,7 +1343,7 @@ class NPCOperandTraits(OperandTraits):
exportContextSymbols = ('IntRegOperandTraits', 'FloatRegOperandTraits',
'ControlRegOperandTraits', 'MemOperandTraits',
'NPCOperandTraits', 'InstObjParams', 'CodeBlock',
're', 'string')
'makeList', 're', 'string')
exportContext = {}