From: Peter Johnson Date: Wed, 4 Oct 2006 04:38:43 +0000 (-0000) Subject: Follow-up to #80 and #81: "xchg ax, ax" can use the short 0x90 form as X-Git-Tag: v0.6.0~140 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=b98e1cb5985820f371daa08c5014f9f7be557380;p=yasm Follow-up to #80 and #81: "xchg ax, ax" can use the short 0x90 form as 16-bit operations don't clear the high bits of the 64-bit register, so this is effectively a NOP as well. While I'm still looking at this, make "xchg rax, rax" not output a REX prefix. I thought about being extra-clever and have "xchg ax, ax" not output an operand-size prefix, but thought better of it: if the user says "ax" they're probably going to expect the prefix to be there. Left in as a comment for future readers of the code. svn path=/trunk/yasm/; revision=1639 --- diff --git a/modules/arch/x86/tests/xchg64.hex b/modules/arch/x86/tests/xchg64.hex index b1965407..f7149e3d 100644 --- a/modules/arch/x86/tests/xchg64.hex +++ b/modules/arch/x86/tests/xchg64.hex @@ -1,6 +1,5 @@ 66 -87 -c0 +90 66 93 66 @@ -9,7 +8,6 @@ c0 c0 93 93 -48 90 48 93 diff --git a/modules/arch/x86/x86id.c b/modules/arch/x86/x86id.c index 94677beb..d406c937 100644 --- a/modules/arch/x86/x86id.c +++ b/modules/arch/x86/x86id.c @@ -732,8 +732,15 @@ static const x86_insn_info xchg_insn[] = { {OPT_RM|OPS_8|OPS_Relaxed|OPA_EA, OPT_Reg|OPS_8|OPA_Spare, 0} }, { CPU_Any, MOD_GasSufB, 0, 0, 0, 1, {0x86, 0, 0}, 0, 2, {OPT_Reg|OPS_8|OPA_Spare, OPT_RM|OPS_8|OPS_Relaxed|OPA_EA, 0} }, - { CPU_Any|CPU_64, MOD_GasSufW, 16, 0, 0, 1, {0x87, 0, 0}, 0, 2, - {OPT_Areg|OPS_16|OPA_EA, OPT_Areg|OPS_16|OPA_Spare, 0} }, + /* We could be extra-efficient in the 64-bit mode case here. + * XCHG AX, AX in 64-bit mode is a NOP, as it doesn't clear the + * high 48 bits of RAX. Thus we don't need the operand-size prefix. + * But this feels too clever, and probably not what the user really + * expects in the generated code, so we don't do it. + * + * { CPU_Any|CPU_64, MOD_GasSufW, 0, 0, 0, 1, {0x90, 0, 0}, 0, 2, + * {OPT_Areg|OPS_16|OPA_None, OPT_Areg|OPS_16|OPA_Op0Add, 0} }, + */ { CPU_Any, MOD_GasSufW, 16, 0, 0, 1, {0x90, 0, 0}, 0, 2, {OPT_Areg|OPS_16|OPA_None, OPT_Reg|OPS_16|OPA_Op0Add, 0} }, { CPU_Any, MOD_GasSufW, 16, 0, 0, 1, {0x90, 0, 0}, 0, 2, @@ -742,6 +749,11 @@ static const x86_insn_info xchg_insn[] = { {OPT_RM|OPS_16|OPS_Relaxed|OPA_EA, OPT_Reg|OPS_16|OPA_Spare, 0} }, { CPU_Any, MOD_GasSufW, 16, 0, 0, 1, {0x87, 0, 0}, 0, 2, {OPT_Reg|OPS_16|OPA_Spare, OPT_RM|OPS_16|OPS_Relaxed|OPA_EA, 0} }, + /* Be careful with XCHG EAX, EAX in 64-bit mode. This needs to use + * the long form rather than the NOP form, as the long form clears + * the high 32 bits of RAX. This makes all 32-bit forms in 64-bit + * mode have consistent operation. + */ { CPU_386|CPU_64, MOD_GasSufL, 32, 0, 0, 1, {0x87, 0, 0}, 0, 2, {OPT_Areg|OPS_32|OPA_EA, OPT_Areg|OPS_32|OPA_Spare, 0} }, { CPU_386, MOD_GasSufL, 32, 0, 0, 1, {0x90, 0, 0}, 0, 2, @@ -752,6 +764,11 @@ static const x86_insn_info xchg_insn[] = { {OPT_RM|OPS_32|OPS_Relaxed|OPA_EA, OPT_Reg|OPS_32|OPA_Spare, 0} }, { CPU_386, MOD_GasSufL, 32, 0, 0, 1, {0x87, 0, 0}, 0, 2, {OPT_Reg|OPS_32|OPA_Spare, OPT_RM|OPS_32|OPS_Relaxed|OPA_EA, 0} }, + /* Be efficient with XCHG RAX, RAX. + * This is a NOP and thus doesn't need the REX prefix. + */ + { CPU_Hammer|CPU_64, MOD_GasSufQ, 0, 0, 0, 1, {0x90, 0, 0}, 0, 2, + {OPT_Areg|OPS_64|OPA_None, OPT_Areg|OPS_64|OPA_Op0Add, 0} }, { CPU_Hammer|CPU_64, MOD_GasSufQ, 64, 0, 0, 1, {0x90, 0, 0}, 0, 2, {OPT_Areg|OPS_64|OPA_None, OPT_Reg|OPS_64|OPA_Op0Add, 0} }, { CPU_Hammer|CPU_64, MOD_GasSufQ, 64, 0, 0, 1, {0x90, 0, 0}, 0, 2,