Add decode and translation for trap2 and the vallocframe and vdeallocframe instruction forms introduced with v83. Model vector stack overflow as a precise exception and report it to linux-user as SIGSEGV.
Signed-off-by: Brian Cain <[email protected]> --- target/hexagon/cpu_bits.h | 1 + target/hexagon/gen_tcg.h | 51 +++++++++++++++++++++++++ target/hexagon/hex_regs.h | 2 + target/hexagon/translate.h | 1 + linux-user/hexagon/cpu_loop.c | 4 ++ target/hexagon/cpu.c | 2 +- target/hexagon/hexswi.c | 5 +++ target/hexagon/translate.c | 2 +- target/hexagon/tag_rev_info.c.inc | 10 +++++ target/hexagon/gen_idef_parser_funcs.py | 2 +- target/hexagon/gen_tcg_funcs.py | 4 +- target/hexagon/imported/encode_pp.def | 5 +++ target/hexagon/imported/system.idef | 8 ++++ 13 files changed, 93 insertions(+), 4 deletions(-) diff --git a/target/hexagon/cpu_bits.h b/target/hexagon/cpu_bits.h index a8fba4aa188..02ab05b326a 100644 --- a/target/hexagon/cpu_bits.h +++ b/target/hexagon/cpu_bits.h @@ -77,6 +77,7 @@ enum hex_cause { HEX_CAUSE_NO_COPROC2_ENABLE = 0x018, HEX_CAUSE_PRIV_USER_NO_GINSN = 0x01a, HEX_CAUSE_PRIV_USER_NO_SINSN = 0x01b, + HEX_CAUSE_VECTOR_STACK_OVERFLOW = 0x01c, HEX_CAUSE_REG_WRITE_CONFLICT = 0x01d, HEX_CAUSE_PC_NOT_ALIGNED = 0x01e, HEX_CAUSE_MISALIGNED_LOAD = 0x020, diff --git a/target/hexagon/gen_tcg.h b/target/hexagon/gen_tcg.h index 38d8558c97a..114199aaaac 100644 --- a/target/hexagon/gen_tcg.h +++ b/target/hexagon/gen_tcg.h @@ -1405,6 +1405,57 @@ RtV = RtV; \ } while (0) +#ifdef CONFIG_USER_ONLY +#define fGEN_TCG_V2_CHECK_AND_WRITE_VSP(VSP) \ + do { \ + TCGLabel *write_vsp = gen_new_label(); \ + tcg_gen_brcond_tl(TCG_COND_GEU, VSP, \ + hex_gpr[HEX_REG_VFRAMELIMIT], write_vsp); \ + gen_precise_exception(HEX_CAUSE_VECTOR_STACK_OVERFLOW, ctx->pkt.pc); \ + gen_set_label(write_vsp); \ + tcg_gen_mov_tl(hex_gpr[HEX_REG_VSP], VSP); \ + } while (0) +#else +#define fGEN_TCG_V2_CHECK_AND_WRITE_VSP(VSP) \ + do { \ + TCGLabel *write_vsp = gen_new_label(); \ + TCGv mode = tcg_temp_new(); \ + tcg_gen_andi_tl(mode, hex_t_sreg[HEX_SREG_SSR], \ + 1 << reg_field_info[SSR_EX].offset); \ + tcg_gen_brcondi_tl(TCG_COND_NE, mode, 0, write_vsp); \ + tcg_gen_andi_tl(mode, hex_t_sreg[HEX_SREG_SSR], \ + 1 << reg_field_info[SSR_UM].offset); \ + tcg_gen_brcondi_tl(TCG_COND_EQ, mode, 0, write_vsp); \ + tcg_gen_brcond_tl(TCG_COND_GEU, VSP, \ + hex_gpr[HEX_REG_VFRAMELIMIT], write_vsp); \ + gen_precise_exception(HEX_CAUSE_VECTOR_STACK_OVERFLOW, ctx->pkt.pc); \ + gen_set_label(write_vsp); \ + tcg_gen_mov_tl(hex_gpr[HEX_REG_VSP], VSP); \ + } while (0) +#endif +#define fGEN_TCG_V2_vallocframe_imm(SHORTCODE) \ + do { \ + TCGv vsp = tcg_temp_new(); \ + tcg_gen_subi_tl(vsp, hex_gpr[HEX_REG_VSP], uiV << 11); \ + fGEN_TCG_V2_CHECK_AND_WRITE_VSP(vsp); \ + } while (0) +#define fGEN_TCG_V2_vallocframe_reg(SHORTCODE) \ + do { \ + TCGv size = tcg_temp_new(); \ + TCGv vsp = tcg_temp_new(); \ + tcg_gen_shli_tl(size, RsV, 11); \ + tcg_gen_sub_tl(vsp, hex_gpr[HEX_REG_VSP], size); \ + fGEN_TCG_V2_CHECK_AND_WRITE_VSP(vsp); \ + } while (0) +#define fGEN_TCG_V2_vdeallocframe_imm(SHORTCODE) \ + tcg_gen_addi_tl(hex_gpr[HEX_REG_VSP], hex_gpr[HEX_REG_VSP], uiV << 11) +#define fGEN_TCG_V2_vdeallocframe_reg(SHORTCODE) \ + do { \ + TCGv size = tcg_temp_new(); \ + tcg_gen_shli_tl(size, RsV, 11); \ + tcg_gen_add_tl(hex_gpr[HEX_REG_VSP], hex_gpr[HEX_REG_VSP], size); \ + } while (0) + #define fGEN_TCG_L2_loadw_aq(SHORTCODE) SHORTCODE #define fGEN_TCG_L4_loadd_aq(SHORTCODE) SHORTCODE diff --git a/target/hexagon/hex_regs.h b/target/hexagon/hex_regs.h index 1f6bf9f88a0..03feca477b6 100644 --- a/target/hexagon/hex_regs.h +++ b/target/hexagon/hex_regs.h @@ -77,6 +77,8 @@ enum { HEX_REG_QEMU_PKT_CNT = 52, HEX_REG_QEMU_INSN_CNT = 53, HEX_REG_QEMU_HVX_CNT = 54, + HEX_REG_VFRAMELIMIT = 60, + HEX_REG_VSP = 61, HEX_REG_UTIMERLO = 62, HEX_REG_UTIMERHI = 63, }; diff --git a/target/hexagon/translate.h b/target/hexagon/translate.h index 2d1ed5208b7..a4fc9d0c6f1 100644 --- a/target/hexagon/translate.h +++ b/target/hexagon/translate.h @@ -365,6 +365,7 @@ extern TCGv_i64 hex_llsc_val_i64; extern TCGv hex_vstore_addr[VSTORES_MAX]; extern TCGv hex_vstore_size[VSTORES_MAX]; extern TCGv hex_vstore_pending[VSTORES_MAX]; +void gen_precise_exception(int cause, uint32_t pc); #ifdef CONFIG_USER_ONLY #define hex_hvx_ptr tcg_env #define HEX_HVX_OFFSET(member) offsetof(CPUHexagonState, hvx_ctx.member) diff --git a/linux-user/hexagon/cpu_loop.c b/linux-user/hexagon/cpu_loop.c index e6bb3b62a9f..2e66b4d9ac8 100644 --- a/linux-user/hexagon/cpu_loop.c +++ b/linux-user/hexagon/cpu_loop.c @@ -73,6 +73,10 @@ void cpu_loop(CPUHexagonState *env) force_sig_fault(TARGET_SIGSEGV, TARGET_SEGV_MAPERR, env->gpr[HEX_REG_PC]); break; + case HEX_CAUSE_VECTOR_STACK_OVERFLOW: + force_sig_fault(TARGET_SIGSEGV, TARGET_SEGV_BNDERR, + env->gpr[HEX_REG_PC]); + break; case HEX_CAUSE_PRIV_USER_NO_GINSN: case HEX_CAUSE_PRIV_USER_NO_SINSN: case HEX_CAUSE_INVALID_PACKET: diff --git a/target/hexagon/cpu.c b/target/hexagon/cpu.c index f7303c07abd..6adeee9d57f 100644 --- a/target/hexagon/cpu.c +++ b/target/hexagon/cpu.c @@ -87,7 +87,7 @@ const char * const hexagon_regnames[TOTAL_PER_THREAD_REGS] = { "sa0", "lc0", "sa1", "lc1", "p3_0", "c5", "m0", "m1", "usr", "pc", "ugp", "gp", "cs0", "cs1", "c14", "c15", "c16", "c17", "c18", "c19", "pkt_cnt", "insn_cnt", "hvx_cnt", "c23", - "c24", "c25", "c26", "c27", "c28", "c29", "c30", "c31", + "c24", "c25", "c26", "c27", "vframelimit", "vsp", "c30", "c31", }; #ifndef CONFIG_USER_ONLY diff --git a/target/hexagon/hexswi.c b/target/hexagon/hexswi.c index ef1d558dfc4..73949720ccf 100644 --- a/target/hexagon/hexswi.c +++ b/target/hexagon/hexswi.c @@ -366,6 +366,10 @@ static void coredump(CPUHexagonState *env) fprintf(f, "0x%x, Stack limit check error", HEX_CAUSE_STACK_LIMIT); break; + case HEX_CAUSE_VECTOR_STACK_OVERFLOW: + fprintf(f, "0x%x, Vector stack overflow", + HEX_CAUSE_VECTOR_STACK_OVERFLOW); + break; case HEX_CAUSE_FPTRAP_CAUSE_BADFLOAT: fprintf(f, "0x%x, Floating-Point: Execution of Floating-Point " "instruction resulted in exception", @@ -905,6 +909,7 @@ void hexagon_cpu_do_interrupt(CPUState *cs) case HEX_CAUSE_NO_COPROC_ENABLE: case HEX_CAUSE_NO_COPROC2_ENABLE: case HEX_CAUSE_UNSUPPORTED_HVX_64B: + case HEX_CAUSE_VECTOR_STACK_OVERFLOW: case HEX_CAUSE_REG_WRITE_CONFLICT: case HEX_CAUSE_VWCTRL_WINDOW_MISS: hexagon_ssr_set_cause(env, env->cause_code); diff --git a/target/hexagon/translate.c b/target/hexagon/translate.c index cd1abdf1461..665791db4fb 100644 --- a/target/hexagon/translate.c +++ b/target/hexagon/translate.c @@ -137,7 +137,7 @@ intptr_t ctx_tmp_vreg_off(DisasContext *ctx, int regnum, return offset; } -static void gen_precise_exception(int cause, uint32_t PC) +void gen_precise_exception(int cause, uint32_t PC) { tcg_gen_movi_i32(hex_cause_code, cause); gen_helper_raise_exception(tcg_env, tcg_constant_i32(HEX_EVENT_PRECISE), diff --git a/target/hexagon/tag_rev_info.c.inc b/target/hexagon/tag_rev_info.c.inc index a1b7b50cbf2..c2d4886a846 100644 --- a/target/hexagon/tag_rev_info.c.inc +++ b/target/hexagon/tag_rev_info.c.inc @@ -699,6 +699,16 @@ static const struct tag_rev_info tag_rev_info[XX_LAST_OPCODE] = { }, [V6_vconv_bf_qf32] = { .introduced = HEX_VER_V81, .removed = HEX_VER_NONE }, + [V2_vallocframe_imm] = { .introduced = HEX_VER_V83, + .removed = HEX_VER_NONE }, + [V2_vallocframe_reg] = { .introduced = HEX_VER_V83, + .removed = HEX_VER_NONE }, + [V2_vdeallocframe_imm] = { .introduced = HEX_VER_V83, + .removed = HEX_VER_NONE }, + [V2_vdeallocframe_reg] = { .introduced = HEX_VER_V83, + .removed = HEX_VER_NONE }, + [J2_trap2] = { .introduced = HEX_VER_V83, .removed = HEX_VER_NONE }, + [Y4_dcfetch_multi] = { .introduced = HEX_VER_V85, .removed = HEX_VER_NONE }, [AM_addw_aq] = { .introduced = HEX_VER_V85, .removed = HEX_VER_NONE }, diff --git a/target/hexagon/gen_idef_parser_funcs.py b/target/hexagon/gen_idef_parser_funcs.py index 7151a4f6713..9293be4c398 100644 --- a/target/hexagon/gen_idef_parser_funcs.py +++ b/target/hexagon/gen_idef_parser_funcs.py @@ -77,7 +77,7 @@ def main(): if tag in {"S4_vrcrotate_acc", "S4_vrcrotate"}: continue ## Skip trap instructions - if tag in {"J2_trap0", "J2_trap1"}: + if tag in {"J2_trap0", "J2_trap1", "J2_trap2"}: continue ## Skip 128-bit instructions if tag in {"A7_croundd_ri", "A7_croundd_rr"}: diff --git a/target/hexagon/gen_tcg_funcs.py b/target/hexagon/gen_tcg_funcs.py index b09ce7c285f..bdc3fa0fe04 100755 --- a/target/hexagon/gen_tcg_funcs.py +++ b/target/hexagon/gen_tcg_funcs.py @@ -86,7 +86,9 @@ def gen_tcg_func(f, tag, regs, imms): if "A_HVX_IEEE_FP" in hex_common.attribdict[tag]: gen_disabled_ieee_insn(f, tag, regs) - if hex_common.is_idef_parser_enabled(tag): + if (hex_common.is_idef_parser_enabled(tag) and tag not in { + "V2_vallocframe_imm", "V2_vallocframe_reg", + "V2_vdeallocframe_imm", "V2_vdeallocframe_reg"}): gpr_operands = [ hex_common.get_register(tag, regtype, regid) for regtype, regid in regs diff --git a/target/hexagon/imported/encode_pp.def b/target/hexagon/imported/encode_pp.def index c590ed4f959..ed1de09a40c 100644 --- a/target/hexagon/imported/encode_pp.def +++ b/target/hexagon/imported/encode_pp.def @@ -409,6 +409,11 @@ DEF_EXT_SPACE(EXTRACTW, ICLASS_LD" 001 0 000 iiiii PP0iiiii 001iiiii") DEF_ENC32(Y2_dcfetchbo, "10010100000sssssPP000iiiiiiiiiii") DEF_ENC32(Y4_dcfetch_multi,"10010100000sssssPP001ttttt------") DEF_ENC32(Y2_dcfetchbo_nt,"10010100000sssssPP10-iiiiiiiiiii") +DEF_ENC32(V2_vallocframe_imm,"01100000100-----PP001----iiiiiii") +DEF_ENC32(V2_vallocframe_reg,"01100000100sssssPP010-----------") +DEF_ENC32(V2_vdeallocframe_imm,"01101010100-----PP001----iiiiiii") +DEF_ENC32(V2_vdeallocframe_reg,"01101001010sssssPP010-----------") +DEF_ENC32(J2_trap2,"0101010011------PP-iiiii---iii--") diff --git a/target/hexagon/imported/system.idef b/target/hexagon/imported/system.idef index 9c4897a2eee..ff208b1a1f0 100644 --- a/target/hexagon/imported/system.idef +++ b/target/hexagon/imported/system.idef @@ -48,6 +48,9 @@ Q6INSN(J2_trap1,"trap1(Rx32,#u8)",ATTRIBS(A_COF,A_NOTE_NOPACKET,A_RESTRICT_NOPAC fVIRTINSN_SPSWAP(uiV,RxV); }) +Q6INSN(J2_trap2,"trap2(#u8)",ATTRIBS(A_COF,A_RESTRICT_NOPACKET), + "Trap to Operating System", { fTRAP(2,uiV); }) + Q6INSN(J2_pause,"pause(#u8)",ATTRIBS(A_COF,A_NOTE_NOPACKET,A_RESTRICT_NOPACKET), "Enter low-power state for #u8 cycles",{fPAUSE(uiV);}) @@ -241,6 +244,11 @@ Q6INSN(Y6_dmresume,"dmresume(Rs32)",ATTRIBS(A_NOTE_NOPACKET,A_RESTRICT_NOPACKET, Q6INSN(Y2_dcfetchbo,"dcfetch(Rs32+#u11:3)",ATTRIBS(A_RESTRICT_PREFERSLOT0,A_DCFETCH,A_RESTRICT_NOSLOT1_STORE),"Data Cache Prefetch",{fEA_RI(RsV,uiV); fDCFETCH(EA);}) Q6INSN(Y2_dcfetchbo_nt,"dcfetch(Rs32+#u11:3):nt",ATTRIBS(A_NA_NT,A_RESTRICT_PREFERSLOT0,A_DCFETCH,A_RESTRICT_NOSLOT1_STORE),"Data Cache Prefetch",{fEA_RI(RsV,uiV); fDCFETCH(EA);}) + +Q6INSN(V2_vallocframe_imm,"vallocframe(#u7:0)",ATTRIBS(A_RESTRICT_NOPACKET),"Allocate vector stack frame",{}) +Q6INSN(V2_vallocframe_reg,"vallocframe(Rs32)",ATTRIBS(A_RESTRICT_NOPACKET),"Allocate vector stack frame",{}) +Q6INSN(V2_vdeallocframe_imm,"vdeallocframe(#u7:0)",ATTRIBS(A_RESTRICT_NOPACKET),"Deallocate vector stack frame",{}) +Q6INSN(V2_vdeallocframe_reg,"vdeallocframe(Rs32)",ATTRIBS(A_RESTRICT_NOPACKET),"Deallocate vector stack frame",{}) Q6INSN(Y4_dcfetch_multi,"dcfetch_multi(Rs32,Rt32)",ATTRIBS(A_RESTRICT_PREFERSLOT0,A_DCFETCH,A_RESTRICT_NOSLOT1_STORE),"Data Cache Prefetch",{fEA_REG(RsV); fDCFETCH_MULTI(EA,fEXTRACTU_BITS(RtV,10,0));}) Q6INSN(Y2_dckill,"dckill",ATTRIBS(A_PRIV,A_NOTE_PRIV,A_NOTE_NOPACKET,A_RESTRICT_SLOT0ONLY,A_RESTRICT_NOPACKET,A_CACHEOP,A_DCFLUSHOP),"Data Cache Invalidate",{fDCKILL();}) -- 2.34.1
