1
0
mirror of https://github.com/diegocr/libnix.git synced 2026-03-19 07:16:45 +00:00
Files
amiga-libnix3/math/mul64.c-
2010-07-27 16:58:17 +00:00

302 lines
4.5 KiB
Plaintext

#include <stdio.h>
#include <inttypes.h>
#include "stabs.h"
#if 0
#define umul_ppmm3(xh, xl, a, b) \
__asm__ ("| Inlined umul_ppmm\n" \
" move.l %0,%/d5\n" \
" move.l %1,%/d4\n" \
" moveq #16,%/d3\n" \
" move.l %0,%/d2\n" \
" mulu %1,%0\n" \
" lsr.l %/d3,%/d4\n" \
" lsr.l %/d3,%/d5\n" \
" mulu %/d4,%/d2\n" \
" mulu %/d5,%1\n" \
" mulu %/d5,%/d4\n" \
" move.l %/d2,%/d5\n" \
" lsr.l %/d3,%/d2\n" \
" add.w %1,%/d5\n" \
" addx.l %/d2,%/d4\n" \
" lsl.l %/d3,%/d5\n" \
" lsr.l %/d3,%1\n" \
" add.l %/d5,%0\n" \
" addx.l %/d4,%1" \
: "=d" ((uint32_t) (xl)), "=d" ((uint32_t) (xh)) \
: "0" ((uint32_t) (a)), "1" ((uint32_t) (b)) \
: "d2", "d3", "d4", "d5")
int64_t MUL64(int a, int b)
{
uint32_t au = a;
uint32_t bu = b;
uint32_t resh, resl;
uint64_t res;
umul_ppmm3(resh, resl, au, bu);
if (a < 0)
resh -= bu;
if (b < 0)
resh -= au;
res = ((uint64_t)resh << 32) | resl;
return res;
}
#else
int64_t MUL64(int a, int b)
{
uint32_t resh, resl;
uint32_t au = a;
uint32_t bu = b;
__asm__ ("move.l %0, d5\n\t"
"move.l %1, d4\n\t"
"moveq #16, d3\n\t"
"move.l %0, d2\n\t"
"mulu %1, %0\n\t"
"lsr.l d3, d4\n\t"
"lsr.l d3, d5\n\t"
"mulu d4, d2\n\t"
"mulu d5, %1\n\t"
"mulu d5, d4\n\t"
"move.l d2, d5\n\t"
"lsr.l d3, d2\n\t"
"add.w %1, d5\n\t"
"addx.l d2, d4\n\t"
"lsl.l d3, d5\n\t"
"lsr.l d3, %1\n\t"
"add.l d5, %0\n\t"
"addx.l d4, %1\n\t"
: "=d"(resl), "=d"(resh)
: "0"(au), "1"(bu)
: "d2", "d3", "d4", "d5");
if (a < 0)
resh -= bu;
if (b < 0)
resh -= au;
return ((uint64_t)resh << 32) | resl;
}
#endif
ALIAS(mul64,MUL64);
ALIAS(__mul64,MUL64);
int MULH(int a, int b)
{
uint32_t resh, resl;
uint32_t au = a;
uint32_t bu = b;
__asm__ ("move.l %1, d5\n\t"
"move.l %0, d4\n\t"
"moveq #16, d3\n\t"
"move.l %1, d2\n\t"
"mulu %0, %1\n\t"
"lsr.l d3, d4\n\t"
"lsr.l d3, d5\n\t"
"mulu d4, d2\n\t"
"mulu d5, %0\n\t"
"mulu d5, d4\n\t"
"move.l d2, d5\n\t"
"lsr.l d3, d2\n\t"
"add.w %0, d5\n\t"
"addx.l d2, d4\n\t"
"lsl.l d3, d5\n\t"
"lsr.l d3, %0\n\t"
"add.l d5, %1\n\t"
"addx.l d4, %0\n\t"
: "=d"(resh), "=d"(resl)
: "0"(au), "1"(bu)
: "d2", "d3", "d4", "d5");
if (a < 0)
resh -= bu;
if (b < 0)
resh -= au;
return (int)resh;
}
MAC64:
68060 version:
#include <stdio.h>
#include <stdint.h>
inline int64_t MUL64(int a, int b)
{
union { uint64_t x; unsigned hl[2]; } x;
__asm__(
"move.l %0, d5 \n\t"
"move.l %0, d4 \n\t"
"bge.b 0f \n\t"
"neg.l %0 \n\t"
"neg.l d4 \n\t"
"0: \n\t"
"eor.l %1, d5 \n\t"
"move.l %1, d3 \n\t"
"bge.b 1f \n\t"
"neg.l %1 \n\t"
"neg.l d3 \n\t"
"1: \n\t"
"move.w #16, d5 \n\t"
"move.l %0, d2 \n\t"
"mulu.w %1,%0 \n\t"
"lsr.l d5, d3 \n\t"
"lsr.l d5, d4 \n\t"
"mulu.w d3, d2 \n\t"
"mulu.w d4, %1 \n\t"
"mulu.w d4, d3 \n\t"
"move.l d2, d4 \n\t"
"lsr.l d5, d2 \n\t"
"add.w %1, d4 \n\t"
"addx.l d2, d3 \n\t"
"lsl.l d5, d4 \n\t"
"lsr.l d5, %1 \n\t"
"add.l d4, %0 \n\t"
"addx.l d3, %1 \n\t"
"tst.l d5 \n\t"
"bpl.b 2f \n\t"
"neg.l %0 \n\t"
"negx.l %1 \n\t"
"2: \n\t"
:"=d"(x.hl[1]), "=d"(x.hl[0])
:"0"(a), "1"(b)
:"d2", "d3", "d4", "d5");
return x.x;
}
inline int64_t MAC64(int64_t d, int a, int b)
{
return ((d) += MUL64(a, b));
}
68020 version:
inline av_const int64_t MAC64(int64_t d, int a, int b)
{
union { int64_t x; int hl[2]; } x = { d };
int h, l;
__asm__ ("muls.l %5, %2:%3 \n\t"
"add.l %3, %1 \n\t"
"addx.l %2, %0 \n\t"
: "+dm"(x.hl[0]), "+dm"(x.hl[1]),
"=d"(h), "=&d"(l)
: "3"(a), "dmi"(b));
return x.x;
}
#define MULH(ra,rb) \
({int rt; \
__asm__( \
"move.l %1,d5\n\t" \
"move.l %1,d4\n\t" \
"bge.b pos1\n\t" \
"neg.l %1\n\t" \
"neg.l d4\n\t" \
"pos1:\n\t" \
"eor.l %0,d5\n\t" \
"move.l %0,d3\n\t" \
"bge.b pos0\n\t" \
"neg.l %0\n\t" \
"neg.l d3\n\t" \
"pos0:\n\t" \
"move.w #16,d5\n\t" \
"move.l %1,d2\n\t" \
"mulu.w %0,%1\n\t" \
"lsr.l d5,d3\n\t" \
"lsr.l d5,d4\n\t" \
"mulu.w d3,d2\n\t" \
"mulu.w d4,%0\n\t" \
"mulu.w d4,d3\n\t" \
"move.l d2,d4\n\t" \
"lsr.l d5,d2\n\t" \
"add.w %0,d4\n\t" \
"addx.l d2,d3\n\t" \
"lsl.l d5,d4\n\t" \
"lsr.l d5,%0\n\t" \
"add.l d4,%1\n\t" \
"addx.l d3,%0\n\t" \
"tst.l d5\n\t" \
"bpl.b goodsign\n\t" \
"neg.l %1\n\t" \
"negx.l %0\n\t" \
"goodsign:\n\t" \
:"=d"(rt) \
:"0"((int)ra),"d"((int)rb) \
:"d2","d3","d4","d5"); \
rt;})
static inline int MULH(int a, int b)
{
int hi;
__asm__(
"fmove.s #796917760,fp0 \n\t"
"fmul.l %0,fp0 \n\t"
"fmul.l %1,fp0 \n\t"
"fmove.l fp0,%0 \n\t"
:"=dm"(hi)
:"0"(a), "dm"(b)
);
return hi;
}
static inline int64_t MUL64(int a, int b)
{
int lo, hi;
__asm__(
"fmove.l %0,fp0 \n\t"
"muls.l %1,%0 \n\t"
"bvs.b 0f \n\t"
"smi %1 \n\t"
"extb.l %1 \n\t"
"bra.b 1f \n\t"
"0: \n\t"
"fmul.s #796917760,fp0 \n\t"
"fmul.l %1,fp0 \n\t"
"fmove.l fp0,%1 \n\t"
"1: \n\t"
:"=d"(lo), "=d"(hi)
:"0"(a), "1"(b)
);
return ((uint64_t)hi <<32) | lo;
}