On 07/03/2018 10:46 AM, David Laight wrote:
From: Jan BeulichSent: 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 -- To unsubscribe from this list: send the line "unsubscribe linux-tip-commits" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html
![]() |