Reputation: 1197
In Intel's manual for Intel 64 and IA-32 instruction set section 3.1.1.5, it introduces 64/32-bit mode column in the instruction summary table.
For 64-bit mode support, it says:
- I - Not supported
- N.E. - Indicates an instruction syntax is not encodable in 64-bit mode (it may represent part of a sequence of valid instructions in other modes
What is the difference between an instruction is not encodable in 64-bit mode, and an instruction is not supported in 64-bit mode?
Upvotes: 3
Views: 227
Reputation: 364573
It's not totally clear exactly what distinction Intel is making, or why it's useful to make that distinction1. It looks like Invalid is only used for opcodes that will #UD (illegal instruction fault), which is why they use N.E. even in cases where there's no other way to encode the instruction with that operand-size.
N.E. ... it may represent part of a sequence of valid instructions in other modes
This would make sense and I think match their docs if they said "in this mode". e.g. 0x1F
is not a valid opcode or prefix in 64-bit mode, but in other modes means pop ds
.
Footnote 1: Of course there's no future-proof guarantee of faulting with #UD - a future ISA extension on future CPUs could repurpose unused opcodes for something in 64-bit mode, effectively changing Invalid to N.E. (The future-proof way to #UD is the 0F 0B
opcode, documented as ud2
)
An example of Invalid is aam
(immediate division) in 64-bit mode: there's no encoding of the instruction at all in that mode, and the opcode is unused.
An example of N.E. is the inc r32
short form 0x40+rd which 64-bit mode repurposed (along with 0x48+rd dec
) as REX prefixes. inc eax
is also encodeable, but not with that opcode.
Similarly, inc r/m64
is listed as N.E. for compat/legacy mode; i.e. it's only available in long mode, via a REX prefix.
pop
has examples of both kinds in one table:
pop ds
(or ES/SS) with any operand-size, and those opcodes are freed up for future use, so it's "invalid" in 64-bit mode. (pop cs has never been valid, except for some undocumented / early 8086; only stuff like retf which sets CS:[ER]IP together not just CS.)pop fs
and GS can be done with 16-bit or 64-bit operand-size, but not 32-bit, so the0F A1 POP FS
... Pop top of stack into FS; increment stack pointer by 32 bits"pop r32
and pop r/m32
are both listed as N.E. for 64-bit mode, not invalid, despite the fact that there's no way to encode pop eax
or pop dword [rdi]
in that mode. So it's looking like Invalid is about the opcode, not the instruction.
(Even a REX.W=0 doesn't override the operand size to 32-bit for opcodes where the default is 64, but a 66
operand-size prefix does work as usual to make push/pop 16-bit. This is despite the "description" text saying operand-size may be overridden by REX.W - that seems to be talking about instructions in general, as implied by the current code-segment's D flag.)
Perhaps because 64-bit mode can still pop the other 2 sizes (64 or 16-bit) with the same opcode? Or the other 2 sizes of r/m with pop? e.g. pop ax
and pop word [rdi]
are valid in 64-bit mode along with pop rax
of course.
This is consistent with how they listed pop ds
.
I wondered whether movsxd r64, r/m32
would be Invalid or N.E. in 16/32-bit mode, because the same opcode has a different meaning outside of 64-bit mode (ARPL r,r/m16 - http://ref.x86asm.net/coder32.html#x63).
But instead it's only N.E. for 32-bit mode and movsxd r32, r/m32
is listed as "valid" for both modes! That has to be a bug because it's obviously wrong. Opcode 63
in compat/legacy mode is ARPL. (Which is listed as N.E. (64) / Valid (32), and whose Operation section mentions movsxd for 64-bit mode.) So N.E. would match their pattern of using that for things which mean something else but don't fault.
(Real-world assemblers like NASM and YASM reject movsxd eax, ecx
even in 64-bit mode; they want a 64-bit destination, refusing to let you use it as a worse mov eax, ecx
even though that is possible in machine code, but Intel's manual discourages that. movsxd
unfortunately needs a REX prefix to serve its only purpose: sign-extend 32 to 64. Not being a stack or branch op I guess AMD decided it was more consistent for the operand-size to default to 64-bit.)
Upvotes: 4