-2

Intel x64 CPUs can also run x86 asm. Is there a flag or mode in the CPU to determine whether instructions should be decoded as x86 or x64? How does the CPU know if instructions are x86 or x64?

At the CPU level (not the OS level!), is it possible to mix x86 and x64 instructions?

Note: There are plenty of SO Q&A on this question at the OS level; I'm interested at the CPU level. Talk about libraries, files, etc., are not at the CPU level.

SRobertJames
  • 8,210
  • 14
  • 60
  • 107
  • 2
    `Is there a flag or mode in the CPU to determine whether instructions should be decoded as x86 or x64?` Yes. – tkausl Oct 26 '21 at 22:14
  • 3
    The flag is in the segment descriptor referenced by the current selector in the `CS` register. The only way to mix is to jump between segments. – Jester Oct 26 '21 at 22:28
  • See for instance https://wiki.osdev.org/X86-64#How_do_I_enable_Long_Mode_.3F – Nate Eldredge Oct 26 '21 at 23:31

2 Answers2

5

The bit LMA (Long Mode Active) in the IA32_EFER MSR indicates that the processor is in long mode (64-bit mode).

When in long mode, the L bit in the active code segment descriptor indicates whether the processor is decoding 32-bit or 64-bit instructions.

To change LMA, software clears the PG bit in CR0, changes the LME bit in EFER, and then sets PG.

To change the L bit in CS, software executes a far jump or far call to load CS with a selector for a code segment descriptor with the desired value.

prl
  • 11,716
  • 2
  • 13
  • 31
1

For 80x86; CPU mode has very little to do with code size or instruction decoding (and primarily determines what happens during expensive stuff like segment register loads and interrupt handlers that are relegated to micro-code).

For instruction decoding what matters is code size (not CPU mode); and there's 3 possibilities - 16-bit code, 32-bit code and 64-bit code.

In long mode, the code size is determined by 2 bits in the code segment's descriptor.

In protected mode, the code size is determined by 1 bit in the code segment's descriptor (and 64-bit code isn't an option).

In real mode (and a few other cases - virtual8086 mode, system management mode) code size is "nominally fixed" at 16 bits (where "nominally fixed" means that there's way around it involving switching to another mode temporarily to fudge things up).

Brendan
  • 35,656
  • 2
  • 39
  • 66
  • https://en.wikipedia.org/wiki/X86-64#Operating_modes is a good table of the available combinations, including compat sub-mode of long-mode. The only thing independent of those controls is (I think) the stack address width, from the SS descriptor, right? So you can't have the default address-size be 32 with a default operand-size of 16, but you can have the *stack pointer* width (ESP) for implicit use like push/pop be different from the current address-size. – Peter Cordes Oct 27 '21 at 03:20
  • 1
    @PeterCordes: Correct, in protected mode, the stack pointer width (`SP` vs `ESP`) is determined by the `D/B` flag in the data segment descriptor identified by the selector in `SS`. (in 64-bit mode, though, the width is always 64-bit, and the flag is ignored - in fact, every flag and field is ignored in a data segment descriptor except `P` (present)) – sj95126 Oct 27 '21 at 04:42