Discussion:
[9fans] 6a bug
(too old to reply)
erik quanstrom
2011-11-16 22:25:44 UTC
Permalink
i plan to look at this when i get home, but it appears that 6a
doesn't like big numbers. demo script follows

- erik
-------
; cat >a.s <<'EOF'
#define KZERO (0xffffff0000000000ull)

TEXT bignumber(SB), 1, $0
ADDQ $KZERO, AX
RET
EOF
; cat >ac.c<<EOF
#include <u.h>
#include <libc.h>

extern uvlong bignumber(uvlong);

void
main(void)
{
print("%llux\n", bignumber(0));
exits("");
}
EOF
; 6a a.s; 6c ac.c; 6l a.6 ac.6
Charles Forsyth
2011-11-16 22:36:39 UTC
Permalink
PS: the return value does go in AX
Charles Forsyth
2011-11-16 22:35:49 UTC
Permalink
AX is the wrong register. REGARG is BP. actually, it's "RARG" in 6a, in case it
changes, although that seems less likely now.
Post by erik quanstrom
i plan to look at this when i get home, but it appears that 6a
doesn't like big numbers.  demo script follows
- erik
-------
; cat >a.s <<'EOF'
#define KZERO   (0xffffff0000000000ull)
TEXT bignumber(SB), 1, $0
       ADDQ    $KZERO, AX
       RET
EOF
; cat >ac.c<<EOF
#include <u.h>
#include <libc.h>
extern uvlong bignumber(uvlong);
void
main(void)
{
       print("%llux\n", bignumber(0));
       exits("");
}
EOF
; 6a a.s; 6c ac.c; 6l a.6 ac.6
Russ Cox
2011-11-16 22:50:03 UTC
Permalink
I'm a little surprised 6a accepts the ull suffix.

Russ
Charles Forsyth
2011-11-16 23:27:07 UTC
Permalink
we aim to please!

while(c == 'U' || c == 'u' || c == 'l' || c == 'L')
c = GETC();
Post by Russ Cox
I'm a little surprised 6a accepts the ull suffix.
Russ
erik quanstrom
2011-11-17 00:50:18 UTC
Permalink
Post by Charles Forsyth
AX is the wrong register. REGARG is BP. actually, it's "RARG" in 6a, in case it
changes, although that seems less likely now.
well my example is slightly booged then. i just needed a label.
the point still stands that 6l is not liking the *value*. this actually
comes from _start64v, and i wanted to simplify it. if you replace
the given value with $10, it 6l will not complain.

_start64v: doasm: notfound from=75 to=10 (423) ADDQ $-1099511627776,AX
_start64v: doasm: notfound from=75 to=10 (423) ADDQ $-1099511627776,AX
_start64v: doasm: notfound from=75 to=10 (423) ADDQ $-1099511627776,AX

- erik
Russ Cox
2011-11-17 16:07:40 UTC
Permalink
well my example is slightly booged then.  i just needed a label.
the point still stands that 6l is not liking the *value*.  this actually
comes from _start64v, and i wanted to simplify it.  if you replace
the given value with $10, it 6l will not complain.
This is a detail of the x86-64 architecture.
An immediate in an arithmetic instruction must
fit in a signed 32-bit int, and this one does not.
You've written an impossible instruction, and the
linker is telling you in own cryptic way.
The assemblers do not know such details, never have.

You need to MOVQ that constant into a register
and then use the register as the argument to ADDQ.

Russ
Charles Forsyth
2011-11-17 16:13:21 UTC
Permalink
I'd replied, but "Reply"'s default is never right (either way).
It's as you say, and the reason it worked in the kernel is
that KZERO was a different value, which did satisfy the hardware's constraint.

On some of the older RISC machines, the loader might generate impossible
constants into a register itself, but that relied on defining a global REGTMP,
which was fine on a 32-ish register machine (you hardly ever need that many)
but not so good on the amd64 where the original registers are strange and
in short supply, and the new registers have a penalty, and there are only 16
in all.
erik quanstrom
2011-11-17 16:15:24 UTC
Permalink
Post by Russ Cox
This is a detail of the x86-64 architecture.
An immediate in an arithmetic instruction must
fit in a signed 32-bit int, and this one does not.
You've written an impossible instruction, and the
linker is telling you in own cryptic way.
The assemblers do not know such details, never have.
You need to MOVQ that constant into a register
and then use the register as the argument to ADDQ.
yup. that's the problem. i had forgotten this rule because
i changed from one 64-bit constant to another. the tricky
bit about the first constant was that it was a sign-extended
32-bit constant, and the linker knew this little nugget.
so imagine my surprise when changing

#define KZERO (0xfffffffff0000000ull)

to

#define KZERO (0xffffff0000000000ull)

resulted in linker errors.

it all makes sense now. (even if it is repulsive.)

- erik

Continue reading on narkive:
Loading...