Add HVX support to the semantics generator Signed-off-by: Taylor Simpson <tsimp...@quicinc.com> --- target/hexagon/do_qemu.py | 175 ++++++++++++++++++++++++++++++++++++++--- target/hexagon/gen_semantics.c | 9 +++ 2 files changed, 171 insertions(+), 13 deletions(-)
diff --git a/target/hexagon/do_qemu.py b/target/hexagon/do_qemu.py index 974d45e..5b90d32 100755 --- a/target/hexagon/do_qemu.py +++ b/target/hexagon/do_qemu.py @@ -111,6 +111,16 @@ def SEMANTICS(tag, beh, sem): attribdict[tag] = set() tags.append(tag) # dicts have no order, this is for order +def EXT_SEMANTICS(ext, tag, beh, sem): + #print tag,beh,sem + extnames[ext] = True + extdict[tag] = ext + behdict[tag] = beh + semdict[tag] = sem + attribdict[tag] = set() + tags.append(tag) # dicts have no order, this is for order + + def ATTRIBUTES(tag, attribstring): attribstring = \ attribstring.replace("ATTRIBS","").replace("(","").replace(")","") @@ -174,6 +184,9 @@ def compute_tag_immediates(tag): ## P predicate register ## R GPR register ## M modifier register +## Q HVX predicate vector +## V HVX vector register +## O HVX new vector register ## regid can be one of the following ## d, e destination register ## dd destination register pair @@ -205,6 +218,9 @@ def is_readwrite(regid): def is_scalar_reg(regtype): return regtype in "RPC" +def is_hvx_reg(regtype): + return regtype in "VQ" + def is_old_val(regtype, regid, tag): return regtype+regid+'V' in semdict[tag] @@ -215,7 +231,8 @@ tagimms = dict(zip(tags, list(map(compute_tag_immediates, tags)))) def need_slot(tag): if ('A_CONDEXEC' in attribdict[tag] or - 'A_STORE' in attribdict[tag]): + 'A_STORE' in attribdict[tag] or + 'A_CVI' in attribdict[tag]): return 1 else: return 0 @@ -301,19 +318,32 @@ def gen_helper_prototype(f, tag, regs, imms): f.write('DEF_HELPER_%s(%s' % (def_helper_size, tag)) ## Generate the qemu DEF_HELPER type for each result + ## Iterate over this list twice + ## - Emit the scalar result + ## - Emit the vector result i=0 for regtype,regid,toss,numregs in regs: if (is_written(regid)): - gen_def_helper_opn(f, tag, regtype, regid, toss, numregs, i) + if (not is_hvx_reg(regtype)): + gen_def_helper_opn(f, tag, regtype, regid, toss, numregs, i) i += 1 ## Put the env between the outputs and inputs f.write(', env' ) i += 1 + # Second pass + for regtype,regid,toss,numregs in regs: + if (is_written(regid)): + if (is_hvx_reg(regtype)): + gen_def_helper_opn(f, tag, regtype, regid, toss, numregs, i) + i += 1 + ## Generate the qemu type for each input operand (regs and immediates) for regtype,regid,toss,numregs in regs: if (is_read(regid)): + if (is_hvx_reg(regtype) and is_readwrite(regid)): + continue gen_def_helper_opn(f, tag, regtype, regid, toss, numregs, i) i += 1 for immlett,bits,immshift in imms: @@ -441,11 +471,33 @@ def genptr_dst_write(f,regtype, regid): macro = "WRITE_%sREG_%s" % (regtype, regid) f.write("%s(%s%sN, %s%sV);\n" % (macro, regtype, regid, regtype, regid)) +def genptr_dst_write_ext(f, regtype, regid, newv="0"): + macro = "WRITE_%sREG_%s" % (regtype, regid) + f.write("%s(%s%sN, %s%sV,%s);\n" % \ + (macro, regtype, regid, regtype, regid, newv)) + def genptr_dst_write_opn(f,regtype, regid, tag): if (is_pair(regid)): - genptr_dst_write(f, regtype, regid) + if (is_hvx_reg(regtype)): + if ('A_CVI_TMP' in attribdict[tag] or + 'A_CVI_TMP_DST' in attribdict[tag]): + genptr_dst_write_ext(f, regtype, regid, "EXT_TMP") + else: + genptr_dst_write_ext(f, regtype, regid) + else: + genptr_dst_write(f, regtype, regid) elif (is_single(regid)): - genptr_dst_write(f, regtype, regid) + if (is_hvx_reg(regtype)): + if 'A_CVI_NEW' in attribdict[tag]: + genptr_dst_write_ext(f, regtype, regid, "EXT_NEW") + elif 'A_CVI_TMP' in attribdict[tag]: + genptr_dst_write_ext(f, regtype, regid, "EXT_TMP") + elif 'A_CVI_TMP_DST' in attribdict[tag]: + genptr_dst_write_ext(f, regtype, regid, "EXT_TMP") + else: + genptr_dst_write_ext(f, regtype, regid, "EXT_DFL") + else: + genptr_dst_write(f, regtype, regid) else: print("Bad register parse: ",regtype,regid,toss,numregs) @@ -508,13 +560,23 @@ def gen_tcg_func(f, tag, regs, imms): ## If there is a scalar result, it is the return type for regtype,regid,toss,numregs in regs: if (is_written(regid)): + if (is_hvx_reg(regtype)): + continue gen_helper_call_opn(f, tag, regtype, regid, toss, numregs, i) i += 1 if (i > 0): f.write(", ") f.write("cpu_env") i=1 for regtype,regid,toss,numregs in regs: + if (is_written(regid)): + if (not is_hvx_reg(regtype)): + continue + gen_helper_call_opn(f, tag, regtype, regid, toss, numregs, i) + i += 1 + for regtype,regid,toss,numregs in regs: if (is_read(regid)): + if (is_hvx_reg(regtype) and is_readwrite(regid)): + continue gen_helper_call_opn(f, tag, regtype, regid, toss, numregs, i) i += 1 for immlett,bits,immshift in imms: @@ -577,12 +639,26 @@ def gen_helper_arg_pair(f,regtype,regid,regno): if regno >= 0 : f.write(", ") f.write("int64_t %s%sV" % (regtype,regid)) +def gen_helper_arg_ext(f,regtype,regid,regno): + if regno > 0 : f.write(", ") + f.write("void *%s%sV_void" % (regtype,regid)) + +def gen_helper_arg_ext_pair(f,regtype,regid,regno): + if regno > 0 : f.write(", ") + f.write("void *%s%sV_void" % (regtype,regid)) + def gen_helper_arg_opn(f,regtype,regid,i): if (is_pair(regid)): - gen_helper_arg_pair(f,regtype,regid,i) + if (is_hvx_reg(regtype)): + gen_helper_arg_ext_pair(f,regtype,regid,i) + else: + gen_helper_arg_pair(f,regtype,regid,i) elif (is_single(regid)): if is_old_val(regtype, regid, tag): - gen_helper_arg(f,regtype,regid,i) + if (is_hvx_reg(regtype)): + gen_helper_arg_ext(f,regtype,regid,i) + else: + gen_helper_arg(f,regtype,regid,i) elif is_new_val(regtype, regid, tag): gen_helper_arg_new(f,regtype,regid,i) else: @@ -601,25 +677,61 @@ def gen_helper_dest_decl_pair(f,regtype,regid,regno,subfield=""): f.write("int64_t %s%sV%s = 0;\n" % \ (regtype,regid,subfield)) +def gen_helper_dest_decl_ext(f,regtype,regid): + f.write("/* %s%sV is *(mmvector_t*)(%s%sV_void) */\n" % \ + (regtype,regid,regtype,regid)) + +def gen_helper_dest_decl_ext_pair(f,regtype,regid,regno): + f.write("/* %s%sV is *(mmvector_pair_t*))%s%sV_void) */\n" % \ + (regtype,regid,regtype, regid)) + def gen_helper_dest_decl_opn(f,regtype,regid,i): if (is_pair(regid)): - gen_helper_dest_decl_pair(f,regtype,regid,i) + if (is_hvx_reg(regtype)): + gen_helper_dest_decl_ext_pair(f,regtype,regid, i) + else: + gen_helper_dest_decl_pair(f,regtype,regid,i) elif (is_single(regid)): - gen_helper_dest_decl(f,regtype,regid,i) + if (is_hvx_reg(regtype)): + gen_helper_dest_decl_ext(f,regtype,regid) + else: + gen_helper_dest_decl(f,regtype,regid,i) else: print("Bad register parse: ",regtype,regid,toss,numregs) +def gen_helper_src_var_ext(f,regtype,regid): + f.write("/* %s%sV is *(mmvector_t*)(%s%sV_void) */\n" % \ + (regtype,regid,regtype,regid)) + +def gen_helper_src_var_ext_pair(f,regtype,regid,regno): + f.write("/* %s%sV%s is *(mmvector_pair_t*)(%s%sV%s_void) */\n" % \ + (regtype,regid,regno,regtype,regid,regno)) + def gen_helper_return(f,regtype,regid,regno): f.write("return %s%sV;\n" % (regtype,regid)) def gen_helper_return_pair(f,regtype,regid,regno): f.write("return %s%sV;\n" % (regtype,regid)) +def gen_helper_dst_write_ext(f,regtype,regid): + f.write("/* %s%sV is *(mmvector_t*)%s%sV_void */\n" % \ + (regtype,regid,regtype,regid)) + +def gen_helper_dst_write_ext_pair(f,regtype,regid): + f.write("/* %s%sV is *(mmvector_pair_t*)%s%sV_void */\n" % \ + (regtype,regid, regtype,regid)) + def gen_helper_return_opn(f, regtype, regid, i): if (is_pair(regid)): - gen_helper_return_pair(f,regtype,regid,i) + if (is_hvx_reg(regtype)): + gen_helper_dst_write_ext_pair(f,regtype,regid) + else: + gen_helper_return_pair(f,regtype,regid,i) elif (is_single(regid)): - gen_helper_return(f,regtype,regid,i) + if (is_hvx_reg(regtype)): + gen_helper_dst_write_ext(f,regtype,regid) + else: + gen_helper_return(f,regtype,regid,i) else: print("Bad register parse: ",regtype,regid,toss,numregs) @@ -658,14 +770,20 @@ def gen_helper_definition(f, tag, regs, imms): % (tag, tag)) else: ## The return type of the function is the type of the destination - ## register + ## register (if scalar) i=0 for regtype,regid,toss,numregs in regs: if (is_written(regid)): if (is_pair(regid)): - gen_helper_return_type_pair(f,regtype,regid,i) + if (is_hvx_reg(regtype)): + continue + else: + gen_helper_return_type_pair(f,regtype,regid,i) elif (is_single(regid)): - gen_helper_return_type(f,regtype,regid,i) + if (is_hvx_reg(regtype)): + continue + else: + gen_helper_return_type(f,regtype,regid,i) else: print("Bad register parse: ",regtype,regid,toss,numregs) i += 1 @@ -674,10 +792,30 @@ def gen_helper_definition(f, tag, regs, imms): f.write("void") f.write(" HELPER(%s)(CPUHexagonState *env" % tag) + ## Arguments include the vector destination operands i = 1 + for regtype,regid,toss,numregs in regs: + if (is_written(regid)): + if (is_pair(regid)): + if (is_hvx_reg(regtype)): + gen_helper_arg_ext_pair(f,regtype,regid,i) + else: + continue + elif (is_single(regid)): + if (is_hvx_reg(regtype)): + gen_helper_arg_ext(f,regtype,regid,i) + else: + # This is the return value of the function + continue + else: + print("Bad register parse: ",regtype,regid,toss,numregs) + i += 1 + ## Arguments to the helper function are the source regs and immediates for regtype,regid,toss,numregs in regs: if (is_read(regid)): + if (is_hvx_reg(regtype) and is_readwrite(regid)): + continue gen_helper_arg_opn(f,regtype,regid,i) i += 1 for immlett,bits,immshift in imms: @@ -700,6 +838,17 @@ def gen_helper_definition(f, tag, regs, imms): gen_helper_dest_decl_opn(f,regtype,regid,i) i += 1 + for regtype,regid,toss,numregs in regs: + if (is_read(regid)): + if (is_pair(regid)): + if (is_hvx_reg(regtype)): + gen_helper_src_var_ext_pair(f,regtype,regid,i) + elif (is_single(regid)): + if (is_hvx_reg(regtype)): + gen_helper_src_var_ext(f,regtype,regid) + else: + print("Bad register parse: ",regtype,regid,toss,numregs) + if 'A_FPOP' in attribdict[tag]: f.write('fFPOP_START();\n'); diff --git a/target/hexagon/gen_semantics.c b/target/hexagon/gen_semantics.c index 2211ae6..8fd97c7 100644 --- a/target/hexagon/gen_semantics.c +++ b/target/hexagon/gen_semantics.c @@ -87,6 +87,15 @@ int main(int argc, char *argv[]) #include "imported/macros.def" #undef DEF_MACRO +/* + * Process the macros for HVX + */ +#define DEF_MACRO(MNAME, PARAMS, SDESC, LDESC, BEH, ATTRS) \ + fprintf(outfile, "MACROATTRIB(\"%s\",\"\"\"%s\"\"\",\"%s\",\"%s\")\n", \ + #MNAME, STRINGIZE(BEH), STRINGIZE(ATTRS), EXTSTR); +#include "imported/allext_macros.def" +#undef DEF_MACRO + fclose(outfile); return 0; } -- 2.7.4