[nasm:nasm-2.16.xx] XCHG: adjust lock prefix warning, add specific warning for LOCK XCHG

nasm-bot for H. Peter Anvin hpa at zytor.com
Thu Oct 12 14:54:04 PDT 2023


Commit-ID:  e993b75aa6dc59fbd083ddd7c2b97751fd7bacfc
Gitweb:     http://repo.or.cz/w/nasm.git?a=commitdiff;h=e993b75aa6dc59fbd083ddd7c2b97751fd7bacfc
Author:     H. Peter Anvin <hpa at zytor.com>
AuthorDate: Thu, 12 Oct 2023 14:49:53 -0700
Committer:  H. Peter Anvin <hpa at zytor.com>
CommitDate: Thu, 12 Oct 2023 14:53:40 -0700

XCHG: adjust lock prefix warning, add specific warning for LOCK XCHG

"LOCK XCHG reg,mem" would issue a warning for being unlockable, which
is incorrect. In this case the RM encoding is simply an alias for the
MR encoding. Add a "LOCK1" bit to deal with that.

However, XCHG is *always* locked, so create a new warning to
explicitly flag a user-specified LOCK XCHG; default off.

Consider optimizing that prefix away in the future, but for now, let's
stick to the user-requested code sequence.

Signed-off-by: H. Peter Anvin <hpa at zytor.com>


---
 asm/assemble.c | 29 +++++++++++++++++++++--------
 x86/iflags.ph  |  1 +
 x86/insns.dat  | 20 ++++++++------------
 3 files changed, 30 insertions(+), 20 deletions(-)

diff --git a/asm/assemble.c b/asm/assemble.c
index dbea82cc..008b483f 100644
--- a/asm/assemble.c
+++ b/asm/assemble.c
@@ -1843,14 +1843,27 @@ static int64_t calcsize(int32_t segment, int64_t offset, int bits,
         }
     }
 
-    if (has_prefix(ins, PPS_LOCK, P_LOCK) && lockcheck &&
-        (!itemp_has(temp,IF_LOCK) || !is_class(MEMORY, ins->oprs[0].type))) {
-        /*!
-         *!prefix-lock [on] LOCK prefix on unlockable instructions
-         *!=lock
-         *!  warns about \c{LOCK} prefixes on unlockable instructions.
-         */
-        nasm_warn(WARN_PREFIX_LOCK|ERR_PASS2 , "instruction is not lockable");
+    if (lockcheck && has_prefix(ins, PPS_LOCK, P_LOCK)) {
+        if ((!itemp_has(temp,IF_LOCK)  || !is_class(MEMORY, ins->oprs[0].type)) &&
+            (!itemp_has(temp,IF_LOCK1) || !is_class(MEMORY, ins->oprs[1].type))) {
+            /*!
+             *!prefix-lock-error [on] LOCK prefix on unlockable instruction
+             *!=lock
+             *!  warns about \c{LOCK} prefixes on unlockable instructions.
+             */
+            nasm_warn(WARN_PREFIX_LOCK_ERROR|ERR_PASS2 , "instruction is not lockable");
+        } else if (temp->opcode == I_XCHG) {
+            /*!
+             *!prefix-lock-xchg [on] superfluous LOCK prefix on XCHG instruction
+             *!  warns about a \c{LOCK} prefix added to an \c{XCHG} instruction.
+             *!  The \c{XCHG} instruction is \e{always} locking, and so this
+             *!  prefix is not necessary; however, NASM will generate it if
+             *!  explicitly provided by the user, so this warning indicates that
+             *!  suboptimal code is being generated.
+             */
+            nasm_warn(WARN_PREFIX_LOCK_XCHG|ERR_PASS2,
+                      "superfluous LOCK prefix on XCHG instruction");
+        }
     }
 
     bad_hle_warn(ins, hleok);
diff --git a/x86/iflags.ph b/x86/iflags.ph
index ffeb8e5b..35a672f0 100644
--- a/x86/iflags.ph
+++ b/x86/iflags.ph
@@ -34,6 +34,7 @@ if_("PRIV",              "Privileged instruction");
 if_("SMM",               "Only valid in SMM");
 if_("PROT",              "Protected mode only");
 if_("LOCK",              "Lockable if operand 0 is memory");
+if_("LOCK1",             "Lockable if operand 1 is memory");
 if_("NOLONG",            "Not available in long mode");
 if_("LONG",              "Long mode");
 if_("NOHLE",             "HLE prefixes forbidden");
diff --git a/x86/insns.dat b/x86/insns.dat
index 17a3f107..ae4c4b6a 100644
--- a/x86/insns.dat
+++ b/x86/insns.dat
@@ -1455,22 +1455,18 @@ XCHG		reg64,reg_rax			[r-:	o64 90+r]				X86_64,LONG
 ; This must be NOLONG since opcode 90 is NOP, and in 64-bit mode
 ; "xchg eax,eax" is *not* a NOP.
 XCHG		reg_eax,reg_eax			[--:	o32 90]					386,NOLONG
-XCHG		reg8,mem			[rm:	hlenl 86 /r]				8086,SM,LOCK
-XCHG		reg8,reg8			[rm:	86 /r]					8086
-XCHG		reg16,mem			[rm:	hlenl o16 87 /r]			8086,SM,LOCK
-XCHG		reg16,reg16			[rm:	o16 87 /r]				8086
-XCHG		reg32,mem			[rm:	hlenl o32 87 /r]			386,SM,LOCK
-XCHG		reg32,reg32			[rm:	o32 87 /r]				386
-XCHG		reg64,mem			[rm:	hlenl o64 87 /r]			X86_64,LONG,SM,LOCK
-XCHG		reg64,reg64			[rm:	o64 87 /r]				X86_64,LONG
-XCHG		mem,reg8			[mr:	hlenl 86 /r]				8086,SM,LOCK
 XCHG		reg8,reg8			[mr:	86 /r]					8086
-XCHG		mem,reg16			[mr:	hlenl o16 87 /r]			8086,SM,LOCK
 XCHG		reg16,reg16			[mr:	o16 87 /r]				8086
-XCHG		mem,reg32			[mr:	hlenl o32 87 /r]			386,SM,LOCK
 XCHG		reg32,reg32			[mr:	o32 87 /r]				386
-XCHG		mem,reg64			[mr:	hlenl o64 87 /r]			X86_64,LONG,SM,LOCK
 XCHG		reg64,reg64			[mr:	o64 87 /r]				X86_64,LONG
+XCHG		mem,reg8			[mr:	hlenl 86 /r]				8086,SM,LOCK
+XCHG		mem,reg16			[mr:	hlenl o16 87 /r]			8086,SM,LOCK
+XCHG		mem,reg32			[mr:	hlenl o32 87 /r]			386,SM,LOCK
+XCHG		mem,reg64			[mr:	hlenl o64 87 /r]			X86_64,LONG,SM,LOCK
+XCHG		reg8,mem			[rm:	hlenl 86 /r]				8086,SM,LOCK1
+XCHG		reg16,mem			[rm:	hlenl o16 87 /r]			8086,SM,LOCK1
+XCHG		reg32,mem			[rm:	hlenl o32 87 /r]			386,SM,LOCK1
+XCHG		reg64,mem			[rm:	hlenl o64 87 /r]			X86_64,LONG,SM,LOCK1
 XLATB		void				[	d7]					8086
 XLAT		void				[	d7]					8086
 XOR		mem,reg8			[mr:	hle 30 /r]				8086,SM,LOCK


More information about the Nasm-commits mailing list