@@ -41,9 +41,23 @@ def gen_helper_function(f, tag, tagregs, tagimms):
ret_type = hex_common.helper_ret_type(tag, regs).func_arg
declared = []
- for arg in hex_common.helper_args(tag, regs, imms):
+ helper_args, imm_inds, hvx_inds = hex_common.helper_args(tag, regs, imms)
+ for arg in helper_args:
declared.append(arg.func_arg)
+ ## Specify that helpers should be translated by helper-to-tcg
+ f.write(f'LLVM_ANNOTATE("helper-to-tcg")\n')
+ ## Specify which arguments to the helper function should be treated as
+ ## immediate arguments
+ if len(imm_inds) > 0:
+ imm_inds_str = ','.join(str(i) for i in imm_inds)
+ f.write(f'LLVM_ANNOTATE("immediate: {imm_inds_str}")\n')
+ ## Specify which arguments to the helper function should be treated as
+ ## gvec vectors
+ if len(hvx_inds) > 0:
+ hvx_inds_str = ','.join(str(i) for i in hvx_inds)
+ f.write(f'LLVM_ANNOTATE("ptr-to-offset: {hvx_inds_str}")\n')
+
arguments = ", ".join(declared)
f.write(f"{ret_type} HELPER({tag})({arguments})\n")
f.write("{\n")
@@ -51,6 +65,7 @@ def gen_helper_function(f, tag, tagregs, tagimms):
f.write(hex_common.code_fmt(f"""\
uint32_t EA;
"""))
+
## Declare the return variable
if not hex_common.is_predicated(tag):
for regtype, regid in regs:
@@ -36,7 +36,7 @@ def gen_helper_prototype(f, tag, tagregs, tagimms):
ret_type = hex_common.helper_ret_type(tag, regs).proto_arg
declared.append(ret_type)
- for arg in hex_common.helper_args(tag, regs, imms):
+ for arg in hex_common.helper_args(tag, regs, imms)[0]:
declared.append(arg.proto_arg)
arguments = ", ".join(declared)
@@ -85,7 +85,7 @@ def gen_tcg_func(f, tag, regs, imms):
if ret_type != "void":
declared.append(ret_type)
- for arg in hex_common.helper_args(tag, regs, imms):
+ for arg in hex_common.helper_args(tag, regs, imms)[0]:
declared.append(arg.call_arg)
arguments = ", ".join(declared)
@@ -32,6 +32,7 @@
tags = [] # list of all tags
overrides = {} # tags with helper overrides
idef_parser_enabled = {} # tags enabled for idef-parser
+helper_to_tcg_enabled = {} # tags enabled for helper-to-tcg
# We should do this as a hash for performance,
# but to keep order let's keep it as a list.
@@ -262,6 +263,10 @@ def is_idef_parser_enabled(tag):
return tag in idef_parser_enabled
+def is_helper_to_tcg_enabled(tag):
+ return tag in helper_to_tcg_enabled
+
+
def is_hvx_insn(tag):
return "A_CVI" in attribdict[tag]
@@ -304,6 +309,13 @@ def read_idef_parser_enabled_file(name):
idef_parser_enabled = set(lines)
+def read_helper_to_tcg_enabled_file(name):
+ global helper_to_tcg_enabled
+ with open(name, "r") as helper_to_tcg_enabled_file:
+ lines = helper_to_tcg_enabled_file.read().strip().split("\n")
+ helper_to_tcg_enabled = set(lines)
+
+
def is_predicated(tag):
return "A_CONDEXEC" in attribdict[tag]
@@ -383,7 +395,7 @@ def hvx_off(self):
def helper_proto_type(self):
return "ptr"
def helper_arg_type(self):
- return "void *"
+ return "void * restrict"
def helper_arg_name(self):
return f"{self.reg_tcg()}_void"
@@ -719,7 +731,7 @@ def decl_tcg(self, f, tag, regno):
const intptr_t {self.hvx_off()} =
{vreg_offset_func(tag)}(ctx, {self.reg_num}, 1, true);
"""))
- if not skip_qemu_helper(tag):
+ if not skip_qemu_helper(tag) and not is_helper_to_tcg_enabled(tag):
f.write(code_fmt(f"""\
TCGv_ptr {self.reg_tcg()} = tcg_temp_new_ptr();
tcg_gen_addi_ptr({self.reg_tcg()}, tcg_env, {self.hvx_off()});
@@ -744,7 +756,7 @@ def decl_tcg(self, f, tag, regno):
f.write(code_fmt(f"""\
const intptr_t {self.hvx_off()} = vreg_src_off(ctx, {self.reg_num});
"""))
- if not skip_qemu_helper(tag):
+ if not skip_qemu_helper(tag) and not is_helper_to_tcg_enabled(tag):
f.write(code_fmt(f"""\
TCGv_ptr {self.reg_tcg()} = tcg_temp_new_ptr();
tcg_gen_addi_ptr({self.reg_tcg()}, tcg_env, {self.hvx_off()});
@@ -785,7 +797,7 @@ def decl_tcg(self, f, tag, regno):
vreg_src_off(ctx, {self.reg_num}),
sizeof(MMVector), sizeof(MMVector));
"""))
- if not skip_qemu_helper(tag):
+ if not skip_qemu_helper(tag) and not is_helper_to_tcg_enabled(tag):
f.write(code_fmt(f"""\
TCGv_ptr {self.reg_tcg()} = tcg_temp_new_ptr();
tcg_gen_addi_ptr({self.reg_tcg()}, tcg_env, {self.hvx_off()});
@@ -814,7 +826,7 @@ def decl_tcg(self, f, tag, regno):
f.write(code_fmt(f"""\
const intptr_t {self.hvx_off()} = offsetof(CPUHexagonState, vtmp);
"""))
- if not skip_qemu_helper(tag):
+ if not skip_qemu_helper(tag) and not is_helper_to_tcg_enabled(tag):
f.write(code_fmt(f"""\
TCGv_ptr {self.reg_tcg()} = tcg_temp_new_ptr();
tcg_gen_addi_ptr({self.reg_tcg()}, tcg_env, {self.hvx_off()});
@@ -850,7 +862,7 @@ def decl_tcg(self, f, tag, regno):
const intptr_t {self.hvx_off()} =
{vreg_offset_func(tag)}(ctx, {self.reg_num}, 2, true);
"""))
- if not skip_qemu_helper(tag):
+ if not skip_qemu_helper(tag) and not is_helper_to_tcg_enabled(tag):
f.write(code_fmt(f"""\
TCGv_ptr {self.reg_tcg()} = tcg_temp_new_ptr();
tcg_gen_addi_ptr({self.reg_tcg()}, tcg_env, {self.hvx_off()});
@@ -882,7 +894,7 @@ def decl_tcg(self, f, tag, regno):
vreg_src_off(ctx, {self.reg_num} ^ 1),
sizeof(MMVector), sizeof(MMVector));
"""))
- if not skip_qemu_helper(tag):
+ if not skip_qemu_helper(tag) and not is_helper_to_tcg_enabled(tag):
f.write(code_fmt(f"""\
TCGv_ptr {self.reg_tcg()} = tcg_temp_new_ptr();
tcg_gen_addi_ptr({self.reg_tcg()}, tcg_env, {self.hvx_off()});
@@ -909,7 +921,7 @@ def decl_tcg(self, f, tag, regno):
vreg_src_off(ctx, {self.reg_num} ^ 1),
sizeof(MMVector), sizeof(MMVector));
"""))
- if not skip_qemu_helper(tag):
+ if not skip_qemu_helper(tag) and not is_helper_to_tcg_enabled(tag):
f.write(code_fmt(f"""\
TCGv_ptr {self.reg_tcg()} = tcg_temp_new_ptr();
tcg_gen_addi_ptr({self.reg_tcg()}, tcg_env, {self.hvx_off()});
@@ -1092,8 +1104,13 @@ def helper_ret_type(tag, regs):
raise Exception("numscalarresults > 1")
return return_type
+
def helper_args(tag, regs, imms):
args = []
+ # Used to ensure immediates are passed translated as immediates by
+ # helper-to-tcg.
+ imm_indices = []
+ hvx_indices = []
## First argument is the CPU state
if need_env(tag):
@@ -1114,16 +1131,20 @@ def helper_args(tag, regs, imms):
for regtype, regid in regs:
reg = get_register(tag, regtype, regid)
if reg.is_written() and reg.is_hvx_reg():
+ hvx_indices.append(len(args))
args.append(reg.helper_arg())
## Pass the source registers
for regtype, regid in regs:
reg = get_register(tag, regtype, regid)
if reg.is_read() and not (reg.is_hvx_reg() and reg.is_readwrite()):
+ if reg.is_hvx_reg():
+ hvx_indices.append(len(args))
args.append(reg.helper_arg())
## Pass the immediates
for immlett, bits, immshift in imms:
+ imm_indices.append(len(args))
args.append(HelperArg(
"s32",
f"tcg_constant_tl({imm_name(immlett)})",
@@ -1132,24 +1153,28 @@ def helper_args(tag, regs, imms):
## Other stuff the helper might need
if need_pkt_has_multi_cof(tag):
+ imm_indices.append(len(args))
args.append(HelperArg(
"i32",
"tcg_constant_tl(ctx->pkt->pkt_has_multi_cof)",
"uint32_t pkt_has_multi_cof"
))
if need_pkt_need_commit(tag):
+ imm_indices.append(len(args))
args.append(HelperArg(
"i32",
"tcg_constant_tl(ctx->need_commit)",
"uint32_t pkt_need_commit"
))
if need_PC(tag):
+ imm_indices.append(len(args))
args.append(HelperArg(
"i32",
"tcg_constant_tl(ctx->pkt->pc)",
"target_ulong PC"
))
if need_next_PC(tag):
+ imm_indices.append(len(args))
args.append(HelperArg(
"i32",
"tcg_constant_tl(ctx->next_PC)",
@@ -1168,18 +1193,20 @@ def helper_args(tag, regs, imms):
"uint32_t SP"
))
if need_slot(tag):
+ imm_indices.append(len(args))
args.append(HelperArg(
"i32",
"gen_slotval(ctx)",
"uint32_t slotval"
))
if need_part1(tag):
+ imm_indices.append(len(args))
args.append(HelperArg(
"i32",
"tcg_constant_tl(insn->part1)"
"uint32_t part1"
))
- return args
+ return args, imm_indices, hvx_indices
def parse_common_args(desc):
@@ -31,6 +31,7 @@
#include "mmvec/macros.h"
#include "op_helper.h"
#include "translate.h"
+#include "helper-to-tcg/annotate.h"
#define SF_BIAS 127
#define SF_MANTBITS 23
Adds the following LLVM_ANNOTATE attributes to helper functions generated by Hexagon: 1. "helper-to-tcg", to specify that a given helper functions should be translated, and; 2. "immediate: ..." to make sure immediate arguments to helper functions remain immediates in the emitted TCG code (e.g. slot). 3. "ptr-to-offset: ..." to make sure pointer arguments are treated as immediates representing an offset into the CPU state, needed to work with gvec. Two functions are also added to hex_common.py, to firstly parse the generated file containing all successfully translated helper functions, and secondly to expose the indices of immediate and pointer (vector) arguments to helper functions. The latter is needed to generate the input of helper-to-tcg. Signed-off-by: Anton Johansson <anjo@rev.ng> --- target/hexagon/gen_helper_funcs.py | 17 ++++++++++- target/hexagon/gen_helper_protos.py | 2 +- target/hexagon/gen_tcg_funcs.py | 2 +- target/hexagon/hex_common.py | 45 +++++++++++++++++++++++------ target/hexagon/op_helper.c | 1 + 5 files changed, 55 insertions(+), 12 deletions(-)