target/i386: decode address before going back to translate.c

There are now relatively few unconverted opcodes in translate.c (there
are 13 of them including 8 for x87), and all of them have the same
format with a mod/rm byte and no immediate.  A good next step is
to remove the early bail out to disas_insn_x87/disas_insn_old,
instead giving these legacy translator functions the same prototype
as the other gen_* functions.

To do this, the X86DecodeInsn can be passed down to the places that
used to fetch address bytes from the instruction stream.  To make
sure that everything is done cleanly, the CPUX86State* argument is
removed.

As part of the unification, the gen_lea_modrm() name is now free,
so rename gen_load_ea() to gen_lea_modrm().  This is as good a name
and it makes the changes to translate.c easier to review.

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
Paolo Bonzini
2024-10-17 19:41:29 +02:00
parent 10eae89937
commit a2e2c78d2a
4 changed files with 103 additions and 118 deletions
+28 -25
View File
@@ -1092,6 +1092,8 @@ static void decode_MOV_CR_DR(DisasContext *s, CPUX86State *env, X86OpEntry *entr
}
static const X86OpEntry opcodes_0F[256] = {
[0x00] = X86_OP_ENTRY1(multi0F, nop,v, nolea), /* unconverted */
[0x01] = X86_OP_ENTRY1(multi0F, nop,v, nolea), /* unconverted */
[0x02] = X86_OP_ENTRYwr(LAR, G,v, E,w, chk(prot)),
[0x03] = X86_OP_ENTRYwr(LSL, G,v, E,w, chk(prot)),
[0x05] = X86_OP_ENTRY0(SYSCALL, chk(o64_intel)),
@@ -1201,6 +1203,7 @@ static const X86OpEntry opcodes_0F[256] = {
[0xc4] = X86_OP_ENTRY4(PINSRW, V,dq,H,dq,E,w, vex5 mmx p_00_66),
[0xc5] = X86_OP_ENTRY3(PEXTRW, G,d, U,dq,I,b, vex5 mmx p_00_66),
[0xc6] = X86_OP_ENTRY4(VSHUF, V,x, H,x, W,x, vex4 p_00_66),
[0xc7] = X86_OP_ENTRY1(multi0F, nop,v, nolea), /* unconverted */
[0xd0] = X86_OP_ENTRY3(VADDSUB, V,x, H,x, W,x, vex2 cpuid(SSE3) p_66_f2),
[0xd1] = X86_OP_ENTRY3(PSRLW_r, V,x, H,x, W,x, vex4 mmx avx2_256 p_00_66),
@@ -1243,6 +1246,8 @@ static const X86OpEntry opcodes_0F[256] = {
[0x18] = X86_OP_ENTRY1(NOP, nop,v), /* prefetch/reserved NOP */
[0x19] = X86_OP_ENTRY1(NOP, nop,v), /* reserved NOP */
[0x1a] = X86_OP_ENTRY1(multi0F, nop,v, nolea), /* unconverted MPX */
[0x1b] = X86_OP_ENTRY1(multi0F, nop,v, nolea), /* unconverted MPX */
[0x1c] = X86_OP_ENTRY1(NOP, nop,v), /* reserved NOP */
[0x1d] = X86_OP_ENTRY1(NOP, nop,v), /* reserved NOP */
[0x1e] = X86_OP_ENTRY1(NOP, nop,v), /* reserved NOP */
@@ -1780,6 +1785,19 @@ static const X86OpEntry opcodes_root[256] = {
[0xCE] = X86_OP_ENTRY0(INTO),
[0xCF] = X86_OP_ENTRY0(IRET, chk(vm86_iopl) svm(IRET)),
/*
* x87 is nolea because it needs the address without segment base,
* in order to store it in fdp.
*/
[0xD8] = X86_OP_ENTRY1(x87, nop,v, nolea),
[0xD9] = X86_OP_ENTRY1(x87, nop,v, nolea),
[0xDA] = X86_OP_ENTRY1(x87, nop,v, nolea),
[0xDB] = X86_OP_ENTRY1(x87, nop,v, nolea),
[0xDC] = X86_OP_ENTRY1(x87, nop,v, nolea),
[0xDD] = X86_OP_ENTRY1(x87, nop,v, nolea),
[0xDE] = X86_OP_ENTRY1(x87, nop,v, nolea),
[0xDF] = X86_OP_ENTRY1(x87, nop,v, nolea),
[0xE8] = X86_OP_ENTRYr(CALL, J,z_f64),
[0xE9] = X86_OP_ENTRYr(JMP, J,z_f64),
[0xEA] = X86_OP_ENTRYrr(JMPF, I_unsigned,p, I_unsigned,w, chk(i64)),
@@ -2612,30 +2630,6 @@ static void disas_insn(DisasContext *s, CPUState *cpu)
}
}
/* Go back to old decoder for unconverted opcodes. */
if (!(s->prefix & PREFIX_VEX)) {
if ((b & ~7) == 0xd8) {
if (!disas_insn_x87(s, cpu, b)) {
goto unknown_op;
}
return;
}
if (b == 0x0f) {
b = x86_ldub_code(env, s);
switch (b) {
case 0x00 ... 0x01: /* mostly privileged instructions */
case 0x1a ... 0x1b: /* MPX */
case 0xc7: /* grp9 */
disas_insn_old(s, cpu, b + 0x100);
return;
default:
decode_func = do_decode_0F;
break;
}
}
}
memset(&decode, 0, sizeof(decode));
decode.cc_op = -1;
decode.b = b;
@@ -2732,6 +2726,15 @@ static void disas_insn(DisasContext *s, CPUState *cpu)
break;
}
/*
* hack for old decoder: 0F C7 has both instructions that accept LOCK
* and instructions that don't, but also needs X86_SPECIAL_NoLoadEA.
* Keep this here until CMPXCHG8B/CMPXCHG16B is separated from the
* other unconverted opcodes.
*/
if (decode.e.gen == gen_multi0F) {
accept_lock = true;
}
if ((s->prefix & PREFIX_LOCK) && !accept_lock) {
goto illegal_op;
}
@@ -2779,7 +2782,7 @@ static void disas_insn(DisasContext *s, CPUState *cpu)
if (decode.e.special != X86_SPECIAL_NoLoadEA &&
(decode.op[0].has_ea || decode.op[1].has_ea || decode.op[2].has_ea)) {
gen_load_ea(s, &decode);
gen_lea_modrm(s, &decode);
}
if (s->prefix & PREFIX_LOCK) {
assert(decode.op[0].has_ea && !decode.op[2].has_ea);
+12 -2
View File
@@ -264,12 +264,13 @@ typedef enum X86VEXSpecial {
typedef struct X86OpEntry X86OpEntry;
typedef struct X86DecodedInsn X86DecodedInsn;
struct DisasContext;
/* Decode function for multibyte opcodes. */
typedef void (*X86DecodeFunc)(DisasContext *s, CPUX86State *env, X86OpEntry *entry, uint8_t *b);
typedef void (*X86DecodeFunc)(struct DisasContext *s, CPUX86State *env, X86OpEntry *entry, uint8_t *b);
/* Code generation function. */
typedef void (*X86GenFunc)(DisasContext *s, X86DecodedInsn *decode);
typedef void (*X86GenFunc)(struct DisasContext *s, X86DecodedInsn *decode);
struct X86OpEntry {
/* Based on the is_decode flags. */
@@ -316,6 +317,14 @@ typedef struct X86DecodedOp {
};
} X86DecodedOp;
typedef struct AddressParts {
int def_seg;
int base;
int index;
int scale;
target_long disp;
} AddressParts;
struct X86DecodedInsn {
X86OpEntry e;
X86DecodedOp op[3];
@@ -333,3 +342,4 @@ struct X86DecodedInsn {
uint8_t b;
};
static void gen_lea_modrm(struct DisasContext *s, X86DecodedInsn *decode);
+1 -1
View File
@@ -78,7 +78,7 @@ static void gen_NM_exception(DisasContext *s)
gen_exception(s, EXCP07_PREX);
}
static void gen_load_ea(DisasContext *s, X86DecodedInsn *decode)
static void gen_lea_modrm(DisasContext *s, X86DecodedInsn *decode)
{
AddressParts *mem = &decode->mem;
TCGv ea;
File diff suppressed because it is too large Load Diff