mirror of
https://github.com/deater/dos33fsprogs.git
synced 2024-09-08 11:54:48 +00:00
1176 lines
25 KiB
C
1176 lines
25 KiB
C
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
|
|
//#define FIXED_IMPLEMENTATION 0
|
|
//#define FIXED_IMPLEMENTATION 1
|
|
//#define FIXED_IMPLEMENTATION 2
|
|
#define FIXED_IMPLEMENTATION 3
|
|
|
|
|
|
#if FIXED_IMPLEMENTATION==0
|
|
int fixed_mul(int x_i,int x_f,
|
|
int y_i,int y_f,
|
|
int *z_i,int *z_f,
|
|
int debug) {
|
|
|
|
short a,b;
|
|
int c;
|
|
|
|
a=((x_i)<<8)+(x_f);
|
|
b=((y_i)<<8)+(y_f);
|
|
|
|
c=a*b;
|
|
|
|
if (debug) {
|
|
printf("%x:%x (%d) * %x:%x (%d) = %x (%d)\n",
|
|
x_i,x_f,a,
|
|
y_i,y_f,b,
|
|
c,c);
|
|
}
|
|
|
|
c>>=8;
|
|
|
|
*z_i=(c>>8);
|
|
*z_f=(c&0xff);
|
|
|
|
|
|
return a*b;
|
|
}
|
|
#endif
|
|
|
|
|
|
#if FIXED_IMPLEMENTATION==1
|
|
int fixed_mul(int x_i,int x_f,
|
|
int y_i, int y_f,
|
|
int *z_i, int *z_f,
|
|
int debug) {
|
|
|
|
int num1h,num1l;
|
|
int num2h,num2l;
|
|
int result3;
|
|
int result2,result1,result0;
|
|
int aa,xx,cc=0,cc2,yy;
|
|
int negate=0;
|
|
|
|
num1h=x_i;
|
|
num1l=x_f;
|
|
|
|
if (!(num1h&0x80)) goto check_num2; // bpl check_num2
|
|
|
|
negate++; // inc negate
|
|
|
|
num1l=~num1l;
|
|
num1h=~num1h;
|
|
|
|
num1l&=0xff;
|
|
num1h&=0xff;
|
|
|
|
num1l+=1;
|
|
cc=!!(num1l&0x100);
|
|
num1h+=cc;
|
|
|
|
num1l&=0xff;
|
|
num1h&=0xff;
|
|
check_num2:
|
|
|
|
num2h=y_i;
|
|
num2l=y_f;
|
|
|
|
if (!(num2h&0x80)) goto unsigned_multiply;
|
|
|
|
negate++;
|
|
|
|
num2l=~num2l;
|
|
num2h=~num2h;
|
|
|
|
num2l&=0xff;
|
|
num2h&=0xff;
|
|
|
|
num2l+=1;
|
|
cc=!!(num2l&0x100);
|
|
num2h+=cc;
|
|
|
|
num2l&=0xff;
|
|
num2h&=0xff;
|
|
|
|
unsigned_multiply:
|
|
|
|
if (debug) {
|
|
printf("Using %02x:%02x * %02x:%02x\n",num1h,num1l,num2h,num2l);
|
|
}
|
|
|
|
result0=0;
|
|
result1=0;
|
|
|
|
|
|
//label_multiply:
|
|
aa=0; // lda #0 (sz)
|
|
result2=aa; // sta result+2
|
|
xx=16; // ldx #16 (sz)
|
|
label_l1:
|
|
cc=(num2h&1); //lsr NUM2+1 (szc)
|
|
num2h>>=1;
|
|
num2h&=0x7f;
|
|
// if (num2_neg) {
|
|
// num2h|=0x80;
|
|
// }
|
|
|
|
cc2=(num2l&1); // ror NUM2 (szc)
|
|
num2l>>=1;
|
|
num2l&=0x7f;
|
|
|
|
|
|
num2l|=(cc<<7);
|
|
cc=cc2;
|
|
|
|
if (cc==0) goto label_l2; // bcc L2
|
|
|
|
yy=aa; // tay (sz)
|
|
cc=0; // clc
|
|
aa=num1l; // lda NUM1 (sz)
|
|
aa=aa+cc+result2; // adc RESULT+2 (svzc)
|
|
cc=!!(aa&0x100);
|
|
aa&=0xff;
|
|
result2=aa; // sta RESULT+2
|
|
aa=yy; // tya
|
|
aa=aa+cc+num1h; // adc NUM1+1
|
|
cc=!!(aa&0x100);
|
|
aa=aa&0xff;
|
|
|
|
label_l2:
|
|
cc2=aa&1;
|
|
aa=aa>>1;
|
|
aa&=0x7f;
|
|
aa|=cc<<7;
|
|
cc=cc2; // ror A
|
|
|
|
cc2=result2&1;
|
|
result2=result2>>1;
|
|
result2&=0x7f;
|
|
result2|=(cc<<7);
|
|
cc=cc2; // ror result+2
|
|
|
|
cc2=result1&1;
|
|
result1=result1>>1;
|
|
result1&=0x7f;
|
|
result1|=cc<<7;
|
|
cc=cc2; // ror result+1
|
|
|
|
cc2=result0&1;
|
|
result0=result0>>1;
|
|
result0&=0x7f;
|
|
result0|=cc<<7;
|
|
cc=cc2; // ror result+0
|
|
|
|
xx--; // dex
|
|
if (xx!=0) goto label_l1; // bne L1
|
|
|
|
result3=aa&0xff; // sta result+3
|
|
|
|
|
|
if (debug) {
|
|
printf("RAW RESULT = %02x:%02x:%02x:%02x\n",
|
|
result3&0xff,result2&0xff,result1&0xff,result0&0xff);
|
|
}
|
|
|
|
if (negate&1) {
|
|
// printf("NEGATING!\n");
|
|
|
|
cc=0;
|
|
|
|
aa=0;
|
|
aa-=result0+cc;
|
|
cc=!!(aa&0x100);
|
|
result0=aa;
|
|
|
|
aa=0;
|
|
aa-=result1+cc;
|
|
cc=!!(aa&0x100);
|
|
result1=aa;
|
|
|
|
aa=0;
|
|
aa-=result2+cc;
|
|
cc=!!(aa&0x100);
|
|
result2=aa;
|
|
|
|
aa=0;
|
|
aa-=result3+cc;
|
|
cc=!!(aa&0x100);
|
|
result3=aa;
|
|
|
|
}
|
|
|
|
*z_i=result2&0xff;
|
|
*z_f=result1&0xff;
|
|
|
|
result3&=0xff;
|
|
result2&=0xff;
|
|
result1&=0xff;
|
|
result0&=0xff;
|
|
|
|
|
|
if (debug) {
|
|
printf("%02x:%02x * %02x:%02x = %02x:%02x:%02x:%02x\n",
|
|
num1h,num1l,y_i,y_f,
|
|
result3&0xff,result2&0xff,result1&0xff,result0&0xff);
|
|
|
|
// printf("%02x%02x * %02x%02x = %02x%02x%02x%02x\n",
|
|
// num1h,num1l,y_i,y_f,
|
|
// result3,result2,result1,result0);
|
|
}
|
|
|
|
int a2;
|
|
// int s1,s2;
|
|
// s1=(num1h<<8)|(num1l);
|
|
// s2=(y_i<<8)|(y_f);
|
|
a2=(result3<<24)|(result2<<16)|(result1<<8)|result0;
|
|
// printf("%d * %d = %d (0x%x)\n",s1,s2,a2,a2);
|
|
|
|
|
|
return a2;
|
|
|
|
}
|
|
#endif
|
|
|
|
|
|
#if FIXED_IMPLEMENTATION==2
|
|
|
|
// Description: Unsigned 16-bit multiplication with unsigned 32-bit result.
|
|
// Input: 16-bit unsigned value in T1
|
|
// 16-bit unsigned value in T2
|
|
// Carry=0: Re-use T1 from previous multiplication (faster)
|
|
// Carry=1: Set T1 (slower)
|
|
//
|
|
// Output: 32-bit unsigned value in PRODUCT
|
|
// Clobbered: PRODUCT, X, A, C
|
|
// Allocation setup: T1,T2 and PRODUCT preferably on Zero-page.
|
|
// square1_lo, square1_hi, square2_lo, square2_hi must be
|
|
// page aligned. Each table are 512 bytes. Total 2kb.
|
|
//
|
|
// Table generation: I:0..511
|
|
// square1_lo = <((I*I)/4)
|
|
// square1_hi = >((I*I)/4)
|
|
// square2_lo = <(((I-255)*(I-255))/4)
|
|
// square2_hi = >(((I-255)*(I-255))/4)
|
|
|
|
static unsigned char square1_lo[512];
|
|
static unsigned char square1_hi[512];
|
|
static unsigned char square2_lo[512];
|
|
static unsigned char square2_hi[512];
|
|
|
|
static int table_ready=0;
|
|
|
|
static void init_table(void) {
|
|
|
|
int i;
|
|
|
|
for(i=0;i<512;i++) {
|
|
square1_lo[i]=((i*i)/4)&0xff;
|
|
square1_hi[i]=(((i*i)/4)>>8)&0xff;
|
|
square2_lo[i]=( ((i-255)*(i-255))/4)&0xff;
|
|
square2_hi[i]=(( ((i-255)*(i-255))/4)>>8)&0xff;
|
|
// printf("%d %x:%x %x:%x\n",i,square1_hi[i],square1_lo[i],
|
|
// square2_hi[i],square2_lo[i]);
|
|
}
|
|
table_ready=1;
|
|
|
|
// 3 * 2
|
|
// 3+2 = 5
|
|
// 3-2 = 1
|
|
// (25 - 1) = 24/4 = 6
|
|
|
|
// int num1l,num2l,a1,a2;
|
|
|
|
// num1l=7;
|
|
// num2l=9;
|
|
|
|
// printf("Trying %d*%d\n",num1l,num2l);
|
|
// a1=square1_lo[num1l+num2l];
|
|
// printf("((%d+%d)^2)/4: %d\n",num1l,num2l,a1);
|
|
// a2=square2_lo[((~num1l)&0xff)+num2l];
|
|
// printf("((%d-%d)^2)/4: %d\n",num1l,num2l,a2);
|
|
|
|
// printf("%d*%d=%d\n",num1l,num2l,a1-a2);
|
|
|
|
}
|
|
|
|
static unsigned int product[4];
|
|
|
|
int fixed_mul_unsigned(int x_i,int x_f,
|
|
int y_i, int y_f,
|
|
int *z_i, int *z_f,
|
|
int debug) {
|
|
|
|
// <T1 * <T2 = AAaa
|
|
// <T1 * >T2 = BBbb
|
|
// >T1 * <T2 = CCcc
|
|
// >T1 * >T2 = DDdd
|
|
//
|
|
// AAaa
|
|
// BBbb
|
|
// CCcc
|
|
// + DDdd
|
|
// ----------
|
|
// PRODUCT!
|
|
|
|
// ; Setup T1 if changed
|
|
int c=0;
|
|
int a,x;
|
|
int sm1a,sm3a,sm5a,sm7a;
|
|
int sm2a,sm4a,sm6a,sm8a;
|
|
int sm1b,sm3b,sm5b,sm7b;
|
|
int sm2b,sm4b,sm6b,sm8b;
|
|
|
|
int _AA,_BB,_CC,_DD,_aa,_bb,_cc,_dd;
|
|
|
|
if (!table_ready) init_table();
|
|
|
|
// printf("\t\t\tMultiplying %2x:%2x * %2x:%2x\n",x_i,x_f,y_i,y_f);
|
|
|
|
/* Set up self-modifying code */
|
|
if (c==0) {
|
|
a=(x_f)&0xff; // lda T1+0 ; 3
|
|
sm1a=a; // sta sm1a+1 ; 3
|
|
sm3a=a; // sta sm3a+1 ; 3
|
|
sm5a=a; // sta sm5a+1 ; 3
|
|
sm7a=a; // sta sm7a+1 ; 3
|
|
a=(~a)&0xff; // eor #$ff ; 2
|
|
sm2a=a; // sta sm2a+1 ; 3
|
|
sm4a=a; // sta sm4a+1 ; 3
|
|
sm6a=a; // sta sm6a+1 ; 3
|
|
sm8a=a; // sta sm8a+1 ; 3
|
|
a=(x_i)&0xff; // lda T1+1 ; 3
|
|
sm1b=a; // sta sm1b+1 ; 3
|
|
sm3b=a; // sta sm3b+1 ; 3
|
|
sm5b=a; // sta sm5b+1 ; 3
|
|
sm7b=a; // sta sm7b+1 ; 3
|
|
a=(~a)&0xff; // eor #$ff ; 2
|
|
sm2b=a; // sta sm2b+1 ; 3
|
|
sm4b=a; // sta sm4b+1 ; 3
|
|
sm6b=a; // sta sm6b+1 ; 3
|
|
sm8b=a; // sta sm8b+1 ; 3
|
|
}
|
|
|
|
/* Perform <T1 * <T2 = AAaa */
|
|
x=(y_f)&0xff; // ldx T2+0 (low le) ; 3
|
|
c=1; // sec ; 2
|
|
//sm1a:
|
|
a=square1_lo[sm1a+x]; // lda square1_lo,x ; 4
|
|
//sm2a:
|
|
a+=~(square2_lo[sm2a+x])+c; // sbc square2_lo,x ; 4
|
|
c=!(a&0x100);
|
|
a&=0xff;
|
|
|
|
// printf("\t\t\t\ta=(%d+%d)^2/4=%d "
|
|
// "b=(%d+%d)^2/4=%d\n",
|
|
// sm1a,x,square1_lo[sm1a+x],
|
|
// sm2a,x,square2_lo[sm2a+x]);
|
|
product[0]=a; // sta PRODUCT+0 ; 3
|
|
_aa=a;
|
|
// printf("\t\t\t\ta-b aa=%2x\n",a);
|
|
//sm3a:
|
|
a=square1_hi[sm3a+x]; // lda square1_hi,x ; 4
|
|
//sm4a:
|
|
a+=(~(square2_hi[sm4a+x]))+c; // sbc square2_hi,x ; 4
|
|
c=!(a&0x100);
|
|
a&=0xff;
|
|
|
|
// printf("\t\t\t\ta=%d b=%d\n",square1_hi[sm3a+x],square2_hi[sm4a+x]);
|
|
|
|
_AA=a; // sta _AA+1 ; 3
|
|
// printf("\t\t\t\tAA=%2x\n",a);
|
|
|
|
/* Perform >T1_hi * <T2 = CCcc */
|
|
c=1; // sec ; 2
|
|
//sm1b:
|
|
a=square1_lo[sm1b+x]; // lda square1_lo,x ; 4
|
|
//sm2b:
|
|
a+=(~(square2_lo[sm2b+x]))+c; // sbc square2_lo,x ; 4
|
|
c=!(a&0x100);
|
|
a&=0xff;
|
|
|
|
_cc=a; // sta _cc+1 ; 3
|
|
//sm3b:
|
|
a=square1_hi[sm3b+x]; // lda square1_hi,x ; 4
|
|
//sm4b:
|
|
a+=(~(square2_hi[sm4b+x]))+c; // sbc square2_hi,x ; 4
|
|
c=!!(a&0x100);
|
|
a&=0xff;
|
|
_CC=a; // sta _CC+1 ; 3
|
|
|
|
/* Perform <T1 * >T2 = BBbb */
|
|
x=(y_i)&0xff; // ldx T2+1 ; 3
|
|
c=1; // sec ; 2
|
|
//sm5a:
|
|
a=square1_lo[sm5a+x]; // lda square1_lo,x ; 4
|
|
//sm6a:
|
|
a+=(~(square2_lo[sm6a+x]))+c; // sbc square2_lo,x ; 4
|
|
c=!(a&0x100);
|
|
a&=0xff;
|
|
_bb=a; // sta _bb+1 ; 3
|
|
// printf("\t\t\t\tbb=%x c=%d\n",_bb,c);
|
|
//sm7a:
|
|
a=square1_hi[sm7a+x]; // lda square1_hi,x ; 4
|
|
//sm8a:
|
|
a+=(~(square2_hi[sm8a+x]))+c; // sbc square2_hi,x ; 4
|
|
c=!(a&0x100);
|
|
a&=0xff;
|
|
_BB=a; // sta _BB+1
|
|
|
|
/* Perform >T1 * >T2 = DDdd */
|
|
c=1; // sec ; 2
|
|
//sm5b:
|
|
a=square1_lo[sm5b+x]; // lda square1_lo,x ; 4
|
|
//sm6b:
|
|
a+=(~(square2_lo[sm6b+x]))+c; // sbc square2_lo,x ; 4
|
|
c=!(a&0x100);
|
|
a&=0xff;
|
|
_dd=a; // sta _dd+1 ; 3
|
|
//sm7b:
|
|
a=square1_hi[sm7b+x]; // lda square1_hi,x ; 4
|
|
//sm8b:
|
|
a+=(~(square2_hi[sm8b+x]))+c; // sbc square2_hi,x ; 4
|
|
c=!(a&0x100);
|
|
a&=0xff;
|
|
|
|
product[3]=a; // sta PRODUCT+3 ; 3
|
|
_DD=a;
|
|
|
|
/*********************************************/
|
|
/* Add the separate multiplications together */
|
|
/*********************************************/
|
|
|
|
// product[0]=_aa;
|
|
if (debug) printf("product[0]=0.%02x\n",_aa);
|
|
|
|
// product[1]=_AA+_bb+(_cc)
|
|
if (debug) printf("product[1]=%02x+%02x+0=",_AA,_bb);
|
|
|
|
c=0; // clc ; 2
|
|
//_AA:
|
|
a=_AA; // lda #0 ; 2
|
|
//_bb:
|
|
a+=(c+_bb); // adc #0 ; 2
|
|
c=!!(a&0x100);
|
|
a&=0xff;
|
|
product[1]=a; // sta PRODUCT+1 ; 3
|
|
if (debug) printf("%x.%02x\n",c,a);
|
|
|
|
// product[2]=_BB+_CC+c
|
|
if (debug) printf("product[2]=%02x+%02x+%d=",_BB,_CC,c);
|
|
//_BB:
|
|
a=_BB; // lda #0 ; 2
|
|
//_CC:
|
|
a+=(c+_CC); // adc #0 ; 2
|
|
c=!!(a&0x100);
|
|
a&=0xff;
|
|
product[2]=a; // sta PRODUCT+2 ; 3
|
|
if (debug) printf("%x.%02x\n",c,a);
|
|
|
|
// product[3]=_DD+c
|
|
if (debug) printf("product[3]=%02x+%d=",_DD,c);
|
|
if (c==0) goto urgh2; // bcc :+ ; 2nt/3
|
|
product[3]++; // inc PRODUCT+3 ; 5
|
|
product[3]&=0xff;
|
|
c=0; // clc ; 2
|
|
urgh2:
|
|
if (debug) printf("%x.%02x\n",c,product[3]);
|
|
// product[1]=_AA+_bb+_cc
|
|
if (debug) printf("product[1]=%02x+%02x+%d=",product[1],_cc,c);
|
|
//_cc:
|
|
a=_cc; // lda #0 ; 2
|
|
a+=c+product[1]; // adc PRODUCT+1 ; 3
|
|
c=!!(a&0x100);
|
|
a&=0xff;
|
|
product[1]=a; // sta PRODUCT+1 ; 3
|
|
if (debug) printf("%x.%02x\n",c,product[1]);
|
|
|
|
// product[2]=_BB+_CC+_dd+c
|
|
if (debug) printf("product[2]=%02x+%02x+%d=",product[2],_dd,c);
|
|
//_dd:
|
|
a=_dd; // lda #0 ; 2
|
|
a+=c+product[2]; // adc PRODUCT+2 ; 3
|
|
c=!!(a&0x100);
|
|
a&=0xff;
|
|
product[2]=a; // sta PRODUCT+2 ; 3
|
|
if (debug) printf("%x.%02x\n",c,product[2]);
|
|
|
|
// product[3]=_DD+c
|
|
if (debug) printf("product[3]=%02x+%d=",product[3],c);
|
|
if (c==0) goto urgh; // bcc :+ ; 2nt/3
|
|
product[3]++; // inc PRODUCT+3 ; 5
|
|
product[3]&=0xff;
|
|
urgh:
|
|
if (debug) printf("%x.%02x\n",c,product[3]);
|
|
*z_i=product[1];
|
|
*z_f=product[0];
|
|
|
|
// printf("Result=%02x:%02x\n",*z_i,*z_f);
|
|
|
|
if (debug) {
|
|
printf(" AAaa %02x:%02x\n",_AA,_aa);
|
|
printf(" BBbb %02x:%02x\n",_BB,_bb);
|
|
printf(" CCcc %02x:%02x\n",_CC,_cc);
|
|
printf("DDdd %02x:%02x\n",_DD,_dd);
|
|
}
|
|
|
|
return (product[3]<<24)|(product[2]<<16)|(product[1]<<8)|product[0];
|
|
// rts ; 6
|
|
}
|
|
|
|
/* signed */
|
|
int fixed_mul(int x_i,int x_f,
|
|
int y_i, int y_f,
|
|
int *z_i, int *z_f,
|
|
int debug) {
|
|
|
|
int a,c;
|
|
|
|
fixed_mul_unsigned(x_i,x_f,y_i,y_f,z_i,z_f,debug);
|
|
// jsr multiply_16bit_unsigned ; 6
|
|
|
|
a=(x_i&0xff); // lda T1+1 ; 3
|
|
if ((a&0x80)==0) goto x_positive; // bpl :+ ; 3/2nt
|
|
if (debug) printf("Before: %02x:%02x:%02x:%02x\n",product[3],product[2],product[1],product[0]);
|
|
|
|
// a=0xff; // lda #$ff ; 2
|
|
// c=1; // sec ; 2
|
|
// a=product[0]^a; // eor product[0]; 3
|
|
// a&=0xff;
|
|
// a+=0+c; // adc #0 ; 2
|
|
// c=!!(a&0x100);
|
|
// a&=0xff;
|
|
// product[0]=a; // sta product[0]; 3
|
|
|
|
|
|
// a=0xff; // lda #$ff ; 2
|
|
// a=product[1]^a; // eor product[0]; 3
|
|
// a&=0xff;
|
|
// a+=0+c; // adc #0 ; 2
|
|
// c=!!(a&0x100);
|
|
// a&=0xff;
|
|
// product[1]=a; // sta product[0]; 3
|
|
|
|
|
|
// a=0xff;
|
|
// a=product[2]^a; // eor product[0]; 3
|
|
// a&=0xff;
|
|
// a+=0+c; // adc #0 ; 2
|
|
// c=!!(a&0x100);
|
|
// a&=0xff;
|
|
// product[2]=a; // sta product[0]; 3
|
|
|
|
|
|
// a=0xff;
|
|
// a=product[3]^a; // eor product[0]; 3
|
|
// a&=0xff;
|
|
// a+=0+c; // adc #0 ; 2
|
|
// c=!!(a&0x100);
|
|
// a&=0xff;
|
|
// product[3]=a; // sta product[0]; 3
|
|
|
|
// product[1]^=a;
|
|
// product[2]^=a;
|
|
// product[3]^=a;
|
|
|
|
|
|
c=1; // sec ; 2
|
|
a=product[2]; // lda PRODUCT+2 ; 3
|
|
a+=(~y_f)+c; // sbc T2+0 ; 3
|
|
c=!(a&0x100);
|
|
a&=0xff;
|
|
product[2]=a; // sta PRODUCT+2 ; 3
|
|
a=product[3]; // lda PRODUCT+3 ; 3
|
|
a+=(~y_i)+c; // sbc T2+1 ; 3
|
|
c=!(a&0x100);
|
|
a&=0xff;
|
|
product[3]=a; // sta PRODUCT+3 ; 3
|
|
if (debug) printf("After: %02x:%02x:%02x:%02x\n",product[3],product[2],product[1],product[0]);
|
|
|
|
x_positive:
|
|
|
|
a=(y_i&0xff); // lda T2+1 ; 3
|
|
if ((a&0x80)==0) goto y_positive; // bpl :+ ; 3/2nt
|
|
|
|
if (debug) printf("Before: %02x:%02x:%02x:%02x\n",product[3],product[2],product[1],product[0]);
|
|
// a=0xff; // lda #$ff ; 2
|
|
// c=1; // sec ; 2
|
|
// a=product[0]^a; // eor product[0]; 3
|
|
// a&=0xff;
|
|
// a+=0+c; // adc #0 ; 2
|
|
// c=!!(a&0x100);
|
|
// a&=0xff;
|
|
// product[0]=a; // sta product[0]; 3
|
|
|
|
|
|
// a=0xff; // lda #$ff ; 2
|
|
// a=product[1]^a; // eor product[0]; 3
|
|
// a&=0xff;
|
|
// a+=0+c; // adc #0 ; 2
|
|
// c=!!(a&0x100);
|
|
// a&=0xff;
|
|
// product[1]=a; // sta product[0]; 3
|
|
|
|
|
|
// a=0xff;
|
|
// a=product[2]^a; // eor product[0]; 3
|
|
// a&=0xff;
|
|
// a+=0+c; // adc #0 ; 2
|
|
// c=!!(a&0x100);
|
|
// a&=0xff;
|
|
// product[2]=a; // sta product[0]; 3
|
|
|
|
|
|
// a=0xff;
|
|
// a=product[3]^a; // eor product[0]; 3
|
|
// a&=0xff;
|
|
// a+=0+c; // adc #0 ; 2
|
|
// c=!!(a&0x100);
|
|
// a&=0xff;
|
|
// product[3]=a; // sta product[0]; 3
|
|
|
|
|
|
c=1; // sec ; 2
|
|
a=product[2]; // lda PRODUCT+2 ; 3
|
|
a+=(~x_f)+c; // sbc T1+0 ; 3
|
|
c=!(a&0x100);
|
|
a&=0xff;
|
|
product[2]=a; // sta PRODUCT+2 ; 3
|
|
a=product[3]; // lda PRODUCT+3 ; 3
|
|
a+=(~x_i)+c; // sbc T1+1 ; 3
|
|
c=!(a&0x100);
|
|
a&=0xff;
|
|
product[3]=a; // sta PRODUCT+3 ; 3
|
|
|
|
if (debug) printf("After: %02x:%02x:%02x:%02x\n",product[3],product[2],product[1],product[0]);
|
|
|
|
y_positive:
|
|
*z_i=product[2];
|
|
*z_f=product[1];
|
|
|
|
return (product[3]<<24)|(product[2]<<16)|(product[1]<<8)|product[0];
|
|
// rts ; 6
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if FIXED_IMPLEMENTATION==3
|
|
|
|
// Description: Unsigned 16-bit multiplication with unsigned 32-bit result.
|
|
// Input: 16-bit unsigned value in T1
|
|
// 16-bit unsigned value in T2
|
|
// Carry=0: Re-use T1 from previous multiplication (faster)
|
|
// Carry=1: Set T1 (slower)
|
|
//
|
|
// Output: 32-bit unsigned value in PRODUCT
|
|
// Clobbered: PRODUCT, X, A, C
|
|
// Allocation setup: T1,T2 and PRODUCT preferably on Zero-page.
|
|
// square1_lo, square1_hi, square2_lo, square2_hi must be
|
|
// page aligned. Each table are 512 bytes. Total 2kb.
|
|
//
|
|
// Table generation: I:0..511
|
|
// square1_lo = <((I*I)/4)
|
|
// square1_hi = >((I*I)/4)
|
|
// square2_lo = <(((I-255)*(I-255))/4)
|
|
// square2_hi = >(((I-255)*(I-255))/4)
|
|
|
|
static unsigned char square1_lo[512];
|
|
static unsigned char square1_hi[512];
|
|
static unsigned char square2_lo[512];
|
|
static unsigned char square2_hi[512];
|
|
|
|
static int table_ready=0;
|
|
|
|
static void init_table(void) {
|
|
|
|
int i;
|
|
|
|
for(i=0;i<512;i++) {
|
|
square1_lo[i]=((i*i)/4)&0xff;
|
|
square1_hi[i]=(((i*i)/4)>>8)&0xff;
|
|
square2_lo[i]=( ((i-255)*(i-255))/4)&0xff;
|
|
square2_hi[i]=(( ((i-255)*(i-255))/4)>>8)&0xff;
|
|
// printf("%d %x:%x %x:%x\n",i,square1_hi[i],square1_lo[i],
|
|
// square2_hi[i],square2_lo[i]);
|
|
}
|
|
table_ready=1;
|
|
|
|
// 3 * 2
|
|
// 3+2 = 5
|
|
// 3-2 = 1
|
|
// (25 - 1) = 24/4 = 6
|
|
|
|
// int num1l,num2l,a1,a2;
|
|
|
|
// num1l=7;
|
|
// num2l=9;
|
|
|
|
// printf("Trying %d*%d\n",num1l,num2l);
|
|
// a1=square1_lo[num1l+num2l];
|
|
// printf("((%d+%d)^2)/4: %d\n",num1l,num2l,a1);
|
|
// a2=square2_lo[((~num1l)&0xff)+num2l];
|
|
// printf("((%d-%d)^2)/4: %d\n",num1l,num2l,a2);
|
|
|
|
// printf("%d*%d=%d\n",num1l,num2l,a1-a2);
|
|
|
|
}
|
|
|
|
static unsigned int product[4];
|
|
|
|
int fixed_mul(int x_i,int x_f,
|
|
int y_i, int y_f,
|
|
int *z_i, int *z_f,
|
|
int debug) {
|
|
|
|
//int fixed_mul_unsigned(int x_i,int x_f,
|
|
// int y_i, int y_f,
|
|
// int debug) {
|
|
|
|
// <T1 * <T2 = AAaa
|
|
// <T1 * >T2 = BBbb
|
|
// >T1 * <T2 = CCcc
|
|
// >T1 * >T2 = DDdd
|
|
//
|
|
// AAaa
|
|
// BBbb
|
|
// CCcc
|
|
// + DDdd
|
|
// ----------
|
|
// PRODUCT!
|
|
|
|
// ; Setup T1 if changed
|
|
int c=0;
|
|
int a,x;
|
|
int sm1a,sm3a,sm5a,sm7a;
|
|
int sm2a,sm4a,sm6a,sm8a;
|
|
int sm1b,sm3b,sm5b;//,sm7b;
|
|
int sm2b,sm4b,sm6b;//,sm8b;
|
|
|
|
int _AA,_BB,_CC;//,_DD;
|
|
int /* _aa,*/ _bb,_cc,_dd;
|
|
|
|
if (!table_ready) init_table();
|
|
|
|
// printf("\t\t\tMultiplying %2x:%2x * %2x:%2x\n",x_i,x_f,y_i,y_f);
|
|
|
|
/* Set up self-modifying code */
|
|
if (c==0) {
|
|
a=(x_f)&0xff; // lda T1+0 ; 3
|
|
sm1a=a; // sta sm1a+1 ; 3
|
|
sm3a=a; // sta sm3a+1 ; 3
|
|
sm5a=a; // sta sm5a+1 ; 3
|
|
sm7a=a; // sta sm7a+1 ; 3
|
|
a=(~a)&0xff; // eor #$ff ; 2
|
|
sm2a=a; // sta sm2a+1 ; 3
|
|
sm4a=a; // sta sm4a+1 ; 3
|
|
sm6a=a; // sta sm6a+1 ; 3
|
|
sm8a=a; // sta sm8a+1 ; 3
|
|
a=(x_i)&0xff; // lda T1+1 ; 3
|
|
sm1b=a; // sta sm1b+1 ; 3
|
|
sm3b=a; // sta sm3b+1 ; 3
|
|
sm5b=a; // sta sm5b+1 ; 3
|
|
// sm7b=a; // sta sm7b+1 ; 3
|
|
a=(~a)&0xff; // eor #$ff ; 2
|
|
sm2b=a; // sta sm2b+1 ; 3
|
|
sm4b=a; // sta sm4b+1 ; 3
|
|
sm6b=a; // sta sm6b+1 ; 3
|
|
// sm8b=a; // sta sm8b+1 ; 3
|
|
}
|
|
|
|
/* Perform <T1 * <T2 = AAaa */
|
|
x=(y_f)&0xff; // ldx T2+0 (low le) ; 3
|
|
c=1; // sec ; 2
|
|
//sm1a:
|
|
a=square1_lo[sm1a+x]; // lda square1_lo,x ; 4
|
|
//sm2a:
|
|
a+=~(square2_lo[sm2a+x])+c; // sbc square2_lo,x ; 4
|
|
c=!(a&0x100);
|
|
a&=0xff;
|
|
|
|
// printf("\t\t\t\ta=(%d+%d)^2/4=%d "
|
|
// "b=(%d+%d)^2/4=%d\n",
|
|
// sm1a,x,square1_lo[sm1a+x],
|
|
// sm2a,x,square2_lo[sm2a+x]);
|
|
// product[0]=a; // sta PRODUCT+0 ; 3
|
|
// _aa=a;
|
|
// printf("\t\t\t\ta-b aa=%2x\n",a);
|
|
//sm3a:
|
|
a=square1_hi[sm3a+x]; // lda square1_hi,x ; 4
|
|
//sm4a:
|
|
a+=(~(square2_hi[sm4a+x]))+c; // sbc square2_hi,x ; 4
|
|
c=!(a&0x100);
|
|
a&=0xff;
|
|
|
|
// printf("\t\t\t\ta=%d b=%d\n",square1_hi[sm3a+x],square2_hi[sm4a+x]);
|
|
|
|
_AA=a; // sta _AA+1 ; 3
|
|
// printf("\t\t\t\tAA=%2x\n",a);
|
|
|
|
/* Perform >T1_hi * <T2 = CCcc */
|
|
c=1; // sec ; 2
|
|
//sm1b:
|
|
a=square1_lo[sm1b+x]; // lda square1_lo,x ; 4
|
|
//sm2b:
|
|
a+=(~(square2_lo[sm2b+x]))+c; // sbc square2_lo,x ; 4
|
|
c=!(a&0x100);
|
|
a&=0xff;
|
|
|
|
_cc=a; // sta _cc+1 ; 3
|
|
//sm3b:
|
|
a=square1_hi[sm3b+x]; // lda square1_hi,x ; 4
|
|
//sm4b:
|
|
a+=(~(square2_hi[sm4b+x]))+c; // sbc square2_hi,x ; 4
|
|
c=!!(a&0x100);
|
|
a&=0xff;
|
|
_CC=a; // sta _CC+1 ; 3
|
|
|
|
/* Perform <T1 * >T2 = BBbb */
|
|
x=(y_i)&0xff; // ldx T2+1 ; 3
|
|
c=1; // sec ; 2
|
|
//sm5a:
|
|
a=square1_lo[sm5a+x]; // lda square1_lo,x ; 4
|
|
//sm6a:
|
|
a+=(~(square2_lo[sm6a+x]))+c; // sbc square2_lo,x ; 4
|
|
c=!(a&0x100);
|
|
a&=0xff;
|
|
_bb=a; // sta _bb+1 ; 3
|
|
// printf("\t\t\t\tbb=%x c=%d\n",_bb,c);
|
|
//sm7a:
|
|
a=square1_hi[sm7a+x]; // lda square1_hi,x ; 4
|
|
//sm8a:
|
|
a+=(~(square2_hi[sm8a+x]))+c; // sbc square2_hi,x ; 4
|
|
c=!(a&0x100);
|
|
a&=0xff;
|
|
_BB=a; // sta _BB+1
|
|
|
|
/* Perform >T1 * >T2 = DDdd */
|
|
c=1; // sec ; 2
|
|
//sm5b:
|
|
a=square1_lo[sm5b+x]; // lda square1_lo,x ; 4
|
|
//sm6b:
|
|
a+=(~(square2_lo[sm6b+x]))+c; // sbc square2_lo,x ; 4
|
|
c=!(a&0x100);
|
|
a&=0xff;
|
|
_dd=a; // sta _dd+1 ; 3
|
|
//sm7b:
|
|
// a=square1_hi[sm7b+x]; // lda square1_hi,x ; 4
|
|
//sm8b:
|
|
// a+=(~(square2_hi[sm8b+x]))+c; // sbc square2_hi,x ; 4
|
|
// c=!(a&0x100);
|
|
// a&=0xff;
|
|
|
|
// product[3]=a; // sta PRODUCT+3 ; 3
|
|
// _DD=a;
|
|
|
|
/*********************************************/
|
|
/* Add the separate multiplications together */
|
|
/*********************************************/
|
|
|
|
// product[0]=_aa;
|
|
// if (debug) printf("product[0]=0.%02x\n",_aa);
|
|
|
|
// product[1]=_AA+_bb+(_cc)
|
|
if (debug) printf("product[1]=%02x+%02x+0=",_AA,_bb);
|
|
|
|
c=0; // clc ; 2
|
|
//_AA:
|
|
a=_AA; // lda #0 ; 2
|
|
//_bb:
|
|
a+=(c+_bb); // adc #0 ; 2
|
|
c=!!(a&0x100);
|
|
a&=0xff;
|
|
product[1]=a; // sta PRODUCT+1 ; 3
|
|
if (debug) printf("%x.%02x\n",c,a);
|
|
|
|
// product[2]=_BB+_CC+c
|
|
if (debug) printf("product[2]=%02x+%02x+%d=",_BB,_CC,c);
|
|
//_BB:
|
|
a=_BB; // lda #0 ; 2
|
|
//_CC:
|
|
a+=(c+_CC); // adc #0 ; 2
|
|
c=!!(a&0x100);
|
|
a&=0xff;
|
|
product[2]=a; // sta PRODUCT+2 ; 3
|
|
if (debug) printf("%x.%02x\n",c,a);
|
|
|
|
// product[3]=_DD+c
|
|
// if (debug) printf("product[3]=%02x+%d=",_DD,c);
|
|
// if (c==0) goto urgh2; // bcc :+ ; 2nt/3
|
|
// product[3]++; // inc PRODUCT+3 ; 5
|
|
// product[3]&=0xff;
|
|
c=0; // clc ; 2
|
|
//urgh2:
|
|
// if (debug) printf("%x.%02x\n",c,product[3]);
|
|
// product[1]=_AA+_bb+_cc
|
|
// if (debug) printf("product[1]=%02x+%02x+%d=",product[1],_cc,c);
|
|
//_cc:
|
|
a=_cc; // lda #0 ; 2
|
|
a+=c+product[1]; // adc PRODUCT+1 ; 3
|
|
c=!!(a&0x100);
|
|
a&=0xff;
|
|
product[1]=a; // sta PRODUCT+1 ; 3
|
|
if (debug) printf("%x.%02x\n",c,product[1]);
|
|
|
|
// product[2]=_BB+_CC+_dd+c
|
|
if (debug) printf("product[2]=%02x+%02x+%d=",product[2],_dd,c);
|
|
//_dd:
|
|
a=_dd; // lda #0 ; 2
|
|
a+=c+product[2]; // adc PRODUCT+2 ; 3
|
|
c=!!(a&0x100);
|
|
a&=0xff;
|
|
product[2]=a; // sta PRODUCT+2 ; 3
|
|
if (debug) printf("%x.%02x\n",c,product[2]);
|
|
|
|
// product[3]=_DD+c
|
|
// if (debug) printf("product[3]=%02x+%d=",product[3],c);
|
|
// if (c==0) goto urgh; // bcc :+ ; 2nt/3
|
|
// product[3]++; // inc PRODUCT+3 ; 5
|
|
// product[3]&=0xff;
|
|
//urgh:
|
|
// if (debug) printf("%x.%02x\n",c,product[3]);
|
|
|
|
// printf("Result=%02x:%02x\n",*z_i,*z_f);
|
|
|
|
// if (debug) {
|
|
// printf(" AAaa %02x:%02x\n",_AA,_aa);
|
|
// printf(" BBbb %02x:%02x\n",_BB,_bb);
|
|
// printf(" CCcc %02x:%02x\n",_CC,_cc);
|
|
// printf("DDdd %02x:%02x\n",_DD,_dd);
|
|
// }
|
|
|
|
// return 0;
|
|
//(product[3]<<24)|(product[2]<<16)|(product[1]<<8)|product[0];
|
|
// rts ; 6
|
|
//}
|
|
|
|
/* signed */
|
|
//int fixed_mul(int x_i,int x_f,
|
|
// int y_i, int y_f,
|
|
// int *z_i, int *z_f,
|
|
// int debug) {
|
|
|
|
// int a,c;
|
|
|
|
// fixed_mul_unsigned(x_i,x_f,y_i,y_f,debug);
|
|
// jsr multiply_16bit_unsigned ; 6
|
|
|
|
a=(x_i&0xff); // lda T1+1 ; 3
|
|
if ((a&0x80)==0) goto x_positive; // bpl :+ ; 3/2nt
|
|
if (debug) printf("Before: %02x:%02x:%02x:%02x\n",product[3],product[2],product[1],product[0]);
|
|
|
|
c=1; // sec ; 2
|
|
a=product[2]; // lda PRODUCT+2 ; 3
|
|
a+=(~y_f)+c; // sbc T2+0 ; 3
|
|
c=!(a&0x100);
|
|
a&=0xff;
|
|
product[2]=a; // sta PRODUCT+2 ; 3
|
|
// a=product[3]; // lda PRODUCT+3 ; 3
|
|
// a+=(~y_i)+c; // sbc T2+1 ; 3
|
|
// c=!(a&0x100);
|
|
// a&=0xff;
|
|
// product[3]=a; // sta PRODUCT+3 ; 3
|
|
if (debug) printf("After: %02x:%02x:%02x:%02x\n",product[3],product[2],product[1],product[0]);
|
|
|
|
x_positive:
|
|
|
|
a=(y_i&0xff); // lda T2+1 ; 3
|
|
if ((a&0x80)==0) goto y_positive; // bpl :+ ; 3/2nt
|
|
|
|
if (debug) printf("Before: %02x:%02x:%02x:%02x\n",product[3],product[2],product[1],product[0]);
|
|
|
|
c=1; // sec ; 2
|
|
a=product[2]; // lda PRODUCT+2 ; 3
|
|
a+=(~x_f)+c; // sbc T1+0 ; 3
|
|
c=!(a&0x100);
|
|
a&=0xff;
|
|
product[2]=a; // sta PRODUCT+2 ; 3
|
|
// a=product[3]; // lda PRODUCT+3 ; 3
|
|
// a+=(~x_i)+c; // sbc T1+1 ; 3
|
|
// c=!(a&0x100);
|
|
// a&=0xff;
|
|
// product[3]=a; // sta PRODUCT+3 ; 3
|
|
|
|
if (debug) printf("After: %02x:%02x:%02x:%02x\n",product[3],product[2],product[1],product[0]);
|
|
|
|
y_positive:
|
|
*z_i=product[2];
|
|
*z_f=product[1];
|
|
|
|
// return (product[3]<<24)|(product[2]<<16)|(product[1]<<8)|product[0];
|
|
return 0;
|
|
// rts ; 6
|
|
}
|
|
|
|
#endif
|
|
|
|
int main(int argc, char **argv) {
|
|
|
|
int a_i,b_i,c_i;
|
|
int a_f,b_f,c_f;
|
|
// short x,y;
|
|
int l,k,i,j;
|
|
|
|
printf("Some tests\n");
|
|
#if 0
|
|
x=-32768;
|
|
y=3;
|
|
|
|
a_i=x>>8;
|
|
a_f=x&0xff;
|
|
b_i=y>>8;
|
|
b_f=y&0xff;
|
|
|
|
printf("\tTrying %d*%d=%d (0x%x)\n",x,y,x*y,x*y);
|
|
k=fixed_mul(a_i,a_f,b_i,b_f,&c_i,&c_f,0);
|
|
if (k!=x*y) {
|
|
printf("\t\tError! got %d (0x%x)\n",k,k);
|
|
exit(1);
|
|
}
|
|
else {
|
|
printf("\t\tProperly calculated %d\n",k);
|
|
}
|
|
|
|
a_i=0x0;
|
|
a_f=0x7;
|
|
|
|
b_i=0x0;
|
|
b_f=0x9;
|
|
|
|
x=7;
|
|
y=9;
|
|
|
|
printf("\tTrying %d*%d=%d (0x%x)\n",x,y,x*y,x*y);
|
|
k=fixed_mul(a_i,a_f,b_i,b_f,&c_i,&c_f,0);
|
|
if (k!=x*y) {
|
|
printf("\t\tError! got %d (0x%x)\n",k,k);
|
|
exit(1);
|
|
}
|
|
else {
|
|
printf("\t\tProperly calculated %d (0x%x)\n",k,k);
|
|
}
|
|
|
|
a_i=0x0;
|
|
a_f=0x2;
|
|
|
|
b_i=0x0;
|
|
b_f=0x3;
|
|
|
|
x=2;
|
|
y=3;
|
|
|
|
printf("\tTrying %d*%d=%d (0x%x)\n",x,y,x*y,x*y);
|
|
k=fixed_mul(a_i,a_f,b_i,b_f,&c_i,&c_f,0);
|
|
if (k!=x*y) {
|
|
printf("\t\tError! got %d (0x%x)\n",k,k);
|
|
exit(1);
|
|
}
|
|
else {
|
|
printf("\t\tProperly calculated %d (0x%x)\n",k,k);
|
|
}
|
|
|
|
a_i=0xff;
|
|
a_f=0xff;
|
|
|
|
b_i=0xff;
|
|
b_f=0xff;
|
|
|
|
x=0xffff;
|
|
y=0xffff;
|
|
|
|
printf("\tTrying %d*%d=%d (0x%x)\n",x,y,x*y,x*y);
|
|
k=fixed_mul(a_i,a_f,b_i,b_f,&c_i,&c_f,0);
|
|
if (k!=x*y) {
|
|
printf("\t\tError! got %d (0x%x)\n",k,k);
|
|
exit(1);
|
|
}
|
|
else {
|
|
printf("\t\tProperly calculated %d (0x%x)\n",k,k);
|
|
}
|
|
|
|
a_i=0xff;
|
|
a_f=0xff;
|
|
|
|
b_i=0x00;
|
|
b_f=0x01;
|
|
|
|
x=0xffff;
|
|
y=0x1;
|
|
|
|
printf("\tTrying %d*%d=%d (0x%x)\n",x,y,x*y,x*y);
|
|
k=fixed_mul(a_i,a_f,b_i,b_f,&c_i,&c_f,0);
|
|
if (k!=x*y) {
|
|
printf("\t\tError! got %d (0x%x)\n",k,k);
|
|
exit(1);
|
|
}
|
|
else {
|
|
printf("\t\tProperly calculated %d (0x%x)\n",k,k);
|
|
}
|
|
|
|
a_i=0x00;
|
|
a_f=0xff;
|
|
|
|
b_i=0x00;
|
|
b_f=0x01;
|
|
|
|
x=0xff;
|
|
y=0x1;
|
|
|
|
printf("\tTrying %d*%d=%d (0x%x)\n",x,y,x*y,x*y);
|
|
k=fixed_mul(a_i,a_f,b_i,b_f,&c_i,&c_f,0);
|
|
if (k!=x*y) {
|
|
printf("\t\tError! got %d (0x%x)\n",k,k);
|
|
exit(1);
|
|
}
|
|
else {
|
|
printf("\t\tProperly calculated %d (0x%x)\n",k,k);
|
|
}
|
|
|
|
for(i=-32768;i<32768;i++) {
|
|
for(j=-32768;j<32768;j++) {
|
|
a_i=i>>8;
|
|
a_f=i&0xff;
|
|
b_i=j>>8;
|
|
b_f=j&0xff;
|
|
|
|
k=fixed_mul(a_i,a_f,b_i,b_f,&c_i,&c_f,0);
|
|
|
|
if (k!=i*j) {
|
|
printf("WRONG! %x*%x = %x not %x\n",
|
|
i,j,i*j,k);
|
|
printf(" %d * %d = %d not %d\n",i,j,i*j,k);
|
|
exit(1);
|
|
}
|
|
}
|
|
if (i%256==0) printf("%x\n",i);
|
|
}
|
|
#endif
|
|
|
|
for(i=-32768;i<32768;i++) {
|
|
for(j=-32768;j<32768;j++) {
|
|
a_i=i>>8;
|
|
a_f=i&0xff;
|
|
b_i=j>>8;
|
|
b_f=j&0xff;
|
|
|
|
fixed_mul(a_i,a_f,b_i,b_f,&c_i,&c_f,0);
|
|
k=((i*j)>>8)&0xffff;
|
|
l=(c_i<<8)|(c_f);
|
|
|
|
if (k!=l) {
|
|
printf("WRONG! %x*%x = %x, %x not %02x:%02x\n",
|
|
i,j,i*j,k,c_i,c_f);
|
|
printf(" %d * %d = %d not %d\n",i,j,l,k);
|
|
exit(1);
|
|
}
|
|
}
|
|
if (i%256==0) printf("%x\n",i);
|
|
}
|
|
|
|
|
|
return 0;
|
|
}
|
|
|
|
|