ack/mach/i386/libem/mli8.s
George Koehler 893df4b79b Experiment with 8-byte integers in ncg i386.
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);
2019-08-20 13:38:18 -04:00

21 lines
408 B
ArmAsm

.sect .text; .sect .rom; .sect .data; .sect .bss
.sect .text
.define .mli8
yl=4
yh=8
! xl in eax
! xh in edx
.mli8:
! x * y = (xh + xl) * (yh + yl)
! = xh * yh + xh * yl + xl * yh + xl * yl
! The term xh * yh overflows to zero.
mov ecx,eax
imul ecx,yh(esp) ! ecx = xl * yh
imul edx,yl(esp) ! edx = xh * yl
add ecx,edx
mul yl(esp) ! edx:eax = xl * yl
add edx,ecx ! edx:eax = x * y
ret 8