Skip to content

Commit b8e3210

Browse files
quic-mathbernandrom3da
authored andcommitted
target/hexagon: raise exception on multiple writes to same reg
As specified by the PRM, we should raise an exception when a packet contains multiple writes to the same register. Lets introduce a bitmap at the CPUArchState, looking for writes to already written registers and properly generate an exception when needed. Also add a test case to tests/tcg/system. Signed-off-by: Matheus Tavares Bernardino <quic_mathbern@quicinc.com>
1 parent 3ce679e commit b8e3210

File tree

7 files changed

+63
-0
lines changed

7 files changed

+63
-0
lines changed

target/hexagon/cpu.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828

2929
#define NUM_PREGS 4
3030
#define TOTAL_PER_THREAD_REGS 64
31+
#define NUM_GPREGS 32
3132

3233
#define SLOTS_MAX 4
3334
#define STORES_MAX 2
@@ -78,6 +79,9 @@ typedef struct CPUArchState {
7879

7980
uint8_t slot_cancelled;
8081
target_ulong new_value_usr;
82+
target_ulong gpreg_written;
83+
QEMU_BUILD_BUG_MSG(NUM_GPREGS > CHAR_BIT * sizeof(target_ulong),
84+
"Hexagon's CPUArchState.gpreg_written type is too small");
8185

8286
MemLog mem_log_stores[STORES_MAX];
8387

target/hexagon/cpu_bits.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
enum hex_event {
2727
HEX_EVENT_NONE = -1,
2828
HEX_EVENT_TRAP0 = 0x008,
29+
HEX_EVENT_PRECISE = 0x2,
2930
};
3031

3132
enum hex_cause {
@@ -34,6 +35,7 @@ enum hex_cause {
3435
HEX_CAUSE_FETCH_NO_UPAGE = 0x012,
3536
HEX_CAUSE_INVALID_PACKET = 0x015,
3637
HEX_CAUSE_INVALID_OPCODE = 0x015,
38+
HEX_CAUSE_REG_WRITE_CONFLICT = 0x01d,
3739
HEX_CAUSE_PC_NOT_ALIGNED = 0x01e,
3840
HEX_CAUSE_PRIV_NO_UREAD = 0x024,
3941
HEX_CAUSE_PRIV_NO_UWRITE = 0x025,

target/hexagon/genptr.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ void gen_log_reg_write(DisasContext *ctx, int rnum, TCGv val)
100100

101101
gen_masked_reg_write(val, hex_gpr[rnum], reg_mask);
102102
tcg_gen_mov_tl(get_result_gpr(ctx, rnum), val);
103+
gen_helper_check_reg_write(tcg_env, tcg_constant_tl(rnum));
103104
}
104105

105106
static void gen_log_reg_write_pair(DisasContext *ctx, int rnum, TCGv_i64 val)
@@ -113,6 +114,8 @@ static void gen_log_reg_write_pair(DisasContext *ctx, int rnum, TCGv_i64 val)
113114
/* High word */
114115
tcg_gen_extrh_i64_i32(val32, val);
115116
gen_log_reg_write(ctx, rnum + 1, val32);
117+
118+
gen_helper_check_reg_write_pair(tcg_env, tcg_constant_tl(rnum));
116119
}
117120

118121
TCGv get_result_pred(DisasContext *ctx, int pnum)

target/hexagon/helper.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@ DEF_HELPER_5(vacsh_val, s64, env, s64, s64, s64, i32)
3030
DEF_HELPER_FLAGS_4(vacsh_pred, TCG_CALL_NO_RWG_SE, s32, env, s64, s64, s64)
3131
DEF_HELPER_FLAGS_2(cabacdecbin_val, TCG_CALL_NO_RWG_SE, s64, s64, s64)
3232
DEF_HELPER_FLAGS_2(cabacdecbin_pred, TCG_CALL_NO_RWG_SE, s32, s64, s64)
33+
DEF_HELPER_2(check_reg_write, void, env, int)
34+
DEF_HELPER_3(check_cond_reg_write, void, env, int, int)
35+
DEF_HELPER_2(check_reg_write_pair, void, env, int)
36+
DEF_HELPER_3(check_cond_reg_write_pair, void, env, int, int)
3337

3438
/* Floating point */
3539
DEF_HELPER_2(conv_sf2df, f64, env, f32)

target/hexagon/op_helper.c

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,24 @@ void log_store32(CPUHexagonState *env, target_ulong addr,
5959
env->mem_log_stores[slot].data32 = val;
6060
}
6161

62+
static void do_check_reg_write(CPUHexagonState *env, int rnum)
63+
{
64+
target_ulong mask = 1 << rnum;
65+
if (rnum >= NUM_GPREGS) {
66+
return;
67+
}
68+
if ((env->gpreg_written & mask) == 0) {
69+
env->gpreg_written |= mask;
70+
return;
71+
}
72+
#ifdef CONFIG_USER_ONLY
73+
hexagon_raise_exception_err(env, HEX_CAUSE_REG_WRITE_CONFLICT, 0);
74+
#else
75+
env->cause_code = HEX_CAUSE_REG_WRITE_CONFLICT;
76+
hexagon_raise_exception_err(env, HEX_EVENT_PRECISE, 0);
77+
#endif
78+
}
79+
6280
void log_store64(CPUHexagonState *env, target_ulong addr,
6381
int64_t val, int width, int slot)
6482
{
@@ -67,6 +85,32 @@ void log_store64(CPUHexagonState *env, target_ulong addr,
6785
env->mem_log_stores[slot].data64 = val;
6886
}
6987

88+
void HELPER(check_reg_write)(CPUHexagonState *env, int rnum)
89+
{
90+
do_check_reg_write(env, rnum);
91+
}
92+
93+
void HELPER(check_cond_reg_write)(CPUHexagonState *env, int rnum, int skip)
94+
{
95+
if (!skip) {
96+
do_check_reg_write(env, rnum);
97+
}
98+
}
99+
100+
void HELPER(check_reg_write_pair)(CPUHexagonState *env, int rnum)
101+
{
102+
do_check_reg_write(env, rnum);
103+
do_check_reg_write(env, rnum + 1);
104+
}
105+
106+
void HELPER(check_cond_reg_write_pair)(CPUHexagonState *env, int rnum, int skip)
107+
{
108+
if (!skip) {
109+
do_check_reg_write(env, rnum);
110+
do_check_reg_write(env, rnum + 1);
111+
}
112+
}
113+
70114
static void commit_store(CPUHexagonState *env, int slot_num, uintptr_t ra)
71115
{
72116
uint8_t width = env->mem_log_stores[slot_num].width;

target/hexagon/translate.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ TCGv hex_gpr[TOTAL_PER_THREAD_REGS];
5050
TCGv hex_pred[NUM_PREGS];
5151
TCGv hex_slot_cancelled;
5252
TCGv hex_new_value_usr;
53+
TCGv hex_gpreg_written;
5354
TCGv hex_store_addr[STORES_MAX];
5455
TCGv hex_store_width[STORES_MAX];
5556
TCGv hex_store_val32[STORES_MAX];
@@ -438,6 +439,7 @@ static void gen_start_packet(DisasContext *ctx)
438439
* gen phase, so clear it again.
439440
*/
440441
bitmap_zero(ctx->pregs_written, NUM_PREGS);
442+
tcg_gen_movi_tl(hex_gpreg_written, 0);
441443

442444
/* Initialize the runtime state for packet semantics */
443445
if (need_slot_cancelled(pkt)) {
@@ -1057,6 +1059,9 @@ void hexagon_translate_init(void)
10571059
hex_new_value_usr = tcg_global_mem_new(tcg_env,
10581060
offsetof(CPUHexagonState, new_value_usr), "new_value_usr");
10591061

1062+
hex_gpreg_written = tcg_global_mem_new(tcg_env,
1063+
offsetof(CPUHexagonState, gpreg_written), "gpreg_written");
1064+
10601065
for (i = 0; i < NUM_PREGS; i++) {
10611066
hex_pred[i] = tcg_global_mem_new(tcg_env,
10621067
offsetof(CPUHexagonState, pred[i]),

target/hexagon/translate.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,7 @@ extern TCGv hex_gpr[TOTAL_PER_THREAD_REGS];
270270
extern TCGv hex_pred[NUM_PREGS];
271271
extern TCGv hex_slot_cancelled;
272272
extern TCGv hex_new_value_usr;
273+
extern TCGv hex_gpreg_written;
273274
extern TCGv hex_store_addr[STORES_MAX];
274275
extern TCGv hex_store_width[STORES_MAX];
275276
extern TCGv hex_store_val32[STORES_MAX];

0 commit comments

Comments
 (0)