My i386 code from 893df4b gave the wrong sign to some 8-byte
remainders. Fix by splitting .dvi8 and .rmi8 so each has its own code
to pick the sign. They and .dvu8 and .rmu8 share a private sub
.divrem8 for unsigned division.
Improve the i386 code by using instructions like _bsr_ and _shrd_.
Change the helpers to yield a quotient in ebx:eax or a remainder in
ecx:edx; this seems more convenient, because _div_ puts its quotient
in eax and remainder in edx.
This provides adi, sbi, mli, dvi, rmi, ngi, dvu, rmu 8, but is missing
shifts and rotates. It is also missing conversions between 8-byte
integers and other sizes of integers or floats. The code might not be
all correct, but works at least some of the time.
I adapted this from how ncg i86 does 4-byte integers, but I use a
different algorithm when dividing by a large value: i86 avoids the div
instruction and uses a shift-and-subtract loop; but I use the div
instruction to estimate a quotient, which is more like how big integer
libraries do division. My .dvi8 and .dvu8 also set ecx:ebx to the
remainder; this might be a bad idea, because it requires .dvi8 and
.dvu8 to always calculate the remainder, even when the caller only
wants the quotient.
To play with 8-byte integers, I wrote EM procedures like
mes 2, 4, 4
exp $ngi
pro $ngi,0
ldl 4
ngi 8
lol 0
sti 8
lol 0
ret 4
end
exp $adi
pro $adi,0
ldl 4
ldl 12
adi 8
lol 0
sti 8
lol 0
ret 4
end
and called them from C like
typedef struct { int l; int h; } q;
q ngi(q);
q adi(q, q);