There are several problems in your built-in build instruction, most of which are indicated by error messages.
The first error message is Error: operand type mismatch for `push' corresponds to the pushw %eax instruction. The error occurs because the operand size suffix you used, w , does not match the actual operand size, %eax . You told him to use the instruction to push a 16-bit value on the stack, but on condition that the 32-bit register is an operand. You can fix this using pushw %ax , but that is not what you want. It would only store the lower 16 bits of the RAX register, not the entire register.
Another โobviousโ fix would be to use pushl %eax , but there are two problems with this. First, to fix other problems, you need to change the entire RAX register, which means that you need to save all 64 bits, not just the lower 32 bits. Secondly, there is no 32-bit PUSH instruction in 64-bit mode, so you are forced to use pushq %rax independently.
The following two error messages: Error: unsupported for `mov' . These error messages follow the instructions movl %cr0,%eax and movl %eax,%cr0 . and both are the result of the same problem. In 64-bit mode, there is no 32-bit version of these operands. You need to use a 64-bit operand, so the fix is โโsimply to use RAX instead of EAX. This is where all 64-bit RAXs go astray, and why I said you need to keep the whole register.
Last error message Error: operand type mismatch for `pop' . This is the result of a similar problem, such as the first. In this case, you did not use the operand size suffix, which means that the assembler will try to determine the operand size based on the operands. Since you used the 32-bit operand, %eax , it uses the 32-bit operand size. However, as with PUSH, there is a 32-bit POP command in 64-bit mode, so you cannot use %eax . In any case, since the PUSH command must be 64-bit, the POP command must be 64-bit to match, so the fix should use popq %rax .
Finally, one problem that is not indicated by the error message is that in 64-bit mode, the CR0 size expands to 64 bits. While the extra 32 bits are currently reserved and should be set to zero, they can be specified in future processors. Therefore, the command orl $0x40000000,%eax should preserve the upper 64-bit. Unfortunately, this does not happen, it will clear the upper 32-bit RAX bits, which means that this instruction will also inadvertently clear any of these bits that future processors may give. Therefore, it should be replaced by orq $0x40000000,%rax .
Thus, a fixed sequence of instructions will:
pushq %rax movq %cr0, %rax orq $0x40000000, %rax movq %rax, %cr0 wbinvd popq %rax
This is not what I'm going to suggest using in your inline assembly. This can be simplified by allowing GCC to select the register used. Thus, there is no need to save it. Here is what I would suggest instead:
long long dummy; asm volatile ("movq %%cr0, %0\n\t" "orq $0x40000000, %0\n\t" "movq %0, %%cr0\n\t" "wbinvd" : "=r" (dummy) : :);