Messages in this thread | | | Date | Wed, 25 Mar 1998 10:17:06 -0800 (PST) | From | Linus Torvalds <> | Subject | Re: [PATCH] APM support doesn't compile with binutils 2.8.1.0.24 |
| |
On Wed, 25 Mar 1998, Bernhard Rosenkraenzer wrote: > > According to the binutils people, it's related to bogus asm in apm_bios.c > - the patch I've attached fixes it.
Are the binutils people aware that the size prefix _does_ make a difference for segment loads?
If you do a 16-bit "mov seg -> reg", the operation will write only the low 16 bits, while if you do a 32-bit version it will actually write all 32 bits (high bits zero, I do believe).
(Just to confuse matters: if the destination is memory, it seems to be always written 16 bits at a time regardless of the size of the operand. Don't you all love Intel?)
Anyway, this does mean that people can quite _deliberately_ need both the 16- and 32-bit versions, and gas _should_ accept a "w" or "l" at the instruction to imply which one is needed.
The old gas bug was that it defaulted to 16-bit mode which is slower and bigger (and is also strange, considering that gas always otherwise defaults to 32-bit mode when not told otherwise). But the new gas behaviour is equally buggy in that it appears to not support the 16-bit mode at all, and even complains when explicitly given a (legal) size.
The "b" case (8-bit) is illegal and should not be allowed (which was my original complaint about the patch that Ingo posted).
In short:
push %ds : legal, should default to 32-bit mode, no override pushl %ds : legal, 32-bit, no override pushw %ds : legal, 16-bit, operand size override pushb %ds : illegal
mov %ds,%eax : legal, should default to 32-bit mode, no override mov %ds,%ax : if gas notices that "%ax" is 16-bit it would be great. movw %ds,%ax : 16-bit, operand size override REQUIRED movl %ds,%eax : 32-bit, no override
When moving to memory (pushw and movw to memory) the 16-bit override _may_ be optimized away, but as explained above it definitely may NOT be optimized away when moving to a register because the behaviour is very different (I don't know whether the segment checks are for 16- or 32-bit entities, though, so maybe even the mov-to-memory case is different).
When moving _to_ a segment register there really isn't any difference between a 16-bit and a 32-bit operand size (there is no zero-extend semantics for moving to segment registers), but even then the assembler should probably allow specifying an override, and should _definitely_ allow specifying a size (that might be ignored) in order to have the same syntax as moving the other way:
pop %ds : default to 32-bit, no override popl %ds : 32-bit, no override popw %ds : 16-bit (but maybe the override can be optimized away)
mov %eax,%ds : legal, should default to 32-bit mode, no override movl %eax,%ds : legal, no override movw %ax,%ds : 16-bit (but maybe the override can be optimized away)
So I think the APM bios access code is actually correct in specifying a "l" on the push/pop operations.
Linus
- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.rutgers.edu
| |