mirror of
				https://github.com/yuzu-emu/unicorn.git
				synced 2025-11-04 13:54:48 +00:00 
			
		
		
		
	target/arm: Convert Neon VCVT fp size field to MO_* in decode
Convert the insns using the 2reg_vcvt and 2reg_vcvt_f16 formats to pass the size through to the trans function as a MO_* value rather than the '0==f32, 1==f16' used in the fp 3-same encodings. Backports commit 0ae715c658a02af1834b63563c56112a6d8842cb
This commit is contained in:
		
							parent
							
								
									524b54bc7b
								
							
						
					
					
						commit
						61abec1908
					
				| 
						 | 
					@ -42,8 +42,14 @@ output_fd = None
 | 
				
			||||||
insntype = 'uint32_t'
 | 
					insntype = 'uint32_t'
 | 
				
			||||||
decode_function = 'decode'
 | 
					decode_function = 'decode'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
re_ident = '[a-zA-Z][a-zA-Z0-9_]*'
 | 
					# An identifier for C.
 | 
				
			||||||
 | 
					re_C_ident = '[a-zA-Z][a-zA-Z0-9_]*'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Identifiers for Arguments, Fields, Formats and Patterns.
 | 
				
			||||||
 | 
					re_arg_ident = '&[a-zA-Z0-9_]*'
 | 
				
			||||||
 | 
					re_fld_ident = '%[a-zA-Z0-9_]*'
 | 
				
			||||||
 | 
					re_fmt_ident = '@[a-zA-Z0-9_]*'
 | 
				
			||||||
 | 
					re_pat_ident = '[a-zA-Z0-9_]*'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def error_with_file(file, lineno, *args):
 | 
					def error_with_file(file, lineno, *args):
 | 
				
			||||||
    """Print an error message from file:line and args and exit."""
 | 
					    """Print an error message from file:line and args and exit."""
 | 
				
			||||||
| 
						 | 
					@ -632,7 +638,6 @@ class ExcMultiPattern(MultiPattern):
 | 
				
			||||||
def parse_field(lineno, name, toks):
 | 
					def parse_field(lineno, name, toks):
 | 
				
			||||||
    """Parse one instruction field from TOKS at LINENO"""
 | 
					    """Parse one instruction field from TOKS at LINENO"""
 | 
				
			||||||
    global fields
 | 
					    global fields
 | 
				
			||||||
    global re_ident
 | 
					 | 
				
			||||||
    global insnwidth
 | 
					    global insnwidth
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # A "simple" field will have only one entry;
 | 
					    # A "simple" field will have only one entry;
 | 
				
			||||||
| 
						 | 
					@ -641,7 +646,7 @@ def parse_field(lineno, name, toks):
 | 
				
			||||||
    width = 0
 | 
					    width = 0
 | 
				
			||||||
    func = None
 | 
					    func = None
 | 
				
			||||||
    for t in toks:
 | 
					    for t in toks:
 | 
				
			||||||
        if re.fullmatch('!function=' + re_ident, t):
 | 
					        if re.match('^!function=', t):
 | 
				
			||||||
            if func:
 | 
					            if func:
 | 
				
			||||||
                error(lineno, 'duplicate function')
 | 
					                error(lineno, 'duplicate function')
 | 
				
			||||||
            func = t.split('=')
 | 
					            func = t.split('=')
 | 
				
			||||||
| 
						 | 
					@ -695,7 +700,7 @@ def parse_field(lineno, name, toks):
 | 
				
			||||||
def parse_arguments(lineno, name, toks):
 | 
					def parse_arguments(lineno, name, toks):
 | 
				
			||||||
    """Parse one argument set from TOKS at LINENO"""
 | 
					    """Parse one argument set from TOKS at LINENO"""
 | 
				
			||||||
    global arguments
 | 
					    global arguments
 | 
				
			||||||
    global re_ident
 | 
					    global re_C_ident
 | 
				
			||||||
    global anyextern
 | 
					    global anyextern
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    flds = []
 | 
					    flds = []
 | 
				
			||||||
| 
						 | 
					@ -705,7 +710,7 @@ def parse_arguments(lineno, name, toks):
 | 
				
			||||||
            extern = True
 | 
					            extern = True
 | 
				
			||||||
            anyextern = True
 | 
					            anyextern = True
 | 
				
			||||||
            continue
 | 
					            continue
 | 
				
			||||||
        if not re.fullmatch(re_ident, t):
 | 
					        if not re.fullmatch(re_C_ident, t):
 | 
				
			||||||
            error(lineno, 'invalid argument set token "{0}"'.format(t))
 | 
					            error(lineno, 'invalid argument set token "{0}"'.format(t))
 | 
				
			||||||
        if t in flds:
 | 
					        if t in flds:
 | 
				
			||||||
            error(lineno, 'duplicate argument "{0}"'.format(t))
 | 
					            error(lineno, 'duplicate argument "{0}"'.format(t))
 | 
				
			||||||
| 
						 | 
					@ -791,7 +796,10 @@ def parse_generic(lineno, parent_pat, name, toks):
 | 
				
			||||||
    global arguments
 | 
					    global arguments
 | 
				
			||||||
    global formats
 | 
					    global formats
 | 
				
			||||||
    global allpatterns
 | 
					    global allpatterns
 | 
				
			||||||
    global re_ident
 | 
					    global re_arg_ident
 | 
				
			||||||
 | 
					    global re_fld_ident
 | 
				
			||||||
 | 
					    global re_fmt_ident
 | 
				
			||||||
 | 
					    global re_C_ident
 | 
				
			||||||
    global insnwidth
 | 
					    global insnwidth
 | 
				
			||||||
    global insnmask
 | 
					    global insnmask
 | 
				
			||||||
    global variablewidth
 | 
					    global variablewidth
 | 
				
			||||||
| 
						 | 
					@ -807,7 +815,7 @@ def parse_generic(lineno, parent_pat, name, toks):
 | 
				
			||||||
    fmt = None
 | 
					    fmt = None
 | 
				
			||||||
    for t in toks:
 | 
					    for t in toks:
 | 
				
			||||||
        # '&Foo' gives a format an explcit argument set.
 | 
					        # '&Foo' gives a format an explcit argument set.
 | 
				
			||||||
        if t[0] == '&':
 | 
					        if re.fullmatch(re_arg_ident, t):
 | 
				
			||||||
            tt = t[1:]
 | 
					            tt = t[1:]
 | 
				
			||||||
            if arg:
 | 
					            if arg:
 | 
				
			||||||
                error(lineno, 'multiple argument sets')
 | 
					                error(lineno, 'multiple argument sets')
 | 
				
			||||||
| 
						 | 
					@ -818,7 +826,7 @@ def parse_generic(lineno, parent_pat, name, toks):
 | 
				
			||||||
            continue
 | 
					            continue
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # '@Foo' gives a pattern an explicit format.
 | 
					        # '@Foo' gives a pattern an explicit format.
 | 
				
			||||||
        if t[0] == '@':
 | 
					        if re.fullmatch(re_fmt_ident, t):
 | 
				
			||||||
            tt = t[1:]
 | 
					            tt = t[1:]
 | 
				
			||||||
            if fmt:
 | 
					            if fmt:
 | 
				
			||||||
                error(lineno, 'multiple formats')
 | 
					                error(lineno, 'multiple formats')
 | 
				
			||||||
| 
						 | 
					@ -829,19 +837,19 @@ def parse_generic(lineno, parent_pat, name, toks):
 | 
				
			||||||
            continue
 | 
					            continue
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # '%Foo' imports a field.
 | 
					        # '%Foo' imports a field.
 | 
				
			||||||
        if t[0] == '%':
 | 
					        if re.fullmatch(re_fld_ident, t):
 | 
				
			||||||
            tt = t[1:]
 | 
					            tt = t[1:]
 | 
				
			||||||
            flds = add_field_byname(lineno, flds, tt, tt)
 | 
					            flds = add_field_byname(lineno, flds, tt, tt)
 | 
				
			||||||
            continue
 | 
					            continue
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # 'Foo=%Bar' imports a field with a different name.
 | 
					        # 'Foo=%Bar' imports a field with a different name.
 | 
				
			||||||
        if re.fullmatch(re_ident + '=%' + re_ident, t):
 | 
					        if re.fullmatch(re_C_ident + '=' + re_fld_ident, t):
 | 
				
			||||||
            (fname, iname) = t.split('=%')
 | 
					            (fname, iname) = t.split('=%')
 | 
				
			||||||
            flds = add_field_byname(lineno, flds, fname, iname)
 | 
					            flds = add_field_byname(lineno, flds, fname, iname)
 | 
				
			||||||
            continue
 | 
					            continue
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # 'Foo=number' sets an argument field to a constant value
 | 
					        # 'Foo=number' sets an argument field to a constant value
 | 
				
			||||||
        if re.fullmatch(re_ident + '=[+-]?[0-9]+', t):
 | 
					        if re.fullmatch(re_C_ident + '=[+-]?[0-9]+', t):
 | 
				
			||||||
            (fname, value) = t.split('=')
 | 
					            (fname, value) = t.split('=')
 | 
				
			||||||
            value = int(value)
 | 
					            value = int(value)
 | 
				
			||||||
            flds = add_field(lineno, flds, fname, ConstField(value))
 | 
					            flds = add_field(lineno, flds, fname, ConstField(value))
 | 
				
			||||||
| 
						 | 
					@ -866,7 +874,7 @@ def parse_generic(lineno, parent_pat, name, toks):
 | 
				
			||||||
            fixedmask = (fixedmask << shift) | fms
 | 
					            fixedmask = (fixedmask << shift) | fms
 | 
				
			||||||
            undefmask = (undefmask << shift) | ubm
 | 
					            undefmask = (undefmask << shift) | ubm
 | 
				
			||||||
        # Otherwise, fieldname:fieldwidth
 | 
					        # Otherwise, fieldname:fieldwidth
 | 
				
			||||||
        elif re.fullmatch(re_ident + ':s?[0-9]+', t):
 | 
					        elif re.fullmatch(re_C_ident + ':s?[0-9]+', t):
 | 
				
			||||||
            (fname, flen) = t.split(':')
 | 
					            (fname, flen) = t.split(':')
 | 
				
			||||||
            sign = False
 | 
					            sign = False
 | 
				
			||||||
            if flen[0] == 's':
 | 
					            if flen[0] == 's':
 | 
				
			||||||
| 
						 | 
					@ -971,6 +979,10 @@ def parse_generic(lineno, parent_pat, name, toks):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def parse_file(f, parent_pat):
 | 
					def parse_file(f, parent_pat):
 | 
				
			||||||
    """Parse all of the patterns within a file"""
 | 
					    """Parse all of the patterns within a file"""
 | 
				
			||||||
 | 
					    global re_arg_ident
 | 
				
			||||||
 | 
					    global re_fld_ident
 | 
				
			||||||
 | 
					    global re_fmt_ident
 | 
				
			||||||
 | 
					    global re_pat_ident
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # Read all of the lines of the file.  Concatenate lines
 | 
					    # Read all of the lines of the file.  Concatenate lines
 | 
				
			||||||
    # ending in backslash; discard empty lines and comments.
 | 
					    # ending in backslash; discard empty lines and comments.
 | 
				
			||||||
| 
						 | 
					@ -1063,14 +1075,16 @@ def parse_file(f, parent_pat):
 | 
				
			||||||
            continue
 | 
					            continue
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # Determine the type of object needing to be parsed.
 | 
					        # Determine the type of object needing to be parsed.
 | 
				
			||||||
        if name[0] == '%':
 | 
					        if re.fullmatch(re_fld_ident, name):
 | 
				
			||||||
            parse_field(start_lineno, name[1:], toks)
 | 
					            parse_field(start_lineno, name[1:], toks)
 | 
				
			||||||
        elif name[0] == '&':
 | 
					        elif re.fullmatch(re_arg_ident, name):
 | 
				
			||||||
            parse_arguments(start_lineno, name[1:], toks)
 | 
					            parse_arguments(start_lineno, name[1:], toks)
 | 
				
			||||||
        elif name[0] == '@':
 | 
					        elif re.fullmatch(re_fmt_ident, name):
 | 
				
			||||||
            parse_generic(start_lineno, None, name[1:], toks)
 | 
					            parse_generic(start_lineno, None, name[1:], toks)
 | 
				
			||||||
        else:
 | 
					        elif re.fullmatch(re_pat_ident, name):
 | 
				
			||||||
            parse_generic(start_lineno, parent_pat, name, toks)
 | 
					            parse_generic(start_lineno, parent_pat, name, toks)
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            error(lineno, 'invalid token "{0}"'.format(name))
 | 
				
			||||||
        toks = []
 | 
					        toks = []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if nesting != 0:
 | 
					    if nesting != 0:
 | 
				
			||||||
| 
						 | 
					@ -1257,7 +1271,7 @@ def main():
 | 
				
			||||||
    long_opts = ['decode=', 'translate=', 'output=', 'insnwidth=',
 | 
					    long_opts = ['decode=', 'translate=', 'output=', 'insnwidth=',
 | 
				
			||||||
                 'static-decode=', 'varinsnwidth=']
 | 
					                 'static-decode=', 'varinsnwidth=']
 | 
				
			||||||
    try:
 | 
					    try:
 | 
				
			||||||
        (opts, args) = getopt.getopt(sys.argv[1:], 'o:vw:', long_opts)
 | 
					        (opts, args) = getopt.gnu_getopt(sys.argv[1:], 'o:vw:', long_opts)
 | 
				
			||||||
    except getopt.GetoptError as err:
 | 
					    except getopt.GetoptError as err:
 | 
				
			||||||
        error(0, err)
 | 
					        error(0, err)
 | 
				
			||||||
    for o, a in opts:
 | 
					    for o, a in opts:
 | 
				
			||||||
| 
						 | 
					@ -1327,12 +1341,10 @@ def main():
 | 
				
			||||||
    # but we can't tell which ones.  Prevent issues from the compiler by
 | 
					    # but we can't tell which ones.  Prevent issues from the compiler by
 | 
				
			||||||
    # suppressing redundant declaration warnings.
 | 
					    # suppressing redundant declaration warnings.
 | 
				
			||||||
    if anyextern:
 | 
					    if anyextern:
 | 
				
			||||||
        output("#ifdef CONFIG_PRAGMA_DIAGNOSTIC_AVAILABLE\n",
 | 
					        output("#pragma GCC diagnostic push\n",
 | 
				
			||||||
               "# pragma GCC diagnostic push\n",
 | 
					               "#pragma GCC diagnostic ignored \"-Wredundant-decls\"\n",
 | 
				
			||||||
               "# pragma GCC diagnostic ignored \"-Wredundant-decls\"\n",
 | 
					               "#ifdef __clang__\n"
 | 
				
			||||||
               "# ifdef __clang__\n"
 | 
					 | 
				
			||||||
               "#  pragma GCC diagnostic ignored \"-Wtypedef-redefinition\"\n",
 | 
					               "#  pragma GCC diagnostic ignored \"-Wtypedef-redefinition\"\n",
 | 
				
			||||||
               "# endif\n",
 | 
					 | 
				
			||||||
               "#endif\n\n")
 | 
					               "#endif\n\n")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    out_pats = {}
 | 
					    out_pats = {}
 | 
				
			||||||
| 
						 | 
					@ -1347,9 +1359,7 @@ def main():
 | 
				
			||||||
    output('\n')
 | 
					    output('\n')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if anyextern:
 | 
					    if anyextern:
 | 
				
			||||||
        output("#ifdef CONFIG_PRAGMA_DIAGNOSTIC_AVAILABLE\n",
 | 
					        output("#pragma GCC diagnostic pop\n\n")
 | 
				
			||||||
               "# pragma GCC diagnostic pop\n",
 | 
					 | 
				
			||||||
               "#endif\n\n")
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for n in sorted(formats.keys()):
 | 
					    for n in sorted(formats.keys()):
 | 
				
			||||||
        f = formats[n]
 | 
					        f = formats[n]
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -256,9 +256,8 @@ VMINNM_fp_3s     1111 001 1 0 . 1 . .... .... 1111 ... 1 .... @3same_fp
 | 
				
			||||||
@2reg_shll_b     .... ... . . . 001 shift:3  .... .... 0 . . . .... \
 | 
					@2reg_shll_b     .... ... . . . 001 shift:3  .... .... 0 . . . .... \
 | 
				
			||||||
                 &2reg_shift vm=%vm_dp vd=%vd_dp size=0 q=0
 | 
					                 &2reg_shift vm=%vm_dp vd=%vd_dp size=0 q=0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# We use size=0 for fp32 and size=1 for fp16 to match the 3-same encodings.
 | 
					 | 
				
			||||||
@2reg_vcvt       .... ... . . . 1 ..... .... .... . q:1 . . .... \
 | 
					@2reg_vcvt       .... ... . . . 1 ..... .... .... . q:1 . . .... \
 | 
				
			||||||
                 &2reg_shift vm=%vm_dp vd=%vd_dp size=0 shift=%neon_rshift_i5
 | 
					                 &2reg_shift vm=%vm_dp vd=%vd_dp size=2 shift=%neon_rshift_i5
 | 
				
			||||||
@2reg_vcvt_f16   .... ... . . . 11 .... .... .... . q:1 . . .... \
 | 
					@2reg_vcvt_f16   .... ... . . . 11 .... .... .... . q:1 . . .... \
 | 
				
			||||||
                 &2reg_shift vm=%vm_dp vd=%vd_dp size=1 shift=%neon_rshift_i4
 | 
					                 &2reg_shift vm=%vm_dp vd=%vd_dp size=1 shift=%neon_rshift_i4
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1653,7 +1653,7 @@ static bool do_fp_2sh(DisasContext *s, arg_2reg_shift *a,
 | 
				
			||||||
        return false;
 | 
					        return false;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (a->size != 0) {
 | 
					    if (a->size == MO_16) {
 | 
				
			||||||
        if (!dc_isar_feature(aa32_fp16_arith, s)) {
 | 
					        if (!dc_isar_feature(aa32_fp16_arith, s)) {
 | 
				
			||||||
            return false;
 | 
					            return false;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					@ -1673,7 +1673,7 @@ static bool do_fp_2sh(DisasContext *s, arg_2reg_shift *a,
 | 
				
			||||||
        return true;
 | 
					        return true;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fpst = fpstatus_ptr(tcg_ctx, a->size ? FPST_STD_F16 : FPST_STD);
 | 
					    fpst = fpstatus_ptr(tcg_ctx, a->size == MO_16 ? FPST_STD_F16 : FPST_STD);
 | 
				
			||||||
    tcg_gen_gvec_2_ptr(tcg_ctx, rd_ofs, rm_ofs, fpst, vec_size, vec_size, a->shift, fn);
 | 
					    tcg_gen_gvec_2_ptr(tcg_ctx, rd_ofs, rm_ofs, fpst, vec_size, vec_size, a->shift, fn);
 | 
				
			||||||
    tcg_temp_free_ptr(tcg_ctx, fpst);
 | 
					    tcg_temp_free_ptr(tcg_ctx, fpst);
 | 
				
			||||||
    return true;
 | 
					    return true;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue