Commit 44fd71bb7e for qemu.org
commit 44fd71bb7ed9c85c5049cb55643e4e0accdd0208
Author: Richard Henderson <richard.henderson@linaro.org>
Date: Fri Aug 28 08:18:47 2026 -0700
tcg/x86_64: Introduce TCG_REG_NONE
Rather than hard-code -1, or compare < 0, use something
more descriptive. This also allows more use of TCGReg.
Reviewed-by: Matt Turner <mattst88@gmail.com>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
diff --git a/tcg/x86_64/tcg-target.c.inc b/tcg/x86_64/tcg-target.c.inc
index 46efee87e6..d85e95a32b 100644
--- a/tcg/x86_64/tcg-target.c.inc
+++ b/tcg/x86_64/tcg-target.c.inc
@@ -210,7 +210,8 @@ static bool tcg_target_const_match(int64_t val, int ct,
return 0;
}
-# define LOWREGMASK(x) ((x) & 7)
+#define LOWREGMASK(x) ((x) & 7)
+#define REGOR0(x) ((x) == TCG_REG_NONE ? 0 : (x))
#define P_EXT 0x100 /* 0x0f opcode prefix */
#define P_EXT38 0x200 /* 0x0f 0x38 opcode prefix */
@@ -525,7 +526,7 @@ static const uint8_t tcg_cond_to_jcc[] = {
[TCG_COND_TSTNE] = JCC_JNE,
};
-static void tcg_out_opc(TCGContext *s, int opc, int r, int rm, int x)
+static void tcg_out_opc(TCGContext *s, int opc, TCGReg r, TCGReg rm, TCGReg x)
{
int rex;
@@ -573,14 +574,14 @@ static void tcg_out_opc(TCGContext *s, int opc, int r, int rm, int x)
tcg_out8(s, opc);
}
-static void tcg_out_modrm(TCGContext *s, int opc, int r, int rm)
+static void tcg_out_modrm(TCGContext *s, int opc, TCGReg r, TCGReg rm)
{
tcg_out_opc(s, opc, r, rm, 0);
tcg_out8(s, 0xc0 | (LOWREGMASK(r) << 3) | LOWREGMASK(rm));
}
-static void tcg_out_vex_opc(TCGContext *s, int opc, int r, int v,
- int rm, int index)
+static void tcg_out_vex_opc(TCGContext *s, int opc, TCGReg r, TCGReg v,
+ TCGReg rm, TCGReg index)
{
int tmp;
@@ -631,8 +632,8 @@ static void tcg_out_vex_opc(TCGContext *s, int opc, int r, int v,
tcg_out8(s, opc);
}
-static void tcg_out_evex_opc(TCGContext *s, int opc, int r, int v,
- int rm, int index, int aaa, bool z)
+static void tcg_out_evex_opc(TCGContext *s, int opc, TCGReg r, TCGReg v,
+ TCGReg rm, TCGReg index, int aaa, bool z)
{
/* The entire 4-byte evex prefix; with R' and V' set. */
uint32_t p = 0x08041062;
@@ -677,7 +678,8 @@ static void tcg_out_evex_opc(TCGContext *s, int opc, int r, int v,
tcg_out8(s, opc);
}
-static void tcg_out_vex_modrm(TCGContext *s, int opc, int r, int v, int rm)
+static void tcg_out_vex_modrm(TCGContext *s, int opc, TCGReg r,
+ TCGReg v, TCGReg rm)
{
if (opc & P_EVEX) {
tcg_out_evex_opc(s, opc, r, v, rm, 0, 0, false);
@@ -688,7 +690,7 @@ static void tcg_out_vex_modrm(TCGContext *s, int opc, int r, int v, int rm)
}
static void tcg_out_vex_modrm_type(TCGContext *s, int opc,
- int r, int v, int rm, TCGType type)
+ TCGReg r, TCGReg v, TCGReg rm, TCGType type)
{
if (type == TCG_TYPE_V256) {
opc |= P_VEXL;
@@ -696,8 +698,8 @@ static void tcg_out_vex_modrm_type(TCGContext *s, int opc,
tcg_out_vex_modrm(s, opc, r, v, rm);
}
-static void tcg_out_evex_modrm_type(TCGContext *s, int opc, int r, int v,
- int rm, int aaa, bool z, TCGType type)
+static void tcg_out_evex_modrm_type(TCGContext *s, int opc, TCGReg r, TCGReg v,
+ TCGReg rm, int aaa, bool z, TCGType type)
{
if (type == TCG_TYPE_V256) {
opc |= P_VEXL;
@@ -711,12 +713,12 @@ static void tcg_out_evex_modrm_type(TCGContext *s, int opc, int r, int v,
mode for absolute addresses, ~RM is the size of the immediate operand
that will follow the instruction. */
-static void tcg_out_sib_offset(TCGContext *s, int r, int rm, int index,
+static void tcg_out_sib_offset(TCGContext *s, TCGReg r, TCGReg rm, TCGReg index,
int shift, intptr_t offset)
{
int mod, len;
- if (index < 0 && rm < 0) {
+ if (index == TCG_REG_NONE && rm == TCG_REG_NONE) {
/*
* Try for a rip-relative addressing mode. This has replaced
* the 32-bit-mode absolute addressing encoding.
@@ -747,7 +749,7 @@ static void tcg_out_sib_offset(TCGContext *s, int r, int rm, int index,
/* Find the length of the immediate addend. Note that the encoding
that would be used for (%ebp) indicates absolute addressing. */
- if (rm < 0) {
+ if (rm == TCG_REG_NONE) {
mod = 0, len = 4, rm = 5;
} else if (offset == 0 && LOWREGMASK(rm) != TCG_REG_EBP) {
mod = 0, len = 0;
@@ -759,7 +761,7 @@ static void tcg_out_sib_offset(TCGContext *s, int r, int rm, int index,
/* Use a single byte MODRM format if possible. Note that the encoding
that would be used for %esp is the escape to the two byte form. */
- if (index < 0 && LOWREGMASK(rm) != TCG_REG_ESP) {
+ if (index == TCG_REG_NONE && LOWREGMASK(rm) != TCG_REG_ESP) {
/* Single byte MODRM format. */
tcg_out8(s, mod | (LOWREGMASK(r) << 3) | LOWREGMASK(rm));
} else {
@@ -768,7 +770,7 @@ static void tcg_out_sib_offset(TCGContext *s, int r, int rm, int index,
/* Note that the encoding that would place %esp into the index
field indicates no index register. In 64-bit mode, the REX.X
bit counts, so %r12 can be used as the index. */
- if (index < 0) {
+ if (index == TCG_REG_NONE) {
index = 4;
} else {
tcg_debug_assert(index != TCG_REG_ESP);
@@ -785,32 +787,34 @@ static void tcg_out_sib_offset(TCGContext *s, int r, int rm, int index,
}
}
-static void tcg_out_modrm_sib_offset(TCGContext *s, int opc, int r, int rm,
- int index, int shift, intptr_t offset)
+static void tcg_out_modrm_sib_offset(TCGContext *s, int opc, TCGReg r,
+ TCGReg rm, TCGReg index,
+ int shift, intptr_t offset)
{
- tcg_out_opc(s, opc, r, rm < 0 ? 0 : rm, index < 0 ? 0 : index);
+ tcg_out_opc(s, opc, r, REGOR0(rm), REGOR0(index));
tcg_out_sib_offset(s, r, rm, index, shift, offset);
}
-static void tcg_out_vex_modrm_sib_offset(TCGContext *s, int opc, int r, int v,
- int rm, int index, int shift,
+static void tcg_out_vex_modrm_sib_offset(TCGContext *s, int opc,
+ TCGReg r, TCGReg v, TCGReg rm,
+ TCGReg index, int shift,
intptr_t offset)
{
- tcg_out_vex_opc(s, opc, r, v, rm < 0 ? 0 : rm, index < 0 ? 0 : index);
+ tcg_out_vex_opc(s, opc, r, v, REGOR0(rm), REGOR0(index));
tcg_out_sib_offset(s, r, rm, index, shift, offset);
}
/* A simplification of the above with no index or shift. */
-static inline void tcg_out_modrm_offset(TCGContext *s, int opc, int r,
- int rm, intptr_t offset)
+static void tcg_out_modrm_offset(TCGContext *s, int opc, TCGReg r,
+ TCGReg rm, intptr_t offset)
{
- tcg_out_modrm_sib_offset(s, opc, r, rm, -1, 0, offset);
+ tcg_out_modrm_sib_offset(s, opc, r, rm, TCG_REG_NONE, 0, offset);
}
-static inline void tcg_out_vex_modrm_offset(TCGContext *s, int opc, int r,
- int v, int rm, intptr_t offset)
+static void tcg_out_vex_modrm_offset(TCGContext *s, int opc, TCGReg r,
+ TCGReg v, TCGReg rm, intptr_t offset)
{
- tcg_out_vex_modrm_sib_offset(s, opc, r, v, rm, -1, 0, offset);
+ tcg_out_vex_modrm_sib_offset(s, opc, r, v, rm, TCG_REG_NONE, 0, offset);
}
/* Output an opcode with an expected reference to the constant pool. */
@@ -1890,7 +1894,7 @@ static bool tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
#ifdef CONFIG_USER_ONLY
static HostAddress x86_guest_base = {
- .index = -1
+ .index = TCG_REG_NONE
};
#if defined(__linux__)
@@ -2174,7 +2178,7 @@ static void tgen_qemu_ld(TCGContext *s, TCGType type, TCGReg data,
HostAddress h;
ldst = prepare_host_addr(s, &h, addr, oi, true);
- tcg_out_qemu_ld_direct(s, data, -1, h, type, get_memop(oi));
+ tcg_out_qemu_ld_direct(s, data, TCG_REG_NONE, h, type, get_memop(oi));
if (ldst) {
ldst->type = type;
@@ -2312,7 +2316,7 @@ static void tgen_qemu_st(TCGContext *s, TCGType type, TCGReg data,
HostAddress h;
ldst = prepare_host_addr(s, &h, addr, oi, false);
- tcg_out_qemu_st_direct(s, data, -1, h, get_memop(oi));
+ tcg_out_qemu_st_direct(s, data, TCG_REG_NONE, h, get_memop(oi));
if (ldst) {
ldst->type = type;
diff --git a/tcg/x86_64/tcg-target.h b/tcg/x86_64/tcg-target.h
index 7ebae56a7d..7109722f24 100644
--- a/tcg/x86_64/tcg-target.h
+++ b/tcg/x86_64/tcg-target.h
@@ -31,6 +31,7 @@
#define MAX_CODE_GEN_BUFFER_SIZE (2 * GiB)
typedef enum {
+ TCG_REG_NONE = -1,
TCG_REG_EAX = 0,
TCG_REG_ECX,
TCG_REG_EDX,