Messages in this thread | | | Subject | Re: [tip:x86/asm] x86/entry/64: Add two more instruction suffixes | From | Denys Vlasenko <> | Date | Tue, 3 Jul 2018 13:59:21 +0200 |
| |
On 07/03/2018 10:46 AM, David Laight wrote: > From: Jan Beulich >> Sent: 03 July 2018 09:36 > ... >> As said there, omitting suffixes from instructions in AT&T mode is bad >> practice when operand size cannot be determined by the assembler from >> register operands, and is likely going to be warned about by upstream >> gas in the future (mine does already). > ... >> - bt $9, EFLAGS(%rsp) /* interrupts off? */ >> + btl $9, EFLAGS(%rsp) /* interrupts off? */ > > Hmmm.... > Does the operand size make any difference at all for the bit instructions? > I'm pretty sure that the cpus (386 onwards) have always done aligned 32bit > transfers (the docs never actually said aligned). > I can't remember whether 64bit mode allows immediates above 31.
Immediates up to 63 are allowed in 64 bit mode (IOW: for REX-prefixed form) (run-tested).
Keep in mind that this instruction is "special" with register bit offset:
Register/memory form (BT REG,[MEM]) does not limit or mask the value of bit offset in REG, the instruction uses bit REG%8 in byte at address [MEM+REG/8].
This works correctly even for negative values: REG = -1 will access the most significant bit in the byte immediately before MEM.
Thus, for accesses of standard RAM locations (not memory-mapped IO and such), the "operand size" concept for this instruction (and BTC, BTR, BTS) does not make much sense: it accesses one bit. The width of actual memory access is irrelevant.
I'd say assembler should just use the "natural" width for current mode (16 or 32-bit), and warn when code tries to use immediate operand which will be truncated and thus needs a wider operand size.
Intel documentation says that immediate operand in BT IMM,[MEM] is truncated to operand size. My experiment seems to confirm it:
254:1 <- BT 254,[MEM] actually accesses bit #30, not #254 255:0 254:0 255:0
#include <string.h> #include <stdio.h> int main(int argc, char **argv, char **envp) { char buf[256]; int result;
memset(buf, 0x55, sizeof(buf)); /* bit pattern: 01010101 */
buf[255/8] = 0; asm("\n" " bt %1, %2\n" " sbb %0, %0\n" : "=r" (result) : "i" (254), "m" (buf) ); printf("254:%x\n", !!result); asm("\n" " bt %1, %2\n" " sbb %0, %0\n" : "=r" (result) : "i" (255), "m" (buf) ); printf("255:%x\n", !!result); buf[255/8] = 0x55;
buf[31/8] = 0; asm("\n" " bt %1, %2\n" " sbb %0, %0\n" : "=r" (result) : "i" (254), "m" (buf) ); printf("254:%x\n", !!result); asm("\n" " bt %1, %2\n" " sbb %0, %0\n" : "=r" (result) : "i" (255), "m" (buf) ); printf("255:%x\n", !!result);
return 0; }
When I use "r" instead of "i" to generate REG,[MEM] form, the instruction does access bit #254:
254:0 255:0 254:1 255:0
| |