tcg/i386: Add tcg_out_vex_modrm
Prepare for emitting BMI insns which require VEX encoding. Reviewed-by: Paolo Bonzini <pbonzini@redhat.com> Reviewed-by: Aurelien Jarno <aurelien@aurel32.net> Signed-off-by: Richard Henderson <rth@twiddle.net>
This commit is contained in:
parent
a1b29c9ae0
commit
ecc7e84327
|
@ -402,9 +402,9 @@ static void tcg_out_opc(TCGContext *s, int opc, int r, int rm, int x)
|
||||||
|
|
||||||
rex = 0;
|
rex = 0;
|
||||||
rex |= (opc & P_REXW) ? 0x8 : 0x0; /* REX.W */
|
rex |= (opc & P_REXW) ? 0x8 : 0x0; /* REX.W */
|
||||||
rex |= (r & 8) >> 1; /* REX.R */
|
rex |= (r & 8) >> 1; /* REX.R */
|
||||||
rex |= (x & 8) >> 2; /* REX.X */
|
rex |= (x & 8) >> 2; /* REX.X */
|
||||||
rex |= (rm & 8) >> 3; /* REX.B */
|
rex |= (rm & 8) >> 3; /* REX.B */
|
||||||
|
|
||||||
/* P_REXB_{R,RM} indicates that the given register is the low byte.
|
/* P_REXB_{R,RM} indicates that the given register is the low byte.
|
||||||
For %[abcd]l we need no REX prefix, but for %{si,di,bp,sp}l we do,
|
For %[abcd]l we need no REX prefix, but for %{si,di,bp,sp}l we do,
|
||||||
|
@ -453,6 +453,41 @@ static void tcg_out_modrm(TCGContext *s, int opc, int r, int rm)
|
||||||
tcg_out8(s, 0xc0 | (LOWREGMASK(r) << 3) | LOWREGMASK(rm));
|
tcg_out8(s, 0xc0 | (LOWREGMASK(r) << 3) | LOWREGMASK(rm));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void tcg_out_vex_modrm(TCGContext *s, int opc, int r, int v, int rm)
|
||||||
|
{
|
||||||
|
int tmp;
|
||||||
|
|
||||||
|
if ((opc & (P_REXW | P_EXT | P_EXT38)) || (rm & 8)) {
|
||||||
|
/* Three byte VEX prefix. */
|
||||||
|
tcg_out8(s, 0xc4);
|
||||||
|
|
||||||
|
/* VEX.m-mmmm */
|
||||||
|
if (opc & P_EXT38) {
|
||||||
|
tmp = 2;
|
||||||
|
} else if (opc & P_EXT) {
|
||||||
|
tmp = 1;
|
||||||
|
} else {
|
||||||
|
tcg_abort();
|
||||||
|
}
|
||||||
|
tmp |= 0x40; /* VEX.X */
|
||||||
|
tmp |= (r & 8 ? 0 : 0x80); /* VEX.R */
|
||||||
|
tmp |= (rm & 8 ? 0 : 0x20); /* VEX.B */
|
||||||
|
tcg_out8(s, tmp);
|
||||||
|
|
||||||
|
tmp = (opc & P_REXW ? 0x80 : 0); /* VEX.W */
|
||||||
|
} else {
|
||||||
|
/* Two byte VEX prefix. */
|
||||||
|
tcg_out8(s, 0xc5);
|
||||||
|
|
||||||
|
tmp = (r & 8 ? 0 : 0x80); /* VEX.R */
|
||||||
|
}
|
||||||
|
tmp |= (opc & P_DATA16 ? 1 : 0); /* VEX.pp */
|
||||||
|
tmp |= (~v & 15) << 3; /* VEX.vvvv */
|
||||||
|
tcg_out8(s, tmp);
|
||||||
|
tcg_out8(s, opc);
|
||||||
|
tcg_out8(s, 0xc0 | (LOWREGMASK(r) << 3) | LOWREGMASK(rm));
|
||||||
|
}
|
||||||
|
|
||||||
/* Output an opcode with a full "rm + (index<<shift) + offset" address mode.
|
/* Output an opcode with a full "rm + (index<<shift) + offset" address mode.
|
||||||
We handle either RM and INDEX missing with a negative value. In 64-bit
|
We handle either RM and INDEX missing with a negative value. In 64-bit
|
||||||
mode for absolute addresses, ~RM is the size of the immediate operand
|
mode for absolute addresses, ~RM is the size of the immediate operand
|
||||||
|
|
Loading…
Reference in New Issue