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:
parent
59ba3d463c
commit
3cc6c59582
4 changed files with 199 additions and 98 deletions
|
@ -34,47 +34,47 @@ decode OPCODE default Unknown::unknown() {
|
||||||
}
|
}
|
||||||
|
|
||||||
format LoadOrNop {
|
format LoadOrNop {
|
||||||
0x0a: ldbu({{ EA = Rb + disp; }}, {{ Ra.uq = Mem.ub; }});
|
0x0a: ldbu({{ Ra.uq = Mem.ub; }});
|
||||||
0x0c: ldwu({{ EA = Rb + disp; }}, {{ Ra.uq = Mem.uw; }});
|
0x0c: ldwu({{ Ra.uq = Mem.uw; }});
|
||||||
0x0b: ldq_u({{ EA = (Rb + disp) & ~7; }}, {{ Ra = Mem.uq; }});
|
0x0b: ldq_u({{ Ra = Mem.uq; }}, ea_code = {{ EA = (Rb + disp) & ~7; }});
|
||||||
0x23: ldt({{ EA = Rb + disp; }}, {{ Fa = Mem.df; }});
|
0x23: ldt({{ Fa = Mem.df; }});
|
||||||
0x2a: ldl_l({{ EA = Rb + disp; }}, {{ Ra.sl = Mem.sl; }}, LOCKED);
|
0x2a: ldl_l({{ Ra.sl = Mem.sl; }}, mem_flags = LOCKED);
|
||||||
0x2b: ldq_l({{ EA = Rb + disp; }}, {{ Ra.uq = Mem.uq; }}, LOCKED);
|
0x2b: ldq_l({{ Ra.uq = Mem.uq; }}, mem_flags = LOCKED);
|
||||||
0x20: MiscPrefetch::copy_load({{ EA = Ra; }},
|
0x20: MiscPrefetch::copy_load({{ EA = Ra; }},
|
||||||
{{ fault = xc->copySrcTranslate(EA); }},
|
{{ fault = xc->copySrcTranslate(EA); }},
|
||||||
IsMemRef, IsLoad, IsCopy);
|
inst_flags = [IsMemRef, IsLoad, IsCopy]);
|
||||||
}
|
}
|
||||||
|
|
||||||
format LoadOrPrefetch {
|
format LoadOrPrefetch {
|
||||||
0x28: ldl({{ EA = Rb + disp; }}, {{ Ra.sl = Mem.sl; }});
|
0x28: ldl({{ Ra.sl = Mem.sl; }});
|
||||||
0x29: ldq({{ EA = Rb + disp; }}, {{ Ra.uq = Mem.uq; }}, EVICT_NEXT);
|
0x29: ldq({{ Ra.uq = Mem.uq; }}, pf_flags = EVICT_NEXT);
|
||||||
// IsFloating flag on lds gets the prefetch to disassemble
|
// IsFloating flag on lds gets the prefetch to disassemble
|
||||||
// using f31 instead of r31... funcitonally it's unnecessary
|
// using f31 instead of r31... funcitonally it's unnecessary
|
||||||
0x22: lds({{ EA = Rb + disp; }}, {{ Fa.uq = s_to_t(Mem.ul); }},
|
0x22: lds({{ Fa.uq = s_to_t(Mem.ul); }},
|
||||||
PF_EXCLUSIVE, IsFloating);
|
pf_flags = PF_EXCLUSIVE, inst_flags = IsFloating);
|
||||||
}
|
}
|
||||||
|
|
||||||
format Store {
|
format Store {
|
||||||
0x0e: stb({{ EA = Rb + disp; }}, {{ Mem.ub = Ra<7:0>; }});
|
0x0e: stb({{ Mem.ub = Ra<7:0>; }});
|
||||||
0x0d: stw({{ EA = Rb + disp; }}, {{ Mem.uw = Ra<15:0>; }});
|
0x0d: stw({{ Mem.uw = Ra<15:0>; }});
|
||||||
0x2c: stl({{ EA = Rb + disp; }}, {{ Mem.ul = Ra<31:0>; }});
|
0x2c: stl({{ Mem.ul = Ra<31:0>; }});
|
||||||
0x2d: stq({{ EA = Rb + disp; }}, {{ Mem.uq = Ra.uq; }});
|
0x2d: stq({{ Mem.uq = Ra.uq; }});
|
||||||
0x0f: stq_u({{ EA = (Rb + disp) & ~7; }}, {{ Mem.uq = Ra.uq; }});
|
0x0f: stq_u({{ Mem.uq = Ra.uq; }}, {{ EA = (Rb + disp) & ~7; }});
|
||||||
0x26: sts({{ EA = Rb + disp; }}, {{ Mem.ul = t_to_s(Fa.uq); }});
|
0x26: sts({{ Mem.ul = t_to_s(Fa.uq); }});
|
||||||
0x27: stt({{ EA = Rb + disp; }}, {{ Mem.df = Fa; }});
|
0x27: stt({{ Mem.df = Fa; }});
|
||||||
0x24: MiscPrefetch::copy_store({{ EA = Rb; }},
|
0x24: MiscPrefetch::copy_store({{ EA = Rb; }},
|
||||||
{{ fault = xc->copy(EA); }},
|
{{ fault = xc->copy(EA); }},
|
||||||
IsMemRef, IsStore, IsCopy);
|
inst_flags = [IsMemRef, IsStore, IsCopy]);
|
||||||
}
|
}
|
||||||
|
|
||||||
format StoreCond {
|
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;
|
uint64_t tmp = write_result;
|
||||||
// see stq_c
|
// see stq_c
|
||||||
Ra = (tmp == 0 || tmp == 1) ? tmp : Ra;
|
Ra = (tmp == 0 || tmp == 1) ? tmp : Ra;
|
||||||
}}, LOCKED);
|
}}, mem_flags = LOCKED);
|
||||||
0x2f: stq_c({{ EA = Rb + disp; }}, {{ Mem.uq = Ra; }},
|
0x2f: stq_c({{ Mem.uq = Ra; }},
|
||||||
{{
|
{{
|
||||||
uint64_t tmp = write_result;
|
uint64_t tmp = write_result;
|
||||||
// If the write operation returns 0 or 1, then
|
// 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
|
// mailbox access, and we don't update the
|
||||||
// result register at all.
|
// result register at all.
|
||||||
Ra = (tmp == 0 || tmp == 1) ? tmp : Ra;
|
Ra = (tmp == 0 || tmp == 1) ? tmp : Ra;
|
||||||
}}, LOCKED);
|
}}, mem_flags = LOCKED);
|
||||||
}
|
}
|
||||||
|
|
||||||
format IntegerOperate {
|
format IntegerOperate {
|
||||||
|
@ -607,8 +607,9 @@ decode OPCODE default Unknown::unknown() {
|
||||||
format MiscPrefetch {
|
format MiscPrefetch {
|
||||||
0xf800: wh64({{ EA = Rb & ~ULL(63); }},
|
0xf800: wh64({{ EA = Rb & ~ULL(63); }},
|
||||||
{{ xc->writeHint(EA, 64, memAccessFlags); }},
|
{{ xc->writeHint(EA, 64, memAccessFlags); }},
|
||||||
IsMemRef, IsDataPrefetch, IsStore, MemWriteOp,
|
mem_flags = NO_FAULT,
|
||||||
NO_FAULT);
|
inst_flags = [IsMemRef, IsDataPrefetch,
|
||||||
|
IsStore, MemWriteOp]);
|
||||||
}
|
}
|
||||||
|
|
||||||
format BasicOperate {
|
format BasicOperate {
|
||||||
|
|
|
@ -407,16 +407,12 @@ def template LoadPrefetchCheckDecode {{
|
||||||
|
|
||||||
|
|
||||||
let {{
|
let {{
|
||||||
def LoadStoreBase(name, Name, ea_code, memacc_code, postacc_code = '',
|
def LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
|
||||||
base_class = 'MemoryDisp32', flags = [],
|
postacc_code = '', base_class = 'MemoryDisp32',
|
||||||
decode_template = BasicDecode, exec_template_base = ''):
|
decode_template = BasicDecode, exec_template_base = ''):
|
||||||
# Segregate flags into instruction flags (handled by InstObjParams)
|
# Make sure flags are in lists (convert to lists if not).
|
||||||
# and memory access flags (handled here).
|
mem_flags = makeList(mem_flags)
|
||||||
|
inst_flags = makeList(inst_flags)
|
||||||
# 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]
|
|
||||||
|
|
||||||
# add hook to get effective addresses into execution trace output.
|
# add hook to get effective addresses into execution trace output.
|
||||||
ea_code += '\nif (traceData) { traceData->setAddr(EA); }\n'
|
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) = \
|
(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,
|
decode_template = LoadNopCheckDecode,
|
||||||
exec_template_base = 'Load')
|
exec_template_base = 'Load')
|
||||||
}};
|
}};
|
||||||
|
|
||||||
|
|
||||||
// Note that the flags passed in apply only to the prefetch version
|
// 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
|
# declare the load instruction object and generate the decode block
|
||||||
(header_output, decoder_output, decode_block, exec_output) = \
|
(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,
|
decode_template = LoadPrefetchCheckDecode,
|
||||||
exec_template_base = 'Load')
|
exec_template_base = 'Load')
|
||||||
|
|
||||||
# Declare the prefetch instruction object.
|
# Declare the prefetch instruction object.
|
||||||
|
|
||||||
# convert flags from tuple to list to make them mutable
|
# Make sure flag args are lists so we can mess with them.
|
||||||
pf_flags = list(pf_flags) + ['IsMemRef', 'IsLoad', 'IsDataPrefetch', 'MemReadOp', 'NO_FAULT']
|
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) = \
|
(pf_header_output, pf_decoder_output, _, pf_exec_output) = \
|
||||||
LoadStoreBase(name, Name + 'Prefetch', ea_code,
|
LoadStoreBase(name, Name + 'Prefetch', ea_code,
|
||||||
'xc->prefetch(EA, memAccessFlags);',
|
'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
|
header_output += pf_header_output
|
||||||
decoder_output += pf_decoder_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) = \
|
(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')
|
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) = \
|
(header_output, decoder_output, decode_block, exec_output) = \
|
||||||
LoadStoreBase(name, Name, ea_code, memacc_code, postacc_code,
|
LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
|
||||||
flags = flags, exec_template_base = 'Store')
|
postacc_code, exec_template_base = 'Store')
|
||||||
}};
|
}};
|
||||||
|
|
||||||
|
|
||||||
// Use 'MemoryNoDisp' as base: for wh64, fetch, ecb
|
// 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) = \
|
(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')
|
base_class = 'MemoryNoDisp', exec_template_base = 'Misc')
|
||||||
}};
|
}};
|
||||||
|
|
||||||
|
|
|
@ -198,23 +198,25 @@ output decoder {{
|
||||||
def format HwLoad(ea_code, memacc_code, class_ext, *flags) {{
|
def format HwLoad(ea_code, memacc_code, class_ext, *flags) {{
|
||||||
(header_output, decoder_output, decode_block, exec_output) = \
|
(header_output, decoder_output, decode_block, exec_output) = \
|
||||||
LoadStoreBase(name, Name + class_ext, ea_code, memacc_code,
|
LoadStoreBase(name, Name + class_ext, ea_code, memacc_code,
|
||||||
flags = flags, base_class = 'HwLoadStore',
|
mem_flags = [], inst_flags = flags,
|
||||||
exec_template_base = 'Load')
|
base_class = 'HwLoadStore', exec_template_base = 'Load')
|
||||||
}};
|
}};
|
||||||
|
|
||||||
|
|
||||||
def format HwStore(ea_code, memacc_code, class_ext, *flags) {{
|
def format HwStore(ea_code, memacc_code, class_ext, *flags) {{
|
||||||
(header_output, decoder_output, decode_block, exec_output) = \
|
(header_output, decoder_output, decode_block, exec_output) = \
|
||||||
LoadStoreBase(name, Name + class_ext, ea_code, memacc_code,
|
LoadStoreBase(name, Name + class_ext, ea_code, memacc_code,
|
||||||
flags = flags, base_class = 'HwLoadStore',
|
mem_flags = [], inst_flags = flags,
|
||||||
exec_template_base = 'Store')
|
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) = \
|
(header_output, decoder_output, decode_block, exec_output) = \
|
||||||
LoadStoreBase(name, Name + class_ext, ea_code, memacc_code,
|
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')
|
||||||
}};
|
}};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -82,10 +82,9 @@ tokens = reserved + (
|
||||||
|
|
||||||
# ( ) [ ] { } < > , ; : :: *
|
# ( ) [ ] { } < > , ; : :: *
|
||||||
'LPAREN', 'RPAREN',
|
'LPAREN', 'RPAREN',
|
||||||
# not used any more... commented out to suppress PLY warning
|
'LBRACKET', 'RBRACKET',
|
||||||
# 'LBRACKET', 'RBRACKET',
|
|
||||||
'LBRACE', 'RBRACE',
|
'LBRACE', 'RBRACE',
|
||||||
'LESS', 'GREATER',
|
'LESS', 'GREATER', 'EQUALS',
|
||||||
'COMMA', 'SEMI', 'COLON', 'DBLCOLON',
|
'COMMA', 'SEMI', 'COLON', 'DBLCOLON',
|
||||||
'ASTERISK',
|
'ASTERISK',
|
||||||
|
|
||||||
|
@ -104,13 +103,13 @@ tokens = reserved + (
|
||||||
# Regular expressions for token matching
|
# Regular expressions for token matching
|
||||||
t_LPAREN = r'\('
|
t_LPAREN = r'\('
|
||||||
t_RPAREN = r'\)'
|
t_RPAREN = r'\)'
|
||||||
# not used any more... commented out to suppress PLY warning
|
t_LBRACKET = r'\['
|
||||||
# t_LBRACKET = r'\['
|
t_RBRACKET = r'\]'
|
||||||
# t_RBRACKET = r'\]'
|
|
||||||
t_LBRACE = r'\{'
|
t_LBRACE = r'\{'
|
||||||
t_RBRACE = r'\}'
|
t_RBRACE = r'\}'
|
||||||
t_LESS = r'\<'
|
t_LESS = r'\<'
|
||||||
t_GREATER = r'\>'
|
t_GREATER = r'\>'
|
||||||
|
t_EQUALS = r'='
|
||||||
t_COMMA = r','
|
t_COMMA = r','
|
||||||
t_SEMI = r';'
|
t_SEMI = r';'
|
||||||
t_COLON = r':'
|
t_COLON = r':'
|
||||||
|
@ -387,32 +386,66 @@ def p_def_format(t):
|
||||||
t[0] = GenCode()
|
t[0] = GenCode()
|
||||||
|
|
||||||
# The formal parameter list for an instruction format is a possibly
|
# 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):
|
def p_param_list_0(t):
|
||||||
'param_list : empty'
|
'param_list : positional_param_list COMMA nonpositional_param_list'
|
||||||
t[0] = [ ]
|
t[0] = t[1] + t[3]
|
||||||
|
|
||||||
def p_param_list_1(t):
|
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]]
|
t[0] = [t[1]]
|
||||||
|
|
||||||
def p_param_list_2(t):
|
def p_positional_param_list_2(t):
|
||||||
'param_list : param_list COMMA param'
|
'positional_param_list : positional_param_list COMMA ID'
|
||||||
t[0] = t[1]
|
t[0] = t[1] + [t[3]]
|
||||||
t[0].append(t[3])
|
|
||||||
|
|
||||||
# Each formal parameter is either an identifier or an identifier
|
def p_nonpositional_param_list_0(t):
|
||||||
# preceded by an asterisk. As in Python, the latter (if present) gets
|
'nonpositional_param_list : keyword_param_list COMMA excess_args_param'
|
||||||
# a tuple containing all the excess positional arguments, allowing
|
t[0] = t[1] + t[3]
|
||||||
# varargs functions.
|
|
||||||
def p_param_0(t):
|
def p_nonpositional_param_list_1(t):
|
||||||
'param : ID'
|
'''nonpositional_param_list : keyword_param_list
|
||||||
|
| excess_args_param'''
|
||||||
t[0] = t[1]
|
t[0] = t[1]
|
||||||
|
|
||||||
def p_param_1(t):
|
def p_keyword_param_list_0(t):
|
||||||
'param : ASTERISK ID'
|
'keyword_param_list : keyword_param'
|
||||||
# just concatenate them: '*ID'
|
t[0] = [t[1]]
|
||||||
t[0] = t[1] + t[2]
|
|
||||||
|
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.
|
# End of format definition-related rules.
|
||||||
##############
|
##############
|
||||||
|
@ -577,26 +610,79 @@ def p_inst_1(t):
|
||||||
codeObj.prepend_all(comment)
|
codeObj.prepend_all(comment)
|
||||||
t[0] = codeObj
|
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):
|
def p_arg_list_0(t):
|
||||||
'arg_list : empty'
|
'arg_list : positional_arg_list COMMA keyword_arg_list'
|
||||||
t[0] = [ ]
|
t[0] = ( t[1], t[3] )
|
||||||
|
|
||||||
def p_arg_list_1(t):
|
def p_arg_list_1(t):
|
||||||
'arg_list : arg'
|
'arg_list : positional_arg_list'
|
||||||
t[0] = [t[1]]
|
t[0] = ( t[1], {} )
|
||||||
|
|
||||||
def p_arg_list_2(t):
|
def p_arg_list_2(t):
|
||||||
'arg_list : arg_list COMMA arg'
|
'arg_list : keyword_arg_list'
|
||||||
t[0] = t[1]
|
t[0] = ( [], t[1] )
|
||||||
t[0].append(t[3])
|
|
||||||
|
|
||||||
def p_arg(t):
|
def p_positional_arg_list_0(t):
|
||||||
'''arg : ID
|
'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
|
| INTLIT
|
||||||
| STRLIT
|
| STRLIT
|
||||||
| CODELIT'''
|
| CODELIT'''
|
||||||
t[0] = t[1]
|
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.
|
# Empty production... use in other rules for readability.
|
||||||
#
|
#
|
||||||
|
@ -779,7 +865,7 @@ class Format:
|
||||||
context.update(exportContext)
|
context.update(exportContext)
|
||||||
context.update({ 'name': name, 'Name': string.capitalize(name) })
|
context.update({ 'name': name, 'Name': string.capitalize(name) })
|
||||||
try:
|
try:
|
||||||
vars = self.func(self.user_code, context, *args)
|
vars = self.func(self.user_code, context, *args[0], **args[1])
|
||||||
except Exception, exc:
|
except Exception, exc:
|
||||||
error(lineno, 'error defining "%s": %s.' % (name, exc))
|
error(lineno, 'error defining "%s": %s.' % (name, exc))
|
||||||
for k in vars.keys():
|
for k in vars.keys():
|
||||||
|
@ -974,14 +1060,18 @@ class Template:
|
||||||
#
|
#
|
||||||
#####################################################################
|
#####################################################################
|
||||||
|
|
||||||
# Force the argument to be a list
|
# Force the argument to be a list. Useful for flags, where a caller
|
||||||
def makeList(list_or_item):
|
# can specify a singleton flag or a list of flags. Also usful for
|
||||||
if not list_or_item:
|
# 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 []
|
return []
|
||||||
elif type(list_or_item) == ListType:
|
|
||||||
return list_or_item
|
|
||||||
else:
|
else:
|
||||||
return [ list_or_item ]
|
return [ arg ]
|
||||||
|
|
||||||
# generate operandSizeMap based on provided operandTypeMap:
|
# generate operandSizeMap based on provided operandTypeMap:
|
||||||
# basically generate equiv. C++ type and make is_signed flag
|
# basically generate equiv. C++ type and make is_signed flag
|
||||||
|
@ -1253,7 +1343,7 @@ class NPCOperandTraits(OperandTraits):
|
||||||
exportContextSymbols = ('IntRegOperandTraits', 'FloatRegOperandTraits',
|
exportContextSymbols = ('IntRegOperandTraits', 'FloatRegOperandTraits',
|
||||||
'ControlRegOperandTraits', 'MemOperandTraits',
|
'ControlRegOperandTraits', 'MemOperandTraits',
|
||||||
'NPCOperandTraits', 'InstObjParams', 'CodeBlock',
|
'NPCOperandTraits', 'InstObjParams', 'CodeBlock',
|
||||||
're', 'string')
|
'makeList', 're', 'string')
|
||||||
|
|
||||||
exportContext = {}
|
exportContext = {}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue