Evian
Evian

Reputation: 1197

What is the difference between N.E. and I in Intel manual?

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

Answers (1)

Peter Cordes
Peter Cordes

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:

  • there's no longer any way to do 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 the
    "0F A1 POP FS ... Pop top of stack into FS; increment stack pointer by 32 bits"
    line of the table has N.E. for 64-bit mode, valid for compat/legacy. And the ... by 64 bits line is the reverse, valid for 64, invalid for 32. (Amusing that they write "by 64 bits" instead of "by 8" when RSP counts in bytes, not 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

Related Questions