Implement v83 restricted indirect-control-flow instructions and validate
their targets.

Signed-off-by: Brian Cain <[email protected]>
---
 target/hexagon/cpu.h                       |  3 ++
 target/hexagon/cpu_bits.h                  |  1 +
 target/hexagon/gen_tcg.h                   | 56 +++++++++++++++++++++-
 target/hexagon/gen_tcg_sys.h               |  6 +++
 target/hexagon/macros.h                    | 12 +++++
 target/hexagon/translate.h                 |  3 ++
 target/hexagon/attribs_def.h.inc           |  1 +
 target/hexagon/reg_fields_def.h.inc        |  1 +
 linux-user/hexagon/cpu_loop.c              |  6 +++
 target/hexagon/cpu.c                       |  6 +++
 target/hexagon/genptr.c                    | 36 ++++++++++++++
 target/hexagon/hex_interrupts.c            |  3 ++
 target/hexagon/hexswi.c                    | 11 +++++
 target/hexagon/machine.c                   |  3 +-
 target/hexagon/translate.c                 | 51 ++++++++++++++++++++
 target/hexagon/tag_rev_info.c.inc          | 20 ++++++++
 target/hexagon/imported/alu.idef           |  3 ++
 target/hexagon/imported/branch.idef        | 38 +++++++++++++++
 target/hexagon/imported/encode_pp.def      | 18 ++++++-
 target/hexagon/imported/encode_subinsn.def |  1 +
 target/hexagon/imported/subinsns.idef      |  2 +
 target/hexagon/imported/system.idef        |  2 +-
 22 files changed, 279 insertions(+), 4 deletions(-)

diff --git a/target/hexagon/cpu.h b/target/hexagon/cpu.h
index 65fd2b29830..310ff5efad9 100644
--- a/target/hexagon/cpu.h
+++ b/target/hexagon/cpu.h
@@ -132,6 +132,9 @@ typedef struct CPUArchState {
     target_ulong gpr[TOTAL_PER_THREAD_REGS];
     target_ulong pred[NUM_PREGS];
     uint32_t cause_code;
+    uint32_t cfi_active;
+    uint32_t cfi_active_log;
+    uint32_t cfi_updated;
 
     /* For comparing with LLDB on target - see adjust_stack_ptrs function */
     target_ulong last_pc_dumped;
diff --git a/target/hexagon/cpu_bits.h b/target/hexagon/cpu_bits.h
index 02ab05b326a..69839ef5230 100644
--- a/target/hexagon/cpu_bits.h
+++ b/target/hexagon/cpu_bits.h
@@ -71,6 +71,7 @@ enum hex_cause {
     HEX_CAUSE_TRAP1 = 0x009,
     HEX_CAUSE_FETCH_NO_XPAGE = 0x011,
     HEX_CAUSE_FETCH_NO_UPAGE = 0x012,
+    HEX_CAUSE_CFI_VIOLATION = 0x014,
     HEX_CAUSE_INVALID_PACKET = 0x015,
     HEX_CAUSE_INVALID_OPCODE = 0x015, /* alias: same cause as INVALID_PACKET */
     HEX_CAUSE_NO_COPROC_ENABLE = 0x016,
diff --git a/target/hexagon/gen_tcg.h b/target/hexagon/gen_tcg.h
index 38d8558c97a..d4f6d34a29d 100644
--- a/target/hexagon/gen_tcg.h
+++ b/target/hexagon/gen_tcg.h
@@ -726,6 +726,16 @@
     gen_callr(ctx, RsV)
 #define fGEN_TCG_J2_callrh(SHORTCODE) \
     gen_callr(ctx, RsV)
+#define fGEN_TCG_J2_callr_rb(SHORTCODE) \
+    do { \
+        gen_callr(ctx, RsV); \
+        gen_set_cfi(ctx); \
+    } while (0)
+#define fGEN_TCG_J2_callrh_rb(SHORTCODE) \
+    do { \
+        gen_callr(ctx, RsV); \
+        gen_set_cfi(ctx); \
+    } while (0)
 
 #define fGEN_TCG_J2_callt(SHORTCODE) \
     gen_cond_call(ctx, PuV, TCG_COND_TSTEQ, riV)
@@ -735,6 +745,16 @@
     gen_cond_callr(ctx, TCG_COND_TSTEQ, PuV, RsV)
 #define fGEN_TCG_J2_callrf(SHORTCODE) \
     gen_cond_callr(ctx, TCG_COND_TSTNE, PuV, RsV)
+#define fGEN_TCG_J2_callrt_rb(SHORTCODE) \
+    do { \
+        gen_cond_callr(ctx, TCG_COND_TSTEQ, PuV, RsV); \
+        gen_cond_set_cfi(ctx, true, PuV, -1); \
+    } while (0)
+#define fGEN_TCG_J2_callrf_rb(SHORTCODE) \
+    do { \
+        gen_cond_callr(ctx, TCG_COND_TSTNE, PuV, RsV); \
+        gen_cond_set_cfi(ctx, false, PuV, -1); \
+    } while (0)
 
 #define fGEN_TCG_J2_loop0r(SHORTCODE) \
     gen_loop0r(ctx, RsV, riV)
@@ -955,6 +975,39 @@
     gen_jumpr(ctx, RsV)
 #define fGEN_TCG_J2_jumprh(SHORTCODE) \
     gen_jumpr(ctx, RsV)
+#define fGEN_TCG_J2_jumpr_rb(SHORTCODE) \
+    do { \
+        gen_jumpr(ctx, RsV); \
+        gen_set_cfi_for_target(ctx, RsN); \
+    } while (0)
+#define fGEN_TCG_J2_jumprh_rb(SHORTCODE) \
+    fGEN_TCG_J2_jumpr_rb(SHORTCODE)
+#define fGEN_TCG_J2_jumprt_rb(SHORTCODE) \
+    do { \
+        gen_cond_jumpr(ctx, RsV, TCG_COND_TSTEQ, PuV); \
+        gen_cond_set_cfi(ctx, true, PuV, RsN); \
+    } while (0)
+#define fGEN_TCG_J2_jumprf_rb(SHORTCODE) \
+    do { \
+        gen_cond_jumpr(ctx, RsV, TCG_COND_TSTNE, PuV); \
+        gen_cond_set_cfi(ctx, false, PuV, RsN); \
+    } while (0)
+#define fGEN_TCG_J2_jumprtpt_rb(SHORTCODE) fGEN_TCG_J2_jumprt_rb(SHORTCODE)
+#define fGEN_TCG_J2_jumprfpt_rb(SHORTCODE) fGEN_TCG_J2_jumprf_rb(SHORTCODE)
+#define fGEN_TCG_J2_jumprtnew_rb(SHORTCODE) \
+    do { \
+        gen_cond_jumpr(ctx, RsV, TCG_COND_TSTEQ, PuN); \
+        gen_cond_set_cfi(ctx, true, PuN, RsN); \
+    } while (0)
+#define fGEN_TCG_J2_jumprfnew_rb(SHORTCODE) \
+    do { \
+        gen_cond_jumpr(ctx, RsV, TCG_COND_TSTNE, PuN); \
+        gen_cond_set_cfi(ctx, false, PuN, RsN); \
+    } while (0)
+#define fGEN_TCG_J2_jumprtnewpt_rb(SHORTCODE) \
+    fGEN_TCG_J2_jumprtnew_rb(SHORTCODE)
+#define fGEN_TCG_J2_jumprfnewpt_rb(SHORTCODE) \
+    fGEN_TCG_J2_jumprfnew_rb(SHORTCODE)
 #define fGEN_TCG_J4_jumpseti(SHORTCODE) \
     do { \
         tcg_gen_movi_tl(RdV, UiV); \
@@ -1144,7 +1197,7 @@
                            RdV, tcg_constant_tl(0)); \
     } while (0)
 
-#define fGEN_TCG_Y2_break(SHORTCODE)
+#define fGEN_TCG_Y2_break(SHORTCODE) gen_reset_cfi(ctx)
 #define fGEN_TCG_J2_unpause(SHORTCODE)
 
 #ifdef CONFIG_USER_ONLY
@@ -1426,4 +1479,5 @@
 #endif
 
 #define fGEN_TCG_A2_nop(SHORTCODE) do { } while (0)
+#define fGEN_TCG_A2_nop_rb(SHORTCODE) gen_reset_cfi(ctx)
 #define fGEN_TCG_SA1_setin1(SHORTCODE) tcg_gen_movi_tl(RdV, -1)
diff --git a/target/hexagon/gen_tcg_sys.h b/target/hexagon/gen_tcg_sys.h
index c9f6b41a877..d11109fcfb6 100644
--- a/target/hexagon/gen_tcg_sys.h
+++ b/target/hexagon/gen_tcg_sys.h
@@ -127,11 +127,17 @@
  */
 #define fGEN_TCG_J2_rte(SHORTCODE) \
     do { \
+        TCGv_i32 cfi = tcg_temp_new_i32(); \
         TCGv_i32 new_ssr = tcg_temp_new_i32(); \
+        tcg_gen_extract_i32(cfi, hex_t_sreg[HEX_SREG_SSR], \
+                            reg_field_info[SSR_CFI].offset, 1); \
+        fSET_CFI(cfi); \
         tcg_gen_deposit_tl(new_ssr, hex_t_sreg[HEX_SREG_SSR], \
                            tcg_constant_tl(0), \
                            reg_field_info[SSR_EX].offset, \
                            reg_field_info[SSR_EX].width); \
+        tcg_gen_deposit_tl(new_ssr, new_ssr, tcg_constant_tl(0), \
+                           reg_field_info[SSR_CFI].offset, 1); \
         gen_log_sreg_write(ctx, HEX_SREG_SSR, new_ssr); \
         gen_jumpr(ctx, hex_t_sreg[HEX_SREG_ELR]); \
     } while (0)
diff --git a/target/hexagon/macros.h b/target/hexagon/macros.h
index a5b9c24c6bb..195bd6a0c9c 100644
--- a/target/hexagon/macros.h
+++ b/target/hexagon/macros.h
@@ -423,6 +423,18 @@ static inline TCGv gen_read_ireg(TCGv result, TCGv val, 
int shift)
 #define fCAST8S_16S(A) (int128_exts64(A))
 #define fCAST16S_8S(A) (int128_getlo(A))
 
+#define fSET_CFI(CFI_VALUE) \
+    do { \
+        TCGLabel *skip_cfi_reset = gen_new_label(); \
+        tcg_gen_movcond_i32(TCG_COND_NE, hex_cfi_active_log, hex_cfi_updated, \
+                            tcg_constant_i32(1), tcg_constant_i32(0), \
+                            hex_cfi_active_log); \
+        tcg_gen_movi_i32(hex_cfi_updated, 1); \
+        tcg_gen_brcondi_i32(TCG_COND_EQ, CFI_VALUE, 0, skip_cfi_reset); \
+        tcg_gen_movi_i32(hex_cfi_active_log, 1); \
+        gen_set_label(skip_cfi_reset); \
+    } while (0)
+
 #ifdef QEMU_GENERATE
 #define fEA_RI(REG, IMM) tcg_gen_addi_tl(EA, REG, IMM)
 #define fEA_RRs(REG, REG2, SCALE) \
diff --git a/target/hexagon/translate.h b/target/hexagon/translate.h
index a4fc9d0c6f1..fd68ed1f6ea 100644
--- a/target/hexagon/translate.h
+++ b/target/hexagon/translate.h
@@ -365,6 +365,9 @@ 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];
+extern TCGv_i32 hex_cfi_active;
+extern TCGv_i32 hex_cfi_active_log;
+extern TCGv_i32 hex_cfi_updated;
 void gen_precise_exception(int cause, uint32_t pc);
 #ifdef CONFIG_USER_ONLY
 #define hex_hvx_ptr tcg_env
diff --git a/target/hexagon/attribs_def.h.inc b/target/hexagon/attribs_def.h.inc
index 8deef8e4cfb..96ad1fd2f8e 100644
--- a/target/hexagon/attribs_def.h.inc
+++ b/target/hexagon/attribs_def.h.inc
@@ -200,6 +200,7 @@ DEF_ATTRIB(NOTE_SHIFT_RESOURCE, "Uses the HVX shift 
resource.", "", "")
 /* Restrictions to make note of */
 DEF_ATTRIB(RESTRICT_NOSLOT1_STORE, "Packet must not have slot 1 store", "", "")
 DEF_ATTRIB(RESTRICT_LATEPRED, "Predicate can not be used as a .new.", "", "")
+DEF_ATTRIB(RESTRICT_TARGET, "Restricted branch target instruction", "", "")
 
 /* HVX IEEE FP extension attributes */
 DEF_ATTRIB(HVX_IEEE_FP, "HVX IEEE FP extension instruction", "", "")
diff --git a/target/hexagon/reg_fields_def.h.inc 
b/target/hexagon/reg_fields_def.h.inc
index 553f6ffffbc..21babbbb982 100644
--- a/target/hexagon/reg_fields_def.h.inc
+++ b/target/hexagon/reg_fields_def.h.inc
@@ -95,6 +95,7 @@ DEF_REG_FIELD(SYSCFG_L2GCA, 31, 1)
 /* SSR fields */
 DEF_REG_FIELD(SSR_CAUSE, 0, 8)
 DEF_REG_FIELD(SSR_ASID, 8, 7)
+DEF_REG_FIELD(SSR_CFI, 15, 1)
 DEF_REG_FIELD(SSR_UM, 16, 1)
 DEF_REG_FIELD(SSR_EX, 17, 1)
 DEF_REG_FIELD(SSR_IE, 18, 1)
diff --git a/linux-user/hexagon/cpu_loop.c b/linux-user/hexagon/cpu_loop.c
index 2e66b4d9ac8..f234af4ff82 100644
--- a/linux-user/hexagon/cpu_loop.c
+++ b/linux-user/hexagon/cpu_loop.c
@@ -77,6 +77,12 @@ void cpu_loop(CPUHexagonState *env)
                 force_sig_fault(TARGET_SIGSEGV, TARGET_SEGV_BNDERR,
                                 env->gpr[HEX_REG_PC]);
                 break;
+            case HEX_CAUSE_CFI_VIOLATION:
+                env->cfi_active = 0;
+                env->cfi_updated = 0;
+                force_sig_fault(TARGET_SIGILL, TARGET_ILL_ILLOPC,
+                                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 6adeee9d57f..5d8241eccc1 100644
--- a/target/hexagon/cpu.c
+++ b/target/hexagon/cpu.c
@@ -413,6 +413,9 @@ void hexagon_cpu_soft_reset(CPUHexagonState *env)
 
     BQL_LOCK_GUARD();
     env->llsc_addr = ~0;
+    env->cfi_active = 0;
+    env->cfi_active_log = 0;
+    env->cfi_updated = 0;
     env->t_sreg[HEX_SREG_SSR] = 0;
     hexagon_ssr_set_cause(env, HEX_CAUSE_RESET);
 
@@ -450,6 +453,9 @@ static void hexagon_cpu_reset_hold(Object *obj, ResetType 
type)
     set_float_default_nan_pattern(0b01111111, &env->hvx_fp_status);
 
     env->llsc_addr = ~0;
+    env->cfi_active = 0;
+    env->cfi_active_log = 0;
+    env->cfi_updated = 0;
 #ifndef CONFIG_USER_ONLY
     memset(env->t_sreg, 0, sizeof(uint32_t) * NUM_SREGS);
     memset(env->greg, 0, sizeof(uint32_t) * NUM_GREGS);
diff --git a/target/hexagon/genptr.c b/target/hexagon/genptr.c
index 7ef60244de0..0c4d1f489ee 100644
--- a/target/hexagon/genptr.c
+++ b/target/hexagon/genptr.c
@@ -1057,6 +1057,42 @@ static void gen_cond_callr(DisasContext *ctx,
     gen_set_label(skip);
 }
 
+static void gen_set_cfi(DisasContext *ctx)
+{
+    fSET_CFI(tcg_constant_i32(1));
+}
+
+static void gen_reset_cfi(DisasContext *ctx)
+{
+    fSET_CFI(tcg_constant_i32(0));
+}
+
+/* Indirect transfers through LR are returns, which do not set the CFI state */
+static void gen_set_cfi_for_target(DisasContext *ctx, int rs_num)
+{
+    if (rs_num == HEX_REG_LR) {
+        gen_reset_cfi(ctx);
+    } else {
+        gen_set_cfi(ctx);
+    }
+}
+
+/*
+ * Update the CFI state if the predicate (true if @sense, else false) holds.
+ * @rs_num is the jump target register, or -1 for calls.
+ */
+static void gen_cond_set_cfi(DisasContext *ctx, bool sense, TCGv pred,
+                             int rs_num)
+{
+    TCGv lsb = tcg_temp_new();
+    TCGLabel *skip = gen_new_label();
+
+    tcg_gen_andi_tl(lsb, pred, 1);
+    tcg_gen_brcondi_tl(sense ? TCG_COND_EQ : TCG_COND_NE, lsb, 0, skip);
+    gen_set_cfi_for_target(ctx, rs_num);
+    gen_set_label(skip);
+}
+
 #ifndef CONFIG_HEXAGON_IDEF_PARSER
 /* frame = ((LR << 32) | FP) ^ (FRAMEKEY << 32)) */
 static TCGv_i64 gen_frame_scramble(void)
diff --git a/target/hexagon/hex_interrupts.c b/target/hexagon/hex_interrupts.c
index ab66d548a1e..b17ca20d6ca 100644
--- a/target/hexagon/hex_interrupts.c
+++ b/target/hexagon/hex_interrupts.c
@@ -48,6 +48,7 @@ static void set_ssr_ex_cause(CPUHexagonState *env, int ex, 
uint32_t cause)
     old = env->t_sreg[HEX_SREG_SSR];
     SET_SYSTEM_FIELD(env, HEX_SREG_SSR, SSR_EX, ex);
     SET_SYSTEM_FIELD(env, HEX_SREG_SSR, SSR_CAUSE, cause);
+    SET_SYSTEM_FIELD(env, HEX_SREG_SSR, SSR_CFI, env->cfi_active);
     new = env->t_sreg[HEX_SREG_SSR];
     hexagon_modify_ssr(env, new, old);
 }
@@ -369,6 +370,8 @@ static void hex_accept_int(CPUHexagonState *env, int 
int_num)
                                    env->threadId);
 
         set_ssr_ex_cause(env, 1, HEX_CAUSE_INT0 | int_num);
+        env->cfi_active = 0;
+        env->cfi_updated = 0;
         set_elr(env, elr);
         env->gpr[HEX_REG_PC] = evb | (cs->exception_index << 2);
     }
diff --git a/target/hexagon/hexswi.c b/target/hexagon/hexswi.c
index 73949720ccf..82e233243ca 100644
--- a/target/hexagon/hexswi.c
+++ b/target/hexagon/hexswi.c
@@ -779,7 +779,17 @@ void hexagon_cpu_do_interrupt(CPUState *cs)
     env->llsc_addr = ~0;
 
     ssr = env->t_sreg[HEX_SREG_SSR];
+    if (GET_SSR_FIELD(SSR_EX, ssr) == 0) {
+        SET_SSR_FIELD(env, SSR_CFI, env->cfi_active);
+    }
+    env->cfi_active = 0;
+    env->cfi_updated = 0;
+
     if (GET_SSR_FIELD(SSR_EX, ssr) == 1) {
+        /*
+         * Double exception: keep the SSR.CFI value saved by the first
+         * exception, which a later rte would need to restore.
+         */
         if (cpu->globalregs) {
             hexagon_globalreg_write(cpu->globalregs, HEX_SREG_DIAG,
                                     env->cause_code, env->threadId);
@@ -879,6 +889,7 @@ void hexagon_cpu_do_interrupt(CPUState *cs)
         switch (env->cause_code) {
         case HEX_CAUSE_FETCH_NO_XPAGE:
         case HEX_CAUSE_FETCH_NO_UPAGE:
+        case HEX_CAUSE_CFI_VIOLATION:
         case HEX_CAUSE_PRIV_NO_READ:
         case HEX_CAUSE_PRIV_NO_UREAD:
         case HEX_CAUSE_PRIV_NO_WRITE:
diff --git a/target/hexagon/machine.c b/target/hexagon/machine.c
index f3e97224d81..7b95907d015 100644
--- a/target/hexagon/machine.c
+++ b/target/hexagon/machine.c
@@ -21,7 +21,7 @@ static int hexagon_cpu_post_load(void *opaque, int version_id)
 
 const VMStateDescription vmstate_hexagon_cpu = {
     .name = "cpu",
-    .version_id = 2,
+    .version_id = 3,
     .minimum_version_id = 2,
     .post_load = hexagon_cpu_post_load,
     .fields = (const VMStateField[]) {
@@ -37,6 +37,7 @@ const VMStateDescription vmstate_hexagon_cpu = {
         VMSTATE_UINT32(env.cause_code, HexagonCPU),
         VMSTATE_UINT64(env.t_cycle_count, HexagonCPU),
         VMSTATE_UINT32(env.imprecise_exception, HexagonCPU),
+        VMSTATE_UINT32_V(env.cfi_active, HexagonCPU, 3),
 
         VMSTATE_END_OF_LIST()
     },
diff --git a/target/hexagon/translate.c b/target/hexagon/translate.c
index 665791db4fb..4ad019c67ef 100644
--- a/target/hexagon/translate.c
+++ b/target/hexagon/translate.c
@@ -69,6 +69,9 @@ TCGv hex_imprecise_exception;
 TCGv hex_vstore_addr[VSTORES_MAX];
 TCGv hex_vstore_size[VSTORES_MAX];
 TCGv hex_vstore_pending[VSTORES_MAX];
+TCGv_i32 hex_cfi_active;
+TCGv_i32 hex_cfi_active_log;
+TCGv_i32 hex_cfi_updated;
 #ifndef CONFIG_USER_ONLY
 TCGv_ptr hex_hvx_ptr;
 #endif
@@ -456,6 +459,36 @@ static void mark_implicit_reg_write(DisasContext *ctx, int 
attrib, int rnum)
     }
 }
 
+static bool pkt_legal_cfi_target(const Packet *pkt)
+{
+    int i;
+
+    for (i = 0; i < pkt->num_insns; i++) {
+        if (GET_ATTRIB(pkt->insn[i].opcode, A_RESTRICT_TARGET) ||
+            pkt->insn[i].opcode == Y2_break ||
+            (pkt->insn[i].opcode == J2_trap0 &&
+             pkt->insn[i].immed[0] == 0xdb)) {
+            return true;
+        }
+    }
+    return false;
+}
+
+static void gen_cfi_check(DisasContext *ctx)
+{
+    TCGLabel *skip;
+
+    if (ctx->hex_def->hex_version < HEX_VER_V83 ||
+        pkt_legal_cfi_target(&ctx->pkt)) {
+        return;
+    }
+
+    skip = gen_new_label();
+    tcg_gen_brcondi_i32(TCG_COND_EQ, hex_cfi_active, 0, skip);
+    gen_precise_exception(HEX_CAUSE_CFI_VIOLATION, ctx->pkt.pc);
+    gen_set_label(skip);
+}
+
 static void mark_implicit_usr_write(DisasContext *ctx, int attrib)
 {
     uint16_t opcode = ctx->insn->opcode;
@@ -724,6 +757,8 @@ static void gen_start_packet(DisasContext *ctx)
         tcg_gen_movi_tl(hex_gpr[HEX_REG_PC], ctx->next_PC);
     }
 
+    gen_cfi_check(ctx);
+
     /* Preload the predicated registers into get_result_gpr(ctx, i) */
     if (ctx->need_commit &&
         !bitmap_empty(ctx->predicated_regs, TOTAL_PER_THREAD_REGS)) {
@@ -1251,6 +1286,16 @@ static void gen_commit_packet(DisasContext *ctx)
     process_store_log(ctx);
 
     gen_reg_writes(ctx);
+    if (ctx->hex_def->hex_version >= HEX_VER_V83) {
+        if (pkt_legal_cfi_target(&ctx->pkt)) {
+            tcg_gen_movi_i32(hex_cfi_active_log, 0);
+            tcg_gen_movi_i32(hex_cfi_updated, 1);
+        }
+        tcg_gen_movcond_i32(TCG_COND_NE, hex_cfi_active, hex_cfi_updated,
+                            tcg_constant_i32(0), hex_cfi_active_log,
+                            hex_cfi_active);
+        tcg_gen_movi_i32(hex_cfi_updated, 0);
+    }
 #ifndef CONFIG_USER_ONLY
     gen_greg_writes(ctx);
     gen_sreg_writes(ctx);
@@ -1472,6 +1517,12 @@ void hexagon_translate_init(void)
     }
     hex_new_value_usr = tcg_global_mem_new(tcg_env,
         offsetof(CPUHexagonState, new_value_usr), "new_value_usr");
+    hex_cfi_active = tcg_global_mem_new_i32(tcg_env,
+        offsetof(CPUHexagonState, cfi_active), "cfi_active");
+    hex_cfi_active_log = tcg_global_mem_new_i32(tcg_env,
+        offsetof(CPUHexagonState, cfi_active_log), "cfi_active_log");
+    hex_cfi_updated = tcg_global_mem_new_i32(tcg_env,
+        offsetof(CPUHexagonState, cfi_updated), "cfi_updated");
 
     for (i = 0; i < NUM_PREGS; i++) {
         hex_pred[i] = tcg_global_mem_new(tcg_env,
diff --git a/target/hexagon/tag_rev_info.c.inc 
b/target/hexagon/tag_rev_info.c.inc
index c2d4886a846..88958b334d8 100644
--- a/target/hexagon/tag_rev_info.c.inc
+++ b/target/hexagon/tag_rev_info.c.inc
@@ -707,6 +707,26 @@ static const struct tag_rev_info 
tag_rev_info[XX_LAST_OPCODE] = {
                                .removed = HEX_VER_NONE },
     [V2_vdeallocframe_reg] = { .introduced = HEX_VER_V83,
                                .removed = HEX_VER_NONE },
+    [J2_callr_rb] = { .introduced = HEX_VER_V83, .removed = HEX_VER_NONE },
+    [J2_callrh_rb] = { .introduced = HEX_VER_V83, .removed = HEX_VER_NONE },
+    [J2_callrt_rb] = { .introduced = HEX_VER_V83, .removed = HEX_VER_NONE },
+    [J2_callrf_rb] = { .introduced = HEX_VER_V83, .removed = HEX_VER_NONE },
+    [J2_jumpr_rb] = { .introduced = HEX_VER_V83, .removed = HEX_VER_NONE },
+    [J2_jumprh_rb] = { .introduced = HEX_VER_V83, .removed = HEX_VER_NONE },
+    [J2_jumprt_rb] = { .introduced = HEX_VER_V83, .removed = HEX_VER_NONE },
+    [J2_jumprf_rb] = { .introduced = HEX_VER_V83, .removed = HEX_VER_NONE },
+    [J2_jumprtpt_rb] = { .introduced = HEX_VER_V83, .removed = HEX_VER_NONE },
+    [J2_jumprfpt_rb] = { .introduced = HEX_VER_V83, .removed = HEX_VER_NONE },
+    [J2_jumprtnew_rb] = { .introduced = HEX_VER_V83, .removed = HEX_VER_NONE },
+    [J2_jumprfnew_rb] = { .introduced = HEX_VER_V83, .removed = HEX_VER_NONE },
+    [J2_jumprtnewpt_rb] = { .introduced = HEX_VER_V83,
+                            .removed = HEX_VER_NONE },
+    [J2_jumprfnewpt_rb] = { .introduced = HEX_VER_V83,
+                            .removed = HEX_VER_NONE },
+    [S2_allocframe_rb] = { .introduced = HEX_VER_V83, .removed = HEX_VER_NONE 
},
+    [SS2_allocframe_rb] = { .introduced = HEX_VER_V83,
+                            .removed = HEX_VER_NONE },
+    [A2_nop_rb] = { .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,
diff --git a/target/hexagon/imported/alu.idef b/target/hexagon/imported/alu.idef
index b8556769891..7c039ab018a 100644
--- a/target/hexagon/imported/alu.idef
+++ b/target/hexagon/imported/alu.idef
@@ -241,6 +241,9 @@ Q6INSN(A2_minup,"Rdd32=minu(Rtt32,Rss32)",ATTRIBS(A_ARCHV3),
 Q6INSN(A2_nop,"nop",ATTRIBS(A_IT_NOP),
 "Nop (32-bit encoding)",
  fHIDE( { }  ))
+Q6INSN(A2_nop_rb,"nop_rb",ATTRIBS(A_IT_NOP,A_RESTRICT_TARGET),
+"Restricted branch nop target",
+ fHIDE( { } ))
 
 
 Q6INSN(A4_ext,"immext(#u26:6)",ATTRIBS(A_IT_EXTENDER),
diff --git a/target/hexagon/imported/branch.idef 
b/target/hexagon/imported/branch.idef
index 93e2e375a5c..b943a41a3fc 100644
--- a/target/hexagon/imported/branch.idef
+++ b/target/hexagon/imported/branch.idef
@@ -37,6 +37,19 @@ Q6INSN(J2_jumpr,"jumpr Rs32",ATTRIBS(A_JINDIR), "indirect 
unconditional jump",
 Q6INSN(J2_jumprh,"jumprh Rs32",ATTRIBS(A_JINDIR, A_HINTED_COF), "indirect 
unconditional jump",
 {fJUMPR(RsN,RsV,COF_TYPE_JUMPR);})
 
+Q6INSN(J2_jumpr_rb,"jumpr_rb Rs32",ATTRIBS(A_JINDIR),
+       "restricted indirect unconditional jump",
+       {fJUMPR(RsN,RsV,COF_TYPE_JUMPR);})
+Q6INSN(J2_jumprh_rb,"jumprh_rb Rs32",ATTRIBS(A_JINDIR, A_HINTED_COF),
+        "restricted hinted indirect unconditional jump",
+        {fJUMPR(RsN,RsV,COF_TYPE_JUMPR);})
+
+#define OLDCOND_JUMP_RB(TAG,OPER,OPER2,ATTRIB,DESCR,SEMANTICS) \
+Q6INSN(TAG##t_rb,"if (Pu4) "OPER":nt 
"OPER2,ATTRIB,DESCR,{fBRANCH_SPECULATE_STALL(fLSBOLD(PuV),,SPECULATE_NOT_TAKEN,12,0);
 if (fLSBOLD(PuV)) { SEMANTICS; }}) \
+Q6INSN(TAG##f_rb,"if (!Pu4) "OPER":nt 
"OPER2,ATTRIB,DESCR,{fBRANCH_SPECULATE_STALL(fLSBOLDNOT(PuV),,SPECULATE_NOT_TAKEN,12,0);
 if (fLSBOLDNOT(PuV)) { SEMANTICS; }}) \
+Q6INSN(TAG##tpt_rb,"if (Pu4) "OPER":t 
"OPER2,ATTRIB,DESCR,{fBRANCH_SPECULATE_STALL(fLSBOLD(PuV),,SPECULATE_TAKEN,12,0);
 if (fLSBOLD(PuV)) { SEMANTICS; }}) \
+Q6INSN(TAG##fpt_rb,"if (!Pu4) "OPER":t 
"OPER2,ATTRIB,DESCR,{fBRANCH_SPECULATE_STALL(fLSBOLDNOT(PuV),,SPECULATE_TAKEN,12,0);
 if (fLSBOLDNOT(PuV)) { SEMANTICS; }})
+
 #define OLDCOND_JUMP(TAG,OPER,OPER2,ATTRIB,DESCR,SEMANTICS) \
 Q6INSN(TAG##t,"if (Pu4) "OPER":nt 
"OPER2,ATTRIB,DESCR,{fBRANCH_SPECULATE_STALL(fLSBOLD(PuV),,SPECULATE_NOT_TAKEN,12,0);
 if (fLSBOLD(PuV)) { SEMANTICS; }}) \
 Q6INSN(TAG##f,"if (!Pu4) "OPER":nt 
"OPER2,ATTRIB,DESCR,{fBRANCH_SPECULATE_STALL(fLSBOLDNOT(PuV),,SPECULATE_NOT_TAKEN,12,0);
 if (fLSBOLDNOT(PuV)) { SEMANTICS; }}) \
@@ -48,6 +61,9 @@ fIMMEXT(riV);fPCALIGN(riV); 
fBRANCH(fREAD_PC()+riV,COF_TYPE_JUMP);)
 
 OLDCOND_JUMP(J2_jumpr,"jumpr","Rs32",ATTRIBS(A_JINDIROLD),"indirect 
conditional jump",
 fJUMPR(RsN,RsV,COF_TYPE_JUMPR);)
+OLDCOND_JUMP_RB(J2_jumpr,"jumpr_rb","Rs32",ATTRIBS(A_JINDIROLD),
+                "restricted indirect conditional jump",
+                fJUMPR(RsN,RsV,COF_TYPE_JUMPR);)
 
 #define NEWCOND_JUMP(TAG,OPER,OPER2,ATTRIB,DESCR,SEMANTICS)\
 Q6INSN(TAG##tnew,"if (Pu4.new) "OPER":nt 
"OPER2,ATTRIB,DESCR,{fBRANCH_SPECULATE_STALL(fLSBNEW(PuN),, SPECULATE_NOT_TAKEN 
, 12,0)} {if(fLSBNEW(PuN)){SEMANTICS;}})\
@@ -61,6 +77,17 @@ fIMMEXT(riV); fPCALIGN(riV); 
fBRANCH(fREAD_PC()+riV,COF_TYPE_JUMPNEW);)
 NEWCOND_JUMP(J2_jumpr,"jumpr","Rs32",ATTRIBS(A_JINDIRNEW,A_ARCHV3),"indirect 
conditional jump",
 fJUMPR(RsN,RsV,COF_TYPE_JUMPR);)
 
+#define NEWCOND_JUMP_RB(TAG,OPER,OPER2,ATTRIB,DESCR,SEMANTICS) \
+Q6INSN(TAG##tnew_rb,"if (Pu4.new) "OPER":nt 
"OPER2,ATTRIB,DESCR,{fBRANCH_SPECULATE_STALL(fLSBNEW(PuN),, SPECULATE_NOT_TAKEN 
, 12,0)} {if(fLSBNEW(PuN)){SEMANTICS;}}) \
+Q6INSN(TAG##fnew_rb,"if (!Pu4.new) "OPER":nt 
"OPER2,ATTRIB,DESCR,{fBRANCH_SPECULATE_STALL(fLSBNEWNOT(PuN),, 
SPECULATE_NOT_TAKEN , 12,0)} {if(fLSBNEWNOT(PuN)){SEMANTICS;}}) \
+Q6INSN(TAG##tnewpt_rb,"if (Pu4.new) "OPER":t 
"OPER2,ATTRIB,DESCR,{fBRANCH_SPECULATE_STALL(fLSBNEW(PuN),, SPECULATE_TAKEN , 
12,0)} {if(fLSBNEW(PuN)){SEMANTICS;}}) \
+Q6INSN(TAG##fnewpt_rb,"if (!Pu4.new) "OPER":t 
"OPER2,ATTRIB,DESCR,{fBRANCH_SPECULATE_STALL(fLSBNEWNOT(PuN),, SPECULATE_TAKEN 
, 12,0)} {if(fLSBNEWNOT(PuN)){SEMANTICS;}})
+
+NEWCOND_JUMP_RB(J2_jumpr,"jumpr_rb","Rs32",
+                ATTRIBS(A_JINDIRNEW,A_ARCHV3),
+                "restricted indirect conditional jump",
+                fJUMPR(RsN,RsV,COF_TYPE_JUMPR);)
+
 
 
 Q6INSN(J4_hintjumpr,"hintjr(Rs32)",ATTRIBS(A_JINDIR),"hint indirect 
conditional jump",
@@ -202,6 +229,17 @@ Q6INSN(J2_callrf,"if (!Pu4) callr 
Rs32",ATTRIBS(CINDIR_STD),"indirect conditiona
 Q6INSN(J2_callrh,"callrh Rs32",ATTRIBS(CINDIR_STD, A_HINTED_COF), "hinted 
indirect unconditional call",
 { fCALLR(RsV); })
 
+Q6INSN(J2_callr_rb,"callr_rb Rs32",ATTRIBS(CINDIR_STD),
+       "restricted indirect unconditional call", { fCALLR(RsV); })
+Q6INSN(J2_callrh_rb,"callrh_rb Rs32",ATTRIBS(CINDIR_STD, A_HINTED_COF),
+        "restricted hinted indirect unconditional call", { fCALLR(RsV); })
+Q6INSN(J2_callrt_rb,"if (Pu4) callr_rb Rs32",ATTRIBS(CINDIR_STD),
+       "restricted indirect conditional call if true",
+       {if (fLSBOLD(PuV)) { fCALLR(RsV); }})
+Q6INSN(J2_callrf_rb,"if (!Pu4) callr_rb Rs32",ATTRIBS(CINDIR_STD),
+       "restricted indirect conditional call if false",
+       {if (fLSBOLDNOT(PuV)) { fCALLR(RsV); }})
+
 
 
 /*********************************************/
diff --git a/target/hexagon/imported/encode_pp.def 
b/target/hexagon/imported/encode_pp.def
index ed1de09a40c..97af0fcb394 100644
--- a/target/hexagon/imported/encode_pp.def
+++ b/target/hexagon/imported/encode_pp.def
@@ -413,6 +413,20 @@ 
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_callr_rb,"01010000001sssssPP--------------")
+DEF_ENC32(J2_callrh_rb,"01010000010sssssPP--------------")
+DEF_ENC32(J2_callrt_rb,"01010001100sssssPP----uu--------")
+DEF_ENC32(J2_callrf_rb,"01010001101sssssPP----uu--------")
+DEF_ENC32(J2_jumpr_rb,"01010010000sssssPP--------------")
+DEF_ENC32(J2_jumprh_rb,"01010010010sssssPP--------------")
+DEF_ENC32(J2_jumprt_rb,"01010011110sssssPP-00-uu--------")
+DEF_ENC32(J2_jumprf_rb,"01010011111sssssPP-00-uu--------")
+DEF_ENC32(J2_jumprtpt_rb,"01010011110sssssPP-10-uu--------")
+DEF_ENC32(J2_jumprfpt_rb,"01010011111sssssPP-10-uu--------")
+DEF_ENC32(J2_jumprtnew_rb,"01010011110sssssPP-01-uu--------")
+DEF_ENC32(J2_jumprfnew_rb,"01010011111sssssPP-01-uu--------")
+DEF_ENC32(J2_jumprtnewpt_rb,"01010011110sssssPP-11-uu--------")
+DEF_ENC32(J2_jumprfnewpt_rb,"01010011111sssssPP-11-uu--------")
 DEF_ENC32(J2_trap2,"0101010011------PP-iiiii---iii--")
 
 
@@ -514,6 +528,7 @@ 
DEF_ENC32(S2_pstorerdf_pi_nt,"10101010110xxxxxPP1ttttt0iiii1vv")
 /*                               x bus/cache     */
 /*                                    x store/cache     */
 DEF_ENC32(S2_allocframe,   ICLASS_ST" 000 01 00xxxxx PP000iii iiiiiiii")
+DEF_ENC32(S2_allocframe_rb,ICLASS_ST" 000 01 00xxxxx PP100iii iiiiiiii")
 DEF_ENC32(Y5_l2locka,      ICLASS_ST" 000 01 11sssss PP1----- ------dd")
 DEF_ENC32(Y2_dczeroa,      ICLASS_ST" 000 01 10sssss PP0----- --------")
 DEF_ENC32(Y2_dczeroa_nt,"10100000110sssssPP1-------------")
@@ -1407,7 +1422,8 @@ DEF_ENC32(C2_cmoveif,   ICLASS_ALU2op" 1110 1uu0iiii 
PP0iiiii iiiddddd")
 
 
 DEF_FIELDROW_DESC32(    ICLASS_ALU2op" 1111 -------- PP------ --------","[#15] 
nop")
-DEF_ENC32(A2_nop,       ICLASS_ALU2op" 1111 -------- PP------ --------")
+DEF_ENC32(A2_nop,       ICLASS_ALU2op" 1111 0------- PP------ --------")
+DEF_ENC32(A2_nop_rb,    ICLASS_ALU2op" 1111 1------- PP------ --------")
 
 
 
diff --git a/target/hexagon/imported/encode_subinsn.def 
b/target/hexagon/imported/encode_subinsn.def
index 742fb50efb6..4ff3e95a253 100644
--- a/target/hexagon/imported/encode_subinsn.def
+++ b/target/hexagon/imported/encode_subinsn.def
@@ -71,6 +71,7 @@ DEF_ENC_SUBINSN(SS2_storebi0,    SUBINSN_S2, "100 10ssssiiii")
 DEF_ENC_SUBINSN(SS2_storebi1,    SUBINSN_S2, "100 11ssssiiii")
 
 DEF_ENC_SUBINSN(SS2_allocframe,  SUBINSN_S2, "111 0iiiii----")
+DEF_ENC_SUBINSN(SS2_allocframe_rb,SUBINSN_S2, "111 1iiiii----")
 
 
 
diff --git a/target/hexagon/imported/subinsns.idef 
b/target/hexagon/imported/subinsns.idef
index be0ae8779da..a4be385f588 100644
--- a/target/hexagon/imported/subinsns.idef
+++ b/target/hexagon/imported/subinsns.idef
@@ -147,3 +147,5 @@ Q6INSN(SS2_storebi1,   "memb(Rs16+#u4:0)=#1", 
ATTRIBS(A_MEMSIZE_1B,A_STORE,A_SUB
 
 Q6INSN(SS2_allocframe,"allocframe(#u5:3)", 
ATTRIBS(A_REGWRSIZE_8B,A_SUBINSN,A_MEMSIZE_8B,A_STORE,A_RESTRICT_SLOT0ONLY), 
"Allocate stack frame",
 { fEA_RI(fREAD_SP(),-8);  fSTORE(1,8,EA,fFRAME_SCRAMBLE((fCAST8_8u(fREAD_LR()) 
<< 32) | fCAST4_4u(fREAD_FP()))); fWRITE_FP(EA); fFRAMECHECK(EA-uiV,EA); 
fWRITE_SP(EA-uiV); })
+Q6INSN(SS2_allocframe_rb,"allocframe_rb(#u5:3)", 
ATTRIBS(A_REGWRSIZE_8B,A_SUBINSN,A_MEMSIZE_8B,A_STORE,A_RESTRICT_SLOT0ONLY,A_RESTRICT_TARGET),
 "Allocate stack frame",
+{ fEA_RI(fREAD_SP(),-8);  fSTORE(1,8,EA,fFRAME_SCRAMBLE((fCAST8_8u(fREAD_LR()) 
<< 32) | fCAST4_4u(fREAD_FP()))); fWRITE_FP(EA); fFRAMECHECK(EA-uiV,EA); 
fWRITE_SP(EA-uiV); })
diff --git a/target/hexagon/imported/system.idef 
b/target/hexagon/imported/system.idef
index 80fa0cd5618..f279c52b7d6 100644
--- a/target/hexagon/imported/system.idef
+++ b/target/hexagon/imported/system.idef
@@ -48,7 +48,7 @@ 
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),
+Q6INSN(J2_trap2,"trap2(#u8)",ATTRIBS(A_COF,A_NOTE_NOPACKET,A_RESTRICT_NOPACKET),
        "Trap to Operating System", { fTRAP(2,uiV); })
 
 
Q6INSN(J2_pause,"pause(#u8)",ATTRIBS(A_COF,A_NOTE_NOPACKET,A_RESTRICT_NOPACKET),
-- 
2.34.1

Reply via email to