target/hexagon: Handle system/guest registers in gen_analyze_funcs.py and hex_common.py
Add register classes for guest (G) and system (S) registers to hex_common.py, and update gen_analyze_funcs.py to handle them. Guest and system registers can only appear once per packet (one transfer instruction each), so there is no read-after-write hazard to detect during the analyze phase. Source classes (GuestSource, GuestPairSource, SystemSource, SystemPairSource) provide a no-op analyze_read() since these register reads do not need tracking. 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:27 UTC
a9f88b99cb10b7af9afff971618804a367a469bb
2 files changed
+164
-2
target/hexagon/gen_analyze_funcs.py
+12
-2
@@ -22,7 +22,6 @@ import re
22
import string
23
import hex_common
24
25
-
25
##
26
## Generate the code to analyze the instruction
27
## For A2_add: Rd32=add(Rs32,Rt32), { RdV=RsV+RtV;}
@@ -42,6 +41,13 @@ def gen_analyze_func(f, tag, regs, imms):
41
f.write(f"static void analyze_{tag}(DisasContext *ctx)\n")
42
f.write("{\n")
43
44
+ if hex_common.tag_ignore(tag):
45
+ f.write("}\n\n")
46
+ return
47
+
48
+ if hex_common.is_sysemu_tag(tag):
49
+ f.write("#ifndef CONFIG_USER_ONLY\n")
50
+
51
f.write(" Insn *insn G_GNUC_UNUSED = ctx->insn;\n")
52
if (hex_common.is_hvx_insn(tag)):
53
if hex_common.has_hvx_helper(tag):
@@ -58,7 +64,8 @@ def gen_analyze_func(f, tag, regs, imms):
64
for regno, register in enumerate(regs):
65
reg_type, reg_id = register
66
reg = hex_common.get_register(tag, reg_type, reg_id)
61
- reg.decl_reg_num(f, regno)
67
+ if reg.is_read() or reg.is_written():
68
+ reg.decl_reg_num(f, regno)
69
70
## Analyze the register reads
71
for regno, register in enumerate(regs):
@@ -78,6 +85,9 @@ def gen_analyze_func(f, tag, regs, imms):
85
86
f.write(" mark_implicit_writes(ctx);\n")
87
88
+ if hex_common.is_sysemu_tag(tag):
89
+ f.write("#endif /* !CONFIG_USER_ONLY */\n")
90
+
91
f.write("}\n\n")
92
93
target/hexagon/hex_common.py
+152
@@ -33,6 +33,41 @@ tags = [] # list of all tags
33
overrides = {} # tags with helper overrides
34
idef_parser_enabled = {} # tags enabled for idef-parser
35
36
+
37
+def is_sysemu_tag(tag):
38
+ return bool(attribdict[tag] & {"A_PRIV", "A_GUEST"})
39
+
40
+
41
+def tag_ignore(tag):
42
+ tag_skips = (
43
+ "Y6_diag",
44
+ "Y6_diag0",
45
+ "Y6_diag1",
46
+ )
47
+ attr_skips = {
48
+ "A_FAKEINSN",
49
+ "A_MAPPING",
50
+ "A_CONDMAPPING",
51
+ }
52
+ return tag in tag_skips or attribdict[tag] & attr_skips
53
+
54
+
55
+def get_sys_tags():
56
+ return sorted(
57
+ tag for tag in frozenset(tags) if is_sysemu_tag(tag)
58
+ )
59
+
60
+
61
+def get_user_tags():
62
+ return sorted(
63
+ tag for tag in frozenset(tags) if not is_sysemu_tag(tag)
64
+ )
65
+
66
+
67
+def get_all_tags():
68
+ return get_user_tags() + get_sys_tags()
69
+
70
+
71
# We should do this as a hash for performance,
72
# but to keep order let's keep it as a list.
73
def uniquify(seq):
@@ -369,12 +404,16 @@ class Single(Scalar):
404
return "s32"
405
def helper_arg_type(self):
406
return "int32_t"
407
+ def is_pair(self):
408
+ return False
409
410
class Pair(Scalar):
411
def helper_proto_type(self):
412
return "s64"
413
def helper_arg_type(self):
414
return "int64_t"
415
+ def is_pair(self):
416
+ return True
417
418
class Hvx:
419
def is_scalar_reg(self):
@@ -1010,6 +1049,109 @@ class QRegReadWrite(Register, Hvx, ReadWrite):
1049
ctx_log_qreg_write(ctx, {self.reg_num}, insn_has_hvx_helper);
1050
"""))
1051
1052
+class GuestRegister(Register):
1053
+ pass
1054
+
1055
+class GuestDest(GuestRegister, Single, Dest):
1056
+ def decl_tcg(self, f, tag, regno):
1057
+ self.decl_reg_num(f, regno)
1058
+ f.write(code_fmt(f"""\
1059
+ TCGv_i32 {self.reg_tcg()} = tcg_temp_new_i32();
1060
+ """))
1061
+ def gen_write(self, f, tag):
1062
+ f.write(code_fmt(f"""\
1063
+ gen_log_greg_write(ctx, {self.reg_num}, {self.reg_tcg()});
1064
+ """))
1065
+ def analyze_write(self, f, tag, regno):
1066
+ f.write(code_fmt(f"""\
1067
+ ctx_log_greg_write(ctx, {self.reg_num});
1068
+ """))
1069
+
1070
+class GuestSource(GuestRegister, Single, OldSource):
1071
+ def decl_tcg(self, f, tag, regno):
1072
+ self.decl_reg_num(f, regno)
1073
+ f.write(code_fmt(f"""\
1074
+ TCGv_i32 {self.reg_tcg()} = tcg_temp_new_i32();
1075
+ gen_read_greg({self.reg_tcg()}, {self.reg_num});
1076
+ """))
1077
+ def analyze_read(self, f, regno):
1078
+ pass
1079
+
1080
+class GuestPairDest(GuestRegister, Pair, Dest):
1081
+ def decl_tcg(self, f, tag, regno):
1082
+ self.decl_reg_num(f, regno)
1083
+ f.write(code_fmt(f"""\
1084
+ TCGv_i64 {self.reg_tcg()} = tcg_temp_new_i64();
1085
+ """))
1086
+ def gen_write(self, f, tag):
1087
+ f.write(code_fmt(f"""\
1088
+ gen_log_greg_write_pair(ctx, {self.reg_num}, {self.reg_tcg()});
1089
+ """))
1090
+ def analyze_write(self, f, tag, regno):
1091
+ f.write(code_fmt(f"""\
1092
+ ctx_log_greg_write_pair(ctx, {self.reg_num});
1093
+ """))
1094
+
1095
+class GuestPairSource(GuestRegister, Pair, OldSource):
1096
+ def decl_tcg(self, f, tag, regno):
1097
+ self.decl_reg_num(f, regno)
1098
+ f.write(code_fmt(f"""\
1099
+ TCGv_i64 {self.reg_tcg()} = tcg_temp_new_i64();
1100
+ gen_read_greg_pair({self.reg_tcg()}, {self.reg_num});
1101
+ """))
1102
+ def analyze_read(self, f, regno):
1103
+ pass
1104
+
1105
+class SystemDest(Register, Single, Dest):
1106
+ def decl_tcg(self, f, tag, regno):
1107
+ self.decl_reg_num(f, regno)
1108
+ f.write(code_fmt(f"""\
1109
+ TCGv_i32 {self.reg_tcg()} = tcg_temp_new_i32();
1110
+ """))
1111
+ def gen_write(self, f, tag):
1112
+ f.write(code_fmt(f"""\
1113
+ gen_log_sreg_write(ctx, {self.reg_num}, {self.reg_tcg()});
1114
+ """))
1115
+ def analyze_write(self, f, tag, regno):
1116
+ f.write(code_fmt(f"""\
1117
+ ctx_log_sreg_write(ctx, {self.reg_num});
1118
+ """))
1119
+
1120
+class SystemSource(Register, Single, OldSource):
1121
+ def decl_tcg(self, f, tag, regno):
1122
+ self.decl_reg_num(f, regno)
1123
+ f.write(code_fmt(f"""\
1124
+ TCGv_i32 {self.reg_tcg()} = tcg_temp_new_i32();
1125
+ gen_read_sreg({self.reg_tcg()}, {self.reg_num});
1126
+ """))
1127
+ def analyze_read(self, f, regno):
1128
+ pass
1129
+
1130
+class SystemPairDest(Register, Pair, Dest):
1131
+ def decl_tcg(self, f, tag, regno):
1132
+ self.decl_reg_num(f, regno)
1133
+ f.write(code_fmt(f"""\
1134
+ TCGv_i64 {self.reg_tcg()} = tcg_temp_new_i64();
1135
+ """))
1136
+ def gen_write(self, f, tag):
1137
+ f.write(code_fmt(f"""\
1138
+ gen_log_sreg_write_pair(ctx, {self.reg_num}, {self.reg_tcg()});
1139
+ """))
1140
+ def analyze_write(self, f, tag, regno):
1141
+ f.write(code_fmt(f"""\
1142
+ ctx_log_sreg_write_pair(ctx, {self.reg_num});
1143
+ """))
1144
+
1145
+class SystemPairSource(Register, Pair, OldSource):
1146
+ def decl_tcg(self, f, tag, regno):
1147
+ self.decl_reg_num(f, regno)
1148
+ f.write(code_fmt(f"""\
1149
+ TCGv_i64 {self.reg_tcg()} = tcg_temp_new_i64();
1150
+ gen_read_sreg_pair({self.reg_tcg()}, {self.reg_num});
1151
+ """))
1152
+ def analyze_read(self, f, regno):
1153
+ pass
1154
+
1155
def init_registers():
1156
regs = {
1157
GprDest("R", "d"),
@@ -1056,6 +1198,16 @@ def init_registers():
1198
QRegSource("Q", "u"),
1199
QRegSource("Q", "v"),
1200
QRegReadWrite("Q", "x"),
1201
+
1202
+ # system regs
1203
+ GuestDest("G", "d"),
1204
+ GuestSource("G", "s"),
1205
+ GuestPairDest("G", "dd"),
1206
+ GuestPairSource("G", "ss"),
1207
+ SystemDest("S", "d"),
1208
+ SystemSource("S", "s"),
1209
+ SystemPairDest("S", "dd"),
1210
+ SystemPairSource("S", "ss"),
1211
}
1212
for reg in regs:
1213
registers[f"{reg.regtype}{reg.regid}"] = reg