\\======================================================================================== \\ efp.gp \\ Copyright (C) 2003-2019 Makoto Kamada \\ \\ This file is part of the XEiJ (X68000 Emulator in Java). \\ You can use, modify and redistribute the XEiJ if the conditions are met. \\ Read the XEiJ License for more details. \\ https://stdkmd.net/xeij/ \\======================================================================================== \\---------------------------------------------------------------------------------------- \\ 設定 \\---------------------------------------------------------------------------------------- \\テストプログラム TEST_S="fputest.s"; \\ソースファイル TEST_X="fputest.x"; \\実行ファイル TEST_LOG="fputest.log"; \\ログファイル TEST_S_TMP=Str(TEST_S,".tmp"); TEST_S_BAK=Str(TEST_S,".bak~"); TEST_COMMENT=1; \\1=ソースファイルのデータにコメントを付ける if(type(TEST_HARD_FSGLDIV)=="t_POL",TEST_HARD_FSGLDIV=0); \\1=MC68882のFSGLDIVのバグを再現する if(type(TEST_HARD_FSGLMUL)=="t_POL",TEST_HARD_FSGLMUL=0); \\1=MC68882のFSGLMULのバグを再現する \\有効桁数 \p 400 \\---------------------------------------------------------------------------------------- \\ 定数 \\---------------------------------------------------------------------------------------- \\精度を変更できるように数学定数をコピーしないことにした LOG_ZERO=1e-99999; \\abs(x)<=LOG_ZEROのときx≒0と見なしてlog(x)の計算を避ける \\FPUの種類 MC68881=1<<0; MC68882=1<<1; MC68040=1<<2; FPSP040=1<<3; MC68060=1<<4; FPSP060=1<<5; \\---------------------------------------------------------------------------------------- \\ ファイル操作 \\---------------------------------------------------------------------------------------- \\writef(file,format,args...) \\ fileへフォーマット出力する writef(file,format,args[..])=write1(file,call(Strprintf,[format,args])); \\---------------------------------------------------------------------------------------- \\ 数値操作 \\---------------------------------------------------------------------------------------- \\y=realtofrac(x) \\ 実数(t_REAL)xを有理数(t_FRAC)または整数(t_INT)に変換する \\ 現在の精度でx==yになる \\ 分母が2の累乗になるとは限らない realtofrac(x)=if(type(x)=="t_REAL",bestappr(x,2^default(realbitprecision)),x); \\y=realnextdown(x) \\ 現在の精度で実数xよりも僅かに小さい数を返す realnextdown(x)={ my(y,m); if(x<0,return(-realnextup(-x))); x*=1.0; if(x<LOG_ZERO,return(-LOG_ZERO)); y=x-2.0^(2+floor(log(x)/log(2))-default(realbitprecision)); \\誤差を考慮して小さめの数を元に数に寄せる if(x==y,error("realnextdown(",x,")")); m=(x+y)*0.5; while((y<m)&&(m<x), \\通常は1回、2の累乗のときは2回 y=m; m=(x+y)*0.5); y } \\y=realnextup(x) \\ 現在の精度で実数xよりも僅かに大きい数を返す realnextup(x)={ my(y,m); if(x<0,return(-realnextdown(-x))); x*=1.0; if(x<LOG_ZERO,return(LOG_ZERO)); y=x+2.0^(2+floor(log(x)/log(2))-default(realbitprecision)); \\誤差を考慮して大きめの数を元の数に寄せる if(x==y,error("realnextup(",x,")")); m=(x+y)*0.5; while((x<m)&&(m<y), \\通常は1回 y=m; m=(x+y)*0.5); y } \\y=log2(x) \\ 二進対数 \\ $ gp -q \\ ? \p 400 \\ ? default(realbitprecision) \\ 1344 \\ ? log(2^1338)-log(2^1338-4) \\ 2.666771371729126107 E-402 \\ ? log(2^1338)-log(2^1338+4) \\ 2.666771371729126107 E-402 \\ この誤差は都合が悪い log2(x)={ my(y,n,m); y=log(x)/log(2); n=floor(y); m=2^n; \\整数または有理数で表現された厳密な値。xの絶対値が大きいと負荷がかかる if(x==m,n, x<m,realnextdown(n), \\大きすぎる 2*m<=x,n+1, \\小さすぎる y) } \\y=log10(x) \\ 常用対数 log10(x)={ my(y,n,m); y=log(x)/log(10); n=floor(y); m=10^n; \\整数または有理数で表現された厳密な値。xの絶対値が大きいと負荷がかかる if(x==m,n, x<m,realnextdown(n), \\大きすぎる 10*m<=x,n+1, \\小さすぎる y) } rint(x)={ if(frac(x)==1/2, \\frac(x)=x-floor(x) if(0<=x, floor(x)+(floor(x)%2), \\x%y=x-floor(x/y)*y ceil(x)-(ceil(x)%2)), floor(x+1/2)) } trunc(x)=if(0<=x,floor(x),ceil(x)); \\truncate(x) \\---------------------------------------------------------------------------------------- \\ 文字列操作 \\---------------------------------------------------------------------------------------- \\t=strlwr(s) \\ 文字列sを小文字にする strlwr(s)=Strchr(apply(c->if((65<=c)&&(c<=90),c+32,c),Vec(Vecsmall(s)))); \\t=strupr(s) \\ 文字列sを大文字にする strupr(s)=Strchr(apply(c->if((97<=c)&&(c<=122),c-32,c),Vec(Vecsmall(s)))); \\x=hex(s) \\ 文字列sを16進数と見なして符号なし整数に変換する \\ "_"を読み飛ばす hex(s)=eval(Str("0x",Strchr(select(c->c!=95,Vec(Vecsmall(s)))))); \\"_"を取り除いてから先頭に"0x"を付けてevalにかける \\x=bin(s) \\ 文字列sを2進数と見なして符号なし整数に変換する \\ "_"を読み飛ばす bin(s)=eval(Str("0b",Strchr(select(c->c!=95,Vec(Vecsmall(s)))))); \\"_"を取り除いてから先頭に"0b"を付けてevalにかける \\x=oct(s) \\ 文字列sを8進数と見なして符号なし整数に変換する \\ "_"を読み飛ばす oct(s)={ my(v,x,c); v=Vecsmall(s); x=0; for(k=1,#v, c=v[k]; if(c!=95, \\_ x=(x<<3)+if((48<=c)&&(c<=55),c-48, \\0-7 error("oct(\"",s,"\")")))); x } \\s=hexstr(x,n) \\ 整数xの16進数表現の末尾のn桁を文字列で返す \\ プレフィックスは付けない \\ printfやStrprintfの書式文字列の"%x"は符号を無視するので負の数をそのまま指定すると64bit単位の補数表現になる \\ -1は2^64-1、-2^64は2^128-2^64など。桁数が16の倍数でないと"0"が並んだ後に"F"が並ぶことになる hexstr(x,n)=Strprintf(Str("%0",n,"X"),bitand(x,16^n-1)); \\s=hex1(u) \\ 整数uの末尾の4bitを1桁の16進数の文字列に変換する hex1(u)=hexstr(u,1); \\s=hex2(u) \\ 整数uの末尾の8bitを2桁の16進数の文字列に変換する hex2(u)=hexstr(u,2); \\s=hex4(u) \\ 整数uの末尾の16bitを4桁の16進数の文字列に変換する hex4(u)=hexstr(u,4); \\s=hex8(u) \\ 整数uの末尾の32bitを8桁の16進数の文字列に変換する hex8(u)=hexstr(u,8); \\s=hex10(u) \\ 整数uの末尾の40bitを10桁の16進数の文字列に変換する hex10(u)=hexstr(u,10); \\s=hex16(u) \\ 整数uの末尾の64bitを16桁の16進数の文字列に変換する hex16(u)=hexstr(u,16); \\s=hex18(u) \\ 整数uの末尾の72bitを18桁の16進数の文字列に変換する hex18(u)=hexstr(u,18); \\s=hex24(u) \\ 整数uの末尾の96bitを24桁の16進数の文字列に変換する hex24(u)=hexstr(u,24); \\s=hex28(u) \\ 整数uの末尾の112bitを28桁の16進数の文字列に変換する hex28(u)=hexstr(u,28); \\s=hex32(u) \\ 整数uの末尾の128bitを32桁の16進数の文字列に変換する hex32(u)=hexstr(u,32); \\s=hex48(u) \\ 整数uの末尾の192bitを48桁の16進数の文字列に変換する hex48(u)=hexstr(u,48); \\s=hex64(u) \\ 整数uの末尾の256bitを64桁の16進数の文字列に変換する hex64(u)=hexstr(u,64); \\s=hex1imm(u) \\ 整数uの末尾の4bitを1桁の16進数の文字列に変換する hex1imm(u)=Str("$",hexstr(u,1)); \\s=hex2imm(u) \\ 整数uの末尾の8bitを2桁の16進数の文字列に変換する hex2imm(u)=Str("$",hexstr(u,2)); \\s=hex4imm(u) \\ 整数uの末尾の16bitを4桁の16進数の文字列に変換する hex4imm(u)=Str("$",hexstr(u,4)); \\s=hex8imm(u) \\ 整数uの末尾の32bitを8桁の16進数の文字列に変換する hex8imm(u)=Str("$",hexstr(u,8)); \\s=hex16imm(u) \\ 整数uの末尾の64bitを2個の8桁の16進数の文字列に変換する hex16imm(u)=Str("$",hexstr(u>>32,8),",$",hexstr(u,8)); \\s=hex24imm(u) \\ 整数uの末尾の96bitを3個の8桁の16進数の文字列に変換する hex24imm(u)=Str("$",hexstr(u>>64,8),",$",hexstr(u>>32,8),",$",hexstr(u,8)); \\s=hex32imm(u) \\ 整数uの末尾の128bitを4個の8桁の16進数の文字列に変換する hex32imm(u)=Str("$",hexstr(u>>96,8),",$",hexstr(u>>64,8),",$",hexstr(u>>32,8),",$",hexstr(u,8)); \\s=hex48imm(u) \\ 整数uの末尾の192bitを6個の8桁の16進数の文字列に変換する hex48imm(u)=Str("$",hexstr(u>>160,8),",$",hexstr(u>>128,8),",$",hexstr(u>>96,8),",$",hexstr(u>>64,8),",$",hexstr(u>>32,8),",$",hexstr(u,8)); \\s=hex64imm(u) \\ 整数uの末尾の256bitを8個の8桁の16進数の文字列に変換する hex64imm(u)=Str("$",hexstr(u>>224,8),",$",hexstr(u>>192,8),",$",hexstr(u>>160,8),",$",hexstr(u>>128,8),",$",hexstr(u>>96,8),",$",hexstr(u>>64,8),",$",hexstr(u>>32,8),",$",hexstr(u,8)); \\s=octstr(x,n) \\ 整数xの8進数表現の末尾のn桁を文字列で返す \\ プレフィックスは付けない octstr(x,n)=Strprintf(Str("%0",n,"o"),bitand(x,8^n-1)); \\s=binstr(x,n) \\ 整数xの2進数表現の末尾のn桁を文字列で返す \\ プレフィックスは付けない \\ printfやStrprintfの書式文字列に"%b"はない binstr(x,n)=Strchr(vector(n,k,48+bittest(bitand(x,2^n-1),n-k))); \\s=formatg(x,n) \\ 数値を有効桁数を指定して文字列に変換する formatg(x,n)={ my(s,g,v); if(type(x)=="t_POL",return(Str(x))); if(0<=x, s="", s="-"; x=-x); \\x=abs(x) if(n<1,n=1); if(x<=LOG_ZERO, \\x==0のとき。log10(x)を計算できない g=0; v=vector(n,i,48), \\0のときは0を並べる g=floor(log10(x)); \\x!=0のときの指数 v=Vecsmall(Str(floor(10^(n-1-g)*x+0.5))); \\先頭のn桁を整数で取り出して1桁ずつ分解する if(#v==n+1,g++)); \\丸めで1桁増えたとき指数部を増やす。vの要素がn+1個あるのでStrchr(v)ではなくStrchr(v[1..n])と書くこと if((-3<=g)&&(g<=-2), Str(s,"0.",Strchr(vector(-1-g,i,48)),Strchr(v[1..n])), \\すべて小数部。小数点以下n-g-1桁。先頭に0.0または0.00を付ける。指数形式にしても.e-3で4文字増えることに変わりないので0.00までは指数形式にしない。有効桁数は0以外の数字から数えればよい g==-1, Str(s,"0.",Strchr(v[1..n])), \\すべて小数部。小数点以下n桁。先頭に0.を付ける (0<=g)&&(g<=n-2), Str(s,Strchr(v[1..g+1]),".",Strchr(v[g+2..n])), \\g+1桁の整数部と小数点とn-g-1桁の小数部 g==n-1, Str(s,Strchr(v[1..n])), \\すべて整数部 \\(n<=g)&&(g<=n+3), \\Str(s,Strchr(v[1..n]),Strchr(vector(g+1-n,i,48))), \\すべて整数部。g+1桁。末尾のg+1-n桁は0。0の数が指数部よりも少なければ指数形式と比較して文字数は多くならないが有効桁数がわからなくなるので不採用 n==1, Str(s,Strchr(v[1]),if(0<g,"e+","e"),g), \\1桁の整数部と指数部 Str(s,Strchr(v[1]),".",Strchr(v[2..n]),if(0<g,"e+","e"),g)) \\1桁の整数部と小数点とn-1桁の小数部と指数部 } \\---------------------------------------------------------------------------------------- \\ 配列操作 \\---------------------------------------------------------------------------------------- \\w=append(v...) \\ 多数のベクタv...を連結する append(v[..])={ if(#v==0,[], #v==1,v[1], #v==2,concat(v[1],v[2]), concat(call(append,[v[1..#v>>1]]),call(append,[v[(#v>>1)+1..#v]]))) } \\t=join(s,v) \\ 区切り文字列sを挟みながらベクタvの要素を連結して1つの文字列にする join(s,v)={ if(#v==0,"", #v==1,Str(v[1]), #v==2,Str(v[1],s,v[2]), Str(call(join,[s,v[1..#v>>1]]),s,call(join,[s,v[(#v>>1)+1..#v]]))) } \\x=merge(v,w,c) \\ 昇順にソートされたベクタvとベクタwをコンパレータcでマージしたベクタを返す \\ 自然順序のときはcmpを指定する merge(v,w,c)={ my(l=#v,m=#w,n=l+m,x=Vec(0,n),i=1,j=1,s,t); for(k=1,n, if(m<j,x[k]=v[i];i++, \\gpのi++はCの++iなのでv[i++]は不可 l<i,x[k]=w[j];j++, s=v[i];t=w[j];if(c(s,t)<=0,x[k]=s;i++,x[k]=t;j++))); x } \\w=sort(v,c) \\ ベクタvをコンパレータcで昇順にソートする \\ 自然順序のときはcmpを指定する sort(v,c)={ my(n=#v,w=Vec(0,n),l); for(k=1,n,w[k]=[v[k]]); \\ベクタを長さ1のブロックに分割する l=1; \\lは現在のブロックの長さ。最後のブロックの長さは1以上 while(l+1<=n, \\ブロックが2個以上ある forstep(k=l+1,n,l<<1, \\kは偶数番目のブロックのインデックス w[k-l]=merge(w[k-l],w[k],c)); \\奇数番目のブロックに偶数番目のブロックをマージする l<<=1); w[1] \\1番目のブロックを返す } \\w=uniq(v,c) \\ ベクタvの連続する要素がコンパレータcで等しいとき2番目以降の要素を取り除く \\ 自然順序のときはcmpを指定する uniq(v,c)={ my(m=#v,k,w); k=1; \\出力する要素の数 for(j=2,m, \\入力インデックス if(c(v[j-1],v[j])!=0,k++)); \\直前の要素と等しくなければ出力する w=Vec(0,k);w[1]=v[1]; \\先頭の要素は無条件に出力する k=1; \\出力した要素の数 for(j=2,m, \\入力インデックス if(c(v[j-1],v[j])!=0,k++;w[k]=v[j])); \\直前の要素と等しくなければ出力する w } \\---------------------------------------------------------------------------------------- \\ ビットリーダ/ビットライタ \\---------------------------------------------------------------------------------------- BLIST=1; BCODE=2; BDATA=3; BFRAC=4; \\ gpのベクタは変数や引数に代入するとコピーされてしまうので破壊関数を作りにくい bbox=List(); \\br=bropen(list) \\ ビットリーダを開く bropen(list)={ my(br); br=#bbox+1; listput(bbox,[list,1,1,0],br); br } \\data=brdata(br) brdata(br)={ my(data); data=bbox[br][BLIST][bbox[br][BDATA]]; bbox[br][BDATA]++; data } \\code=brcode(br,width) brcode(br,width)={ my(code); code=0; while(0<width, if(bbox[br][BFRAC]==0, bbox[br][BCODE]=bbox[br][BDATA]; bbox[br][BDATA]++; bbox[br][BFRAC]=8); if(width<=bbox[br][BFRAC], \\足りるとき \\ 右にfraction-width bitずらして下位width bitを取り出す code=bitor(code<<width, bitand(bbox[br][BLIST][bbox[br][BCODE]]>>(bbox[br][BFRAC]-width),(1<<width)-1)); bbox[br][BFRAC]-=width; width=0, \\足りないとき \\ 下位fraction bitをすべて取り出す code=bitor(code<<bbox[br][BFRAC], bitand(bbox[br][BLIST][bbox[br][BCODE]],(1<<bbox[br][BFRAC])-1)); width-=bbox[br][BFRAC]; bbox[br][BFRAC]=0)); code } \\brclose(br) \\ ビットリーダを閉じる brclose(br)={ listput(bbox,0,br) } \\bw=bwopen() \\ ビットライタを開く bwopen()={ my(bw); bw=#bbox+1; listput(bbox,[List(),1,1,0],bw); bw } \\bwdata(bw,data) bwdata(bw,data)={ listput(bbox[bw][BLIST],bitand(data,255),bbox[bw][BDATA]); bbox[bw][BDATA]++ } \\bwcode(bw,width,code) bwcode(bw,width,code)={ while(0<width, if (bbox[bw][BFRAC]==0, bbox[bw][BCODE]=bbox[bw][BDATA]; listput(bbox[bw][BLIST],0,bbox[bw][BDATA]); bbox[bw][BDATA]++; bbox[bw][BFRAC]=8); if(width<=bbox[bw][BFRAC], \\入り切るとき \\ 左にfraction-width bitずらして書き込む listput(bbox[bw][BLIST],bitor(bbox[bw][BLIST][bbox[bw][BCODE]],code<<(bbox[bw][BFRAC]-width)),bbox[bw][BCODE]); bbox[bw][BFRAC]-=width; width=0, \\入り切らないとき \\ 上位fraction bitを右にfraction-width bitずらして書き込む listput(bbox[bw][BLIST],bitor(bbox[bw][BLIST][bbox[bw][BCODE]],code>>(width-bbox[bw][BFRAC])),bbox[bw][BCODE]); width-=bbox[bw][BFRAC]; code=bitand(code,(1<<width)-1); bbox[bw][BFRAC]=0)) } \\list=bwclose(bw) \\ ビットライタを閉じる bwclose(bw)={ my(list); list=bbox[bw][BLIST]; listput(bbox,0,bw); list } \\---------------------------------------------------------------------------------------- \\ 圧縮/解凍 \\---------------------------------------------------------------------------------------- DICTIONARY_BITS=9; \\単語辞書の大きさ DICTIONARY_SIZE=1<<DICTIONARY_BITS; COMPRESS_PAGE=1; \\1=単語辞書のページ番号を圧縮する COMPRESS_CHAR=1; \\1=文字を圧縮する \\w=compress(v) \\ 0..255の整数からなるベクタvを圧縮する compress(inpbuf)={ my(ptrdic,lendic,chrdic,inplen,bw,inpptr,bstpag,bstlen,pag,len,ptr,equ,wid,tmp,chr); ptrdic=vector(DICTIONARY_SIZE); \\単語辞書。開始位置 lendic=vector(DICTIONARY_SIZE); \\単語辞書。長さ chrdic=vector(256,n,n-1); \\文字辞書 inplen=#inpbuf; \\入力データの長さ bw=bwopen(); bwdata(bw,inplen>>24); bwdata(bw,inplen>>16); bwdata(bw,inplen>>8); bwdata(bw,inplen); inpptr=0; \\入力ポインタ while(inpptr<inplen, \\単語辞書から探す bstpag=-1; \\最も長く一致した単語があるページ bstlen=0; \\最も長く一致した単語の長さ for(pag=0,DICTIONARY_SIZE-1, len=lendic[1+pag]; \\単語辞書にある単語の長さ if((bstlen<len)&&(inpptr+len+1<=inplen), \\これまでより長い、かつ、はみ出さない ptr=ptrdic[1+pag]; \\単語辞書にある単語の開始位置 equ=1; for(i=0,len-1, if(inpbuf[1+inpptr+i]!=inpbuf[1+ptr+i], equ=0; break())); if(equ, \\一致した bstpag=pag; bstlen=len))); if(bstlen, \\単語辞書にある bwcode(bw,1,1); if(COMPRESS_PAGE, \\単語辞書のページ番号を圧縮する wid=1; \\単語辞書のページ番号に2を加えた値の先頭の1を除いたbit数 tmp=(bstpag+2)>>1; while(tmp!=1, wid++; tmp>>=1); tmp=(1<<wid)-1; bwcode(bw,wid,tmp-1); bwcode(bw,wid,bitand(bstpag+2,tmp)), \\単語辞書のページ番号を圧縮しない bwcode(bw,DICTIONARY_BITS,bstpag)), \\単語辞書にない bwcode(bw,1,0)); chr=inpbuf[1+inpptr+bstlen]; \\今回の文字 if(COMPRESS_CHAR, \\文字を圧縮する \\文字辞書から探す bstpag=-1; \\文字が一致したページ。必ずある for(i=0,255, if(chrdic[1+i]==chr, bstpag=i; break())); wid=1; \\文字辞書のページ番号に2を加えた値の先頭の1を除いたbit数 tmp=(bstpag+2)>>1; while(tmp!=1, wid++; tmp>>=1); tmp=(1<<wid)-1; bwcode(bw,wid,tmp-1); bwcode(bw,wid,bitand(bstpag+2,tmp)); \\今回の文字を文字辞書の先頭に移動させる forstep(i=bstpag,1,-1, chrdic[1+i]=chrdic[1+i-1]); chrdic[1+0]=chr, \\文字を圧縮しない bwdata(bw,chr)); \\1文字伸ばす bstlen++; \\単語辞書を後ろにずらす forstep(i=DICTIONARY_SIZE-1,1,-1, ptrdic[1+i]=ptrdic[1+i-1]; lendic[1+i]=lendic[1+i-1]); \\単語辞書の先頭に登録する ptrdic[1+0]=inpptr; lendic[1+0]=bstlen; inpptr+=bstlen); Vecsmall(bwclose(bw)) } \\v=decompress(w) \\ 0..255の整数からなるベクタwを解凍する decompress(w)={ my(ptrdic,lendic,chrdic,outlen,outbuf,outptr,bstlen,wid,pag,ptr,len,chr); ptrdic=vector(DICTIONARY_SIZE); \\単語辞書。ポインタ lendic=vector(DICTIONARY_SIZE); \\単語辞書。長さ chrdic=vector(256,n,n-1); \\文字辞書 br=bropen(w); outlen=brdata(br); outlen=(outlen<<8)+brdata(br); outlen=(outlen<<8)+brdata(br); outlen=(outlen<<8)+brdata(br); outbuf=Vecsmall(vector(outlen)); outptr=0; while(outptr<outlen, if(brcode(br,1), \\単語辞書にある if(COMPRESS_PAGE, \\単語辞書のページ番号が圧縮されている \\単語辞書のページ番号を求める wid=1; \\単語辞書のページ番号に2を加えた値の先頭の1を除いたbit数 while(brcode(br,1), wid++); pag=(1<<wid)+brcode(br,wid)-2, \\単語辞書のページ番号 \\単語辞書のページ番号が圧縮されていない pag=brcode(br,DICTIONARY_BITS)); \\単語辞書から取り出す ptr=ptrdic[1+pag]; len=lendic[1+pag]; for(i=0,len-1, outbuf[1+outptr+i]=outbuf[1+ptr+i]); bstlen=len, \\単語辞書にない bstlen=0); if(COMPRESS_CHAR, \\文字が圧縮されている \\文字辞書のページ番号を求める wid=1; \\文字辞書のページ番号に2を加えた値の先頭の1を除いたbit数 while(brcode(br,1)!=0, wid++); bstpag=(1<<wid)+brcode(br,wid)-2; \\文字辞書から取り出す chr=chrdic[1+bstpag]; \\取り出した文字を文字辞書の先頭に移動させる forstep(i=bstpag,1,-1, chrdic[1+i]=chrdic[1+i-1]); chrdic[1+0]=chr, \\文字が圧縮されていない chr=brdata(br)); \\文字を出力する outbuf[1+outptr+bstlen]=chr; \\1文字伸ばす bstlen++; \\単語辞書を後ろにずらす forstep(i=DICTIONARY_SIZE-1,1,-1, ptrdic[1+i]=ptrdic[1+i-1]; lendic[1+i]=lendic[1+i-1]); \\単語辞書の先頭に登録する ptrdic[1+0]=outptr; lendic[1+0]=bstlen; outptr+=bstlen); brclose(br); outbuf } ASM_DECOMPRESS={Str( " ;-------------------------------------------------------------------------------- ; 解凍 ;-------------------------------------------------------------------------------- DICTIONARY_BITS equ ",DICTIONARY_BITS," DICTIONARY_SIZE equ ",DICTIONARY_SIZE," COMPRESS_PAGE equ ",COMPRESS_PAGE," ;1=単語辞書のページ番号を圧縮する COMPRESS_CHAR equ ",COMPRESS_CHAR," ;1=文字を圧縮する ;---------------------------------------------------------------- ;brcode n ; n bit取り出す ; n 取り出すbit数。0..25bit ;<d1.l:入力プール。右寄せ ;<d2.w:入力プールの残りbit数 ;<a0.l:入力アドレス ;>d0.l:n bitのデータ。0拡張 ;>d1.l:入力プール。右寄せ ;>d2.w:入力プールの残りbit数 ;>a0.l:入力アドレス brcode .macro n sub.w n,d2 bpl @skip @loop: lsl.l #8,d1 move.b (a0)+,d1 addq.w #8,d2 bmi @loop @skip: move.l d1,d0 lsr.l d2,d0 lsl.l d2,d0 eor.l d0,d1 lsr.l d2,d0 .endm ;---------------------------------------------------------------- ;decompress(in,out) ; 解凍する ; 汎用ではない。エラーチェックを行っていないのでデータが壊れているとクラッシュする regs reg d0-d7/a0-a5 .offsym 0,_a6 _size: _regs: .ds.b .sizeof.(regs) _a6: .ds.l 1 _pc: .ds.l 1 _in: .ds.l 1 ;入力アドレス _out: .ds.l 1 ;出力アドレス .text .even decompress:: link.w a6,#_size movem.l regs,(_regs,a6) ;単語辞書を初期化する lea.l decompress_wdic,a3 ;単語辞書 movea.l a3,a0 move.w #DICTIONARY_SIZE-1,d0 @@: clr.l (a0)+ clr.l (a0)+ dbra d0,@b ;文字辞書を初期化する lea.l decompress_cdic,a5 ;文字辞書 movea.l a5,a0 move.l #$00010203,d3 move.l #$04040404,d4 moveq.l #256/4-1,d0 @@: move.l d3,(a0)+ add.l d4,d3 dbra d0,@b ; moveq.l #0,d1 ;入力プール。右寄せ moveq.l #0,d2 ;入力プールの残りbit数 moveq.l #0,d5 ;単語辞書のアドレスのゲタ movea.l (_in,a6),a0 ;入力アドレス movea.l (_out,a6),a1 ;出力アドレス movea.l a1,a2 adda.l (a0)+,a2 ;出力バッファの末尾 ;解凍ループ cmpa.l a2,a1 bhs 199f 100: brcode #1 ;1bit取り出す bne 20f ;単語辞書にある ;単語辞書にない moveq.l #1,d3 ;length subq.w #8,d5 ;単語辞書のアドレスのゲタをずらす and.w #(DICTIONARY_SIZE-1)<<3,d5 movem.l d3/a1,(a3,d5.l) ;単語辞書の先頭に登録する。length,address bra 30f ;単語辞書にある 20: .if COMPRESS_PAGE ;単語辞書のページ番号が圧縮されている ;単語辞書のページ番号を求める moveq.l #0,d4 ;wid。単語辞書のページ番号に2を加えた値の先頭の1を除いたbit数 @@: addq.w #1,d4 brcode #1 ;brcode(1) bne @b brcode d4 ;brcode(wid) bset.l d4,d0 ;(1<<wid)+brcode(wid) subq.w #2,d0 ;(1<<wid)+brcode(wid)-2。単語辞書のページ番号 .else ;単語辞書のページ番号が圧縮されていない brcode #DICTIONARY_BITS ;brcode(DICTIONARY_BITS)。単語辞書のページ番号 .endif ;単語辞書から取り出す lsl.l #3,d0 ;ページオフセット add.w d5,d0 ;ページオフセットに単語辞書のアドレスのゲタを加える and.w #(DICTIONARY_SIZE-1)<<3,d0 movem.l (a3,d0.l),d3/a4 ;length,address ;単語辞書のアドレスのゲタをずらす subq.l #8,d5 and.l #(DICTIONARY_SIZE-1)<<3,d5 ;1文字伸ばす addq.l #1,d3 ;単語辞書の先頭に登録する movem.l d3/a1,(a3,d5.l) ;length,address ;単語辞書から取り出した文字を出力する subq.l #1+1,d3 @@: move.b (a4)+,(a1)+ dbra d3,@b 30: .if COMPRESS_CHAR ;文字が圧縮されている ;文字辞書のページ番号を求める moveq.l #0,d4 ;wid。文字辞書のページ番号に2を加えた値の先頭の1を除いたbit数 @@: addq.w #1,d4 brcode #1 ;brcode(1) bne @b brcode d4 ;brcode(wid) bset.l d4,d0 ;(1<<wid)+brcode(wid) subq.w #2,d0 ;(1<<wid)+brcode(wid)-2。文字辞書のページ番号 ;文字辞書から取り出す lea.l (a5,d0.w),a4 ;文字辞書のページアドレス move.b (a4),d3 ;文字辞書から取り出した文字を出力する move.b d3,(a1)+ ;取り出した文字を文字辞書の先頭に移動させる bra 2f 1: move.b -(a4),1(a4) 2: dbra d0,1b move.b d3,(a5) .else ;文字が圧縮されていない ;入力された文字を出力する move.b (a0)+,(a1)+ .endif cmpa.l a2,a1 blo 100b 199: movem.l (_regs,a6),regs unlk a6 rts .bss .align 4 decompress_wdic:: .ds.l 2*DICTIONARY_SIZE ;単語辞書。length,address,... decompress_cdic:: .ds.b 256 ;文字辞書。0..255を最近使われた順に並べる ")} \\---------------------------------------------------------------------------------------- \\ BCD \\---------------------------------------------------------------------------------------- \\u=encodebcd(x) \\ 整数xをBCDの内部表現を表す符号なし整数に変換する encodebcd(x)={ my(v,u); if(x<0,error("encodebcd(",x,")")); v=Vecsmall(Strprintf("%d",x)); u=0; for(i=1,#v,u=(u<<4)+bitand(v[i],15)); u } \\x=decodebcd(u) \\ 符号なし整数uをBCDの内部表現と見なして整数に変換する \\ 0..9以外の文字があるとき-1を返す decodebcd(u)={ my(x,b,t); if(u<0,error("decodebcd(",u,")")); x=0; b=1; while(u, t=bitand(u,15); if(9<t,return(-1)); x+=b*t; b*=10; u>>=4); x } \\---------------------------------------------------------------------------------------- \\ 特別な数値 \\---------------------------------------------------------------------------------------- \\ Rei +0 \\ -Rei -0 \\ Inf +Inf \\ -Inf -Inf \\ NaN NaN \\ \\ type(x)=="t_POL"とx==Reiなどで判別できる。Rei<xは不可 \\ 単なる変数なので間違って値を代入しないように注意すること \\f=iszero(x) \\ ゼロか iszero(x)={ if(x==0,x=Rei); if((x==-Rei)||(x==Rei),1, \\-ReiとReiと0を含む 0) } \\f=isplus(x) \\ 正か isplus(x)={ if(x==0,x=Rei); if((x==Rei)||(x==Inf),1, \\-Reiを含まない。Reiと0を含む (x==-Inf)||(x==-Rei)||(x==NaN),0, 0<x,1, 0) } \\f=isminus(x) \\ 負か isminus(x)={ if(x==0,x=Rei); if((x==-Inf)||(x==-Rei),1, \\-Reiを含む。Reiと0を含まない (x==Rei)||(x==Inf)||(x==NaN),0, x<0,1, 0) } \\comparator(x,y) \\ データをソートするためのコンパレータ。-ReiとReiを区別する \\ -Inf==-Inf \\ -Rei==-Rei \\ Rei==Rei \\ Inf==Inf \\ NaN==NaN \\ -Inf<-1<-Rei<Rei<1<Inf<NaN comparator(x,y)={ if(x==0,x=Rei); if(y==0,y=Rei); if((x==-Inf)&&(y==-Inf),0, (x==-Rei)&&(y==-Rei),0, (x==Rei)&&(y==Rei),0, (x==Inf)&&(y==Inf),0, (x==NaN)&&(y==NaN),0, x==NaN,1, y==NaN,-1, x==Inf,1, y==Inf,-1, x==-Inf,-1, y==-Inf,1, (x==Rei)&&(y==-Rei),1, (x==-Rei)&&(y==Rei),-1, (x==Rei)||(x==-Rei),-sign(y), (y==Rei)||(y==-Rei),sign(x), sign(x-y)) } test_comparator()={ my(v=[-Inf,-1,-Rei,Rei,1,Inf,NaN],f); for(y=1,#v, for(x=1,#v, f=comparator(v[x],v[y]); printf("%-10s ",Str(v[x],if(f<0,"<",f==0,"==",">"),v[y]))); print()) } getexp(x)={ if(type(x)=="t_POL", if(x==-Inf,-Inf, x==-Rei,-Rei, x==Rei,Rei, x==Inf,Inf, x==NaN,NaN, error("getexp(",x,")")), floor(log2(abs(x)))) } getman(x)={ if(type(x)=="t_POL", if(x==-Inf,-Inf, x==-Rei,-Rei, x==Rei,Rei, x==Inf,Inf, x==NaN,NaN, error("getman(",x,")")), x/2^floor(log2(abs(x)))) } \\---------------------------------------------------------------------------------------- \\ FPSR \\---------------------------------------------------------------------------------------- fpsr=0; \\コンディションコードバイト MI=1<<27; ZE=1<<26; IN=1<<25; NA=1<<24; \\エクセプションバイト BS=1<<15; SN=1<<14; OE=1<<13; OF=1<<12; UF=1<<11; DZ=1<<10; X2=1<<9; X1=1<<8; \\アクルードエクセプションバイト AV=1<<7; AO=1<<6; AU=1<<5; AZ=1<<4; AX=1<<3; FPSR_MASK_1=[MI,ZE,IN,NA]; FPSR_NAME_1=["MI","ZE","IN","NA"]; FPSR_MASK_2=[BS,SN,OE,OF,UF,DZ,X2,X1,AV,AO,AU,AZ,AX]; FPSR_NAME_2=["BS","SN","OE","OF","UF","DZ","X2","X1","AV","AO","AU","AZ","AX"]; \\s=strfpsr(sr) \\ fpsrを文字列に変換する strfpsr(sr)={ my(s,n); if(sr==0,"0", s=""; for(i=1,#FPSR_MASK_1, if(bitand(sr,FPSR_MASK_1[i])!=0, if(s!="",s=concat(s,"+")); s=concat(s,FPSR_NAME_1[i]))); if(bitand(sr>>23,1)!=0, if(s!="",s=concat(s,"+")); s=concat(s,Str("(",bitand(sr>>23,1),"<<23)"))); if(bitand(sr>>16,127)!=0, if(s!="",s=concat(s,"+")); s=concat(s,Str("(",bitand(sr>>16,127),"<<16)"))); for(i=1,#FPSR_MASK_2, if(bitand(sr,FPSR_MASK_2[i])!=0, if(s!="",s=concat(s,"+")); s=concat(s,FPSR_NAME_2[i])))); s } \\fpsr_update_ccr(x) \\ fpsrのコンディションコードバイトを更新する fpsr_update_ccr(x)={ fpsr=bitand(fpsr,(1<<24)-1); if(x==Rei,fpsr=bitor(fpsr,ZE), x==-Rei,fpsr=bitor(fpsr,MI+ZE), x==Inf,fpsr=bitor(fpsr,IN), x==-Inf,fpsr=bitor(fpsr,MI+IN), x==NaN,fpsr=bitor(fpsr,NA), x<0,fpsr=bitor(fpsr,MI)) } \\ fpsrのアクルードエクセプションバイトを更新する fpsr_update_aer()={ if(bitand(fpsr,BS+SN+OE)!=0,fpsr=bitor(fpsr,AV)); if(bitand(fpsr,OF)!=0,fpsr=bitor(fpsr,AO)); if(bitand(fpsr,UF+X2)==(UF+X2),fpsr=bitor(fpsr,AU)); if(bitand(fpsr,DZ)!=0,fpsr=bitor(fpsr,AZ)); if(bitand(fpsr,OF+X2+X1)!=0,fpsr=bitor(fpsr,AX)) } \\---------------------------------------------------------------------------------------- \\ FPCR \\---------------------------------------------------------------------------------------- \\ rp=0..2 丸め桁数 EXD=0; \\extended 拡張精度 SGL=1; \\single 単精度 DBL=2; \\double 倍精度 DBL3=3; \\double 倍精度 \\ rm=0..3 丸めモード RN=0; \\to nearest RZ=1; \\toward zero RM=2; \\toward minus infinity RP=3; \\toward plus infinity RMSTR=["RN","RZ","RM","RP"]; strrm(rm)=RMSTR[1+rm]; strrmf(rm,s)=Str(RMSTR[1+rm],"(",s,")"); \\ rprm=0..11 丸め桁数と丸めモード XRN=(EXD<<2)+RN; XRZ=(EXD<<2)+RZ; XRM=(EXD<<2)+RM; XRP=(EXD<<2)+RP; SRN=(SGL<<2)+RN; SRZ=(SGL<<2)+RZ; SRM=(SGL<<2)+RM; SRP=(SGL<<2)+RP; DRN=(DBL<<2)+RN; DRZ=(DBL<<2)+RZ; DRM=(DBL<<2)+RM; DRP=(DBL<<2)+RP; \\s=strrprm(rprm) \\ rprmを文字列に変換する STRRPRM=["XRN","XRZ","XRM","XRP","SRN","SRZ","SRM","SRP","DRN","DRZ","DRM","DRP"]; strrprm(rprm)=STRRPRM[1+rprm]; \\ 以下は拡張 \\ 型変換を行う関数の引数の丸め桁数rpに指定する \\ FPCRには指定できない TPL=4; \\triple 三倍精度 QPL=5; \\quadruple 四倍精度 SPL=6; \\sextuple 六倍精度 OPL=7; \\octuple 八倍精度 XSG=8; \\xsingle 拡張単精度 XDB=9; \\xdouble 拡張倍精度 EFP=10; \\efp efp BYTE=11; \\byte バイト WORD=12; \\word ワード LONG=13; \\long ロング QUAD=14; \\quad クワッド \\---------------------------------------------------------------------------------------- \\ 浮動小数点数の内部表現 \\---------------------------------------------------------------------------------------- \\ perl -e "printf qq@%c%c %9s%5s%5s%4s%4s%4s%5s%7s%8s%8s%8s%7s%5s%5s%5s\n@,92,92,'name','inr','bit','sw','ew','iw','fw','bias','demin','demax','nomin','nomax','dgt','hex','imm';for my$i(['single','sgl',8,0,23,8,'sgh','sgi'],['double','dbl',11,0,52,16,'dbh','dbi'],['extended','exd',15,1,63,24,'exh','exi'],['triple','tpl',15,1,79,24,'tph','tpi'],['quadruple','qpl',15,0,112,32,'qph','qpi'],['sextuple','spl',15,0,176,48,'sph','spi'],['octuple','opl',15,0,240,64,'oph','opi'],['xsingle','xsg',15,1,23,10,'xsh','xsi'],['xdouble','xdb',15,1,52,18,'xdh','xdi'],['efp','efp',16,1,91,28,'efh','efi']){my($name,$inr,$ew,$iw,$fw,$dgt,$hex,$imm)=@$i;my$bias=(1<<($ew-1))-1;my$demin=1-$iw-$bias-$fw;my$demax=-$iw-$bias;my$nomin=1-$iw-$bias;my$nomax=$bias;printf qq@%c%c %9s%5s%5d%4d%4d%4d%5d%7d%8d%8d%8d%7d%5d%5s%5s\n@,92,92,$name,$inr,1+$ew+$iw+$fw,1,$ew,$iw,$fw,$bias,$demin,$demax,$nomin,$nomax,$dgt,$hex,$imm;}" \\ name inr bit sw ew iw fw bias demin demax nomin nomax dgt hex imm \\ single sgl 32 1 8 0 23 127 -149 -127 -126 127 8 sgh sgi \\ double dbl 64 1 11 0 52 1023 -1074 -1023 -1022 1023 16 dbh dbi \\ extended exd 80 1 15 1 63 16383 -16446 -16384 -16383 16383 24 exh exi \\ triple tpl 96 1 15 1 79 16383 -16462 -16384 -16383 16383 24 tph tpi \\ quadruple qpl 128 1 15 0 112 16383 -16494 -16383 -16382 16383 32 qph qpi \\ sextuple spl 192 1 15 0 176 16383 -16558 -16383 -16382 16383 48 sph spi \\ octuple opl 256 1 15 0 240 16383 -16622 -16383 -16382 16383 64 oph opi \\ xsingle xsg 40 1 15 1 23 16383 -16406 -16384 -16383 16383 10 xsh xsi \\ xdouble xdb 69 1 15 1 52 16383 -16435 -16384 -16383 16383 18 xdh xdi \\ efp efp 109 1 16 1 91 32767 -32858 -32768 -32767 32767 28 efh efi \\ \\ ew 浮動小数点数の内部表現の指数部のbit数 \\ iw 浮動小数点数の内部表現の整数部のbit数 \\ fw 浮動小数点数の内部表現の小数部のbit数 \\ bias=(1<<(ew-1))-1; \\指数のバイアス \\ demin=1-iw-bias-fw; \\非正規化数の指数の下限 \\ demax=-iw-bias; \\非正規化数の指数の上限 \\ nomin=1-iw-bias; \\正規化数の指数の下限 \\ nomax=bias; \\正規化数の指数の上限 \\ SGLDEMIN=2^-149; \\0x3F6A8000000000000000 0x00000001 単精度 非正規化数 最小値 SGLDEMAX=2^-126-2^-149; \\0x3F80FFFFFE0000000000 0x007FFFFF 単精度 非正規化数 最大値 SGLNOMIN=2^-126; \\0x3F818000000000000000 0x00800000 単精度 正規化数 最小値 SGLNOMAX=2^128-2^104; \\0x407EFFFFFF0000000000 0x7F7FFFFF 単精度 正規化数 最大値 DBLDEMIN=2^-1074; \\0x3BCD8000000000000000 0x0000000000000001 倍精度 非正規化数 最小値 DBLDEMAX=2^-1022-2^-1074; \\0x3C00FFFFFFFFFFFFF000 0x000FFFFFFFFFFFFF 倍精度 非正規化数 最大値 DBLNOMIN=2^-1022; \\0x3C018000000000000000 0x0010000000000000 倍精度 正規化数 最小値 DBLNOMAX=2^1024-2^971; \\0x43FEFFFFFFFFFFFFF800 0x7FEFFFFFFFFFFFFF 倍精度 正規化数 最大値 EXDDEMIN=2^-16446; \\0x00000000000000000001 拡張精度 非正規化数 最小値 EXDDEMAX=2^-16383-2^-16446; \\0x00007FFFFFFFFFFFFFFF 拡張精度 非正規化数 最大値 EXDNOMIN=2^-16383; \\0x00008000000000000000 拡張精度 正規化数 最小値 EXDNOMAX=2^16384-2^16320; \\0x7FFEFFFFFFFFFFFFFFFF 拡張精度 正規化数 最大値 TPLDEMIN=2^-16462; \\0x000000000000000000000001 三倍精度 非正規化数 最小値 TPLDEMAX=2^-16383-2^-16462; \\0x00007FFFFFFFFFFFFFFFFFFF 三倍精度 非正規化数 最大値 TPLNOMIN=2^-16383; \\0x000080000000000000000000 三倍精度 正規化数 最小値 TPLNOMAX=2^16384-2^16304; \\0x7FFEFFFFFFFFFFFFFFFFFFFF 三倍精度 正規化数 最大値 QPLDEMIN=2^-16494; \\0x00000000000000000000000000000001 四倍精度 非正規化数 最小値 QPLDEMAX=2^-16382-2^-16494; \\0x0000FFFFFFFFFFFFFFFFFFFFFFFFFFFF 四倍精度 非正規化数 最大値 QPLNOMIN=2^-16382; \\0x00010000000000000000000000000000 四倍精度 正規化数 最小値 QPLNOMAX=2^16384-2^16271; \\0x7FFEFFFFFFFFFFFFFFFFFFFFFFFFFFFF 四倍精度 正規化数 最大値 SPLDEMIN=2^-16558; \\0x000000000000000000000000000000000000000000000001 六倍精度 非正規化数 最小値 SPLDEMAX=2^-16382-2^-16558; \\0x0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 六倍精度 非正規化数 最大値 SPLNOMIN=2^-16382; \\0x000100000000000000000000000000000000000000000000 六倍精度 正規化数 最小値 SPLNOMAX=2^16384-2^16207; \\0x7FFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 六倍精度 正規化数 最大値 OPLDEMIN=2^-16622; \\0x0000000000000000000000000000000000000000000000000000000000000001 八倍精度 非正規化数 最小値 OPLDEMAX=2^-16382-2^-16622; \\0x0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 八倍精度 非正規化数 最大値 OPLNOMIN=2^-16382; \\0x0001000000000000000000000000000000000000000000000000000000000000 八倍精度 正規化数 最小値 OPLNOMAX=2^16384-2^16143; \\0x7FFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 八倍精度 正規化数 最大値 XSGDEMIN=2^-16406; \\0x0000000001 拡張単精度 非正規化数 最小値 XSGDEMAX=2^-16383-2^-16406; \\0x00007FFFFF 拡張単精度 非正規化数 最大値 XSGNOMIN=2^-16383; \\0x0000800000 拡張単精度 正規化数 最小値 XSGNOMAX=2^16384-2^16360; \\0x7FFEFFFFFF 拡張単精度 正規化数 最大値 XDBDEMIN=2^-16435; \\0x000000000000000001 拡張倍精度 非正規化数 最小値 XDBDEMAX=2^-16383-2^-16435; \\0x00000FFFFFFFFFFFFF 拡張倍精度 非正規化数 最大値 XDBNOMIN=2^-16383; \\0x000010000000000000 拡張倍精度 正規化数 最小値 XDBNOMAX=2^16384-2^16331; \\0x0FFFDFFFFFFFFFFFFF 拡張倍精度 正規化数 最大値 EFPDEMIN=2^-32858; \\0x0000000000000000000000000001 efp 非正規化数 最小値 EFPDEMAX=2^-32767-2^-32858; \\0x000007FFFFFFFFFFFFFFFFFFFFFF efp 非正規化数 最大値 EFPNOMIN=2^-32767; \\0x0000080000000000000000000000 efp 正規化数 最小値 EFPNOMAX=2^32768-2^32676; \\0x0FFFEFFFFFFFFFFFFFFFFFFFFFFF efp 正規化数 最大値 BYTEMIN=-2^7; \\0x80 バイト 最小値 BYTEMAX=2^7-1; \\0x7F バイト 最大値 WORDMIN=-2^15; \\0x8000 ワード 最小値 WORDMAX=2^15-1; \\0x7FFF ワード 最大値 LONGMIN=-2^31; \\0x80000000 ロング 最小値 LONGMAX=2^31-1; \\0x7FFFFFFF ロング 最大値 QUADMIN=-2^63; \\0x8000000000000000 クワッド 最小値 QUADMAX=2^63-1; \\0x7FFFFFFFFFFFFFFF クワッド 最大値 \\x=xxxtonum(u,ew,iw,fw) \\ (1+ew+iw+fw)bit符号なし整数uを浮動小数点数の内部表現と見なして数値または特別な数値に変換する \\ x 数値または特別な数値 \\ u (1+ew+iw+fw)bit符号なし整数 \\ ew 浮動小数点数の内部表現の指数部のbit数 \\ iw 浮動小数点数の内部表現の整数部のbit数 \\ fw 浮動小数点数の内部表現の小数部のbit数 xxxtonum(u,ew,iw,fw)={ my(eb,sp,ep,ip,fp,sv); eb=(1<<(ew-1))-1; \\指数のバイアス sp=u>>(ew+iw+fw); \\符号部 ep=bitand(u>>(iw+fw),(1<<ew)-1); \\指数部 ip=bitand(u>>fw,(1<<iw)-1); \\整数部 fp=bitand(u,(1<<fw)-1); \\小数部 sv=if(sp==0,1,-1); \\符号 if(ep==((1<<ew)-1), \\指数部がすべて1 if(fp==0,sv*Inf, \\指数部がすべて1で小数部がすべて0ならば±Inf NaN), \\指数部がすべて1で小数部が0でなければNaN iw==0, \\整数部がないとき(single,double) \\ 指数部が0でなければ正規化数、指数部が0で小数部が0でなければ非正規化数、指数部が0で小数部も0ならば0 \\ 指数部が1の正規化数と指数部が0の非正規化数は小数点の位置が同じで同じ指数 if(ep!=0,sv*2^(ep-eb-fw)*((1<<fw)+fp), \\指数部が0でなければ正規化数 fp!=0,sv*2^(1-eb-fw)*fp, \\指数部が0で小数部が0でなければ非正規化数 sv*Rei), \\指数部が0で小数部も0ならば±0 \\整数部があるとき(extended) \\ 整数部が0でなければ正規化数、指数部と整数部が0で小数部が0でなければ非正規化数、指数部と整数部と小数部が0ならば±0、それ以外はNaN \\ 指数部が0の正規化数と指数部が0の非正規化数は小数点の位置が同じで同じ指数 if((ip!=0),sv*2^(ep-eb-fw)*((ip<<fw)+fp), \\整数部が0でなければ正規化数 (ep==0)&&(ip==0)&&(fp!=0),sv*2^(0-eb-fw)*fp, \\指数部と整数部が0で小数部が0でなければ非正規化数 (ep==0)&&(ip==0)&&(fp==0),sv*Rei, \\指数部と整数部と小数部が0ならば±0 NaN)) \\それ以外はNaN } \\x=sgltonum(u) \\ 32bit符号なし整数をsingleの内部表現と見なして数値または特別な数値に変換する \\ x 数値または特別な数値 \\ u 32bit符号なし整数 sgltonum(u)=xxxtonum(u,8,0,23); \\x=dbltonum(u) \\ 64bit符号なし整数をdoubleの内部表現と見なして数値または特別な数値に変換する \\ x 数値または特別な数値 \\ u 64bit符号なし整数 dbltonum(u)=xxxtonum(u,11,0,52); \\x=exdtonum(u) \\ 96bit符号なし整数をextendedの内部表現と見なして数値または特別な数値に変換する \\ x 数値または特別な数値 \\ u 96bit符号なし整数 exdtonum(u)={ \\ |符号部と指数部(16bit)|空き(16bit)|仮数部(64bit)| \\ ↓ \\ |符号部と指数部(16bit)|仮数部(64bit)| u=((bitand(u,(1<<96)-(1<<80))>>16)+ \\符号部と指数部(16bit) bitand(u,(1<<64)-(1<<0))); \\仮数部(64bit) xxxtonum(u,15,1,63) } \\x=tpltonum(u) \\ 96bit符号なし整数をtripleの内部表現と見なして数値または特別な数値に変換する \\ x 数値または特別な数値 \\ u 96bit符号なし整数 tpltonum(u)={ \\ |符号部と指数部(16bit)|仮数部の下位(16bit)|仮数部の上位(64bit)| \\ ↓ \\ |符号部と指数部(16bit)|仮数部の上位(64bit)|仮数部の下位(16bit)| u=(bitand(u,(1<<96)-(1<<80))+ \\符号部と指数部(16bit) (bitand(u,(1<<64)-(1<<0))<<16)+ \\仮数部の上位(64bit) (bitand(u,(1<<80)-(1<<64))>>64)); \\仮数部の下位(16bit) xxxtonum(u,15,1,79) } \\x=qpltonum(u) \\ 128bit符号なし整数をquadrupleの内部表現と見なして数値または特別な数値に変換する \\ x 数値または特別な数値 \\ u 128bit符号なし整数 qpltonum(u)=xxxtonum(u,15,0,112); \\x=spltonum(u) \\ 192bit符号なし整数をsextupleの内部表現と見なして数値または特別な数値に変換する \\ x 数値または特別な数値 \\ u 192bit符号なし整数 spltonum(u)=xxxtonum(u,15,0,176); \\x=opltonum(u) \\ 256bit符号なし整数をoctupleの内部表現と見なして数値または特別な数値に変換する \\ x 数値または特別な数値 \\ u 256bit符号なし整数 opltonum(u)=xxxtonum(u,15,0,240); \\x=xsgtonum(u) \\ 40bit符号なし整数をxsingleの内部表現と見なして数値または特別な数値に変換する \\ x 数値または特別な数値 \\ u 40bit符号なし整数 xsgtonum(u)=xxxtonum(u,15,1,23); \\x=xdbtonum(u) \\ 69bit符号なし整数をxdoubleの内部表現と見なして数値または特別な数値に変換する \\ x 数値または特別な数値 \\ u 69bit符号なし整数 xdbtonum(u)=xxxtonum(u,15,1,52); \\x=efptonum(u) \\ 109bit符号なし整数をefpの内部表現と見なして数値または特別な数値に変換する \\ x 数値または特別な数値 \\ u 109bit符号なし整数 efptonum(u)=xxxtonum(u,16,1,91); \\x=sghtonum(s) \\ 8桁の16進数の文字列をsingleの内部表現と見なして数値または特別な数値に変換する \\ s 8桁の16進数の文字列 \\ x 数値または特別な数値 sghtonum(s)=sgltonum(hex(s)); \\x=dbhtonum(s) \\ 16桁の16進数の文字列をdoubleの内部表現と見なして数値または特別な数値に変換する \\ s 16桁の16進数の文字列 \\ x 数値または特別な数値 dbhtonum(s)=dbltonum(hex(s)); \\x=exhtonum(s) \\ 24桁の16進数の文字列をextendedの内部表現と見なして数値または特別な数値に変換する \\ s 24桁の16進数の文字列 \\ x 数値または特別な数値 exhtonum(s)=exdtonum(hex(s)); \\x=tphtonum(s) \\ 24桁の16進数の文字列をtripleの内部表現と見なして数値または特別な数値に変換する \\ s 24桁の16進数の文字列 \\ x 数値または特別な数値 tphtonum(s)=tpltonum(hex(s)); \\x=qphtonum(s) \\ 32桁の16進数の文字列をquadrupleの内部表現と見なして数値または特別な数値に変換する \\ s 32桁の16進数の文字列 \\ x 数値または特別な数値 qphtonum(s)=qpltonum(hex(s)); \\x=spltonum(s) \\ 48桁の16進数の文字列をsextupleの内部表現と見なして数値または特別な数値に変換する \\ s 48桁の16進数の文字列 \\ x 数値または特別な数値 sphtonum(s)=spltonum(hex(s)); \\x=opltonum(s) \\ 64桁の16進数の文字列をoctupleの内部表現と見なして数値または特別な数値に変換する \\ s 64桁の16進数の文字列 \\ x 数値または特別な数値 ophtonum(s)=opltonum(hex(s)); \\x=xshtonum(s) \\ 10桁の16進数の文字列をxsingleの内部表現と見なして数値または特別な数値に変換する \\ s 10桁の16進数の文字列 \\ x 数値または特別な数値 xshtonum(s)=xsgtonum(hex(s)); \\x=xdhtonum(s) \\ 18桁の16進数の文字列をxdoubleの内部表現と見なして数値または特別な数値に変換する \\ s 18桁の16進数の文字列 \\ x 数値または特別な数値 xdhtonum(s)=xdbtonum(hex(s)); \\x=efhtonum(s) \\ 28桁の16進数の文字列をefpの内部表現と見なして数値または特別な数値に変換する \\ s 28桁の16進数の文字列 \\ x 数値または特別な数値 efhtonum(s)=efptonum(hex(s)); \\y=round_fw(x,fw,rm) \\ 数値または特別な数値xを仮数部が(1+fw)bitの数値または特別な数値に丸めモードrmで丸める \\ 指数部は無制限 \\ 指数部が無制限なので正規化数と非正規化数の範囲は設定されない \\ 絶対値の大きい数値がオーバーフローして±Infに変化することはない \\ 絶対値の小さい数値がアンダーフローして±0に変化することはない(log2(abs(x))を計算できない場合を除く) \\ ±Infや±0が丸めモードによって数値に変化することはない \\ y 仮数部が(1+fw)bitの数値または特別な数値 \\ x 数値または特別な数値 \\ fw 小数部のbit数 \\ rm 丸めモード \\ fpsr \\ UF アンダーフロー。log2(abs(x))を計算できない場合 \\ X2 不正確な結果 round_fw(x,fw,rm)={ my(a,e,t,m); if(type(x)=="t_POL",return(x)); \\特別な数値はそのまま返す if(x==0,return(Rei)); \\数値の0はReiに変換する a=abs(x); \\絶対値 if(a<=LOG_ZERO, \\0ではないが0に近すぎてlog2(abs(x))を計算できない fpsr=bitor(fpsr,UF+X2); \\アンダーフロー、不正確な結果 return(if(x<0,-Rei,Rei))); \\±0 e=floor(log2(a)); \\指数 t=a*2^(fw-e); m=floor(t); \\仮数部の先頭(1+fw)bit t-=m; \\仮数部の端数 if(t!=0, \\端数がある fpsr=bitor(fpsr,X2); \\不正確な結果 if(((rm==RN)&&(((1/2)<t)|| ((t==(1/2))&&(bitand(m,1)==1))))|| \\RNで端数が1/2より大きいか端数が1/2と等しくて1の位が1 ((rm==RM)&&(x<0))|| \\端数が0ではなくてRMで-または ((rm==RP)&&(0<x)), \\端数が0ではなくてRPで+ m++; \\切り上げる if(m==1<<(1+fw), \\1桁増えた m=1<<fw; e++))); \\指数部をインクリメントする if((m<2^fw)||(2^(1+fw)<=m),error("round_fw(",x,",",rm,",",fw,")")); sign(x)*m*2^(e-fw) } \\y=roundsgl(x,rm) \\ 数値または特別な数値xを仮数部が(1+23)bitの数値または特別な数値に丸めモードrmで丸める \\ 指数部は無制限 \\ y 仮数部が(1+23)bitの数値または特別な数値 \\ x 数値または特別な数値 \\ rm 丸めモード \\ fpsr \\ UF アンダーフロー。log2(abs(x))を計算できない場合 \\ X2 不正確な結果 roundsgl(x,rm)=round_fw(x,23,rm); \\y=rounddbl(x,rm) \\ 数値または特別な数値xを仮数部が(1+52)bitの数値または特別な数値に丸めモードrmで丸める \\ 指数部は無制限 \\ y 仮数部が(1+52)bitの数値または特別な数値 \\ x 数値または特別な数値 \\ rm 丸めモード \\ fpsr \\ UF アンダーフロー。log2(abs(x))を計算できない場合 \\ X2 不正確な結果 rounddbl(x,rm)=round_fw(x,52,rm); \\y=roundexd(x,rm) \\ 数値または特別な数値xを仮数部が(1+63)bitの数値または特別な数値に丸めモードrmで丸める \\ 指数部は無制限 \\ y 仮数部が(1+63)bitの数値または特別な数値 \\ x 数値または特別な数値 \\ rm 丸めモード \\ fpsr \\ UF アンダーフロー。log2(abs(x))を計算できない場合 \\ X2 不正確な結果 roundexd(x,rm)=round_fw(x,63,rm); \\y=roundtpl(x,rm) \\ 数値または特別な数値xを仮数部が(1+79)bitの数値または特別な数値に丸めモードrmで丸める \\ 指数部は無制限 \\ y 仮数部が(1+79)bitの数値または特別な数値 \\ x 数値または特別な数値 \\ rm 丸めモード \\ fpsr \\ UF アンダーフロー。log2(abs(x))を計算できない場合 \\ X2 不正確な結果 roundtpl(x,rm)=round_fw(x,79,rm); \\y=roundqpl(x,rm) \\ 数値または特別な数値xを仮数部が(1+112)bitの数値または特別な数値に丸めモードrmで丸める \\ 指数部は無制限 \\ y 仮数部が(1+112)bitの数値または特別な数値 \\ x 数値または特別な数値 \\ rm 丸めモード \\ fpsr \\ UF アンダーフロー。log2(abs(x))を計算できない場合 \\ X2 不正確な結果 roundqpl(x,rm)=round_fw(x,112,rm); \\y=roundspl(x,rm) \\ 数値または特別な数値xを仮数部が(1+176)bitの数値または特別な数値に丸めモードrmで丸める \\ 指数部は無制限 \\ y 仮数部が(1+176)bitの数値または特別な数値 \\ x 数値または特別な数値 \\ rm 丸めモード \\ fpsr \\ UF アンダーフロー。log2(abs(x))を計算できない場合 \\ X2 不正確な結果 roundspl(x,rm)=round_fw(x,176,rm); \\y=roundopl(x,rm) \\ 数値または特別な数値xを仮数部が(1+240)bitの数値または特別な数値に丸めモードrmで丸める \\ 指数部は無制限 \\ y 仮数部が(1+240)bitの数値または特別な数値 \\ x 数値または特別な数値 \\ rm 丸めモード \\ fpsr \\ UF アンダーフロー。log2(abs(x))を計算できない場合 \\ X2 不正確な結果 roundopl(x,rm)=round_fw(x,240,rm); \\y=roundefp(x,rm) \\ 数値または特別な数値xを仮数部が(1+91)bitの数値または特別な数値に丸めモードrmで丸める \\ 指数部は無制限 \\ y 仮数部が(1+91)bitの数値または特別な数値 \\ x 数値または特別な数値 \\ rm 丸めモード \\ fpsr \\ UF アンダーフロー。log2(abs(x))を計算できない場合 \\ X2 不正確な結果 roundefp(x,rm)=round_fw(x,91,rm); \\y=roundxxx(x,rp,rm) \\ 数値または特別な数値xを仮数部が丸め桁数rpと同じbit数の数値または特別な数値に丸めモードrmで丸める \\ 指数部は無制限 \\ y 仮数部が丸め桁数rpと同じbit数の数値または特別な数値 \\ x 数値または特別な数値 \\ rm 丸めモード \\ fpsr \\ UF アンダーフロー。log2(abs(x))を計算できない場合 \\ X2 不正確な結果 roundxxx(x,rp,rm)={ if(rp==SGL,roundsgl(x,rm), (rp==DBL)||(rp==DBL3),rounddbl(x,rm), rp==EXD,roundexd(x,rm), rp==TPL,roundtpl(x,rm), rp==QPL,roundqpl(x,rm), rp==SPL,roundspl(x,rm), rp==OPL,roundopl(x,rm), rp==EFP,roundefp(x,rm), error("roundxxx(",x,",",rp,",",rm,")")) } \\u=numtoxxx(x,rm,ew,iw,fw) \\ 数値または特別な数値を浮動小数点数の内部表現の符号なし整数に変換する \\ 数値が特別な数値に変化することがある \\ 絶対値の大きい数値が±Infに変化することがある(オーバーフロー) \\ 絶対値の小さい数値が±0に変化することがある(アンダーフロー) \\ ±Infや±0が丸めモードによって数値に変化することがある \\ u (1+ew+iw+fw)bit符号なし整数 \\ x 数値または特別な数値 \\ rm 丸めモード \\ ew 浮動小数点数の内部表現の指数部のbit数 \\ iw 浮動小数点数の内部表現の整数部のbit数 \\ fw 浮動小数点数の内部表現の小数部のbit数 \\ fpsr \\ OF オーバーフロー \\ 指数部が正規化数の最大値を上回っているときセット \\ 0に近付く方向に丸めて正規化数の最大値になったときもセット \\ UF アンダーフロー \\ singleまたはdoubleの \\ 丸める前の値が0でなくて正規化数の最小値を下回っているときセット \\ (丸めた結果が正規化数の最小値になったときもセットされる) \\ extendedまたはxsingle \\ 丸めた結果が非正規化数のときセット \\ X2 不正確な結果 \\ 丸める前の値の端数が0でないときセット \\ アンダーフローしたときセット \\ オーバーフローしたときは端数が0でないときだけセット numtoxxx(x,rm,ew,iw,fw)={ my(bias,demin,demax,nomin,nomax,a,z,e,o,t,m); bias=(1<<(ew-1))-1; \\指数のバイアス demin=1-iw-bias-fw; \\非正規化数の指数の下限 demax=-iw-bias; \\非正規化数の指数の上限 nomin=1-iw-bias; \\正規化数の指数の下限 nomax=bias; \\正規化数の指数の上限 if(type(x)=="t_POL", return(if(x==Rei,if(rm==RP,1,0), x==-Rei,(1<<(ew+iw+fw))+if(rm==RM,1,0), x==Inf,(((1<<ew)-1)<<(iw+fw))-if((rm==RZ)||(rm==RM),1,0), x==-Inf,(1<<(ew+iw+fw))+(((1<<ew)-1)<<(iw+fw))-if((rm==RZ)||(rm==RP),1,0), x==NaN,(1<<(ew+iw+fw))-1, error("numtoxxx(",x,",",rm,",",ew,",",iw,",",rw,")")))); a=abs(x); \\絶対値 z=if(x<0,1<<(ew+iw+fw),0); \\符号 if(x==0,return(z)); \\±0 if(a<=LOG_ZERO, \\0ではないが0に近すぎる。0に近すぎるとlog2(a)の計算に失敗する fpsr=bitor(fpsr,UF+X2); \\アンダーフロー、不正確な結果 return(z)); \\±0 e=floor(log2(a)); \\指数 \\if(a<2^e,e--); \\補正する if(e<demin-1, \\指数部が小さすぎる。丸めで繰り上がる場合があるので一旦非正規化数の指数の下限-1まで受け入れる fpsr=bitor(fpsr,UF+X2); \\アンダーフロー、不正確な結果 \\符号を跨がず±0から遠ざかる方向に丸めるときは±0ではなく絶対値が最小の非正規化数を返す return(z+if(((x<0)&&(rm==RM))||((0<x)&&(rm==RP)),1,0))); o=if(demax<e,1+fw,e-demax+fw); \\1+小数部のbit数。正規化数のときo==1+fw、非正規化数のときo<1+fw t=a*2^(o-1-e); m=floor(t); \\仮数部の先頭(o)bit t-=m; \\仮数部の端数 if(if(o==0,m!=0,(m<2^(o-1))||(2^o<=m)),error("numtoxxx(",x,",",rm,",",ew,",",iw,",",fw,")")); if(nomax<e, \\指数部が大きすぎる fpsr=bitor(fpsr,OF); \\オーバーフロー if(t!=0,fpsr=bitor(fpsr,X2)); \\不正確な結果 \\±0に近付く方向に丸めるときは±Infではなく絶対値が最大の正規化数を返す return(z+(((1<<ew)-1)<<(iw+fw))-if(((x<0)&&((rm==RZ)||(rm==RP)))||((0<x)&&((rm==RZ)||(rm==RM))),1,0))); if(ew<15, \\singleまたはdoubleのとき if(o<1+fw, \\非正規化数 fpsr=bitor(fpsr,UF))); \\アンダーフロー if(t!=0, \\端数が0ではない fpsr=bitor(fpsr,X2); \\不正確な結果 if(((rm==RN)&&(((1/2)<t)|| ((t==(1/2))&&(bitand(m,1)==1))))|| \\RNで端数が1/2より大きいか端数が1/2と等しくて1の位が1 ((rm==RM)&&(x<0))|| \\端数が0ではなくてRMで-または ((rm==RP)&&(0<x)), \\端数が0ではなくてRPで+のとき m++; \\繰り上げる if(m==(1<<o), \\1桁増えた if(o==1+fw, \\正規化数が溢れた m>>=1; e++; \\指数部をインクリメントする if(nomax<e, \\指数部が溢れた fpsr=bitor(fpsr,OF); \\オーバーフロー \\±0に近付く方向に丸めるときは±Infではなく絶対値が最大の正規化数を返す return(z+(((1<<ew)-1)<<(iw+fw))-if(((x<0)&&((rm==RZ)||(rm==RP)))||((0<x)&&((rm==RZ)||(rm==RM))),1,0))), m==(1<<fw), \\非正規化数が正規化数になった e=nomin)))); if(e<nomin, \\非正規化数 fpsr=bitor(fpsr,UF)); \\アンダーフロー if(m==0, \\非正規化数が指数の下限-1から繰り上がらなかった \\符号を跨がず±0から遠ざかる方向に丸めるときは±0ではなく絶対値が最小の非正規化数を返す return(z+if(((x<0)&&(rm==RM))||((0<x)&&(rm==RP)),1,0))); z+(if(0<=bias+e,bias+e,0)<<(iw+fw))+bitand(m,(1<<(iw+fw))-1) } numtoxxx2(x,rm,ew,iw,fw)={ my(bias,demin,demax,nomin,nomax,a,z,e,o,t,m); bias=(1<<(ew-1))-1; \\指数のバイアス demin=1-iw-bias-fw; \\非正規化数の指数の下限 demax=-iw-bias; \\非正規化数の指数の上限 nomin=1-iw-bias; \\正規化数の指数の下限 nomax=bias; \\正規化数の指数の上限 if(type(x)=="t_POL", return(if(x==Rei,if(rm==RP,1,0), x==-Rei,(1<<(ew+iw+fw))+if(rm==RM,1,0), x==Inf,(((1<<ew)-1)<<(iw+fw))-if((rm==RZ)||(rm==RM),1,0), x==-Inf,(1<<(ew+iw+fw))+(((1<<ew)-1)<<(iw+fw))-if((rm==RZ)||(rm==RP),1,0), x==NaN,(1<<(ew+iw+fw))-1, error("numtoxxx(",x,",",rm,",",ew,",",iw,",",rw,")")))); a=abs(x); \\絶対値 z=if(x<0,1<<(ew+iw+fw),0); \\符号 if(x==0,return(z)); \\±0 if(a<=LOG_ZERO, \\0ではないが0に近すぎる。0に近すぎるとlog2(a)の計算に失敗する fpsr=bitor(fpsr,UF+X2); \\アンダーフロー、不正確な結果 return(z)); \\±0 e=floor(log2(a)); \\指数 \\if(a<2^e,e--); \\補正する if(e<demin-1, \\指数部が小さすぎる。丸めで繰り上がる場合があるので一旦非正規化数の指数の下限-1まで受け入れる fpsr=bitor(fpsr,UF+X2); \\アンダーフロー、不正確な結果 \\符号を跨がず±0から遠ざかる方向に丸めるときは±0ではなく絶対値が最小の非正規化数を返す return(z+if(((x<0)&&(rm==RM))||((0<x)&&(rm==RP)),1,0))); o=if(demax<e,1+fw,e-demax+fw); \\1+小数部のbit数。正規化数のときo==1+fw、非正規化数のときo<1+fw t=a*2^(o-1-e); m=floor(t); \\仮数部の先頭(o)bit t-=m; \\仮数部の端数 if(if(o==0,m!=0,(m<2^(o-1))||(2^o<=m)),error("numtoxxx(",x,",",rm,",",ew,",",iw,",",fw,")")); if(nomax<e, \\指数部が大きすぎる fpsr=bitor(fpsr,OF); \\オーバーフロー if(t!=0,fpsr=bitor(fpsr,X2)); \\不正確な結果 \\±0に近付く方向に丸めるときは±Infではなく絶対値が最大の正規化数を返す return(z+(((1<<ew)-1)<<(iw+fw))-if(((x<0)&&((rm==RZ)||(rm==RP)))||((0<x)&&((rm==RZ)||(rm==RM))),1,0))); if(o<1+fw, \\非正規化数 fpsr=bitor(fpsr,UF)); \\アンダーフロー if(t!=0, \\端数が0ではない fpsr=bitor(fpsr,X2); \\不正確な結果 if(((rm==RN)&&(((1/2)<t)|| ((t==(1/2))&&(bitand(m,1)==1))))|| \\RNで端数が1/2より大きいか端数が1/2と等しくて1の位が1 ((rm==RM)&&(x<0))|| \\端数が0ではなくてRMで-または ((rm==RP)&&(0<x)), \\端数が0ではなくてRPで+のとき m++; \\繰り上げる if(m==(1<<o), \\1桁増えた if(o==1+fw, \\正規化数が溢れた m>>=1; e++; \\指数部をインクリメントする if(nomax<e, \\指数部が溢れた fpsr=bitor(fpsr,OF); \\オーバーフロー \\±0に近付く方向に丸めるときは±Infではなく絶対値が最大の正規化数を返す return(z+(((1<<ew)-1)<<(iw+fw))-if(((x<0)&&((rm==RZ)||(rm==RP)))||((0<x)&&((rm==RZ)||(rm==RM))),1,0))), m==(1<<fw), \\非正規化数が正規化数になった e=nomin)))); if(e<nomin, \\非正規化数 fpsr=bitor(fpsr,UF)); \\アンダーフロー if(m==0, \\非正規化数が指数の下限-1から繰り上がらなかった \\符号を跨がず±0から遠ざかる方向に丸めるときは±0ではなく絶対値が最小の非正規化数を返す return(z+if(((x<0)&&(rm==RM))||((0<x)&&(rm==RP)),1,0))); z+(if(0<=bias+e,bias+e,0)<<(iw+fw))+bitand(m,(1<<(iw+fw))-1) } \\u=numtosgl(x,rm) \\ 数値または特別な数値をsingleの内部表現の32bit符号なし整数に変換する \\ u 32bit符号なし整数 \\ x 数値または特別な数値 \\ rm 丸めモード \\ fpsr \\ OF オーバーフロー \\ UF アンダーフロー \\ X2 不正確な結果 numtosgl(x,rm)=numtoxxx(x,rm,8,0,23); \\u=numtodbl(x,rm) \\ 数値または特別な数値をdoubleの内部表現の64bit符号なし整数に変換する \\ u 64bit符号なし整数 \\ x 数値または特別な数値 \\ rm 丸めモード \\ fpsr \\ OF オーバーフロー \\ UF アンダーフロー \\ X2 不正確な結果 numtodbl(x,rm)=numtoxxx(x,rm,11,0,52); \\u=numtoexd(x,rm) \\ 数値または特別な数値をextendedの内部表現の96bit符号なし整数に変換する \\ u 96bit符号なし整数 \\ x 数値または特別な数値 \\ rm 丸めモード \\ fpsr \\ OF オーバーフロー \\ UF アンダーフロー \\ X2 不正確な結果 numtoexd(x,rm)={ my(u); u=numtoxxx(x,rm,15,1,63); \\ |符号部と指数部(16bit)|仮数部(64bit)| \\ ↓ \\ |符号部と指数部(16bit)|空き(16bit)|仮数部(64bit)| ((bitand(u,(1<<80)-(1<<64))<<16)+ \\符号部と指数部(16bit) bitand(u,(1<<64)-(1<<0))) \\仮数部(64bit) } numtoexd2(x,rm)={ my(u); u=numtoxxx2(x,rm,15,1,63); \\ |符号部と指数部(16bit)|仮数部(64bit)| \\ ↓ \\ |符号部と指数部(16bit)|空き(16bit)|仮数部(64bit)| ((bitand(u,(1<<80)-(1<<64))<<16)+ \\符号部と指数部(16bit) bitand(u,(1<<64)-(1<<0))) \\仮数部(64bit) } \\u=numtotpl(x,rm) \\ 数値または特別な数値をtripleの内部表現の96bit符号なし整数に変換する \\ u 96bit符号なし整数 \\ x 数値または特別な数値 \\ rm 丸めモード \\ fpsr \\ OF オーバーフロー \\ UF アンダーフロー \\ X2 不正確な結果 numtotpl(x,rm)={ my(u); u=numtoxxx(x,rm,15,1,79); \\ |符号部と指数部(16bit)|仮数部の上位(64bit)|仮数部の下位(16bit)| \\ ↓ \\ |符号部と指数部(16bit)|仮数部の下位(16bit)|仮数部の上位(64bit)| (bitand(u,(1<<96)-(1<<80))+ \\符号部と指数部(16bit) (bitand(u,(1<<16)-(1<<0))<<64)+ \\仮数部の下位(16bit) (bitand(u,(1<<80)-(1<<16))>>16)) \\仮数部の上位(64bit) } \\u=numtoqpl(x,rm) \\ 数値または特別な数値をquadrupleの内部表現の128bit符号なし整数に変換する \\ u 128bit符号なし整数 \\ x 数値または特別な数値 \\ rm 丸めモード \\ fpsr \\ OF オーバーフロー \\ UF アンダーフロー \\ X2 不正確な結果 numtoqpl(x,rm)=numtoxxx(x,rm,15,0,112); \\u=numtospl(x,rm) \\ 数値または特別な数値をsextupleの内部表現の192bit符号なし整数に変換する \\ u 192bit符号なし整数 \\ x 数値または特別な数値 \\ rm 丸めモード \\ fpsr \\ OF オーバーフロー \\ UF アンダーフロー \\ X2 不正確な結果 numtospl(x,rm)=numtoxxx(x,rm,15,0,176); \\u=numtoopl(x,rm) \\ 数値または特別な数値をoctupleの内部表現の256bit符号なし整数に変換する \\ u 256bit符号なし整数 \\ x 数値または特別な数値 \\ rm 丸めモード \\ fpsr \\ OF オーバーフロー \\ UF アンダーフロー \\ X2 不正確な結果 numtoopl(x,rm)=numtoxxx(x,rm,15,0,240); \\u=numtoxsg(x,rm) \\ 数値または特別な数値をxsingleの内部表現の40bit符号なし整数に変換する \\ u 40bit符号なし整数 \\ x 数値または特別な数値 \\ rm 丸めモード \\ fpsr \\ OF オーバーフロー \\ UF アンダーフロー \\ X2 不正確な結果 numtoxsg(x,rm)=numtoxxx(x,rm,15,1,23); \\u=numtoxdb(x,rm) \\ 数値または特別な数値をxdoubleの内部表現の69bit符号なし整数に変換する \\ u 69bit符号なし整数 \\ x 数値または特別な数値 \\ rm 丸めモード \\ fpsr \\ OF オーバーフロー \\ UF アンダーフロー \\ X2 不正確な結果 numtoxdb(x,rm)=numtoxxx(x,rm,15,1,52); \\u=numtoefp(x,rm) \\ 数値または特別な数値をefpの内部表現の109bit符号なし整数に変換する \\ u 109bit符号なし整数 \\ x 数値または特別な数値 \\ rm 丸めモード \\ fpsr \\ OF オーバーフロー \\ UF アンダーフロー \\ X2 不正確な結果 numtoefp(x,rm)=numtoxxx(x,rm,16,1,91); \\s=numtosgh(x,rm) \\ 数値または特別な数値をsingleの内部表現を表す8桁の16進数の文字列に変換する \\ s 8桁の16進数の文字列 \\ x 数値または特別な数値 \\ rm 丸めモード \\ fpsr \\ OF オーバーフロー \\ UF アンダーフロー \\ X2 不正確な結果 numtosgh(x,rm)=hex8(numtosgl(x,rm)); \\s=numtodbh(x,rm) \\ 数値または特別な数値をdoubleの内部表現を表す16桁の16進数の文字列に変換する \\ s 16桁の16進数の文字列 \\ x 数値または特別な数値 \\ rm 丸めモード \\ fpsr \\ OF オーバーフロー \\ UF アンダーフロー \\ X2 不正確な結果 numtodbh(x,rm)=hex16(numtodbl(x,rm)); \\s=numtoexh(x,rm) \\ 数値または特別な数値をextendedの内部表現を表す24桁の16進数の文字列に変換する \\ s 24桁の16進数の文字列 \\ x 数値または特別な数値 \\ rm 丸めモード \\ fpsr \\ OF オーバーフロー \\ UF アンダーフロー \\ X2 不正確な結果 numtoexh(x,rm)=hex24(numtoexd(x,rm)); \\s=numtotph(x,rm) \\ 数値または特別な数値をtripleの内部表現を表す24桁の16進数の文字列に変換する \\ s 24桁の16進数の文字列 \\ x 数値または特別な数値 \\ rm 丸めモード \\ fpsr \\ OF オーバーフロー \\ UF アンダーフロー \\ X2 不正確な結果 numtotph(x,rm)=hex24(numtotpl(x,rm)); \\s=numtoqph(x,rm) \\ 数値または特別な数値をquadrupleの内部表現を表す32桁の16進数の文字列に変換する \\ s 32桁の16進数の文字列 \\ x 数値または特別な数値 \\ rm 丸めモード \\ fpsr \\ OF オーバーフロー \\ UF アンダーフロー \\ X2 不正確な結果 numtoqph(x,rm)=hex32(numtoqpl(x,rm)); \\s=numtosph(x,rm) \\ 数値または特別な数値をsextupleの内部表現を表す48桁の16進数の文字列に変換する \\ s 48桁の16進数の文字列 \\ x 数値または特別な数値 \\ rm 丸めモード \\ fpsr \\ OF オーバーフロー \\ UF アンダーフロー \\ X2 不正確な結果 numtosph(x,rm)=hex48(numtospl(x,rm)); \\s=numtooph(x,rm) \\ 数値または特別な数値をoctupleの内部表現を表す64桁の16進数の文字列に変換する \\ s 64桁の16進数の文字列 \\ x 数値または特別な数値 \\ rm 丸めモード \\ fpsr \\ OF オーバーフロー \\ UF アンダーフロー \\ X2 不正確な結果 numtooph(x,rm)=hex64(numtoopl(x,rm)); \\s=numtoxsh(x,rm) \\ 数値または特別な数値をxsingleの内部表現を表す10桁の16進数の文字列に変換する \\ s 10桁の16進数の文字列 \\ x 数値または特別な数値 \\ rm 丸めモード \\ fpsr \\ OF オーバーフロー \\ UF アンダーフロー \\ X2 不正確な結果 numtoxsh(x,rm)=hex10(numtoxsg(x,rm)); \\s=numtoxdh(x,rm) \\ 数値または特別な数値をxdoubleの内部表現を表す18桁の16進数の文字列に変換する \\ s 18桁の16進数の文字列 \\ x 数値または特別な数値 \\ rm 丸めモード \\ fpsr \\ OF オーバーフロー \\ UF アンダーフロー \\ X2 不正確な結果 numtoxdh(x,rm)=hex18(numtoxdb(x,rm)); \\s=numtoefh(x,rm) \\ 数値または特別な数値をefpの内部表現を表す28桁の16進数の文字列に変換する \\ s 28桁の16進数の文字列 \\ x 数値または特別な数値 \\ rm 丸めモード \\ fpsr \\ OF オーバーフロー \\ UF アンダーフロー \\ X2 不正確な結果 numtoefh(x,rm)=hex28(numtoefp(x,rm)); \\y=sgl(x,rm) \\ 数値または特別な数値をsingleで表現できる数値または特別な数値に丸めモードrmで丸める \\ y singleで表現できる数値または特別な数値 \\ x 数値または特別な数値 \\ rm 丸めモード \\ fpsr \\ OF オーバーフロー \\ UF アンダーフロー \\ X2 不正確な結果 sgl(x,rm)=sgltonum(numtosgl(x,rm)); \\y=dbl(x,rm) \\ 数値または特別な数値をdoubleで表現できる数値または特別な数値に丸めモードrmで丸める \\ y doubleで表現できる数値または特別な数値 \\ x 数値または特別な数値 \\ rm 丸めモード \\ fpsr \\ OF オーバーフロー \\ UF アンダーフロー \\ X2 不正確な結果 dbl(x,rm)=dbltonum(numtodbl(x,rm)); \\y=exd(x,rm) \\ 数値または特別な数値をextendedで表現できる数値または特別な数値に丸めモードrmで丸める \\ y extendedで表現できる数値または特別な数値 \\ x 数値または特別な数値 \\ rm 丸めモード \\ fpsr \\ OF オーバーフロー \\ UF アンダーフロー \\ X2 不正確な結果 exd(x,rm)=exdtonum(numtoexd(x,rm)); exd2(x,rm)=exdtonum(numtoexd2(x,rm)); \\y=tpl(x,rm) \\ 数値または特別な数値をtripleで表現できる数値または特別な数値に丸めモードrmで丸める \\ y tripleで表現できる数値または特別な数値 \\ x 数値または特別な数値 \\ rm 丸めモード \\ fpsr \\ OF オーバーフロー \\ UF アンダーフロー \\ X2 不正確な結果 tpl(x,rm)=tpltonum(numtotpl(x,rm)); \\y=qpl(x,rm) \\ 数値または特別な数値をquadrupleで表現できる数値または特別な数値に丸めモードrmで丸める \\ y quadrupleで表現できる数値または特別な数値 \\ x 数値または特別な数値 \\ rm 丸めモード \\ fpsr \\ OF オーバーフロー \\ UF アンダーフロー \\ X2 不正確な結果 qpl(x,rm)=qpltonum(numtoqpl(x,rm)); \\y=spl(x,rm) \\ 数値または特別な数値をsextupleで表現できる数値または特別な数値に丸めモードrmで丸める \\ y sextupleで表現できる数値または特別な数値 \\ x 数値または特別な数値 \\ rm 丸めモード \\ fpsr \\ OF オーバーフロー \\ UF アンダーフロー \\ X2 不正確な結果 spl(x,rm)=spltonum(numtospl(x,rm)); \\y=opl(x,rm) \\ 数値または特別な数値をoctupleで表現できる数値または特別な数値に丸めモードrmで丸める \\ y octupleで表現できる数値または特別な数値 \\ x 数値または特別な数値 \\ rm 丸めモード \\ fpsr \\ OF オーバーフロー \\ UF アンダーフロー \\ X2 不正確な結果 opl(x,rm)=opltonum(numtoopl(x,rm)); \\y=xsg(x,rm) \\ 数値または特別な数値をxsingleで表現できる数値または特別な数値に丸めモードrmで丸める \\ y xsingleで表現できる数値または特別な数値 \\ x 数値または特別な数値 \\ rm 丸めモード \\ fpsr \\ OF オーバーフロー \\ UF アンダーフロー \\ X2 不正確な結果 xsg(x,rm)=xsgtonum(numtoxsg(x,rm)); \\y=xdb(x,rm) \\ 数値または特別な数値をxdoubleで表現できる数値または特別な数値に丸めモードrmで丸める \\ y xdoubleで表現できる数値または特別な数値 \\ x 数値または特別な数値 \\ rm 丸めモード \\ fpsr \\ OF オーバーフロー \\ UF アンダーフロー \\ X2 不正確な結果 xdb(x,rm)=xdbtonum(numtoxdb(x,rm)); \\y=efp(x,rm) \\ 数値または特別な数値をefpで表現できる数値または特別な数値に丸めモードrmで丸める \\ y efpで表現できる数値または特別な数値 \\ x 数値または特別な数値 \\ rm 丸めモード \\ fpsr \\ OF オーバーフロー \\ UF アンダーフロー \\ X2 不正確な結果 efp(x,rm)=efptonum(numtoefp(x,rm)); \\y=xxx(x,rp,rm) \\ 数値または特別な数値を丸め桁数rpで表現できる数値または特別な数値に丸めモードrmで丸める \\ y 数値を丸め桁数rpで表現できる数値または特別な数値 \\ x 数値または特別な数値 \\ rp 丸め桁数 \\ rm 丸めモード \\ fpsr \\ OF オーバーフロー \\ UF アンダーフロー \\ X2 不正確な結果 xxx(x,rp,rm)={ if(rp==SGL,sgl(x,rm), (rp==DBL)||(rp==DBL3),dbl(x,rm), rp==EXD,exd(x,rm), rp==TPL,tpl(x,rm), rp==QPL,qpl(x,rm), rp==SPL,spl(x,rm), rp==OPL,opl(x,rm), rp==XSG,xsg(x,rm), rp==XDB,xdb(x,rm), rp==EFP,efp(x,rm), error("xxx(",x,",",rp,",",rm,")")) } xxx2(x,rp,rm)={ if(rp==SGL,sgl(x,rm), (rp==DBL)||(rp==DBL3),dbl(x,rm), rp==EXD,exd2(x,rm), rp==TPL,tpl(x,rm), rp==QPL,qpl(x,rm), rp==SPL,spl(x,rm), rp==OPL,opl(x,rm), rp==XSG,xsg(x,rm), rp==XDB,xdb(x,rm), rp==EFP,efp(x,rm), error("xxx(",x,",",rp,",",rm,")")) } \\s=numtosgi(x,rm) \\ 数値または特別な数値をsingleの内部表現を表す1個の8桁の16進数の文字列に変換する \\ s singleの内部表現を表す1個の8桁の16進数の文字列 \\ x 数値または特別な数値 \\ rm 丸めモード \\ fpsr \\ OF オーバーフロー \\ UF アンダーフロー \\ X2 不正確な結果 numtosgi(x,rm)=hex8imm(numtosgl(x,rm)); \\s=numtodbi(x,rm) \\ 数値または特別な数値をdoubleの内部表現を表す2個の8桁の16進数の文字列に変換する \\ s doubleの内部表現を表す2個の8桁の16進数の文字列 \\ x 数値または特別な数値 \\ rm 丸めモード \\ fpsr \\ OF オーバーフロー \\ UF アンダーフロー \\ X2 不正確な結果 numtodbi(x,rm)=hex16imm(numtodbl(x,rm)); \\s=numtoexi(x,rm) \\ 数値または特別な数値をextendedのメモリ内部表現を表す3個の8桁の16進数の文字列に変換する \\ s extendedの内部表現を表す3個の8桁の16進数の文字列 \\ x 数値または特別な数値 \\ rm 丸めモード \\ fpsr \\ OF オーバーフロー \\ UF アンダーフロー \\ X2 不正確な結果 numtoexi(x,rm)=hex24imm(numtoexd(x,rm)); \\s=numtotpi(x,rm) \\ 数値または特別な数値をtripleのメモリ内部表現を表す3個の8桁の16進数の文字列に変換する \\ s tripleの内部表現を表す3個の8桁の16進数の文字列 \\ x 数値または特別な数値 \\ rm 丸めモード \\ fpsr \\ OF オーバーフロー \\ UF アンダーフロー \\ X2 不正確な結果 numtotpi(x,rm)=hex24imm(numtotpl(x,rm)); \\s=numtoqpi(x,rm) \\ 数値または特別な数値をquadrupleの内部表現を表す4個の8桁の16進数の文字列に変換する \\ s quadrupleの内部表現を表す4個の8桁の16進数の文字列 \\ x 数値または特別な数値 \\ rm 丸めモード \\ fpsr \\ OF オーバーフロー \\ UF アンダーフロー \\ X2 不正確な結果 numtoqpi(x,rm)=hex32imm(numtoqpl(x,rm)); \\s=numtospi(x,rm) \\ 数値または特別な数値をsextupleの内部表現を表す6個の8桁の16進数の文字列に変換する \\ s sextupleの内部表現を表す6個の8桁の16進数の文字列 \\ x 数値または特別な数値 \\ rm 丸めモード \\ fpsr \\ OF オーバーフロー \\ UF アンダーフロー \\ X2 不正確な結果 numtospi(x,rm)=hex48imm(numtospl(x,rm)); \\s=numtoopi(x,rm) \\ 数値または特別な数値をoctupleの内部表現を表す8個の8桁の16進数の文字列に変換する \\ s octupleの内部表現を表す8個の8桁の16進数の文字列 \\ x 数値または特別な数値 \\ rm 丸めモード \\ fpsr \\ OF オーバーフロー \\ UF アンダーフロー \\ X2 不正確な結果 numtoopi(x,rm)=hex64imm(numtoopl(x,rm)); \\s=numtoxsi(x,rm) \\ 数値または特別な数値をxsingleの内部表現を表す2個の8桁の16進数の文字列に変換する \\ s xsingleの内部表現を表す2個の8桁の16進数の文字列 \\ x 数値または特別な数値 \\ rm 丸めモード \\ fpsr \\ OF オーバーフロー \\ UF アンダーフロー \\ X2 不正確な結果 numtoxsi(x,rm)=hex16imm(numtoxsg(x,rm)); \\s=numtoxdi(x,rm) \\ 数値または特別な数値をxdoubleの内部表現を表す3個の8桁の16進数の文字列に変換する \\ s xdoubleの内部表現を表す3個の8桁の16進数の文字列 \\ x 数値または特別な数値 \\ rm 丸めモード \\ fpsr \\ OF オーバーフロー \\ UF アンダーフロー \\ X2 不正確な結果 numtoxdi(x,rm)=hex24imm(numtoxdb(x,rm)); \\s=numtoefi(x,rm) \\ 数値または特別な数値をefpの内部表現を表す4個の8桁の16進数の文字列に変換する \\ s efpの内部表現を表す4個の8桁の16進数の文字列 \\ x 数値または特別な数値 \\ rm 丸めモード \\ fpsr \\ OF オーバーフロー \\ UF アンダーフロー \\ X2 不正確な結果 numtoefi(x,rm)=hex32imm(numtoefp(x,rm)); \\y=xxxnextdown(x,ew,iw,fw) \\ 数値または特別な数値よりも小さい最大の表現できる数値または特別な数値を返す \\ y xよりも小さい最大の表現できる数値または特別な数値 \\ x 数値または特別な数値 \\ ew 浮動小数点数の内部表現の指数部のbit数 \\ iw 浮動小数点数の内部表現の整数部のbit数 \\ fw 浮動小数点数の内部表現の小数部のbit数 xxxnextdown(x,ew,iw,fw)={ my(bias,demin,demax,nomin,nomax,y); bias=(1<<(ew-1))-1; \\指数のバイアス demin=1-iw-bias-fw; \\非正規化数の指数の下限 demax=-iw-bias; \\非正規化数の指数の上限 nomin=1-iw-bias; \\正規化数の指数の下限 nomax=bias; \\正規化数の指数の上限 if(type(x)=="t_POL", return(if((x==Rei)||(x==-Rei),-2^demin, \\±0の下は負の非正規化数の最大値 x==Inf,2^(nomax+1)-2^(nomax+1-(1+fw)), \\Infの下は正の正規化数の最大値 x==-Inf,-Inf, \\負の無限大で飽和する x==NaN,NaN, error("xxxnextdown(",x,",",ew,",",iw,",",fw,")")))); if(x==0,return(-2^demin)); \\±0の下は負の非正規化数の最大値 if(x==-2^nomin+2^(nomin-fw), \\負の非正規化数の最小値 \\if(ew<15, \\singleまたはdoubleのとき \\ fpsr=bitor(fpsr,UF)); \\アンダーフロー return(-2^nomin)); \\負の正規化数の最大値 y=xxxtonum(numtoxxx(x,RM,ew,iw,fw),ew,iw,fw); \\xと等しいか小さい最大の表現できる数値または特別な数値 if(y==x, \\xが表現できる数値だった y=xxxtonum(numtoxxx(y-abs(y)*2^-(2+fw),RM,ew,iw,fw),ew,iw,fw)); y } \\y=sglnextdown(x) \\y=sglnextnextdown(x) \\ 数値または特別な数値よりも小さい最大のsingleで表現できる数値または特別な数値を返す \\ y xよりも小さい最大のsingleで表現できる数値または特別な数値 \\ x 数値または特別な数値 sglnextdown(x)=xxxnextdown(x,8,0,23); sglnextnextdown(x)=sglnextdown(sglnextdown(x)); \\y=dblnextnextdown(x) \\ 数値または特別な数値よりも小さい最大のdoubleで表現できる数値または特別な数値を返す \\ y xよりも小さい最大のdoubleで表現できる数値または特別な数値 \\ x 数値または特別な数値 dblnextdown(x)=xxxnextdown(x,11,0,52); dblnextnextdown(x)=dblnextdown(dblnextdown(x)); \\y=exdnextdown(x) \\y=exdnextnextdown(x) \\ 数値または特別な数値よりも小さい最大のextendedで表現できる数値または特別な数値を返す \\ y xよりも小さい最大のextendedで表現できる数値または特別な数値 \\ x 数値または特別な数値 exdnextdown(x)=xxxnextdown(x,15,1,63); exdnextnextdown(x)=exdnextdown(exdnextdown(x)); \\y=tplnextdown(x) \\y=tplnextnextdown(x) \\ 数値または特別な数値よりも小さい最大のtripleで表現できる数値または特別な数値を返す \\ y xよりも小さい最大のtripleで表現できる数値または特別な数値 \\ x 数値または特別な数値 tplnextdown(x)=xxxnextdown(x,15,1,79); tplnextnextdown(x)=tplnextdown(tplnextdown(x)); \\y=qplnextdown(x) \\y=qplnextnextdown(x) \\ 数値または特別な数値よりも小さい最大のquadrupleで表現できる数値または特別な数値を返す \\ y xよりも小さい最大のquadrupleで表現できる数値または特別な数値 \\ x 数値または特別な数値 qplnextdown(x)=xxxnextdown(x,15,0,112); qplnextnextdown(x)=qplnextdown(qplnextdown(x)); \\y=splnextdown(x) \\y=splnextnextdown(x) \\ 数値または特別な数値よりも小さい最大のsextupleで表現できる数値または特別な数値を返す \\ y xよりも小さい最大のsextupleで表現できる数値または特別な数値 \\ x 数値または特別な数値 splnextdown(x)=xxxnextdown(x,15,0,176); splnextnextdown(x)=splnextdown(splnextdown(x)); \\y=otpnextdown(x) \\y=otpnextnextdown(x) \\ 数値または特別な数値よりも小さい最大のoctupleで表現できる数値または特別な数値を返す \\ y xよりも小さい最大のoctupleで表現できる数値または特別な数値 \\ x 数値または特別な数値 oplnextdown(x)=xxxnextdown(x,15,0,240); oplnextnextdown(x)=oplnextdown(oplnextdown(x)); \\y=xsgnextdown(x) \\y=xsgnextnextdown(x) \\ 数値または特別な数値よりも小さい最大のxsingleで表現できる数値または特別な数値を返す \\ y xよりも小さい最大のxsingleで表現できる数値または特別な数値 \\ x 数値または特別な数値 xsgnextdown(x)=xxxnextdown(x,15,1,23); xsgnextnextdown(x)=xsgnextdown(xsgnextdown(x)); \\y=xdbnextdown(x) \\y=xdbnextnextdown(x) \\ 数値または特別な数値よりも小さい最大のxdoubleで表現できる数値または特別な数値を返す \\ y xよりも小さい最大のxdoubleで表現できる数値または特別な数値 \\ x 数値または特別な数値 xdbnextdown(x)=xxxnextdown(x,15,1,52); xdbnextnextdown(x)=efpnextdown(xdbnextdown(x)); \\y=efpnextdown(x) \\y=efpnextnextdown(x) \\ 数値または特別な数値よりも小さい最大のefpで表現できる数値または特別な数値を返す \\ y xよりも小さい最大のefpで表現できる数値または特別な数値 \\ x 数値または特別な数値 efpnextdown(x)=xxxnextdown(x,16,1,91); efpnextnextdown(x)=efpnextdown(efpnextdown(x)); \\y=nextdown(x,rp) \\ 数値または特別な数値よりも小さい最大の丸め桁数rpで表現できる数値または特別な数値を返す \\ y xよりも小さい最大の丸め桁数rpで表現できる数値または特別な数値 \\ x 数値または特別な数値 \\ rp 丸め桁数 nextdown(x,rp)={ if(rp==SGL,sglnextdown(x), (rp==DBL)||(rp==DBL3),dblnextdown(x), rp==EXD,exdnextdown(x), rp==TPL,tplnextdown(x), rp==QPL,qplnextdown(x), rp==SPL,splnextdown(x), rp==OPL,oplnextdown(x), rp==XSG,xsgnextdown(x), rp==XDB,xdbnextdown(x), rp==EFP,efpnextdown(x), error("nextdown(",x,",",rp")")) } \\y=xxxnextup(x,ew,iw,fw) \\ 数値または特別な数値よりも大きい最小の表現できる数値または特別な数値を返す \\ y xよりも大きい最小の表現できる数値または特別な数値 \\ x 数値または特別な数値 \\ ew 浮動小数点数の内部表現の指数部のbit数 \\ iw 浮動小数点数の内部表現の整数部のbit数 \\ fw 浮動小数点数の内部表現の小数部のbit数 xxxnextup(x,ew,iw,fw)={ my(bias,demin,demax,nomin,nomax,y); bias=(1<<(ew-1))-1; \\指数のバイアス demin=1-iw-bias-fw; \\非正規化数の指数の下限 demax=-iw-bias; \\非正規化数の指数の上限 nomin=1-iw-bias; \\正規化数の指数の下限 nomax=bias; \\正規化数の指数の上限 if(type(x)=="t_POL", return(if((x==Rei)||(x==-Rei),2^demin, \\±0の上は正の非正規化数の最小値 x==Inf,Inf, \\正の無限大で飽和する x==-Inf,-2^(nomax+1)+2^(nomax+1-(1+fw)), \\-Infの上は負の正規化数の最小値 x==NaN,NaN, error("xxxnextup(",x,",",ew,",",iw,",",fw,")")))); if(x==0,return(2^demin)); \\±0の上は正の非正規化数の最小値 if(x==2^nomin-2^(nomin-fw), \\正の非正規化数の最大値 \\if(ew<15, \\singleまたはdoubleのとき \\ fpsr=bitor(fpsr,UF)); \\アンダーフロー return(2^nomin)); \\正の正規化数の最小値 y=xxxtonum(numtoxxx(x,RP,ew,iw,fw),ew,iw,fw); \\xと等しいか大きい最小の表現できる数値または特別な数値 if(y==x, \\xが表現できる数値だった y=xxxtonum(numtoxxx(y+abs(y)*2^-(2+fw),RP,ew,iw,fw),ew,iw,fw)); y } \\y=sglnextup(x) \\y=sglnextnextup(x) \\ 数値または特別な数値よりも大きい最小のsingleで表現できる数値または特別な数値を返す \\ y xよりも大きい最小のsingleで表現できる数値または特別な数値 \\ x 数値または特別な数値 sglnextup(x)=xxxnextup(x,8,0,23); sglnextnextup(x)=sglnextup(sglnextup(x)); \\y=dblnextup(x) \\y=dblnextnextup(x) \\ 数値または特別な数値よりも大きい最小のdoubleで表現できる数値または特別な数値を返す \\ y xよりも大きい最小のdoubleで表現できる数値または特別な数値 \\ x 数値または特別な数値 dblnextup(x)=xxxnextup(x,11,0,52); dblnextnextup(x)=dblnextup(dblnextup(x)); \\y=exdnextup(x) \\y=exdnextnextup(x) \\ 数値または特別な数値よりも大きい最小のextendedで表現できる数値または特別な数値を返す \\ y xよりも大きい最小のextendedで表現できる数値または特別な数値 \\ x 数値または特別な数値 exdnextup(x)=xxxnextup(x,15,1,63); exdnextnextup(x)=exdnextup(exdnextup(x)); \\y=tplnextup(x) \\y=tplnextnextup(x) \\ 数値または特別な数値よりも大きい最小のtripleで表現できる数値または特別な数値を返す \\ y xよりも大きい最小のtripleで表現できる数値または特別な数値 \\ x 数値または特別な数値 tplnextup(x)=xxxnextup(x,15,1,79); tplnextnextup(x)=tplnextup(tplnextup(x)); \\y=qplnextup(x) \\y=qplnextnextup(x) \\ 数値または特別な数値よりも大きい最小のquadrupleで表現できる数値または特別な数値を返す \\ y xよりも大きい最小のquadrupleで表現できる数値または特別な数値 \\ x 数値または特別な数値 qplnextup(x)=xxxnextup(x,15,0,112); qplnextnextup(x)=qplnextup(qplnextup(x)); \\y=splnextup(x) \\y=splnextnextup(x) \\ 数値または特別な数値よりも大きい最小のsextupleで表現できる数値または特別な数値を返す \\ y xよりも大きい最小のsextupleで表現できる数値または特別な数値 \\ x 数値または特別な数値 splnextup(x)=xxxnextup(x,15,0,176); splnextnextup(x)=splnextup(splnextup(x)); \\y=otpnextup(x) \\y=otpnextnextup(x) \\ 数値または特別な数値よりも大きい最小のoctupleで表現できる数値または特別な数値を返す \\ y xよりも大きい最小のoctupleで表現できる数値または特別な数値 \\ x 数値または特別な数値 oplnextup(x)=xxxnextup(x,15,0,240); oplnextnextup(x)=oplnextup(oplnextup(x)); \\y=xsgnextup(x) \\y=xsgnextnextup(x) \\ 数値または特別な数値よりも大きい最小のxsingleで表現できる数値または特別な数値を返す \\ y xよりも大きい最小のxsingleで表現できる数値または特別な数値 \\ x 数値または特別な数値 xsgnextup(x)=xxxnextup(x,15,1,23); xsgnextnextup(x)=xsgnextup(xsgnextup(x)); \\y=xdbnextup(x) \\y=xdbnextnextup(x) \\ 数値または特別な数値よりも大きい最小のxdoubleで表現できる数値または特別な数値を返す \\ y xよりも大きい最小のxdoubleで表現できる数値または特別な数値 \\ x 数値または特別な数値 xdbnextup(x)=xxxnextup(x,15,1,52); xdbnextnextup(x)=xdbnextup(xdbnextup(x)); \\y=efpnextup(x) \\y=efpnextnextup(x) \\ 数値または特別な数値よりも大きい最小のefpで表現できる数値または特別な数値を返す \\ y xよりも大きい最小のefpで表現できる数値または特別な数値 \\ x 数値または特別な数値 efpnextup(x)=xxxnextup(x,16,1,91); efpnextnextup(x)=efpnextup(efpnextup(x)); \\y=nextup(x,rp) \\ 数値または特別な数値よりも大きい最小の丸め桁数rpで表現できる数値または特別な数値を返す \\ y xよりも大きい最小の丸め桁数rpで表現できる数値または特別な数値 \\ x 数値または特別な数値 \\ rp 丸め桁数 nextup(x,rp)={ if(rp==SGL,sglnextup(x), (rp==DBL)||(rp==DBL3),dblnextup(x), rp==EXD,exdnextup(x), rp==TPL,tplnextup(x), rp==QPL,qplnextup(x), rp==SPL,splnextup(x), rp==OPL,oplnextup(x), rp==XSG,xsgnextup(x), rp==XDB,xdbnextup(x), rp==EFP,efpnextup(x), error("nextup(",x,",",rp")")) } \\u=numtoyyyy(x,rm,iw) \\ 数値または特別な数値を丸めモードrmでiw-bit符号あり整数に丸めて内部表現のiw-bit符号なし整数に変換する \\ u iw-bit符号あり整数の内部表現のiw-bit符号なし整数 \\ x 数値または特別な数値 \\ rm 丸めモード \\ iw 符号あり整数のbit数 \\ fpsr \\ OE iw-bit符号あり整数の範囲外、±Inf,NaN \\ X2 不正確な結果 \\ AV NaN numtoyyyy(x,rm,iw)={ my(y); if(type(x)=="t_POL", if((x==Rei)||(x==-Rei),return(0), fpsr=bitor(fpsr,OE); if(x==Inf,return((1<<(iw-1))-1), x==-Inf,return(1<<(iw-1)), fpsr=bitor(fpsr,AV); return((1<<iw)-1)))); y=if(rm==RN,rint(x), rm==RZ,trunc(x), rm==RM,floor(x), rm==RP,ceil(x), error("numtoyyyy(",x,",",rm,",",iw,")")); if(y!=x,fpsr=bitor(fpsr,X2)); \\不正確な結果 if((0<=y)&&(y<1<<(iw-1)),return(y)); if((-(1<<(iw-1))<=y)&&(y<0),return((1<<iw)+y)); fpsr=bitor(fpsr,OE); if(0<y, (1<<(iw-1))-1, 1<<(iw-1)) } \\u=numtobyte(x,rm) \\ 数値または特別な数値を丸めモードrmでbyteに丸めて内部表現の8bit符号なし整数に変換する \\ u byteの内部表現の8bit符号なし整数 \\ x 数値または特別な数値 \\ rm 丸めモード \\ fpsr \\ OE byteの範囲外 \\ X2 不正確な結果 numtobyte(x,rm)=numtoyyyy(x,rm,8); \\u=numtoword(x,rm) \\ 数値または特別な数値を丸めモードrmでwordに丸めて内部表現の16bit符号なし整数に変換する \\ u wordの内部表現の16bit符号なし整数 \\ x 数値または特別な数値 \\ rm 丸めモード \\ fpsr \\ OE wordの範囲外 \\ X2 不正確な結果 numtoword(x,rm)=numtoyyyy(x,rm,16); \\u=numtolong(x,rm) \\ 数値または特別な数値を丸めモードrmでlongに丸めて内部表現の32bit符号なし整数に変換する \\ u longの内部表現の32bit符号なし整数 \\ x 数値または特別な数値 \\ rm 丸めモード \\ fpsr \\ OE longの範囲外 \\ X2 不正確な結果 numtolong(x,rm)=numtoyyyy(x,rm,32); \\u=numtoquad(x,rm) \\ 数値または特別な数値を丸めモードrmでquadに丸めて内部表現の64bit符号なし整数に変換する \\ u quadの内部表現の64bit符号なし整数 \\ x 数値または特別な数値 \\ rm 丸めモード \\ fpsr \\ OE quadの範囲外 \\ X2 不正確な結果 numtoquad(x,rm)=numtoyyyy(x,rm,64); \\x=yyyytonum(u,iw) \\ iw-bit符号なし整数uをiw-bit符号あり整数の内部表現と見なして数値または特別な数値に変換する \\ x 数値または特別な数値 \\ u iw-bit符号あり整数の内部表現のiw-bit符号なし整数 \\ iw 符号あり整数のbit数 yyyytonum(u,iw)={ u=bitand(u,(1<<iw)-1); if(u==0,Rei, bittest(u,iw-1),u-(1<<iw), u) } \\x=bytetonum(u) \\ 8bit符号なし整数uをbyteの内部表現と見なして数値または特別な数値に変換する \\ x 数値または特別な数値 \\ u byteの内部表現の8bit符号なし整数 bytetonum(u)=yyyytonum(u,8); \\x=wordtonum(u) \\ 16bit符号なし整数uをwordの内部表現と見なして数値または特別な数値に変換する \\ x 数値または特別な数値 \\ u wordの内部表現の16bit符号なし整数 wordtonum(u)=yyyytonum(u,16); \\x=longtonum(u) \\ 32bit符号なし整数uをlongの内部表現と見なして数値または特別な数値に変換する \\ x 数値または特別な数値 \\ u longの内部表現の32bit符号なし整数 longtonum(u)=yyyytonum(u,32); \\x=quadtonum(u) \\ 64bit符号なし整数uをquadの内部表現と見なして数値または特別な数値に変換する \\ x 数値または特別な数値 \\ u quadの内部表現の64bit符号なし整数 quadtonum(u)=yyyytonum(u,64); \\u=numtopkd(x,k,rm) \\ 数値または特別な数値xをk-factor kと丸めモードrmでpackedの内部表現の96bit符号なし整数uに変換する \\ u packedの内部表現の96bit符号なし整数 \\ x 数値または特別な数値 \\ k k-factor。下位7bitが有効。-64..17 \\ rm 丸めモード \\ fpsr \\ OE k-factorまたは指数部が範囲外 \\ X2 誤差がある numtopkd(x,k,rm)={ my(a,e,m,v,t,u,w); \\k-factorの範囲を確認する k=bitand(k,127); \\k=0..127 if(64<=k,k-=128); \\k=-64..63 if(17<k, fpsr=bitor(fpsr,OE); k=17); \\k=-64..17 \\特別な数値を処理する if(type(x)=="t_POL", return(if(x==Rei,0, x==-Rei,1<<95, x==Inf,0x7FFF<<80, x==-Inf,0xFFFF<<80, (0x7FFF<<80)+0xFFFFFFFFFFFFFFFF))); \\仮数部の先頭18桁を取り出す a=abs(x); if(a<=LOG_ZERO, return(if(0<=x,0,1<<95))); e=floor(log10(a)); \\小数点を1桁目の右側に置いたときの指数部 m=floor(a*10^(17-e)); \\仮数部の先頭の18桁 if(m<10^17,e--;m=floor(a*10^(17-e)), 10^18<=m,e++;m=floor(a*10^(17-e))); t=if(a!=m*10^(e-17),1,0); \\k+2桁目以降の端数の有無 v=Vecsmall(Str(m)); if(#v!=18,error("numtopacked(",x,",",k,")")); for(i=1,#v,v[i]=bitand(v[i],15)); \\固定小数点形式のとき有効桁数を決める if(k<=0, k=1+e-k; \\小数点の左側の桁数は1+e、小数点の右側の桁数は-k if(k<1,k=1, 17<k,k=17)); \\k=1..17 \\丸める for(i=k+2,18,t+=v[i]); \\k+2桁目以降の端数の有無 if((v[k+1]!=0)||(t!=0), \\k+1桁目以降に端数がある fpsr=bitor(fpsr,X2); \\誤差がある \\ 060FPSPはbindecのA12で端数をFINTを使って丸めている \\ 丸めモードを変更せず丸め桁数だけextendedに変更する処理も書かれているが、 \\ FINTはsingleまたはdoubleへの丸め処理を行わないのでコメントアウトされている if(((rm==RN)&& ((5<v[k+1])|| \\k+1桁目以降に端数があってRNでk+1桁目が5より大きいか、 ((v[k+1]==5)&&((t!=0)|| \\k+1桁目が5でk+2桁目以降に端数があるか、 (bitand(v[k],1)!=0)))))|| \\k+1桁目が5でk+2桁目以降に端数がなくてk桁目が奇数または ((rm==RM)&&(x<0))|| \\RMで負または ((rm==RP)&&(0<=x)), \\RPで正のとき切り上げる forstep(i=k,1,-1, if(v[i]<9, v[i]++; break(), v[i]=0)); if(v[1]==0, v[1]=1; e++))); for(i=k+1,18,v[i]=0); \\k+1桁目以降を0にする \\指数部の範囲を確認する if((e<-999)||(999<e), fpsr=bitor(fpsr,OE); if(e<-9999,return(if(0<=x,0,1<<95))); if(9999<e,return(if(0<=x,0x7FFF<<80,0xFFFF<<80)))); \\packedの内部表現を作る u=0; if(x<0,u+=1<<95); \\仮数部の符号 if(e<0,u+=1<<94); \\指数部の符号 w=Vecsmall(Strprintf("%04d",abs(e)%10000)); for(i=1,#w,w[i]=bitand(w[i],15)); u+=(w[2]<<88)+(w[3]<<84)+(w[4]<<80)+(w[1]<<76); \\指数部 for(i=1,17,u+=v[i]<<(68-4*i)); \\仮数部 u } numtopkd2(x,k,rm)={ my(a,e,m,v,t,u,w); \\k-factorの範囲を確認する k=bitand(k,127); \\k=0..127 if(64<=k,k-=128); \\k=-64..63 \\特別な数値を処理する \\ 17<kでもOEはセットされない if(type(x)=="t_POL", return(if(x==Rei,0, x==-Rei,1<<95, x==Inf,0x7FFF<<80, x==-Inf,0xFFFF<<80, (0x7FFF<<80)+0xFFFFFFFFFFFFFFFF))); if(17<k, fpsr=bitor(fpsr,OE); k=17); \\k=-64..17 \\仮数部の先頭18桁を取り出す a=abs(x); if(a<=LOG_ZERO, return(if(0<=x,0,1<<95))); e=floor(log10(a)); \\小数点を1桁目の右側に置いたときの指数部 m=floor(a*10^(17-e)); \\仮数部の先頭の18桁 if(m<10^17,e--;m=floor(a*10^(17-e)), 10^18<=m,e++;m=floor(a*10^(17-e))); t=if(a!=m*10^(e-17),1,0); \\k+2桁目以降の端数の有無 v=Vecsmall(Str(m)); if(#v!=18,error("numtopacked(",x,",",k,")")); for(i=1,#v,v[i]=bitand(v[i],15)); \\固定小数点形式のとき有効桁数を決める if(k<=0, k=1+e-k; \\小数点の左側の桁数は1+e、小数点の右側の桁数は-k if(k<1,k=1, 17<k,k=17)); \\k=1..17 \\丸める for(i=k+2,18,t+=v[i]); \\k+2桁目以降の端数の有無 if((v[k+1]!=0)||(t!=0), \\k+1桁目以降に端数がある fpsr=bitor(fpsr,X2); \\誤差がある \\ 060FPSPはbindecのA12で端数をFINTを使って丸めている \\ 丸めモードを変更せず丸め桁数だけextendedに変更する処理も書かれているが、 \\ FINTはsingleまたはdoubleへの丸め処理を行わないのでコメントアウトされている if(((rm==RN)&& ((5<v[k+1])|| \\k+1桁目以降に端数があってRNでk+1桁目が5より大きいか、 ((v[k+1]==5)&&((t!=0)|| \\k+1桁目が5でk+2桁目以降に端数があるか、 (bitand(v[k],1)!=0)))))|| \\k+1桁目が5でk+2桁目以降に端数がなくてk桁目が奇数または ((rm==RM)&&(x<0))|| \\RMで負または ((rm==RP)&&(0<=x)), \\RPで正のとき切り上げる forstep(i=k,1,-1, if(v[i]<9, v[i]++; break(), v[i]=0)); if(v[1]==0, v[1]=1; e++))); for(i=k+1,18,v[i]=0); \\k+1桁目以降を0にする \\指数部の範囲を確認する if((e<-999)||(999<e), fpsr=bitor(fpsr,OE); if(e<-9999,return(if(0<=x,0,1<<95))); if(9999<e,return(if(0<=x,0x7FFF<<80,0xFFFF<<80)))); \\packedの内部表現を作る u=0; if(x<0,u+=1<<95); \\仮数部の符号 if(e<0,u+=1<<94); \\指数部の符号 w=Vecsmall(Strprintf("%04d",abs(e)%10000)); for(i=1,#w,w[i]=bitand(w[i],15)); u+=(w[2]<<88)+(w[3]<<84)+(w[4]<<80)+(w[1]<<76); \\指数部 for(i=1,17,u+=v[i]<<(68-4*i)); \\仮数部 u } \\s=numtopkh(x,k,rm) \\ 数値または特別な数値xをk-factor kと丸めモードrmでpackedの内部表現を表す24桁の16進数の文字列sに変換する \\ s packedの内部表現を表す24桁の16進数の文字列 \\ x 数値または特別な数値 \\ k k-factor。下位7bitが有効。-64..17 \\ rm 丸めモード \\ fpsr \\ OE k-factorまたは指数部が範囲外 \\ X2 誤差がある numtopkh(x,k,rm)=hex24(numtopkd(x,k,rm)); \\s=numtopki(x,k,rm) \\ 数値または特別な数値xをk-factor kと丸めモードrmでpackedの内部表現を表す3個の8桁の16進数の文字列sに変換する \\ s packedの内部表現を表す3個の8桁の16進数の文字列 \\ x 数値または特別な数値 \\ k k-factor。下位7bitが有効。-64..17 \\ rm 丸めモード \\ fpsr \\ OE k-factorまたは指数部が範囲外 \\ X2 誤差がある numtopki(x,k,rm)=hex24imm(numtopkd(x,k,rm)); \\x=pkdtonum(u) \\ 96bit符号なし整数uをpackedの内部表現と見なして数値または特別な数値xに変換する \\ 数値は高々1000桁の有理数なので誤差はない \\ x 数値または特別な数値 \\ u packedの内部表現の96bit符号なし整数 \\ fpsr \\ SN SNaN pkdtonum(u)={ my(e,m); e=decodebcd(bitand(u>>80,(1<<12)-1)); \\指数部(3桁) m=decodebcd(bitand(u,(1<<68)-1)); \\仮数部(17桁) if(bittest(u,93)||bittest(u,92)|| \\±Inf,NaN e<0||m<0, \\指数部または仮数部に0..9以外の文字がある if(bitand(u,(1<<64)-1)==0,return(if(bittest(u,95),-Inf,Inf))); \\小数部が0のとき±Inf if(bittest(u,62)==0,fpsr=bitor(fpsr,SN)); \\SNaN return(NaN)); \\小数部が0でないときNaN if(bitand(u,(1<<68)-1)==0,return(if(bittest(u,95),-Rei,Rei))); \\整数部と小数部が0のとき±Rei if(bittest(u,95),-1,1)*10^(if(bittest(u,94),-e,e)-16)*m } \\x=pkdtoxxx(u,rp,rm) \\ 96bit符号なし整数uをpackedの内部表現と見なして丸め桁数rpで表現できる数値または特別な数値xに丸めモードrmで変換する \\ x 数値または特別な数値 \\ u packedの内部表現の96bit符号なし整数 \\ rp 丸め桁数 \\ rm 丸めモード \\ fpsr \\ SN SNaN \\ X1 誤差がある。X2はセットしない pkdtoxxx(u,rp,rm)={ my(sr,x); sr=fpsr; fpsr=0; x=pkdtonum(u); x=roundexd(x,rm); if(bitand(fpsr,SN),sr=bitor(sr,SN)); if(bitand(fpsr,X2),sr=bitor(sr,X1)); fpsr=sr; if(type(x)!="t_POL", x=xxx(x,rp,rm)); x } \\x=pkdtosgl(u,rm) \\ 96bit符号なし整数uをpackedの内部表現と見なしてsingleで表現できる数値または特別な数値xに丸めモードrmで変換する \\ x singleで表現できる数値または特別な数値 \\ u packedの内部表現の96bit符号なし整数 \\ rm 丸めモード \\ fpsr \\ SN SNaN \\ X1 誤差がある。X2はセットしない pkdtosgl(u)=pkdtoxxx(u,SGL,rm); \\x=pkdtodbl(u,rm) \\ 96bit符号なし整数uをpackedの内部表現と見なしてdoubleで表現できる数値または特別な数値xに丸めモードrmで変換する \\ x doubleで表現できる数値または特別な数値 \\ u packedの内部表現の96bit符号なし整数 \\ rm 丸めモード \\ fpsr \\ SN SNaN \\ X1 誤差がある。X2はセットしない pkdtodbl(u)=pkdtoxxx(u,DBL,rm); \\x=pkdtoexd(u,rm) \\ 96bit符号なし整数uをpackedの内部表現と見なしてextendedで表現できる数値または特別な数値xに丸めモードrmで変換する \\ x extendedで表現できる数値または特別な数値 \\ u packedの内部表現の96bit符号なし整数 \\ rm 丸めモード \\ fpsr \\ SN SNaN \\ X1 誤差がある。X2はセットしない pkdtoexd(u)=pkdtoxxx(u,EXD,rm); \\x=pkdtotpl(u,rm) \\ 96bit符号なし整数uをpackedの内部表現と見なしてtripleで表現できる数値または特別な数値xに丸めモードrmで変換する \\ x tripleで表現できる数値または特別な数値 \\ u packedの内部表現の96bit符号なし整数 \\ rm 丸めモード \\ fpsr \\ SN SNaN \\ X1 誤差がある。X2はセットしない pkdtotpl(u)=pkdtoxxx(u,TPL,rm); \\x=pkdtoqpl(u,rm) \\ 96bit符号なし整数uをpackedの内部表現と見なしてquadrupleで表現できる数値または特別な数値xに丸めモードrmで変換する \\ x quadrupleで表現できる数値または特別な数値 \\ u packedの内部表現の96bit符号なし整数 \\ rm 丸めモード \\ fpsr \\ SN SNaN \\ X1 誤差がある。X2はセットしない pkdtoqpl(u)=pkdtoxxx(u,QPL,rm); \\x=pkdtospl(u,rm) \\ 96bit符号なし整数uをpackedの内部表現と見なしてsextupleで表現できる数値または特別な数値xに丸めモードrmで変換する \\ x sextupleで表現できる数値または特別な数値 \\ u packedの内部表現の96bit符号なし整数 \\ rm 丸めモード \\ fpsr \\ SN SNaN \\ X1 誤差がある。X2はセットしない pkdtospl(u)=pkdtoxxx(u,SPL,rm); \\x=pkdtoopl(u,rm) \\ 96bit符号なし整数uをpackedの内部表現と見なしてoctupleで表現できる数値または特別な数値xに丸めモードrmで変換する \\ x octupleで表現できる数値または特別な数値 \\ u packedの内部表現の96bit符号なし整数 \\ rm 丸めモード \\ fpsr \\ SN SNaN \\ X1 誤差がある。X2はセットしない pkdtoopl(u)=pkdtoxxx(u,OPL,rm); \\x=pkdtoxsg(u,rm) \\ 96bit符号なし整数uをpackedの内部表現と見なしてxsingleで表現できる数値または特別な数値xに丸めモードrmで変換する \\ x xsingleで表現できる数値または特別な数値 \\ u packedの内部表現の96bit符号なし整数 \\ rm 丸めモード \\ fpsr \\ SN SNaN \\ X1 誤差がある。X2はセットしない pkdtoxsg(u)=pkdtoxxx(u,XSG,rm); \\x=pkdtoxdb(u,rm) \\ 96bit符号なし整数uをpackedの内部表現と見なしてxdoubleで表現できる数値または特別な数値xに丸めモードrmで変換する \\ x xdoubleで表現できる数値または特別な数値 \\ u packedの内部表現の96bit符号なし整数 \\ rm 丸めモード \\ fpsr \\ SN SNaN \\ X1 誤差がある。X2はセットしない pkdtoxdb(u)=pkdtoxxx(u,XDB,rm); \\x=pkdtoefp(u,rm) \\ 96bit符号なし整数uをpackedの内部表現と見なしてefpで表現できる数値または特別な数値xに丸めモードrmで変換する \\ x efpで表現できる数値または特別な数値 \\ u packedの内部表現の96bit符号なし整数 \\ rm 丸めモード \\ fpsr \\ SN SNaN \\ X1 誤差がある。X2はセットしない pkdtoefp(u)=pkdtoxxx(u,EFP,rm); \\y=pkd(x,rm) \\ 数値または特別な数値xを丸めモードrmでpackedで表現できる数値または特別な数値yに変換する \\ yは高々1000桁の有理数なので誤差はない \\ y packedで表現できる数値または特別な数値 \\ x 数値または特別な数値 \\ rm 丸めモード \\ fpsr \\ OE 指数部が範囲外 \\ X2 誤差がある pkd(x,rm)={ my(u); u=numtopkd(x,17,rm); if(bitand(u,0xF<<76)!=0, \\指数部の1000の位が0でないときは元に戻せない if(bittest(u,95), if(bittest(u,94),-Rei,-Inf), if(bittest(u,94),Rei,Inf)), pkdtonum(u)) } \\---------------------------------------------------------------------------------------- \\ グラフ \\---------------------------------------------------------------------------------------- \\graph(f) \\ 関数fのグラフを表示する graph(f)={ my(reso=10000,m,r,c,i,x,y); m=matrix(41,81,r,c, if(r%20==1, if(c%10==1,"+","-"), c%40==1, if(r%5==1,"+","|"), " " ) ); for(i=-4*reso,4*reso, x=i/reso; iferr(y=f(x); if(imag(y)==0, r=21-round(y*5); if(1<=r&&r<=41, c=41+round(x*10); m[r,c]="*" ) ), ERR, 0 ) ); for(r=1,41, print1(" // "); for(c=1,81, print1(m[r,c]) ); print() ) } \\---------------------------------------------------------------------------------------- \\ Javaコード生成 \\---------------------------------------------------------------------------------------- \\s=efpnew(x,rm) \\ 数値または特別な数値xを丸めモードrmでefpで表現できる数値または特別な数値に変換してインスタンスを生成するコードsを返す \\ s インスタンスを生成するコード \\ x 数値または特別な数値 \\ rm 丸めモード efpnew(x,rm)={ my(e,m); if(x==0,x=Rei); if(type(x)=="t_POL", if(x==-Inf,"new EFP (M | I, 0, 0L, 0L)", x==-Rei,"new EFP (M | Z, 0, 0L, 0L)", x==Rei,"new EFP ()", x==Inf,"new EFP (P | I, 0, 0L, 0L)", x==NaN,"new EFP (N, 0, 0L, 0L)", error("efpnew(",x,",",rm,")")), x=roundefp(x,rm); e=getexp(x); m=abs(getman(x))*2^91; Strprintf("new EFP (%s, %6d, 0x%016xL, 0x%07xL << 36)", if(x<0,"M","P"),e,m>>28,bitand(m,(1<<28)-1))) } \\efpmem([x,rm,c],…) \\ インスタンスを生成するコードを出力する \\ x 数値または特別な数値または式を表す文字列 \\ rm 丸めモード \\ c 式を表す文字列 efpmem(aa[..])={ my(vv,xx,rm,cc,rr); for(ii=1,#aa, vv=aa[ii]; if((type(vv)!="t_VEC")||(#vv<1),error("efpmem(",vv,")")); xx=vv[1]; rm=if(#vv<2,RN,vv[2]); cc=if(#vv<3,"",vv[3]); if(xx==0,xx=Rei); if(type(xx)=="t_STR", cc=xx; xx=eval(xx)); if(cc!="",cc=Str(cc,"=")); rr=roundefp(xx,rm); printf(" %s, //%s%s%s\n", efpnew(xx,rm),if(type(rr)=="t_POL","=",rr<xx,"<",rr==xx,"=",">"),cc,formatg(xx,30))) } \\efppub([id,x,rm,c],…) \\ 定数宣言のコードを出力する \\ id 識別子 \\ x 数値または特別な数値または式を表す文字列 \\ rm 丸めモード \\ c 式を表す文字列 efppub(aa[..])={ my(vv,id,xx,rm,cc,rr); for(ii=1,#aa, vv=aa[ii]; if((type(vv)!="t_VEC")||(#vv<2),error("efppub(",vv,")")); id=vv[1]; xx=vv[2]; rm=if(#vv<3,RN,vv[3]); cc=if(#vv<4,"",vv[4]); if(xx==0,xx=Rei); if(type(xx)=="t_STR", cc=xx; xx=eval(xx)); if(cc!="",cc=Str(cc,"=")); rr=roundefp(xx,rm); printf(" public final EFP %12s = %s; //%s%s%s\n", id,efpnew(xx,rm),if(type(rr)=="t_POL","=",rr<xx,"<",rr==xx,"=",">"),cc,formatg(xx,30))) } \\efppub2([id,x,rm,c],…) \\ 定数宣言のコードを2倍の精度で出力する \\ id 識別子 \\ x 数値または特別な数値または式を表す文字列 \\ rm 丸めモード \\ c 式を表す文字列 efppub2(aa[..])={ my(vv,id,xx,rm,cc,rr); for(ii=1,#aa, vv=aa[ii]; if((type(vv)!="t_VEC")||(#vv<2),error("efppub2(",vv,")")); id=vv[1]; xx=vv[2]; rm=if(#vv<3,RN,vv[3]); cc=if(#vv<4,"",vv[4]); if(xx==0,xx=Rei); if(type(xx)=="t_STR", cc=xx; xx=eval(xx)); if(cc!="",cc=Str(cc,"=")); rr=roundefp(xx,rm); printf(" public final EFP %12s = %s; //%s%s%s\n", id,efpnew(xx,rm),if(type(rr)=="t_POL","=",rr<xx,"<",rr==xx,"=",">"),cc,formatg(xx,30)); if(type(xx)!="t_POL",xx=xx-rr); rr=roundefp(xx,rm); printf(" public final EFP %11sA = %s; //%s%s\n", id,efpnew(xx,rm),if(type(rr)=="t_POL","=",rr<xx,"<",rr==xx,"=",">"),formatg(xx,30))) } \\---------------------------------------------------------------------------------------- \\ チェビシェフ展開 \\---------------------------------------------------------------------------------------- \\g=enunit(f,x,a,b) \\ 変数変換 \\ 定義域[a,b]の関数f(x)を定義域[-1,1]の関数g(x)に写す enunit(f,x,a,b)=f((b-a)/2*x+(a+b)/2); \\q=deunit(p,x,a,b) \\ 変数変換 \\ 定義域[-1,1]の多項式p(x)を定義域[a,b]の多項式q(x)に写す deunit(p,x,a,b)=subst(p,x,2/(b-a)*x-(a+b)/(b-a)); \\p=chebyshev(f,a,b,n) \\ 定義域[a,b]の関数f(x)をn次チェビシェフ展開した多項式p(x)を作る chebyshev(f,a,b,n)=deunit(sum(k=0,n,if(k==0,1,2)/Pi*intnum(t=0,Pi,cos(k*t)*enunit(f,cos(t),a,b))*polchebyshev(k)),x,a,b); \\q=efpcoeff(p) \\ 多項式pの係数をefpに丸めた多項式qを返す \\ q 係数をefpに丸めた多項式 \\ p 多項式 efpcoeff(p)={ my(c); sum(n=0,poldegree(p), c=polcoeff(p,n); if(abs(c)<1e-300,0,efp(c,RN)*x^n)) \\1e-300未満は切り捨てる } \\c=closeness(f,p,a,b,n) \\ 関数f(x)と多項式p(x)を定義域[a,b]をn等分したn+1箇所すべてで比較して一致しているbit数の最小値を返す closeness(ff,pp,aa,bb,nn)={ my(ww,rr,x,ffx,ppx); ww=bb-aa; rr=1e999; for(kk=0,nn, x=(aa+ww*kk/nn)*1.0; ffx=ff(x); ppx=eval(pp); if(ffx!=ppx,rr=min(rr,abs(if(abs(ppx)<abs(ffx),ffx,ppx)/(ffx-ppx))))); if(rr<1,0,log2(rr)) } \\efpclose(f,p,a,b) \\ 関数f(x)と多項式p(x)を定義域[a,b]をn等分したn+1箇所すべてで比較して一致しているbit数の最小値を出力する efpclose(f,p,a,b)=printf(" // %.2fbit\n",closeness(f,p,a,b,10000)); \\efppoly(id,f,p,a,b) \\ 定義域[a,b]の関数f(x)の近似多項式p(x)の係数の定数宣言を出力する efppoly(id,f,p,a,b)={ for(k=0,poldegree(p), c=polcoeff(p,k); if(1e-300<=abs(c), efppub([Str(id,k),c,RN]))); efpclose(f,p,a,b) } \\s=efpchebyshev(id,f,a,b,n) \\ 定義域[a,b]の関数f(x)をn次チェビシェフ展開した多項式p(x)の係数の定数宣言を出力する efpchebyshev(id,f,a,b,n)=efppoly(id,f,efpcoeff(chebyshev(f,a,b,n)),a,b); \\---------------------------------------------------------------------------------------- \\ 数式文字列 \\ 数式を表す文字列 \\---------------------------------------------------------------------------------------- \\t=negexpr(s) \\ 数式文字列sの符号を反転する \\ "NaN"はそのまま \\ 先頭が"+"または"-"でないとき、先頭に"+"を付ける \\ "("~")"の外側の先頭または"^"以外の文字の後に"+"または"-"があるとき、"+"を"-"に、"-"を"+"にする \\ 先頭が"+"のとき、先頭の"+"を取り除く negexpr(s)={ my(v,d,p,c); if(s=="NaN",return(s)); \\NaNはそのまま v=Vecsmall(s); if((v[1]!=43)&&(v[1]!=45), \\先頭が"+"または"-"でないとき v=concat(Vecsmall([43]),v)); \\先頭に"+"を付ける d=0; \\"("~")"の深さ p=0; \\直前の文字 for(k=1,#v, c=v[k]; \\k番目の文字 if(c==40,d++, \\"(" c==41,d--, \\")" (d==0)&&(p!=94)&&((c==43)||(c==45)), \\"("~")"の外側の先頭または"^"以外の文字の後に"+"または"-"があるとき v[k]=43+45-c); \\"+"を"-"に、"-"を"+"にする p=c); if(v[1]==43, \\先頭が"+"のとき v=v[2..#v]); \\先頭の"+"を取り除く Strchr(v) } \\w=bothsign(v) \\ 数式文字列を並べたベクタvに符号を反転した数式文字列を加える bothsign(v)=concat(v,vector(#v,n,negexpr(v[n]))); \\---------------------------------------------------------------------------------------- \\ ソースファイルの操作 \\---------------------------------------------------------------------------------------- asm_list=List(); asm_open()={ system(Str("rm -f ",TEST_S_TMP)); asm_list=List() } asm(a[..])={ for(i=1,#a,listput(asm_list,a[i])); if(50000<=#asm_list, write1(TEST_S_TMP,join("",Vec(asm_list))); asm_list=List()) } asmln(a[..])={ for(i=1,#a,listput(asm_list,a[i])); listput(asm_list,"\n"); if(50000<=#asm_list, write1(TEST_S_TMP,join("",Vec(asm_list))); asm_list=List()) } asmf(f,a[..])={ listput(asm_list,call(Strprintf,[f,a])); if(50000<=#asm_list, write1(TEST_S_TMP,join("",Vec(asm_list))); asm_list=List()) } asm_close()={ write1(TEST_S_TMP,join("",Vec(asm_list))); system(Str("mv ",TEST_S," ",TEST_S_BAK)); system(Str("mv ",TEST_S_TMP," ",TEST_S)); print(TEST_S," was updated") } \\---------------------------------------------------------------------------------------- \\ 間接データ \\---------------------------------------------------------------------------------------- indirect_list=0; indirect_buffer=0; indirect_offset=0; indirect_start()={ indirect_list=List([]); indirect_offset=List([]); indirect_buffer=List([]); } indirect_end()={ my(v,w); print1("compressing indirect data ... "); v=Vecsmall(indirect_buffer); w=compress(v); print(#w,"/",#v); \\if(decompress(w)!=v,error()); asm( " ;-------------------------------------------------------------------------------- ; indirect data ;-------------------------------------------------------------------------------- .text .even indirect_start:: pea.l indirect_decompressed pea.l indirect_compressed jbsr decompress addq.l #8,sp rts .align 4 indirect_compressed:: "); for(i=1,#w, if(i%16==1,asm(" .dc.b "), asm(",")); asm("$",hex2(w[i])); if((i==#w)||(i%16==0),asm("\n"))); asm( " .bss .align 4 indirect_decompressed:: .ds.b ",#indirect_buffer," ") } \\---------------------------------------------------------------------------------------- \\ 圧縮 \\---------------------------------------------------------------------------------------- push_buffer=0; push_max_length=0; push_start()={ push_buffer=List() } push(b,u)={ u=bitand(u,(1<<(b<<3))-1); forstep(i=b-1,0,-1, listput(push_buffer,bitand(u>>(i<<3),255))) } push_indirect(b,u)={ my(u1); u=bitand(u,(1<<(b<<3))-1); u1=bitor(1<<(b<<3),u); \\サイズを区別するために上位に1を付け足す for(n=1,#indirect_list, if(indirect_list[n]==u1, push(4,indirect_offset[n]); return())); listput(indirect_list,u1); listput(indirect_offset,#indirect_buffer); forstep(i=b-1,0,-1, listput(indirect_buffer,bitand(u>>(i<<3),255))); push(4,indirect_offset[#indirect_offset]) } push_end()={ my(v,w); if(push_max_length<#push_buffer, push_max_length=#push_buffer); print1("compressing data ... "); v=Vecsmall(push_buffer); w=compress(v); print(#w,"/",#v); \\if(decompress(w)!=v,error()); push_buffer=0; for(i=1,#w, if(i%16==1,asm(" .dc.b "), asm(",")); asm("$",hex2(w[i])); if((i==#w)||(i%16==0),asm("\n"))); } \\---------------------------------------------------------------------------------------- \\ テストプログラムを作る \\---------------------------------------------------------------------------------------- make_test(a[..])={ my(mnemmap,all,cmd); mnemmap=Map(); for(i=1,#a,mapput(mnemmap,strlwr(a[i]),1)); all=#a==0||mapisdefined(mnemmap,"all"); asm_open(); asm( ";======================================================================================== ; ",TEST_S," ; Copyright (C) 2003-2019 Makoto Kamada ; ; This file is part of the XEiJ (X68000 Emulator in Java). ; You can use, modify and redistribute the XEiJ if the conditions are met. ; Read the XEiJ License for more details. ; https://stdkmd.net/xeij/ ;======================================================================================== .include doscall.mac .include iocscall.mac .cpu 68000 ;-------------------------------------------------------------------------------- ; 定数 ;-------------------------------------------------------------------------------- MI equ 1<<27 ZE equ 1<<26 IN equ 1<<25 NA equ 1<<24 BS equ 1<<15 SN equ 1<<14 OE equ 1<<13 OF equ 1<<12 UF equ 1<<11 DZ equ 1<<10 X2 equ 1<<9 X1 equ 1<<8 AV equ 1<<7 AO equ 1<<6 AU equ 1<<5 AZ equ 1<<4 AX equ 1<<3 ;-------------------------------------------------------------------------------- ; マクロ ;-------------------------------------------------------------------------------- leamsg .macro p0,an .data @msg: .dc.b p0,0 .text lea.l @msg,an .endm peamsg .macro p0,p1,p2,p3,p4,p5,p6,p7,p8,p9,q0,q1,q2,q3,q4,q5,q6,q7,q8,q9 .data @msg: .dc.b p0,p1,p2,p3,p4,p5,p6,p7,p8,p9,q0,q1,q2,q3,q4,q5,q6,q7,q8,q9,0 .text pea.l @msg .endm putmsg .macro p0,p1,p2,p3,p4,p5,p6,p7,p8,p9,q0,q1,q2,q3,q4,q5,q6,q7,q8,q9 peamsg p0,p1,p2,p3,p4,p5,p6,p7,p8,p9,q0,q1,q2,q3,q4,q5,q6,q7,q8,q9 jbsr printstr addq.l #4,sp .endm putstr .macro p0 move.l p0,-(sp) jbsr printstr addq.l #4,sp .endm putchr .macro p0 move.b p0,-(sp) jbsr printchr addq.l #2,sp .endm putlong .macro p0 move.l p0,-(sp) jbsr printlong addq.l #4,sp .endm putdec .macro p0 move.l p0,-(sp) jbsr printdec addq.l #4,sp .endm putdecz2 .macro p0 pea.l 2.w move.l p0,-(sp) jbsr printdecz addq.l #8,sp .endm putdecz4 .macro p0 pea.l 4.w move.l p0,-(sp) jbsr printdecz addq.l #8,sp .endm putfix .macro p0,p1 move.b p1,-(sp) move.l p0,-(sp) jbsr printfix addq.l #6,sp .endm puthex2 .macro p0 move.b p0,-(sp) jbsr printhex2 addq.l #2,sp .endm puthex4 .macro p0 move.w p0,-(sp) jbsr printhex4 addq.l #2,sp .endm puthex8 .macro p0 move.l p0,-(sp) jbsr printhex8 addq.l #4,sp .endm puthex16 .macro p0,p1 puthex8 p0 putchr #',' puthex8 p1 .endm puthex24 .macro p0,p1,p2 puthex8 p0 putchr #',' puthex8 p1 putchr #',' puthex8 p2 .endm putcrlf .macro jbsr printcrlf .endm putdate .macro jbsr printdate .endm ;-------------------------------------------------------------------------------- ; メイン ;-------------------------------------------------------------------------------- .text .even main:: ;------------------------------------------------ ;bssが確保されているか確認する lea.l (16,a0),a0 suba.l a0,a1 movem.l a0-a1,-(sp) DOS _SETBLOCK addq.l #8,sp tst.l d0 bmi exit ;------------------------------------------------ ;スタックエリアを設定する lea.l stack_area_end,sp ;スタックエリアの末尾 ;------------------------------------------------ ;FPUの種類を確認する jbsr fpu_check beq exit ;------------------------------------------------ ;コマンドラインをコピーする pea.l 1(a2) jbsr option_start addq.l #4,sp beq exit ;------------------------------------------------ ;アボートの準備をする move.l sp,abort_sp move.w #_CTRLVC,-(sp) DOS _INTVCG addq.l #2,sp move.l d0,abort_ctrlvc ;元の_CTRLVC move.w #_ERRJVC,-(sp) DOS _INTVCG addq.l #2,sp move.l d0,abort_errjvc ;元の_ERRJVC pea.l abort move.w #_CTRLVC,-(sp) DOS _INTVCS addq.l #6,sp pea.l abort move.w #_ERRJVC,-(sp) DOS _INTVCS addq.l #6,sp ;------------------------------------------------ ;ベクタを変更する pea.l trapv_routine ;TRAPV/TRAPcc/FTRAPccルーチン move.w #7,-(sp) DOS _INTVCS addq.l #6,sp move.l d0,trapv_vector ;元のTRAPV/TRAPcc/FTRAPccベクタ ;------------------------------------------------ ;ロギングを開始する jbsr logging_start beq exit ;------------------------------------------------ ;統計を開始する jbsr statistics_start ;------------------------------------------------ ;開始メッセージ putmsg 'begin: ' putdate putcrlf ;------------------------------------------------ ;圧縮された間接データを展開する jbsr indirect_start ;------------------------------------------------ ;全体ループ開始 loop:: ;------------------------------------------------ ;引数を確認する jbsr option_loop beq loopend ;------------------------------------------------ ;テストを実行する "); if(all||mapisdefined(mnemmap,"fabs"),asmln(" jbsr fabs_test")); if(all||mapisdefined(mnemmap,"facos"),asmln(" jbsr facos_test")); if(all||mapisdefined(mnemmap,"fadd"),asmln(" jbsr fadd_test")); if(all||mapisdefined(mnemmap,"fasin"),asmln(" jbsr fasin_test")); if(all||mapisdefined(mnemmap,"fatan"),asmln(" jbsr fatan_test")); if(all||mapisdefined(mnemmap,"fatanh"),asmln(" jbsr fatanh_test")); if(all||mapisdefined(mnemmap,"fbccl"), asmln(" jbsr fbccl060_test"); asmln(" jbsr fbccl88x_test")); if(all||mapisdefined(mnemmap,"fbccw"), asmln(" jbsr fbccw060_test"); asmln(" jbsr fbccw88x_test")); if(all||mapisdefined(mnemmap,"fcmp"),asmln(" jbsr fcmp_test")); if(all||mapisdefined(mnemmap,"fcos"),asmln(" jbsr fcos_test")); if(all||mapisdefined(mnemmap,"fcosh"),asmln(" jbsr fcosh_test")); if(all||mapisdefined(mnemmap,"fdabs"),asmln(" jbsr fdabs_test")); if(all||mapisdefined(mnemmap,"fdadd"),asmln(" jbsr fdadd_test")); if(all||mapisdefined(mnemmap,"fdbcc"), asmln(" jbsr fdbcc060_test"); asmln(" jbsr fdbcc88x_test")); if(all||mapisdefined(mnemmap,"fddiv"),asmln(" jbsr fddiv_test")); if(all||mapisdefined(mnemmap,"fdiv"),asmln(" jbsr fdiv_test")); if(all||mapisdefined(mnemmap,"fdmove"),asmln(" jbsr fdmove_test")); if(all||mapisdefined(mnemmap,"fdmul"),asmln(" jbsr fdmul_test")); if(all||mapisdefined(mnemmap,"fdneg"),asmln(" jbsr fdneg_test")); if(all||mapisdefined(mnemmap,"fdsqrt"),asmln(" jbsr fdsqrt_test")); if(all||mapisdefined(mnemmap,"fdsub"),asmln(" jbsr fdsub_test")); if(all||mapisdefined(mnemmap,"fetox"),asmln(" jbsr fetox_test")); if(all||mapisdefined(mnemmap,"fetoxm1"),asmln(" jbsr fetoxm1_test")); if(all||mapisdefined(mnemmap,"fgetexp"),asmln(" jbsr fgetexp_test")); if(all||mapisdefined(mnemmap,"fgetman"),asmln(" jbsr fgetman_test")); if(all||mapisdefined(mnemmap,"fint"),asmln(" jbsr fint_test")); if(all||mapisdefined(mnemmap,"fintrz"),asmln(" jbsr fintrz_test")); if(all||mapisdefined(mnemmap,"flog10"),asmln(" jbsr flog10_test")); if(all||mapisdefined(mnemmap,"flog2"),asmln(" jbsr flog2_test")); if(all||mapisdefined(mnemmap,"flogn"),asmln(" jbsr flogn_test")); if(all||mapisdefined(mnemmap,"flognp1"),asmln(" jbsr flognp1_test")); if(all||mapisdefined(mnemmap,"fmod"),asmln(" jbsr fmod_test")); if(all||mapisdefined(mnemmap,"fmoveb"), asmln(" jbsr fmovebregto_test"); asmln(" jbsr fmovebtoreg_test")); if(all||mapisdefined(mnemmap,"fmoved"), asmln(" jbsr fmovedregto_test"); asmln(" jbsr fmovedtoreg_test")); if(all||mapisdefined(mnemmap,"fmovel"), asmln(" jbsr fmovelregto_test"); asmln(" jbsr fmoveltoreg_test")); if(all||mapisdefined(mnemmap,"fmovep"), asmln(" jbsr fmovepregto_test"); asmln(" jbsr fmoveptoreg_test")); if(all||mapisdefined(mnemmap,"fmoves"), asmln(" jbsr fmovesregto_test"); asmln(" jbsr fmovestoreg_test")); if(all||mapisdefined(mnemmap,"fmovew"), asmln(" jbsr fmovewregto_test"); asmln(" jbsr fmovewtoreg_test")); if(all||mapisdefined(mnemmap,"fmovex"), asmln(" jbsr fmovexregto_test"); asmln(" jbsr fmovextoreg_test")); if(all||mapisdefined(mnemmap,"fmovecr"), asmln(" jbsr fmovecr881_test"); asmln(" jbsr fmovecr882_test")); \\if(all||mapisdefined(mnemmap,"fmoveml"), \\ asmln(" jbsr fmovemlregto_test"); \\ asmln(" jbsr fmovemltoreg_test")); \\if(all||mapisdefined(mnemmap,"fmovemx"), \\ asmln(" jbsr fmovemxregto_test"); \\ asmln(" jbsr fmovemxtoreg_test")); if(all||mapisdefined(mnemmap,"fmul"),asmln(" jbsr fmul_test")); if(all||mapisdefined(mnemmap,"fneg"),asmln(" jbsr fneg_test")); if(all||mapisdefined(mnemmap,"frem"),asmln(" jbsr frem_test")); \\if(all||mapisdefined(mnemmap,"frestore"),asmln(" jbsr frestore_test")); if(all||mapisdefined(mnemmap,"fsabs"),asmln(" jbsr fsabs_test")); if(all||mapisdefined(mnemmap,"fsadd"),asmln(" jbsr fsadd_test")); \\if(all||mapisdefined(mnemmap,"fsave"),asmln(" jbsr fsave_test")); if(all||mapisdefined(mnemmap,"fscale"),asmln(" jbsr fscale_test")); if(all||mapisdefined(mnemmap,"fscc"), asmln(" jbsr fscc060_test"); asmln(" jbsr fscc88x_test")); if(all||mapisdefined(mnemmap,"fsdiv"),asmln(" jbsr fsdiv_test")); if(all||mapisdefined(mnemmap,"fsgldiv"), asmln(" jbsr fsgldiv060_test"); asmln(" jbsr fsgldiv88x_test")); if(all||mapisdefined(mnemmap,"fsglmul"), asmln(" jbsr fsglmul060_test"); asmln(" jbsr fsglmul88x_test")); if(all||mapisdefined(mnemmap,"fsin"),asmln(" jbsr fsin_test")); if(all||mapisdefined(mnemmap,"fsincos"),asmln(" jbsr fsincos_test")); if(all||mapisdefined(mnemmap,"fsinh"),asmln(" jbsr fsinh_test")); if(all||mapisdefined(mnemmap,"fsmove"),asmln(" jbsr fsmove_test")); if(all||mapisdefined(mnemmap,"fsmul"),asmln(" jbsr fsmul_test")); if(all||mapisdefined(mnemmap,"fsneg"),asmln(" jbsr fsneg_test")); if(all||mapisdefined(mnemmap,"fsqrt"),asmln(" jbsr fsqrt_test")); if(all||mapisdefined(mnemmap,"fssqrt"),asmln(" jbsr fssqrt_test")); if(all||mapisdefined(mnemmap,"fssub"),asmln(" jbsr fssub_test")); if(all||mapisdefined(mnemmap,"fsub"),asmln(" jbsr fsub_test")); if(all||mapisdefined(mnemmap,"ftan"),asmln(" jbsr ftan_test")); if(all||mapisdefined(mnemmap,"ftanh"),asmln(" jbsr ftanh_test")); if(all||mapisdefined(mnemmap,"ftentox"),asmln(" jbsr ftentox_test")); if(all||mapisdefined(mnemmap,"ftrapcc"), asmln(" jbsr ftrapcc060_test"); asmln(" jbsr ftrapcc88x_test")); if(all||mapisdefined(mnemmap,"ftrapccl"), asmln(" jbsr ftrapccl060_test"); asmln(" jbsr ftrapccl88x_test")); if(all||mapisdefined(mnemmap,"ftrapccw"), asmln(" jbsr ftrapccw060_test"); asmln(" jbsr ftrapccw88x_test")); if(all||mapisdefined(mnemmap,"ftst"),asmln(" jbsr ftst_test")); if(all||mapisdefined(mnemmap,"ftwotox"),asmln(" jbsr ftwotox_test")); asm( " ;------------------------------------------------ ;次の引数に進む jbsr option_next jbra loop ;------------------------------------------------ ;全体ループ終了 loopend:: ;------------------------------------------------ ;アボート処理 abort:: movea.l abort_sp,sp move.l abort_ctrlvc,-(sp) ;元の_CTRLVC move.w #_CTRLVC,-(sp) DOS _INTVCS addq.l #6,sp move.l abort_errjvc,-(sp) ;元の_ERRJVC move.w #_ERRJVC,-(sp) DOS _INTVCS addq.l #6,sp ;------------------------------------------------ ;ベクタを復元する move.l trapv_vector,d0 ;元のTRAPV/TRAPcc/FTRAPccベクタ beq @f move.l d0,-(sp) move.w #7,-(sp) DOS _INTVCS addq.l #6,sp @@: ;------------------------------------------------ ;統計を終了する jbsr statistics_end ;------------------------------------------------ ;終了メッセージ putmsg 'end: ' putdate putcrlf putcrlf ;------------------------------------------------ ;ロギングを終了する jbsr logging_end ;------------------------------------------------ ;プログラムを終了する exit:: DOS _EXIT ;------------------------------------------------ ;アボート処理 .data .align 4 abort_sp:: .dc.l 0 ;アボートするときのスタックポインタ abort_ctrlvc:: .dc.l 0 ;元の_CTRLVC abort_errjvc:: .dc.l 0 ;元の_ERRJVC ;------------------------------------------------ ;スタックエリア .bss .align 4 stack_area:: .ds.b 1024*64 ;スタックエリア stack_area_end:: ;スタックエリアの末尾 ;-------------------------------------------------------------------------------- ; TRAPV/TRAPcc/FTRAPcc ;-------------------------------------------------------------------------------- ;TRAPV/TRAPcc/FTRAPccルーチン .text .even trapv_routine:: addq.l #1,trapv_occurred ;TRAPV/TRAPcc/FTRAPccが発生した rte .data .align 4 trapv_vector:: .dc.l 0 ;元のTRAPV/TRAPcc/FTRAPccベクタ trapv_occurred:: .dc.l 0 ;0=TRAPV/TRAPcc/FTRAPccは発生していない,1=TRAPV/TRAPcc/FTRAPccが発生した ;-------------------------------------------------------------------------------- ; FPUの種類 ;-------------------------------------------------------------------------------- MC68881 equ 1<<0 MC68882 equ 1<<1 MC68040 equ 1<<2 FPSP040 equ 1<<3 MC68060 equ 1<<4 FPSP060 equ 1<<5 ;---------------------------------------------------------------- ;successful=fpu_check() ; FPUの種類を確認する ;>d0.l:0=failed,1=successful ;------------------------------------------------ .cpu 68030 .text .even fpu_check:: movem.l d1-d2/a1,-(sp) lea.l $0CBD.w,a1 ;FPUの有無 IOCS _B_BPEEK tst.b d0 beq 80f ;FPUなし lea.l $0CBC.w,a1 ;MPUの種類 IOCS _B_BPEEK move.l #MC68060,d2 cmp.b #6,d0 beq @f move.l #MC68040,d2 cmp.b #4,d0 beq @f move.l #MC68882,d2 fmove.l #0,fpcr fmovecr.x #1,fp0 fmove.x fp0,-(sp) move.l (sp)+,d0 or.l (sp)+,d0 or.l (sp)+,d0 bne @f move.l #MC68881,d2 @@: move.l d2,fpu_type ;FPUの種類 move.l #-1,fpu_last ;前回のFPUの種類 moveq.l #1,d0 99: movem.l (sp)+,d1-d2/a1 rts 80: putmsg 'no floating point unit',13,10 moveq.l #0,d0 bra 99b .cpu 68000 .bss .align 4 fpu_type:: .ds.l 1 ;FPUの種類 fpu_last:: .ds.l 1 ;前回のFPUの種類 ;-------------------------------------------------------------------------------- ; 動作モード ;-------------------------------------------------------------------------------- OPTION_MARGIN_DEFAULT equ 1 ;超越関数の許容誤差 OPTION_MARGIN_LIMIT equ 11 OPTION_MARGIN_MASK equ $F OPTION_MAXIMUM_DEFAULT equ 100 ;テスト毎の出力される結果の最大数 OPTION_MAXIMUM_LIMIT equ 1000000 OPTION_MAXIMUM_MASK equ $FFFFF OPTION_MAXIMUM_SHIFT equ 4 OPTION_DESTINATION equ 1<<24 ;デスティネーションオペランドを調べる OPTION_FAILED equ 1<<25 ;失敗したテストの結果を出力する OPTION_NANS equ 1<<26 ;NaNの仮数部を調べる OPTION_FPSP equ 1<<27 ;浮動小数点ソフトウェアパッケージで処理される命令をテストする OPTION_STATUS equ 1<<28 ;ステータスレジスタを調べる OPTION_SUCCESSFUL equ 1<<29 ;成功したテストの結果を出力する OPTION_DEFAULT equ OPTION_STATUS+OPTION_FAILED+OPTION_DESTINATION+(OPTION_MAXIMUM_DEFAULT<<OPTION_MAXIMUM_SHIFT)+OPTION_MARGIN_DEFAULT ;---------------------------------------------------------------- ;successful=option_start(cmdl) ; 全体ループの開始前に呼び出す ; コマンドラインをコピーする ; 引数がひとつもないとき使用法を表示する ; 全体ループの準備をする ;<4(sp).l:コマンドライン ;>d0.l:0=failed,1=successful ;------------------------------------------------ .offsym 0,_a6 _size: regs reg d1-d2/a0-a2 _regs: .ds.l .sizeof.(regs) _a6: .ds.l 1 _pc: .ds.l 1 _cmdl: .ds.l 1 ;------------------------------------------------ .text .even option_start:: link.w a6,#_size movem.l regs,(_regs,a6) ;------------------------------------------------ ;コマンドラインをコピーする movea.l (_cmdl,a6),a0 ;コマンドライン lea.l option_args,a1 ;単語列バッファ lea.l option_argsend,a2 ;単語列バッファの末尾 bra 2f ;単語の間の空白を読み飛ばす ;単語が終わった 1: cmpa.l a2,a1 bcc 11f ;バッファが溢れた clr.b (a1)+ ;単語の末尾の0 ;単語の間の空白を読み飛ばす 2: move.b (a0)+,d0 beq 10f ;単語が始まる前にコマンドラインが終わった cmp.b #' ',d0 bls 2b ;単語の間の空白を読み飛ばす cmp.b #$22,d0 beq 6f ;$22~$22の中の次の文字を読み出す cmp.b #$27,d0 beq 8f ;'~'の中の次の文字を読み出す cmp.b #'a',d0 blo 3f ;文字をバッファに書き込む cmp.b #'z',d0 bhi 3f ;文字をバッファに書き込む and.b #$DF,d0 ;大文字にする ;文字をバッファに書き込む 3: cmpa.l a2,a1 bcc 11f ;バッファが溢れた move.b d0,(a1)+ ;次の文字を読み出す 4: move.b (a0)+,d0 beq 9f ;単語の途中でコマンドラインが終わった cmp.b #' ',d0 bls 1b ;単語が終わった cmp.b #$22,d0 beq 6f ;$22~$22の中の次の文字を読み出す cmp.b #$27,d0 beq 8f ;'~'の中の次の文字を読み出す cmp.b #'a',d0 blo 3b ;文字をバッファに書き込む cmp.b #'z',d0 bhi 3b ;文字をバッファに書き込む and.b #$DF,d0 ;大文字にする bra 3b ;文字をバッファに書き込む ;$22~$22の中の文字をバッファに書き込む 5: cmpa.l a2,a1 bcc 11f ;バッファが溢れた move.b d0,(a1)+ ;$22~$22の中の次の文字を読み出す 6: move.b (a0)+,d0 beq 9f ;単語の途中でコマンドラインが終わった cmp.b #$22,d0 beq 4b ;次の文字を読み出す cmp.b #'a',d0 blo 5b ;$22~$22の中の文字をバッファに書き込む cmp.b #'z',d0 bhi 5b ;$22~$22の中の文字をバッファに書き込む and.b #$DF,d0 ;大文字にする bra 5b ;$22~$22の中の文字をバッファに書き込む ;'~'の中の文字をバッファに書き込む 7: cmpa.l a2,a1 bcc 11f ;バッファが溢れた move.b d0,(a1)+ ;'~'の中の次の文字を読み出す 8: move.b (a0)+,d0 beq 9f ;単語の途中でコマンドラインが終わった cmp.b #$27,d0 beq 4b ;次の文字を読み出す cmp.b #'a',d0 blo 7b ;'~'の中の文字をバッファに書き込む cmp.b #'z',d0 bhi 7b ;'~'の中の文字をバッファに書き込む and.b #$DF,d0 ;大文字にする bra 7b ;'~'の中の文字をバッファに書き込む ;単語の途中でコマンドラインが終わった 9: cmpa.l a2,a1 bcc 11f ;バッファが溢れた clr.b (a1)+ ;単語の末尾の0 ;単語が始まる前にコマンドラインが終わった 10: cmpa.l a2,a1 bcc 11f ;バッファが溢れた clr.b (a1) ;バッファの末尾の0 bra 12f ;バッファが溢れた 11: putmsg 'too long command line',13,10 moveq.l #0,d0 bra 99f 12: ;------------------------------------------------ ;引数がひとつもないとき使用法を表示する tst.b option_args bne @f putstr #option_usage moveq.l #0,d0 bra 99f @@: ;------------------------------------------------ ;全体ループの準備をする lea.l option_args,a1 ;単語列バッファ move.l a1,option_word ;次の単語 move.l #OPTION_DEFAULT,option_mode ;動作モード move.l #-1,option_lastmode ;前回の動作モード lea.l option_donestart,a1 ;実行済みのテストのIDと動作モードのリストの先頭 move.l a1,option_donepointer ;実行済みのテストのIDと動作モードのリストの末尾 ;------------------------------------------------ 98: moveq.l #1,d0 99: movem.l (_regs,a6),regs unlk a6 rts ;------------------------------------------------ ;使用法 .text option_usage:: .dc.b 'usage: ",TEST_X," <mnemonic or option> ...',13,10 .dc.b ' FABS FACOS FADD ... -- Run tests selected by the first few letters of a mnemonic.',13,10 .dc.b ' all -- Run all tests.',13,10 .dc.b ' destination=0..[1] -- Check the destination operand.',13,10 .dc.b ' easy -- It',39,'s the same as margin=1 nans=0.',13,10 .dc.b ' failed=0..[1] -- Output the results of failed tests.',13,10 .dc.b ' fpsp=[0]..1 -- Test the instructions processed by the software package.',13,10 .dc.b ' hard -- It',39,'s the same as margin=0 nans=1.',13,10 .dc.b ' logging=0..[1] -- Output the results to ',34,'",TEST_LOG,"',34,'.',13,10 .dc.b ' margin=0..[1]..11 -- The acceptable margin of error in transcendental functions.',13,10 .dc.b ' maximum=0..[100]..1000000 -- The maximum number of results outputted for each test.',13,10 .dc.b ' nans=[0]..1 -- Check the mantissa of NaNs.',13,10 .dc.b ' status=0..[1] -- Check the status register.',13,10 .dc.b ' stdout=0..[1] -- Output the results to the standard output.',13,10 .dc.b ' successful=[0]..1 -- Output the results of successful tests.',13,10 .dc.b 0 ;---------------------------------------------------------------- ;option_loop() ; 全体ループの先頭で呼び出す ; 次の単語がなければ全体ループを終了する ; 次の単語によって動作モードを変更する .text .even option_loop:: movea.l option_word,a2 ;次の単語 move.l option_mode,d2 ;動作モード bra 20f ;次の単語に進む 10: tst.b (a2)+ bne 10b ;------------------------------------------------ ;次の単語がなければ全体ループを終了する 20: tst.b (a2) beq 80f ;全体ループを終了する ;------------------------------------------------ ;次の単語によって動作モードを更新する ;-------------------------------- ;destination=0..1 leamsg 'DESTINATION',a0 movea.l a2,a1 bsr option_stringstartwith bne 2f lea.l (.sizeof.('DESTINATION'),a2),a0 moveq.l #1,d0 jbsr option_equal_n bmi 2f and.l #.not.(OPTION_DESTINATION),d2 neg.l d0 and.l #OPTION_DESTINATION,d0 or.l d0,d2 ;destination bra 10b ;次の単語に進む 2: ;-------------------------------- ;easy=1 leamsg 'EASY',a0 movea.l a2,a1 bsr option_stringequals bne 2f and.l #.not.(OPTION_NANS+OPTION_MARGIN_MASK),d2 or.l #1,d2 ;margin=1 nans=0 bra 10b ;次の単語に進む 2: ;-------------------------------- ;failed=0..1 leamsg 'FAILED',a0 movea.l a2,a1 bsr option_stringstartwith bne 2f lea.l (.sizeof.('FAILED'),a2),a0 moveq.l #1,d0 jbsr option_equal_n bmi 2f and.l #.not.(OPTION_FAILED),d2 neg.l d0 and.l #OPTION_FAILED,d0 or.l d0,d2 ;failed bra 10b ;次の単語に進む 2: ;-------------------------------- ;fpsp=0..1 leamsg 'FPSP',a0 movea.l a2,a1 bsr option_stringstartwith bne 2f lea.l (.sizeof.('FPSP'),a2),a0 moveq.l #1,d0 jbsr option_equal_n bmi 2f bne 1f and.l #.not.(OPTION_FPSP),d2 ;fpsp=0 cmpi.l #FPSP040,fpu_type bne @f move.l #MC68040,fpu_type bra 10b ;次の単語に進む @@: cmpi.l #FPSP060,fpu_type bne 10b ;次の単語に進む move.l #MC68060,fpu_type bra 10b ;次の単語に進む 1: or.l #OPTION_FPSP,d2 ;fpsp=1 cmpi.l #MC68040,fpu_type bne @f move.l #FPSP040,fpu_type bra 10b ;次の単語に進む @@: cmpi.l #MC68060,fpu_type bne 10b ;次の単語に進む move.l #FPSP060,fpu_type bra 10b ;次の単語に進む 2: ;-------------------------------- ;hard=1 leamsg 'HARD',a0 movea.l a2,a1 bsr option_stringequals bne 2f and.l #.not.(OPTION_NANS+OPTION_MARGIN_MASK),d2 or.l #OPTION_NANS+0,d2 ;margin=0 nans=1 bra 10b ;次の単語に進む 2: ;-------------------------------- ;logging=0..1 leamsg 'LOGGING',a0 movea.l a2,a1 bsr option_stringstartwith bne 2f lea.l (.sizeof.('LOGGING'),a2),a0 moveq.l #1,d0 jbsr option_equal_n bmi 2f sne.b logging_logging bra 10b ;次の単語に進む 2: ;-------------------------------- ;margin=0..OPTION_MARGIN_LIMIT leamsg 'MARGIN=',a0 movea.l a2,a1 bsr option_stringstartwith bne 2f lea.l (.sizeof.('MARGIN'),a2),a0 moveq.l #OPTION_MARGIN_LIMIT,d0 jbsr option_equal_n bmi 2f and.l #.not.(OPTION_MARGIN_MASK),d2 or.l d0,d2 ;margin bra 10b ;次の単語に進む 2: ;-------------------------------- ;maxmum=0..OPTION_MAXIMUM_LIMIT leamsg 'MAXIMUM=',a0 movea.l a2,a1 bsr option_stringstartwith bne 2f lea.l (.sizeof.('MAXIMUM'),a2),a0 move.l #OPTION_MAXIMUM_LIMIT,d0 jbsr option_equal_n bmi 2f and.l #.not.(OPTION_MAXIMUM_MASK<<OPTION_MAXIMUM_SHIFT),d2 lsl.l #OPTION_MAXIMUM_SHIFT,d0 or.l d0,d2 ;maximum bra 10b ;次の単語に進む 2: ;-------------------------------- ;nans=0..1 leamsg 'NANS',a0 movea.l a2,a1 bsr option_stringstartwith bne 2f lea.l (.sizeof.('NANS'),a2),a0 moveq.l #1,d0 jbsr option_equal_n bmi 2f and.l #.not.(OPTION_NANS),d2 neg.l d0 and.l #OPTION_NANS,d0 or.l d0,d2 ;nans bra 10b ;次の単語に進む 2: ;-------------------------------- ;successful=0..1 leamsg 'SUCCESSFUL',a0 movea.l a2,a1 bsr option_stringstartwith bne 2f lea.l (.sizeof.('SUCCESSFUL'),a2),a0 moveq.l #1,d0 jbsr option_equal_n bmi 2f and.l #.not.(OPTION_SUCCESSFUL),d2 neg.l d0 and.l #OPTION_SUCCESSFUL,d0 or.l d0,d2 ;successful bra 10b ;次の単語に進む 2: ;-------------------------------- ;status=0..1 leamsg 'STATUS',a0 movea.l a2,a1 bsr option_stringstartwith bne 2f lea.l (.sizeof.('STATUS'),a2),a0 moveq.l #1,d0 jbsr option_equal_n bmi 2f and.l #.not.(OPTION_STATUS),d2 neg.l d0 and.l #OPTION_STATUS,d0 or.l d0,d2 ;status bra 10b ;次の単語に進む 2: ;-------------------------------- ;stdout=0..1 leamsg 'STDOUT',a0 movea.l a2,a1 bsr option_stringstartwith bne 2f lea.l (.sizeof.('STDOUT'),a2),a0 moveq.l #1,d0 jbsr option_equal_n bmi 2f sne.b logging_stdout bra 10b ;次の単語に進む 2: ;-------------------------------- move.l d2,option_mode ;動作モード move.l a2,option_word ;次の単語 ; bra 98f ;全体ループを終了する 80: moveq.l #0,d0 bra 99f 98: moveq.l #1,d0 99: rts ;---------------------------------------------------------------- ;mnemonic_start(mnemonic,fpu) ; 個々のテストの開始前に呼び出す ; ニモニックを確認する ; FPUを確認する ; 実行済みかどうか確認する ; ニモニックのカウンタをクリアする ; 初回または動作モードが変更されたとき動作モードを表示する ; バックグラウンドスレッドを回す ;<(sp).l:復帰アドレス。テストのIDとして使う ;<4(sp).l:テストのニモニックの条件 ;<8(sp).l:テストのFPUの条件 ;>d0.l:0=失敗,1=成功 ;>eq=失敗,ne=成功 ;------------------------------------------------ .offsym 0,_a6 _size: regs reg d1-d2/a0-a2 _regs: .ds.l .sizeof.(regs) _a6: .ds.l 1 _pc: .ds.l 1 _mnem: .ds.l 1 _fpu: .ds.l 1 ;------------------------------------------------ .text .even mnemonic_start:: link.w a6,#_size movem.l regs,(_regs,a6) ;------------------------------------------------ ;ニモニックを確認する leamsg 'ALL',a0 movea.l option_word,a1 ;次の単語 bsr option_stringequals beq @f ;allはすべてのニモニックと一致する movea.l option_word,a0 ;次の単語 movea.l (_mnem,a6),a1 ;テストのニモニックの条件 bsr option_stringstartwith bne 97f ;ニモニックが一致しなかった。失敗 @@: ;------------------------------------------------ ;FPUを確認する move.l (_fpu,a6),d0 ;テストのFPUの条件 and.l fpu_type,d0 ;FPUの種類 beq 97f ;FPUが一致しなかった。失敗 ;------------------------------------------------ ;実行済みかどうか確認する move.l (_pc,a6),d0 ;テストのID move.l option_mode,d1 ;動作モード lea.l option_donestart,a0 ;実行済みのテストのIDと動作モードのリストの先頭 movea.l option_donepointer,a1 ;実行済みのテストのIDと動作モードのリストの末尾 bra 3f 1: cmp.l (a0),d0 ;テストのID bne 2f cmp.l 4(a0),d1 ;動作モード beq 97f ;実行済みだった。失敗 2: addq.l #8,a0 3: cmpa.l a1,a0 blo 1b ;実行済みではなかった move.l d0,(a1)+ ;実行済みのテストのID move.l d1,(a1)+ ;実行済みの動作モード move.l a1,option_donepointer ;------------------------------------------------ ;ニモニックのカウンタをクリアする clr.l mnemonic_counter clr.l statistics_tested clr.l statistics_failed ;------------------------------------------------ ;初回はFPUの種類を表示する move.l fpu_type,d2 ;FPUの種類 cmp.l fpu_last,d2 ;前回のFPUの種類 beq 3f move.l d2,fpu_last putmsg 'fpu: ' ; move.l #MC68881,d0 and.l d2,d0 beq 1f leamsg 'MC68881',a0 bra 2f 1: move.l #MC68882,d0 and.l d2,d0 beq 1f leamsg 'MC68882',a0 bra 2f 1: move.l #MC68040,d0 and.l d2,d0 beq 1f leamsg 'MC68040',a0 bra 2f 1: move.l #FPSP040,d0 and.l d2,d0 beq 1f leamsg '040FPSP',a0 bra 2f 1: move.l #MC68060,d0 and.l d2,d0 beq 1f leamsg 'MC68060',a0 bra 2f 1: move.l #FPSP060,d0 and.l d2,d0 beq 1f leamsg '060FPSP',a0 bra 2f 1: leamsg '???',a0 2: putstr a0 putcrlf 3: ;------------------------------------------------ ;初回または動作モードが変更されたとき動作モードを表示する move.l option_mode,d2 ;動作モード cmp.l option_lastmode,d2 ;前回の動作モード beq 3f move.l d2,option_lastmode putmsg 'option:' ;-------------------------------- putmsg ' destination' move.l d2,d0 and.l #OPTION_DESTINATION,d0 bne @f putmsg '=0' @@: ;-------------------------------- move.l d2,d0 and.l #OPTION_NANS+OPTION_MARGIN_MASK,d0 cmp.l #1,d0 ;margin=1 nans=0 bne @f putmsg ' easy' @@: ;-------------------------------- putmsg ' failed' move.l d2,d0 and.l #OPTION_FAILED,d0 bne @f putmsg '=0' @@: ;-------------------------------- putmsg ' fpsp' move.l d2,d0 and.l #OPTION_FPSP,d0 bne @f putmsg '=0' @@: ;-------------------------------- move.l d2,d0 and.l #OPTION_NANS+OPTION_MARGIN_MASK,d0 cmp.l #OPTION_NANS+0,d0 ;margin=0 nans=1 bne @f putmsg ' hard' @@: ;-------------------------------- putmsg ' margin=' move.l d2,d0 and.l #OPTION_MARGIN_MASK,d0 putdec d0 ;-------------------------------- putmsg ' maximum=' move.l d2,d0 lsr.l #OPTION_MAXIMUM_SHIFT,d0 and.l #OPTION_MAXIMUM_MASK,d0 putdec d0 ;-------------------------------- putmsg ' nans' move.l d2,d0 and.l #OPTION_NANS,d0 bne @f putmsg '=0' @@: ;-------------------------------- putmsg ' status' move.l d2,d0 and.l #OPTION_STATUS,d0 bne @f putmsg '=0' @@: ;-------------------------------- putmsg ' successful' move.l d2,d0 and.l #OPTION_SUCCESSFUL,d0 bne @f putmsg '=0' @@: ;------------------------------------------------ putcrlf 3: ;------------------------------------------------ ;バックグラウンドスレッドを回す move.l fpu_type,d0 ;FPUの種類 and.l #MC68881+MC68882+MC68040+FPSP040+MC68060+FPSP060,d0 beq @f .cpu 68030 fnop .cpu 68000 @@: DOS _CHANGE_PR ;------------------------------------------------ ;成功 98: moveq.l #1,d0 99: movem.l (_regs,a6),regs unlk a6 rts ;失敗 97: moveq.l #0,d0 bra 99b .data .align 4 mnemonic_counter:: .dc.l 1 ;ニモニックのカウンタ ;---------------------------------------------------------------- ;mnemonic_end() ; ニモニックの成績を表示する ; ニモニックの成績を総合成績に加える .text .even mnemonic_end:: movem.l d0-d1,-(sp) move.l statistics_tested,d0 move.l statistics_failed,d1 putmsg 'score: ' movem.l d0-d1,-(sp) jbsr statistics_output addq.l #8,sp add.l d0,statistics_ttl_tested add.l d1,statistics_ttl_failed movem.l (sp)+,d0-d1 rts ;---------------------------------------------------------------- ;option_next() ; 全体ループの末尾で呼び出す ; 次の単語に進む .text .even option_next:: move.l a0,-(sp) ;------------------------------------------------ ;次の単語に進む movea.l option_word,a0 ;次の単語 @@: tst.b (a0)+ bne @b move.l a0,option_word ;次の単語 ;------------------------------------------------ movea.l (sp)+,a0 rts ;---------------------------------------------------------------- ; 文字列比較 ;<a0.l:文字列 ;<a1.l:文字列 ;>eq=一致,ne=不一致 .text .even option_stringequals:: 1: tst.b (a0) beq 2f cmpm.b (a1)+,(a0)+ beq 1b rts 2: tst.b (a1) rts ;---------------------------------------------------------------- ; 先頭文字列比較 ;<a0.l:先頭文字列 ;<a1.l:文字列 ;>eq=一致,ne=不一致 .text .even option_stringstartwith:: 1: tst.b (a0) beq 2f cmpm.b (a1)+,(a0)+ beq 1b 2: rts ;---------------------------------------------------------------- ; '=N'を読み取る ;<d0.l:上限 ;<a0.l:'='の位置 ;>d0.l:N。'='がないとき1。エラーのとき-1 .text .even option_equal_n:: movem.l d1-d2/a0,-(sp) move.l d0,d2 moveq.l #1,d0 tst.b (a0) beq 9f ;最初に文字がない cmpi.b #'=',(a0)+ bne 8f ;最初の文字が'='でない move.b (a0)+,d0 beq 8f ;'='の後に文字がない sub.b #'0',d0 blo 8f ;'='の後の文字が数字でない cmp.b #9,d0 bhi 8f ;'='の後の文字が数字でない 1: moveq.l #0,d1 move.b (a0)+,d1 beq 2f ;次の文字がない sub.b #'0',d1 blo 8f ;次の文字が数字でない cmp.b #9,d1 bhi 8f ;次の文字が数字でない add.l d0,d0 add.l d0,d1 lsl.l #2,d0 add.l d1,d0 bra 1b 2: cmp.l d2,d0 bls 9f 8: moveq.l #-1,d0 9: movem.l (sp)+,d1-d2/a0 tst.l d0 rts ;---------------------------------------------------------------- .bss option_args:: .ds.b 4096 ;単語列バッファ。単語,0,単語,0,…,単語,0,0 option_argsend:: .bss .align 4 option_word:: .ds.l 1 ;次の単語 option_mode:: .ds.l 1 ;動作モード option_lastmode:: .ds.l 1 ;動作モード .bss .align 4 option_donepointer:: .ds.l 1 ;実行済みのテストのIDと動作モードの書き込み位置 option_donestart:: .ds.l 2*1024*32 ;実行済みのテストのIDと動作モードのリスト option_doneend:: ;-------------------------------------------------------------------------------- ; logging ;-------------------------------------------------------------------------------- ;------------------------------------------------ ;logging_start() ;>d0.l:0=failed,1=successful .text .even logging_start:: move.l d1,-(sp) ; st.b logging_logging st.b logging_stdout ;open log file move.w #2,-(sp) ;read and write peamsg '",TEST_LOG,"' ;log file name DOS _OPEN addq.l #6,sp tst.l d0 bpl @f move.w #$0020,-(sp) ;file peamsg '",TEST_LOG,"' ;log file name DOS _CREATE addq.l #6,sp tst.l d0 bpl @f putmsg 'cannot open ",TEST_LOG," to write' moveq.l #0,d0 bra 99f @@: move.w d0,d1 ;log file handle move.w d1,logging_file_handle ;check device type move.w d1,-(sp) ;log file handle clr.w -(sp) ;device information DOS _IOCTRL addq.l #4,sp tst.b d0 bmi 1f ;character device ;block device or remote device ;seek end move.w #2,-(sp) ;SEEK_END clr.l -(sp) move.w d1,-(sp) ;log file handle DOS _SEEK addq.l #8,sp bra 2f ;character device 1: ;check output status move.w d1,-(sp) ;log file handle move.w #7,-(sp) ;output status DOS _IOCTRL addq.l #4,sp tst.l d0 bne @f putmsg 'cannot output to ",TEST_LOG,"' moveq.l #0,d0 bra 99f @@: 2: move.l #logging_cache_start,logging_cache_pointer ; 98: moveq.l #1,d0 99: move.l (sp)+,d1 tst.l d0 rts ;------------------------------------------------ ;logging_write(buffer,length) ;<4(sp).l:buffer ;<8(sp).l:length regs reg d0-d3/a0-a3 .offsym 0,_a6 _size: _regs: .ds.b .sizeof.(regs) _a6: .ds.l 1 _pc: .ds.l 1 _buff: .ds.l 1 _leng: .ds.l 1 .text .even logging_write:: link.w a6,#_size movem.l regs,(_regs,a6) ;ログファイルに出力する tst.b logging_logging beq 19f move.w logging_file_handle,d1 ;log file handle bmi 19f ;出力データをキャッシュにコピーする move.l (_leng,a6),d2 ;出力データの残りのバイト数 movea.l (_buff,a6),a0 ;出力データの読み出し位置 movea.l logging_cache_pointer,a1 ;キャッシュの書き込み位置 lea.l logging_cache_end,a3 ;キャッシュの終了アドレス。固定 bra 17f 10: move.l a3,d3 ;キャッシュの終了アドレス sub.l a1,d3 ;キャッシュの残りのバイト数。キャッシュの終了アドレス-キャッシュの書き込み位置 cmp.l d2,d3 ;キャッシュの残りのバイト数<=>出力データの残りのバイト数 blo 11f move.l d2,d3 ;出力データの残りのバイト数 11: ;<d3.l:出力データをキャッシュにコピーするバイト数。出力データの残りのバイト数とキャッシュの残りのバイト数の少ない方。0ではない move.l d3,d0 ;出力データをキャッシュにコピーするバイト数 subq.l #1,d0 swap.w d0 12: swap.w d0 13: move.b (a0)+,(a1)+ ;出力データの読み出し位置からキャッシュの書き込み位置へ dbra d0,13b swap.w d0 dbra d0,12b cmpa.l a3,a1 ;キャッシュの書き込み位置<=>キャッシュの終了アドレス blo 14f ;キャッシュが一杯になった lea.l logging_cache_start,a1 ;キャッシュの開始アドレス movea.l a3,a2 ;キャッシュの終了アドレス suba.l a1,a2 ;キャッシュの全体のバイト数 movem.l a1-a2,-(sp) move.w d1,-(sp) ;log file handle DOS _WRITE lea.l 10(sp),sp 14: move.l a1,logging_cache_pointer ;キャッシュの書き込み位置 sub.l d3,d2 ;出力データの残りのバイト数 17: tst.l d2 ;出力データの残りのバイト数 bne 10b 19: ;標準出力に出力する tst.b logging_stdout beq 29f move.l (_leng,a6),-(sp) ;length move.l (_buff,a6),-(sp) ;buffer move.w #1,-(sp) ;stdout DOS _WRITE lea.l 10(sp),sp 29: movem.l (_regs,a6),regs unlk a6 rts ;------------------------------------------------ ;logging_end() logging_end:: movem.l d0-d1/a1-a2,-(sp) ;close log file move.w logging_file_handle,d1 ;log file handle bmi 19f lea.l logging_cache_start,a1 ;キャッシュの開始アドレス movea.l logging_cache_pointer,a2 ;キャッシュの書き込み位置 suba.l a1,a2 ;キャッシュの現在のバイト数 move.l a2,d0 beq 11f movem.l a1-a2,-(sp) move.w d1,-(sp) ;log file handle DOS _WRITE lea.l 10(sp),sp 11: move.l a1,logging_cache_pointer ;キャッシュの書き込み位置 move.w d1,-(sp) ;log file handle DOS _CLOSE addq.l #2,sp move.w #-1,logging_file_handle 19: ; sf.b logging_logging st.b logging_stdout ; movem.l (sp)+,d0-d1/a1-a2 rts ;------------------------------------------------ .data logging_logging:: .dc.b 0 ;ファイルに出力する logging_stdout:: .dc.b -1 ;標準出力に出力する .even logging_file_handle:: .dc.w -1 ;log file handle .bss .align 4 logging_cache_pointer:: .ds.l 1 ;キャッシュの書き込み位置 logging_cache_start:: .ds.b 1024*64 ;キャッシュ logging_cache_end:: ;-------------------------------------------------------------------------------- ; statistics ;-------------------------------------------------------------------------------- ;-------------------------------------------------------------------------------- .text .even statistics_start:: clr.l statistics_ttl_tested clr.l statistics_ttl_failed rts ;-------------------------------------------------------------------------------- ;statistics_update() ;<(4,sp).l:0=failed,1=successful ;>d0.l:0=not output,1=output .text .even statistics_update:: addq.l #1,statistics_tested tst.l (4,sp) bne 1f ;successful ;failed addq.l #1,statistics_failed move.l #OPTION_FAILED,d0 bra 2f ;successful 1: move.l #OPTION_SUCCESSFUL,d0 2: and.l option_mode,d0 beq 8f ;not output addq.l #1,mnemonic_counter move.l option_mode,d0 lsr.l #OPTION_MAXIMUM_SHIFT,d0 and.l #OPTION_MAXIMUM_MASK,d0 cmp.l mnemonic_counter,d0 blo 8f ;not output ;output move.l mnemonic_counter,d0 putdec d0 putmsg ': ', moveq.l #1,d0 9: rts ;not output 8: moveq.l #0,d0 bra 9b ;-------------------------------------------------------------------------------- .text .even statistics_end:: putmsg 'total: ' move.l statistics_ttl_failed,-(sp) move.l statistics_ttl_tested,-(sp) jbsr statistics_output addq.l #8,sp rts ;-------------------------------------------------------------------------------- ;<(4,sp).l:tested ;<(8,sp).l:failed .text .even statistics_output:: movem.l d0-d6,-(sp) move.l (4*7+4,sp),d6 ;d6=tested move.l (4*7+8,sp),d4 ;d4=failed putmsg 'tested=' move.l d6,d5 ;tested sub.l d4,d5 ;d5=successful=tested-failed putdec d6 ;tested tst.l d6 ;tested beq 8f ;no tests were performed move.l #10000,d0 move.l d5,d1 ;successful jbsr mull ;d0:d1=10000*successful moveq.l #0,d2 move.l d6,d3 ;d2:d3=tested jbsr divq ;d1=10000*successful/tested move.l #10000,d0 sub.l d1,d0 ;d0=10000-10000*successful/tested putmsg ' failed=' putdec d4 ;failed putchr #'(' putfix d0,#2 ;10000-10000*successful/tested putmsg '%) successful=' putdec d5 ;successful putchr #'(' putfix d1,#2 ;10000*successful/tested putmsg '%)' 8: putcrlf movem.l (sp)+,d0-d6 rts .bss .align 4 statistics_tested:: .ds.l 1 ;number of tests statistics_failed:: .ds.l 1 ;number of failed tests statistics_ttl_tested:: .ds.l 1 ;number of total tests statistics_ttl_failed:: .ds.l 1 ;number of total failed tests ;-------------------------------------------------------------------------------- ; 結果を比較する ;-------------------------------------------------------------------------------- ;-------------------------------------------------------------------------------- ;successful=test_status() ; statusを比較する ;<(4,sp).l:actual status ;<(8,sp).l:expected status ;>d0.l:0=failed,1=successful .cpu 68030 .offsym 0,_a6 _size: _a6: .ds.l 1 _pc: .ds.l 1 _asta: .ds.l 1 ;actual status _esta: .ds.l 1 ;expected status .text .even test_status:: link.w a6,#_size ;------------------------------------------------ ;status move.l option_mode,d0 and.l #OPTION_STATUS,d0 beq 19f ;statusをテストしない。statusが一致 ;statusをテストする move.l (_asta,a6),d0 ;actual status cmp.l (_esta,a6),d0 ;expected status bne 97f ;statusが一致しない。失敗 ;statusが一致 19: ;------------------------------------------------ ;成功 98: moveq.l #1,d0 99: unlk a6 rts ;失敗 97: moveq.l #0,d0 bra 99b .cpu 68000 ;-------------------------------------------------------------------------------- ;successful=test_single() ; singleの結果を比較する。誤差は許容しない ;<(4,sp).s:actual result ;<(8,sp).l:actual status ;<(12,sp).s:expected result ;<(16,sp).l:expected status ;>d0.l:0=failed,1=successful .cpu 68030 .offsym 0,_a6 _size: _a6: .ds.l 1 _pc: .ds.l 1 _ares: .ds.s 1 ;actual result _asta: .ds.l 1 ;actual status _eres: .ds.s 1 ;expected result _esta: .ds.l 1 ;expected status .text .even test_single:: link.w a6,#_size ;------------------------------------------------ ;status move.l option_mode,d0 and.l #OPTION_STATUS,d0 beq 19f ;statusをテストしない。statusが一致 ;statusをテストする move.l (_asta,a6),d0 ;actual status cmp.l (_esta,a6),d0 ;expected status bne 97f ;statusが一致しない。失敗 ;statusが一致 19: ;------------------------------------------------ ;result move.l option_mode,d0 and.l #OPTION_DESTINATION,d0 beq 39f ;resultをテストしない。resultが一致 ;resultをテストする move.l (_ares,a6),d0 ;actual result cmp.l (_eres,a6),d0 ;expected result bne 97f ;resultが一致しない。失敗 ;resultが一致 39: ;------------------------------------------------ ;成功 98: moveq.l #1,d0 99: unlk a6 rts ;失敗 97: moveq.l #0,d0 bra 99b .cpu 68000 ;-------------------------------------------------------------------------------- ;successful=test_double() ; doubleの結果を比較する。誤差は許容しない ;<(4,sp).d:actual result ;<(12,sp).l:actual status ;<(16,sp).d:expected result ;<(24,sp).l:expected status ;>d0.l:0=failed,1=successful .cpu 68030 .offsym 0,_a6 _size: _a6: .ds.l 1 _pc: .ds.l 1 _ares: .ds.d 1 ;actual result _asta: .ds.l 1 ;actual status _eres: .ds.d 1 ;expected result _esta: .ds.l 1 ;expected status .text .even test_double:: link.w a6,#_size ;------------------------------------------------ ;status move.l option_mode,d0 and.l #OPTION_STATUS,d0 beq 19f ;statusをテストしない。statusが一致 ;statusをテストする move.l (_asta,a6),d0 ;actual status cmp.l (_esta,a6),d0 ;expected status bne 97f ;statusが一致しない。失敗 ;statusが一致 19: ;------------------------------------------------ ;result move.l option_mode,d0 and.l #OPTION_DESTINATION,d0 beq 39f ;resultをテストしない。resultが一致 ;resultをテストする move.l (_ares,a6),d0 ;actual result 1st cmp.l (_eres,a6),d0 ;expected result 1st bne 97f ;resultが一致しない。失敗 move.l (4+_ares,a6),d0 ;actual result 2nd cmp.l (4+_eres,a6),d0 ;expected result 2nd bne 97f ;resultが一致しない。失敗 ;resultが一致 39: ;------------------------------------------------ ;成功 98: moveq.l #1,d0 99: unlk a6 rts ;失敗 97: moveq.l #0,d0 bra 99b .cpu 68000 ;-------------------------------------------------------------------------------- ;successful=test_packed() ; packedの結果を比較する。誤差は許容しない ;<(4,sp).p:actual result ;<(12,sp).l:actual status ;<(16,sp).p:expected result ;<(24,sp).l:expected status ;>d0.l:0=failed,1=successful .cpu 68030 .offsym 0,_a6 _size: _a6: .ds.l 1 _pc: .ds.l 1 _ares: .ds.p 1 ;actual result _asta: .ds.l 1 ;actual status _eres: .ds.p 1 ;expected result _esta: .ds.l 1 ;expected status .text .even test_packed:: link.w a6,#_size ;------------------------------------------------ ;status move.l option_mode,d0 and.l #OPTION_STATUS,d0 beq 19f ;statusをテストしない。statusが一致 ;statusをテストする move.l (_asta,a6),d0 ;actual status cmp.l (_esta,a6),d0 ;expected status bne 97f ;statusが一致しない。失敗 ;statusが一致 19: ;------------------------------------------------ ;result move.l option_mode,d0 and.l #OPTION_DESTINATION,d0 beq 39f ;resultをテストしない。resultが一致 ;resultをテストする move.l (_ares,a6),d0 ;actual result 1st cmp.l (_eres,a6),d0 ;expected result 1st bne 97f ;resultが一致しない。失敗 move.l (4+_ares,a6),d0 ;actual result 2nd cmp.l (4+_eres,a6),d0 ;expected result 2nd bne 97f ;resultが一致しない。失敗 move.l (8+_ares,a6),d0 ;actual result 3rd cmp.l (8+_eres,a6),d0 ;expected result 3rd bne 97f ;resultが一致しない。失敗 ;resultが一致 39: ;------------------------------------------------ ;成功 98: moveq.l #1,d0 99: unlk a6 rts ;失敗 97: moveq.l #0,d0 bra 99b .cpu 68000 ;-------------------------------------------------------------------------------- ;successful=test_extended() ; extendedの結果を比較する。誤差を許容する ;<(4,sp).x:actual result ;<(16,sp).l:actual status ;<(20,sp).x:expected result ;<(32,sp).l:expected status ;<(36,sp).l:fpcr(rp<<6,-1=strict) ;>d0.l:0=failed,1=successful .cpu 68030 regs reg d1-d6 cregs reg fpcr/fpsr/fpiar fregs reg fp0-fp2 .offsym 0,_a6 _size: _regs: .ds.b .sizeof.(regs) _fregs: .ds.b .sizeof.(fregs) _cregs: .ds.b .sizeof.(cregs) _a6: .ds.l 1 _pc: .ds.l 1 _ares: .ds.x 1 ;actual result _asta: .ds.l 1 ;actual status _eres: .ds.x 1 ;expected result _esta: .ds.l 1 ;expected status _fpcr: .ds.l 1 ;fpcr(rp<<6,-1=strict) .text .even test_extended:: link.w a6,#_size movem.l regs,(_regs,a6) fmovem.l cregs,(_cregs,a6) fmovem.x fregs,(_fregs,a6) ;---------------------------------------------------------------- ;status move.l option_mode,d0 and.l #OPTION_STATUS,d0 beq 19f ;statusをテストしない。statusが一致 ;statusをテストする move.l (_asta,a6),d0 ;actual status cmp.l (_esta,a6),d0 ;expected status bne 97f ;statusが一致しない。失敗 ;statusが一致 19: ;---------------------------------------------------------------- ;result move.l option_mode,d0 and.l #OPTION_DESTINATION,d0 beq 39f ;resultをテストしない。resultが一致 ;resultをテストする fmove.l #0,fpcr ;------------------------------------------------ ;expected resultが正規化数または非正規化数か調べる move.l (_eres,a6),d0 ;expected result 1st and.l #$7FFF0000,d0 cmp.l #$7FFF0000,d0 beq 30f ;expected resultが±InfまたはNaN。完全に一致しなければならない or.l (4+_eres,a6),d0 ;expected result 2nd or.l (8+_eres,a6),d0 ;expected result 3rd beq 30f ;expected resultが±0。完全に一致しなければならない ;expected resultは正規化数または非正規化数 ;------------------------------------------------ ;1ulpを求める move.l (_fpcr,a6),d0 ;fpcr(rp<<6,-1=strict) cmp.l #-1,d0 beq 30f ;strict。完全に一致しなければならない move.l #$00000000,d4 ;extendedの1ulp move.l #$00000001,d5 lsr.b #6,d0 ;rounding precision beq 49f ;extended ;singleまたはdouble subq.b #2,d0 bcc 43f ;double ;-------------------------------- ;single move.l #$00000100,d4 ;singleの1ulp move.l #$00000000,d5 movem.l (_ares,a6),d1-d3 ;actual result and.l #$7FFF0000,d1 cmp.l #$7FFF0000,d1 beq 49f ;actual resultが±InfまたはNaN ;actual resultが±0または非正規化数または正規化数 move.l d2,d0 or.l d3,d0 beq 49f ;actual resultが±0 ;actual resultが非正規化数または正規化数 ;actual resultがsingleに丸められていることを確認する tst.l d2 bmi 42f ;actual resultが正規化数 ;actual resultが非正規化数 41: add.l d3,d3 addx.l d2,d2 bpl 41b ;actual resultが非正規化数 ;actual resultが正規化数 42: and.l #$000000FF,d2 or.l d3,d2 bne 97f ;actual resultがsingleに丸められていない。失敗 bra 49f ;-------------------------------- ;double 43: move.l #$00000000,d4 ;doubleの1ulp move.l #$00000800,d5 movem.l (_ares,a6),d1-d3 ;actual result and.l #$7FFF0000,d1 cmp.l #$7FFF0000,d1 beq 49f ;actual resultが±InfまたはNaN ;actual resultが±0または非正規化数または正規化数 move.l d2,d0 or.l d3,d0 beq 49f ;actual resultが±0 ;actual resultが非正規化数または正規化数 ;actual resultがdoubleに丸められていることを確認する tst.l d2 bmi 45f ;actual resultが正規化数 ;actual resultが非正規化数 44: add.l d3,d3 addx.l d2,d2 bpl 44b ;actual resultが非正規化数 ;actual resultが正規化数 45: and.l #$000007FF,d3 bne 97f ;actual resultがdoubleに丸められていない。失敗 49: ;<d4-d5:1ulp ;------------------------------------------------ ;マージンを求める move.l option_mode,d0 and.l #OPTION_MARGIN_MASK,d0 ;margin bne 1f moveq.l #0,d4 moveq.l #0,d5 bra 2f 1: subq.w #1,d0 lsl.l d0,d4 ;extended,single,doubleのいずれも下位ワードが1bit立っているだけなのでこれだけでよい lsl.l d0,d5 2: ;<d4-d5:マージン ;------------------------------------------------ ;許容範囲の絶対値の下限を求める movem.l (_eres,a6),d1-d3 ;expected result tst.l d2 bpl 22f ;非正規化数 ;正規化数 sub.l d5,d3 subx.l d4,d2 bmi 23f ;指数部が変わらない move.l d1,d0 and.l #$7FFF0000,d0 beq 23f ;指数部が0のときは正規化数が非正規化数になる sub.l #$00010000,d1 ;指数部を1減らす add.l d3,d3 ;仮数部を左にずらす addx.l d2,d2 bra 23f ;非正規化数 22: sub.l d5,d3 subx.l d4,d2 bpl 23f and.l #$80000000,d1 ;引けなかったとき許容範囲の絶対値の下限は0 move.l #$00000000,d2 move.l #$00000000,d3 23: movem.l d1-d3,-(sp) fmove.x (sp)+,fp1 ;許容範囲の絶対値の下限 ;<fp1.x:許容範囲の絶対値の下限 ;------------------------------------------------ ;許容範囲の絶対値の上限を求める movem.l (_eres,a6),d1-d3 ;expected result tst.l d2 bpl 25f ;非正規化数 ;正規化数 add.l d5,d3 addx.l d4,d2 bmi 26f ;指数部が変わらない move.l d1,d0 and.l #$7FFF0000,d0 cmp.l #$7FFE0000,d0 beq 24f ;指数部が$7FFEのときは±Infになる add.l #$00010000,d1 ;指数部を1増やす roxr.l #1,d2 ;仮数部を右にずらす roxr.l #1,d3 or.l #$80000000,d2 bra 26f 24: or.l #$7FFF0000,d1 moveq.l #0,d2 moveq.l #0,d3 bra 26f ;非正規化数 25: add.l d5,d3 ;仮数部にマージンを加える。非正規化数が正規化数になる場合がある addx.l d4,d2 26: movem.l d1-d3,-(sp) fmove.x (sp)+,fp2 ;許容範囲の絶対値の上限 ;<fp2.x:許容範囲の絶対値の上限 ;------------------------------------------------ ;下限<=上限にする。マージンが0のときは下限==上限になる。下限と上限は範囲に含まれる fcmp.x fp1,fp2 fbge 27f fmove.x fp2,fp0 fmove.x fp1,fp2 fmove.x fp0,fp1 27: ;<fp1.x:許容範囲の下限 ;<fp2.x:許容範囲の上限 ;------------------------------------------------ ;比較する fmove.x (_ares,a6),fp0 ;actual result fcmp.x fp1,fp0 fbult 97f ;actual resultがNaNまたは小さすぎる。失敗 fcmp.x fp2,fp0 fbugt 97f ;actual resultがNaNまたは大きすぎる。失敗 bra 98f ;成功 ;------------------------------------------------ ;完全に一致しなければならない 30: movem.l (_eres,a6),d1-d3 ;expected result movem.l (_ares,a6),d4-d6 ;actual result move.l #OPTION_NANS,d0 and.l option_mode,d0 bne 35f ;NaNの仮数部を比較する ;NaNの仮数部を無視する ;------------------------------------------------ ;expected resultがNaNのとき仮数をすべて1にする move.l d1,d0 and.l #$7FFF0000,d0 cmp.l #$7FFF0000,d0 bne 32f ;±InfまたはNaNではない tst.l d2 bne 31f ;NaN tst.l d3 beq 32f ;±Inf ;NaN 31: move.l #$FFFFFFFF,d2 ;NaNの仮数部をすべて1にする move.l #$FFFFFFFF,d3 32: ;------------------------------------------------ ;actual resultがNaNのとき仮数をすべて1にする move.l d4,d0 and.l #$7FFF0000,d0 cmp.l #$7FFF0000,d0 bne 34f ;±InfまたはNaNではない tst.l d5 bne 33f ;NaN tst.l d6 beq 34f ;±Inf ;NaN 33: move.l #$FFFFFFFF,d5 ;NaNの仮数部をすべて1にする move.l #$FFFFFFFF,d6 34: ;------------------------------------------------ ;比較する 35: cmp.l d1,d4 bne 97f ;resultが一致しない。失敗 cmp.l d2,d5 bne 97f ;resultが一致しない。失敗 cmp.l d3,d6 bne 97f ;resultが一致しない。失敗 ;resultが一致 39: ;------------------------------------------------ ;成功 98: moveq.l #1,d0 99: fmovem.x (_fregs,a6),fregs fmovem.l (_cregs,a6),cregs movem.l (_regs,a6),regs unlk a6 rts ;失敗 97: moveq.l #0,d0 bra 99b .cpu 68000 ;-------------------------------------------------------------------------------- ; 結果を出力する ;-------------------------------------------------------------------------------- ;-------------------------------------------------------------------------------- ;output_status() ; output status ;<(4,sp).l:actual status ;<(8,sp).l:expected status ;<(12,sp).l:0=failed,1=successful .cpu 68030 regs reg d3-d4/a3 .offsym 0,_a6 _size: _regs: .ds.b .sizeof.(regs) _a6: .ds.l 1 _pc: .ds.l 1 _asta: .ds.l 1 ;actual status _esta: .ds.l 1 ;expected status _succ: .ds.l 1 ;0=failed,1=successful .text .even output_status:: link.w a6,#_size movem.l regs,(_regs,a6) movea.l (_esta,a6),a3 ;expected status move.l (_asta,a6),d3 ;actual status ;successfulかどうかに関わらず完全に一致しているときだけexpectedを省略する moveq.l #1,d4 ;0=完全に一致してはいない,1=完全に一致している cmp.l a3,d3 beq 2f moveq.l #0,d4 ;0=完全に一致してはいない,1=完全に一致している ;expected putchr #9 move.l a3,-(sp) jbsr printfpsr addq.l #4,sp putmsg 9,';expected',13,10 2: ;actual putchr #9 move.l d3,-(sp) jbsr printfpsr addq.l #4,sp tst.l d4 beq 3f ;完全に一致してはいない ;完全に一致している putmsg 9,';' bra 4f 3: ;完全に一致してはいない putmsg 9,';actual ... ' 4: tst.l (_succ,a6) beq 5f ;failed ;successful putmsg 'OK',13,10 bra 6f 5: ;failed putmsg 'ERROR',13,10 6: ; 99: movem.l (_regs,a6),regs unlk a6 rts .cpu 68000 ;-------------------------------------------------------------------------------- ;output_single() ; output result and status ;<(4,sp).s:actual result ;<(8,sp).l:actual status ;<(12,sp).s:expected result ;<(16,sp).l:expected status ;<(20,sp).l:0=failed,1=successful .cpu 68030 regs reg d0/d3-d4/a0/a3 .offsym 0,_a6 _size: _regs: .ds.b .sizeof.(regs) _a6: .ds.l 1 _pc: .ds.l 1 _ares: .ds.s 1 ;actual result _asta: .ds.l 1 ;actual status _eres: .ds.s 1 ;expected result _esta: .ds.l 1 ;expected status _succ: .ds.l 1 ;0=failed,1=successful .text .even output_single:: link.w a6,#_size movem.l regs,(_regs,a6) movea.l (_eres,a6),a0 ;expected result movea.l (_esta,a6),a3 ;expected status move.l (_ares,a6),d0 ;actual result move.l (_asta,a6),d3 ;actual status ;successfulかどうかに関わらず完全に一致しているときだけexpectedを省略する moveq.l #1,d4 ;0=完全に一致してはいない,1=完全に一致している cmp.l a0,d0 bne 1f cmp.l a3,d3 beq 2f 1: moveq.l #0,d4 ;0=完全に一致してはいない,1=完全に一致している ;expected putchr #9 puthex8 a0 putchr #',' move.l a3,-(sp) jbsr printfpsr addq.l #4,sp putmsg 9,';expected',13,10 2: ;actual putchr #9 puthex8 d0 putchr #',' move.l d3,-(sp) jbsr printfpsr addq.l #4,sp tst.l d4 beq 3f ;完全に一致してはいない ;完全に一致している putmsg 9,';' bra 4f 3: ;完全に一致してはいない putmsg 9,';actual ... ' 4: tst.l (_succ,a6) beq 5f ;failed ;successful putmsg 'OK',13,10 bra 6f 5: ;failed putmsg 'ERROR',13,10 6: ; 99: movem.l (_regs,a6),regs unlk a6 rts .cpu 68000 ;-------------------------------------------------------------------------------- ;output_double() ; output result and status ;<(4,sp).d:actual result ;<(12,sp).l:actual status ;<(16,sp).d:expected result ;<(24,sp).l:expected status ;<(28,sp).l:0=failed,1=successful .cpu 68030 regs reg d0-d1/d3-d4/a0-a1/a3 .offsym 0,_a6 _size: _regs: .ds.b .sizeof.(regs) _a6: .ds.l 1 _pc: .ds.l 1 _ares: .ds.d 1 ;actual result _asta: .ds.l 1 ;actual status _eres: .ds.d 1 ;expected result _esta: .ds.l 1 ;expected status _succ: .ds.l 1 ;0=failed,1=successful .text .even output_double:: link.w a6,#_size movem.l regs,(_regs,a6) movem.l (_eres,a6),a0-a1 ;expected result movea.l (_esta,a6),a3 ;expected status movem.l (_ares,a6),d0-d1 ;actual result move.l (_asta,a6),d3 ;actual status ;successfulかどうかに関わらず完全に一致しているときだけexpectedを省略する moveq.l #1,d4 ;0=完全に一致してはいない,1=完全に一致している cmp.l a0,d0 bne 1f cmp.l a1,d1 bne 1f cmp.l a3,d3 beq 2f 1: moveq.l #0,d4 ;0=完全に一致してはいない,1=完全に一致している ;expected putchr #9 puthex16 a0,a1 putchr #',' move.l a3,-(sp) jbsr printfpsr addq.l #4,sp putmsg 9,';expected',13,10 2: ;actual putchr #9 puthex16 d0,d1 putchr #',' move.l d3,-(sp) jbsr printfpsr addq.l #4,sp tst.l d4 beq 3f ;完全に一致してはいない ;完全に一致している putmsg 9,';' bra 4f 3: ;完全に一致してはいない putmsg 9,';actual ... ' 4: tst.l (_succ,a6) beq 5f ;failed ;successful putmsg 'OK',13,10 bra 6f 5: ;failed putmsg 'ERROR',13,10 6: ; movem.l (_regs,a6),regs unlk a6 rts .cpu 68000 ;-------------------------------------------------------------------------------- ;output_packed() ; output result and status ;<(4,sp).p:actual result ;<(16,sp).l:actual status ;<(20,sp).p:expected result ;<(32,sp).l:expected status ;<(36,sp).l:0=failed,1=successful .cpu 68030 regs reg d0-d4/a0-a3 .offsym 0,_a6 _size: _regs: .ds.b .sizeof.(regs) _a6: .ds.l 1 _pc: .ds.l 1 _ares: .ds.p 1 ;actual result _asta: .ds.l 1 ;actual status _eres: .ds.p 1 ;expected result _esta: .ds.l 1 ;expected status _succ: .ds.l 1 ;0=failed,1=successful .text .even output_packed:: link.w a6,#_size movem.l regs,(_regs,a6) movem.l (_eres,a6),a0-a2 ;expected result movea.l (_esta,a6),a3 ;expected status movem.l (_ares,a6),d0-d2 ;actual result move.l (_asta,a6),d3 ;actual status ;successfulかどうかに関わらず完全に一致しているときだけexpectedを省略する moveq.l #1,d4 ;0=完全に一致してはいない,1=完全に一致している cmp.l a0,d0 bne 1f cmp.l a1,d1 bne 1f cmp.l a2,d2 bne 1f cmp.l a3,d3 beq 2f 1: moveq.l #0,d4 ;0=完全に一致してはいない,1=完全に一致している ;expected putchr #9 puthex24 a0,a1,a2 putchr #',' move.l a3,-(sp) jbsr printfpsr addq.l #4,sp putmsg 9,';expected',13,10 2: ;actual putchr #9 puthex24 d0,d1,d2 putchr #',' move.l d3,-(sp) jbsr printfpsr addq.l #4,sp tst.l d4 beq 3f ;完全に一致してはいない ;完全に一致している putmsg 9,';' bra 4f 3: ;完全に一致してはいない putmsg 9,';actual ... ' 4: tst.l (_succ,a6) beq 5f ;failed ;successful putmsg 'OK',13,10 bra 6f 5: ;failed putmsg 'ERROR',13,10 6: ; movem.l (_regs,a6),regs unlk a6 rts .cpu 68000 ;-------------------------------------------------------------------------------- ;output_extended() ; output result and status ;<(4,sp).x:actual result ;<(16,sp).l:actual status ;<(20,sp).x:expected result ;<(32,sp).l:expected status ;<(36,sp).l:0=failed,1=successful .cpu 68030 regs reg d0-d4/a0-a3 .offsym 0,_a6 _size: _regs: .ds.b .sizeof.(regs) _a6: .ds.l 1 _pc: .ds.l 1 _ares: .ds.x 1 ;actual result _asta: .ds.l 1 ;actual status _eres: .ds.x 1 ;expected result _esta: .ds.l 1 ;expected status _succ: .ds.l 1 ;0=failed,1=successful .text .even output_extended:: link.w a6,#_size movem.l regs,(_regs,a6) movem.l (_eres,a6),a0-a2 ;expected result movea.l (_esta,a6),a3 ;expected status movem.l (_ares,a6),d0-d2 ;actual result move.l (_asta,a6),d3 ;actual status ;successfulかどうかに関わらず完全に一致しているときだけexpectedを省略する moveq.l #1,d4 ;0=完全に一致してはいない,1=完全に一致している cmp.l a0,d0 bne 1f cmp.l a1,d1 bne 1f cmp.l a2,d2 bne 1f cmp.l a3,d3 beq 2f 1: moveq.l #0,d4 ;0=完全に一致してはいない,1=完全に一致している ;expected putchr #9 puthex24 a0,a1,a2 putchr #',' move.l a3,-(sp) jbsr printfpsr addq.l #4,sp putmsg 9,';expected',13,10 2: ;actual putchr #9 puthex24 d0,d1,d2 putchr #',' move.l d3,-(sp) jbsr printfpsr addq.l #4,sp tst.l d4 beq 3f ;完全に一致してはいない ;完全に一致している putmsg 9,';' bra 4f 3: ;完全に一致してはいない putmsg 9,';actual ... ' 4: tst.l (_succ,a6) beq 5f ;failed ;successful putmsg 'OK',13,10 bra 6f 5: ;failed putmsg 'ERROR',13,10 6: ; movem.l (_regs,a6),regs unlk a6 rts .cpu 68000 ;-------------------------------------------------------------------------------- ; 出力サブルーチン ;-------------------------------------------------------------------------------- ;---------------------------------------------------------------- ;printfpcrrprm(fpcr) ;<(4,sp).l:fpcr .text .even printfpcrrprm:: movem.l d0/a0,-(sp) move.l (4*2+4,sp),d0 ;fpcr and.w #$00F0,d0 ;rp,rm lsr.w #4-2,d0 lea.l (10f,pc,d0.w),a0 putstr a0 movem.l (sp)+,d0/a0 rts .align 4 10: .dc.l 'XRN'<<8|0 .dc.l 'XRZ'<<8|0 .dc.l 'XRM'<<8|0 .dc.l 'XRP'<<8|0 .dc.l 'SRN'<<8|0 .dc.l 'SRZ'<<8|0 .dc.l 'SRM'<<8|0 .dc.l 'SRP'<<8|0 .dc.l 'DRN'<<8|0 .dc.l 'DRZ'<<8|0 .dc.l 'DRM'<<8|0 .dc.l 'DRP'<<8|0 .dc.l 'DRN'<<8|0 .dc.l 'DRZ'<<8|0 .dc.l 'DRM'<<8|0 .dc.l 'DRP'<<8|0 ;---------------------------------------------------------------- ;printfpsr ;<4(sp).l:fpsr .text .even printfpsr:: movem.l d0/a0,-(sp) move.l (4*2+4,sp),d0 ;fpsr lea.l (-128,sp),sp movea.l sp,a0 jbsr fpsrstr putstr sp lea.l (128,sp),sp movem.l (sp)+,d0/a0 rts ;---------------------------------------------------------------- ;fpsrstr ;<d0.l:fpsr ;<a0.l:buffer ;>a0.l:buffer .text .even fpsrstr:: movem.l d0-d5/a1,-(sp) move.l d0,d5 ;fpsr sf.b d4 ;condition code byte lea.l (10f,pc),a1 moveq.l #27,d1 1: move.b (a1)+,d2 move.b (a1)+,d3 btst.l d1,d5 beq 2f move.b d2,(a0)+ move.b d3,(a0)+ move.b #'+',(a0)+ st.b d4 2: subq.w #1,d1 cmp.w #24,d1 bhs 1b ;quotient byte btst.l #23,d5 beq 1f move.b #'(',(a0)+ move.b #'1',(a0)+ move.b #'<',(a0)+ move.b #'<',(a0)+ move.b #'2',(a0)+ move.b #'3',(a0)+ move.b #')',(a0)+ move.b #'+',(a0)+ st.b d4 1: move.l d5,d0 and.l #$007F0000,d0 beq 2f swap.w d0 move.b #'(',(a0)+ jbsr decstr move.b #'<',(a0)+ move.b #'<',(a0)+ move.b #'1',(a0)+ move.b #'6',(a0)+ move.b #')',(a0)+ move.b #'+',(a0)+ st.b d4 2: ;exception byte, accrued exception byte lea.l (11f,pc),a1 moveq.l #15,d1 1: move.b (a1)+,d2 move.b (a1)+,d3 btst.l d1,d5 beq 2f move.b d2,(a0)+ move.b d3,(a0)+ move.b #'+',(a0)+ st.b d4 2: subq.w #1,d1 cmp.w #3,d1 bhs 1b tst.b d4 beq 3f clr.b -(a0) ;remove unnecessary '+' bra 8f 3: move.b #'0',(a0)+ clr.b (a0) 8: movem.l (sp)+,d0-d5/a1 rts 10: ; 27 26 25 24 .dc.b 'MI','ZE','IN','NA' 11: ; 15 14 13 12 11 10 9 8 7 6 5 4 3 .dc.b 'BS','SN','OE','OF','UF','DZ','X2','X1','AV','AO','AU','AZ','AX' ;---------------------------------------------------------------- ;printdate ; yyyy-mm-ddThh:mm:ss+09:00 .text .even printdate:: move.l a0,-(sp) lea.l (-28,sp),sp movea.l sp,a0 jbsr datestr putstr sp lea.l (28,sp),sp movea.l (sp)+,a0 rts ;---------------------------------------------------------------- ;datestr ; yyyy-mm-ddThh:mm:ss+09:00 .text .even datestr:: movem.l d0-d3,-(sp) ;get date and time DOS _GETDATE move.l d0,d2 ;<d2.l:date((dayofweek(0=sunday)<<16)+((year-1980)<<9)+(month<<5)+dayofmonth) DOS _GETTIM2 move.l d0,d3 ;<d3.l:time((hour<<16)+(minute<<8)+second) ;year ;........ .....www yyyyyyym mmmddddd rol.w #7,d2 ;........ .....www mmmmdddd dyyyyyyy moveq.l #$7F,d0 ;________ ________ ________ _1111111 and.w d2,d0 ;________ ________ ________ _yyyyyyy add.w #1980,d0 move.l #4,d1 jbsr deczstr move.b #'-',(a0)+ ;month rol.w #4,d2 ;........ .....www dddddyyy yyyymmmm moveq.l #$0F,d0 ;________ ________ ________ ____1111 and.w d2,d0 ;________ ________ ________ ____mmmm move.l #2,d1 jbsr deczstr move.b #'-',(a0)+ ;dayofmonth rol.w #5,d2 ;........ .....www yyyyyyym mmmddddd moveq.l #$1F,d0 ;________ ________ ________ ___11111 and.w d2,d0 ;________ ________ ________ ___ddddd ; move.l #2,d1 jbsr deczstr move.b #'T',(a0)+ ;hour ;........ ...hhhhh ..mmmmmm ..ssssss swap.w d3 ;..mmmmmm ..ssssss ........ ...hhhhh moveq.l #$1F,d0 ;________ ________ ________ ___11111 and.w d3,d0 ;________ ________ ________ ___hhhhh ; move.l #2,d1 jbsr deczstr move.b #':',(a0)+ ;minute rol.l #8,d3 ;..ssssss ........ ...hhhhh ..mmmmmm moveq.l #$3F,d0 ;________ ________ ________ __111111 and.w d3,d0 ;________ ________ ________ __mmmmmm ; move.l #2,d1 jbsr deczstr move.b #':',(a0)+ ;second rol.l #8,d3 ;........ ...hhhhh ..mmmmmm ..ssssss moveq.l #$3F,d0 ;________ ________ ________ __111111 and.w d3,d0 ;________ ________ ________ __ssssss ; move.l #2,d1 jbsr deczstr move.b #'+',(a0)+ move.b #'0',(a0)+ move.b #'9',(a0)+ move.b #':',(a0)+ move.b #'0',(a0)+ move.b #'0',(a0)+ clr.b (a0) movem.l (sp)+,d0-d3 rts ;---------------------------------------------------------------- ;printlong(number) ; %d ;<(4,sp).l:number .text .even printlong:: move.l (4,sp),-(sp) bpl @f putchr #'-' neg.l (sp) @@: jbsr printdec addq.l #4,sp rts ;---------------------------------------------------------------- ;printdec(number) ; %u ;<(4,sp).l:number .text .even printdec:: movem.l d0/a0,-(sp) move.l (4*2+4,sp),d0 ;number lea.l (-12,sp),sp movea.l sp,a0 jbsr decstr putstr sp lea.l (12,sp),sp movem.l (sp)+,d0/a0 rts ;---------------------------------------------------------------- ;printdecs(number,digits) ; %*u ;<(4,sp).l:number ;<(8,sp).l:digits .text .even printdecs:: movem.l d0-d2/a0,-(sp) movem.l (4*4+4,sp),d0-d1 ;number,digits moveq.l #4,d2 add.l d1,d2 and.w #-4,d2 suba.l d2,sp movea.l sp,a0 jbsr decsstr putstr sp adda.l d2,sp movem.l (sp)+,d0-d2 rts ;---------------------------------------------------------------- ;printdecz(number,digits) ; %0*u ;<(4,sp).l:number ;<(8,sp).l:digits .text .even printdecz:: movem.l d0-d2/a0,-(sp) movem.l (4*4+4,sp),d0-d1 ;number,digits moveq.l #4,d2 add.l d1,d2 and.w #-4,d2 suba.l d2,sp movea.l sp,a0 jbsr deczstr putstr sp adda.l d2,sp movem.l (sp)+,d0-d2 rts ;---------------------------------------------------------------- ;decstr ; %u ;<d0.l:number ;<a0.l:buffer ;>a0.l:buffer .text .even decstr:: movem.l d0-d2/a1,-(sp) tst.l d0 bne 1f move.b #'0',(a0)+ bra 5f 1: lea.l baseten,a1 2: move.l (a1)+,d1 cmp.l d1,d0 blo 2b 3: moveq.l #'0'-1,d2 4: addq.b #1,d2 sub.l d1,d0 bhs 4b add.l d1,d0 move.b d2,(a0)+ move.l (a1)+,d1 bne 3b 5: clr.b (a0) movem.l (sp)+,d0-d2/a1 rts ;---------------------------------------------------------------- ;decsstr ; %*u ;<d0.l:number ;<d1.l:digits ;<a0.l:buffer ;>a0.l:buffer .text .even decsstr:: movem.l d0-d2/a1-a2,-(sp) lea.l baseten+4*10,a1 movea.l a1,a2 ;remove zero digits tst.l d1 bne @f moveq.l #1,d1 @@: ;remove 11 or more digits cmp.l #11,d1 blo 3f sub.l #11,d1 swap.w d1 1: swap.w d1 2: move.b #' ',(a0)+ dbra d1,2b swap.w d1 dbra d1,1b moveq.l #10,d1 3: lsl.w #2,d1 suba.w d1,a2 ;specified start point ;calculate minimum digits tst.l d0 beq 2f lea.l (-4*10,a1),a1 1: cmp.l (a1)+,d0 blo 1b 2: subq.l #4,a1 ;required start point ;fill cmpa.l a1,a2 bhs 2f 1: move.b #' ',(a0)+ addq.l #4,a2 cmpa.l a1,a2 blo 1b 2: ;print decimal number move.l (a1)+,d1 1: moveq.l #'0'-1,d2 2: addq.b #1,d2 sub.l d1,d0 bhs 2b add.l d1,d0 move.b d2,(a0)+ move.l (a1)+,d1 bne 1b move.b d1,(a0) ;0 movem.l (sp)+,d0-d2/a1-a2 rts ;---------------------------------------------------------------- ;deczstr ; %0*u ;<d0.l:number ;<d1.l:digits ;<a0.l:buffer ;>a0.l:buffer .text .even deczstr:: movem.l d0-d2/a1-a2,-(sp) lea.l baseten+4*10,a1 movea.l a1,a2 ;remove zero digits tst.l d1 bne @f moveq.l #1,d1 @@: ;remove 11 or more digits cmp.l #11,d1 blo 3f sub.l #11,d1 swap.w d1 1: swap.w d1 2: move.b #'0',(a0)+ dbra d1,2b swap.w d1 dbra d1,1b moveq.l #10,d1 3: lsl.w #2,d1 suba.w d1,a2 ;specified start point ;calculate minimum digits tst.l d0 beq 2f lea.l (-4*10,a1),a1 1: cmp.l (a1)+,d0 blo 1b 2: subq.l #4,a1 ;required start point ;fill cmpa.l a1,a2 bhs 2f 1: move.b #'0',(a0)+ addq.l #4,a2 cmpa.l a1,a2 blo 1b 2: ;print decimal number move.l (a1)+,d1 1: moveq.l #'0'-1,d2 2: addq.b #1,d2 sub.l d1,d0 bhs 2b add.l d1,d0 move.b d2,(a0)+ move.l (a1)+,d1 bne 1b move.b d1,(a0) ;0 movem.l (sp)+,d0-d2/a1-a2 rts ;---------------------------------------------------------------- ;printfix(number,digits) ; print fixed point decimal number ;<4(sp).l:number. fixed point decimal number * 10^(number of digits after decimal point) ;<8(sp).b:digits. number of digits after decimal point regs reg d0-d4/a0-a1 .offsym 0,_a6 _size: _regs: .ds.b .sizeof.(regs) _a6: .ds.l 1 _pc: .ds.l 1 _numb: .ds.l 1 _digi: .ds.w 1 .text .even printfix:: link.w a6,#_size movem.l regs,(_regs,a6) moveq.l #0,d3 move.b (_digi,a6),d3 ;<d3.l:number of digits after decimal point move.l d3,d4 addq.w #3,d4 and.w #-4,d4 ;round up to multiples of four add.w #12,d4 ;12 bytes for integer part and decimal point ;<d4.l:buffer size suba.l d4,sp ;<sp.l:buffer movea.l sp,a0 move.l (_numb,a6),d0 ;fixed point decimal number * 10^(number of digits after decimal point) bne 20f ;non-zero ;zero move.b #'0',(a0)+ move.w d3,d2 ;number of digits after decimal point beq 13f ;omit decimal point move.b #'.',(a0)+ bra 12f 11: move.b #'0',(a0)+ 12: dbra d2,11b 13: bra 80f ;print 20: ;non-zero ;<d0.l:fixed point decimal number * 10^(number of digits after decimal point) lea.l baseten,a1 ;zero suppression 21: move.l (a1)+,d1 cmp.l d1,d0 blo 21b ;convert to decimal number 22: moveq.l #'0'-1,d2 23: addq.b #1,d2 sub.l d1,d0 bcc 23b add.l d1,d0 move.b d2,(a0)+ move.l (a1)+,d1 bne 22b ; move.l a0,d2 sub.l sp,d2 ;<d2.l:actual number of digits cmp.w d3,d2 bls 40f ;actual number of digits > number of digits after decimal point ;integer part exists ;insert '.' move.w d3,d2 ;number of digits after decimal point beq 33f ;omit decimal point movea.l a0,a1 addq.l #1,a0 bra 32f 31: move.b -(a1),1(a1) 32: dbra d2,31b move.b #'.',(a1) 33: bra 80f ;print 40: ;actual number of digits <= number of digits after decimal point ;no integer part exists ;insert '0.00...' move.w d3,d0 ;number of digits after decimal point sub.w d2,d0 ;number of zeros after decimal point movea.l a0,a1 lea.l 2(a0,d0.w),a0 bra 42f 41: move.b -(a1),2(a1,d0.w) 42: dbra d2,41b movea.l sp,a1 move.b #'0',(a1)+ move.b #'.',(a1)+ bra 44f 43: move.b #'0',(a1)+ 44: dbra d0,43b ;print 80: suba.l sp,a0 move.l a0,-(sp) ;length pea.l 4(sp) ;buffer jbsr logging_write ; addq.l #8,sp ; adda.l d4,sp movem.l (_regs,a6),regs unlk a6 rts ;---------------------------------------------------------------- .text .align 4 baseten:: .dc.l 1000000000 .dc.l 100000000 .dc.l 10000000 .dc.l 1000000 .dc.l 100000 .dc.l 10000 .dc.l 1000 .dc.l 100 .dc.l 10 .dc.l 1 .dc.l 0 ;---------------------------------------------------------------- ;printhex2(number) ; print hexadecimal number $XX ;<4(sp).b:number .text .even printhex2:: movem.l d0-d2/a0,-(sp) move.b 4*4+4(sp),d0 ;number subq.l #4,sp ;buffer movea.l sp,a0 move.b #'$',(a0)+ moveq.l #2-1,d2 2: rol.b #4,d0 moveq.l #15,d1 and.w d0,d1 move.b 10f(pc,d1.w),(a0)+ dbra d2,2b pea.l 1+2.w ;length pea.l 4(sp) ;buffer jbsr logging_write lea.l 8+4(sp),sp movem.l (sp)+,d0-d2/a0 rts 10: .dc.b '0123456789ABCDEF' ;---------------------------------------------------------------- ;printhex4(number) ; print hexadecimal number $XXXX ;<4(sp).w:number .text .even printhex4:: movem.l d0-d2/a0,-(sp) move.w 4*4+4(sp),d0 ;number subq.l #6,sp ;buffer movea.l sp,a0 move.b #'$',(a0)+ moveq.l #4-1,d2 2: rol.w #4,d0 moveq.l #15,d1 and.w d0,d1 move.b 10f(pc,d1.w),(a0)+ dbra d2,2b pea.l 1+4.w ;length pea.l 4(sp) ;buffer jbsr logging_write lea.l 8+6(sp),sp movem.l (sp)+,d0-d2/a0 rts 10: .dc.b '0123456789ABCDEF' ;---------------------------------------------------------------- ;printhex8(number) ; print hexadecimal number $XXXXXXXX ;<4(sp).l:number .text .even printhex8:: movem.l d0-d2/a0,-(sp) move.l 4*4+4(sp),d0 ;number lea.l -10(sp),sp ;buffer movea.l sp,a0 move.b #'$',(a0)+ moveq.l #8-1,d2 2: rol.l #4,d0 moveq.l #15,d1 and.w d0,d1 move.b 10f(pc,d1.w),(a0)+ dbra d2,2b pea.l 1+8.w ;length pea.l 4(sp) ;buffer jbsr logging_write lea.l 8+10(sp),sp movem.l (sp)+,d0-d2/a0 rts 10: .dc.b '0123456789ABCDEF' ;---------------------------------------------------------------- ;printcrlf() ; print CR and LF .text .even printcrlf:: move.l d0,-(sp) pea.l 2.w ;length pea.l 10f(pc) ;buffer jbsr logging_write addq.l #8,sp move.l (sp)+,d0 rts 10: .dc.b 13,10 ;---------------------------------------------------------------- ;printchr(character) ; print character ;<4(sp).b:character .text .even printchr:: move.l d0,-(sp) pea.l 1.w ;length pea.l 4+4+4(sp) ;character jbsr logging_write addq.l #8,sp move.l (sp)+,d0 rts ;---------------------------------------------------------------- ;printstr(string) ; print string ;<4(sp).l:string .text .even printstr:: movem.l d0/a0-a1,-(sp) movea.l 4*3+4(sp),a0 ;string movea.l a0,a1 @@: tst.b (a1)+ bne @b subq.l #1,a1 suba.l a0,a1 ;length movem.l a0-a1,-(sp) ;length, string jbsr logging_write addq.l #8,sp movem.l (sp)+,d0/a0-a1 rts ;-------------------------------------------------------------------------------- ; 計算サブルーチン ;-------------------------------------------------------------------------------- ;---------------------------------------------------------------- ;mull ; unsigned multiplication. long*long ;<d0.l:multiplicand ;<d1.l:multiplier ;>d0:d1.q:product .text .even mull:: cmp.l #$0000FFFF,d0 bhi 10f cmp.l #$0000FFFF,d1 bhi 10f mulu.w d0,d1 moveq.l #0,d0 rts 10: movem.l d2-d4,-(sp) ; d0 d1 d2 d3 d4 ; A B C D . . . . . . move.l d1,d2 ; C D move.l d1,d3 ; C D swap.w d2 ; D C move.l d2,d4 ; D C mulu.w d0,d1 ; B*D mulu.w d0,d4 ; B*C swap.w d0 ; B A mulu.w d0,d3 ; A*D mulu.w d2,d0 ; A*C ; ACh ACl BDh BDl move.w d1,d2 ; --- BDl move.w d0,d1 ; --- ACl swap.w d1 ; ACl BDh swap.w d0 ; --- ACh add.l d3,d1 ; +AD clr.w d3 addx.w d3,d0 add.l d4,d1 ; +BC addx.w d3,d0 swap.w d0 ; ACh --- swap.w d1 ; BDh ACl move.w d1,d0 ; ACl --- move.w d2,d1 ; BDl movem.l (sp)+,d2-d4 rts ;---------------------------------------------------------------- ;divq ; unsigned division. quad/quad ;<d0:d1.q:dividend ;<d2:d3.q:divisor ;>d0:d1.q:quotient ;>d2:d3.q:remainder ;>x:0 ;>n:1=quotient is negative ;>z:1=quotient is zero ;>v:0 ;>c:1=divide by zero. d0:d1 and d2:d3 are not changed. z=0,n=0 .text .even divq:: tst.l d2 bne 20f ;$FFFFFFFF<divisor ;divisor<=$FFFFFFFF tst.l d3 beq 40f ;divisor==0 tst.l d0 bne 50f ;$FFFFFFFF<dividend && divisor<=$FFFFFFFF ;dividend<=$FFFFFFFF && divisor<=$FFFFFFFF cmp.l d3,d1 bls 60f ;dividend<=divisor ;divisor<dividend 10: movem.l d5-d6,-(sp) move.l d3,d5 moveq.l #0,d3 moveq.l #31,d6 1: add.l d1,d1 addx.l d3,d3 cmp.l d5,d3 blo 2f addq.b #1,d1 sub.l d5,d3 2: dbra d6,1b subq.w #1,d6 ;$0000FFFF->$0000FFFE. x=0 or.l d0,d6 ;n=*,z=0,v=0,c=0 movem.l (sp)+,d5-d6 rts ;$FFFFFFFF<divisor 20: cmp.l d2,d0 bhi 30f ;divisor<dividend blo 70f ;dividend<divisor cmp.l d3,d1 bls 60f ;dividend<=divisor ;divisor<dividend 30: movem.l d4-d6,-(sp) move.l d2,d4 move.l d3,d5 moveq.l #0,d2 move.l d0,d3 move.l d1,d0 moveq.l #0,d1 moveq.l #31,d6 1: add.l d1,d1 addx.l d0,d0 addx.l d3,d3 addx.l d2,d2 .if 1 cmp.l d4,d2 blo 3f bhi 2f cmp.l d5,d3 blo 3f 2: sub.l d5,d3 subx.l d4,d2 addq.b #1,d1 3: .else addq.b #1,d1 sub.l d5,d3 subx.l d4,d2 bhs 2f subq.b #1,d1 add.l d5,d3 addx.l d4,d2 2: .endif dbra d6,1b subq.w #1,d6 ;$0000FFFF->$0000FFFE. x=0 or.l d0,d6 ;n=*,z=0,v=0,c=0 movem.l (sp)+,d4-d6 rts ;divisor==0 40: move.w #%00001,ccr ;x=0,n=0,z=0,v=0,c=1 rts ;$FFFFFFFF<dividend && divisor<=$FFFFFFFF 50: movem.l d5-d6,-(sp) move.l d3,d5 moveq.l #0,d3 moveq.l #63,d6 1: add.l d1,d1 addx.l d0,d0 addx.l d3,d3 cmp.l d5,d3 blo 2f addq.b #1,d1 sub.l d5,d3 2: dbra d6,1b subq.w #1,d6 ;$0000FFFF->$0000FFFE. x=0 or.l d0,d6 ;n=*,z=0,v=0,c=0 movem.l (sp)+,d5-d6 rts ;dividend<=divisor 60: beq 80f ;dividend==divisor ;dividend<divisor 70: move.l d0,d2 ;remainder=dividend move.l d1,d3 sub.l d0,d0 ;quotient=0. x=0 moveq.l #0,d1 ;n=0,z=1,v=0,c=0 rts ;dividend==divisor 80: moveq.l #0,d2 ;remainder=0 moveq.l #0,d3 sub.l d0,d0 ;quotient=1. x=0 moveq.l #1,d1 ;n=0,z=0,v=0,c=0 rts .if 0 movem.l d4-d6,-(sp) move.l d2,d4 move.l d3,d5 moveq.l #0,d2 moveq.l #0,d3 moveq.l #63,d6 1: add.l d1,d1 addx.l d0,d0 addx.l d3,d3 addx.l d2,d2 addq.b #1,d1 sub.l d5,d3 subx.l d4,d2 bcc 2f subq.b #1,d1 add.l d5,d3 addx.l d4,d2 2: dbra d6,1b movem.l (sp)+,d4-d6 rts .endif "); \\圧縮された間接データを展開するサブルーチンを出力する asm(ASM_DECOMPRESS); \\間接データの構築を開始する indirect_start(); \\テストルーチンを出力する if(all||mapisdefined(mnemmap,"fabs"),make_fabs()); if(all||mapisdefined(mnemmap,"facos"),make_facos()); if(all||mapisdefined(mnemmap,"fadd"),make_fadd()); if(all||mapisdefined(mnemmap,"fasin"),make_fasin()); if(all||mapisdefined(mnemmap,"fatan"),make_fatan()); if(all||mapisdefined(mnemmap,"fatanh"),make_fatanh()); if(all||mapisdefined(mnemmap,"fbccl"), make_fbccl060(); make_fbccl88x()); if(all||mapisdefined(mnemmap,"fbccw"), make_fbccw060(); make_fbccw88x()); if(all||mapisdefined(mnemmap,"fcmp"),make_fcmp()); if(all||mapisdefined(mnemmap,"fcos"),make_fcos()); if(all||mapisdefined(mnemmap,"fcosh"),make_fcosh()); if(all||mapisdefined(mnemmap,"fdabs"),make_fdabs()); if(all||mapisdefined(mnemmap,"fdadd"),make_fdadd()); if(all||mapisdefined(mnemmap,"fdbcc"), make_fdbcc060(); make_fdbcc88x()); if(all||mapisdefined(mnemmap,"fddiv"),make_fddiv()); if(all||mapisdefined(mnemmap,"fdiv"),make_fdiv()); if(all||mapisdefined(mnemmap,"fdmove"),make_fdmove()); if(all||mapisdefined(mnemmap,"fdmul"),make_fdmul()); if(all||mapisdefined(mnemmap,"fdneg"),make_fdneg()); if(all||mapisdefined(mnemmap,"fdsqrt"),make_fdsqrt()); if(all||mapisdefined(mnemmap,"fdsub"),make_fdsub()); if(all||mapisdefined(mnemmap,"fetox"),make_fetox()); if(all||mapisdefined(mnemmap,"fetoxm1"),make_fetoxm1()); if(all||mapisdefined(mnemmap,"fgetexp"),make_fgetexp()); if(all||mapisdefined(mnemmap,"fgetman"),make_fgetman()); if(all||mapisdefined(mnemmap,"fint"),make_fint()); if(all||mapisdefined(mnemmap,"fintrz"),make_fintrz()); if(all||mapisdefined(mnemmap,"flog10"),make_flog10()); if(all||mapisdefined(mnemmap,"flog2"),make_flog2()); if(all||mapisdefined(mnemmap,"flogn"),make_flogn()); if(all||mapisdefined(mnemmap,"flognp1"),make_flognp1()); if(all||mapisdefined(mnemmap,"fmod"),make_fmod()); if(all||mapisdefined(mnemmap,"fmoveb"), make_fmovebregto(); make_fmovebtoreg()); if(all||mapisdefined(mnemmap,"fmoved"), make_fmovedregto(); make_fmovedtoreg()); if(all||mapisdefined(mnemmap,"fmovel"), make_fmovelregto(); make_fmoveltoreg()); if(all||mapisdefined(mnemmap,"fmovep"), make_fmovepregto(); make_fmoveptoreg()); if(all||mapisdefined(mnemmap,"fmoves"), make_fmovesregto(); make_fmovestoreg()); if(all||mapisdefined(mnemmap,"fmovew"), make_fmovewregto(); make_fmovewtoreg()); if(all||mapisdefined(mnemmap,"fmovex"), make_fmovexregto(); make_fmovextoreg()); if(all||mapisdefined(mnemmap,"fmovecr"), make_fmovecr881(); make_fmovecr882()); \\if(all||mapisdefined(mnemmap,"fmoveml"), \\ make_fmovemlregto(); \\ make_fmovemltoreg()); \\if(all||mapisdefined(mnemmap,"fmovemx"), \\ make_fmovemxregto(); \\ make_fmovemxtoreg()); if(all||mapisdefined(mnemmap,"fmul"),make_fmul()); if(all||mapisdefined(mnemmap,"fneg"),make_fneg()); if(all||mapisdefined(mnemmap,"frem"),make_frem()); \\if(all||mapisdefined(mnemmap,"frestore"),make_frestore()); if(all||mapisdefined(mnemmap,"fsabs"),make_fsabs()); if(all||mapisdefined(mnemmap,"fsadd"),make_fsadd()); \\if(all||mapisdefined(mnemmap,"fsave"),make_fsave()); if(all||mapisdefined(mnemmap,"fscale"),make_fscale()); if(all||mapisdefined(mnemmap,"fscc"), make_fscc060(); make_fscc88x()); if(all||mapisdefined(mnemmap,"fsdiv"),make_fsdiv()); if(all||mapisdefined(mnemmap,"fsgldiv"), make_fsgldiv060(); make_fsgldiv88x()); if(all||mapisdefined(mnemmap,"fsglmul"), make_fsglmul060(); make_fsglmul88x()); if(all||mapisdefined(mnemmap,"fsin"),make_fsin()); if(all||mapisdefined(mnemmap,"fsincos"),make_fsincos()); if(all||mapisdefined(mnemmap,"fsinh"),make_fsinh()); if(all||mapisdefined(mnemmap,"fsmove"),make_fsmove()); if(all||mapisdefined(mnemmap,"fsmul"),make_fsmul()); if(all||mapisdefined(mnemmap,"fsneg"),make_fsneg()); if(all||mapisdefined(mnemmap,"fsqrt"),make_fsqrt()); if(all||mapisdefined(mnemmap,"fssqrt"),make_fssqrt()); if(all||mapisdefined(mnemmap,"fssub"),make_fssub()); if(all||mapisdefined(mnemmap,"fsub"),make_fsub()); if(all||mapisdefined(mnemmap,"ftan"),make_ftan()); if(all||mapisdefined(mnemmap,"ftanh"),make_ftanh()); if(all||mapisdefined(mnemmap,"ftentox"),make_ftentox()); if(all||mapisdefined(mnemmap,"ftrapcc"), make_ftrapcc060(); make_ftrapcc88x()); if(all||mapisdefined(mnemmap,"ftrapccl"), make_ftrapccl060(); make_ftrapccl88x()); if(all||mapisdefined(mnemmap,"ftrapccw"), make_ftrapccw060(); make_ftrapccw88x()); if(all||mapisdefined(mnemmap,"ftst"),make_ftst()); if(all||mapisdefined(mnemmap,"ftwotox"),make_ftwotox()); \\条件の文字列を出力する asm( " .text .align 4 uppercase_cc:: .irp cc,F,EQ,OGT,OGE,OLT,OLE,OGL,OR,UN,UEQ,UGT,UGE,ULT,ULE,NE,T,SF,SEQ,GT,GE,LT,LE,GL,GLE,NGLE,NGL,NLE,NLT,NGE,NGT,SNE,ST .dc.l uppercase_cc_&cc .endm .irp cc,F,EQ,OGT,OGE,OLT,OLE,OGL,OR,UN,UEQ,UGT,UGE,ULT,ULE,NE,T,SF,SEQ,GT,GE,LT,LE,GL,GLE,NGLE,NGL,NLE,NLT,NGE,NGT,SNE,ST uppercase_cc_&cc:: .dc.b '&cc',0 .endm "); \\間接データの構築を終了する indirect_end(); asm( " .bss .align 4 push_decompressed:: .ds.b ",push_max_length," ;-------------------------------------------------------------------------------- ; end ;-------------------------------------------------------------------------------- .end main "); asm_close() } \\---------------------------------------------------------------------------------------- \\ 共通データ \\---------------------------------------------------------------------------------------- \\ 表現できる値に丸められ、重複する値は取り除かれる DATA_SPECIAL=[Rei, Inf]; DATA_EXTENDED={[ EXDDEMIN, exdnextup(EXDDEMIN), exdnextdown(EXDNOMIN/2), EXDNOMIN/2, exdnextup(EXDNOMIN/2), exdnextdown(EXDDEMAX), EXDDEMAX, EXDNOMIN, exdnextup(EXDNOMIN), exdnextdown(EXDNOMIN*2), EXDNOMIN*2, exdnextup(EXDNOMIN*2), exdnextdown(EXDNOMAX/2), EXDNOMAX/2, exdnextup(EXDNOMAX/2), exdnextdown(EXDNOMAX), EXDNOMAX, \\ exdnextdown(DBLDEMIN), DBLDEMIN, DBLDEMAX, exdnextup(DBLDEMAX), exdnextdown(DBLNOMIN), DBLNOMIN, DBLNOMAX, exdnextup(DBLNOMAX), \\ exdnextdown(SGLDEMIN), SGLDEMIN, SGLDEMAX, exdnextup(SGLDEMAX), exdnextdown(SGLNOMIN), SGLNOMIN, SGLNOMAX, exdnextup(SGLNOMAX) ]}; DATA_DOUBLE={[ DBLDEMIN, dblnextup(DBLDEMIN), dblnextdown(DBLNOMIN/2), DBLNOMIN/2, dblnextup(DBLNOMIN/2), dblnextdown(DBLDEMAX), DBLDEMAX, DBLNOMIN, dblnextup(DBLNOMIN), dblnextdown(DBLNOMIN*2), DBLNOMIN*2, dblnextup(DBLNOMIN*2), dblnextdown(DBLNOMAX/2), DBLNOMAX/2, dblnextup(DBLNOMAX/2), dblnextdown(DBLNOMAX), DBLNOMAX, \\ dblnextdown(SGLDEMIN), SGLDEMIN, SGLDEMAX, dblnextup(SGLDEMAX), dblnextdown(SGLNOMIN), SGLNOMIN, SGLNOMAX, dblnextup(SGLNOMAX) ]}; DATA_SINGLE={[ SGLDEMIN, sglnextup(SGLDEMIN), sglnextdown(SGLNOMIN/2), SGLNOMIN/2, sglnextup(SGLNOMIN/2), sglnextdown(SGLDEMAX), SGLDEMAX, SGLNOMIN, sglnextup(SGLNOMIN), sglnextdown(SGLNOMIN*2), SGLNOMIN*2, sglnextup(SGLNOMIN*2), sglnextdown(SGLNOMAX/2), SGLNOMAX/2, sglnextup(SGLNOMAX/2), sglnextdown(SGLNOMAX), SGLNOMAX ]}; DATA_FLOAT={append( DATA_EXTENDED, DATA_DOUBLE, DATA_SINGLE )}; DATA_BYTE=vector(256,n,n-1); DATA_WORD={ vector(256,n, (bitand(n-1,0x80)<<(15-7))*0x01+ \\a 11111100_00000000 (bitand(n-1,0x40)<<(14-6))*0x01+ \\b 54321098_76543210 (bitand(n-1,0x20)<<( 9-5))*0x1F+ \\c abcccccd_efffffgh (bitand(n-1,0x10)<<( 8-4))*0x01+ \\d abcdefgh (bitand(n-1,0x08)<<( 7-3))*0x01+ \\e (bitand(n-1,0x04)<<( 2-2))*0x1F+ \\f (bitand(n-1,0x02)<<( 1-1))*0x01+ \\g (bitand(n-1,0x01)<<( 0-0))*0x01) \\h }; DATA_LONG={ vector(256,n, (bitand(n-1,0x80)<<(31-7))*0x01+ \\a 33222222_22221111_11111100_00000000 (bitand(n-1,0x40)<<(30-6))*0x01+ \\b 10987654_32109876_54321098_76543210 (bitand(n-1,0x20)<<(24-5))*0x3F+ \\c abcccccc_dddddddd_eeeeeeee_ffffffgh (bitand(n-1,0x10)<<(16-4))*0xFF+ \\d abcdefgh (bitand(n-1,0x08)<<( 8-3))*0xFF+ \\e (bitand(n-1,0x04)<<( 2-2))*0x3F+ \\f (bitand(n-1,0x02)<<( 1-1))*0x01+ \\g (bitand(n-1,0x01)<<( 0-0))*0x01) \\h }; DATA_PACKED={[ 2^56*10^27, \\extendedとpackedの両方で正確に表現できる最大の整数 exdnextdown(1), 1, exdnextup(1), exdnextdown(9), 9, exdnextup(9), exdnextdown(10), 10, exdnextup(10), exdnextdown(90), 90, exdnextup(90), exdnextdown(10^9), 10^9, exdnextup(10^9), exdnextdown(9*10^9), 9*10^9, exdnextup(9*10^9), exdnextdown(10^10), 10^10, exdnextup(10^10), exdnextdown(9*10^10), 9*10^10, exdnextup(9*10^10), exdnextdown(1e+90), exdnextup(1e+90), exdnextdown(9e+90), exdnextup(9e+90), exdnextdown(1e+100), exdnextup(1e+100), exdnextdown(9e+100), exdnextup(9e+100), exdnextdown(1e+900), exdnextup(1e+900), exdnextdown(9e+900), exdnextup(9e+900), exdnextdown(1e+1000), exdnextup(1e+1000), exdnextdown(1e+4932), exdnextup(1e+4932), exdnextdown(0.1), exdnextup(0.1), exdnextdown(0.9), exdnextup(0.9), exdnextdown(1e-9), exdnextup(1e-9), exdnextdown(9e-9), exdnextup(9e-9), exdnextdown(1e-10), exdnextup(1e-10), exdnextdown(9e-10), exdnextup(9e-10), exdnextdown(1e-90), exdnextup(1e-90), exdnextdown(9e-90), exdnextup(9e-90), exdnextdown(1e-100), exdnextup(1e-100), exdnextdown(9e-100), exdnextup(9e-100), exdnextdown(1e-900), exdnextup(1e-900), exdnextdown(9e-900), exdnextup(9e-900), exdnextdown(1e-1000), exdnextup(1e-1000), exdnextdown(1e-4932), exdnextup(1e-4932), exdnextdown(0.0999999999999999995), exdnextup(0.0999999999999999995), exdnextdown(0.9999999999999995), exdnextup(0.9999999999999995), exdnextdown(9.9999999999995), exdnextup(9.9999999999995), exdnextdown(99.9999999995), exdnextup(99.9999999995), exdnextdown(999.9999995), exdnextup(999.9999995), exdnextdown(9999.9995), exdnextup(9999.9995), exdnextdown(999995/10), 999995/10, exdnextup(999995/10), exdnextdown(999500), 999500, exdnextup(999500), exdnextdown(9.9999999995e+99), exdnextup(9.9999999995e+99), exdnextdown(9.9999999995e-99), exdnextup(9.9999999995e-99), exdnextdown(9.999999999995e-999), exdnextup(9.999999999995e-999), exdnextdown(9.999999999995e+999), exdnextup(9.999999999995e+999) ]}; DATA_BASIC={append( vector(120,n,exdnextdown(n/12)),vector(120,n,n/12),vector(120,n,exdnextup(n/12)), \\0..10付近 vector(129,n,2^(n-65)), \\2^-64..2^64 vector(30,n,exdnextdown(10^(n^(5/2)))),vector(30,n,10^(n^(5/2))),vector(30,n,exdnextup(10^(n^(5/2)))) \\大域 )}; DATA_ZERO_PLUS=vector(30,n,10^-(n^(5/2))); \\ε DATA_ONE_MINUS=vector(19,n,1-(5/2)^(-5/2*n)); \\1-ε DATA_ONE_PLUS=vector(19,n,1+(5/2)^(-5/2*n)); \\1+ε DATA_TRIGONOMETRIC={append( vector(19,n,Pi/2-(5/2)^(-5/2*n)), \\π/2-ε vector(19,n,Pi/2+(5/2)^(-5/2*n)), \\π/2+ε vector(19,n,Pi-(5/2)^(-5/2*n)), \\π-ε vector(19,n,Pi+(5/2)^(-5/2*n)), \\π+ε vector(19,n,3/2*Pi-(5/2)^(-5/2*n)), \\3/2*π-ε vector(19,n,3/2*Pi+(5/2)^(-5/2*n)), \\3/2*π+ε vector(19,n,2*Pi-(5/2)^(-5/2*n)), \\2*π-ε vector(19,n,2*Pi+(5/2)^(-5/2*n)) \\2*π+ε )}; DATA_ROUND={append( vector(9,n,exdnextdown(2^7+(n-5)/4)),vector(9,n,2^7+(n-5)/4),vector(9,n,exdnextup(2^7+(n-5)/4)), \\2^7付近 vector(9,n,exdnextdown(2^8+(n-5)/4)),vector(9,n,2^8+(n-5)/4),vector(9,n,exdnextup(2^8+(n-5)/4)), \\2^8付近 vector(9,n,exdnextdown(2^15+(n-5)/4)),vector(9,n,2^15+(n-5)/4),vector(9,n,exdnextup(2^15+(n-5)/4)), \\2^15付近 vector(9,n,exdnextdown(2^16+(n-5)/4)),vector(9,n,2^16+(n-5)/4),vector(9,n,exdnextup(2^16+(n-5)/4)), \\2^16付近 vector(9,n,exdnextdown(2^23+(n-5)/4)),vector(9,n,2^23+(n-5)/4),vector(9,n,exdnextup(2^23+(n-5)/4)), \\2^23付近 vector(9,n,exdnextdown(2^24+(n-5)/4)),vector(9,n,2^24+(n-5)/4),vector(9,n,exdnextup(2^24+(n-5)/4)), \\2^24付近 vector(9,n,exdnextdown(2^31+(n-5)/4)),vector(9,n,2^31+(n-5)/4),vector(9,n,exdnextup(2^31+(n-5)/4)), \\2^31付近 vector(9,n,exdnextdown(2^32+(n-5)/4)),vector(9,n,2^32+(n-5)/4),vector(9,n,exdnextup(2^32+(n-5)/4)), \\2^32付近 vector(9,n,exdnextdown(2^52+(n-5)/4)),vector(9,n,2^52+(n-5)/4),vector(9,n,exdnextup(2^52+(n-5)/4)), \\2^52付近 vector(9,n,exdnextdown(2^53+(n-5)/4)),vector(9,n,2^53+(n-5)/4),vector(9,n,exdnextup(2^53+(n-5)/4)), \\2^53付近 vector(9,n,exdnextdown(2^63+(n-5)/4)),vector(9,n,2^63+(n-5)/4),vector(9,n,exdnextup(2^63+(n-5)/4)), \\2^63付近 vector(9,n,exdnextdown(2^64+(n-5)/4)),vector(9,n,2^64+(n-5)/4),vector(9,n,exdnextup(2^64+(n-5)/4)) \\2^64付近 )}; DATA_BINARY={append( vector(12,n,exdnextdown(n/6)), vector(12,n,n/6), vector(12,n,exdnextup(n/6)), \\0..2付近 vector(3,n,2^23-2+n), \\2^23付近 vector(3,n,2^24-2+n), \\2^24付近 vector(3,n,2^31-2+n), \\2^31付近 vector(3,n,2^32-2+n), \\2^32付近 vector(3,n,2^52-2+n), \\2^52付近 vector(3,n,2^53-2+n), \\2^53付近 vector(3,n,2^63-2+n), \\2^63付近 vector(3,n,2^64-2+n) \\2^64付近 )}; \\---------------------------------------------------------------------------------------- \\ 原点を傾き1で通る関数で原点付近の入力と出力の大小関係に矛盾が生じていたら修正する \\---------------------------------------------------------------------------------------- originLowerLower(y,x,rp,rm)={ if((type(y)!="t_POL")&&(type(x)!="t_POL")&&(abs(x)<2^-16), if(x<0, if((rp!=SGL)&&(rp!=DBL)&&(x<y),y=x); if((rm==RM)&&(x<=y),y=nextdown(x,rp)), if((rp!=SGL)&&(rp!=DBL)&&(x<y),y=x); if(((rm==RZ)||(rm==RM))&&(x<=y),y=nextdown(x,rp)))); y } originLowerUpper(y,x,rp,rm)={ if((type(y)!="t_POL")&&(type(x)!="t_POL")&&(abs(x)<2^-16), if(x<0, if((rp!=SGL)&&(rp!=DBL)&&(x<y),y=x); if((rm==RM)&&(x<=y),y=nextdown(x,rp)), if((rp!=SGL)&&(rp!=DBL)&&(y<x),y=x); if((rm==RP)&&(y<=x),y=nextup(x,rp)))); y } originUpperLower(y,x,rp,rm)={ if((type(y)!="t_POL")&&(type(x)!="t_POL")&&(abs(x)<2^-16), if(x<0, if((rp!=SGL)&&(rp!=DBL)&&(y<x),y=x); if(((rm==RZ)||(rm==RP))&&(y<=x),y=nextup(x,rp)), if((rp!=SGL)&&(rp!=DBL)&&(x<y),y=x); if(((rm==RZ)||(rm==RM))&&(x<=y),y=nextdown(x,rp)))); y } originUpperUpper(y,x,rp,rm)={ if((type(y)!="t_POL")&&(type(x)!="t_POL")&&(abs(x)<2^-16), if(x<0, if((rp!=SGL)&&(rp!=DBL)&&(y<x),y=x); if(((rm==RZ)||(rm==RP))&&(y<=x),y=nextup(x,rp)), if((rp!=SGL)&&(rp!=DBL)&&(y<x),y=x); if((rm==RP)&&(y<=x),y=nextup(x,rp)))); y } \\ 非正規化数のときUFをセット、正規化数のときUFをクリアする correctUnderflow(y,rp)={ if(type(y)!="t_POL", if(abs(y)<if(rp==SGL,SGLNOMIN, rp==DBL,DBLNOMIN, EXDNOMIN), \\非正規化数のとき fpsr=bitor(fpsr,UF), \\UFをセット \\正規化数のとき fpsr=bitand(fpsr,bitneg(UF)))); \\UFをクリア y } fputocpu(fpu)={ if(bitand(fpu,MC68881+MC68882),"68030", bitand(fpu,MC68040+FPSP040),"68040", bitand(fpu,MC68060+FPSP060),"68060", error()) } \\---------------------------------------------------------------------------------------- \\ Fop.X FPn \\---------------------------------------------------------------------------------------- make_fop1to0(name,fop,frp,fpu,a,func)={ my(FOP,cpu,x,rp,rm,sr); FOP=strupr(fop); print("making ",name); cpu=fputocpu(fpu); a=vector(#a,n,exd(a[n],RN)); a=uniq(sort(append(a,vector(#a,n,-a[n]),[NaN]),comparator),comparator); asm( " ;-------------------------------------------------------------------------------- ; ",FOP,".X FPn ;-------------------------------------------------------------------------------- .cpu ",cpu," regs reg d0-d7/a0-a5 cregs reg fpcr/fpsr/fpiar fregs reg fp0-fp7 .offsym 0,_a6 _size: _regs: .ds.b .sizeof.(regs) _fregs: .ds.b .sizeof.(fregs) _cregs: .ds.b .sizeof.(cregs) _a6: .ds.l 1 _pc: .ds.l 1 .text .even ",name,"_test:: link.w a6,#_size movem.l regs,(_regs,a6) fmovem.l cregs,(_cregs,a6) fmovem.x fregs,(_fregs,a6) ; move.l #",fpu,",-(sp) peamsg '",FOP,".X FPN' jbsr mnemonic_start addq.l #8,sp beq 99f putmsg 'test: ",FOP,".X FPn',13,10 ;------------------------------------------------ ; d1 fpcr=(XRN..DRP)<<4 ; d3 0=failed,1=successful ; d5 expected status ; d7 actual status ; a2 source handle,... ; a4 expected status,... ; fp2 source ;------------------------------------------------ lea.l push_decompressed,a0 ;decompress data move.l a0,-(sp) pea.l ",name,"_data_compressed jbsr decompress addq.l #8,sp ;relocate decompressed handle move.l #indirect_decompressed,d0 movea.l a0,a2 ;source handle,... @@: add.l d0,(a0)+ ;source handle tst.l (a0) bpl @b addq.l #4,a0 ;-1 movea.l a0,a4 ;expected status,... ; 22: move.l #",XRN<<4,",d1 ;fpcr=(XRN..DRP)<<4 11: ;FPn fmove.l #0,fpcr fmove.x ([a2]),fp2 ;source fmove.l d1,fpcr ;fpcr fmove.l #0,fpsr ;source ",fop,".x fp2 ;EXECUTE ;actual result fmove.l fpsr,d7 ;actual status fmove.l #0,fpcr ; move.l (a4),d5 ;expected status ; move.l ",if(frp==-2,"d1",frp==-1,"#-1",Str("#",frp<<6)),",-(sp) ;fpcr(rp<<6,-1=strict) move.l d5,-(sp) ;expected status move.l d7,-(sp) ;actual status jbsr test_status lea.l (12,sp),sp move.l d0,d3 ;0=failed,1=successful ; move.l d3,-(sp) ;0=failed,1=successful jbsr statistics_update addq.l #4,sp beq @f ;not output ;output putmsg '",FOP,".X FPn=' puthex24 ([a2]),(4,[a2]),(8,[a2]) ;source putmsg ' @' move.l d1,-(sp) jbsr printfpcrrprm addq.l #4,sp putcrlf move.l d3,-(sp) ;0=failed,1=successful move.l d5,-(sp) ;expected status move.l d7,-(sp) ;actual status jbsr output_status lea.l (12,sp),sp @@: ; addq.l #4,a4 ;expected status,... ; add.w #1<<4,d1 ;rprm++ cmp.w #",DRP<<4,",d1 ;fpcr=(XRN..DRP)<<4 bls 11b ; addq.l #4,a2 ;source handle,... tst.l (a2) ;source handle,... bpl 22b ; jbsr mnemonic_end 99: fmovem.x (_fregs,a6),fregs fmovem.l (_cregs,a6),cregs movem.l (_regs,a6),regs unlk a6 rts .cpu 68000 .align 4 ",name,"_data_compressed:: "); push_start(); for(i=1,#a, x=a[i]; \\ソース push_indirect(12,numtoexd(x,RN))); push(4,-1); for(i=1,#a, x=a[i]; \\ソース for(rprm=XRN,DRP, \\(rp<<2)+rm。丸め桁数と丸めモード rp=bitand(rprm>>2,3); \\丸め桁数 rm=bitand(rprm,3); \\丸めモード fpsr=0; func(x,rp,rm); fpsr_update_aer(); sr=fpsr; push(4,sr))); push_end() } \\---------------------------------------------------------------------------------------- \\ Fop.X FPm,FPn \\---------------------------------------------------------------------------------------- make_fop1to1(name,fop,frp,fpu,a,func)={ my(FOP,cpu,x,y,rp,rm,sr); FOP=strupr(fop); print("making ",name); cpu=fputocpu(fpu); a=vector(#a,n,exd(a[n],RN)); a=uniq(sort(append(a,vector(#a,n,-a[n]),[NaN]),comparator),comparator); asm( " ;-------------------------------------------------------------------------------- ; ",FOP,".X FPm,FPn ;-------------------------------------------------------------------------------- .cpu ",cpu," regs reg d0-d7/a0-a5 cregs reg fpcr/fpsr/fpiar fregs reg fp0-fp7 .offsym 0,_a6 _size: _regs: .ds.b .sizeof.(regs) _fregs: .ds.b .sizeof.(fregs) _cregs: .ds.b .sizeof.(cregs) _a6: .ds.l 1 _pc: .ds.l 1 .text .even ",name,"_test:: link.w a6,#_size movem.l regs,(_regs,a6) fmovem.l cregs,(_cregs,a6) fmovem.x fregs,(_fregs,a6) ; move.l #",fpu,",-(sp) peamsg '",FOP,".X FPM,FPN' jbsr mnemonic_start addq.l #8,sp beq 99f putmsg 'test: ",FOP,".X FPm,FPn',13,10 ;------------------------------------------------ ; d1 fpcr=(XRN..DRP)<<4 ; d3 0=failed,1=successful ; d5 expected status ; d7 actual status ; a2 source handle,... ; a4 expected result handle,expected status,... ; fp2 source ; fp5 expected result ; fp7 actual result ;------------------------------------------------ lea.l push_decompressed,a0 ;decompress data move.l a0,-(sp) pea.l ",name,"_data_compressed jbsr decompress addq.l #8,sp ;relocate decompressed handle move.l #indirect_decompressed,d0 @@: add.l d0,(a0)+ ;source handle tst.l (a0) bpl @b addq.l #4,a0 ;-1 @@: add.l d0,(a0)+ ;expected result handle addq.l #4,a0 ;expected status tst.l (a0) bpl @b ; addq.l #4,a0 ;-1 ; lea.l push_decompressed,a2 ;source handle,... lea.l (4*",#a,"+4,a2),a4 ;expected result handle,expected status,... 22: move.l #",XRN<<4,",d1 ;fpcr=(XRN..DRP)<<4 11: ;FPn,FPn fmove.l #0,fpcr fmove.x ([a2]),fp2 ;source fmove.x fp2,fp7 ;source fmove.l d1,fpcr ;fpcr fmove.l #0,fpsr ;source ",fop,".x fp7,fp7 ;EXECUTE ;actual result fmove.l fpsr,d7 ;actual status fmove.l #0,fpcr ; fmove.x ([a4]),fp5 ;expected result move.l (4,a4),d5 ;expected status ; move.l ",if(frp==-2,"d1",frp==-1,"#-1",Str("#",frp<<6)),",-(sp) ;fpcr(rp<<6,-1=strict) move.l d5,-(sp) ;expected status fmove.x fp5,-(sp) ;expected result move.l d7,-(sp) ;actual status fmove.x fp7,-(sp) ;actual result jbsr test_extended lea.l 36(sp),sp move.l d0,d3 ;0=failed,1=successful ; move.l d3,-(sp) ;0=failed,1=successful jbsr statistics_update addq.l #4,sp beq @f ;not output ;output putmsg '",FOP,".X FPn=' puthex24 ([a2]),(4,[a2]),(8,[a2]) ;source putmsg ',FPn @' move.l d1,-(sp) jbsr printfpcrrprm addq.l #4,sp putcrlf move.l d3,-(sp) ;0=failed,1=successful move.l d5,-(sp) ;expected status fmove.x fp5,-(sp) ;expected result move.l d7,-(sp) ;actual status fmove.x fp7,-(sp) ;actual result jbsr output_extended lea.l 36(sp),sp @@: ; addq.l #8,a4 ;expected result handle,expected status,... ; add.w #1<<4,d1 ;rprm++ cmp.w #",DRP<<4,",d1 ;fpcr=(XRN..DRP)<<4 bls 11b ; addq.l #4,a2 ;source handle,... tst.l (a2) ;source handle,... bpl 22b ; lea.l push_decompressed,a2 ;source handle,... lea.l (4*",#a,"+4,a2),a4 ;expected result handle,expected status,... 22: move.l #",XRN<<4,",d1 ;fpcr=(XRN..DRP)<<4 11: ;FPm,FPn fmove.l #0,fpcr fmove.x ([a2]),fp2 ;source fmove.s #$7FFFFFFF,fp7 ;fill=NaN fmove.l d1,fpcr ;fpcr fmove.l #0,fpsr ;source ",fop,".x fp2,fp7 ;EXECUTE ;actual result fmove.l fpsr,d7 ;actual status fmove.l #0,fpcr ; fmove.x ([a4]),fp5 ;expected result move.l (4,a4),d5 ;expected status ; move.l ",if(frp==-2,"d1",frp==-1,"#-1",Str("#",frp<<6)),",-(sp) ;fpcr(rp<<6,-1=strict) move.l d5,-(sp) ;expected status fmove.x fp5,-(sp) ;expected result move.l d7,-(sp) ;actual status fmove.x fp7,-(sp) ;actual result jbsr test_extended lea.l 36(sp),sp move.l d0,d3 ;0=failed,1=successful ; move.l d3,-(sp) ;0=failed,1=successful jbsr statistics_update addq.l #4,sp beq @f ;not output ;output putmsg '",FOP,".X FPm=' puthex24 ([a2]),(4,[a2]),(8,[a2]) ;source putmsg ',FPn @' move.l d1,-(sp) jbsr printfpcrrprm addq.l #4,sp putcrlf move.l d3,-(sp) ;0=failed,1=successful move.l d5,-(sp) ;expected status fmove.x fp5,-(sp) ;expected result move.l d7,-(sp) ;actual status fmove.x fp7,-(sp) ;actual result jbsr output_extended lea.l 36(sp),sp @@: ; addq.l #8,a4 ;expected result handle,expected status,... ; add.w #1<<4,d1 ;rprm++ cmp.w #",DRP<<4,",d1 ;fpcr=(XRN..DRP)<<4 bls 11b ; addq.l #4,a2 ;source handle,... tst.l (a2) ;source handle,... bpl 22b ; jbsr mnemonic_end 99: fmovem.x (_fregs,a6),fregs fmovem.l (_cregs,a6),cregs movem.l (_regs,a6),regs unlk a6 rts .cpu 68000 .align 4 ",name,"_data_compressed:: "); push_start(); for(i=1,#a, x=a[i]; \\ソース push_indirect(12,numtoexd(x,RN))); push(4,-1); for(i=1,#a, x=a[i]; \\ソース for(rprm=XRN,DRP, \\(rp<<2)+rm。丸め桁数と丸めモード rp=bitand(rprm>>2,3); \\丸め桁数 rm=bitand(rprm,3); \\丸めモード fpsr=0; y=func(x,rp,rm); fpsr_update_ccr(y); fpsr_update_aer(); sr=fpsr; push_indirect(12,numtoexd(y,RN)); push(4,sr))); push(4,-1); push_end() } \\---------------------------------------------------------------------------------------- \\ Fop.X FPm,FPn \\---------------------------------------------------------------------------------------- make_fop2to0(name,fop,frp,fpu,a,func)={ my(FOP,cpu,x,y,rp,rm,sr); FOP=strupr(fop); print("making ",name); cpu=fputocpu(fpu); a=vector(#a,n,exd(a[n],RN)); a=uniq(sort(append(a,vector(#a,n,-a[n]),[NaN]),comparator),comparator); asm( " ;-------------------------------------------------------------------------------- ; ",FOP,".X FPm,FPn ;-------------------------------------------------------------------------------- .cpu ",cpu," regs reg d0-d7/a0-a5 cregs reg fpcr/fpsr/fpiar fregs reg fp0-fp7 .offsym 0,_a6 _size: _regs: .ds.b .sizeof.(regs) _fregs: .ds.b .sizeof.(fregs) _cregs: .ds.b .sizeof.(cregs) _a6: .ds.l 1 _pc: .ds.l 1 .text .even ",name,"_test:: link.w a6,#_size movem.l regs,(_regs,a6) fmovem.l cregs,(_cregs,a6) fmovem.x fregs,(_fregs,a6) ; move.l #",fpu,",-(sp) peamsg '",FOP,".X FPM,FPN' jbsr mnemonic_start addq.l #8,sp beq 99f putmsg 'test: ",FOP,".X FPm,FPn',13,10 ;------------------------------------------------ ; d1 fpcr=(XRN..XRP)<<4 ; d3 0=failed,1=successful ; d5 expected status ; d7 actual status ; a2 source handle,... ; a3 destination handle,... ; a4 expected status,... ; fp2 source ;------------------------------------------------ lea.l push_decompressed,a0 ;decompress data move.l a0,-(sp) pea.l ",name,"_data_compressed jbsr decompress addq.l #8,sp ;relocate decompressed handle move.l #indirect_decompressed,d0 @@: add.l d0,(a0)+ ;destination handle tst.l (a0) bpl @b addq.l #4,a0 ;-1 movea.l a0,a4 ;expected status,... ; lea.l push_decompressed,a3 ;destination handle,... 33: move.l #",XRN<<4,",d1 ;fpcr=(XRN..XRP)<<4 11: ;FPn,FPn fmove.l #0,fpcr fmove.x ([a3]),fp3 ;destination fmove.l d1,fpcr ;fpcr fmove.l #0,fpsr ;source ",fop,".x fp3,fp3 ;EXECUTE ;actual result fmove.l fpsr,d7 ;actual status fmove.l #0,fpcr ; move.l (a4),d5 ;expected status ; move.l ",if(frp==-2,"d1",frp==-1,"#-1",Str("#",frp<<6)),",-(sp) ;fpcr(rp<<6,-1=strict) move.l d5,-(sp) ;expected status move.l d7,-(sp) ;actual status jbsr test_status lea.l (12,sp),sp move.l d0,d3 ;0=failed,1=successful ; move.l d3,-(sp) ;0=failed,1=successful jbsr statistics_update addq.l #4,sp beq @f ;not output ;output putmsg '",FOP,".X FPn=' puthex24 ([a3]),(4,[a3]),(8,[a3]) ;source putmsg ',FPn=' puthex24 ([a3]),(4,[a3]),(8,[a3]) ;destination putmsg ' @' move.l d1,-(sp) jbsr printfpcrrprm addq.l #4,sp putcrlf move.l d3,-(sp) ;0=failed,1=successful move.l d5,-(sp) ;expected status move.l d7,-(sp) ;actual status jbsr output_status lea.l (12,sp),sp @@: ; addq.l #4,a4 ;expected status,... ; add.w #1<<4,d1 ;rprm++ cmp.w #",XRP<<4,",d1 ;fpcr=(XRN..XRP)<<4 bls 11b ; addq.l #4,a3 ;destination handle,... tst.l (a3) ;destination handle,... bpl 33b ; lea.l push_decompressed,a3 ;destination handle,... 33: lea.l push_decompressed,a2 ;source handle,... 22: move.l #",XRN<<4,",d1 ;fpcr=(XRN..XRP)<<4 11: ;FPm,FPn fmove.l #0,fpcr fmove.x ([a2]),fp2 ;source fmove.x ([a3]),fp3 ;destination fmove.l d1,fpcr ;fpcr fmove.l #0,fpsr ;source ",fop,".x fp2,fp3 ;EXECUTE ;actual result fmove.l fpsr,d7 ;actual status fmove.l #0,fpcr ; move.l (a4),d5 ;expected status ; move.l ",if(frp==-2,"d1",frp==-1,"#-1",Str("#",frp<<6)),",-(sp) ;fpcr(rp<<6,-1=strict) move.l d5,-(sp) ;expected status move.l d7,-(sp) ;actual status jbsr test_status lea.l (12,sp),sp move.l d0,d3 ;0=failed,1=successful ; move.l d3,-(sp) ;0=failed,1=successful jbsr statistics_update addq.l #4,sp beq @f ;not output ;output putmsg '",FOP,".X FPm=' puthex24 ([a2]),(4,[a2]),(8,[a2]) ;source putmsg ',FPn=' puthex24 ([a3]),(4,[a3]),(8,[a3]) ;destination putmsg ' @' move.l d1,-(sp) jbsr printfpcrrprm addq.l #4,sp putcrlf move.l d3,-(sp) ;0=failed,1=successful move.l d5,-(sp) ;expected status move.l d7,-(sp) ;actual status jbsr output_status lea.l (12,sp),sp @@: ; addq.l #4,a4 ;expected status,... ; add.w #1<<4,d1 ;rprm++ cmp.w #",XRP<<4,",d1 ;fpcr=(XRN..XRP)<<4 bls 11b ; addq.l #4,a2 ;source handle,... tst.l (a2) ;source handle,... bpl 22b ; addq.l #4,a3 ;destination handle,... tst.l (a3) ;destination handle,... bpl 33b ; jbsr mnemonic_end 99: fmovem.x (_fregs,a6),fregs fmovem.l (_cregs,a6),cregs movem.l (_regs,a6),regs unlk a6 rts .cpu 68000 .align 4 ",name,"_data_compressed:: "); push_start(); for(i=1,#a, x=a[i]; \\ソース,デスティネーション push_indirect(12,numtoexd(x,RN))); push(4,-1); for(i=1,#a, x=a[i]; \\ソース,デスティネーション for(rprm=XRN,XRP, \\(rp<<2)+rm。丸め桁数と丸めモード。extendedのみ rp=bitand(rprm>>2,3); \\丸め桁数 rm=bitand(rprm,3); \\丸めモード fpsr=0; func(x,x,rp,rm); fpsr_update_aer(); sr=fpsr; push(4,sr))); for(i=1,#a, x=a[i]; \\デスティネーション for(j=1,#a, y=a[j]; \\ソース for(rprm=XRN,XRP, \\(rp<<2)+rm。丸め桁数と丸めモード。extendedのみ rp=bitand(rprm>>2,3); \\丸め桁数 rm=bitand(rprm,3); \\丸めモード fpsr=0; func(x,y,rp,rm); fpsr_update_aer(); sr=fpsr; push(4,sr)))); push_end() } \\---------------------------------------------------------------------------------------- \\ Fop.X FPm,FPn \\---------------------------------------------------------------------------------------- make_fop2to1(name,fop,frp,fpu,a,func)={ my(FOP,cpu,x,y,z,rp,rm,sr); FOP=strupr(fop); print("making ",name); cpu=fputocpu(fpu); a=vector(#a,n,exd(a[n],RN)); a=uniq(sort(append(a,vector(#a,n,-a[n]),[NaN]),comparator),comparator); asm( " ;-------------------------------------------------------------------------------- ; ",FOP,".X FPm,FPn ;-------------------------------------------------------------------------------- .cpu ",cpu," regs reg d0-d7/a0-a5 cregs reg fpcr/fpsr/fpiar fregs reg fp0-fp7 .offsym 0,_a6 _size: _regs: .ds.b .sizeof.(regs) _fregs: .ds.b .sizeof.(fregs) _cregs: .ds.b .sizeof.(cregs) _a6: .ds.l 1 _pc: .ds.l 1 .text .even ",name,"_test:: link.w a6,#_size movem.l regs,(_regs,a6) fmovem.l cregs,(_cregs,a6) fmovem.x fregs,(_fregs,a6) ; move.l #",fpu,",-(sp) peamsg '",FOP,".X FPM,FPN' jbsr mnemonic_start addq.l #8,sp beq 99f putmsg 'test: ",FOP,".X FPm,FPn',13,10 ;------------------------------------------------ ; d1 fpcr=(XRN..XRP)<<4 ; d3 0=failed,1=successful ; d5 expected status ; d7 actual status ; a2 source handle,... ; a3 destination handle,... ; a4 expected result handle,expected status,... ; fp2 source ; fp3 destination ; fp5 expected result ; fp7 actual result ;------------------------------------------------ lea.l push_decompressed,a0 ;decompress data move.l a0,-(sp) pea.l ",name,"_data_compressed jbsr decompress addq.l #8,sp ;relocate decompressed handle move.l #indirect_decompressed,d0 @@: add.l d0,(a0)+ ;destination handle tst.l (a0) bpl @b addq.l #4,a0 ;-1 movea.l a0,a4 ;expected result handle,expected status,... @@: add.l d0,(a0)+ ;expected result handle addq.l #4,a0 ;expected status tst.l (a0) bpl @b ; addq.l #4,a0 ;-1 ; lea.l push_decompressed,a3 ;destination handle,... 33: move.l #",XRN<<4,",d1 ;fpcr=(XRN..XRP)<<4 11: ;FPn,FPn fmove.l #0,fpcr fmove.x ([a3]),fp3 ;destination fmove.x fp3,fp7 ;actual result=destination fmove.l d1,fpcr ;fpcr fmove.l #0,fpsr ;source ",fop,".x fp7,fp7 ;EXECUTE ;actual result fmove.l fpsr,d7 ;actual status fmove.l #0,fpcr ; fmove.x ([a4]),fp5 ;expected result move.l (4,a4),d5 ;expected status ; move.l ",if(frp==-2,"d1",frp==-1,"#-1",Str("#",frp<<6)),",-(sp) ;fpcr(rp<<6,-1=strict) move.l d5,-(sp) ;expected status fmove.x fp5,-(sp) ;expected result move.l d7,-(sp) ;actual status fmove.x fp7,-(sp) ;actual result jbsr test_extended lea.l 36(sp),sp move.l d0,d3 ;0=failed,1=successful ; move.l d3,-(sp) ;0=failed,1=successful jbsr statistics_update addq.l #4,sp beq @f ;not output ;output putmsg '",FOP,".X FPn=' puthex24 ([a3]),(4,[a3]),(8,[a3]) ;source putmsg ',FPn=' puthex24 ([a3]),(4,[a3]),(8,[a3]) ;destination putmsg ' @' move.l d1,-(sp) jbsr printfpcrrprm addq.l #4,sp putcrlf move.l d3,-(sp) ;0=failed,1=successful move.l d5,-(sp) ;expected status fmove.x fp5,-(sp) ;expected result move.l d7,-(sp) ;actual status fmove.x fp7,-(sp) ;actual result jbsr output_extended lea.l 36(sp),sp @@: ; addq.l #8,a4 ;expected result handle,expected status,... ; add.w #1<<4,d1 ;rprm++ cmp.w #",XRP<<4,",d1 ;fpcr=(XRN..XRP)<<4 bls 11b ; addq.l #4,a3 ;destination handle,... tst.l (a3) ;destination handle,... bpl 33b ; lea.l push_decompressed,a3 ;destination handle,... 33: lea.l push_decompressed,a2 ;source handle,... 22: move.l #",XRN<<4,",d1 ;fpcr=(XRN..XRP)<<4 11: ;FPm,FPn fmove.l #0,fpcr fmove.x ([a2]),fp2 ;source fmove.x ([a3]),fp3 ;destination fmove.x fp3,fp7 ;actual result=destination fmove.l d1,fpcr ;fpcr fmove.l #0,fpsr ;source ",fop,".x fp2,fp7 ;EXECUTE ;actual result fmove.l fpsr,d7 ;actual status fmove.l #0,fpcr ; fmove.x ([a4]),fp5 ;expected result move.l (4,a4),d5 ;expected status ; move.l ",if(frp==-2,"d1",frp==-1,"#-1",Str("#",frp<<6)),",-(sp) ;fpcr(rp<<6,-1=strict) move.l d5,-(sp) ;expected status fmove.x fp5,-(sp) ;expected result move.l d7,-(sp) ;actual status fmove.x fp7,-(sp) ;actual result jbsr test_extended lea.l 36(sp),sp move.l d0,d3 ;0=failed,1=successful ; move.l d3,-(sp) ;0=failed,1=successful jbsr statistics_update addq.l #4,sp beq @f ;not output ;output putmsg '",FOP,".X FPm=' puthex24 ([a2]),(4,[a2]),(8,[a2]) ;source putmsg ',FPn=' puthex24 ([a3]),(4,[a3]),(8,[a3]) ;destination putmsg ' @' move.l d1,-(sp) jbsr printfpcrrprm addq.l #4,sp putcrlf move.l d3,-(sp) ;0=failed,1=successful move.l d5,-(sp) ;expected status fmove.x fp5,-(sp) ;expected result move.l d7,-(sp) ;actual status fmove.x fp7,-(sp) ;actual result jbsr output_extended lea.l 36(sp),sp @@: ; addq.l #8,a4 ;expected result handle,expected status,... ; add.w #1<<4,d1 ;rprm++ cmp.w #",XRP<<4,",d1 ;fpcr=(XRN..XRP)<<4 bls 11b ; addq.l #4,a2 ;source handle,... tst.l (a2) ;source handle,... bpl 22b ; addq.l #4,a3 ;destination handle,... tst.l (a3) ;destination handle,... bpl 33b ; jbsr mnemonic_end 99: fmovem.x (_fregs,a6),fregs fmovem.l (_cregs,a6),cregs movem.l (_regs,a6),regs unlk a6 rts .cpu 68000 .align 4 ",name,"_data_compressed:: "); push_start(); for(i=1,#a, x=a[i]; \\ソース,デスティネーション push_indirect(12,numtoexd(x,RN))); push(4,-1); for(i=1,#a, x=a[i]; \\ソース,デスティネーション for(rprm=XRN,XRP, \\(rp<<2)+rm。丸め桁数と丸めモード。extendedのみ rp=bitand(rprm>>2,3); \\丸め桁数 rm=bitand(rprm,3); \\丸めモード fpsr=0; z=func(x,x,rp,rm); fpsr_update_ccr(z); fpsr_update_aer(); sr=fpsr; push_indirect(12,numtoexd(z,RN)); push(4,sr))); for(i=1,#a, x=a[i]; \\デスティネーション for(j=1,#a, y=a[j]; \\ソース for(rprm=XRN,XRP, \\(rp<<2)+rm。丸め桁数と丸めモード。extendedのみ rp=bitand(rprm>>2,3); \\丸め桁数 rm=bitand(rprm,3); \\丸めモード fpsr=0; z=func(x,y,rp,rm); fpsr_update_ccr(z); fpsr_update_aer(); sr=fpsr; push_indirect(12,numtoexd(z,RN)); push(4,sr)))); push(4,-1); push_end() } \\---------------------------------------------------------------------------------------- \\ Fop.X FPm,FPc:FPs \\---------------------------------------------------------------------------------------- make_fop1to2(name,fop,frp,fpu,a,funcc,funcs)={ my(FOP,cpu,x,ys,yc,rp,rm,sr); FOP=strupr(fop); print("making ",name); cpu=fputocpu(fpu); a=vector(#a,n,exd(a[n],RN)); a=uniq(sort(append(a,vector(#a,n,-a[n]),[NaN]),comparator),comparator); asm( " ;-------------------------------------------------------------------------------- ; ",FOP,".X FPm,FPc:FPs ;-------------------------------------------------------------------------------- .cpu ",cpu," regs reg d0-d7/a0-a5 cregs reg fpcr/fpsr/fpiar fregs reg fp0-fp7 .offsym 0,_a6 _size: _regs: .ds.b .sizeof.(regs) _fregs: .ds.b .sizeof.(fregs) _cregs: .ds.b .sizeof.(cregs) _a6: .ds.l 1 _pc: .ds.l 1 .text .even ",name,"_test:: link.w a6,#_size movem.l regs,(_regs,a6) fmovem.l cregs,(_cregs,a6) fmovem.x fregs,(_fregs,a6) ; move.l #",fpu,",-(sp) peamsg '",FOP,".X FPM,FPC:FPS' jbsr mnemonic_start addq.l #8,sp beq 99f putmsg 'test: ",FOP,".X FPm,FPc:FPs',13,10 ;------------------------------------------------ ; d1 fpcr=(XRN..DRP)<<4 ; d2 0=failed,1=successful upper ; d3 0=failed,1=successful lower ; d5 expected status ; d7 actual status ; a2 source handle,... ; a4 expected result upper handle,expected status upper,expected result lower handle,expected status lower,... ; fp2 source ; fp4 expected result upper ; fp5 expected result lower ; fp6 actual result upper ; fp7 actual result lower ;------------------------------------------------ lea.l push_decompressed,a0 ;decompress data move.l a0,-(sp) pea.l ",name,"_data_compressed jbsr decompress addq.l #8,sp ;relocate decompressed handle move.l #indirect_decompressed,d0 @@: add.l d0,(a0)+ ;source handle tst.l (a0) bpl @b addq.l #4,a0 ;-1 @@: add.l d0,(a0)+ ;expected result upper handle addq.l #4,a0 ;expected status upper add.l d0,(a0)+ ;expected result lower handle addq.l #4,a0 ;expected status lower tst.l (a0) bpl @b ; addq.l #4,a0 ;-1 ; lea.l push_decompressed,a2 ;source handle,... lea.l (4*",#a,"+4,a2),a4 ;expected result upper handle,expected status upper,expected result lower handle,expected status lower,... 22: move.l #",XRN<<4,",d1 ;fpcr=(XRN..DRP)<<4 11: ;FPn,FPn:FPn fmove.l #0,fpcr fmove.x ([a2]),fp2 ;source fmove.x fp2,fp7 ;source fmove.l d1,fpcr ;fpcr fmove.l #0,fpsr ;source ",fop,".x fp7,fp7:fp7 ;EXECUTE ;actual result upper ;actual result lower fmove.l fpsr,d7 ;actual status fmove.l #0,fpcr ; fmove.x ([8,a4]),fp5 ;expected result lower move.l (12,a4),d5 ;expected status lower ; move.l ",if(frp==-2,"d1",frp==-1,"#-1",Str("#",frp<<6)),",-(sp) ;fpcr(rp<<6,-1=strict) move.l d5,-(sp) ;expected status fmove.x fp5,-(sp) ;expected result lower move.l d7,-(sp) ;actual status fmove.x fp7,-(sp) ;actual result lower jbsr test_extended lea.l 36(sp),sp move.l d0,d3 ;0=failed,1=successful lower ; move.l d3,-(sp) ;0=failed,1=successful jbsr statistics_update addq.l #4,sp beq @f ;not output ;output putmsg '",FOP,".X FPn=' puthex24 ([a2]),(4,[a2]),(8,[a2]) ;source putmsg ',FPn:FPn @' move.l d1,-(sp) jbsr printfpcrrprm addq.l #4,sp putcrlf move.l d3,-(sp) ;0=failed,1=successful lower move.l d5,-(sp) ;expected status fmove.x fp5,-(sp) ;expected result lower move.l d7,-(sp) ;actual status fmove.x fp7,-(sp) ;actual result lower jbsr output_extended lea.l 36(sp),sp @@: ; lea.l 16(a4),a4 ;expected result upper handle,expected status upper,expected result lower handle,expected status lower,... ; add.w #1<<4,d1 ;rprm++ cmp.w #",DRP<<4,",d1 ;fpcr=(XRN..DRP)<<4 bls 11b ; addq.l #4,a2 ;source handle,... tst.l (a2) ;source handle,... bpl 22b ; lea.l push_decompressed,a2 ;source handle,... lea.l (4*",#a,"+4,a2),a4 ;expected result upper handle,expected status upper,expected result lower handle,expected status lower,... 22: move.l #",XRN<<4,",d1 ;fpcr=(XRN..DRP)<<4 11: ;FPm,FPc:FPs fmove.l #0,fpcr fmove.x ([a2]),fp2 ;source fmove.s #$7FFFFFFF,fp6 ;fill upper=NaN fmove.s #$7FFFFFFF,fp7 ;fill lower=NaN fmove.l d1,fpcr ;fpcr fmove.l #0,fpsr ;source ",fop,".x fp2,fp6:fp7 ;EXECUTE ;actual result upper ;actual result lower fmove.l fpsr,d7 ;actual status fmove.l #0,fpcr ; fmove.x ([a4]),fp4 ;expected result upper move.l (4,a4),d4 ;expected status upper fmove.x ([8,a4]),fp5 ;expected result lower move.l (12,a4),d5 ;expected status lower ; move.l ",if(frp==-2,"d1",frp==-1,"#-1",Str("#",frp<<6)),",-(sp) ;fpcr(rp<<6,-1=strict) clr.l -(sp) ;dummy status fmove.x fp4,-(sp) ;expected result upper clr.l -(sp) ;dummy status fmove.x fp6,-(sp) ;actual result upper jbsr test_extended lea.l 36(sp),sp move.l d0,d2 ;0=failed,1=successful upper ; move.l ",if(frp==-2,"d1",frp==-1,"#-1",Str("#",frp<<6)),",-(sp) ;fpcr(rp<<6,-1=strict) move.l d5,-(sp) ;expected status fmove.x fp5,-(sp) ;expected result lower move.l d7,-(sp) ;actual status fmove.x fp7,-(sp) ;actual result lower jbsr test_extended lea.l 36(sp),sp move.l d0,d3 ;0=failed,1=successful lower ; move.l d2,d0 ;0=failed,1=successful upper and.l d3,d0 ;0=failed,1=successful lower ;0=failed,1=successful move.l d0,-(sp) ;0=failed,1=successful jbsr statistics_update addq.l #4,sp beq @f ;not output ;output putmsg '",FOP,".X FPm=' puthex24 ([a2]),(4,[a2]),(8,[a2]) ;source putmsg ',FPc:FPs @' move.l d1,-(sp) jbsr printfpcrrprm addq.l #4,sp putcrlf move.l d2,-(sp) ;0=failed,1=successful upper clr.l -(sp) ;dummy status fmove.x fp4,-(sp) ;expected result upper clr.l -(sp) ;dummy status fmove.x fp6,-(sp) ;actual result upper jbsr output_extended lea.l 36(sp),sp move.l d3,-(sp) ;0=failed,1=successful lower move.l d5,-(sp) ;expected status fmove.x fp5,-(sp) ;expected result lower move.l d7,-(sp) ;actual status fmove.x fp7,-(sp) ;actual result lower jbsr output_extended lea.l 36(sp),sp @@: ; lea.l 16(a4),a4 ;expected result upper handle,expected status upper,expected result lower handle,expected status lower,... ; add.w #1<<4,d1 ;rprm++ cmp.w #",DRP<<4,",d1 ;fpcr=(XRN..DRP)<<4 bls 11b ; addq.l #4,a2 ;source handle,... tst.l (a2) ;source handle,... bpl 22b ; jbsr mnemonic_end 99: fmovem.x (_fregs,a6),fregs fmovem.l (_cregs,a6),cregs movem.l (_regs,a6),regs unlk a6 rts .cpu 68000 .align 4 ",name,"_data_compressed:: "); push_start(); for(i=1,#a, x=a[i]; \\ソース push_indirect(12,numtoexd(x,RN))); push(4,-1); for(i=1,#a, x=a[i]; \\ソース for(rprm=XRN,DRP, \\(rp<<2)+rm。丸め桁数と丸めモード rp=bitand(rprm>>2,3); \\丸め桁数 rm=bitand(rprm,3); \\丸めモード yc=funcc(x,rp,rm); \\upper fpsr=0; ys=funcs(x,rp,rm); \\lower fpsr_update_ccr(ys); fpsr_update_aer(); sr=fpsr; push_indirect(12,numtoexd(yc,RN)); \\upper push(4,0); push_indirect(12,numtoexd(ys,RN)); \\lower push(4,sr))); push(4,-1); push_end() } \\ frp \\ -2 デフォルトで1ulpまでの誤差を許容するもの \\ FACOS FASIN FATAN FATANH FCOS FCOSH FETOX FETOXM1 \\ FLOG10 FLOG2 FLOGN FLOGNP1 \\ FMOVE.P <mem>,FPn \\ FSIN FSINCOS FSINH FTAN FTANH FTENTOX FTWOTOX \\ -1 常にstrictになるもの \\ FABS FADD FCMP FDABS FDADD FDDIV FDIV FDMOVE FDMUL FDNEG FDSQRT FDSUB \\ FGETEXP FGETMAN FINT FINTRZ FMOD \\ FMOVE(FMOVE.P <mem>,FPn以外) \\ FMOVECR FMUL FNEG FREM \\ FSABS FSCALE FSDIV FSGLDIV FSGLMUL FSMOVE FSMUL FSNEG FSQRT FSSQRT FSSUB FSUB FTST \\---------------------------------------------------------------------------------------- \\ FABS.X FPm,FPn \\---------------------------------------------------------------------------------------- make_fabs()={ make_fop1to1("fabs", "fabs", -1, MC68881+MC68882+MC68040+FPSP040+MC68060+FPSP060, append(DATA_SPECIAL, DATA_FLOAT, DATA_BASIC, DATA_ROUND), (x,rp,rm)->if(type(x)=="t_POL", if(x==-Inf,Inf, \\abs(-Inf)=+Inf x==-Rei,Rei, \\abs(-0)=+0 x==Rei,Rei, \\abs(+0)=+0 x==Inf,Inf, \\abs(+Inf)=+Inf NaN), xxx(abs(x),rp,rm))) } \\---------------------------------------------------------------------------------------- \\ FACOS.X FPm,FPn \\---------------------------------------------------------------------------------------- make_facos()={ make_fop1to1("facos", "facos", -2, MC68881+MC68882+FPSP040+FPSP060, append(DATA_SPECIAL, DATA_FLOAT, DATA_BASIC, DATA_ROUND, DATA_ZERO_PLUS, DATA_ONE_MINUS), (x,rp,rm)->if(type(x)=="t_POL", if(x==-Inf,fpsr=bitor(fpsr,OE);NaN, \\acos(-Inf)=NaN,OE x==-Rei,fpsr=bitor(fpsr,X2);xxx(Pi/2,rp,rm), \\acos(-0)=π/2,X2 x==Rei,fpsr=bitor(fpsr,X2);xxx(Pi/2,rp,rm), \\acos(+0)=π/2,X2 x==Inf,fpsr=bitor(fpsr,OE);NaN, \\acos(+Inf)=NaN,OE NaN), x<-1,fpsr=bitor(fpsr,OE);NaN, \\acos(x<-1)=NaN,OE x==-1,fpsr=bitor(fpsr,X2);xxx(Pi,rp,rm), \\acos(-1)=π,X2 x==1,Rei, \\acos(+1)=+0 1<x,fpsr=bitor(fpsr,OE);NaN, \\acos(1<x)=NaN,OE fpsr=bitor(fpsr,X2); xxx(acos(x),rp,rm))) } \\---------------------------------------------------------------------------------------- \\ FADD.X FPm,FPn \\---------------------------------------------------------------------------------------- make_fadd()={ my(z); make_fop2to1("fadd", "fadd", -1, MC68881+MC68882+MC68040+FPSP040+MC68060+FPSP060, append(DATA_SPECIAL, DATA_EXTENDED, DATA_BINARY), (x,y,rp,rm)->if((x==NaN)||(y==NaN),NaN, (x==Inf)&&(y==-Inf),fpsr=bitor(fpsr,OE);NaN, \\(+Inf)+(-Inf)=NaN,OE (x==-Inf)&&(y==Inf),fpsr=bitor(fpsr,OE);NaN, \\(-Inf)+(+Inf)=NaN,OE (x==Rei)&&(y==Rei),Rei, \\(+0)+(+0)=+0 (x==-Rei)&&(y==-Rei),-Rei, \\(-0)+(-0)=-0 (x==Rei)&&(y==-Rei),if(rm==RM,-Rei,Rei), \\(+0)+(-0)=±0 (x==-Rei)&&(y==Rei),if(rm==RM,-Rei,Rei), \\(-0)+(+0)=±0 (y==Inf)||(y==-Inf),y, \\(±x)+(±Inf)=±Inf (x==Inf)||(x==-Inf),x, \\(±Inf)+(±y)=±Inf z=xxx(if((x==Rei)||(x==-Rei),0,x)+ if((y==Rei)||(y==-Rei),0,y),rp,rm); \\(±x)+(±0)=(±x),(±0)+(±y)=±y if((z==Rei)||(z==-Rei),z=if(rm==RM,-Rei,Rei)); z)) } \\---------------------------------------------------------------------------------------- \\ FASIN.X FPm,FPn \\---------------------------------------------------------------------------------------- make_fasin()={ my(y); make_fop1to1("fasin", "fasin", -2, MC68881+MC68882+FPSP040+FPSP060, append(DATA_SPECIAL, DATA_FLOAT, DATA_BASIC, DATA_ROUND, DATA_ZERO_PLUS, DATA_ONE_MINUS), (x,rp,rm)->if(type(x)=="t_POL", if(x==-Inf,fpsr=bitor(fpsr,OE);NaN, \\asin(-Inf)=NaN,OE x==-Rei,-Rei, \\asin(-0)=-0 x==Rei,Rei, \\asin(+0)=+0 x==Inf,fpsr=bitor(fpsr,OE);NaN, \\asin(+Inf)=NaN,OE NaN), x<-1,fpsr=bitor(fpsr,OE);NaN, \\asin(x<-1)=NaN,OE x==-1,fpsr=bitor(fpsr,X2);xxx(-Pi/2,rp,rm), \\asin(-1)=-π/2,X2 x==1,fpsr=bitor(fpsr,X2);xxx(Pi/2,rp,rm), \\asin(1)=π/2,X2 1<x,fpsr=bitor(fpsr,OE);NaN, \\asin(1<x)=NaN,OE fpsr=bitor(fpsr,X2); y=roundxxx(asin(x),rp,rm); y=originLowerUpper(y,x,rp,rm); y=xxx(y,rp,rm); correctUnderflow(y,rp))) } \\---------------------------------------------------------------------------------------- \\ FATAN.X FPm,FPn \\---------------------------------------------------------------------------------------- make_fatan()={ my(y); make_fop1to1("fatan", "fatan", -2, MC68881+MC68882+FPSP040+FPSP060, append(DATA_SPECIAL, DATA_FLOAT, DATA_BASIC, DATA_ROUND, DATA_ZERO_PLUS), (x,rp,rm)->if(type(x)=="t_POL", if(x==-Inf,fpsr=bitor(fpsr,X2);xxx(-Pi/2,rp,rm), \\atan(-Inf)=-π/2,X2 x==-Rei,-Rei, \\atan(-0)=-0 x==Rei,Rei, \\atan(+0)=+0 x==Inf,fpsr=bitor(fpsr,X2);xxx(Pi/2,rp,rm), \\atan(+Inf)=π/2,X2 NaN), fpsr=bitor(fpsr,X2); y=roundxxx(atan(x),rp,rm); y=originUpperLower(y,x,rp,rm); y=xxx(y,rp,rm); correctUnderflow(y,rp))) } \\---------------------------------------------------------------------------------------- \\ FATANH.X FPm,FPn \\---------------------------------------------------------------------------------------- make_fatanh()={ my(y); make_fop1to1("fatanh", "fatanh", -2, MC68881+MC68882+FPSP040+FPSP060, append(DATA_SPECIAL, DATA_FLOAT, DATA_BASIC, DATA_ROUND, DATA_ZERO_PLUS, DATA_ONE_MINUS), (x,rp,rm)->if(type(x)=="t_POL", if(x==-Inf,fpsr=bitor(fpsr,OE);NaN, \\atanh(-Inf)=NaN,OE x==-Rei,-Rei, \\atanh(-0)=-0 x==Rei,Rei, \\atanh(+0)=+0 x==Inf,fpsr=bitor(fpsr,OE);NaN, \\atanh(+Inf)=NaN,OE NaN), x<-1,fpsr=bitor(fpsr,OE);NaN, \\atanh(x<-1)=NaN,OE x==-1,fpsr=bitor(fpsr,DZ);-Inf, \\atanh(-1)=-Inf,DZ x==1,fpsr=bitor(fpsr,DZ);Inf, \\atanh(1)=+Inf,DZ 1<x,fpsr=bitor(fpsr,OE);NaN, \\atanh(1<x)=NaN,OE fpsr=bitor(fpsr,X2); y=roundxxx(atanh(x),rp,rm); y=originLowerUpper(y,x,rp,rm); y=xxx(y,rp,rm); correctUnderflow(y,rp))) } \\---------------------------------------------------------------------------------------- \\ FBcc.L <label> \\---------------------------------------------------------------------------------------- make_fbccl060()={ my(m,z,n,a); print("making fbccl060"); asm( " ;-------------------------------------------------------------------------------- ; FBcc.L <label> ;-------------------------------------------------------------------------------- .cpu 68030 regs reg d0-d7/a0-a5 cregs reg fpcr/fpsr/fpiar fregs reg fp0-fp7 .offsym 0,_a6 _size: _regs: .ds.b .sizeof.(regs) _fregs: .ds.b .sizeof.(fregs) _cregs: .ds.b .sizeof.(cregs) _a6: .ds.l 1 _pc: .ds.l 1 .text .even fbccl060_test:: link.w a6,#_size movem.l regs,(_regs,a6) fmovem.l cregs,(_cregs,a6) fmovem.x fregs,(_fregs,a6) ; move.l #MC68060+FPSP060,-(sp) peamsg 'FBCC.L <LABEL>' jbsr mnemonic_start addq.l #8,sp beq 99f putmsg 'test: FBcc.L <label>',13,10 ;------------------------------------------------ ; d1 actual result ; d4 actual status ; d5 cc=0..31 ; d6 fpsr=(mzin=0..15)<<24 ; d7 0=failed,1=successful ; a0 expected result,expected status,... ; a1 expected result ; a4 expected status ;------------------------------------------------ lea.l push_decompressed,a0 ;expected result,expected status,... ;decompress data move.l a0,-(sp) pea.l fbccl060_expected_compressed jbsr decompress addq.l #8,sp move.l #0<<24,d6 ;fpsr=(mzin=0..15)<<24 66: moveq.l #0,d5 ;cc=0..31 55: ;FBcc.L <forward-label> fmove.l #0,fpcr fmove.l d6,fpsr ;fpsr jsr ([fbccl060_execute_forward,za0,d5.l*4]) ;EXECUTE ;actual result fmove.l fpsr,d4 ;actual status ; movea.l (a0),a1 ;expected result movea.l (4,a0),a4 ;expected status ; movem.l d1/d4/a1/a4,-(sp) ;actual result,actual status,expected result,expected status jbsr test_single lea.l 16(sp),sp move.l d0,d7 ;0=failed,1=successful ; move.l d7,-(sp) ;0=failed,1=successful jbsr statistics_update addq.l #4,sp beq @f ;not output ;output putmsg 'FB' putstr (uppercase_cc,za0,d5.l*4) putmsg '.L <forward-label> @' move.l d6,-(sp) ;fpsr jbsr printfpsr addq.l #4,sp putcrlf move.l d7,-(sp) ;0=failed,1=successful movem.l d1/d4/a1/a4,-(sp) ;actual result,actual status,expected result,expected status jbsr output_single lea.l 20(sp),sp @@: ; ;FBcc.L <backward-label> fmove.l #0,fpcr fmove.l d6,fpsr ;fpsr jsr ([fbccl060_execute_backward,za0,d5.l*4]) ;EXECUTE ;actual result fmove.l fpsr,d4 ;actual status ; movea.l (a0),a1 ;expected result movea.l (4,a0),a4 ;expected status ; movem.l d1/d4/a1/a4,-(sp) ;actual result,actual status,expected result,expected status jbsr test_single lea.l 16(sp),sp move.l d0,d7 ;0=failed,1=successful ; move.l d7,-(sp) ;0=failed,1=successful jbsr statistics_update addq.l #4,sp beq @f ;not output ;output putmsg 'FB' putstr (uppercase_cc,za0,d5.l*4) putmsg '.L <backward-label> @' move.l d6,-(sp) ;fpsr jbsr printfpsr addq.l #4,sp putcrlf move.l d7,-(sp) ;0=failed,1=successful movem.l d1/d4/a1/a4,-(sp) ;actual result,actual status,expected result,expected status jbsr output_single lea.l 20(sp),sp @@: ; addq.l #8,a0 ;expected result ; addq.w #1,d5 ;cc++ cmp.w #31,d5 ;cc=0..31 bls 55b ; add.l #1<<24,d6 ;mzin++ cmp.l #15<<24,d6 ;fpsr=(mzin=0..15)<<24 bls 66b ; jbsr mnemonic_end 99: fmovem.x (_fregs,a6),fregs fmovem.l (_cregs,a6),cregs movem.l (_regs,a6),regs unlk a6 rts .align 4 fbccl060_execute_forward:: .irp cc,F,EQ,OGT,OGE,OLT,OLE,OGL,OR,UN,UEQ,UGT,UGE,ULT,ULE,NE,T,SF,SEQ,GT,GE,LT,LE,GL,GLE,NGLE,NGL,NLE,NLT,NGE,NGT,SNE,ST .dc.l fbccl060_execute_forward_&cc .endm fbccl060_execute_backward:: .irp cc,F,EQ,OGT,OGE,OLT,OLE,OGL,OR,UN,UEQ,UGT,UGE,ULT,ULE,NE,T,SF,SEQ,GT,GE,LT,LE,GL,GLE,NGLE,NGL,NLE,NLT,NGE,NGT,SNE,ST .dc.l fbccl060_execute_backward_&cc .endm .irp cc,F,EQ,OGT,OGE,OLT,OLE,OGL,OR,UN,UEQ,UGT,UGE,ULT,ULE,NE,T,SF,SEQ,GT,GE,LT,LE,GL,GLE,NGLE,NGL,NLE,NLT,NGE,NGT,SNE,ST fbccl060_execute_forward_&cc:: moveq.l #2,d1 ;actual result. 2=too long FB&cc.L @f ;EXECUTE moveq.l #0,d1 ;actual result. 0=not taken rts subq.l #2,d1 ;actual result. -1=too short(forward)/too long(backward) @@: subq.l #1,d1 ;actual result. 1=taken rts fbccl060_execute_backward_&cc:: moveq.l #2,d1 ;actual result. 2=too short FB&cc.L @b ;EXECUTE moveq.l #0,d1 ;actual result. 0=not taken rts .endm .cpu 68000 .align 4 fbccl060_expected_compressed:: "); push_start(); for(mzin=0,15, m=bitand(mzin>>3,1); z=bitand(mzin>>2,1); n=bitand(mzin>>0,1); a=[ 0, \\000000 F z, \\000001 EQ !(n||z||m), \\000010 OGT z||!(n||m), \\000011 OGE m&&!(n||z), \\000100 OLT z||(m&&!n), \\000101 OLE !(n||z), \\000110 OGL !n, \\000111 OR n, \\001000 UN n||z, \\001001 UEQ n||!(m||z), \\001010 UGT n||(z||!m), \\001011 UGE n||(m&&!z), \\001100 ULT n||z||m, \\001101 ULE !z, \\001110 NE 1 \\001111 T ]; for(cc=0,15, push(4,a[1+cc]); push(4,mzin<<24)); for(cc=16,31, push(4,a[1+cc-16]); push(4,(mzin<<24)+if(n,BS+AV,0)))); push_end() } make_fbccl88x()={ my(m,z,n,a); print("making fbccl88x"); asm( " ;-------------------------------------------------------------------------------- ; FBcc.L <label> ;-------------------------------------------------------------------------------- .cpu 68030 regs reg d0-d7/a0-a5 cregs reg fpcr/fpsr/fpiar fregs reg fp0-fp7 .offsym 0,_a6 _size: _regs: .ds.b .sizeof.(regs) _fregs: .ds.b .sizeof.(fregs) _cregs: .ds.b .sizeof.(cregs) _a6: .ds.l 1 _pc: .ds.l 1 .text .even fbccl88x_test:: link.w a6,#_size movem.l regs,(_regs,a6) fmovem.l cregs,(_cregs,a6) fmovem.x fregs,(_fregs,a6) ; move.l #MC68881+MC68882+MC68040+FPSP040,-(sp) peamsg 'FBCC.L <LABEL>' jbsr mnemonic_start addq.l #8,sp beq 99f putmsg 'test: FBcc.L <label>',13,10 ;------------------------------------------------ ; d1 actual result ; d4 actual status ; d5 cc=0..31 ; d6 fpsr=(mzin=0..15)<<24 ; d7 0=failed,1=successful ; a0 expected result,expected status,... ; a1 expected result ; a4 expected status ;------------------------------------------------ lea.l push_decompressed,a0 ;expected result,expected status,... ;decompress data move.l a0,-(sp) pea.l fbccl88x_expected_compressed jbsr decompress addq.l #8,sp move.l #0<<24,d6 ;fpsr=(mzin=0..15)<<24 66: moveq.l #0,d5 ;cc=0..31 55: ;FBcc.L <forward-label> fmove.l #0,fpcr fmove.l d6,fpsr ;fpsr jsr ([fbccl88x_execute_forward,za0,d5.l*4]) ;EXECUTE ;actual result fmove.l fpsr,d4 ;actual status ; movea.l (a0),a1 ;expected result movea.l (4,a0),a4 ;expected status ; movem.l d1/d4/a1/a4,-(sp) ;actual result,actual status,expected result,expected status jbsr test_single lea.l 16(sp),sp move.l d0,d7 ;0=failed,1=successful ; move.l d7,-(sp) ;0=failed,1=successful jbsr statistics_update addq.l #4,sp beq @f ;not output ;output putmsg 'FB' putstr (uppercase_cc,za0,d5.l*4) putmsg '.L <forward-label> @' move.l d6,-(sp) ;fpsr jbsr printfpsr addq.l #4,sp putcrlf move.l d7,-(sp) ;0=failed,1=successful movem.l d1/d4/a1/a4,-(sp) ;actual result,actual status,expected result,expected status jbsr output_single lea.l 20(sp),sp @@: ; ;FBcc.L <backward-label> fmove.l #0,fpcr fmove.l d6,fpsr ;fpsr jsr ([fbccl88x_execute_backward,za0,d5.l*4]) ;EXECUTE ;actual result fmove.l fpsr,d4 ;actual status ; movea.l (a0),a1 ;expected result movea.l (4,a0),a4 ;expected status ; movem.l d1/d4/a1/a4,-(sp) ;actual result,actual status,expected result,expected status jbsr test_single lea.l 16(sp),sp move.l d0,d7 ;0=failed,1=successful ; move.l d7,-(sp) ;0=failed,1=successful jbsr statistics_update addq.l #4,sp beq @f ;not output ;output putmsg 'FB' putstr (uppercase_cc,za0,d5.l*4) putmsg '.L <backward-label> @' move.l d6,-(sp) ;fpsr jbsr printfpsr addq.l #4,sp putcrlf move.l d7,-(sp) ;0=failed,1=successful movem.l d1/d4/a1/a4,-(sp) ;actual result,actual status,expected result,expected status jbsr output_single lea.l 20(sp),sp @@: ; addq.l #8,a0 ;expected result ; addq.w #1,d5 ;cc++ cmp.w #31,d5 ;cc=0..31 bls 55b ; add.l #1<<24,d6 ;mzin++ cmp.l #15<<24,d6 ;fpsr=(mzin=0..15)<<24 bls 66b ; jbsr mnemonic_end 99: fmovem.x (_fregs,a6),fregs fmovem.l (_cregs,a6),cregs movem.l (_regs,a6),regs unlk a6 rts .align 4 fbccl88x_execute_forward:: .irp cc,F,EQ,OGT,OGE,OLT,OLE,OGL,OR,UN,UEQ,UGT,UGE,ULT,ULE,NE,T,SF,SEQ,GT,GE,LT,LE,GL,GLE,NGLE,NGL,NLE,NLT,NGE,NGT,SNE,ST .dc.l fbccl88x_execute_forward_&cc .endm fbccl88x_execute_backward:: .irp cc,F,EQ,OGT,OGE,OLT,OLE,OGL,OR,UN,UEQ,UGT,UGE,ULT,ULE,NE,T,SF,SEQ,GT,GE,LT,LE,GL,GLE,NGLE,NGL,NLE,NLT,NGE,NGT,SNE,ST .dc.l fbccl88x_execute_backward_&cc .endm .irp cc,F,EQ,OGT,OGE,OLT,OLE,OGL,OR,UN,UEQ,UGT,UGE,ULT,ULE,NE,T,SF,SEQ,GT,GE,LT,LE,GL,GLE,NGLE,NGL,NLE,NLT,NGE,NGT,SNE,ST fbccl88x_execute_forward_&cc:: moveq.l #2,d1 ;actual result. 2=too long FB&cc.L @f ;EXECUTE moveq.l #0,d1 ;actual result. 0=not taken rts subq.l #2,d1 ;actual result. -1=too short(forward)/too long(backward) @@: subq.l #1,d1 ;actual result. 1=taken rts fbccl88x_execute_backward_&cc:: moveq.l #2,d1 ;actual result. 2=too short FB&cc.L @b ;EXECUTE moveq.l #0,d1 ;actual result. 0=not taken rts .endm .cpu 68000 .align 4 fbccl88x_expected_compressed:: "); push_start(); for(mzin=0,15, m=bitand(mzin>>3,1); z=bitand(mzin>>2,1); n=bitand(mzin>>0,1); a=[ 0, \\000000 F z, \\000001 EQ !(n||z||m), \\000010 OGT z||!(n||m), \\000011 OGE m&&!(n||z), \\000100 OLT z||(m&&!n), \\000101 OLE !(n||z), \\000110 OGL z||!n, \\000111 OR n, \\001000 UN n||z, \\001001 UEQ n||!(m||z), \\001010 UGT n||(z||!m), \\001011 UGE n||(m&&!z), \\001100 ULT n||z||m, \\001101 ULE n||!z, \\001110 NE 1 \\001111 T ]; for(cc=0,15, push(4,a[1+cc]); push(4,mzin<<24)); for(cc=16,31, push(4,a[1+cc-16]); push(4,(mzin<<24)+if(n,BS+AV,0)))); push_end() } \\---------------------------------------------------------------------------------------- \\ FBcc.W <label> \\---------------------------------------------------------------------------------------- make_fbccw060()={ my(m,z,n,a); print("making fbccw060"); asm( " ;-------------------------------------------------------------------------------- ; FBcc.W <label> ;-------------------------------------------------------------------------------- .cpu 68030 regs reg d0-d7/a0-a5 cregs reg fpcr/fpsr/fpiar fregs reg fp0-fp7 .offsym 0,_a6 _size: _regs: .ds.b .sizeof.(regs) _fregs: .ds.b .sizeof.(fregs) _cregs: .ds.b .sizeof.(cregs) _a6: .ds.l 1 _pc: .ds.l 1 .text .even fbccw060_test:: link.w a6,#_size movem.l regs,(_regs,a6) fmovem.l cregs,(_cregs,a6) fmovem.x fregs,(_fregs,a6) ; move.l #MC68060+FPSP060,-(sp) peamsg 'FBCC.W <LABEL>' jbsr mnemonic_start addq.l #8,sp beq 99f putmsg 'test: FBcc.W <label>',13,10 ;------------------------------------------------ ; d1 actual result ; d4 actual status ; d5 cc=0..31 ; d6 fpsr=(mzin=0..15)<<24 ; d7 0=failed,1=successful ; a0 expected result,expected status,... ; a1 expected result ; a4 expected status ;------------------------------------------------ lea.l push_decompressed,a0 ;expected result,expected status,... ;decompress data move.l a0,-(sp) pea.l fbccw060_expected_compressed jbsr decompress addq.l #8,sp move.l #0<<24,d6 ;fpsr=(mzin=0..15)<<24 66: moveq.l #0,d5 ;cc=0..31 55: ;FBcc.W <forward-label> fmove.l #0,fpcr fmove.l d6,fpsr ;fpsr jsr ([fbccw060_execute_forward,za0,d5.l*4]) ;EXECUTE ;actual result fmove.l fpsr,d4 ;actual status ; movea.l (a0),a1 ;expected result movea.l (4,a0),a4 ;expected status ; movem.l d1/d4/a1/a4,-(sp) ;actual result,actual status,expected result,expected status jbsr test_single lea.l 16(sp),sp move.l d0,d7 ;0=failed,1=successful ; move.l d7,-(sp) ;0=failed,1=successful jbsr statistics_update addq.l #4,sp beq @f ;not output ;output putmsg 'FB' putstr (uppercase_cc,za0,d5.l*4) putmsg '.W <forward-label> @' move.l d6,-(sp) ;fpsr jbsr printfpsr addq.l #4,sp putcrlf move.l d7,-(sp) ;0=failed,1=successful movem.l d1/d4/a1/a4,-(sp) ;actual result,actual status,expected result,expected status jbsr output_single lea.l 20(sp),sp @@: ; ;FBcc.W <backward-label> fmove.l #0,fpcr fmove.l d6,fpsr ;fpsr jsr ([fbccw060_execute_backward,za0,d5.l*4]) ;EXECUTE ;actual result fmove.l fpsr,d4 ;actual status ; movea.l (a0),a1 ;expected result movea.l (4,a0),a4 ;expected status ; movem.l d1/d4/a1/a4,-(sp) ;actual result,actual status,expected result,expected status jbsr test_single lea.l 16(sp),sp move.l d0,d7 ;0=failed,1=successful ; move.l d7,-(sp) ;0=failed,1=successful jbsr statistics_update addq.l #4,sp beq @f ;not output ;output putmsg 'FB' putstr (uppercase_cc,za0,d5.l*4) putmsg '.W <backward-label> @' move.l d6,-(sp) ;fpsr jbsr printfpsr addq.l #4,sp putcrlf move.l d7,-(sp) ;0=failed,1=successful movem.l d1/d4/a1/a4,-(sp) ;actual result,actual status,expected result,expected status jbsr output_single lea.l 20(sp),sp @@: ; addq.l #8,a0 ;expected result ; addq.w #1,d5 ;cc++ cmp.w #31,d5 ;cc=0..31 bls 55b ; add.l #1<<24,d6 ;mzin++ cmp.l #15<<24,d6 ;fpsr=(mzin=0..15)<<24 bls 66b ; jbsr mnemonic_end 99: fmovem.x (_fregs,a6),fregs fmovem.l (_cregs,a6),cregs movem.l (_regs,a6),regs unlk a6 rts .align 4 fbccw060_execute_forward:: .irp cc,F,EQ,OGT,OGE,OLT,OLE,OGL,OR,UN,UEQ,UGT,UGE,ULT,ULE,NE,T,SF,SEQ,GT,GE,LT,LE,GL,GLE,NGLE,NGL,NLE,NLT,NGE,NGT,SNE,ST .dc.l fbccw060_execute_forward_&cc .endm fbccw060_execute_backward:: .irp cc,F,EQ,OGT,OGE,OLT,OLE,OGL,OR,UN,UEQ,UGT,UGE,ULT,ULE,NE,T,SF,SEQ,GT,GE,LT,LE,GL,GLE,NGLE,NGL,NLE,NLT,NGE,NGT,SNE,ST .dc.l fbccw060_execute_backward_&cc .endm .irp cc,F,EQ,OGT,OGE,OLT,OLE,OGL,OR,UN,UEQ,UGT,UGE,ULT,ULE,NE,T,SF,SEQ,GT,GE,LT,LE,GL,GLE,NGLE,NGL,NLE,NLT,NGE,NGT,SNE,ST fbccw060_execute_forward_&cc:: moveq.l #2,d1 ;actual result. 2=too long FB&cc.W @f ;EXECUTE moveq.l #0,d1 ;actual result. 0=not taken rts subq.l #2,d1 ;actual result. -1=too short(forward)/too long(backward) @@: subq.l #1,d1 ;actual result. 1=taken rts fbccw060_execute_backward_&cc:: moveq.l #2,d1 ;actual result. 2=too short FB&cc.W @b ;EXECUTE moveq.l #0,d1 ;actual result. 0=not taken rts .endm .cpu 68000 .align 4 fbccw060_expected_compressed:: "); push_start(); for(mzin=0,15, m=bitand(mzin>>3,1); z=bitand(mzin>>2,1); n=bitand(mzin>>0,1); a=[ 0, \\000000 F z, \\000001 EQ !(n||z||m), \\000010 OGT z||!(n||m), \\000011 OGE m&&!(n||z), \\000100 OLT z||(m&&!n), \\000101 OLE !(n||z), \\000110 OGL !n, \\000111 OR n, \\001000 UN n||z, \\001001 UEQ n||!(m||z), \\001010 UGT n||(z||!m), \\001011 UGE n||(m&&!z), \\001100 ULT n||z||m, \\001101 ULE !z, \\001110 NE 1 \\001111 T ]; for(cc=0,15, push(4,a[1+cc]); push(4,mzin<<24)); for(cc=16,31, push(4,a[1+cc-16]); push(4,(mzin<<24)+if(n,BS+AV,0)))); push_end() } make_fbccw88x()={ my(m,z,n,a); print("making fbccw88x"); asm( " ;-------------------------------------------------------------------------------- ; FBcc.W <label> ;-------------------------------------------------------------------------------- .cpu 68030 regs reg d0-d7/a0-a5 cregs reg fpcr/fpsr/fpiar fregs reg fp0-fp7 .offsym 0,_a6 _size: _regs: .ds.b .sizeof.(regs) _fregs: .ds.b .sizeof.(fregs) _cregs: .ds.b .sizeof.(cregs) _a6: .ds.l 1 _pc: .ds.l 1 .text .even fbccw88x_test:: link.w a6,#_size movem.l regs,(_regs,a6) fmovem.l cregs,(_cregs,a6) fmovem.x fregs,(_fregs,a6) ; move.l #MC68881+MC68882+MC68040+FPSP040,-(sp) peamsg 'FBCC.W <LABEL>' jbsr mnemonic_start addq.l #8,sp beq 99f putmsg 'test: FBcc.W <label>',13,10 ;------------------------------------------------ ; d1 actual result ; d4 actual status ; d5 cc=0..31 ; d6 fpsr=(mzin=0..15)<<24 ; d7 0=failed,1=successful ; a0 expected result,expected status,... ; a1 expected result ; a4 expected status ;------------------------------------------------ lea.l push_decompressed,a0 ;expected result,expected status,... ;decompress data move.l a0,-(sp) pea.l fbccw88x_expected_compressed jbsr decompress addq.l #8,sp move.l #0<<24,d6 ;fpsr=(mzin=0..15)<<24 66: moveq.l #0,d5 ;cc=0..31 55: ;FBcc.W <forward-label> fmove.l #0,fpcr fmove.l d6,fpsr ;fpsr jsr ([fbccw88x_execute_forward,za0,d5.l*4]) ;EXECUTE ;actual result fmove.l fpsr,d4 ;actual status ; movea.l (a0),a1 ;expected result movea.l (4,a0),a4 ;expected status ; movem.l d1/d4/a1/a4,-(sp) ;actual result,actual status,expected result,expected status jbsr test_single lea.l 16(sp),sp move.l d0,d7 ;0=failed,1=successful ; move.l d7,-(sp) ;0=failed,1=successful jbsr statistics_update addq.l #4,sp beq @f ;not output ;output putmsg 'FB' putstr (uppercase_cc,za0,d5.l*4) putmsg '.W <forward-label> @' move.l d6,-(sp) ;fpsr jbsr printfpsr addq.l #4,sp putcrlf move.l d7,-(sp) ;0=failed,1=successful movem.l d1/d4/a1/a4,-(sp) ;actual result,actual status,expected result,expected status jbsr output_single lea.l 20(sp),sp @@: ; ;FBcc.W <backward-label> fmove.l #0,fpcr fmove.l d6,fpsr ;fpsr jsr ([fbccw88x_execute_backward,za0,d5.l*4]) ;EXECUTE ;actual result fmove.l fpsr,d4 ;actual status ; movea.l (a0),a1 ;expected result movea.l (4,a0),a4 ;expected status ; movem.l d1/d4/a1/a4,-(sp) ;actual result,actual status,expected result,expected status jbsr test_single lea.l 16(sp),sp move.l d0,d7 ;0=failed,1=successful ; move.l d7,-(sp) ;0=failed,1=successful jbsr statistics_update addq.l #4,sp beq @f ;not output ;output putmsg 'FB' putstr (uppercase_cc,za0,d5.l*4) putmsg '.W <backward-label> @' move.l d6,-(sp) ;fpsr jbsr printfpsr addq.l #4,sp putcrlf move.l d7,-(sp) ;0=failed,1=successful movem.l d1/d4/a1/a4,-(sp) ;actual result,actual status,expected result,expected status jbsr output_single lea.l 20(sp),sp @@: ; addq.l #8,a0 ;expected result ; addq.w #1,d5 ;cc++ cmp.w #31,d5 ;cc=0..31 bls 55b ; add.l #1<<24,d6 ;mzin++ cmp.l #15<<24,d6 ;fpsr=(mzin=0..15)<<24 bls 66b ; jbsr mnemonic_end 99: fmovem.x (_fregs,a6),fregs fmovem.l (_cregs,a6),cregs movem.l (_regs,a6),regs unlk a6 rts .align 4 fbccw88x_execute_forward:: .irp cc,F,EQ,OGT,OGE,OLT,OLE,OGL,OR,UN,UEQ,UGT,UGE,ULT,ULE,NE,T,SF,SEQ,GT,GE,LT,LE,GL,GLE,NGLE,NGL,NLE,NLT,NGE,NGT,SNE,ST .dc.l fbccw88x_execute_forward_&cc .endm fbccw88x_execute_backward:: .irp cc,F,EQ,OGT,OGE,OLT,OLE,OGL,OR,UN,UEQ,UGT,UGE,ULT,ULE,NE,T,SF,SEQ,GT,GE,LT,LE,GL,GLE,NGLE,NGL,NLE,NLT,NGE,NGT,SNE,ST .dc.l fbccw88x_execute_backward_&cc .endm .irp cc,F,EQ,OGT,OGE,OLT,OLE,OGL,OR,UN,UEQ,UGT,UGE,ULT,ULE,NE,T,SF,SEQ,GT,GE,LT,LE,GL,GLE,NGLE,NGL,NLE,NLT,NGE,NGT,SNE,ST fbccw88x_execute_forward_&cc:: moveq.l #2,d1 ;actual result. 2=too long FB&cc.W @f ;EXECUTE moveq.l #0,d1 ;actual result. 0=not taken rts subq.l #2,d1 ;actual result. -1=too short(forward)/too long(backward) @@: subq.l #1,d1 ;actual result. 1=taken rts fbccw88x_execute_backward_&cc:: moveq.l #2,d1 ;actual result. 2=too short FB&cc.W @b ;EXECUTE moveq.l #0,d1 ;actual result. 0=not taken rts .endm .cpu 68000 .align 4 fbccw88x_expected_compressed:: "); push_start(); for(mzin=0,15, m=bitand(mzin>>3,1); z=bitand(mzin>>2,1); n=bitand(mzin>>0,1); a=[ 0, \\000000 F z, \\000001 EQ !(n||z||m), \\000010 OGT z||!(n||m), \\000011 OGE m&&!(n||z), \\000100 OLT z||(m&&!n), \\000101 OLE !(n||z), \\000110 OGL z||!n, \\000111 OR n, \\001000 UN n||z, \\001001 UEQ n||!(m||z), \\001010 UGT n||(z||!m), \\001011 UGE n||(m&&!z), \\001100 ULT n||z||m, \\001101 ULE n||!z, \\001110 NE 1 \\001111 T ]; for(cc=0,15, push(4,a[1+cc]); push(4,mzin<<24)); for(cc=16,31, push(4,a[1+cc-16]); push(4,(mzin<<24)+if(n,BS+AV,0)))); push_end() } \\---------------------------------------------------------------------------------------- \\ FCMP.X FPm,FPn \\---------------------------------------------------------------------------------------- fcmp_func(x,y,rp,rm)={ fpsr=bitor(fpsr,if((x==NaN)||(y==NaN),NA, \\どちらかがNaN x==y,if((x==-Rei)||(x==-Inf),MI+ZE, (x==Rei)||(x==Inf),ZE, x<0,MI+ZE, ZE), \\-0==-0,+0==+0,-Inf==-Inf,+Inf==+Inf,±x==±y (x==-Rei)&&(y==Rei),MI+ZE, \\-0==+0 (x==Rei)&&(y==-Rei),ZE, \\+0==-0 (x==-Inf)||(y==Inf),MI, \\-Inf<±y,±x<Inf (x==Inf)||(y==-Inf),0, \\+Inf>±y,±x>-Inf if((x==Rei)||(x==-Rei),0,x)<if((y==Rei)||(y==-Rei),0,y),MI, \\±x<±y 0)) \\±x>±y } make_fcmp()={ make_fop2to0("fcmp", "fcmp", -1, MC68881+MC68882+MC68040+FPSP040+MC68060+FPSP060, append(DATA_SPECIAL, DATA_EXTENDED, DATA_BINARY), fcmp_func) } \\---------------------------------------------------------------------------------------- \\ FCOS.X FPm,FPn \\---------------------------------------------------------------------------------------- make_fcos()={ my(y); make_fop1to1("fcos", "fcos", -2, MC68881+MC68882+FPSP040+FPSP060, append(DATA_SPECIAL, DATA_FLOAT, DATA_BASIC, DATA_ROUND, DATA_ZERO_PLUS, DATA_TRIGONOMETRIC), (x,rp,rm)->if(type(x)=="t_POL", if(x==-Inf,fpsr=bitor(fpsr,OE);NaN, \\cos(-Inf)=NaN,OE x==-Rei,1, \\cos(-0)=1 x==Rei,1, \\cos(+0)=1 x==Inf,fpsr=bitor(fpsr,OE);NaN, \\cos(+Inf)=NaN,OE NaN), fpsr=bitor(fpsr,X2); y=roundxxx(cos(x),rp,rm); if(type(y)!="t_POL", if(y==1,if((rm==RZ)||(rm==RM),y=nextdown(1,rp))); if(y==-1,if((rm==RZ)||(rm==RP),y=nextup(1,rp)))); xxx(y,rp,rm))) } \\---------------------------------------------------------------------------------------- \\ FCOSH.X FPm,FPn \\---------------------------------------------------------------------------------------- make_fcosh()={ my(y); make_fop1to1("fcosh", "fcosh", -2, MC68881+MC68882+FPSP040+FPSP060, append(DATA_SPECIAL, DATA_FLOAT, DATA_BASIC, DATA_ROUND, DATA_ZERO_PLUS), (x,rp,rm)->if(type(x)=="t_POL", if(x==-Inf,Inf, \\cosh(-Inf)=Inf x==-Rei,1, \\cosh(-0)=1 x==Rei,1, \\cosh(+0)=1 x==Inf,Inf, \\cosh(+Inf)=Inf NaN), fpsr=bitor(fpsr,X2); if(x<=-65536,fpsr=bitor(fpsr,OF);xxx(Inf,rp,rm), \\cosh(-big)=+Inf,OF 65536<=x,fpsr=bitor(fpsr,OF);xxx(Inf,rp,rm), \\cosh(+big)=+Inf,OF y=roundxxx(cosh(x),rp,rm); if(type(x)!="t_POL", if(rm==RP,if(y==1,y=nextup(1,rp)))); xxx(y,rp,rm)))) } \\---------------------------------------------------------------------------------------- \\ FDABS.X FPm,FPn \\---------------------------------------------------------------------------------------- make_fdabs()={ make_fop1to1("fdabs", "fdabs", -1, MC68040+FPSP040+MC68060+FPSP060, append(DATA_SPECIAL, DATA_FLOAT, DATA_BASIC, DATA_ROUND), (x,rp,rm)->if(type(x)=="t_POL", if(x==-Inf,Inf, \\dabs(-Inf)=+Inf x==-Rei,Rei, \\dabs(-0)=+0 x==Rei,Rei, \\dabs(+0)=+0 x==Inf,Inf, \\dabs(+Inf)=+Inf NaN), dbl(abs(x),rm))) } \\---------------------------------------------------------------------------------------- \\ FDADD.X FPm,FPn \\---------------------------------------------------------------------------------------- fdadd_func(x,y,rp,rm)={ my(z); if(x==0,x=Rei); if(y==0,y=Rei); if((x==NaN)||(y==NaN),NaN, (x==Inf)&&(y==-Inf),fpsr=bitor(fpsr,OE);NaN, \\(+Inf)+(-Inf)=NaN,OE (x==-Inf)&&(y==Inf),fpsr=bitor(fpsr,OE);NaN, \\(-Inf)+(+Inf)=NaN,OE (x==Rei)&&(y==Rei),Rei, \\(+0)+(+0)=+0 (x==-Rei)&&(y==-Rei),-Rei, \\(-0)+(-0)=-0 (x==Rei)&&(y==-Rei),if(rm==RM,-Rei,Rei), \\(+0)+(-0)=±0 (x==-Rei)&&(y==Rei),if(rm==RM,-Rei,Rei), \\(-0)+(+0)=±0 (y==Inf)||(y==-Inf),y, \\(±x)+(±Inf)=±Inf (x==Inf)||(x==-Inf),x, \\(±Inf)+(±y)=±Inf (y==Rei)||(y==-Rei),dbl(x,rm), \\(±x)+(±0)=(±x) (x==Rei)||(x==-Rei),dbl(y,rm), \\(±0)+(±y)=±y z=x+y; if(z==0, if(rm==RM,-Rei,Rei), dbl(z,rm))) } make_fdadd()={ make_fop2to1("fdadd", "fdadd", -1, MC68040+FPSP040+MC68060+FPSP060, append(DATA_SPECIAL, DATA_EXTENDED, DATA_BINARY), fdadd_func) } \\---------------------------------------------------------------------------------------- \\ FDBcc Dr,<label> \\---------------------------------------------------------------------------------------- make_fdbcc060()={ my(m,z,n,a,hh,ll); print("making fdbcc060"); asm( " ;-------------------------------------------------------------------------------- ; FDBcc Dr,<label> ;-------------------------------------------------------------------------------- .cpu 68030 regs reg d0-d7/a0-a5 cregs reg fpcr/fpsr/fpiar fregs reg fp0-fp7 .offsym 0,_a6 _size: _regs: .ds.b .sizeof.(regs) _fregs: .ds.b .sizeof.(fregs) _cregs: .ds.b .sizeof.(cregs) _a6: .ds.l 1 _pc: .ds.l 1 .text .even fdbcc060_test:: link.w a6,#_size movem.l regs,(_regs,a6) fmovem.l cregs,(_cregs,a6) fmovem.x fregs,(_fregs,a6) ; move.l #FPSP060,-(sp) peamsg 'FDBCC DR,<LABEL>' jbsr mnemonic_start addq.l #8,sp beq 99f putmsg 'test: FDBcc Dr,<label>',13,10 ;------------------------------------------------ ; d1 actual result ; d2 actual count ; d3 actual status ; d4 source count ; d5 cc=0..31 ; d6 fpsr=(mzin=0..15)<<24 ; d7 0=failed,1=successful ; a0 expected result,expected count,expected status,... ; a1 expected result ; a2 expected count ; a3 expected status ; a4 source count,... ;------------------------------------------------ lea.l push_decompressed,a3 ;decompress data move.l a3,-(sp) pea.l fdbcc060_data_compressed jbsr decompress addq.l #8,sp @@: addq.l #4,a3 ;source count tst.l (a3) bne @b addq.l #4,a3 ;0 movea.l a3,a0 ;expected result,expected count,expected status,... ; move.l #0<<24,d6 ;fpsr=(mzin=0..15)<<24 66: moveq.l #0,d5 ;cc=0..31 55: lea.l push_decompressed,a4 ;source count,... 44: ;FDBcc Dr=count,<forward-label> fmove.l #0,fpcr fmove.l d6,fpsr ;fpsr move.l (a4),d4 ;source count move.l d4,d2 ;actual count jsr ([fdbcc060_execute_forward,za0,d5.l*4]) ;EXECUTE ;actual result ;actual count fmove.l fpsr,d3 ;actual status ; movem.l (a0),a1-a3 ;expected result,expected count,expected status ; movem.l d1-d3/a1-a3,-(sp) ;actual result,actual count,actual status,expected result,expected count,expected status jbsr test_double lea.l 24(sp),sp move.l d0,d7 ;0=failed,1=successful ; move.l d7,-(sp) ;0=failed,1=successful jbsr statistics_update addq.l #4,sp beq @f ;not output ;output putmsg 'FDB' putstr (uppercase_cc,za0,d5.l*4) putmsg ' Dr=' puthex8 d4 ;source count putmsg ',<forward-label> @' move.l d6,-(sp) ;fpsr jbsr printfpsr addq.l #4,sp putcrlf move.l d7,-(sp) ;0=failed,1=successful movem.l d1-d3/a1-a3,-(sp) ;actual result,actual count,actual status,expected result,expected count,expected status jbsr output_double lea.l 28(sp),sp @@: ; ;FDBcc Dr=count,<backward-label> fmove.l #0,fpcr fmove.l d6,fpsr ;fpsr move.l (a4),d4 ;source count move.l d4,d2 ;actual count jsr ([fdbcc060_execute_backward,za0,d5.l*4]) ;EXECUTE ;actual result ;actual count fmove.l fpsr,d3 ;actual status ; movem.l (a0),a1-a3 ;expected result,expected count,expected status ; movem.l d1-d3/a1-a3,-(sp) ;actual result,actual count,actual status,expected result,expected count,expected status jbsr test_double lea.l 24(sp),sp move.l d0,d7 ;0=failed,1=successful ; move.l d7,-(sp) ;0=failed,1=successful jbsr statistics_update addq.l #4,sp beq @f ;not output ;output putmsg 'FDB' putstr (uppercase_cc,za0,d5.l*4) putmsg ' Dr=' puthex8 d4 ;source count putmsg ',<backward-label> @' move.l d6,-(sp) ;fpsr jbsr printfpsr addq.l #4,sp putcrlf move.l d7,-(sp) ;0=failed,1=successful movem.l d1-d3/a1-a3,-(sp) ;actual result,actual count,actual status,expected result,expected count,expected status jbsr output_double lea.l 28(sp),sp @@: ; lea.l (12,a0),a0 ;expected result,expected count,expected status,... ; addq.l #4,a4 ;source count tst.l (a4) ;source count,... bne 44b ; addq.w #1,d5 ;cc++ cmp.w #31,d5 ;cc=0..31 bls 55b ; add.l #1<<24,d6 ;mzin++ cmp.l #15<<24,d6 ;fpsr=(mzin=0..15)<<24 bls 66b ; jbsr mnemonic_end 99: fmovem.x (_fregs,a6),fregs fmovem.l (_cregs,a6),cregs movem.l (_regs,a6),regs unlk a6 rts .align 4 fdbcc060_execute_forward:: .irp cc,F,EQ,OGT,OGE,OLT,OLE,OGL,OR,UN,UEQ,UGT,UGE,ULT,ULE,NE,T,SF,SEQ,GT,GE,LT,LE,GL,GLE,NGLE,NGL,NLE,NLT,NGE,NGT,SNE,ST .dc.l fdbcc060_execute_forward_&cc .endm fdbcc060_execute_backward:: .irp cc,F,EQ,OGT,OGE,OLT,OLE,OGL,OR,UN,UEQ,UGT,UGE,ULT,ULE,NE,T,SF,SEQ,GT,GE,LT,LE,GL,GLE,NGLE,NGL,NLE,NLT,NGE,NGT,SNE,ST .dc.l fdbcc060_execute_backward_&cc .endm .irp cc,F,EQ,OGT,OGE,OLT,OLE,OGL,OR,UN,UEQ,UGT,UGE,ULT,ULE,NE,T,SF,SEQ,GT,GE,LT,LE,GL,GLE,NGLE,NGL,NLE,NLT,NGE,NGT,SNE,ST fdbcc060_execute_forward_&cc:: moveq.l #2,d1 ;actual result. 2=too long FDB&cc d2,@f ;EXECUTE moveq.l #0,d1 ;actual result. 0=not taken rts subq.l #2,d1 ;actual result. -1=too short(forward)/too long(backward) @@: subq.l #1,d1 ;actual result. 1=taken rts fdbcc060_execute_backward_&cc:: moveq.l #2,d1 ;actual result. 2=too short FDB&cc d2,@b ;EXECUTE moveq.l #0,d1 ;actual result. 0=not taken rts .endm .cpu 68000 .align 4 fdbcc060_data_compressed:: "); push_start(); \\source count,... for(h=0,5, hh=if(h<2,h,h<5,0x7FFD+h,0xFFFF); \\$0000,$0001,$7FFF,$8000,$8001,$FFFF for(l=0,5, ll=if(l<2,l,l<5,0x7FFD+l,0xFFFF); \\$0000,$0001,$7FFF,$8000,$8001,$FFFF push(4,(hh<<16)+ll))); push(4,0); \\expected result,expected count,expected status,... for(mzin=0,15, m=bitand(mzin>>3,1); z=bitand(mzin>>2,1); n=bitand(mzin>>0,1); a=[ 0, \\000000 F z, \\000001 EQ !(n||z||m), \\000010 OGT z||!(n||m), \\000011 OGE m&&!(n||z), \\000100 OLT z||(m&&!n), \\000101 OLE !(n||z), \\000110 OGL !n, \\000111 OR n, \\001000 UN n||z, \\001001 UEQ n||!(m||z), \\001010 UGT n||(z||!m), \\001011 UGE n||(m&&!z), \\001100 ULT n||z||m, \\001101 ULE !z, \\001110 NE 1 \\001111 T ]; for(cc=0,15, for(h=0,5, hh=if(h<2,h,h<5,0x7FFD+h,0xFFFF); \\$0000,$0001,$7FFF,$8000,$8001,$FFFF for(l=0,5, ll=if(l<2,l,l<5,0x7FFD+l,0xFFFF); \\$0000,$0001,$7FFF,$8000,$8001,$FFFF push(4,!a[1+cc]&&(ll!=0)); \\expected result. 0=not taken,1=taken push(4,(hh<<16)+if(a[1+cc],ll,bitand(0xFFFF,ll-1))); \\expected count push(4,mzin<<24)))); \\expected status for(cc=16,31, for(h=0,5, hh=if(h<2,h,h<5,0x7FFD+h,0xFFFF); \\$0000,$0001,$7FFF,$8000,$8001,$FFFF for(l=0,5, ll=if(l<2,l,l<5,0x7FFD+l,0xFFFF); \\$0000,$0001,$7FFF,$8000,$8001,$FFFF push(4,!a[1+cc-16]&&(ll!=0)); \\expected result. 0=not taken,1=taken push(4,(hh<<16)+if(a[1+cc-16],ll,bitand(0xFFFF,ll-1))); \\expected count push(4,(mzin<<24)+if(n,BS+AV,0)))))); \\expected status push(4,-1); push_end() } make_fdbcc88x()={ my(m,z,n,a,hh,ll); print("making fdbcc88x"); asm( " ;-------------------------------------------------------------------------------- ; FDBcc Dr,<label> ;-------------------------------------------------------------------------------- .cpu 68030 regs reg d0-d7/a0-a5 cregs reg fpcr/fpsr/fpiar fregs reg fp0-fp7 .offsym 0,_a6 _size: _regs: .ds.b .sizeof.(regs) _fregs: .ds.b .sizeof.(fregs) _cregs: .ds.b .sizeof.(cregs) _a6: .ds.l 1 _pc: .ds.l 1 .text .even fdbcc88x_test:: link.w a6,#_size movem.l regs,(_regs,a6) fmovem.l cregs,(_cregs,a6) fmovem.x fregs,(_fregs,a6) ; move.l #MC68881+MC68882+MC68040+FPSP040,-(sp) peamsg 'FDBCC DR,<LABEL>' jbsr mnemonic_start addq.l #8,sp beq 99f putmsg 'test: FDBcc Dr,<label>',13,10 ;------------------------------------------------ ; d1 actual result ; d2 actual count ; d3 actual status ; d4 source count ; d5 cc=0..31 ; d6 fpsr=(mzin=0..15)<<24 ; d7 0=failed,1=successful ; a0 expected result,expected count,expected status,... ; a1 expected result ; a2 expected count ; a3 expected status ; a4 source count,... ;------------------------------------------------ lea.l push_decompressed,a3 ;decompress data move.l a3,-(sp) pea.l fdbcc88x_data_compressed jbsr decompress addq.l #8,sp @@: addq.l #4,a3 ;source count tst.l (a3) bne @b addq.l #4,a3 ;0 movea.l a3,a0 ;expected result,expected count,expected status,... ; move.l #0<<24,d6 ;fpsr=(mzin=0..15)<<24 66: moveq.l #0,d5 ;cc=0..31 55: lea.l push_decompressed,a4 ;source count,... 44: ;FDBcc Dr,<forward-label> fmove.l #0,fpcr fmove.l d6,fpsr ;fpsr move.l (a4),d4 ;source count move.l d4,d2 ;actual count jsr ([fdbcc88x_execute_forward,za0,d5.l*4]) ;EXECUTE ;actual result ;actual count fmove.l fpsr,d3 ;actual status ; movem.l (a0),a1-a3 ;expected result,expected count,expected status ; movem.l d1-d3/a1-a3,-(sp) ;actual result,actual count,actual status,expected result,expected count,expected status jbsr test_double lea.l 24(sp),sp move.l d0,d7 ;0=failed,1=successful ; move.l d7,-(sp) ;0=failed,1=successful jbsr statistics_update addq.l #4,sp beq @f ;not output ;output putmsg 'FDB' putstr (uppercase_cc,za0,d5.l*4) putmsg ' Dr=' puthex8 d4 ;source count putmsg ',<forward-label> @' move.l d6,-(sp) ;fpsr jbsr printfpsr addq.l #4,sp putcrlf move.l d7,-(sp) ;0=failed,1=successful movem.l d1-d3/a1-a3,-(sp) ;actual result,actual count,actual status,expected result,expected count,expected status jbsr output_double lea.l 28(sp),sp @@: ; ;FDBcc Dr,<backward-label> fmove.l #0,fpcr fmove.l d6,fpsr ;fpsr move.l (a4),d4 ;source count move.l d4,d2 ;actual count jsr ([fdbcc88x_execute_backward,za0,d5.l*4]) ;EXECUTE ;actual result ;actual count fmove.l fpsr,d3 ;actual status ; movem.l (a0),a1-a3 ;expected result,expected count,expected status ; movem.l d1-d3/a1-a3,-(sp) ;actual result,actual count,actual status,expected result,expected count,expected status jbsr test_double lea.l 24(sp),sp move.l d0,d7 ;0=failed,1=successful ; move.l d7,-(sp) ;0=failed,1=successful jbsr statistics_update addq.l #4,sp beq @f ;not output ;output putmsg 'FDB' putstr (uppercase_cc,za0,d5.l*4) putmsg ' Dr=' puthex8 d4 ;source count putmsg ',<backward-label> @' move.l d6,-(sp) ;fpsr jbsr printfpsr addq.l #4,sp putcrlf move.l d7,-(sp) ;0=failed,1=successful movem.l d1-d3/a1-a3,-(sp) ;actual result,actual count,actual status,expected result,expected count,expected status jbsr output_double lea.l 28(sp),sp @@: ; lea.l (12,a0),a0 ;expected result,expected count,expected status,... ; addq.l #4,a4 ;source count tst.l (a4) ;source count,... bne 44b ; addq.w #1,d5 ;cc++ cmp.w #31,d5 ;cc=0..31 bls 55b ; add.l #1<<24,d6 ;mzin++ cmp.l #15<<24,d6 ;fpsr=(mzin=0..15)<<24 bls 66b ; jbsr mnemonic_end 99: fmovem.x (_fregs,a6),fregs fmovem.l (_cregs,a6),cregs movem.l (_regs,a6),regs unlk a6 rts .align 4 fdbcc88x_execute_forward:: .irp cc,F,EQ,OGT,OGE,OLT,OLE,OGL,OR,UN,UEQ,UGT,UGE,ULT,ULE,NE,T,SF,SEQ,GT,GE,LT,LE,GL,GLE,NGLE,NGL,NLE,NLT,NGE,NGT,SNE,ST .dc.l fdbcc88x_execute_forward_&cc .endm fdbcc88x_execute_backward:: .irp cc,F,EQ,OGT,OGE,OLT,OLE,OGL,OR,UN,UEQ,UGT,UGE,ULT,ULE,NE,T,SF,SEQ,GT,GE,LT,LE,GL,GLE,NGLE,NGL,NLE,NLT,NGE,NGT,SNE,ST .dc.l fdbcc88x_execute_backward_&cc .endm .irp cc,F,EQ,OGT,OGE,OLT,OLE,OGL,OR,UN,UEQ,UGT,UGE,ULT,ULE,NE,T,SF,SEQ,GT,GE,LT,LE,GL,GLE,NGLE,NGL,NLE,NLT,NGE,NGT,SNE,ST fdbcc88x_execute_forward_&cc:: moveq.l #2,d1 ;actual result. 2=too long FDB&cc d2,@f ;EXECUTE moveq.l #0,d1 ;actual result. 0=not taken rts subq.l #2,d1 ;actual result. -1=too short(forward)/too long(backward) @@: subq.l #1,d1 ;actual result. 1=taken rts fdbcc88x_execute_backward_&cc:: moveq.l #2,d1 ;actual result. 2=too short FDB&cc d2,@b ;EXECUTE moveq.l #0,d1 ;actual result. 0=not taken rts .endm .cpu 68000 .align 4 fdbcc88x_data_compressed:: "); push_start(); \\source count,... for(h=0,5, hh=if(h<2,h,h<5,0x7FFD+h,0xFFFF); \\$0000,$0001,$7FFF,$8000,$8001,$FFFF for(l=0,5, ll=if(l<2,l,l<5,0x7FFD+l,0xFFFF); \\$0000,$0001,$7FFF,$8000,$8001,$FFFF push(4,(hh<<16)+ll))); push(4,0); \\expected result,expected count,expected status,... for(mzin=0,15, m=bitand(mzin>>3,1); z=bitand(mzin>>2,1); n=bitand(mzin>>0,1); a=[ 0, \\000000 F z, \\000001 EQ !(n||z||m), \\000010 OGT z||!(n||m), \\000011 OGE m&&!(n||z), \\000100 OLT z||(m&&!n), \\000101 OLE !(n||z), \\000110 OGL z||!n, \\000111 OR n, \\001000 UN n||z, \\001001 UEQ n||!(m||z), \\001010 UGT n||(z||!m), \\001011 UGE n||(m&&!z), \\001100 ULT n||z||m, \\001101 ULE n||!z, \\001110 NE 1 \\001111 T ]; for(cc=0,15, for(h=0,5, hh=if(h<2,h,h<5,0x7FFD+h,0xFFFF); \\$0000,$0001,$7FFF,$8000,$8001,$FFFF for(l=0,5, ll=if(l<2,l,l<5,0x7FFD+l,0xFFFF); \\$0000,$0001,$7FFF,$8000,$8001,$FFFF push(4,!a[1+cc]&&(ll!=0)); \\expected result. 0=not taken,1=taken push(4,(hh<<16)+if(a[1+cc],ll,bitand(0xFFFF,ll-1))); \\expected count push(4,mzin<<24)))); \\expected status for(cc=16,31, for(h=0,5, hh=if(h<2,h,h<5,0x7FFD+h,0xFFFF); \\$0000,$0001,$7FFF,$8000,$8001,$FFFF for(l=0,5, ll=if(l<2,l,l<5,0x7FFD+l,0xFFFF); \\$0000,$0001,$7FFF,$8000,$8001,$FFFF push(4,!a[1+cc-16]&&(ll!=0)); \\expected result. 0=not taken,1=taken push(4,(hh<<16)+if(a[1+cc-16],ll,bitand(0xFFFF,ll-1))); \\expected count push(4,(mzin<<24)+if(n,BS+AV,0)))))); \\expected status push(4,-1); push_end() } \\---------------------------------------------------------------------------------------- \\ FDDIV.X FPm,FPn \\---------------------------------------------------------------------------------------- make_fddiv()={ make_fop2to1("fddiv", "fddiv", -1, MC68040+FPSP040+MC68060+FPSP060, append(DATA_SPECIAL, DATA_EXTENDED, DATA_BINARY), (x,y,rp,rm)->if((x==NaN)||(y==NaN),NaN, ((x==Rei)||(x==-Rei))&&((y==Rei)||(y==-Rei)),fpsr=bitor(fpsr,OE);NaN, \\(±0)/(±0)=NaN,OE ((x==Inf)||(x==-Inf))&&((y==Inf)||(y==-Inf)),fpsr=bitor(fpsr,OE);NaN, \\(±Inf)/(±Inf)=NaN,OE ((x==Inf)||(x==-Inf))&&((y==Rei)||(y==-Rei)),if(x==Inf,1,-1)*if(y==Rei,1,-1)*Inf, \\(±Inf)/(±0)=±Inf,non-DZ ((x==Rei)||(x==-Rei))&&((y==Inf)||(y==-Inf)),if(x==Rei,1,-1)*if(y==Inf,1,-1)*Rei, \\(±0)/(±Inf)=±0 (y==Rei)||(y==-Rei),fpsr=bitor(fpsr,DZ);sign(x)*if(y==Rei,1,-1)*Inf, \\(±x)/(±0)=±Inf,DZ (y==Inf)||(y==-Inf),sign(x)*if(y==Inf,1,-1)*Rei, \\(±x)/(±Inf)=±0 (x==Rei)||(x==-Rei),if(x==Rei,1,-1)*sign(y)*Rei, \\(±0)/(±y)=±0 (x==Inf)||(x==-Inf),if(x==Inf,1,-1)*sign(y)*Inf, \\(±Inf)/(±y)=±Inf dbl(x/y,rm))) } \\---------------------------------------------------------------------------------------- \\ FDIV.X FPm,FPn \\---------------------------------------------------------------------------------------- make_fdiv()={ make_fop2to1("fdiv", "fdiv", -1, MC68881+MC68882+MC68040+FPSP040+MC68060+FPSP060, append(DATA_SPECIAL, DATA_EXTENDED, DATA_BINARY), (x,y,rp,rm)->if((x==NaN)||(y==NaN),NaN, ((x==Rei)||(x==-Rei))&&((y==Rei)||(y==-Rei)),fpsr=bitor(fpsr,OE);NaN, \\(±0)/(±0)=NaN,OE ((x==Inf)||(x==-Inf))&&((y==Inf)||(y==-Inf)),fpsr=bitor(fpsr,OE);NaN, \\(±Inf)/(±Inf)=NaN,OE ((x==Inf)||(x==-Inf))&&((y==Rei)||(y==-Rei)),if(x==Inf,1,-1)*if(y==Rei,1,-1)*Inf, \\(±Inf)/(±0)=±Inf,non-DZ ((x==Rei)||(x==-Rei))&&((y==Inf)||(y==-Inf)),if(x==Rei,1,-1)*if(y==Inf,1,-1)*Rei, \\(±0)/(±Inf)=±0 (y==Rei)||(y==-Rei),fpsr=bitor(fpsr,DZ);sign(x)*if(y==Rei,1,-1)*Inf, \\(±x)/(±0)=±Inf,DZ (y==Inf)||(y==-Inf),sign(x)*if(y==Inf,1,-1)*Rei, \\(±x)/(±Inf)=±0 (x==Rei)||(x==-Rei),if(x==Rei,1,-1)*sign(y)*Rei, \\(±0)/(±y)=±0 (x==Inf)||(x==-Inf),if(x==Inf,1,-1)*sign(y)*Inf, \\(±Inf)/(±y)=±Inf xxx2(x/y,rp,rm))) } \\---------------------------------------------------------------------------------------- \\ FDMOVE.X FPm,FPn \\---------------------------------------------------------------------------------------- make_fdmove()={ make_fop1to1("fdmove", "fdmove", -1, MC68040+FPSP040+MC68060+FPSP060, append(DATA_SPECIAL, DATA_FLOAT, DATA_BASIC, DATA_ROUND), (x,rp,rm)->if(type(x)=="t_POL", if(x==-Inf,-Inf, \\dmove(-Inf)=-Inf x==-Rei,-Rei, \\dmove(-0)=-0 x==Rei,Rei, \\dmove(+0)=+0 x==Inf,Inf, \\dmove(+Inf)=+Inf NaN), dbl(x,rm))) } \\---------------------------------------------------------------------------------------- \\ FDMUL.X FPm,FPn \\---------------------------------------------------------------------------------------- make_fdmul()={ make_fop2to1("fdmul", "fdmul", -1, MC68040+FPSP040+MC68060+FPSP060, append(DATA_SPECIAL, DATA_EXTENDED, DATA_BINARY), (x,y,rp,rm)->if((x==NaN)||(y==NaN),NaN, ((x==Rei)||(x==-Rei))&&((y==Inf)||(y==-Inf)),fpsr=bitor(fpsr,OE);NaN, \\(±0)*(±Inf)=NaN,OE ((x==Inf)||(x==-Inf))&&((y==Rei)||(y==-Rei)),fpsr=bitor(fpsr,OE);NaN, \\(±Inf)*(±0)=NaN,OE ((x==Rei)||(x==-Rei))&&((y==Rei)||(y==-Rei)),if(x==Rei,1,-1)*if(y==Rei,1,-1)*Rei, \\(±0)*(±0)=±0 ((x==Inf)||(x==-Inf))&&((y==Inf)||(y==-Inf)),if(x==Inf,1,-1)*if(y==Inf,1,-1)*Inf, \\(±Inf)*(±Inf)=±Inf (y==Rei)||(y==-Rei),sign(x)*if(y==Rei,1,-1)*Rei, \\(±x)*(±0)=±0 (y==Inf)||(y==-Inf),sign(x)*if(y==Inf,1,-1)*Inf, \\(±x)*(±Inf)=±Inf (x==Rei)||(x==-Rei),if(x==Rei,1,-1)*sign(y)*Rei, \\(±0)*(±y)=±0 (x==Inf)||(x==-Inf),if(x==Inf,1,-1)*sign(y)*Inf, \\(±Inf)*(±y)=±Inf dbl(x*y,rm))); } \\---------------------------------------------------------------------------------------- \\ FDNEG.X FPm,FPn \\---------------------------------------------------------------------------------------- make_fdneg()={ make_fop1to1("fdneg", "fdneg", -1, MC68040+FPSP040+MC68060+FPSP060, append(DATA_SPECIAL, DATA_FLOAT, DATA_BASIC, DATA_ROUND), (x,rp,rm)->if(type(x)=="t_POL", if(x==-Inf,Inf, \\dneg(-Inf)=+Inf x==-Rei,Rei, \\dneg(-0)=+0 x==Rei,-Rei, \\dneg(+0)=-0 x==Inf,-Inf, \\dneg(+Inf)=-Inf NaN), dbl(-x,rm))) } \\---------------------------------------------------------------------------------------- \\ FDSQRT.X FPm,FPn