893df4b79b
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);
21 lines
408 B
ArmAsm
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
|