@samitouri / QOSamiQemu / commits / 6e158c0574

target/hexagon: Add handlers for guest/sysreg r/w

This commit provides handlers to generate TCG for guest and system register reads and writes. They will be leveraged by a future commit. Reviewed-by: Taylor Simpson <ltaylorsimpson@gmail.com> Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>

Brian Cain committed Jun 22, 2026 at 15:28 UTC 6e158c05741d43c4317ecf86599070902acae0cf
1 file changed +151
target/hexagon/genptr.c
+151
@@ -23,6 +23,7 @@
23 #include "exec/helper-gen.h"
24 #include "insn.h"
25 #include "opcodes.h"
26 +#include "sys_macros.h"
27 #include "translate.h"
28 #define QEMU_GENERATE /* Used internally by macros.h */
29 #include "macros.h"
@@ -120,6 +121,156 @@ TCGv get_result_pred(DisasContext *ctx, int pnum)
121 }
122 }
123
124 +#ifndef CONFIG_USER_ONLY
125 +G_GNUC_UNUSED
126 +static bool greg_writable(int rnum, bool pair)
127 +{
128 + if (pair) {
129 + if (rnum < HEX_GREG_G3) {
130 + return true;
131 + }
132 + qemu_log_mask(LOG_UNIMP,
133 + "Warning: ignoring write to guest register pair G%d:%d\n",
134 + rnum + 1, rnum);
135 + } else {
136 + if (rnum <= HEX_GREG_G3) {
137 + return true;
138 + }
139 + qemu_log_mask(LOG_UNIMP,
140 + "Warning: ignoring write to guest register G%d\n", rnum);
141 + }
142 + return false;
143 +}
144 +
145 +G_GNUC_UNUSED
146 +static void check_greg_impl(int rnum, bool pair)
147 +{
148 + if (pair && (!greg_implemented(rnum) || !greg_implemented(rnum + 1))) {
149 + qemu_log_mask(LOG_UNIMP,
150 + "Warning: guest register pair G%d:%d is unimplemented or "
151 + "reserved. Read will yield 0.\n",
152 + rnum + 1, rnum);
153 + } else if (!pair && !greg_implemented(rnum)) {
154 + qemu_log_mask(LOG_UNIMP,
155 + "Warning: guest register G%d is unimplemented or reserved."
156 + " Read will yield 0.\n", rnum);
157 + }
158 +}
159 +
160 +G_GNUC_UNUSED
161 +static inline void gen_log_greg_write(DisasContext *ctx, int rnum, TCGv_i32 val)
162 +{
163 + tcg_gen_mov_i32(ctx->greg_new_value[rnum], val);
164 +}
165 +
166 +G_GNUC_UNUSED
167 +static void gen_log_greg_write_pair(DisasContext *ctx, int rnum, TCGv_i64 val)
168 +{
169 + TCGv_i32 val32 = tcg_temp_new_i32();
170 +
171 + /* Low word */
172 + tcg_gen_extrl_i64_i32(val32, val);
173 + gen_log_greg_write(ctx, rnum, val32);
174 +
175 + /* High word */
176 + tcg_gen_extrh_i64_i32(val32, val);
177 + gen_log_greg_write(ctx, rnum + 1, val32);
178 +}
179 +
180 +static const uint32_t sreg_immut_masks[NUM_SREGS] = {
181 + [HEX_SREG_STID] = 0xff00ff00,
182 + [HEX_SREG_ELR] = 0x00000003,
183 + [HEX_SREG_SSR] = 0x00008000,
184 + [HEX_SREG_CCR] = 0x10e0ff24,
185 + [HEX_SREG_HTID] = IMMUTABLE,
186 + [HEX_SREG_IMASK] = 0xffff0000,
187 + [HEX_SREG_GEVB] = 0x000000ff,
188 +};
189 +
190 +G_GNUC_UNUSED
191 +static void gen_log_sreg_write(DisasContext *ctx, int rnum, TCGv_i32 val)
192 +{
193 + const uint32_t reg_mask = sreg_immut_masks[rnum];
194 +
195 + if (reg_mask != IMMUTABLE) {
196 + if (rnum < HEX_SREG_GLB_START) {
197 + gen_masked_reg_write(val, hex_t_sreg[rnum], reg_mask);
198 + if (ctx->need_commit || rnum == HEX_SREG_SSR) {
199 + tcg_gen_mov_i32(ctx->t_sreg_new_value[rnum], val);
200 + } else {
201 + tcg_gen_mov_i32(hex_t_sreg[rnum], val);
202 + }
203 + } else {
204 + gen_helper_sreg_write_masked(tcg_env, tcg_constant_i32(rnum), val);
205 + }
206 + }
207 +}
208 +
209 +G_GNUC_UNUSED
210 +static void gen_log_sreg_write_pair(DisasContext *ctx, int rnum, TCGv_i64 val)
211 +{
212 + TCGv_i32 val32 = tcg_temp_new_i32();
213 +
214 + /* Low word */
215 + tcg_gen_extrl_i64_i32(val32, val);
216 + gen_log_sreg_write(ctx, rnum, val32);
217 +
218 + /* High word */
219 + tcg_gen_extrh_i64_i32(val32, val);
220 + gen_log_sreg_write(ctx, rnum + 1, val32);
221 +}
222 +
223 +G_GNUC_UNUSED
224 +static void gen_read_sreg(TCGv_i32 dst, int reg_num)
225 +{
226 + if (reg_num >= HEX_SREG_GLB_START || reg_num == HEX_SREG_BADVA) {
227 + gen_helper_sreg_read(dst, tcg_env, tcg_constant_i32(reg_num));
228 + } else {
229 + tcg_gen_mov_i32(dst, hex_t_sreg[reg_num]);
230 + }
231 +}
232 +
233 +G_GNUC_UNUSED
234 +static void gen_read_sreg_pair(TCGv_i64 dst, int reg_num)
235 +{
236 + if (reg_num < HEX_SREG_GLB_START) {
237 + if (reg_num + 1 == HEX_SREG_BADVA) {
238 + TCGv_i32 badva = tcg_temp_new_i32();
239 + gen_helper_sreg_read(badva, tcg_env,
240 + tcg_constant_i32(HEX_SREG_BADVA));
241 + tcg_gen_concat_i32_i64(dst, hex_t_sreg[reg_num], badva);
242 + } else {
243 + tcg_gen_concat_i32_i64(dst, hex_t_sreg[reg_num],
244 + hex_t_sreg[reg_num + 1]);
245 + }
246 + } else {
247 + gen_helper_sreg_read_pair(dst, tcg_env, tcg_constant_i32(reg_num));
248 + }
249 +}
250 +
251 +G_GNUC_UNUSED
252 +static void gen_read_greg(TCGv_i32 dst, int reg_num)
253 +{
254 + if (reg_num <= HEX_GREG_G3) {
255 + tcg_gen_mov_i32(dst, hex_greg[reg_num]);
256 + } else {
257 + gen_helper_greg_read(dst, tcg_env, tcg_constant_i32(reg_num));
258 + }
259 +}
260 +
261 +G_GNUC_UNUSED
262 +static void gen_read_greg_pair(TCGv_i64 dst, int reg_num)
263 +{
264 + if (reg_num == HEX_GREG_G0 || reg_num == HEX_GREG_G2) {
265 + tcg_gen_concat_i32_i64(dst, hex_greg[reg_num],
266 + hex_greg[reg_num + 1]);
267 + } else {
268 + gen_helper_greg_read_pair(dst, tcg_env, tcg_constant_i32(reg_num));
269 + }
270 +}
271 +#endif
272 +
273 +
274 void gen_pred_write(DisasContext *ctx, int pnum, TCGv val)
275 {
276 TCGv pred = get_result_pred(ctx, pnum);