oscar64/include/fixmath.c

588 lines
5.7 KiB
C

#include "fixmath.h"
unsigned long lmul16u(unsigned x, unsigned y)
{
__asm
{
lda #0
sta accu + 2
sta accu + 3
ldx #16
L1: lsr x + 1
ror x
bcc W1
clc
lda accu + 2
adc y
sta accu + 2
lda accu + 3
adc y + 1
sta accu + 3
W1:
ror accu + 3
ror accu + 2
ror accu + 1
ror accu
dex
bne L1
}
}
long lmul16s(int x, int y)
{
__asm
{
bit y + 1
bpl W0
sec
lda #0
sbc y
sta y
lda #0
sbc y + 1
sta y + 1
sec
lda #0
sbc x
sta x
lda #0
sbc x + 1
sta x + 1
W0:
ldx #15
lda #0
sta accu + 2
L1: lsr x + 1
ror x
bcc W1
tay
clc
lda accu + 2
adc y
sta accu + 2
tya
adc y + 1
W1:
ror
ror accu + 2
ror accu + 1
ror accu
dex
bne L1
lsr x
bcc W2
tay
sec
lda accu + 2
sbc y
sta accu + 2
tya
sbc y + 1
sec
W2:
ror
ror accu + 2
ror accu + 1
ror accu
sta accu + 3
}
}
inline int lmul12f4s(int x, int y)
{
return (int)(lmul16s(x, y) >> 4);
}
inline int lmul8f8s(int x, int y)
{
return (int)(lmul16s(x, y) >> 8);
}
inline unsigned long lsqr4f12s(int x)
{
if (x < 0) x = -x;
return lmul16u(x, x);
}
int lmul4f12s(int x, int y)
{
__asm
{
bit y + 1
bpl W0
sec
lda #0
sbc y
sta y
lda #0
sbc y + 1
sta y + 1
sec
lda #0
sbc x
sta x
lda #0
sbc x + 1
sta x + 1
W0:
ldx #15
lda #0
sta accu + 1
L1: lsr x + 1
ror x
bcc W1
tay
clc
lda accu + 1
adc y
sta accu + 1
tya
adc y + 1
W1:
ror
ror accu + 1
ror accu
dex
bne L1
lsr x
bcc W2
tay
sec
lda accu + 1
sbc y
sta accu + 1
tya
sbc y + 1
sec
W2:
ror
ror accu + 1
ror accu
lsr
ror accu + 1
ror accu
lsr
ror accu + 1
ror accu
lsr
ror accu + 1
ror accu
lsr
ror accu + 1
ror accu
}
}
unsigned ldiv16u(unsigned long x, unsigned y)
{
__asm
{
lda #0
sta accu
sta accu + 1
ldx #17
L1:
sec
lda x + 2
sbc y
tay
lda x + 3
sbc y + 1
bcc W1
sta x + 3
sty x + 2
W1:
rol accu
rol accu + 1
asl x
rol x + 1
rol x + 2
rol x + 3
dex
beq E1
bcc L1
lda x + 2
sbc y
sta x + 2
lda x + 3
sbc y + 1
sta x + 3
sec
bcs W1
E1:
}
}
int ldiv16s(long x, int y)
{
if (x < 0)
{
if (y < 0)
return ldiv16u(-x, - y);
else
return -ldiv16u(-x, y);
}
else if (y < 0)
return -ldiv16u(x, -y);
else
return ldiv16u(x, y);
}
inline int ldiv12f4s(int x, int y)
{
return (int)(ldiv16s((long)x << 4, y));
}
inline int ldiv8f8s(int x, int y)
{
return (int)(ldiv16s((long)x << 8, y));
}
inline int ldiv4f12s(int x, int y)
{
return (int)(ldiv16s((long)x << 12, y));
}
unsigned lmuldiv16u(unsigned a, unsigned b, unsigned c)
{
__asm
{
lda #0
sta __tmp + 0
sta __tmp + 1
sta __tmp + 2
sta __tmp + 3
ldx #16
L1: lsr a + 1
ror a
bcc W1
clc
lda __tmp + 2
adc b
sta __tmp + 2
lda __tmp + 3
adc b + 1
sta __tmp + 3
W1:
ror __tmp + 3
ror __tmp + 2
ror __tmp + 1
ror __tmp
dex
bne L1
lda #0
sta accu
sta accu + 1
ldx #17
L2:
sec
lda __tmp + 2
sbc c
tay
lda __tmp + 3
sbc c + 1
bcc W2
sta __tmp + 3
sty __tmp + 2
W2:
rol accu
rol accu + 1
asl __tmp
rol __tmp + 1
rol __tmp + 2
rol __tmp + 3
dex
beq E2
bcc L2
lda __tmp + 2
sbc c
sta __tmp + 2
lda __tmp + 3
sbc c + 1
sta __tmp + 3
sec
bcs W2
E2:
}
}
int lmuldiv16s(int a, int b, int c)
{
bool sign = false;
if (a < 0)
{
a = -a;
sign = !sign;
}
if (b < 0)
{
b = -b;
sign = !sign;
}
if (c < 0)
{
c = -c;
sign = !sign;
}
__asm
{
lda #0
sta __tmp + 0
sta __tmp + 1
sta __tmp + 2
sta __tmp + 3
ldx #16
L1: lsr a + 1
ror a
bcc W1
clc
lda __tmp + 2
adc b
sta __tmp + 2
lda __tmp + 3
adc b + 1
sta __tmp + 3
W1:
ror __tmp + 3
ror __tmp + 2
ror __tmp + 1
ror __tmp
dex
bne L1
lda #0
sta accu
sta accu + 1
ldx #17
L2:
sec
lda __tmp + 2
sbc c
tay
lda __tmp + 3
sbc c + 1
bcc W2
sta __tmp + 3
sty __tmp + 2
W2:
rol accu
rol accu + 1
asl __tmp
rol __tmp + 1
rol __tmp + 2
rol __tmp + 3
dex
beq E2
bcc L2
lda __tmp + 2
sbc c
sta __tmp + 2
lda __tmp + 3
sbc c + 1
sta __tmp + 3
sec
bcs W2
E2:
lda sign
beq E1
sec
lda #0
sbc accu
sta accu
lda #0
sbc accu + 1
sta accu + 1
E1:
}
}
unsigned lmuldiv16by8(unsigned a, char b, char c)
{
__asm {
lda #0
sta accu + 0
sta accu + 1
sta accu + 2
sta accu + 3
lda b
beq z1
lda c
l1:
asl
bcs e1
cmp b
bcs e2
asl a + 0
rol a + 1
jmp l1
e2:
clc
e1:
ror
sta c
ldx #16
l2:
lda b
sec
sbc c
bcc w1
sta b
clc
lda accu + 2
adc a
sta accu + 2
lda accu + 3
adc a + 1
sta accu + 3
bcc * + 8
inc accu + 0
bne * + 4
inc accu + 1
w1:
asl accu + 2
rol accu + 3
rol accu + 0
rol accu + 1
asl b
bcc w2
lda b
sbc c
sta b
clc
lda accu + 2
adc a
sta accu + 2
lda accu + 3
adc a + 1
sta accu + 3
bcc * + 8
inc accu + 0
bne * + 4
inc accu + 1
w2:
dex
bne l2
z1:
}
}
unsigned lmuldiv8by8(char a, char b, char c)
{
__asm {
ldy #0
sty accu + 0
sty accu + 1
sty accu + 2
lda a
beq z1
lda c
beq z1
ldx #8
lda b
beq z1
cmp c
bcc w0
l1:
lsr
ror accu + 1
inx
cmp c
bcs l1
bcc wa
l2:
asl accu + 2
rol accu + 0
wa:
rol accu + 1
w0:
rol
bcc w2
sbc c
bcc w3
w2:
tay
sec
sbc c
bcc w1
w3:
tay
clc
lda accu + 2
adc a
sta accu + 2
bcc w1
inc accu + 0
bne w1
inc accu + 1
w1:
tya
dex
bne l2
z1:
}
}
int lmuldiv16sby8(int a, char b, char c)
{
if (a < 0)
return -(int)lmuldiv16by8(-a, b, c);
else
return lmuldiv16by8(a, b, c);
}