FEFunction.java
     1: //========================================================================================
     2: //  FEFunction.java
     3: //    en:FE function
     4: //    ja:FEファンクション
     5: //  Copyright (C) 2003-2024 Makoto Kamada
     6: //
     7: //  This file is part of the XEiJ (X68000 Emulator in Java).
     8: //  You can use, modify and redistribute the XEiJ if the conditions are met.
     9: //  Read the XEiJ License for more details.
    10: //  https://stdkmd.net/xeij/
    11: //========================================================================================
    12: 
    13: //----------------------------------------------------------------------------------------
    14: //  FEファンクションコール(オペコード0xfe00~0xfeff)をMPUの命令として処理することで高速化する
    15: //  line 1111 emulator/privilege violation例外が発生しないのでFLOATn.Xが組み込まれていてもFLOATn.Xのルーチンは使用されない
    16: //----------------------------------------------------------------------------------------
    17: 
    18: package xeij;
    19: 
    20: import java.lang.*;  //Boolean,Character,Class,Comparable,Double,Exception,Float,IllegalArgumentException,Integer,Long,Math,Number,Object,Runnable,SecurityException,String,StringBuilder,System
    21: 
    22: public class FEFunction {
    23: 
    24:   public static final boolean FPK_DEBUG_TRACE = false;
    25: 
    26:   public static final int FPK_CLOCK = 80;  //一律に80サイクルかかることにする
    27: 
    28:   public static final boolean FPK_FPCP_NAN = true;  //true=JavaのNaN(0x7ff8000000000000L,0x7fc00000)をFPCPのNaN(0x7fffffffffffffffL,0x7fffffff)に変換する
    29: 
    30:   public static boolean fpkOn;  //true=FEファンクションコールを命令として処理する
    31: 
    32:   //  Human68kのline 1111 emulator/privilege violation例外処理ルーチンの手前にFLOATn.Xのマジック'FEfn'を押し込む
    33:   //  CONFIG.SYSにFLOATn.Xが書いてあっても「すでに浮動小数点演算パッケージは登録されています」と表示されて組み込まれなくなる
    34:   //  FLOATn.Xを組み込んでもFEファンクションが命令として処理されることに変わりはないが、
    35:   //  FLOATn.Xを組み込まなければFライン例外がFLOATn.Xを通らなくなるのでDOSコールのオーバーヘッドが少なくなる
    36:   public static boolean fpkRejectFloatOn;  //true=FLOATn.Xを組み込まない
    37: 
    38:   public static void fpkInit () {
    39:     fpkOn = Settings.sgsGetOnOff ("fefunc");  //FEファンクション命令
    40:     fpkRejectFloatOn = Settings.sgsGetOnOff ("rejectfloat");  //FLOATn.Xを組み込まない
    41:   }  //fpkInit()
    42: 
    43: 
    44: 
    45:   public static final int[] fpkRndTable = new int[55];
    46:   public static int fpkRndPointer = -1;
    47: 
    48:   //fpkRndInit ()
    49:   //  rnd()乱数列の初期化
    50:   public static void fpkRndInit (int t) {
    51:     for (int i = 0; i < 55; i++) {
    52:       t = (char) t * 15625 + 1;  //15625=5^6
    53:       fpkRndTable[i] = t << 16 | (char) t;
    54:     }
    55:     fpkRndPointer = 54;
    56:     fpkRndShuffle ();
    57:     fpkRndShuffle ();
    58:     fpkRndShuffle ();
    59:   }  //fpkRndInit()
    60: 
    61:   //fpkRndShuffle ()
    62:   //  rnd()乱数列の更新
    63:   public static void fpkRndShuffle () {
    64:     for (int i = 0; i < 24; i++) {
    65:       fpkRndTable[i] -= fpkRndTable[i + 31];
    66:     }
    67:     for (int i = 24; i < 55; i++) {
    68:       fpkRndTable[i] -= fpkRndTable[i - 24];
    69:     }
    70:   }  //fpkRndShuffle()
    71: 
    72:   //rnd = fpkRndLong ()
    73:   //  rnd()乱数列の取り出し
    74:   public static int fpkRndLong () {
    75:     int i = fpkRndPointer;
    76:     if (i < 0) {
    77:       fpkRndInit (111);
    78:       i = fpkRndPointer;
    79:     }
    80:     if (i == 54) {
    81:       fpkRndShuffle ();
    82:       i = 0;
    83:     } else {
    84:       i++;
    85:     }
    86:     fpkRndPointer = i;
    87:     return fpkRndTable[i];
    88:   }  //fpkRndLong()
    89: 
    90: 
    91: 
    92:   public static final short[] fpkRandTable = new short[55];
    93:   public static int fpkRandPointer = -1;
    94: 
    95:   //fpkRandInit (t)
    96:   //  rand()乱数列の初期化
    97:   public static void fpkRandInit (int t) {
    98:     for (int i = 0; i < 55; i++) {
    99:       t = (char) t * 15625 + 1;
   100:       fpkRandTable[i] = (short) t;
   101:     }
   102:     fpkRandPointer = 54;
   103:     fpkRandShuffle ();
   104:   }  //fpkRandInit(int)
   105: 
   106:   //fpkRandShuffle ()
   107:   //  rand()乱数列の更新
   108:   public static void fpkRandShuffle () {
   109:     for (int i = 0; i < 24; i++) {
   110:       fpkRandTable[i] -= fpkRandTable[i + 31];
   111:     }
   112:     for (int i = 24; i < 55; i++) {
   113:       fpkRandTable[i] -= fpkRandTable[i - 24];
   114:     }
   115:   }  //fpkRandShuffle()
   116: 
   117:   //rand = fpkRandShort ()
   118:   //  rand()乱数列の取り出し
   119:   public static short fpkRandShort () {
   120:     int i = fpkRandPointer;
   121:     if (i < 0) {
   122:       fpkRandInit (51);
   123:       i = fpkRandPointer;
   124:     }
   125:     if (i == 54) {
   126:       fpkRandShuffle ();
   127:       i = 0;
   128:     } else {
   129:       i++;
   130:     }
   131:     fpkRandPointer = i;
   132:     return fpkRandTable[i];
   133:   }  //fpkRandShort()
   134: 
   135:   //10^(±16^q*r)のテーブル
   136:   //  10進数の指数部を4bitずつ分割して10^(±16^q*r)のテーブルを参照する
   137:   //  4bitずつ分割するのは誤差を減らすため
   138:   //  3bitずつ分割しても3分割に変わりないが非正規化数の最小値4.94e-324を処理するときに1.0e+320が必要になるので不可
   139:   //  一般的には10進数の指数部を1bitずつ分割して10^(±2^q)のテーブルを参照することが多い
   140:   //  誤差を小さくしたければ分割せずに直接10^(±r)のテーブルを参照する方法もある。doubleならば高々600個余りである
   141:   public static final double[] FPK_TEN_P16QR = {
   142:     //  perl -e "for$i(0..33){$q=$i>>4;$r=$i&15;printf'    1.0e+%d,  //10^(16^%d*%d)%c',16**$q*$r,$q,$r,10}"
   143:     1.0e+0,  //10^(16^0*0)
   144:     1.0e+1,  //10^(16^0*1)
   145:     1.0e+2,  //10^(16^0*2)
   146:     1.0e+3,  //10^(16^0*3)
   147:     1.0e+4,  //10^(16^0*4)
   148:     1.0e+5,  //10^(16^0*5)
   149:     1.0e+6,  //10^(16^0*6)
   150:     1.0e+7,  //10^(16^0*7)
   151:     1.0e+8,  //10^(16^0*8)
   152:     1.0e+9,  //10^(16^0*9)
   153:     1.0e+10,  //10^(16^0*10)
   154:     1.0e+11,  //10^(16^0*11)
   155:     1.0e+12,  //10^(16^0*12)
   156:     1.0e+13,  //10^(16^0*13)
   157:     1.0e+14,  //10^(16^0*14)
   158:     1.0e+15,  //10^(16^0*15)
   159:     1.0e+0,  //10^(16^1*0)
   160:     1.0e+16,  //10^(16^1*1)
   161:     1.0e+32,  //10^(16^1*2)
   162:     1.0e+48,  //10^(16^1*3)
   163:     1.0e+64,  //10^(16^1*4)
   164:     1.0e+80,  //10^(16^1*5)
   165:     1.0e+96,  //10^(16^1*6)
   166:     1.0e+112,  //10^(16^1*7)
   167:     1.0e+128,  //10^(16^1*8)
   168:     1.0e+144,  //10^(16^1*9)
   169:     1.0e+160,  //10^(16^1*10)
   170:     1.0e+176,  //10^(16^1*11)
   171:     1.0e+192,  //10^(16^1*12)
   172:     1.0e+208,  //10^(16^1*13)
   173:     1.0e+224,  //10^(16^1*14)
   174:     1.0e+240,  //10^(16^1*15)
   175:     1.0e+0,  //10^(16^2*0)
   176:     1.0e+256,  //10^(16^2*1)
   177:   };
   178:   public static final double[] FPK_TEN_M16QR = {
   179:     //  perl -e "for$i(0..33){$q=$i>>4;$r=$i&15;printf'    1.0e-%d,  //10^(-16^%d*%d)%c',16**$q*$r,$q,$r,10}"
   180:     1.0e-0,  //10^(-16^0*0)
   181:     1.0e-1,  //10^(-16^0*1)
   182:     1.0e-2,  //10^(-16^0*2)
   183:     1.0e-3,  //10^(-16^0*3)
   184:     1.0e-4,  //10^(-16^0*4)
   185:     1.0e-5,  //10^(-16^0*5)
   186:     1.0e-6,  //10^(-16^0*6)
   187:     1.0e-7,  //10^(-16^0*7)
   188:     1.0e-8,  //10^(-16^0*8)
   189:     1.0e-9,  //10^(-16^0*9)
   190:     1.0e-10,  //10^(-16^0*10)
   191:     1.0e-11,  //10^(-16^0*11)
   192:     1.0e-12,  //10^(-16^0*12)
   193:     1.0e-13,  //10^(-16^0*13)
   194:     1.0e-14,  //10^(-16^0*14)
   195:     1.0e-15,  //10^(-16^0*15)
   196:     1.0e-0,  //10^(-16^1*0)
   197:     1.0e-16,  //10^(-16^1*1)
   198:     1.0e-32,  //10^(-16^1*2)
   199:     1.0e-48,  //10^(-16^1*3)
   200:     1.0e-64,  //10^(-16^1*4)
   201:     1.0e-80,  //10^(-16^1*5)
   202:     1.0e-96,  //10^(-16^1*6)
   203:     1.0e-112,  //10^(-16^1*7)
   204:     1.0e-128,  //10^(-16^1*8)
   205:     1.0e-144,  //10^(-16^1*9)
   206:     1.0e-160,  //10^(-16^1*10)
   207:     1.0e-176,  //10^(-16^1*11)
   208:     1.0e-192,  //10^(-16^1*12)
   209:     1.0e-208,  //10^(-16^1*13)
   210:     1.0e-224,  //10^(-16^1*14)
   211:     1.0e-240,  //10^(-16^1*15)
   212:     1.0e-0,  //10^(-16^2*0)
   213:     1.0e-256,  //10^(-16^2*1)
   214:   };
   215: 
   216: 
   217: 
   218:   //fpkLMUL ()
   219:   //  $FE00  __LMUL
   220:   //  32bit符号あり整数乗算
   221:   //  <d0.l:32bit符号あり整数。被乗数x
   222:   //  <d1.l:32bit符号あり整数。乗数y
   223:   //  >d0.l:32bit符号あり整数。積x*y。オーバーフローのとき不定
   224:   //  >ccr:cs=エラーあり。cs,ne,vs=オーバーフロー
   225:   //  メモ
   226:   //    ZフラグとVフラグの変化はCZ-6BP1のマニュアルに書かれていないがX-BASICが使っている
   227:   //    FLOAT2.X 2.02/2.03とFLOAT3.X 2.03はオーバーフローのときZフラグをクリア、Vフラグをセットする
   228:   //    FLOAT4.X 1.02はオーバーフローのときZフラグとVフラグをクリアする
   229:   //      X-BASICで「print 99999*99999」が「オーバーフローしました」ではなく「アンダーフローしました」になる
   230:   public static void fpkLMUL () {
   231:     long xl = (long) XEiJ.regRn[0];
   232:     long yl = (long) XEiJ.regRn[1];
   233:     long zl = xl * yl;
   234:     int zi = (int) zl;
   235:     if ((long) zi != zl) {  //オーバーフロー
   236:       XEiJ.regRn[0] = zi;  //d0.lは不定。ここでは積の下位32bit
   237:       XEiJ.regCCR = XEiJ.REG_CCR_V | XEiJ.REG_CCR_C;
   238:     } else {
   239:       XEiJ.regRn[0] = zi;
   240:       XEiJ.regCCR = 0;
   241:     }
   242:   }  //fpkLMUL()
   243: 
   244:   //fpkLDIV ()
   245:   //  $FE01  __LDIV
   246:   //  32bit符号あり整数除算
   247:   //  <d0.l:32bit符号あり整数。被除数x
   248:   //  <d1.l:32bit符号あり整数。除数y
   249:   //  >d0.l:32bit符号あり整数。商x/y。ゼロ除算のとき不定。オーバーフローのとき$7FFFFFFF
   250:   //  >ccr:cs=エラーあり。cs,eq,vc=ゼロ除算(0/0を含む)。cs,ne,vs=オーバーフロー(-$80000000/-$00000001=+$80000000)
   251:   //  バグ
   252:   //    FLOAT2.X 2.02/2.03とFLOAT3.X 2.03は0/0のときCフラグをセットしない
   253:   //      X-BASICで「print 0/0」が「0による除算が行われました」ではなく「0」になる
   254:   //    FLOAT4.X 1.02はオーバーフローのときCフラグをセットしない
   255:   //      X-BASICで「print &H80000000/-1」が「オーバーフローしました」ではなく「-2147483648」になる
   256:   //  メモ
   257:   //    ZフラグとVフラグの変化はCZ-6BP1のマニュアルに書かれていないがX-BASICが使っている
   258:   //    FLOAT2.X 2.02/2.03とFLOAT3.X 2.03はゼロ除算(0/0を含まない)のときZフラグをセット、Vフラグをクリアする
   259:   //    FLOAT2.X 2.02/2.03とFLOAT3.X 2.03はオーバーフローのときZフラグをクリア、Vフラグをセットする
   260:   //    FLOAT4.X 1.02はゼロ除算(0/0を含む)のときZフラグとVフラグをクリアする
   261:   //      X-BASICで「print 1/0」や「print 0/0」が「0による除算が行われました」ではなく「アンダーフローしました」になる
   262:   public static void fpkLDIV () {
   263:     long xl = (long) XEiJ.regRn[0];
   264:     long yl = (long) XEiJ.regRn[1];
   265:     if (yl == 0L) {  //ゼロ除算
   266:       //d0.lは不定。ここでは変化しない
   267:       XEiJ.regCCR = XEiJ.REG_CCR_Z | XEiJ.REG_CCR_C;
   268:     } else {
   269:       long zl = xl / yl;
   270:       int zi = (int) zl;
   271:       if ((long) zi != zl) {  //オーバーフロー
   272:         XEiJ.regRn[0] = 0x7fffffff;  //d0.lは$7FFFFFFF
   273:         XEiJ.regCCR = XEiJ.REG_CCR_V | XEiJ.REG_CCR_C;
   274:       } else {
   275:         XEiJ.regRn[0] = zi;
   276:         XEiJ.regCCR = 0;
   277:       }
   278:     }
   279:   }  //fpkLDIV()
   280: 
   281:   //fpkLMOD ()
   282:   //  $FE02  __LMOD
   283:   //  32bit符号あり整数剰余算
   284:   //  <d0.l:32bit符号あり整数。被除数x
   285:   //  <d1.l:32bit符号あり整数。除数y
   286:   //  >d0.l:32bit符号あり整数。余りx%y。余りの符号は被除数の符号と同じ。ゼロ除算のとき不定
   287:   //  >ccr:cs=エラーあり。cs,eq,vc=ゼロ除算(0%0を含む)。オーバーフローすることはない
   288:   //  バグ
   289:   //    FLOAT2.X 2.02/2.03とFLOAT3.X 2.03は0%0のときCフラグをセットしない
   290:   //      X-BASICで「print 0 mod 0」が「0による除算が行われました」ではなく「0」になる
   291:   //    FLOAT4.X 1.02は-$80000000%-$00000001が-$00000001になる
   292:   //      X-BASICで「print &H80000000 mod -1」が「0」ではなく「-1」になる
   293:   //  メモ
   294:   //    ZフラグとVフラグの変化はCZ-6BP1のマニュアルに書かれていないがX-BASICが使っている
   295:   //    FLOAT2.X 2.02/2.03とFLOAT3.X 2.03はゼロ除算(0%0を含まない)のときZフラグをセット、Vフラグをクリアする
   296:   //    FLOAT4.X 1.02はゼロ除算(0%0を含む)のときZフラグとVフラグをクリアする
   297:   //      X-BASICで「print 1 mod 0」や「print 0 mod 0」が「0による除算が行われました」ではなく「アンダーフローしました」になる
   298:   public static void fpkLMOD () {
   299:     long xl = (long) XEiJ.regRn[0];
   300:     long yl = (long) XEiJ.regRn[1];
   301:     if (yl == 0L) {  //ゼロ除算
   302:       //d0.lは不定。ここでは変化しない
   303:       XEiJ.regCCR = XEiJ.REG_CCR_Z | XEiJ.REG_CCR_C;
   304:     } else {
   305:       long zl = xl % yl;
   306:       int zi = (int) zl;
   307:       XEiJ.regRn[0] = zi;
   308:       XEiJ.regCCR = 0;
   309:     }
   310:   }  //fpkLMOD()
   311: 
   312:   //fpkUMUL ()
   313:   //  $FE04  __UMUL
   314:   //  32bit符号なし整数乗算
   315:   //  <d0.l:32bit符号なし整数。被乗数x
   316:   //  <d1.l:32bit符号なし整数。乗数y
   317:   //  >d0.l:32bit符号なし整数。積x*y。オーバーフローのとき不定
   318:   //  >ccr:cs=エラーあり。cs,ne,vs=オーバーフロー
   319:   //  メモ
   320:   //    ZフラグとVフラグの変化はCZ-6BP1のマニュアルに書かれていない
   321:   //    FLOAT2.X 2.02/2.03とFLOAT3.X 2.03はオーバーフローのときZフラグをクリア、Vフラグをセットする
   322:   //    FLOAT4.X 1.02はオーバーフローのときZフラグとVフラグをクリアする
   323:   public static void fpkUMUL () {
   324:     long xl = 0xffffffffL & (long) XEiJ.regRn[0];
   325:     long yl = 0xffffffffL & (long) XEiJ.regRn[1];
   326:     long zl = xl * yl;
   327:     int zi = (int) zl;
   328:     if ((0xffffffffL & (long) zi) != zl) {  //オーバーフロー
   329:       XEiJ.regRn[0] = zi;  //d0.lは不定。ここでは積の下位32bit
   330:       XEiJ.regCCR = XEiJ.REG_CCR_V | XEiJ.REG_CCR_C;
   331:     } else {
   332:       XEiJ.regRn[0] = zi;
   333:       XEiJ.regCCR = 0;
   334:     }
   335:   }  //fpkUMUL()
   336: 
   337:   //fpkUDIV ()
   338:   //  $FE05  __UDIV
   339:   //  32bit符号なし整数除算
   340:   //  <d0.l:32bit符号なし整数。被除数x
   341:   //  <d1.l:32bit符号なし整数。除数y
   342:   //  >d0.l:32bit符号なし整数。商x/y。ゼロ除算のとき不定
   343:   //  >ccr:cs=エラーあり。cs,eq,vc=ゼロ除算(0/0を含む)。オーバーフローすることはない
   344:   //  バグ
   345:   //    FLOAT2.X 2.02/2.03とFLOAT3.X 2.03は0/0のときCフラグをセットしない
   346:   //  メモ
   347:   //    ZフラグとVフラグの変化はCZ-6BP1のマニュアルに書かれていない
   348:   //    FLOAT2.X 2.02/2.03とFLOAT3.X 2.03はゼロ除算(0/0を含まない)のときZフラグをセット、Vフラグをクリアする
   349:   //    FLOAT4.X 1.02はゼロ除算(0/0を含む)のときZフラグとVフラグをクリアする
   350:   public static void fpkUDIV () {
   351:     long xl = 0xffffffffL & (long) XEiJ.regRn[0];
   352:     long yl = 0xffffffffL & (long) XEiJ.regRn[1];
   353:     if (yl == 0L) {  //ゼロ除算
   354:       //d0.lは不定。ここでは変化しない
   355:       XEiJ.regCCR = XEiJ.REG_CCR_Z | XEiJ.REG_CCR_C;
   356:     } else {
   357:       long zl = xl / yl;
   358:       int zi = (int) zl;
   359:       XEiJ.regRn[0] = zi;
   360:       XEiJ.regCCR = 0;
   361:     }
   362:   }  //fpkUDIV()
   363: 
   364:   //fpkUMOD ()
   365:   //  $FE06  __UMOD
   366:   //  32bit符号なし整数剰余算
   367:   //  <d0.l:32bit符号なし整数。被除数x
   368:   //  <d1.l:32bit符号なし整数。除数y
   369:   //  >d0.l:32bit符号なし整数。余りx%y。ゼロ除算のとき不定
   370:   //  >ccr:cs=エラーあり。cs,eq,vc=ゼロ除算(0%0を含む)。オーバーフローすることはない
   371:   //  バグ
   372:   //    FLOAT2.X 2.02/2.03とFLOAT3.X 2.03は0%0のときCフラグをセットしない
   373:   //  メモ
   374:   //    ZフラグとVフラグの変化はCZ-6BP1のマニュアルに書かれていない
   375:   //    FLOAT2.X 2.02/2.03とFLOAT3.X 2.03はゼロ除算(0%0を含まない)のときZフラグをセット、Vフラグをクリアする
   376:   //    FLOAT4.X 1.02はゼロ除算(0%0を含む)のときZフラグとVフラグをクリアする
   377:   public static void fpkUMOD () {
   378:     long xl = 0xffffffffL & (long) XEiJ.regRn[0];
   379:     long yl = 0xffffffffL & (long) XEiJ.regRn[1];
   380:     if (yl == 0L) {  //ゼロ除算
   381:       //d0.lは不定。ここでは変化しない
   382:       XEiJ.regCCR = XEiJ.REG_CCR_Z | XEiJ.REG_CCR_C;
   383:     } else {
   384:       long zl = xl % yl;
   385:       int zi = (int) zl;
   386:       XEiJ.regRn[0] = zi;
   387:       XEiJ.regCCR = 0;
   388:     }
   389:   }  //fpkUMOD()
   390: 
   391:   //fpkIMUL ()
   392:   //  $FE08  __IMUL
   393:   //  32bit符号なし整数乗算
   394:   //  <d0.l:32bit符号なし整数。被乗数x
   395:   //  <d1.l:32bit符号なし整数。乗数y
   396:   //  >d0d1.q:64bit符号なし整数。積x*y
   397:   public static void fpkIMUL () {
   398:     long xl = 0xffffffffL & (long) XEiJ.regRn[0];
   399:     long yl = 0xffffffffL & (long) XEiJ.regRn[1];
   400:     long zl = xl * yl;
   401:     XEiJ.regRn[0] = (int) (zl >>> 32);
   402:     XEiJ.regRn[1] = (int) zl;
   403:   }  //fpkIMUL()
   404: 
   405:   //fpkIDIV ()
   406:   //  $FE09  __IDIV
   407:   //  32bit符号なし整数除算・剰余算
   408:   //  <d0.l:32bit符号なし整数。被除数x
   409:   //  <d1.l:32bit符号なし整数。除数y
   410:   //  >d0.l:32bit符号なし整数。商x/y。ゼロ除算のとき不定
   411:   //  >d1.l:32bit符号なし整数。余りx%y。ゼロ除算のとき不定
   412:   //  >ccr:cs=エラーあり。cs=ゼロ除算(0/0を含む)。オーバーフローすることはない
   413:   public static void fpkIDIV () {
   414:     long xl = 0xffffffffL & (long) XEiJ.regRn[0];
   415:     long yl = 0xffffffffL & (long) XEiJ.regRn[1];
   416:     if (yl == 0L) {  //ゼロ除算
   417:       //d0.l,d1.lは不定。ここでは変化しない
   418:       XEiJ.regCCR = XEiJ.REG_CCR_C;
   419:     } else {
   420:       long zl = xl / yl;
   421:       XEiJ.regRn[0] = (int) zl;
   422:       XEiJ.regRn[1] = (int) (xl - yl * zl);
   423:       XEiJ.regCCR = 0;
   424:     }
   425:   }  //fpkIDIV()
   426: 
   427:   //fpkRANDOMIZE ()
   428:   //  $FE0C  __RANDOMIZE
   429:   //  rnd()乱数列の初期化
   430:   //  <d0.l:乱数の種x(0~65535)
   431:   //  >d0.l:0
   432:   public static void fpkRANDOMIZE () {
   433:     fpkRndInit (XEiJ.regRn[0]);
   434:     XEiJ.regRn[0] = 0;
   435:   }  //fpkRANDOMIZE()
   436: 
   437:   //fpkSRAND ()
   438:   //  $FE0D  __SRAND
   439:   //  rand()乱数列の初期化
   440:   //  <d0.l:乱数の種x(0~65535)
   441:   //  >d0.l:0
   442:   public static void fpkSRAND () {
   443:     fpkRandInit (XEiJ.regRn[0]);
   444:     XEiJ.regRn[0] = 0;
   445:   }  //fpkSRAND()
   446: 
   447:   //fpkRAND ()
   448:   //  $FE0E  __RAND
   449:   //  整数乱数
   450:   //  >d0.l:乱数rand()(0~32767)
   451:   public static void fpkRAND () {
   452:     XEiJ.regRn[0] = fpkRandShort () & 0x7fff;
   453:   }  //fpkRAND()
   454: 
   455:   //fpkLTOD ()
   456:   //  $FE1A  __LTOD
   457:   //  32bit符号あり整数を64bit浮動小数点数に変換する
   458:   //  <d0.l:32bit符号あり整数。x
   459:   //  >d0d1.d:64bit浮動小数点数。(double)x
   460:   public static void fpkLTOD () {
   461:     //int→double→[long]→[int,int]
   462:     long l = Double.doubleToLongBits ((double) XEiJ.regRn[0]);
   463:     XEiJ.regRn[0] = (int) (l >>> 32);
   464:     XEiJ.regRn[1] = (int) l;
   465:   }  //fpkLTOD()
   466: 
   467:   //fpkDTOL ()
   468:   //  $FE1B  __DTOL
   469:   //  64bit浮動小数点数を32bit符号あり整数に変換する
   470:   //  <d0d1.d:64bit浮動小数点数。x
   471:   //  >d0.l:32bit符号あり整数。(int)x。オーバーフローのときは不定
   472:   //  >ccr:cs=オーバーフロー。C以外は不定
   473:   public static void fpkDTOL () {
   474:     //[int,int]→[long]→double→int
   475:     double d = Double.longBitsToDouble ((long) XEiJ.regRn[0] << 32 | 0xffffffffL & XEiJ.regRn[1]);
   476:     XEiJ.regRn[0] = (int) d;  //オーバーフローのときは最小値または最大値
   477:     XEiJ.regCCR = (double) Integer.MIN_VALUE - 1.0 < d && d < (double) Integer.MAX_VALUE + 1.0 ? 0 : XEiJ.REG_CCR_C;  //NaN,±Infはエラー
   478:   }  //fpkDTOL()
   479: 
   480:   //fpkLTOF ()
   481:   //  $FE1C  __LTOF
   482:   //  32bit符号あり整数を32bit浮動小数点数に変換する
   483:   //  <d0.l:32bit符号あり整数。x
   484:   //  >d0.s:32bit浮動小数点数。(float)x
   485:   public static void fpkLTOF () {
   486:     //int→float→[int]
   487:     XEiJ.regRn[0] = Float.floatToIntBits ((float) XEiJ.regRn[0]);
   488:   }  //fpkLTOF()
   489: 
   490:   //fpkFTOL ()
   491:   //  $FE1D  __FTOL
   492:   //  32bit浮動小数点数を32bit符号あり整数に変換する
   493:   //  <d0.s:32bit浮動小数点数。x
   494:   //  >d0.l:32bit符号あり整数。(int)x。オーバーフローのときは不定
   495:   //  >ccr:cs=オーバーフロー。C以外は不定
   496:   public static void fpkFTOL () {
   497:     //[int]→float→int
   498:     float f = Float.intBitsToFloat (XEiJ.regRn[0]);
   499:     XEiJ.regRn[0] = (int) f;
   500:     XEiJ.regCCR = (float) Integer.MIN_VALUE - 1.0F < f && f < (float) Integer.MAX_VALUE + 1.0F ? 0 : XEiJ.REG_CCR_C;  //NaN,±Infはエラー
   501:   }  //fpkFTOL()
   502: 
   503:   //fpkFTOD ()
   504:   //  $FE1E  __FTOD
   505:   //  32bit浮動小数点数を64bit浮動小数点数に変換する
   506:   //  バグ
   507:   //    FLOAT2.X 2.02/2.03はfloatの非正規化数を正しく処理できない
   508:   //      (double)0x007fffff=0x380fffffc0000000Lが0x380fffffe0000000Lになる
   509:   //      (double)0x00000001=0x36a0000000000000Lが0x3800000020000000Lになる
   510:   //  <d0.s:32bit浮動小数点数。x
   511:   //  >d0d1.d:64bit浮動小数点数。(double)x
   512:   public static void fpkFTOD () {
   513:     //[int]→float→double→[long]→[int,int]
   514:     long l = Double.doubleToLongBits ((double) Float.intBitsToFloat (XEiJ.regRn[0]));
   515:     if (FPK_FPCP_NAN && l == 0x7ff8000000000000L) {
   516:       l = 0x7fffffffffffffffL;
   517:     }
   518:     XEiJ.regRn[0] = (int) (l >>> 32);
   519:     XEiJ.regRn[1] = (int) l;
   520:   }  //fpkFTOD()
   521: 
   522:   //fpkDTOF ()
   523:   //  $FE1F  __DTOF
   524:   //  64bit浮動小数点数を32bit浮動小数点数に変換する
   525:   //  バグ
   526:   //    FLOAT2.X 2.02/2.03はfloatの非正規化数を正しく処理できない
   527:   //      (float)0x380fffffc0000000L=0x007fffffが0x007ffffeになる
   528:   //      (float)0x36a0000000000000L=0x00000001が0x00000000になる
   529:   //    FLOAT2.X 2.02/2.03は(float)0x8010000000000000L=0x80000000が0x00000000になる
   530:   //  <d0d1.d:64bit浮動小数点数。x
   531:   //  >d0.s:32bit浮動小数点数。(float)x
   532:   //  >ccr:cs=オーバーフロー。C以外は不定
   533:   public static void fpkDTOF () {
   534:     //[int,int]→[long]→double→float→[int]
   535:     double d = Double.longBitsToDouble ((long) XEiJ.regRn[0] << 32 | 0xffffffffL & XEiJ.regRn[1]);
   536:     int h = Float.floatToIntBits ((float) d);
   537:     if (FPK_FPCP_NAN && h == 0x7fc00000) {
   538:       h = 0x7fffffff;
   539:     }
   540:     XEiJ.regRn[0] = h;
   541:     XEiJ.regCCR = (Double.isNaN (d) || Double.isInfinite (d) ||
   542:            Math.abs (d) < (double) Float.MAX_VALUE + 0.5 * (double) Math.ulp (Float.MAX_VALUE) ? 0 : XEiJ.REG_CCR_C);  //アンダーフローはエラーなし
   543:   }  //fpkDTOF()
   544: 
   545:   //fpkDTST ()
   546:   //  $FE28  __DTST
   547:   //  64bit浮動小数点数と0の比較
   548:   //  x<=>0
   549:   //  バグ
   550:   //    FLOAT2.X 2.02/2.03は-0<0となる
   551:   //    FLOAT4.X 1.02は-0<0となる(実機で確認済み)
   552:   //  <d0d1.d:64bit浮動小数点数。x
   553:   //  >ccr:lt=x<0,eq=x==0,gt=x>0
   554:   public static void fpkDTST () {
   555:     if (true) {
   556:       long l = (long) XEiJ.regRn[0] << 32 | 0xffffffffL & XEiJ.regRn[1];
   557:       XEiJ.regCCR = l << 1 == 0L ? XEiJ.REG_CCR_Z : 0L <= l ? 0 : XEiJ.REG_CCR_N;  //NaNのときは0
   558:     } else {
   559:       //([int,int]→[long]→double)<=>0
   560:       double d = Double.longBitsToDouble ((long) XEiJ.regRn[0] << 32 | 0xffffffffL & XEiJ.regRn[1]);
   561:       XEiJ.regCCR = d < 0.0 ? XEiJ.REG_CCR_N : d == 0.0 ? XEiJ.REG_CCR_Z : 0;  //NaNのときは0
   562:     }
   563:   }  //fpkDTST()
   564: 
   565:   //fpkDCMP ()
   566:   //  $FE29  __DCMP
   567:   //  64bit浮動小数点数の比較
   568:   //  x<=>y
   569:   //  バグ
   570:   //    FLOAT2.X 2.02/2.03はNaNがNaNと等しく、NaN以外のすべての数よりも大きい
   571:   //    FLOAT4.X 1.02はNaNがNaNと等しく、NaN以外のすべての数よりも大きい
   572:   //    FLOAT2.X 2.02/2.03は-0が0よりも小さい
   573:   //    FLOAT4.X 1.02は-0が0よりも小さい
   574:   //  <d0d1.d:64bit浮動小数点数。x
   575:   //  <d2d3.d:64bit浮動小数点数。y
   576:   //  >ccr:lt=x<y,eq=x==y,gt=x>y
   577:   public static void fpkDCMP () {
   578:     //([int,int]→[long]→double)<=>([int,int]→[long]→double)
   579:     double xd = Double.longBitsToDouble ((long) XEiJ.regRn[0] << 32 | 0xffffffffL & XEiJ.regRn[1]);
   580:     double yd = Double.longBitsToDouble ((long) XEiJ.regRn[2] << 32 | 0xffffffffL & XEiJ.regRn[3]);
   581:     XEiJ.regCCR = xd < yd ? XEiJ.REG_CCR_N | XEiJ.REG_CCR_C : xd == yd ? XEiJ.REG_CCR_Z : 0;  //どちらかがNaNのときは0
   582:   }  //fpkDCMP()
   583: 
   584:   //fpkDNEG ()
   585:   //  $FE2A  __DNEG
   586:   //  64bit浮動小数点数の符号反転
   587:   //  バグ
   588:   //    FLOAT2.X 2.02/2.03は-(+0)が+0になる
   589:   //    FLOAT4.X 1.02は-(+0)が+0になる
   590:   //    FLOAT2.X 2.02/2.03は-NaNが0xffffffffffffffffLになる
   591:   //    FLOAT4.X 1.02は-NaNが0xffffffffffffffffLになる
   592:   //    FLOAT2.X 2.02/2.03は-0x0000000000000001Lが0x0000000000000001Lになる
   593:   //    FLOAT4.X 1.02は-0x0000000000000001Lが0x0000000000000001Lになる
   594:   //  <d0d1.d:64bit浮動小数点数。x
   595:   //  >d0d1.d:64bit浮動小数点数。-x
   596:   public static void fpkDNEG () {
   597:     //-([int,int]→[long]→double)→[long]→[int,int]
   598:     long l = Double.doubleToLongBits (-Double.longBitsToDouble ((long) XEiJ.regRn[0] << 32 | 0xffffffffL & XEiJ.regRn[1]));
   599:     if (FPK_FPCP_NAN && l == 0x7ff8000000000000L) {
   600:       l = 0x7fffffffffffffffL;
   601:     }
   602:     XEiJ.regRn[0] = (int) (l >>> 32);
   603:     XEiJ.regRn[1] = (int) l;
   604:   }  //fpkDNEG()
   605: 
   606:   //fpkDADD ()
   607:   //  $FE2B  __DADD
   608:   //  64bit浮動小数点数の加算
   609:   //  バグ
   610:   //    FLOAT2.X 2.02/2.03はNaNを+Infとして計算する。(+Inf)+(-Inf)はNaNになる
   611:   //    FLOAT2.X 2.02/2.03は丸めの処理がおかしい
   612:   //      0x3ff0000000000004+0x4024000000000000=0x4026000000000000が0x4026000000000001になる
   613:   //      0xbff921fb54442d18+0x40c3880000000000=0x40c38736f0255ddfが0x40c38736f0255ddeになる
   614:   //  <d0d1.d:64bit浮動小数点数。被加算数x
   615:   //  <d2d3.d:64bit浮動小数点数。加算数y
   616:   //  >d0d1.d:64bit浮動小数点数。和x+y
   617:   //  >ccr:cs=エラー,vs=オーバーフロー
   618:   public static void fpkDADD () {
   619:     //([int,int]→[long]→double)+([int,int]→[long]→double)→[long]→[int,int]
   620:     double xd = Double.longBitsToDouble ((long) XEiJ.regRn[0] << 32 | 0xffffffffL & XEiJ.regRn[1]);
   621:     double yd = Double.longBitsToDouble ((long) XEiJ.regRn[2] << 32 | 0xffffffffL & XEiJ.regRn[3]);
   622:     double zd = xd + yd;
   623:     long l = Double.doubleToLongBits (zd);
   624:     if (FPK_FPCP_NAN && l == 0x7ff8000000000000L) {
   625:       l = 0x7fffffffffffffffL;
   626:     }
   627:     XEiJ.regRn[0] = (int) (l >>> 32);
   628:     XEiJ.regRn[1] = (int) l;
   629:     XEiJ.regCCR = (Double.isNaN (xd) || Double.isNaN (yd) ? 0 :  //引数がNaN
   630:            Double.isNaN (zd) ? XEiJ.REG_CCR_C :  //引数がNaNでないのに結果がNaNのときはエラー。(+Inf)+(-Inf)=NaN
   631:            Double.isInfinite (xd) || Double.isInfinite (yd) ? 0 :  //引数が±Inf
   632:            Double.isInfinite (zd) ? XEiJ.REG_CCR_V | XEiJ.REG_CCR_C :  //引数が±Infでないのに結果が±Infのときはオーバーフロー
   633:            0);
   634:   }  //fpkDADD()
   635: 
   636:   //fpkDSUB ()
   637:   //  $FE2C  __DSUB
   638:   //  64bit浮動小数点数の減算
   639:   //  バグ
   640:   //    FLOAT2.X 2.02/2.03は丸めの処理がおかしい
   641:   //  <d0d1.d:64bit浮動小数点数。被減算数x
   642:   //  <d2d3.d:64bit浮動小数点数。減算数y
   643:   //  >d0d1.d:64bit浮動小数点数。差x-y
   644:   //  >ccr:cs=エラー,vs=オーバーフロー
   645:   public static void fpkDSUB () {
   646:     //([int,int]→[long]→double)-([int,int]→[long]→double)→[long]→[int,int]
   647:     double xd = Double.longBitsToDouble ((long) XEiJ.regRn[0] << 32 | 0xffffffffL & XEiJ.regRn[1]);
   648:     double yd = Double.longBitsToDouble ((long) XEiJ.regRn[2] << 32 | 0xffffffffL & XEiJ.regRn[3]);
   649:     double zd = xd - yd;
   650:     long l = Double.doubleToLongBits (zd);
   651:     if (FPK_FPCP_NAN && l == 0x7ff8000000000000L) {
   652:       l = 0x7fffffffffffffffL;
   653:     }
   654:     XEiJ.regRn[0] = (int) (l >>> 32);
   655:     XEiJ.regRn[1] = (int) l;
   656:     XEiJ.regCCR = (Double.isNaN (xd) || Double.isNaN (yd) ? 0 :  //引数がNaN
   657:            Double.isNaN (zd) ? XEiJ.REG_CCR_C :  //引数がNaNでないのに結果がNaNのときはエラー。(+Inf)-(+Inf)=NaN
   658:            Double.isInfinite (xd) || Double.isInfinite (yd) ? 0 :  //引数が±Inf
   659:            Double.isInfinite (zd) ? XEiJ.REG_CCR_V | XEiJ.REG_CCR_C :  //引数が±Infでないのに結果が±Infのときはオーバーフロー
   660:            0);
   661:   }  //fpkDSUB()
   662: 
   663:   //fpkDMUL ()
   664:   //  $FE2D  __DMUL
   665:   //  64bit浮動小数点数の乗算
   666:   //  バグ
   667:   //    FLOAT2.X 2.02/2.03は(+Inf)*(非正規化数)=(+Inf)がNaNになる
   668:   //    FLOAT2.X 2.02/2.03は(+x)*(非正規化数)=(+x)が+0になる
   669:   //    FLOAT2.X 2.02/2.03は(+x)*(-0)=(-0)が+0になる
   670:   //  <d0d1.d:64bit浮動小数点数。被乗数x
   671:   //  <d2d3.d:64bit浮動小数点数。乗数y
   672:   //  >d0d1.d:64bit浮動小数点数。積x*y
   673:   //  >ccr:cs=エラー,vs=オーバーフロー
   674:   public static void fpkDMUL () {
   675:     //([int,int]→[long]→double)*([int,int]→[long]→double)→[long]→[int,int]
   676:     double xd = Double.longBitsToDouble ((long) XEiJ.regRn[0] << 32 | 0xffffffffL & XEiJ.regRn[1]);
   677:     double yd = Double.longBitsToDouble ((long) XEiJ.regRn[2] << 32 | 0xffffffffL & XEiJ.regRn[3]);
   678:     double zd = xd * yd;
   679:     long l = Double.doubleToLongBits (zd);
   680:     if (FPK_FPCP_NAN && l == 0x7ff8000000000000L) {
   681:       l = 0x7fffffffffffffffL;
   682:     }
   683:     XEiJ.regRn[0] = (int) (l >>> 32);
   684:     XEiJ.regRn[1] = (int) l;
   685:     XEiJ.regCCR = (Double.isNaN (xd) || Double.isNaN (yd) ? 0 :  //引数がNaN
   686:            Double.isNaN (zd) ? XEiJ.REG_CCR_C :  //引数がNaNでないのに結果がNaNのときはエラー。(±0)*(±Inf)=NaN
   687:            Double.isInfinite (xd) || Double.isInfinite (yd) ? 0 :  //引数が±Inf
   688:            Double.isInfinite (zd) ? XEiJ.REG_CCR_V | XEiJ.REG_CCR_C :  //引数が±Infでないのに結果が±Infのときはオーバーフロー
   689:            0);
   690:   }  //fpkDMUL()
   691: 
   692:   //fpkDDIV ()
   693:   //  $FE2E  __DDIV
   694:   //  64bit浮動小数点数の除算
   695:   //  <d0d1.d:64bit浮動小数点数。被除数x
   696:   //  <d2d3.d:64bit浮動小数点数。除数y
   697:   //  >d0d1.d:64bit浮動小数点数。商x/y。ゼロ除算のときは不定
   698:   //  >ccr:cs=エラー,eq=ゼロ除算,vs=オーバーフロー
   699:   public static void fpkDDIV () {
   700:     //([int,int]→[long]→double)/([int,int]→[long]→double)→[long]→[int,int]
   701:     double xd = Double.longBitsToDouble ((long) XEiJ.regRn[0] << 32 | 0xffffffffL & XEiJ.regRn[1]);
   702:     double yd = Double.longBitsToDouble ((long) XEiJ.regRn[2] << 32 | 0xffffffffL & XEiJ.regRn[3]);
   703:     double zd = xd / yd;
   704:     long l = Double.doubleToLongBits (zd);
   705:     if (FPK_FPCP_NAN && l == 0x7ff8000000000000L) {
   706:       l = 0x7fffffffffffffffL;
   707:     }
   708:     XEiJ.regRn[0] = (int) (l >>> 32);
   709:     XEiJ.regRn[1] = (int) l;
   710:     XEiJ.regCCR = (Double.isNaN (xd) || Double.isNaN (yd) ? 0 :  //引数がNaN
   711:            Double.isNaN (zd) ? XEiJ.REG_CCR_C :  //引数がNaNでないのに結果がNaNのときはエラー。(±0)/(±0)=NaN
   712:            Double.isInfinite (xd) || Double.isInfinite (yd) ? 0 :  //引数が±Inf。(±Inf)/(±0)=(±Inf)
   713:            yd == 0.0 ? XEiJ.REG_CCR_Z | XEiJ.REG_CCR_C :  //除数が±0のときはゼロ除算
   714:            Double.isInfinite (zd) ? XEiJ.REG_CCR_V | XEiJ.REG_CCR_C :  //引数が±Infでないのに結果が±Infのときはオーバーフロー
   715:            0);
   716:   }  //fpkDDIV()
   717: 
   718:   //fpkDMOD ()
   719:   //  $FE2F  __DMOD
   720:   //  64bit浮動小数点数の剰余算
   721:   //  バグ
   722:   //    FLOAT4.X 1.02はNaN%0がエラーになる
   723:   //  <d0d1.d:64bit浮動小数点数。被除数x
   724:   //  <d2d3.d:64bit浮動小数点数。除数y
   725:   //  >d0d1.d:64bit浮動小数点数。余りx%y。ゼロ除算のときは不定
   726:   //  >ccr:cs=エラー,eq=ゼロ除算
   727:   public static void fpkDMOD () {
   728:     //([int,int]→[long]→double)%([int,int]→[long]→double)→[long]→[int,int]
   729:     double xd = Double.longBitsToDouble ((long) XEiJ.regRn[0] << 32 | 0xffffffffL & XEiJ.regRn[1]);
   730:     double yd = Double.longBitsToDouble ((long) XEiJ.regRn[2] << 32 | 0xffffffffL & XEiJ.regRn[3]);
   731:     double zd = xd % yd;
   732:     long l = Double.doubleToLongBits (zd);
   733:     if (FPK_FPCP_NAN && l == 0x7ff8000000000000L) {
   734:       l = 0x7fffffffffffffffL;
   735:     }
   736:     XEiJ.regRn[0] = (int) (l >>> 32);
   737:     XEiJ.regRn[1] = (int) l;
   738:     XEiJ.regCCR = (Double.isNaN (xd) || Double.isNaN (yd) ? 0 :  //引数がNaN
   739:            yd == 0.0 ? XEiJ.REG_CCR_Z | XEiJ.REG_CCR_C :  //除数が0のときはゼロ除算。(±Inf)%(±0)=NaN, x%(±0)=(±Inf)
   740:            Double.isNaN (zd) ? XEiJ.REG_CCR_C :  //引数がNaNでないのに結果がNaNのときはエラー。(±Inf)%y=NaN
   741:            Double.isInfinite (xd) || Double.isInfinite (yd) ? 0 :  //引数が±Inf
   742:            Double.isInfinite (zd) ? XEiJ.REG_CCR_V | XEiJ.REG_CCR_C :  //引数が±Infでないのに結果が±Infのときはオーバーフロー
   743:            0);
   744:   }  //fpkDMOD()
   745: 
   746:   //fpkDABS ()
   747:   //  $FE30  __DABS
   748:   //  64bit浮動小数点数の絶対値
   749:   //  <d0d1.d:64bit浮動小数点数。x
   750:   //  >d0d1.d:64bit浮動小数点数。abs(x)
   751:   public static void fpkDABS () {
   752:     //abs([int,int]→[long]→double)→[long]→[int,int]
   753:     long l = Double.doubleToLongBits (Math.abs (Double.longBitsToDouble ((long) XEiJ.regRn[0] << 32 | 0xffffffffL & XEiJ.regRn[1])));
   754:     if (FPK_FPCP_NAN && l == 0x7ff8000000000000L) {
   755:       l = 0x7fffffffffffffffL;
   756:     }
   757:     XEiJ.regRn[0] = (int) (l >>> 32);
   758:     XEiJ.regRn[1] = (int) l;
   759:   }  //fpkDABS()
   760: 
   761:   //fpkDCEIL ()
   762:   //  $FE31  __DCEIL
   763:   //  64bit浮動小数点数の天井関数(引数を下回らない最小の整数)
   764:   //  バグ
   765:   //    FLOAT2.X 2.02/2.03はCEIL(-0)やCEIL(-0.5)が+0になる
   766:   //  <d0d1.d:64bit浮動小数点数。x
   767:   //  >d0d1.d:64bit浮動小数点数。ceil(x)
   768:   public static void fpkDCEIL () {
   769:     //ceil([int,int]→[long]→double)→[long]→[int,int]
   770:     long l = Double.doubleToLongBits (Math.ceil (Double.longBitsToDouble ((long) XEiJ.regRn[0] << 32 | 0xffffffffL & XEiJ.regRn[1])));
   771:     if (FPK_FPCP_NAN && l == 0x7ff8000000000000L) {
   772:       l = 0x7fffffffffffffffL;
   773:     }
   774:     XEiJ.regRn[0] = (int) (l >>> 32);
   775:     XEiJ.regRn[1] = (int) l;
   776:   }  //fpkDCEIL()
   777: 
   778:   //fpkDFIX ()
   779:   //  $FE32  __DFIX
   780:   //  64bit浮動小数点数の切り落とし関数(絶対値について引数を上回らない最大の整数)
   781:   //  バグ
   782:   //    FLOAT2.X 2.02/2.03はFIX(-0)やFIX(-0.5)が+0になる
   783:   //  <d0d1.d:64bit浮動小数点数。x
   784:   //  >d0d1.d:64bit浮動小数点数。trunc(x)
   785:   public static void fpkDFIX () {
   786:     //trunc([int,int]→[long]→double)→[long]→[int,int]
   787:     double d = Double.longBitsToDouble ((long) XEiJ.regRn[0] << 32 | 0xffffffffL & XEiJ.regRn[1]);
   788:     long l = Double.doubleToLongBits (0.0 <= d ? Math.floor (d) : Math.ceil (d));  //0<=-0だがMath.floor(-0)=-0なので問題ない
   789:     if (FPK_FPCP_NAN && l == 0x7ff8000000000000L) {
   790:       l = 0x7fffffffffffffffL;
   791:     }
   792:     XEiJ.regRn[0] = (int) (l >>> 32);
   793:     XEiJ.regRn[1] = (int) l;
   794:   }  //fpkDFIX()
   795: 
   796:   //fpkDFLOOR ()
   797:   //  $FE33  __DFLOOR
   798:   //  64bit浮動小数点数の床関数(引数を上回らない最大の整数)
   799:   //  バグ
   800:   //    FLOAT2.X 2.02/2.03はFLOOR(-0)が-1になる
   801:   //  <d0d1.d:64bit浮動小数点数。x
   802:   //  >d0d1.d:64bit浮動小数点数。floor(x)
   803:   public static void fpkDFLOOR () {
   804:     //floor([int,int]→[long]→double)→[long]→[int,int]
   805:     long l = Double.doubleToLongBits (Math.floor (Double.longBitsToDouble ((long) XEiJ.regRn[0] << 32 | 0xffffffffL & XEiJ.regRn[1])));
   806:     if (FPK_FPCP_NAN && l == 0x7ff8000000000000L) {
   807:       l = 0x7fffffffffffffffL;
   808:     }
   809:     XEiJ.regRn[0] = (int) (l >>> 32);
   810:     XEiJ.regRn[1] = (int) l;
   811:   }  //fpkDFLOOR()
   812: 
   813:   //fpkDFRAC ()
   814:   //  $FE34  __DFRAC
   815:   //  64bit浮動小数点数の幹小数部
   816:   //  メモ
   817:   //    FLOAT2.X 2.02/2.03はDFRAC(±Inf)が±0になる
   818:   //    同様の機能を持ったライブラリによってはfrac(±Inf)が引数の±Infをそのまま返すものもある
   819:   //    x-trunc(x)だとInf-Inf=NaNになる。trunc(x)+frac(x)がxに戻らないので都合が悪い場合があるかも知れない
   820:   //  バグ
   821:   //    FLOAT2.X 2.02/2.03はDFRAC(NaN)=NaNが0になる
   822:   //    FLOAT4.X 1.02はDFRAC(NaN)=NaNが0になる
   823:   //  <d0d1.d:64bit浮動小数点数。x
   824:   //  >d0d1.d:64bit浮動小数点数。frac(x)=copysign(x-trunc(x),x)
   825:   public static void fpkDFRAC () {
   826:     //frac([int,int]→[long]→double)→[long]→[int,int]
   827:     long l = (long) XEiJ.regRn[0] << 32 | 0xffffffffL & XEiJ.regRn[1];
   828:     double d = Double.longBitsToDouble (l);
   829:     l = (Double.isNaN (d) ? Double.doubleToLongBits (Double.NaN) :  //frac(NaN)=NaN
   830:          Double.isInfinite (d) ? l & 0x8000000000000000L :  //frac(±Inf)=±0
   831:          Double.doubleToLongBits (0L <= l ? d - Math.floor (d) : -(-d - Math.floor (-d))));  //0<=-0なので0<=d?~は不可
   832:     if (FPK_FPCP_NAN && l == 0x7ff8000000000000L) {
   833:       l = 0x7fffffffffffffffL;
   834:     }
   835:     XEiJ.regRn[0] = (int) (l >>> 32);
   836:     XEiJ.regRn[1] = (int) l;
   837:   }  //fpkDFRAC()
   838: 
   839:   //fpkDSGN ()
   840:   //  $FE35  __DSGN
   841:   //  64bit浮動小数点数の符号
   842:   //  バグ
   843:   //    FLOAT2.X 2.02/2.03はDSGN(-0)=-0が+0になる
   844:   //    FLOAT4.X 1.02はDSGN(-0)=-0が+0になる
   845:   //    FLOAT4.X 1.02はDSGN(NaN)=NaNが+1になる
   846:   //  <d0d1.d:64bit浮動小数点数。x
   847:   //  >d0d1.d:64bit浮動小数点数。signum(x)
   848:   public static void fpkDSGN () {
   849:     //signum([int,int]→[long]→double)→[long]→[int,int]
   850:     long l = Double.doubleToLongBits (Math.signum (Double.longBitsToDouble ((long) XEiJ.regRn[0] << 32 | 0xffffffffL & XEiJ.regRn[1])));
   851:     if (FPK_FPCP_NAN && l == 0x7ff8000000000000L) {
   852:       l = 0x7fffffffffffffffL;
   853:     }
   854:     XEiJ.regRn[0] = (int) (l >>> 32);
   855:     XEiJ.regRn[1] = (int) l;
   856:   }  //fpkDSGN()
   857: 
   858:   //fpkSIN ()
   859:   //  $FE36  __SIN
   860:   //  64bit浮動小数点数の正弦
   861:   //  バグ
   862:   //    FLOAT2.X 2.02/2.03はsin(x)でxの絶対値が大きすぎるとき真の値からかけ離れた結果を返す
   863:   //  <d0d1.d:64bit浮動小数点数。x
   864:   //  >d0d1.d:64bit浮動小数点数。sin(x)
   865:   //  >ccr:x=±Inf。C以外は不定
   866:   public static void fpkSIN () {
   867:     //sin([int,int]→[long]→double)→[long]→[int,int]
   868:     double xd = Double.longBitsToDouble ((long) XEiJ.regRn[0] << 32 | 0xffffffffL & XEiJ.regRn[1]);
   869:     double zd = Math.sin (xd);
   870:     long l = Double.doubleToLongBits (zd);
   871:     if (FPK_FPCP_NAN && l == 0x7ff8000000000000L) {
   872:       l = 0x7fffffffffffffffL;
   873:     }
   874:     XEiJ.regRn[0] = (int) (l >>> 32);
   875:     XEiJ.regRn[1] = (int) l;
   876:     XEiJ.regCCR = !Double.isNaN (xd) && Double.isNaN (zd) ? XEiJ.REG_CCR_C : 0;  //引数がNaNでないのに結果がNaNのときはエラー。sin(±Inf)=NaN
   877:   }  //fpkSIN()
   878: 
   879:   //fpkCOS ()
   880:   //  $FE37  __COS
   881:   //  64bit浮動小数点数の余弦
   882:   //  バグ
   883:   //    FLOAT2.X 2.02/2.03はcos(x)でxの絶対値が大きすぎるとき真の値からかけ離れた結果を返す
   884:   //  <d0d1.d:64bit浮動小数点数。x
   885:   //  >d0d1.d:64bit浮動小数点数。cos(x)
   886:   //  >ccr:x=±Inf。C以外は不定
   887:   public static void fpkCOS () {
   888:     //cos([int,int]→[long]→double)→[long]→[int,int]
   889:     double xd = Double.longBitsToDouble ((long) XEiJ.regRn[0] << 32 | 0xffffffffL & XEiJ.regRn[1]);
   890:     double zd = Math.cos (xd);
   891:     long l = Double.doubleToLongBits (zd);
   892:     if (FPK_FPCP_NAN && l == 0x7ff8000000000000L) {
   893:       l = 0x7fffffffffffffffL;
   894:     }
   895:     XEiJ.regRn[0] = (int) (l >>> 32);
   896:     XEiJ.regRn[1] = (int) l;
   897:     XEiJ.regCCR = !Double.isNaN (xd) && Double.isNaN (zd) ? XEiJ.REG_CCR_C : 0;  //引数がNaNでないのに結果がNaNのときはエラー。cos(±Inf)=NaN
   898:   }  //fpkCOS()
   899: 
   900:   //fpkTAN ()
   901:   //  $FE38  __TAN
   902:   //  64bit浮動小数点数の正接
   903:   //  バグ
   904:   //    FLOAT2.X 2.02/2.03はtan(x)でxの絶対値が大きすぎるとき真の値からかけ離れた結果を返す
   905:   //  <d0d1.d:64bit浮動小数点数。x
   906:   //  >d0d1.d:64bit浮動小数点数。tan(x)
   907:   //  >ccr:x=±Inf。C以外は不定
   908:   public static void fpkTAN () {
   909:     //tan([int,int]→[long]→double)→[long]→[int,int]
   910:     double xd = Double.longBitsToDouble ((long) XEiJ.regRn[0] << 32 | 0xffffffffL & XEiJ.regRn[1]);
   911:     double zd = Math.tan (xd);
   912:     long l = Double.doubleToLongBits (zd);
   913:     if (FPK_FPCP_NAN && l == 0x7ff8000000000000L) {
   914:       l = 0x7fffffffffffffffL;
   915:     }
   916:     XEiJ.regRn[0] = (int) (l >>> 32);
   917:     XEiJ.regRn[1] = (int) l;
   918:     XEiJ.regCCR = !Double.isNaN (xd) && Double.isNaN (zd) ? XEiJ.REG_CCR_C : 0;  //引数がNaNでないのに結果がNaNのときはエラー。tan(±Inf)=NaN
   919:   }  //fpkTAN()
   920: 
   921:   //fpkATAN ()
   922:   //  $FE39  __ATAN
   923:   //  64bit浮動小数点数の逆正接
   924:   //  バグ
   925:   //    FLOAT2.X 2.02/2.03は非正規化数を+0とみなす。__ATAN(0x000fffffffffffffL)が+0になる
   926:   //  <d0d1.d:64bit浮動小数点数。x
   927:   //  >d0d1.d:64bit浮動小数点数。atan(x)
   928:   public static void fpkATAN () {
   929:     //atan([int,int]→[long]→double)→[long]→[int,int]
   930:     long l = Double.doubleToLongBits (Math.atan (Double.longBitsToDouble ((long) XEiJ.regRn[0] << 32 | 0xffffffffL & XEiJ.regRn[1])));
   931:     if (FPK_FPCP_NAN && l == 0x7ff8000000000000L) {
   932:       l = 0x7fffffffffffffffL;
   933:     }
   934:     XEiJ.regRn[0] = (int) (l >>> 32);
   935:     XEiJ.regRn[1] = (int) l;
   936:   }  //fpkATAN()
   937: 
   938:   //fpkLOG ()
   939:   //  $FE3A  __LOG
   940:   //  64bit浮動小数点数の自然対数
   941:   //  バグ
   942:   //    FLOAT2.X 2.02/2.03は非正規化数を+0とみなす。__LOG(0x000fffffffffffffL)が-InfになってXEiJ.REG_CCR_Cがセットされる
   943:   //    FLOAT2.X 2.02/2.03は__LOG(±0)でCがセットされるがZをセットしない
   944:   //  <d0d1.d:64bit浮動小数点数。x
   945:   //  >d0d1.d:64bit浮動小数点数。log(x)
   946:   //  >ccr:0=エラーなし,C=x<0,Z|C=x==0
   947:   public static void fpkLOG () {
   948:     //log([int,int]→[long]→double)→[long]→[int,int]
   949:     double xd = Double.longBitsToDouble ((long) XEiJ.regRn[0] << 32 | 0xffffffffL & XEiJ.regRn[1]);
   950:     double zd = Math.log (xd);
   951:     long l = Double.doubleToLongBits (zd);
   952:     if (FPK_FPCP_NAN && l == 0x7ff8000000000000L) {
   953:       l = 0x7fffffffffffffffL;
   954:     }
   955:     XEiJ.regRn[0] = (int) (l >>> 32);
   956:     XEiJ.regRn[1] = (int) l;
   957:     XEiJ.regCCR = (Double.isNaN (xd) ? 0 :  //引数がNaN
   958:            Double.isNaN (zd) ? XEiJ.REG_CCR_C :  //引数がNaNでないのに結果がNaNのときはエラー。log(-x)=NaN
   959:            Double.isInfinite (xd) ? 0 :  //引数が±Inf
   960:            Double.isInfinite (zd) ? XEiJ.REG_CCR_Z | XEiJ.REG_CCR_C :  //引数が±Infでないのに結果が±Infのときはエラー。log(±0)=-Inf
   961:            0);
   962:   }  //fpkLOG()
   963: 
   964:   //fpkEXP ()
   965:   //  $FE3B  __EXP
   966:   //  64bit浮動小数点数の指数関数
   967:   //  <d0d1.d:64bit浮動小数点数。x
   968:   //  >d0d1.d:64bit浮動小数点数。exp(x)
   969:   //  >ccr:cs=オーバーフロー
   970:   public static void fpkEXP () {
   971:     //exp([int,int]→[long]→double)→[long]→[int,int]
   972:     int xh = XEiJ.regRn[0];
   973:     long l = Double.doubleToLongBits (Math.exp (Double.longBitsToDouble ((long) xh << 32 | 0xffffffffL & XEiJ.regRn[1])));
   974:     if (FPK_FPCP_NAN && l == 0x7ff8000000000000L) {
   975:       l = 0x7fffffffffffffffL;
   976:     }
   977:     int zh = (int) (l >>> 32);
   978:     XEiJ.regRn[0] = zh;
   979:     XEiJ.regRn[1] = (int) l;
   980:     XEiJ.regCCR = (zh & 0x7ff00000) == 0x7ff00000 && (xh & 0x7ff00000) != 0x7ff00000 ? XEiJ.REG_CCR_C : 0;  //結果が±Inf,NaNだが引数が±Inf,NaNでなかったときはエラー
   981:   }  //fpkEXP()
   982: 
   983:   //fpkSQR ()
   984:   //  $FE3C  __SQR
   985:   //  64bit浮動小数点数の平方根
   986:   //  バグ
   987:   //    FLOAT4.X 1.02はSQR(-0)=-0が+0になる(実機で確認済み)
   988:   //    FLOAT4.X 1.02はSQR(0x8000000000000001)=NaNがNaNになるがエラーにならない(実機で確認済み)
   989:   //    FLOAT2.X 2.02/2.03は__SQR(0x0000000000000001)が+0になる
   990:   //      __SQR(0x000fffffffffffff)は0x1fffffffffffffffになるので非正規化数がすべて+0になるというわけではない
   991:   //  <d0d1.d:64bit浮動小数点数。x
   992:   //  >d0d1.d:64bit浮動小数点数。sqrt(x)
   993:   //  >ccr:cs=x<0
   994:   public static void fpkSQR () {
   995:     //sqrt([int,int]→[long]→double)→[long]→[int,int]
   996:     double xd = Double.longBitsToDouble ((long) XEiJ.regRn[0] << 32 | 0xffffffffL & XEiJ.regRn[1]);
   997:     long l = Double.doubleToLongBits (Math.sqrt (xd));
   998:     if (FPK_FPCP_NAN && l == 0x7ff8000000000000L) {
   999:       l = 0x7fffffffffffffffL;
  1000:     }
  1001:     XEiJ.regRn[0] = (int) (l >>> 32);
  1002:     XEiJ.regRn[1] = (int) l;
  1003:     XEiJ.regCCR = xd < 0.0 ? XEiJ.REG_CCR_C : 0;  //NaNはエラーなし
  1004:   }  //fpkSQR()
  1005: 
  1006:   //fpkPI ()
  1007:   //  $FE3D  __PI
  1008:   //  64bit浮動小数点数の円周率
  1009:   //  >d0d1.d:64bit浮動小数点数。pi
  1010:   public static void fpkPI () {
  1011:     if (true) {
  1012:       XEiJ.regRn[0] = 0x400921fb;
  1013:       XEiJ.regRn[1] = 0x54442d18;
  1014:     } else {
  1015:       //pi→[long]→[int,int]
  1016:       long l = Double.doubleToLongBits (Math.PI);
  1017:       XEiJ.regRn[0] = (int) (l >>> 32);
  1018:       XEiJ.regRn[1] = (int) l;
  1019:     }
  1020:   }  //fpkPI()
  1021: 
  1022:   //fpkNPI ()
  1023:   //  $FE3E  __NPI
  1024:   //  64bit浮動小数点数の円周率倍
  1025:   //  メモ
  1026:   //    FLOAT2.Xの__NPIは倍精度の円周率を倍精度で掛ける
  1027:   //    FLOAT4.Xの__NPIは拡張精度の円周率を拡張精度で掛けて倍精度に丸める
  1028:   //    乗算以前に円周率の値が違うので結果が一致しない場合が想像以上に多い
  1029:   //  バグ
  1030:   //    FLOAT2.X 2.02/2.03は非正規化数を+0とみなす。__NPI(0x000fffffffffffff)が+0になる
  1031:   //  <d0d1.d:64bit浮動小数点数。x
  1032:   //  >d0d1.d:64bit浮動小数点数。x*pi
  1033:   //  >ccr:cs=オーバーフロー
  1034:   public static void fpkNPI () {
  1035:     //([int,int]→[long]→double)*pi→[long]→[int,int]
  1036:     int xh = XEiJ.regRn[0];
  1037:     //long l = Double.doubleToLongBits (Double.longBitsToDouble ((long) xh << 32 | 0xffffffffL & r[1]) * Math.PI);
  1038:     //  四倍精度のπを四倍精度で掛けて倍精度に丸める
  1039:     long l = Double.doubleToLongBits (new QFP (Double.longBitsToDouble ((long) xh << 32 | 0xffffffffL & XEiJ.regRn[1])).mul (QFP.QFP_PI).getd ());
  1040:     if (FPK_FPCP_NAN && l == 0x7ff8000000000000L) {
  1041:       l = 0x7fffffffffffffffL;
  1042:     }
  1043:     int zh = (int) (l >>> 32);
  1044:     XEiJ.regRn[0] = zh;
  1045:     XEiJ.regRn[1] = (int) l;
  1046:     XEiJ.regCCR = (zh & 0x7ff00000) == 0x7ff00000 && (xh & 0x7ff00000) != 0x7ff00000 ? XEiJ.REG_CCR_C : 0;  //結果が±Inf,NaNだが引数が±Inf,NaNでなかったときはエラー
  1047:   }  //fpkNPI()
  1048: 
  1049:   //fpkPOWER ()
  1050:   //  $FE3F  __POWER
  1051:   //  64bit浮動小数点数の累乗
  1052:   //  バグ
  1053:   //    FLOAT4.X 1.02で(+Inf)^(-Inf)を計算しようとするとハングアップする(実機で確認済み)
  1054:   //      movem.l d0-d1,-(sp)でd0d1.dを(sp).dで取り出せるようにした後、
  1055:   //      spを復元せずにrtsで復帰しようとして0x00f00000にあるCGROMにジャンプしている
  1056:   //  <d0d1.d:64bit浮動小数点数。x
  1057:   //  <d2d3.d:64bit浮動小数点数。y
  1058:   //  >d0d1.d:64bit浮動小数点数。pow(x,y)
  1059:   //  >ccr:cs=オーバーフロー
  1060:   public static void fpkPOWER () {
  1061:     //pow([int,int]→[long]→double,[int,int]→[long]→double)→[long]→[int,int]
  1062:     double xd = Double.longBitsToDouble ((long) XEiJ.regRn[0] << 32 | 0xffffffffL & XEiJ.regRn[1]);
  1063:     double yd = Double.longBitsToDouble ((long) XEiJ.regRn[2] << 32 | 0xffffffffL & XEiJ.regRn[3]);
  1064:     double zd = Math.pow (xd, yd);
  1065:     long l = Double.doubleToLongBits (zd);
  1066:     if (FPK_FPCP_NAN && l == 0x7ff8000000000000L) {
  1067:       l = 0x7fffffffffffffffL;
  1068:     }
  1069:     XEiJ.regRn[0] = (int) (l >>> 32);
  1070:     XEiJ.regRn[1] = (int) l;
  1071:     XEiJ.regCCR = (Double.isNaN (xd) || Double.isNaN (yd) ? 0 :  //引数がNaN
  1072:            Double.isNaN (zd) ? XEiJ.REG_CCR_C :  //引数がNaNでないのに結果がNaNのときはエラー
  1073:            Double.isInfinite (xd) || Double.isInfinite (yd) ? 0 :  //引数が±Inf
  1074:            Double.isInfinite (zd) ? XEiJ.REG_CCR_V | XEiJ.REG_CCR_C :  //引数が±Infでないのに結果が±Infのときはオーバーフロー
  1075:            0);
  1076:   }  //fpkPOWER()
  1077: 
  1078:   //fpkRND ()
  1079:   //  $FE40  __RND
  1080:   //  64bit浮動小数点数の乱数
  1081:   //  >d0d1.d:64bit浮動小数点数。rnd()。0以上1未満
  1082:   public static void fpkRND () {
  1083:     long l = 0xffffffffL & fpkRndLong ();  //下位
  1084:     l |= (0x001fffffL & fpkRndLong ()) << 32;  //上位。順序に注意
  1085:     //  ここでl==0LのときLong.numberOfLeadingZeros(z)==64なので乱数の値は2^-54になる
  1086:     //  FLOATn.Xはその場合を考慮しておらず0のときも先頭の1のビットを探し続けて無限ループに陥ると思われる
  1087:     //  実際に0が53ビット並ぶことはないかも知れない
  1088:     int o = Long.numberOfLeadingZeros (l) - 11;
  1089:     l = (long) (0x3fe - o) << 52 | 0x000fffffffffffffL & l << o;
  1090:     XEiJ.regRn[0] = (int) (l >>> 32);
  1091:     XEiJ.regRn[1] = (int) l;
  1092:   }  //fpkRND()
  1093: 
  1094:   //fpkSINH ()
  1095:   //  $FE41  __SINH
  1096:   //  64bit浮動小数点数の双曲線正弦
  1097:   //  バグ
  1098:   //    FLOAT2.X 2.02/2.03は__SINH(NaN)がエラーになる
  1099:   //    FLOAT2.X 2.02/2.03は|x|<1.5/2^53のとき__SINH(x)が0になる
  1100:   //      sinh(x)=(exp(x)-1/exp(x))/2だけで計算しており、x≒0のとき情報落ちでexp(x)≒1+x≒1となることが考慮されていない
  1101:   //      sinh(0x3ca8000000000000)=0x3ca8000000000000=1.5/2^53
  1102:   //      sinh(0x3ca7ffffffffffff)=0x0000000000000000  ここから突然0になる
  1103:   //    FLOAT2.X 2.02/2.03はx<-6243314768165359/274877906944=-22713.0468…のときVがセットされない
  1104:   //      sinh(0xc0d62e42fefa39ef)はV|C
  1105:   //      sinh(0xc0d62e42fefa39f0)はC
  1106:   //      exp(x)がアンダーフローした時点でエラー終了してしまいオーバーフローするexp(-x)を計算していない
  1107:   //      この場合はアンダーフローした側を0として扱うべき
  1108:   //  <d0d1.d:64bit浮動小数点数。x
  1109:   //  >d0d1.d:64bit浮動小数点数。sinh(x)
  1110:   //  >ccr:cs=エラー,vs=オーバーフロー
  1111:   public static void fpkSINH () {
  1112:     //sinh([int,int]→[long]→double)→[long]→[int,int]
  1113:     double xd = Double.longBitsToDouble ((long) XEiJ.regRn[0] << 32 | 0xffffffffL & XEiJ.regRn[1]);
  1114:     double zd = Math.sinh (xd);
  1115:     long l = Double.doubleToLongBits (zd);
  1116:     if (FPK_FPCP_NAN && l == 0x7ff8000000000000L) {
  1117:       l = 0x7fffffffffffffffL;
  1118:     }
  1119:     XEiJ.regRn[0] = (int) (l >>> 32);
  1120:     XEiJ.regRn[1] = (int) l;
  1121:     XEiJ.regCCR = (Double.isNaN (xd) ? 0 :  //引数がNaN
  1122:            Double.isNaN (zd) ? XEiJ.REG_CCR_C :  //引数がNaNでないのに結果がNaNのときはエラー
  1123:            Double.isInfinite (xd) ? 0 :  //引数が±Inf
  1124:            Double.isInfinite (zd) ? XEiJ.REG_CCR_V | XEiJ.REG_CCR_C :  //引数が±Infでないのに結果が±Infのときはオーバーフロー
  1125:            0);
  1126:   }  //fpkSINH()
  1127: 
  1128:   //fpkCOSH ()
  1129:   //  $FE42  __COSH
  1130:   //  64bit浮動小数点数の双曲線余弦
  1131:   //  バグ
  1132:   //    FLOAT2.X 2.02/2.03はCOSH(NaN)=NaNが+Infになる
  1133:   //  <d0d1.d:64bit浮動小数点数。x
  1134:   //  >d0d1.d:64bit浮動小数点数。cosh(x)
  1135:   //  >ccr:cs=エラー,vs=オーバーフロー
  1136:   public static void fpkCOSH () {
  1137:     //cosh([int,int]→[long]→double)→[long]→[int,int]
  1138:     double xd = Double.longBitsToDouble ((long) XEiJ.regRn[0] << 32 | 0xffffffffL & XEiJ.regRn[1]);
  1139:     double zd = Math.cosh (xd);
  1140:     long l = Double.doubleToLongBits (zd);
  1141:     if (FPK_FPCP_NAN && l == 0x7ff8000000000000L) {
  1142:       l = 0x7fffffffffffffffL;
  1143:     }
  1144:     XEiJ.regRn[0] = (int) (l >>> 32);
  1145:     XEiJ.regRn[1] = (int) l;
  1146:     XEiJ.regCCR = (Double.isNaN (xd) ? 0 :  //引数がNaN
  1147:            Double.isNaN (zd) ? XEiJ.REG_CCR_C :  //引数がNaNでないのに結果がNaNのときはエラー
  1148:            Double.isInfinite (xd) ? 0 :  //引数が±Inf
  1149:            Double.isInfinite (zd) ? XEiJ.REG_CCR_V | XEiJ.REG_CCR_C :  //引数が±Infでないのに結果が±Infのときはオーバーフロー
  1150:            0);
  1151:   }  //fpkCOSH()
  1152: 
  1153:   //fpkTANH ()
  1154:   //  $FE43  __TANH
  1155:   //  64bit浮動小数点数の双曲線正接
  1156:   //  <d0d1.d:64bit浮動小数点数。x
  1157:   //  >d0d1.d:64bit浮動小数点数。tanh(x)
  1158:   public static void fpkTANH () {
  1159:     //tanh([int,int]→[long]→double)→[long]→[int,int]
  1160:     long l = Double.doubleToLongBits (Math.tanh (Double.longBitsToDouble ((long) XEiJ.regRn[0] << 32 | 0xffffffffL & XEiJ.regRn[1])));
  1161:     if (FPK_FPCP_NAN && l == 0x7ff8000000000000L) {
  1162:       l = 0x7fffffffffffffffL;
  1163:     }
  1164:     XEiJ.regRn[0] = (int) (l >>> 32);
  1165:     XEiJ.regRn[1] = (int) l;
  1166:   }  //fpkTANH()
  1167: 
  1168:   //fpkATANH ()
  1169:   //  $FE44  __ATANH
  1170:   //  64bit浮動小数点数の逆双曲線正接
  1171:   //  <d0d1.d:64bit浮動小数点数。x
  1172:   //  >d0d1.d:64bit浮動小数点数。atanh(x)
  1173:   //  >ccr:cs=x<=-1||1<=x
  1174:   public static void fpkATANH () {
  1175:     //atanh([int,int]→[long]→double)→[long]→[int,int]
  1176:     double d = Double.longBitsToDouble ((long) XEiJ.regRn[0] << 32 | 0xffffffffL & XEiJ.regRn[1]);
  1177:     if (true) {
  1178:       QFP.fpsr = 0;
  1179:       d = new QFP (d).atanh ().getd ();
  1180:       XEiJ.regCCR = (QFP.fpsr & (QFP.QFP_OE | QFP.QFP_DZ)) != 0 ? XEiJ.REG_CCR_C : 0;
  1181:     } else {
  1182:       double s = Math.signum (d);
  1183:       double a = Math.abs (d);
  1184:       if (a < 1.0) {
  1185:         d = s * (Math.log1p (a) - Math.log1p (-a)) * 0.5;  //Math.atanh(double)がない
  1186:         XEiJ.regCCR = 0;
  1187:       } else if (a == 1.0) {
  1188:         d = s * Double.POSITIVE_INFINITY;
  1189:         XEiJ.regCCR = XEiJ.REG_CCR_C;
  1190:       } else {
  1191:         d = Double.NaN;
  1192:         XEiJ.regCCR = XEiJ.REG_CCR_C;
  1193:       }
  1194:     }
  1195:     long l = Double.doubleToLongBits (d);
  1196:     if (FPK_FPCP_NAN && l == 0x7ff8000000000000L) {
  1197:       l = 0x7fffffffffffffffL;
  1198:     }
  1199:     XEiJ.regRn[0] = (int) (l >>> 32);
  1200:     XEiJ.regRn[1] = (int) l;
  1201:   }  //fpkATANH()
  1202: 
  1203:   //fpkASIN ()
  1204:   //  $FE45  __ASIN
  1205:   //  64bit浮動小数点数の逆正弦
  1206:   //  <d0d1.d:64bit浮動小数点数。x
  1207:   //  >d0d1.d:64bit浮動小数点数。asin(x)
  1208:   //  >ccr:cs=x<-1||1<x
  1209:   public static void fpkASIN () {
  1210:     //asin([int,int]→[long]→double)→[long]→[int,int]
  1211:     double d = Double.longBitsToDouble ((long) XEiJ.regRn[0] << 32 | 0xffffffffL & XEiJ.regRn[1]);
  1212:     if (d < -1.0 || 1.0 < d) {  //定義域の外。±1,NaNを含まない
  1213:       d = Double.NaN;
  1214:       XEiJ.regCCR = XEiJ.REG_CCR_C;
  1215:     } else {  //定義域の中。±1,NaNを含む
  1216:       d = Math.asin (d);
  1217:       XEiJ.regCCR = 0;
  1218:     }
  1219:     long l = Double.doubleToLongBits (d);
  1220:     if (FPK_FPCP_NAN && l == 0x7ff8000000000000L) {
  1221:       l = 0x7fffffffffffffffL;
  1222:     }
  1223:     XEiJ.regRn[0] = (int) (l >>> 32);
  1224:     XEiJ.regRn[1] = (int) l;
  1225:   }  //fpkASIN()
  1226: 
  1227:   //fpkACOS ()
  1228:   //  $FE46  __ACOS
  1229:   //  64bit浮動小数点数の逆余弦
  1230:   //  <d0d1.d:64bit浮動小数点数。x
  1231:   //  >d0d1.d:64bit浮動小数点数。acos(x)
  1232:   //  >ccr:cs=x<-1||1<x
  1233:   public static void fpkACOS () {
  1234:     //acos([int,int]→[long]→double)→[long]→[int,int]
  1235:     double d = Double.longBitsToDouble ((long) XEiJ.regRn[0] << 32 | 0xffffffffL & XEiJ.regRn[1]);
  1236:     if (d < -1.0 || 1.0 < d) {  //定義域の外。±1,NaNを含まない
  1237:       d = Double.NaN;
  1238:       XEiJ.regCCR = XEiJ.REG_CCR_C;
  1239:     } else {  //定義域の中。±1,NaNを含む
  1240:       d = Math.acos (d);
  1241:       XEiJ.regCCR = 0;
  1242:     }
  1243:     long l = Double.doubleToLongBits (d);
  1244:     if (FPK_FPCP_NAN && l == 0x7ff8000000000000L) {
  1245:       l = 0x7fffffffffffffffL;
  1246:     }
  1247:     XEiJ.regRn[0] = (int) (l >>> 32);
  1248:     XEiJ.regRn[1] = (int) l;
  1249:   }  //fpkACOS()
  1250: 
  1251:   //fpkLOG10 ()
  1252:   //  $FE47  __LOG10
  1253:   //  64bit浮動小数点数の常用対数
  1254:   //  <d0d1.d:64bit浮動小数点数。x
  1255:   //  >d0d1.d:64bit浮動小数点数。log10(x)
  1256:   //  >ccr:0=エラーなし,C=x<0,Z|C=x==0
  1257:   public static void fpkLOG10 () {
  1258:     //log10([int,int]→[long]→double)→[long]→[int,int]
  1259:     double xd = Double.longBitsToDouble ((long) XEiJ.regRn[0] << 32 | 0xffffffffL & XEiJ.regRn[1]);
  1260:     double zd = Math.log10 (xd);
  1261:     long l = Double.doubleToLongBits (zd);
  1262:     if (FPK_FPCP_NAN && l == 0x7ff8000000000000L) {
  1263:       l = 0x7fffffffffffffffL;
  1264:     }
  1265:     XEiJ.regRn[0] = (int) (l >>> 32);
  1266:     XEiJ.regRn[1] = (int) l;
  1267:     XEiJ.regCCR = (Double.isNaN (xd) ? 0 :  //引数がNaN
  1268:            Double.isNaN (zd) ? XEiJ.REG_CCR_C :  //引数がNaNでないのに結果がNaNのときはエラー。log10(-x)=NaN
  1269:            Double.isInfinite (xd) ? 0 :  //引数が±Inf
  1270:            Double.isInfinite (zd) ? XEiJ.REG_CCR_Z | XEiJ.REG_CCR_C :  //引数が±Infでないのに結果が±Infのときはエラー。log10(±0)=-Inf
  1271:            0);
  1272:   }  //fpkLOG10()
  1273: 
  1274:   //fpkLOG2 ()
  1275:   //  $FE48  __LOG2
  1276:   //  64bit浮動小数点数の二進対数
  1277:   //  <d0d1.d:64bit浮動小数点数。x
  1278:   //  >d0d1.d:64bit浮動小数点数。log2(x)
  1279:   //  >ccr:0=エラーなし,C=x<0,Z|C=x==0
  1280:   public static void fpkLOG2 () {
  1281:     //log2([int,int]→[long]→double)→[long]→[int,int]
  1282:     double xd = Double.longBitsToDouble ((long) XEiJ.regRn[0] << 32 | 0xffffffffL & XEiJ.regRn[1]);
  1283:     double zd = Math.log (xd) / 0.69314718055994530941723212146;  //log(2)。Math.log2(double)がない
  1284:     long l = Double.doubleToLongBits (zd);
  1285:     if (FPK_FPCP_NAN && l == 0x7ff8000000000000L) {
  1286:       l = 0x7fffffffffffffffL;
  1287:     }
  1288:     XEiJ.regRn[0] = (int) (l >>> 32);
  1289:     XEiJ.regRn[1] = (int) l;
  1290:     XEiJ.regCCR = (Double.isNaN (xd) ? 0 :  //引数がNaN
  1291:            Double.isNaN (zd) ? XEiJ.REG_CCR_C :  //引数がNaNでないのに結果がNaNのときはエラー。log2(-x)=NaN
  1292:            Double.isInfinite (xd) ? 0 :  //引数が±Inf
  1293:            Double.isInfinite (zd) ? XEiJ.REG_CCR_Z | XEiJ.REG_CCR_C :  //引数が±Infでないのに結果が±Infのときはエラー。log2(±0)=-Inf
  1294:            0);
  1295:   }  //fpkLOG2()
  1296: 
  1297:   //fpkDFREXP ()
  1298:   //  $FE49  __DFREXP
  1299:   //  64bit浮動小数点数の分解
  1300:   //  <d0d1.d:64bit浮動小数点数。x
  1301:   //  >d0d1.d:xの指数部を0にした値。x==0のときは0
  1302:   //  >d2.l:xの指数部。x==0のときは0
  1303:   public static void fpkDFREXP () {
  1304:     int h = XEiJ.regRn[0];
  1305:     if (h << 1 == 0 && XEiJ.regRn[1] == 0) {  //0のとき
  1306:       XEiJ.regRn[0] = 0;
  1307:       XEiJ.regRn[2] = 0;
  1308:     } else {  //0でないとき
  1309:       XEiJ.regRn[0] = (h & 0x800fffff) | 0x3ff00000;  //符号と仮数部を残して指数部を0にする
  1310:       XEiJ.regRn[2] = (h >>> 20 & 0x7ff) - 0x3ff;
  1311:     }
  1312:   }  //fpkDFREXP()
  1313: 
  1314:   //fpkDLDEXP ()
  1315:   //  $FE4A  __DLDEXP
  1316:   //  64bit浮動小数点数の合成
  1317:   //  <d0d1.d:64bit浮動小数点数。x
  1318:   //  <d2.l:xの指数部に加える値。y
  1319:   //  >d0d1.d:xの指数部にyを加えた値。x==0のときは0。エラーのときは変化しない
  1320:   //  >ccr:cs=指数部が範囲外
  1321:   public static void fpkDLDEXP () {
  1322:     int h = XEiJ.regRn[0];
  1323:     if (h << 1 == 0 && XEiJ.regRn[1] == 0) {  //0のとき
  1324:       XEiJ.regRn[0] = 0;
  1325:       XEiJ.regCCR = 0;
  1326:     } else {  //0でないとき
  1327:       int t = (h >>> 20 & 0x7ff) + XEiJ.regRn[2];
  1328:       if ((t & ~0x7ff) != 0) {  //指数部が範囲外
  1329:         XEiJ.regCCR = XEiJ.REG_CCR_C;
  1330:       } else {
  1331:         XEiJ.regRn[0] = (h & 0x800fffff) | t << 20;  //符号と仮数部を残して指数部を交換する
  1332:         XEiJ.regCCR = 0;
  1333:       }
  1334:     }
  1335:   }  //fpkDLDEXP()
  1336: 
  1337:   //fpkDADDONE ()
  1338:   //  $FE4B  __DADDONE
  1339:   //  64bit浮動小数点数に1を加える
  1340:   //  <d0d1.d:64bit浮動小数点数。x
  1341:   //  >d0d1.d:64bit浮動小数点数。x+1
  1342:   public static void fpkDADDONE () {
  1343:     //([int,int]→[long]→double)+1→[long]→[int,int]
  1344:     double xd = Double.longBitsToDouble ((long) XEiJ.regRn[0] << 32 | 0xffffffffL & XEiJ.regRn[1]);
  1345:     double zd = xd + 1.0;
  1346:     long l = Double.doubleToLongBits (zd);
  1347:     if (FPK_FPCP_NAN && l == 0x7ff8000000000000L) {
  1348:       l = 0x7fffffffffffffffL;
  1349:     }
  1350:     XEiJ.regRn[0] = (int) (l >>> 32);
  1351:     XEiJ.regRn[1] = (int) l;
  1352:     XEiJ.regCCR = Double.isInfinite (zd) && !Double.isInfinite (xd) ? XEiJ.REG_CCR_V | XEiJ.REG_CCR_C : 0;  //結果が±Infだが引数が±Infでないときはオーバーフロー
  1353:   }  //fpkDADDONE()
  1354: 
  1355:   //fpkDSUBONE ()
  1356:   //  $FE4C  __DSUBONE
  1357:   //  64bit浮動小数点数から1を引く
  1358:   //  <d0d1.d:64bit浮動小数点数。x
  1359:   //  >d0d1.d:64bit浮動小数点数。x-1
  1360:   public static void fpkDSUBONE () {
  1361:     //([int,int]→[long]→double)-1→[long]→[int,int]
  1362:     double xd = Double.longBitsToDouble ((long) XEiJ.regRn[0] << 32 | 0xffffffffL & XEiJ.regRn[1]);
  1363:     double zd = xd - 1.0;
  1364:     long l = Double.doubleToLongBits (zd);
  1365:     if (FPK_FPCP_NAN && l == 0x7ff8000000000000L) {
  1366:       l = 0x7fffffffffffffffL;
  1367:     }
  1368:     XEiJ.regRn[0] = (int) (l >>> 32);
  1369:     XEiJ.regRn[1] = (int) l;
  1370:     XEiJ.regCCR = Double.isInfinite (zd) && !Double.isInfinite (xd) ? XEiJ.REG_CCR_V | XEiJ.REG_CCR_C : 0;  //結果が±Infだが引数が±Infでないときはオーバーフロー
  1371:   }  //fpkDSUBONE()
  1372: 
  1373:   //fpkDDIVTWO ()
  1374:   //  $FE4D  __DDIVTWO
  1375:   //  64bit浮動小数点数を2で割る
  1376:   //  バグ
  1377:   //    FLOAT2.X 2.02/2.03は__DDIVTWO(0x0010000000000000L)がエラーになる
  1378:   //    FLOAT4.X 1.02は__DDIVTWO(0x0010000000000000L)がエラーになる
  1379:   //    FLOAT2.X 2.02/2.03は__DDIVTWO(0x000fffffffffffffL)がエラーになる
  1380:   //    FLOAT4.X 1.02は__DDIVTWO(0x000fffffffffffffL)がエラーになる
  1381:   //    FLOAT2.X 2.02/2.03は__DDIVTWO(0x0000000000000001L)が0x0000000000000001Lになる
  1382:   //    FLOAT4.X 1.02は__DDIVTWO(0x0000000000000001L)が0x0000000000000001Lになる
  1383:   //    FLOAT2.X 2.02/2.03は__DDIVTWO(-0)がエラーになる
  1384:   //    FLOAT4.X 1.02は__DDIVTWO(-0)がエラーになる
  1385:   //    FLOAT2.X 2.02/2.03は__DDIVTWO(0x8000000000000001L)がエラーになる
  1386:   //    FLOAT4.X 1.02は__DDIVTWO(0x8000000000000001L)がエラーになる
  1387:   //    FLOAT2.X 2.02/2.03は__DDIVTWO(0x800fffffffffffffL)がエラーになる
  1388:   //    FLOAT4.X 1.02は__DDIVTWO(0x800fffffffffffffL)がエラーになる
  1389:   //    FLOAT2.X 2.02/2.03は__DDIVTWO(0x8010000000000000L)がエラーになる
  1390:   //    FLOAT4.X 1.02は__DDIVTWO(0x8010000000000000L)がエラーになる
  1391:   //  <d0d1.d:64bit浮動小数点数。x
  1392:   //  >d0d1.d:64bit浮動小数点数。x/2
  1393:   //  >ccr:cs=アンダーフロー
  1394:   public static void fpkDDIVTWO () {
  1395:     //([int,int]→[long]→double)/2→[long]→[int,int]
  1396:     double xd = Double.longBitsToDouble ((long) XEiJ.regRn[0] << 32 | 0xffffffffL & XEiJ.regRn[1]);
  1397:     double zd = xd * 0.5;
  1398:     long l = Double.doubleToLongBits (zd);
  1399:     if (FPK_FPCP_NAN && l == 0x7ff8000000000000L) {
  1400:       l = 0x7fffffffffffffffL;
  1401:     }
  1402:     XEiJ.regRn[0] = (int) (l >>> 32);
  1403:     XEiJ.regRn[1] = (int) l;
  1404:     XEiJ.regCCR = zd == 0.0 && xd != 0.0 ? XEiJ.REG_CCR_C : 0;  //結果が±0だが引数が±0でないときはアンダーフロー
  1405:   }  //fpkDDIVTWO()
  1406: 
  1407:   //fpkDIEECNV ()
  1408:   //  $FE4E  __DIEECNV
  1409:   //  64bit浮動小数点数をIEEEフォーマットに変換する(FLOAT1.X以外は何もしない)
  1410:   //  <d0d1.d:64bit浮動小数点数。x
  1411:   //  >d0d1.d:64bit浮動小数点数。x
  1412:   public static void fpkDIEECNV () {
  1413:   }  //fpkDIEECNV()
  1414: 
  1415:   //fpkIEEDCNV ()
  1416:   //  $FE4F  __IEEDCNV
  1417:   //  64bit浮動小数点数をIEEEフォーマットから変換する(FLOAT1.X以外は何もしない)
  1418:   //  <d0d1.d:64bit浮動小数点数。x
  1419:   //  >d0d1.d:64bit浮動小数点数。x
  1420:   public static void fpkIEEDCNV () {
  1421:   }  //fpkIEEDCNV()
  1422: 
  1423:   //fpkFTST ()
  1424:   //  $FE58  __FTST
  1425:   //  32bit浮動小数点数と0の比較
  1426:   //  x<=>0
  1427:   //  <d0.s:32bit浮動小数点数。x
  1428:   //  >ccr:lt=x<0,eq=x==0,gt=x>0
  1429:   public static void fpkFTST () {
  1430:     if (true) {
  1431:       int h = XEiJ.regRn[0];
  1432:       XEiJ.regCCR = h << 1 == 0 ? XEiJ.REG_CCR_Z : 0 <= h ? 0 : XEiJ.REG_CCR_N;  //NaNのときは0
  1433:     } else {
  1434:       //([int]→float)<=>0
  1435:       float f = Float.intBitsToFloat (XEiJ.regRn[0]);
  1436:       XEiJ.regCCR = f < 0.0F ? XEiJ.REG_CCR_N : f == 0.0F ? XEiJ.REG_CCR_Z : 0;  //NaNのときは0
  1437:     }
  1438:   }  //fpkFTST()
  1439: 
  1440:   //fpkFCMP ()
  1441:   //  $FE59  __FCMP
  1442:   //  32bit浮動小数点数の比較
  1443:   //  x<=>y
  1444:   //  <d0.s:32bit浮動小数点数。x
  1445:   //  <d1.s:32bit浮動小数点数。y
  1446:   //  >ccr:lt=x<y,eq=x==y,gt=x>y
  1447:   public static void fpkFCMP () {
  1448:     //([int]→float)<=>([int]→float)
  1449:     float xf = Float.intBitsToFloat (XEiJ.regRn[0]);
  1450:     float yf = Float.intBitsToFloat (XEiJ.regRn[1]);
  1451:     XEiJ.regCCR = xf < yf ? XEiJ.REG_CCR_N | XEiJ.REG_CCR_C : xf == yf ? XEiJ.REG_CCR_Z : 0;  //どちらかがNaNのときは0
  1452:   }  //fpkFCMP()
  1453: 
  1454:   //fpkFNEG ()
  1455:   //  $FE5A  __FNEG
  1456:   //  32bit浮動小数点数の符号反転
  1457:   //  <d0.s:32bit浮動小数点数。x
  1458:   //  >d0.s:32bit浮動小数点数。-x
  1459:   public static void fpkFNEG () {
  1460:     //-([int]→float)→[int]
  1461:     int h = Float.floatToIntBits (-Float.intBitsToFloat (XEiJ.regRn[0]));
  1462:     if (FPK_FPCP_NAN && h == 0x7fc00000) {
  1463:       h = 0x7fffffff;
  1464:     }
  1465:     XEiJ.regRn[0] = h;
  1466:   }  //fpkFNEG()
  1467: 
  1468:   //fpkFADD ()
  1469:   //  $FE5B  __FADD
  1470:   //  32bit浮動小数点数の加算
  1471:   //  <d0.s:32bit浮動小数点数。被加算数x
  1472:   //  <d1.s:32bit浮動小数点数。加算数y
  1473:   //  >d0.s:32bit浮動小数点数。和x+y
  1474:   //  >ccr:cs=エラー,vs=オーバーフロー
  1475:   public static void fpkFADD () {
  1476:     //([int]→float)+([int]→float)→[int]
  1477:     float xf = Float.intBitsToFloat (XEiJ.regRn[0]);
  1478:     float yf = Float.intBitsToFloat (XEiJ.regRn[1]);
  1479:     float zf = xf + yf;
  1480:     int h = Float.floatToIntBits (zf);
  1481:     if (FPK_FPCP_NAN && h == 0x7fc00000) {
  1482:       h = 0x7fffffff;
  1483:     }
  1484:     XEiJ.regRn[0] = h;
  1485:     XEiJ.regCCR = (Float.isNaN (xf) || Float.isNaN (yf) ? 0 :  //引数がNaN
  1486:            Float.isNaN (zf) ? XEiJ.REG_CCR_C :  //引数がNaNでないのに結果がNaNのときはエラー。(+Inf)+(-Inf)=NaN
  1487:            Float.isInfinite (xf) || Float.isInfinite (yf) ? 0 :  //引数が±Inf
  1488:            Float.isInfinite (zf) ? XEiJ.REG_CCR_V | XEiJ.REG_CCR_C :  //引数が±Infでないのに結果が±Infのときはオーバーフロー
  1489:            0);
  1490:   }  //fpkFADD()
  1491: 
  1492:   //fpkFSUB ()
  1493:   //  $FE5C  __FSUB
  1494:   //  32bit浮動小数点数の減算
  1495:   //  <d0.s:32bit浮動小数点数。被減算数x
  1496:   //  <d1.s:32bit浮動小数点数。減算数y
  1497:   //  >d0.s:32bit浮動小数点数。差x-y
  1498:   //  >ccr:cs=エラー,vs=オーバーフロー
  1499:   public static void fpkFSUB () {
  1500:     //([int]→float)-([int]→float)→[int]
  1501:     float xf = Float.intBitsToFloat (XEiJ.regRn[0]);
  1502:     float yf = Float.intBitsToFloat (XEiJ.regRn[1]);
  1503:     float zf = xf - yf;
  1504:     int h = Float.floatToIntBits (zf);
  1505:     if (FPK_FPCP_NAN && h == 0x7fc00000) {
  1506:       h = 0x7fffffff;
  1507:     }
  1508:     XEiJ.regRn[0] = h;
  1509:     XEiJ.regCCR = (Float.isNaN (xf) || Float.isNaN (yf) ? 0 :  //引数がNaN
  1510:            Float.isNaN (zf) ? XEiJ.REG_CCR_C :  //引数がNaNでないのに結果がNaNのときはエラー。(+Inf)-(+Inf)=NaN
  1511:            Float.isInfinite (xf) || Float.isInfinite (yf) ? 0 :  //引数が±Inf
  1512:            Float.isInfinite (zf) ? XEiJ.REG_CCR_V | XEiJ.REG_CCR_C :  //引数が±Infでないのに結果が±Infのときはオーバーフロー
  1513:            0);
  1514:   }  //fpkFSUB()
  1515: 
  1516:   //fpkFMUL ()
  1517:   //  $FE5D  __FMUL
  1518:   //  32bit浮動小数点数の乗算
  1519:   //  <d0.s:32bit浮動小数点数。被乗数x
  1520:   //  <d1.s:32bit浮動小数点数。乗数y
  1521:   //  >d0.s:32bit浮動小数点数。積x*y
  1522:   //  >ccr:cs=エラー,vs=オーバーフロー
  1523:   public static void fpkFMUL () {
  1524:     //([int]→float)*([int]→float)→[int]
  1525:     float xf = Float.intBitsToFloat (XEiJ.regRn[0]);
  1526:     float yf = Float.intBitsToFloat (XEiJ.regRn[1]);
  1527:     float zf = xf * yf;
  1528:     int h = Float.floatToIntBits (zf);
  1529:     if (FPK_FPCP_NAN && h == 0x7fc00000) {
  1530:       h = 0x7fffffff;
  1531:     }
  1532:     XEiJ.regRn[0] = h;
  1533:     XEiJ.regCCR = (Float.isNaN (xf) || Float.isNaN (yf) ? 0 :  //引数がNaN
  1534:            Float.isNaN (zf) ? XEiJ.REG_CCR_C :  //引数がNaNでないのに結果がNaNのときはエラー。(±0)*(±Inf)=NaN
  1535:            Float.isInfinite (xf) || Float.isInfinite (yf) ? 0 :  //引数が±Inf
  1536:            Float.isInfinite (zf) ? XEiJ.REG_CCR_V | XEiJ.REG_CCR_C :  //引数が±Infでないのに結果が±Infのときはオーバーフロー
  1537:            0);
  1538:   }  //fpkFMUL()
  1539: 
  1540:   //fpkFDIV ()
  1541:   //  $FE5E  __FDIV
  1542:   //  32bit浮動小数点数の除算
  1543:   //  <d0.s:32bit浮動小数点数。被除数x
  1544:   //  <d1.s:32bit浮動小数点数。除数y
  1545:   //  >d0.s:32bit浮動小数点数。商x/y。ゼロ除算のときは不定
  1546:   //  >ccr:cs=エラー,eq=ゼロ除算,vs=オーバーフロー
  1547:   public static void fpkFDIV () {
  1548:     //([int]→float)/([int]→float)→[int]
  1549:     float xf = Float.intBitsToFloat (XEiJ.regRn[0]);
  1550:     float yf = Float.intBitsToFloat (XEiJ.regRn[1]);
  1551:     float zf = xf / yf;
  1552:     int h = Float.floatToIntBits (zf);
  1553:     if (FPK_FPCP_NAN && h == 0x7fc00000) {
  1554:       h = 0x7fffffff;
  1555:     }
  1556:     XEiJ.regRn[0] = h;
  1557:     XEiJ.regCCR = (Float.isNaN (xf) || Float.isNaN (yf) ? 0 :  //引数がNaN
  1558:            Float.isNaN (zf) ? XEiJ.REG_CCR_C :  //引数がNaNでないのに結果がNaNのときはエラー。(±0)/(±0)=NaN
  1559:            Float.isInfinite (xf) || Float.isInfinite (yf) ? 0 :  //引数が±Inf。(±Inf)/(±0)=(±Inf)
  1560:            yf == 0.0F ? XEiJ.REG_CCR_Z | XEiJ.REG_CCR_C :  //除数が±0のときはゼロ除算
  1561:            Float.isInfinite (zf) ? XEiJ.REG_CCR_V | XEiJ.REG_CCR_C :  //引数が±Infでないのに結果が±Infのときはオーバーフロー
  1562:            0);
  1563:   }  //fpkFDIV()
  1564: 
  1565:   //fpkFMOD ()
  1566:   //  $FE5F  __FMOD
  1567:   //  32bit浮動小数点数の剰余算
  1568:   //  <d0.s:32bit浮動小数点数。被除数x
  1569:   //  <d1.s:32bit浮動小数点数。除数y
  1570:   //  >d0.s:32bit浮動小数点数。余りx%y。ゼロ除算のときは不定
  1571:   //  >ccr:cs=エラー,eq=ゼロ除算
  1572:   public static void fpkFMOD () {
  1573:     //([int]→float)%([int]→float)→[int]
  1574:     float xf = Float.intBitsToFloat (XEiJ.regRn[0]);
  1575:     float yf = Float.intBitsToFloat (XEiJ.regRn[1]);
  1576:     float zf = xf % yf;
  1577:     int h = Float.floatToIntBits (zf);
  1578:     if (FPK_FPCP_NAN && h == 0x7fc00000) {
  1579:       h = 0x7fffffff;
  1580:     }
  1581:     XEiJ.regRn[0] = h;
  1582:     XEiJ.regCCR = (Float.isNaN (xf) || Float.isNaN (yf) ? 0 :  //引数がNaN
  1583:            yf == 0.0F ? XEiJ.REG_CCR_Z | XEiJ.REG_CCR_C :  //除数が0のときはゼロ除算。(±Inf)%(±0)=NaN, x%(±0)=(±Inf)
  1584:            Float.isNaN (zf) ? XEiJ.REG_CCR_C :  //引数がNaNでないのに結果がNaNのときはエラー。(±Inf)%y=NaN
  1585:            Float.isInfinite (xf) || Float.isInfinite (yf) ? 0 :  //引数が±Inf
  1586:            Float.isInfinite (zf) ? XEiJ.REG_CCR_V | XEiJ.REG_CCR_C :  //引数が±Infでないのに結果が±Infのときはオーバーフロー
  1587:            0);
  1588:   }  //fpkFMOD()
  1589: 
  1590:   //fpkFABS ()
  1591:   //  $FE60  __FABS
  1592:   //  32bit浮動小数点数の絶対値
  1593:   //  <d0.s:32bit浮動小数点数。x
  1594:   //  >d0.s:32bit浮動小数点数。abs(x)
  1595:   public static void fpkFABS () {
  1596:     //abs([int]→float)→[int]
  1597:     int h = Float.floatToIntBits (Math.abs (Float.intBitsToFloat (XEiJ.regRn[0])));
  1598:     if (FPK_FPCP_NAN && h == 0x7fc00000) {
  1599:       h = 0x7fffffff;
  1600:     }
  1601:     XEiJ.regRn[0] = h;
  1602:   }  //fpkFABS()
  1603: 
  1604:   //fpkFCEIL ()
  1605:   //  $FE61  __FCEIL
  1606:   //  32bit浮動小数点数の天井関数(引数を下回らない最小の整数)
  1607:   //  <d0.s:32bit浮動小数点数。x
  1608:   //  >d0.s:32bit浮動小数点数。ceil(x)
  1609:   public static void fpkFCEIL () {
  1610:     //ceil([int]→float→double)→float→[int]
  1611:     int h = Float.floatToIntBits ((float) Math.ceil ((double) Float.intBitsToFloat (XEiJ.regRn[0])));
  1612:     if (FPK_FPCP_NAN && h == 0x7fc00000) {
  1613:       h = 0x7fffffff;
  1614:     }
  1615:     XEiJ.regRn[0] = h;
  1616:   }  //fpkFCEIL()
  1617: 
  1618:   //fpkFFIX ()
  1619:   //  $FE62  __FFIX
  1620:   //  32bit浮動小数点数の切り落とし関数(絶対値について引数を上回らない最大の整数)
  1621:   //  <d0.s:32bit浮動小数点数。x
  1622:   //  >d0.s:32bit浮動小数点数。trunc(x)
  1623:   public static void fpkFFIX () {
  1624:     //trunc([int]→float→double)→float→[int]
  1625:     float f = Float.intBitsToFloat (XEiJ.regRn[0]);
  1626:     int h = Float.floatToIntBits (0.0 <= f ? (float) Math.floor ((double) f) : (float) Math.ceil ((double) f));  //0<=-0だがMath.floor(-0)=-0なので問題ない
  1627:     if (FPK_FPCP_NAN && h == 0x7fc00000) {
  1628:       h = 0x7fffffff;
  1629:     }
  1630:     XEiJ.regRn[0] = h;
  1631:   }  //fpkFFIX()
  1632: 
  1633:   //fpkFFLOOR ()
  1634:   //  $FE63  __FFLOOR
  1635:   //  32bit浮動小数点数の床関数(引数を上回らない最大の整数)
  1636:   //  <d0.s:32bit浮動小数点数。x
  1637:   //  >d0.s:32bit浮動小数点数。floor(x)
  1638:   public static void fpkFFLOOR () {
  1639:     //floor([int]→float→double)→float→[int]
  1640:     int h = Float.floatToIntBits ((float) Math.floor ((double) Float.intBitsToFloat (XEiJ.regRn[0])));
  1641:     if (FPK_FPCP_NAN && h == 0x7fc00000) {
  1642:       h = 0x7fffffff;
  1643:     }
  1644:     XEiJ.regRn[0] = h;
  1645:   }  //fpkFFLOOR()
  1646: 
  1647:   //fpkFFRAC ()
  1648:   //  $FE64  __FFRAC
  1649:   //  32bit浮動小数点数の幹小数部
  1650:   //  <d0.s:32bit浮動小数点数。x
  1651:   //  >d0.s:32bit浮動小数点数。frac(x)=copysign(x-trunc(x),x)
  1652:   public static void fpkFFRAC () {
  1653:     //frac([int]→float→double)→float→[int]
  1654:     int h = XEiJ.regRn[0];
  1655:     float f = Float.intBitsToFloat (h);
  1656:     h = (Float.isNaN (f) ? Float.floatToIntBits (Float.NaN) :  //frac(NaN)=NaN
  1657:          Float.isInfinite (f) ? h & 0x80000000 :  //frac(±Inf)=±0
  1658:          Float.floatToIntBits (0 <= h ? f - (float) Math.floor ((double) f) : -(-f - (float) Math.floor ((double) -f))));  //0<=-0なので0<=f?~は不可
  1659:     if (FPK_FPCP_NAN && h == 0x7fc00000) {
  1660:       h = 0x7fffffff;
  1661:     }
  1662:     XEiJ.regRn[0] = h;
  1663:   }  //fpkFFRAC()
  1664: 
  1665:   //fpkFSGN ()
  1666:   //  $FE65  __FSGN
  1667:   //  32bit浮動小数点数の符号
  1668:   //  <d0.s:32bit浮動小数点数。x
  1669:   //  >d0.s:32bit浮動小数点数。signum(x)
  1670:   public static void fpkFSGN () {
  1671:     //signum([int]→float)→[int]
  1672:     int h = Float.floatToIntBits (Math.signum (Float.intBitsToFloat (XEiJ.regRn[0])));  //Math.signum(-0)は-0
  1673:     if (FPK_FPCP_NAN && h == 0x7fc00000) {
  1674:       h = 0x7fffffff;
  1675:     }
  1676:     XEiJ.regRn[0] = h;
  1677:   }  //fpkFSGN()
  1678: 
  1679:   //fpkFSIN ()
  1680:   //  $FE66  __FSIN
  1681:   //  32bit浮動小数点数の正弦
  1682:   //  <d0.s:32bit浮動小数点数。x
  1683:   //  >d0.s:32bit浮動小数点数。sin(x)
  1684:   //  >ccr:x=±Inf。C以外は不定
  1685:   public static void fpkFSIN () {
  1686:     //sin([int]→float→double)→float→[int]
  1687:     float xf = Float.intBitsToFloat (XEiJ.regRn[0]);
  1688:     float zf = (float) Math.sin ((double) xf);
  1689:     int h = Float.floatToIntBits (zf);
  1690:     if (FPK_FPCP_NAN && h == 0x7fc00000) {
  1691:       h = 0x7fffffff;
  1692:     }
  1693:     XEiJ.regRn[0] = h;
  1694:     XEiJ.regCCR = !Float.isNaN (xf) && Float.isNaN (zf) ? XEiJ.REG_CCR_C : 0;  //引数がNaNでないのに結果がNaNのときはエラー。sin(±Inf)=NaN
  1695:   }  //fpkFSIN()
  1696: 
  1697:   //fpkFCOS ()
  1698:   //  $FE67  __FCOS
  1699:   //  32bit浮動小数点数の余弦
  1700:   //  <d0.s:32bit浮動小数点数。x
  1701:   //  >d0.s:32bit浮動小数点数。cos(x)
  1702:   //  >ccr:x=±Inf。C以外は不定
  1703:   public static void fpkFCOS () {
  1704:     //cos([int]→float→double)→float→[int]
  1705:     float xf = Float.intBitsToFloat (XEiJ.regRn[0]);
  1706:     float zf = (float) Math.cos ((double) xf);
  1707:     int h = Float.floatToIntBits (zf);
  1708:     if (FPK_FPCP_NAN && h == 0x7fc00000) {
  1709:       h = 0x7fffffff;
  1710:     }
  1711:     XEiJ.regRn[0] = h;
  1712:     XEiJ.regCCR = !Float.isNaN (xf) && Float.isNaN (zf) ? XEiJ.REG_CCR_C : 0;  //引数がNaNでないのに結果がNaNのときはエラー。cos(±Inf)=NaN
  1713:   }  //fpkFCOS()
  1714: 
  1715:   //fpkFTAN ()
  1716:   //  $FE68  __FTAN
  1717:   //  32bit浮動小数点数の正接
  1718:   //  <d0.s:32bit浮動小数点数。x
  1719:   //  >d0.s:32bit浮動小数点数。tan(x)
  1720:   //  >ccr:x=±Inf。C以外は不定
  1721:   public static void fpkFTAN () {
  1722:     //tan([int]→float→double)→float→[int]
  1723:     float xf = Float.intBitsToFloat (XEiJ.regRn[0]);
  1724:     float zf = (float) Math.tan ((double) xf);
  1725:     int h = Float.floatToIntBits (zf);
  1726:     if (FPK_FPCP_NAN && h == 0x7fc00000) {
  1727:       h = 0x7fffffff;
  1728:     }
  1729:     XEiJ.regRn[0] = h;
  1730:     XEiJ.regCCR = !Float.isNaN (xf) && Float.isNaN (zf) ? XEiJ.REG_CCR_C : 0;  //引数がNaNでないのに結果がNaNのときはエラー。tan(±Inf)=NaN
  1731:   }  //fpkFTAN()
  1732: 
  1733:   //fpkFATAN ()
  1734:   //  $FE69  __FATAN
  1735:   //  32bit浮動小数点数の逆正接
  1736:   //  <d0.s:32bit浮動小数点数。x
  1737:   //  >d0.s:32bit浮動小数点数。atan(x)
  1738:   public static void fpkFATAN () {
  1739:     //atan([int]→float→double)→float→[int]
  1740:     int h = Float.floatToIntBits ((float) Math.atan ((double) Float.intBitsToFloat (XEiJ.regRn[0])));
  1741:     if (FPK_FPCP_NAN && h == 0x7fc00000) {
  1742:       h = 0x7fffffff;
  1743:     }
  1744:     XEiJ.regRn[0] = h;
  1745:   }  //fpkFATAN()
  1746: 
  1747:   //fpkFLOG ()
  1748:   //  $FE6A  __FLOG
  1749:   //  32bit浮動小数点数の自然対数
  1750:   //  <d0.s:32bit浮動小数点数。x
  1751:   //  >d0.s:32bit浮動小数点数。log(x)
  1752:   //  >ccr:0=エラーなし,C=x<0,Z|C=x==0
  1753:   public static void fpkFLOG () {
  1754:     //log([int]→float→double)→float→[int]
  1755:     float xf = Float.intBitsToFloat (XEiJ.regRn[0]);
  1756:     float zf = (float) Math.log ((double) xf);
  1757:     int h = Float.floatToIntBits (zf);
  1758:     if (FPK_FPCP_NAN && h == 0x7fc00000) {
  1759:       h = 0x7fffffff;
  1760:     }
  1761:     XEiJ.regRn[0] = h;
  1762:     XEiJ.regCCR = (Float.isNaN (xf) ? 0 :  //引数がNaN
  1763:            Float.isNaN (zf) ? XEiJ.REG_CCR_C :  //引数がNaNでないのに結果がNaNのときはエラー。log(-x)=NaN
  1764:            Float.isInfinite (xf) ? 0 :  //引数が±Inf
  1765:            Float.isNaN (zf) ? XEiJ.REG_CCR_Z | XEiJ.REG_CCR_C :  //引数が±Infでないのに結果が±Infのときはエラー。log(±0)=-Inf
  1766:            0);
  1767:   }  //fpkFLOG()
  1768: 
  1769:   //fpkFEXP ()
  1770:   //  $FE6B  __FEXP
  1771:   //  32bit浮動小数点数の指数関数
  1772:   //  <d0.s:32bit浮動小数点数。x
  1773:   //  >d0.s:32bit浮動小数点数。exp(x)
  1774:   //  >ccr:cs=オーバーフロー
  1775:   public static void fpkFEXP () {
  1776:     //exp([int]→float→double)→float→[int]
  1777:     int xh = XEiJ.regRn[0];
  1778:     int zh = Float.floatToIntBits ((float) Math.exp ((double) Float.intBitsToFloat (xh)));
  1779:     if (FPK_FPCP_NAN && zh == 0x7fc00000) {
  1780:       zh = 0x7fffffff;
  1781:     }
  1782:     XEiJ.regRn[0] = zh;
  1783:     XEiJ.regCCR = (zh & 0x7fc00000) == 0x7fc00000 && (xh & 0x7fc00000) != 0x7fc00000 ? XEiJ.REG_CCR_C : 0;  //結果が±Inf,NaNだが引数が±Inf,NaNでなかったときはエラー
  1784:   }  //fpkFEXP()
  1785: 
  1786:   //fpkFSQR ()
  1787:   //  $FE6C  __FSQR
  1788:   //  32bit浮動小数点数の平方根
  1789:   //  <d0.s:32bit浮動小数点数。x
  1790:   //  >d0.s:32bit浮動小数点数。sqrt(x)
  1791:   //  >ccr:cs=x<0
  1792:   public static void fpkFSQR () {
  1793:     //sqrt([int]→float→double)→float→[int]
  1794:     float xf = Float.intBitsToFloat (XEiJ.regRn[0]);
  1795:     int h = Float.floatToIntBits ((float) Math.sqrt ((double) xf));
  1796:     if (FPK_FPCP_NAN && h == 0x7fc00000) {
  1797:       h = 0x7fffffff;
  1798:     }
  1799:     XEiJ.regRn[0] = h;
  1800:     XEiJ.regCCR = xf < 0.0F ? XEiJ.REG_CCR_C : 0;  //NaNはエラーなし
  1801:   }  //fpkFSQR()
  1802: 
  1803:   //fpkFPI ()
  1804:   //  $FE6D  __FPI
  1805:   //  32bit浮動小数点数の円周率
  1806:   //  >d0.s:32bit浮動小数点数。pi
  1807:   public static void fpkFPI () {
  1808:     //pi→float→[int]
  1809:     if (true) {
  1810:       XEiJ.regRn[0] = 0x40490fdb;
  1811:     } else {
  1812:       XEiJ.regRn[0] = Float.floatToIntBits ((float) Math.PI);
  1813:     }
  1814:   }  //fpkFPI()
  1815: 
  1816:   //fpkFNPI ()
  1817:   //  $FE6E  __FNPI
  1818:   //  32bit浮動小数点数の円周率倍
  1819:   //  <d0.s:32bit浮動小数点数。x
  1820:   //  >d0.s:32bit浮動小数点数。x*pi
  1821:   //  >ccr:cs=オーバーフロー
  1822:   public static void fpkFNPI () {
  1823:     //([int]→float→double)*pi→float→[int]
  1824:     int xh = XEiJ.regRn[0];
  1825:     //  倍精度のπを倍精度で掛けて単精度に丸める
  1826:     int zh = Float.floatToIntBits ((float) ((double) Float.intBitsToFloat (xh) * Math.PI));
  1827:     if (FPK_FPCP_NAN && zh == 0x7fc00000) {
  1828:       zh = 0x7fffffff;
  1829:     }
  1830:     XEiJ.regRn[0] = zh;
  1831:     XEiJ.regCCR = (zh & 0x7fc00000) == 0x7fc00000 && (xh & 0x7fc00000) != 0x7fc00000 ? XEiJ.REG_CCR_C : 0;  //結果が±Inf,NaNだが引数が±Inf,NaNでなかったときはエラー
  1832:   }  //fpkFNPI()
  1833: 
  1834:   //fpkFPOWER ()
  1835:   //  $FE6F  __FPOWER
  1836:   //  32bit浮動小数点数の累乗
  1837:   //  <d0.s:32bit浮動小数点数。x
  1838:   //  <d1.s:32bit浮動小数点数。y
  1839:   //  >d0.s:32bit浮動小数点数。pow(x,y)
  1840:   //  >ccr:cs=オーバーフロー
  1841:   public static void fpkFPOWER () {
  1842:     //pow([int]→float→double,[int]→float→double)→float→[int]
  1843:     float xf = Float.intBitsToFloat (XEiJ.regRn[0]);
  1844:     float yf = Float.intBitsToFloat (XEiJ.regRn[1]);
  1845:     float zf = (float) Math.pow ((double) xf, (double) yf);
  1846:     int zh = Float.floatToIntBits (zf);
  1847:     if (FPK_FPCP_NAN && zh == 0x7fc00000) {
  1848:       zh = 0x7fffffff;
  1849:     }
  1850:     XEiJ.regRn[0] = zh;
  1851:     XEiJ.regCCR = (Float.isNaN (xf) || Float.isNaN (yf) ? 0 :  //引数がNaN
  1852:            Float.isNaN (zf) ? XEiJ.REG_CCR_C :  //引数がNaNでないのに結果がNaNのときはエラー
  1853:            Float.isInfinite (xf) || Float.isInfinite (yf) ? 0 :  //引数が±Inf
  1854:            Float.isNaN (zf) ? XEiJ.REG_CCR_V | XEiJ.REG_CCR_C :  //引数が±Infでないのに結果が±Infのときはオーバーフロー
  1855:            0);
  1856:   }  //fpkFPOWER()
  1857: 
  1858:   //fpkFRND ()
  1859:   //  $FE70  __FRND
  1860:   //  32bit浮動小数点数の乱数
  1861:   //  >d0.s:32bit浮動小数点数。rnd()。0以上1未満
  1862:   public static void fpkFRND () {
  1863:     //FRND()=DTOF(RND())
  1864:     long l = 0xffffffffL & fpkRndLong ();  //下位
  1865:     l |= (0x001fffffL & fpkRndLong ()) << 32;  //上位。順序に注意
  1866:     //  ここでl==0LのときLong.numberOfLeadingZeros(z)==64なので乱数の値は2^-54になる
  1867:     //  FLOATn.Xはその場合を考慮しておらず0のときも先頭の1のビットを探し続けて無限ループに陥ると思われる
  1868:     //  実際に0が53ビット並ぶことはないかも知れない
  1869:     int o = Long.numberOfLeadingZeros (l) - 11;
  1870:     l = ((long) (1022 - 1 - o) << 52) + (l << o);  //指数部を1減らしておいてbit52に移動した仮数部の先頭の1を加えている
  1871:     XEiJ.regRn[0] = Float.floatToIntBits ((float) Double.longBitsToDouble (l));
  1872:   }  //fpkFRND()
  1873: 
  1874:   //fpkFSINH ()
  1875:   //  $FE71  __FSINH
  1876:   //  32bit浮動小数点数の双曲線正弦
  1877:   //  <d0.s:32bit浮動小数点数。x
  1878:   //  >d0.s:32bit浮動小数点数。sinh(x)
  1879:   //  >ccr:cs=エラー,vs=オーバーフロー
  1880:   public static void fpkFSINH () {
  1881:     //sinh([int]→float→double)→float→[int]
  1882:     float xf = Float.intBitsToFloat (XEiJ.regRn[0]);
  1883:     float zf = (float) Math.sinh ((double) xf);
  1884:     int zh = Float.floatToIntBits (zf);
  1885:     if (FPK_FPCP_NAN && zh == 0x7fc00000) {
  1886:       zh = 0x7fffffff;
  1887:     }
  1888:     XEiJ.regRn[0] = zh;
  1889:     XEiJ.regCCR = (Float.isNaN (xf) ? 0 :  //引数がNaN
  1890:            Float.isNaN (zf) ? XEiJ.REG_CCR_C :  //引数がNaNでないのに結果がNaNのときはエラー
  1891:            Float.isInfinite (xf) ? 0 :  //引数が±Inf
  1892:            Float.isNaN (zf) ? XEiJ.REG_CCR_V | XEiJ.REG_CCR_C :  //引数が±Infでないのに結果が±Infのときはオーバーフロー
  1893:            0);
  1894:   }  //fpkFSINH()
  1895: 
  1896:   //fpkFCOSH ()
  1897:   //  $FE72  __FCOSH
  1898:   //  32bit浮動小数点数の双曲線余弦
  1899:   //  <d0.s:32bit浮動小数点数。x
  1900:   //  >d0.s:32bit浮動小数点数。cosh(x)
  1901:   //  >ccr:cs=エラー,vs=オーバーフロー
  1902:   public static void fpkFCOSH () {
  1903:     //cosh([int]→float→double)→float→[int]
  1904:     float xf = Float.intBitsToFloat (XEiJ.regRn[0]);
  1905:     float zf = (float) Math.cosh ((double) xf);
  1906:     int zh = Float.floatToIntBits (zf);
  1907:     if (FPK_FPCP_NAN && zh == 0x7fc00000) {
  1908:       zh = 0x7fffffff;
  1909:     }
  1910:     XEiJ.regRn[0] = zh;
  1911:     XEiJ.regCCR = (Float.isNaN (xf) ? 0 :  //引数がNaN
  1912:            Float.isNaN (zf) ? XEiJ.REG_CCR_C :  //引数がNaNでないのに結果がNaNのときはエラー
  1913:            Float.isInfinite (xf) ? 0 :  //引数が±Inf
  1914:            Float.isNaN (zf) ? XEiJ.REG_CCR_V | XEiJ.REG_CCR_C :  //引数が±Infでないのに結果が±Infのときはオーバーフロー
  1915:            0);
  1916:   }  //fpkFCOSH()
  1917: 
  1918:   //fpkFTANH ()
  1919:   //  $FE73  __FTANH
  1920:   //  32bit浮動小数点数の双曲線正接
  1921:   //  <d0.s:32bit浮動小数点数。x
  1922:   //  >d0.s:32bit浮動小数点数。tanh(x)
  1923:   public static void fpkFTANH () {
  1924:     //tanh([int]→float→double)→float→[int]
  1925:     int h = Float.floatToIntBits ((float) Math.tanh ((double) Float.intBitsToFloat (XEiJ.regRn[0])));
  1926:     if (FPK_FPCP_NAN && h == 0x7fc00000) {
  1927:       h = 0x7fffffff;
  1928:     }
  1929:     XEiJ.regRn[0] = h;
  1930:   }  //fpkFTANH()
  1931: 
  1932:   //fpkFATANH ()
  1933:   //  $FE74  __FATANH
  1934:   //  32bit浮動小数点数の逆双曲線正接
  1935:   //  <d0.s:32bit浮動小数点数。x
  1936:   //  >d0.s:32bit浮動小数点数。atanh(x)
  1937:   //  >ccr:cs=x<=-1||1<=x
  1938:   public static void fpkFATANH () {
  1939:     //atanh([int]→float→double)→float→[int]
  1940:     double d = (double) Float.intBitsToFloat (XEiJ.regRn[0]);
  1941:     double s = Math.signum (d);
  1942:     double a = Math.abs (d);
  1943:     if (a < 1.0) {
  1944:       d = s * (Math.log1p (a) - Math.log1p (-a)) * 0.5;  //Math.atanh(double)がない
  1945:       XEiJ.regCCR = 0;
  1946:     } else if (a == 1.0) {
  1947:       d = s * Double.POSITIVE_INFINITY;
  1948:       XEiJ.regCCR = XEiJ.REG_CCR_C;
  1949:     } else {
  1950:       d = Double.NaN;
  1951:       XEiJ.regCCR = XEiJ.REG_CCR_C;
  1952:     }
  1953:     int h = Float.floatToIntBits ((float) d);
  1954:     if (FPK_FPCP_NAN && h == 0x7fc00000) {
  1955:       h = 0x7fffffff;
  1956:     }
  1957:     XEiJ.regRn[0] = h;
  1958:   }  //fpkFATANH()
  1959: 
  1960:   //fpkFASIN ()
  1961:   //  $FE75  __FASIN
  1962:   //  32bit浮動小数点数の逆正弦
  1963:   //  <d0.s:32bit浮動小数点数。x
  1964:   //  >d0.s:32bit浮動小数点数。asin(x)
  1965:   //  >ccr:cs=x<-1||1<x
  1966:   public static void fpkFASIN () {
  1967:     //asin([int]→float→double)→float→[int]
  1968:     double d = (double) Float.intBitsToFloat (XEiJ.regRn[0]);
  1969:     if (d < -1.0 || 1.0 < d) {  //定義域の外。±1,NaNを含まない
  1970:       d = Double.NaN;
  1971:       XEiJ.regCCR = XEiJ.REG_CCR_C;
  1972:     } else {  //定義域の中。±1,NaNを含む
  1973:       d = Math.asin (d);
  1974:       XEiJ.regCCR = 0;
  1975:     }
  1976:     int h = Float.floatToIntBits ((float) d);
  1977:     if (FPK_FPCP_NAN && h == 0x7fc00000) {
  1978:       h = 0x7fffffff;
  1979:     }
  1980:     XEiJ.regRn[0] = h;
  1981:   }  //fpkFASIN()
  1982: 
  1983:   //fpkFACOS ()
  1984:   //  $FE76  __FACOS
  1985:   //  32bit浮動小数点数の逆余弦
  1986:   //  <d0.s:32bit浮動小数点数。x
  1987:   //  >d0.s:32bit浮動小数点数。acos(x)
  1988:   //  >ccr:cs=x<-1||1<x
  1989:   public static void fpkFACOS () {
  1990:     //acos([int]→float→double)→float→[int]
  1991:     double d = (double) Float.intBitsToFloat (XEiJ.regRn[0]);
  1992:     if (d < -1.0 || 1.0 < d) {  //定義域の外。±1,NaNを含まない
  1993:       d = Double.NaN;
  1994:       XEiJ.regCCR = XEiJ.REG_CCR_C;
  1995:     } else {  //定義域の中。±1,NaNを含む
  1996:       d = Math.acos (d);
  1997:       XEiJ.regCCR = 0;
  1998:     }
  1999:     int h = Float.floatToIntBits ((float) d);
  2000:     if (FPK_FPCP_NAN && h == 0x7fc00000) {
  2001:       h = 0x7fffffff;
  2002:     }
  2003:     XEiJ.regRn[0] = h;
  2004:   }  //fpkFACOS()
  2005: 
  2006:   //fpkFLOG10 ()
  2007:   //  $FE77  __FLOG10
  2008:   //  32bit浮動小数点数の常用対数
  2009:   //  <d0.s:32bit浮動小数点数。x
  2010:   //  >d0.s:32bit浮動小数点数。log10(x)
  2011:   //  >ccr:0=エラーなし,C=x<0,Z|C=x==0
  2012:   public static void fpkFLOG10 () {
  2013:     //log10([int]→float→double)→float→[int]
  2014:     double xd = (double) Float.intBitsToFloat (XEiJ.regRn[0]);
  2015:     double zd = Math.log10 (xd);
  2016:     int h = Float.floatToIntBits ((float) zd);
  2017:     if (FPK_FPCP_NAN && h == 0x7fc00000) {
  2018:       h = 0x7fffffff;
  2019:     }
  2020:     XEiJ.regRn[0] = h;
  2021:     XEiJ.regCCR = (Double.isNaN (xd) ? 0 :  //引数がNaN
  2022:            Double.isNaN (zd) ? XEiJ.REG_CCR_C :  //引数がNaNでないのに結果がNaNのときはエラー。log10(-x)=NaN
  2023:            Double.isInfinite (xd) ? 0 :  //引数が±Inf
  2024:            Double.isInfinite (zd) ? XEiJ.REG_CCR_Z | XEiJ.REG_CCR_C :  //引数が±Infでないのに結果が±Infのときはエラー。log10(±0)=-Inf
  2025:            0);
  2026:   }  //fpkFLOG10()
  2027: 
  2028:   //fpkFLOG2 ()
  2029:   //  $FE78  __FLOG2
  2030:   //  32bit浮動小数点数の二進対数
  2031:   //  <d0.s:32bit浮動小数点数。x
  2032:   //  >d0.s:32bit浮動小数点数。log2(x)
  2033:   //  >ccr:0=エラーなし,C=x<0,Z|C=x==0
  2034:   public static void fpkFLOG2 () {
  2035:     //log2([int]→float→double)→float→[int]
  2036:     double xd = (double) Float.intBitsToFloat (XEiJ.regRn[0]);
  2037:     double zd = Math.log (xd) / 0.69314718055994530941723212146;  //log(2)。Math.log2(double)がない
  2038:     int h = Float.floatToIntBits ((float) zd);
  2039:     if (FPK_FPCP_NAN && h == 0x7fc00000) {
  2040:       h = 0x7fffffff;
  2041:     }
  2042:     XEiJ.regRn[0] = h;
  2043:     XEiJ.regCCR = (Double.isNaN (xd) ? 0 :  //引数がNaN
  2044:            Double.isNaN (zd) ? XEiJ.REG_CCR_C :  //引数がNaNでないのに結果がNaNのときはエラー。log2(-x)=NaN
  2045:            Double.isInfinite (xd) ? 0 :  //引数が±Inf
  2046:            Double.isInfinite (zd) ? XEiJ.REG_CCR_Z | XEiJ.REG_CCR_C :  //引数が±Infでないのに結果が±Infのときはエラー。log2(±0)=-Inf
  2047:            0);
  2048:   }  //fpkFLOG2()
  2049: 
  2050:   //fpkFFREXP ()
  2051:   //  $FE79  __FFREXP
  2052:   //  32bit浮動小数点数の分解
  2053:   //  <d0.s:32bit浮動小数点数。x
  2054:   //  >d0.s:xの指数部を0にした値。x==0のときは0
  2055:   //  >d1.l:xの指数部。x==0のときは0
  2056:   public static void fpkFFREXP () {
  2057:     int h = XEiJ.regRn[0];
  2058:     if (h << 1 == 0) {  //0のとき
  2059:       XEiJ.regRn[0] = 0;
  2060:       XEiJ.regRn[1] = 0;
  2061:     } else {  //0でないとき
  2062:       XEiJ.regRn[0] = (h & 0x807fffff) | 0x3f800000;  //符号と仮数部を残して指数部を0にする
  2063:       XEiJ.regRn[1] = (h >>> 23 & 255) - 0x7f;
  2064:     }
  2065:   }  //fpkFFREXP()
  2066: 
  2067:   //fpkFLDEXP ()
  2068:   //  $FE7A  __FLDEXP
  2069:   //  32bit浮動小数点数の合成
  2070:   //  <d0.s:32bit浮動小数点数。x
  2071:   //  <d1.l:xの指数部に加える値。y
  2072:   //  >d0.s:xの指数部にyを加えた値。x==0のときは0。エラーのときは変化しない
  2073:   //  >ccr:0=エラーなし,C=指数部が範囲外
  2074:   public static void fpkFLDEXP () {
  2075:     int h = XEiJ.regRn[0];
  2076:     if (h << 1 == 0) {  //0のとき
  2077:       XEiJ.regRn[0] = 0;
  2078:       XEiJ.regCCR = 0;
  2079:     } else {  //0でないとき
  2080:       int t = (h >>> 23 & 255) + XEiJ.regRn[2];
  2081:       if ((t & ~0xff) != 0) {  //指数部が範囲外
  2082:         XEiJ.regCCR = XEiJ.REG_CCR_C;
  2083:       } else {
  2084:         XEiJ.regRn[0] = (h & 0x807fffff) | t << 23;  //符号と仮数部を残して指数部を交換する
  2085:         XEiJ.regCCR = 0;
  2086:       }
  2087:     }
  2088:   }  //fpkFLDEXP()
  2089: 
  2090:   //fpkFADDONE ()
  2091:   //  $FE7B  __FADDONE
  2092:   //  32bit浮動小数点数に1を加える
  2093:   //  <d0.s:32bit浮動小数点数。x
  2094:   //  >d0.s:32bit浮動小数点数。x+1
  2095:   public static void fpkFADDONE () {
  2096:     //([int]→float)+1→[int]
  2097:     float xf = Float.intBitsToFloat (XEiJ.regRn[0]);
  2098:     float zf = xf + 1.0F;
  2099:     int h = Float.floatToIntBits (zf);
  2100:     if (FPK_FPCP_NAN && h == 0x7fc00000) {
  2101:       h = 0x7fffffff;
  2102:     }
  2103:     XEiJ.regRn[0] = h;
  2104:     XEiJ.regCCR = Double.isInfinite (zf) && !Float.isInfinite (xf) ? XEiJ.REG_CCR_V | XEiJ.REG_CCR_C : 0;  //結果が±Infだが引数が±Infでないときはオーバーフロー
  2105:   }  //fpkFADDONE()
  2106: 
  2107:   //fpkFSUBONE ()
  2108:   //  $FE7C  __FSUBONE
  2109:   //  32bit浮動小数点数から1を引く
  2110:   //  <d0.s:32bit浮動小数点数。x
  2111:   //  >d0.s:32bit浮動小数点数。x-1
  2112:   public static void fpkFSUBONE () {
  2113:     //([int]→float)-1→[int]
  2114:     float xf = Float.intBitsToFloat (XEiJ.regRn[0]);
  2115:     float zf = xf - 1.0F;
  2116:     int h = Float.floatToIntBits (zf);
  2117:     if (FPK_FPCP_NAN && h == 0x7fc00000) {
  2118:       h = 0x7fffffff;
  2119:     }
  2120:     XEiJ.regRn[0] = h;
  2121:     XEiJ.regCCR = Double.isInfinite (zf) && !Float.isInfinite (xf) ? XEiJ.REG_CCR_V | XEiJ.REG_CCR_C : 0;  //結果が±Infだが引数が±Infでないときはオーバーフロー
  2122:   }  //fpkFSUBONE()
  2123: 
  2124:   //fpkFDIVTWO ()
  2125:   //  $FE7D  __FDIVTWO
  2126:   //  32bit浮動小数点数を2で割る
  2127:   //  <d0.s:32bit浮動小数点数。x
  2128:   //  >d0.s:32bit浮動小数点数。x/2
  2129:   //  >ccr:0=エラーなし,C=アンダーフロー
  2130:   public static void fpkFDIVTWO () {
  2131:     //([int]→float)/2→[int]
  2132:     float xf = Float.intBitsToFloat (XEiJ.regRn[0]);
  2133:     float zf = xf * 0.5F;
  2134:     int h = Float.floatToIntBits (zf);
  2135:     if (FPK_FPCP_NAN && h == 0x7fc00000) {
  2136:       h = 0x7fffffff;
  2137:     }
  2138:     XEiJ.regRn[0] = h;
  2139:     XEiJ.regCCR = zf == 0.0F && xf != 0.0F ? XEiJ.REG_CCR_C : 0;  //結果が±0だが引数が±0でないときはアンダーフロー
  2140:   }  //fpkFDIVTWO()
  2141: 
  2142:   //fpkFIEECNV ()
  2143:   //  $FE7E  __FIEECNV
  2144:   //  32bit浮動小数点数をIEEEフォーマットに変換する(FLOAT1.X以外は何もしない)
  2145:   //  <d0.s:32bit浮動小数点数。x
  2146:   //  >d0.s:32bit浮動小数点数。x
  2147:   public static void fpkFIEECNV () {
  2148:   }  //fpkFIEECNV()
  2149: 
  2150:   //fpkIEEFCNV ()
  2151:   //  $FE7F  __IEEFCNV
  2152:   //  32bit浮動小数点数をIEEEフォーマットから変換する(FLOAT1.X以外は何もしない)
  2153:   //  <d0.s:32bit浮動小数点数。x
  2154:   //  >d0.s:32bit浮動小数点数。x
  2155:   public static void fpkIEEFCNV () {
  2156:   }  //fpkIEEFCNV()
  2157: 
  2158:   //fpkFEVARG ()
  2159:   //  $FEFE  __FEVARG
  2160:   //  バージョン確認
  2161:   //  >d0.l:'HS86'($48533836)=FLOAT1.X,'IEEE'($49454545)=FLOAT2.X/FLOAT3.X/FLOAT4.X
  2162:   //  >d1.l:'SOFT'($534F4654)=FLOAT1.X/FLOAT2.X,'FPCP'($46504350)=FLOAT3.X,'FP20'($46503230)=FLOAT4.X
  2163:   public static void fpkFEVARG () {
  2164:     XEiJ.regRn[0] = 'I' << 24 | 'E' << 16 | 'E' << 8 | 'E';
  2165:     XEiJ.regRn[1] = 'X' << 24 | 'E' << 16 | 'i' << 8 | 'J';
  2166:   }  //fpkFEVARG()
  2167: 
  2168:   //fpkFEVECS ()
  2169:   //  $FEFF  __FEVECS
  2170:   //  ベクタ設定
  2171:   //  メモ
  2172:   //    FLOATn.Xに処理させる
  2173:   //    登録してもFEファンクション命令をOFFにしなければ既存のFEファンクション命令に上書きすることはできない
  2174:   //  <d0.l:FEファンクションコール番号。$FE00~$FEFF
  2175:   //  <a0.l:新アドレス
  2176:   //  >d0.l:旧アドレス。-1=エラー
  2177:   public static void fpkFEVECS () {
  2178:     XEiJ.regRn[0] = -1;
  2179:   }  //fpkFEVECS()
  2180: 
  2181: 
  2182: 
  2183:   //fpkSTOL ()
  2184:   //  $FE10  __STOL
  2185:   //  10進数の文字列を32bit符号あり整数に変換する
  2186:   //  /^[ \t]*[-+]?[0-9]+/
  2187:   //  先頭の'\t'と' 'を読み飛ばす
  2188:   //  <a0.l:10進数の文字列の先頭
  2189:   //  >d0.l:32bit符号あり整数
  2190:   //  >a0.l:10進数の文字列の直後('\0'とは限らない)
  2191:   //  >ccr:0=エラーなし,N|C=文法エラー,V|C=オーバーフロー
  2192:   public static void fpkSTOL () throws M68kException {
  2193:     int a = XEiJ.regRn[8];  //a0
  2194:     int c = XEiJ.busRbz (a);
  2195:     while (c == ' ' || c == '\t') {
  2196:       c = XEiJ.busRbz (++a);
  2197:     }
  2198:     int n = '7';  //'7'=正,'8'=負
  2199:     if (c == '-') {  //負
  2200:       n = '8';
  2201:       c = XEiJ.busRbz (++a);
  2202:     } else if (c == '+') {  //正
  2203:       c = XEiJ.busRbz (++a);
  2204:     }
  2205:     if (!('0' <= c && c <= '9')) {  //数字が1つもない
  2206:       XEiJ.regRn[8] = a;  //a0
  2207:       XEiJ.regCCR = XEiJ.REG_CCR_N | XEiJ.REG_CCR_C;
  2208:       return;
  2209:     }
  2210:     int x = c - '0';  //値
  2211:     for (c = XEiJ.busRbz (++a); '0' <= c && c <= '9'; c = XEiJ.busRbz (++a)) {
  2212:       if (214748364 < x || x == 214748364 && n < c) {  //正のとき2147483647、負のとき2147483648より大きくなるときオーバーフロー
  2213:         XEiJ.regRn[8] = a;  //a0
  2214:         XEiJ.regCCR = XEiJ.REG_CCR_V | XEiJ.REG_CCR_C;
  2215:         return;
  2216:       }
  2217:       x = x * 10 + (c - '0');
  2218:     }
  2219:     if (n != '7') {  //負
  2220:       x = -x;
  2221:     }
  2222:     XEiJ.regRn[0] = x;  //d0
  2223:     XEiJ.regRn[8] = a;  //a0
  2224:     XEiJ.regCCR = 0;
  2225:   }  //fpkSTOL()
  2226: 
  2227:   //fpkLTOS ()
  2228:   //  $FE11  __LTOS
  2229:   //  32bit符号あり整数を10進数の文字列に変換する
  2230:   //  /^-?[1-9][0-9]*$/
  2231:   //  <d0.l:32bit符号あり整数
  2232:   //  <a0.l:文字列バッファの先頭
  2233:   //  >a0.l:10進数の文字列の直後('\0'の位置)
  2234:   public static void fpkLTOS () throws M68kException {
  2235:     int x = XEiJ.regRn[0];  //d0
  2236:     int a = XEiJ.regRn[8];  //a0
  2237:     if (x < 0) {  //負
  2238:       XEiJ.busWb (a++, '-');
  2239:       x = -x;
  2240:     }
  2241:     long t = XEiJ.fmtBcd12 (0xffffffffL & x);  //符号は取り除いてあるがx=0x80000000の場合があるので(long)xは不可
  2242:     XEiJ.regRn[8] = a += Math.max (1, 67 - Long.numberOfLeadingZeros (t) >> 2);  //a0
  2243:     XEiJ.busWb (a, 0);
  2244:     do {
  2245:       XEiJ.busWb (--a, '0' | (int) t & 15);
  2246:     } while ((t >>>= 4) != 0L);
  2247:   }  //fpkLTOS()
  2248: 
  2249:   //fpkSTOH ()
  2250:   //  $FE12  __STOH
  2251:   //  16進数の文字列を32bit符号なし整数に変換する
  2252:   //  /^[0-9A-Fa-f]+/
  2253:   //  <a0.l:16進数の文字列の先頭
  2254:   //  >d0.l:32bit符号なし整数
  2255:   //  >a0.l:16進数の文字列の直後('\0'とは限らない)
  2256:   //  >ccr:0=エラーなし,N|C=文法エラー,V|C=オーバーフロー
  2257:   public static void fpkSTOH () throws M68kException {
  2258:     int a = XEiJ.regRn[8];  //a0
  2259:     int c = XEiJ.busRbz (a);
  2260:     if (!('0' <= c && c <= '9' || 'A' <= c && c <= 'F' || 'a' <= c && c <= 'f')) {  //数字が1つもない
  2261:       XEiJ.regRn[8] = a;  //a0
  2262:       XEiJ.regCCR = XEiJ.REG_CCR_N | XEiJ.REG_CCR_C;
  2263:       return;
  2264:     }
  2265:     int x = c <= '9' ? c - '0' : c <= 'F' ? c - ('A' - 10) : c - ('a' - 10);  //値
  2266:     for (c = XEiJ.busRbz (++a); '0' <= c && c <= '9' || 'A' <= c && c <= 'F' || 'a' <= c && c <= 'f'; c = XEiJ.busRbz (++a)) {
  2267:       if (0x0fffffff < x) {  //0xffffffffより大きくなるときオーバーフロー
  2268:         XEiJ.regRn[8] = a;  //a0
  2269:         XEiJ.regCCR = XEiJ.REG_CCR_V | XEiJ.REG_CCR_C;
  2270:         return;
  2271:       }
  2272:       x = x << 4 | (c <= '9' ? c - '0' : c <= 'F' ? c - ('A' - 10) : c - ('a' - 10));
  2273:     }
  2274:     XEiJ.regRn[0] = x;  //d0
  2275:     XEiJ.regRn[8] = a;  //a0
  2276:     XEiJ.regCCR = 0;
  2277:   }  //fpkSTOH()
  2278: 
  2279:   //fpkHTOS ()
  2280:   //  $FE13  __HTOS
  2281:   //  32bit符号なし整数を16進数の文字列に変換する
  2282:   //  /^[1-9A-F][0-9A-F]*$/
  2283:   //  <d0.l:32bit符号なし整数
  2284:   //  <a0.l:文字列バッファの先頭
  2285:   //  >a0.l:16進数の文字列の直後('\0'の位置)
  2286:   public static void fpkHTOS () throws M68kException {
  2287:     int x = XEiJ.regRn[0];  //d0
  2288:     int a = XEiJ.regRn[8] += Math.max (1, 35 - Integer.numberOfLeadingZeros (x) >> 2);  //a0
  2289:     XEiJ.busWb (a, 0);
  2290:     do {
  2291:       int t = x & 15;
  2292:       //     t             00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f
  2293:       //   9-t             09 08 07 06 05 04 03 02 01 00 ff fe fd fc fb fa
  2294:       //   9-t>>4          00 00 00 00 00 00 00 00 00 00 ff ff ff ff ff ff
  2295:       //   9-t>>4&7        00 00 00 00 00 00 00 00 00 00 07 07 07 07 07 07
  2296:       //   9-t>>4&7|48     30 30 30 30 30 30 30 30 30 30 37 37 37 37 37 37
  2297:       //  (9-t>>4&7|48)+t  30 31 32 33 34 35 36 37 38 39 41 42 43 44 45 46
  2298:       //                    0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F
  2299:       XEiJ.busWb (--a, (9 - t >> 4 & 7 | 48) + t);
  2300:     } while ((x >>>= 4) != 0);
  2301:   }  //fpkHTOS()
  2302: 
  2303:   //fpkSTOO ()
  2304:   //  $FE14  __STOO
  2305:   //  8進数の文字列を32bit符号なし整数に変換する
  2306:   //  /^[0-7]+/
  2307:   //  <a0.l:8進数の文字列の先頭
  2308:   //  >d0.l:32bit符号なし整数
  2309:   //  >a0.l:8進数の文字列の直後('\0'とは限らない)
  2310:   //  >ccr:0=エラーなし,N|C=文法エラー,V|C=オーバーフロー
  2311:   public static void fpkSTOO () throws M68kException {
  2312:     int a = XEiJ.regRn[8];  //a0
  2313:     int c = XEiJ.busRbz (a);
  2314:     if (!('0' <= c && c <= '7')) {  //数字が1つもない
  2315:       XEiJ.regRn[8] = a;  //a0
  2316:       XEiJ.regCCR = XEiJ.REG_CCR_N | XEiJ.REG_CCR_C;
  2317:       return;
  2318:     }
  2319:     int x = c - '0';  //値
  2320:     for (c = XEiJ.busRbz (++a); '0' <= c && c <= '7'; c = XEiJ.busRbz (++a)) {
  2321:       if (0x1fffffff < x) {  //0xffffffffより大きくなるときオーバーフロー
  2322:         XEiJ.regRn[8] = a;  //a0
  2323:         XEiJ.regCCR = XEiJ.REG_CCR_V | XEiJ.REG_CCR_C;
  2324:         return;
  2325:       }
  2326:       x = x << 3 | c & 7;
  2327:     }
  2328:     XEiJ.regRn[0] = x;  //d0
  2329:     XEiJ.regRn[8] = a;  //a0
  2330:     XEiJ.regCCR = 0;
  2331:   }  //fpkSTOO()
  2332: 
  2333:   //fpkOTOS ()
  2334:   //  $FE15  __OTOS
  2335:   //  32bit符号なし整数を8進数の文字列に変換する
  2336:   //  /^[1-7][0-7]*$/
  2337:   //  <d0.l:32bit符号なし整数
  2338:   //  <a0.l:文字列バッファの先頭
  2339:   //  >a0.l:8進数の文字列の直後('\0'の位置)
  2340:   public static void fpkOTOS () throws M68kException {
  2341:     int x = XEiJ.regRn[0];  //d0
  2342:     //perl optdiv.pl 34 3
  2343:     //  x/3==x*43>>>7 (0<=x<=127) [34*43==1462]
  2344:     int a = XEiJ.regRn[8] += Math.max (1, (34 - Integer.numberOfLeadingZeros (x)) * 43 >>> 7);  //a0
  2345:     XEiJ.busWb (a, 0);
  2346:     do {
  2347:       XEiJ.busWb (--a, '0' | x & 7);
  2348:     } while ((x >>>= 3) != 0);
  2349:   }  //fpkOTOS()
  2350: 
  2351:   //fpkSTOB ()
  2352:   //  $FE16  __STOB
  2353:   //  2進数の文字列を32bit符号なし整数に変換する
  2354:   //  /^[01]+/
  2355:   //  <a0.l:2進数の文字列の先頭
  2356:   //  >d0.l:32bit符号なし整数
  2357:   //  >a0.l:2進数の文字列の直後('\0'とは限らない)
  2358:   //  >ccr:0=エラーなし,N|C=文法エラー,V|C=オーバーフロー
  2359:   public static void fpkSTOB () throws M68kException {
  2360:     int a = XEiJ.regRn[8];  //a0
  2361:     int c = XEiJ.busRbz (a);
  2362:     if (!('0' <= c && c <= '1')) {  //数字が1つもない
  2363:       XEiJ.regRn[8] = a;  //a0
  2364:       XEiJ.regCCR = XEiJ.REG_CCR_N | XEiJ.REG_CCR_C;
  2365:       return;
  2366:     }
  2367:     int x = c - '0';  //値
  2368:     for (c = XEiJ.busRbz (++a); '0' <= c && c <= '1'; c = XEiJ.busRbz (++a)) {
  2369:       if (x < 0) {  //オーバーフロー
  2370:         XEiJ.regRn[8] = a;  //a0
  2371:         XEiJ.regCCR = XEiJ.REG_CCR_V | XEiJ.REG_CCR_C;
  2372:         return;
  2373:       }
  2374:       x = x << 1 | c & 1;
  2375:     }
  2376:     XEiJ.regRn[0] = x;  //d0
  2377:     XEiJ.regRn[8] = a;  //a0
  2378:     XEiJ.regCCR = 0;
  2379:   }  //fpkSTOB()
  2380: 
  2381:   //fpkBTOS ()
  2382:   //  $FE17  __BTOS
  2383:   //  32bit符号なし整数を2進数の文字列に変換する
  2384:   //  /^1[01]*$/
  2385:   //  <d0.l:32bit符号なし整数
  2386:   //  <a0.l:文字列バッファの先頭
  2387:   //  >a0.l:2進数の文字列の直後('\0'の位置)
  2388:   public static void fpkBTOS () throws M68kException {
  2389:     int x = XEiJ.regRn[0];  //d0
  2390:     int a = XEiJ.regRn[8] += Math.max (1, 32 - Integer.numberOfLeadingZeros (x));  //a0
  2391:     XEiJ.busWb (a, 0);
  2392:     do {
  2393:       XEiJ.busWb (--a, '0' | x & 1);
  2394:     } while ((x >>>= 1) != 0);
  2395:   }  //fpkBTOS()
  2396: 
  2397:   //fpkIUSING ()
  2398:   //  $FE18  __IUSING
  2399:   //  32bit符号あり整数を文字数を指定して右詰めで10進数の文字列に変換する
  2400:   //  /^ *-?[1-9][0-9]*$/
  2401:   //  <d0.l:32bit符号あり整数
  2402:   //  <d1.b:文字数
  2403:   //  <a0.l:文字列バッファの先頭
  2404:   //  >a0.l:10進数の文字列の直後('\0'の位置)
  2405:   public static void fpkIUSING () throws M68kException {
  2406:     int x = XEiJ.regRn[0];  //d0
  2407:     int n = 0;  //符号の文字数
  2408:     if (x < 0) {  //負
  2409:       n = 1;
  2410:       x = -x;
  2411:     }
  2412:     long t = XEiJ.fmtBcd12 (0xffffffffL & x);  //符号は取り除いてあるがx=0x80000000の場合があるので(long)xは不可
  2413:     int l = n + Math.max (1, 67 - Long.numberOfLeadingZeros (t) >> 2);  //符号を含めた文字数
  2414:     int a = XEiJ.regRn[8];  //a0
  2415:     for (int i = (XEiJ.regRn[1] & 255) - l; i > 0; i--) {
  2416:       XEiJ.busWb (a++, ' ');
  2417:     }
  2418:     XEiJ.regRn[8] = a += l;  //a0
  2419:     XEiJ.busWb (a, 0);
  2420:     do {
  2421:       XEiJ.busWb (--a, '0' | (int) t & 15);
  2422:     } while ((t >>>= 4) != 0L);
  2423:     if (n != 0) {
  2424:       XEiJ.busWb (--a, '-');
  2425:     }
  2426:   }  //fpkIUSING()
  2427: 
  2428:   //fpkVAL ()
  2429:   //  $FE20  __VAL
  2430:   //  文字列を64bit浮動小数点数に変換する
  2431:   //  先頭の'\t'と' 'を読み飛ばす
  2432:   //  "&B"または"&b"で始まっているときは続きを2進数とみなして__STOBで32bit符号なし整数に変換してから__LTODで64bit浮動小数点数に変換する
  2433:   //  "&O"または"&o"で始まっているときは続きを8進数とみなして__STOOで32bit符号なし整数に変換してから__LTODで64bit浮動小数点数に変換する
  2434:   //  "&H"または"&h"で始まっているときは続きを16進数とみなして__STOHで32bit符号なし整数に変換してから__LTODで64bit浮動小数点数に変換する
  2435:   //  それ以外は__STODと同じ
  2436:   //  <a0.l:文字列の先頭
  2437:   //  >d0d1.d:64bit浮動小数点数
  2438:   //  >d2.l:(先頭が'&'でないとき)65535=64bit浮動小数点数をオーバーフローなしでintに変換できる,0=それ以外
  2439:   //  >d3.l:(先頭が'&'でないとき)d2.l==65535のとき64bit浮動小数点数をintに変換した値
  2440:   //  >a0.l:変換された文字列の直後('\0'とは限らない)
  2441:   //  >ccr:0=エラーなし,N|C=文法エラー,V|C=オーバーフロー
  2442:   public static void fpkVAL () throws M68kException {
  2443:     int a = XEiJ.regRn[8];  //a0
  2444:     //先頭の空白を読み飛ばす
  2445:     int c = XEiJ.busRbs (a++);
  2446:     while (c == ' ' || c == '\t') {
  2447:       c = XEiJ.busRbs (a++);
  2448:     }
  2449:     if (c == '&') {  //&B,&O,&H
  2450:       c = XEiJ.busRbs (a++) & 0xdf;
  2451:       XEiJ.regRn[8] = a;  //&?の直後
  2452:       if (c == 'B') {
  2453:         fpkSTOB ();
  2454:         fpkLTOD ();
  2455:       } else if (c == 'O') {
  2456:         fpkSTOO ();
  2457:         fpkLTOD ();
  2458:       } else if (c == 'H') {
  2459:         fpkSTOH ();
  2460:         fpkLTOD ();
  2461:       } else {
  2462:         XEiJ.regCCR = XEiJ.REG_CCR_N | XEiJ.REG_CCR_C;  //文法エラー
  2463:       }
  2464:     } else {  //&B,&O,&H以外
  2465:       fpkSTOD ();
  2466:     }
  2467:   }  //fpkVAL()
  2468: 
  2469:   //fpkUSING ()
  2470:   //  $FE21  __USING
  2471:   //  64bit浮動小数点数をアトリビュートを指定して文字列に変換する
  2472:   //  メモ
  2473:   //    bit1の'\\'とbit4の'+'を両方指定したときは'\\'が右側。先頭に"+\\"を付ける
  2474:   //    bit1の'\\'とbit2の','とbit4の'+'は整数部の桁数が足りないとき数字を右にずらして押し込まれる
  2475:   //    bit3で指数形式を指示しなければ指数部が極端に大きくても極端に小さくても指数形式にならない
  2476:   //    bit3で指数形式を指定したときbit1の'\\'とbit2の','は無効
  2477:   //    bit4とbit5とbit6はbit4>bit5>bit6の順位で1つだけ有効
  2478:   //    有効数字は14桁で15桁目以降はすべて0
  2479:   //    FLOAT2.Xは整数部の0でない最初の数字から256文字目までで打ち切られてしまう
  2480:   //    整数部の桁数に余裕があれば左側の空白は出力されるので文字列の全体が常に256バイトに収まるわけではない
  2481:   //      using 1234.5 5 0 0    " 1235."
  2482:   //      using 1234.5 5 1 0    " 1234.5"
  2483:   //      using 1234.5 5 2 0    " 1234.50"
  2484:   //      using 1234.5 6 2 1    "**1234.50"
  2485:   //      using 1234.5 6 2 2    " \\1234.50"
  2486:   //      using 1234.5 6 2 3    "*\\1234.50"
  2487:   //      using 1234.5 6 2 4    " 1,234.50"
  2488:   //      using 1234.5 4 2 4    "1,234.50"
  2489:   //      using 1234.5 4 2 5    "1,234.50"
  2490:   //      using 1234.5 4 2 6    "\\1,234.50"
  2491:   //      using 1234.5 4 2 7    "\\1,234.50"
  2492:   //      using 1234.5 4 2 16   "+1234.50"
  2493:   //      using 1234.5 4 2 22   "+\\1,234.50"
  2494:   //      using 1234.5 4 2 32   "1234.50+"
  2495:   //      using 1234.5 4 2 48   "+1234.50"
  2496:   //      using 1234.5 4 2 64   "1234.50 "
  2497:   //      using 1234.5 4 2 80   "+1234.50"
  2498:   //      using 1234.5 4 2 96   "1234.50+"
  2499:   //      using 12345678901234567890 10 1 0      "12345678901235000000.0"
  2500:   //      using 12345678901234567890e+10 10 1 0  "123456789012350000000000000000.0"
  2501:   //      using 0.3333 0 0 0    "."
  2502:   //      using 0.6666 0 0 0    "1."
  2503:   //      using 0.6666 0 3 0    ".667"
  2504:   //      using 0.6666 3 0 0    "  1."
  2505:   //      using 0.3333 0 0 2    "\\."
  2506:   //      using 0.3333 0 0 16   "+."
  2507:   //      using 0.3333 0 0 18   "+\\."
  2508:   //      using 1e-10 3 3 0     "  0.000"
  2509:   //    指数形式の出力は不可解で本来の動作ではないように思えるが、
  2510:   //    X-BASICのprint using命令が使っているのでFLOAT2.Xに合わせておいた方がよさそう
  2511:   //      print using "###.##";1.23         "  1.23"         整数部の桁数は3
  2512:   //      print using "+##.##";1.23         " +1.23"         整数部の桁数は3←
  2513:   //      print using "###.##^^^^^";1.23    " 12.30E-001"    整数部の桁数は3
  2514:   //      print using "+##.##^^^^^";1.23    "+12.30E-001"    整数部の桁数は2←
  2515:   //    FLOAT2.Xでは#NANと#INFは4桁の整数のように出力される。末尾に小数点が付くが小数部には何も出力されない
  2516:   //      using -#INF 7 3 23     "*-\\#,INF."
  2517:   //    FLOAT2.Xで#NANと#INFを指数形式にするとさらに不可解。これはバグと言ってよいと思う
  2518:   //      using #INF 10 10 8      " #INFE-005"
  2519:   //    ここでは#NANと#INFは整数部と小数点と小数部と指数部の全体を使って右寄せにする
  2520:   //  <d0d1.d:64bit浮動小数点数
  2521:   //  <d2.l:整数部の桁数
  2522:   //  <d3.l:小数部の桁数
  2523:   //  <d4.l:アトリビュート
  2524:   //    bit0  左側を'*'で埋める
  2525:   //    bit1  先頭に'\\'を付ける
  2526:   //    bit2  整数部を3桁毎に','で区切る
  2527:   //    bit3  指数形式
  2528:   //    bit4  先頭に符号('+'または'-')を付ける
  2529:   //    bit5  末尾に符号('+'または'-')を付ける
  2530:   //    bit6  末尾に符号(' 'または'-')を付ける
  2531:   //  <a0.l:文字列バッファの先頭
  2532:   //  a0は変化しない
  2533:   public static void fpkUSING () throws M68kException {
  2534:     fpkUSINGSub ((long) XEiJ.regRn[0] << 32 | 0xffffffffL & XEiJ.regRn[1]);  //64bit浮動小数点数
  2535:   }  //fpkUSING()
  2536:   public static void fpkUSINGSub (long l) throws M68kException {
  2537:     int len1 = Math.max (0, XEiJ.regRn[2]);  //整数部の桁数
  2538:     int len2 = Math.max (0, XEiJ.regRn[3]);  //小数部の桁数
  2539:     int attr = XEiJ.regRn[4];  //アトリビュート
  2540:     int a = XEiJ.regRn[8];  //文字列バッファの先頭
  2541:     boolean exp = (attr & 8) != 0;  //true=指数形式
  2542:     int spc = (attr & 1) != 0 ? '*' : ' ';  //先頭の空白を充填する文字
  2543:     int yen = (attr & 2) != 0 ? '\\' : 0;  //先頭の'\\'
  2544:     int cmm = !exp && (attr & 4) != 0 ? ',' : 0;  //3桁毎に入れる','
  2545:     //符号
  2546:     int sgn1 = 0;  //先頭の符号
  2547:     int sgn2 = 0;  //末尾の符号
  2548:     if (l < 0L) {  //負
  2549:       if ((attr & 32 + 64) == 0) {  //末尾に符号を付けない
  2550:         sgn1 = '-';  //先頭の符号
  2551:       } else {  //末尾に符号を付ける
  2552:         sgn2 = '-';  //末尾の符号
  2553:       }
  2554:       l &= 0x7fffffffffffffffL;  //符号bitを消しておく
  2555:     } else {  //正
  2556:       if ((attr & 16) != 0) {  //先頭に符号('+'または'-')を付ける
  2557:         sgn1 = '+';
  2558:       } else if ((attr & 16 + 32) == 32) {  //末尾に符号('+'または'-')を付ける
  2559:         sgn2 = '+';
  2560:       } else if ((attr & 16 + 32 + 64) == 64) {  //末尾に符号(' 'または'-')を付ける
  2561:         sgn2 = ' ';
  2562:       }
  2563:     }
  2564:     double x = Double.longBitsToDouble (l);  //絶対値
  2565:     int e = (int) (l >>> 52) - 1023;  //指数部。ゲタ0。符号bitは消してあるのでマスクは不要
  2566:     l &= 0x000fffffffffffffL;  //仮数部の小数部。正規化数のとき整数部の1が付いていないことに注意
  2567:     //±0,±Inf,NaN
  2568:     if (e == -1023) {  //±0,非正規化数
  2569:       if (l == 0L) {  //±0
  2570:         for (int i = len1 - ((sgn1 != 0 ? 1 : 0) +  //先頭の符号
  2571:                              (yen != 0 ? 1 : 0) +  //'\\'
  2572:                              1  //数字
  2573:                              ); 0 < i; i--) {
  2574:           XEiJ.busWb (a++, spc);  //空白
  2575:         }
  2576:         if (sgn1 != 0) {
  2577:           XEiJ.busWb (a++, sgn1);  //先頭の符号
  2578:         }
  2579:         if (yen != 0) {
  2580:           XEiJ.busWb (a++, yen);  //'\\'
  2581:         }
  2582:         if (0 < len1) {
  2583:           XEiJ.busWb (a++, '0');  //整数部
  2584:         }
  2585:         XEiJ.busWb (a++, '.');  //小数点
  2586:         for (; 0 < len2; len2--) {
  2587:           XEiJ.busWb (a++, '0');  //小数部
  2588:         }
  2589:         XEiJ.busWb (a, '\0');
  2590:         return;
  2591:       }
  2592:       e -= Long.numberOfLeadingZeros (l) - 12;  //非正規化数の指数部を補正する
  2593:     } else if (e == 1024) {  //±Inf,NaN
  2594:       for (int i = len1 + 1 + len2 + (exp ? 5 : 0) -  //整数部と小数点と小数部と指数部の全体を使って右寄せにする
  2595:            ((sgn1 != 0 ? 1 : 0) +  //先頭の符号
  2596:             (yen != 0 ? 1 : 0) +  //'\\'
  2597:             4  //文字
  2598:             ); 0 < i; i--) {
  2599:         XEiJ.busWb (a++, spc);  //空白
  2600:       }
  2601:       if (sgn1 != 0) {
  2602:         XEiJ.busWb (a++, sgn1);  //先頭の符号
  2603:       }
  2604:       if (yen != 0) {
  2605:         XEiJ.busWb (a++, yen);  //'\\'
  2606:       }
  2607:       XEiJ.busWb (a++, '#');
  2608:       if (l == 0L) {  //±Inf
  2609:         XEiJ.busWb (a++, 'I');
  2610:         XEiJ.busWb (a++, 'N');
  2611:         XEiJ.busWb (a++, 'F');
  2612:       } else {  //NaN
  2613:         XEiJ.busWb (a++, 'N');
  2614:         XEiJ.busWb (a++, 'A');
  2615:         XEiJ.busWb (a++, 'N');
  2616:       }
  2617:       XEiJ.busWb (a, '\0');
  2618:       return;
  2619:     }
  2620:     //10進数で表現したときの指数部を求める
  2621:     //  10^e<=x<10^(e+1)となるeを求める
  2622:     e = (int) Math.floor ((double) e * 0.30102999566398119521373889472);  //log10(2)
  2623:     //10^-eを掛けて1<=x<10にする
  2624:     //  非正規化数の最小値から正規化数の最大値まで処理できなければならない
  2625:     //  10^-eを計算してからまとめて掛ける方法はxが非正規化数のとき10^-eがオーバーフローしてしまうので不可
  2626:     //    doubleは非正規化数の逆数を表現できない
  2627:     if (0 < e) {  //10<=x
  2628:       x *= FPK_TEN_M16QR[e & 15];
  2629:       if (16 <= e) {
  2630:         x *= FPK_TEN_M16QR[16 + (e >> 4 & 15)];
  2631:         if (256 <= e) {
  2632:           x *= FPK_TEN_M16QR[33];  //FPK_TEN_M16QR[32 + (e >> 8)]
  2633:         }
  2634:       }
  2635:     } else if (e < 0) {  //x<1
  2636:       x *= FPK_TEN_P16QR[-e & 15];
  2637:       if (e <= -16) {
  2638:         x *= FPK_TEN_P16QR[16 + (-e >> 4 & 15)];
  2639:         if (e <= -256) {
  2640:           x *= FPK_TEN_P16QR[33];  //FPK_TEN_P16QR[32 + (-e >> 8)]
  2641:         }
  2642:       }
  2643:     }
  2644:     //整数部2桁、小数部16桁の10進数に変換する
  2645:     //  1<=x<10なのでw[1]が先頭になるはずだが誤差で前後にずれる可能性がある
  2646:     int[] w = new int[18];
  2647:     {
  2648:       int d = (int) x;
  2649:       int t = XEiJ.FMT_BCD4[d];
  2650:       w[0] = t >> 4;
  2651:       w[1] = t      & 15;
  2652:       for (int i = 2; i < 18; i += 4) {
  2653:         //xを10000倍して整数部dを引くことで小数部を残すが、このとき情報落ちが発生して誤差が蓄積する
  2654:         //Double-Doubleの乗算の要領で10000倍を正確に行い、誤差の蓄積を回避する
  2655:         //x = (x - (double) d) * 10000.0;
  2656:         double xh = x * 0x8000001p0;
  2657:         xh += x - xh;  //xの上半分
  2658:         x = (xh - (double) d) * 10000.0 + (x - xh) * 10000.0;
  2659:         d = (int) x;
  2660:         t = XEiJ.FMT_BCD4[d];
  2661:         w[i    ] = t >> 12;
  2662:         w[i + 1] = t >>  8 & 15;
  2663:         w[i + 2] = t >>  4 & 15;
  2664:         w[i + 3] = t       & 15;
  2665:       }
  2666:     }
  2667:     //先頭の位置を確認する
  2668:     //  w[h]が先頭(0でない最初の数字)の位置
  2669:     int h = w[0] != 0 ? 0 : w[1] != 0 ? 1 : 2;
  2670:     //14+1桁目を四捨五入する
  2671:     int o = h + 14;  //w[o]は四捨五入する桁の位置。w[]の範囲内
  2672:     if (5 <= w[o]) {
  2673:       int i = o;
  2674:       while (10 <= ++w[--i]) {
  2675:         w[i] = 0;
  2676:       }
  2677:       if (i < h) {  //先頭から繰り上がった。このとき新しい先頭は1でそれ以外はすべて0
  2678:         h--;  //先頭を左にずらす
  2679:         o--;  //末尾を左にずらす
  2680:       }
  2681:     }
  2682:     //先頭の位置に応じて指数部を更新する
  2683:     //  w[h]が整数部、w[h+1..13]が小数部。10^eの小数点はw[h]の右側。整数部の桁数はe+1桁
  2684:     e -= h - 1;
  2685:     //整数部の桁数を調節する
  2686:     int ee = !exp ? e : Math.max (0, sgn1 != 0 || sgn2 != 0 ? len1 : len1 - 1) - 1;  //整数部の桁数-1。整数部の桁数はee+1桁。指数部はe-ee
  2687:     //小数点以下len2+1桁目が先頭から14+1桁目よりも左側にあるときその桁で改めて四捨五入する
  2688:     //  あらかじめ14+1桁目で四捨五入しておかないと、
  2689:     //  1.5の5を四捨五入しなければならないときに誤差で1.499…になったまま4を四捨五入しようとして失敗することがある
  2690:     int s = h + ee + 1 + len2;  //w[s]は小数点以下len2+1桁目の位置。w.length<=sの場合があることに注意
  2691:     if (s < o) {
  2692:       o = s;  //w[o]は四捨五入する桁の位置。o<0の場合があることに注意
  2693:       if (0 <= o && 5 <= w[o]) {
  2694:         int i = o;
  2695:         while (10 <= ++w[--i]) {
  2696:           w[i] = 0;
  2697:         }
  2698:         if (i < h) {  //先頭から繰り上がった。このとき新しい先頭は1でそれ以外はすべて0
  2699:           h--;  //先頭を左にずらす
  2700:           if (!exp) {  //指数形式でないとき
  2701:             ee++;  //左に1桁伸ばす。全体の桁数が1桁増える
  2702:           } else {  //指数形式のとき
  2703:             e++;  //指数部を1増やす
  2704:             o--;  //末尾を左にずらす。全体の桁数は変わらない
  2705:           }
  2706:         }
  2707:       }
  2708:     }
  2709:     //文字列に変換する
  2710:     if (0 <= ee) {  //1<=x
  2711:       for (int i = len1 - ((sgn1 != 0 ? 1 : 0) +  //先頭の符号
  2712:                            (yen != 0 ? 1 : 0) +  //'\\'
  2713:                            (cmm != 0 ? ee / 3 : 0) +  //','
  2714:                            ee + 1  //数字
  2715:                            ); 0 < i; i--) {
  2716:         XEiJ.busWb (a++, spc);  //空白
  2717:       }
  2718:       if (sgn1 != 0) {
  2719:         XEiJ.busWb (a++, sgn1);  //先頭の符号
  2720:       }
  2721:       if (yen != 0) {
  2722:         XEiJ.busWb (a++, yen);  //'\\'
  2723:       }
  2724:       for (int i = ee; 0 <= i; i--) {
  2725:         XEiJ.busWb (a++, h < o ? '0' + w[h] : '0');  //整数部
  2726:         h++;
  2727:         if (cmm != 0 && 0 < i && i % 3 == 0) {
  2728:           XEiJ.busWb (a++, cmm);  //','
  2729:         }
  2730:       }
  2731:       XEiJ.busWb (a++, '.');  //小数点
  2732:       for (; 0 < len2; len2--) {
  2733:         XEiJ.busWb (a++, h < o ? '0' + w[h] : '0');  //小数部
  2734:         h++;
  2735:       }
  2736:     } else {  //x<1
  2737:       for (int i = len1 - ((sgn1 != 0 ? 1 : 0) +  //先頭の符号
  2738:                            (yen != 0 ? 1 : 0) +  //'\\'
  2739:                            1  //数字
  2740:                            ); 0 < i; i--) {
  2741:         XEiJ.busWb (a++, spc);  //空白
  2742:       }
  2743:       if (sgn1 != 0) {
  2744:         XEiJ.busWb (a++, sgn1);  //先頭の符号
  2745:       }
  2746:       if (yen != 0) {
  2747:         XEiJ.busWb (a++, yen);  //'\\'
  2748:       }
  2749:       if (0 < len1) {
  2750:         XEiJ.busWb (a++, '0');  //整数部
  2751:       }
  2752:       XEiJ.busWb (a++, '.');  //小数点
  2753:       for (int i = -1 - ee; 0 < len2 && 0 < i; len2--, i--) {
  2754:         XEiJ.busWb (a++, '0');  //小数部の先頭の0の並び
  2755:       }
  2756:       for (; 0 < len2; len2--) {
  2757:         XEiJ.busWb (a++, h < o ? '0' + w[h] : '0');  //小数部
  2758:         h++;
  2759:       }
  2760:     }
  2761:     if (exp) {
  2762:       e -= ee;
  2763:       XEiJ.busWb (a++, 'E');  //指数部の始まり
  2764:       if (0 <= e) {
  2765:         XEiJ.busWb (a++, '+');  //指数部の正符号。省略しない
  2766:       } else {
  2767:         XEiJ.busWb (a++, '-');  //指数部の負符号
  2768:         e = -e;
  2769:       }
  2770:       e = XEiJ.FMT_BCD4[e];
  2771:       XEiJ.busWb (a++, '0' + (e >> 8     ));  //指数部の100の位。0でも省略しない
  2772:       XEiJ.busWb (a++, '0' + (e >> 4 & 15));  //指数部の10の位
  2773:       XEiJ.busWb (a++, '0' + (e      & 15));  //指数部の1の位
  2774:     }
  2775:     if (sgn2 != 0) {
  2776:       XEiJ.busWb (a++, sgn2);  //末尾の符号
  2777:     }
  2778:     XEiJ.busWb (a, '\0');
  2779:   }  //fpkUSINGSub0(long)
  2780: 
  2781:   //fpkSTOD ()
  2782:   //  $FE22  __STOD
  2783:   //  文字列を64bit浮動小数点数に変換する
  2784:   //  先頭の'\t'と' 'を読み飛ばす
  2785:   //  "#INF"は無限大、"#NAN"は非数とみなす
  2786:   //  バグ
  2787:   //    FLOAT2.X 2.02/2.03は誤差が大きい
  2788:   //      "1.7976931348623E+308"=0x7fefffffffffffb0が0x7fefffffffffffb3になる
  2789:   //      "1.5707963267949"=0x3ff921fb54442d28が0x3ff921fb54442d26になる
  2790:   //      "4.9406564584125E-324"(非正規化数の最小値よりもわずかに大きい)がエラーになる
  2791:   //    FLOAT2.X 2.02/2.03は"-0"が+0になる
  2792:   //    FLOAT4.X 1.02は"-0"が+0になる(実機で確認済み)
  2793:   //    FLOAT2.X 2.02/2.03は"-#INF"が+Infになる
  2794:   //      print val("-#INF")で再現できる
  2795:   //      '-'を符号として解釈しておきながら結果の無限大に符号を付けるのを忘れている
  2796:   //    FLOAT2.X 2.02/2.03は".#INF"が+Infになる
  2797:   //      print val(".#INF")で再現できる
  2798:   //    FLOAT4.X 1.02は"#NAN","#INF","-#INF"を読み取ったときa0が文字列の直後ではなく最後の文字を指している
  2799:   //  <a0.l:文字列の先頭
  2800:   //  >d0d1.d:64bit浮動小数点数
  2801:   //  >d2.l:65535=64bit浮動小数点数をオーバーフローなしでintに変換できる,0=それ以外
  2802:   //  >d3.l:d2.l==65535のとき64bit浮動小数点数をintに変換した値
  2803:   //  >a0.l:変換された文字列の直後('\0'とは限らない)
  2804:   //  >ccr:0=エラーなし,N|C=文法エラー,V|C=オーバーフロー
  2805:   public static void fpkSTOD () throws M68kException {
  2806:     long l = Double.doubleToLongBits (fpkSTODSub ());
  2807:     if (FPK_FPCP_NAN && l == 0x7ff8000000000000L) {
  2808:       l = 0x7fffffffffffffffL;
  2809:     }
  2810:     XEiJ.regRn[0] = (int) (l >> 32);  //d0
  2811:     XEiJ.regRn[1] = (int) l;  //d1
  2812:   }  //fpkSTOD()
  2813:   public static double fpkSTODSub () throws M68kException {
  2814:     int a = XEiJ.regRn[8];  //a0
  2815:     //先頭の空白を読み飛ばす
  2816:     int c = XEiJ.busRbs (a);
  2817:     while (c == ' ' || c == '\t') {
  2818:       c = XEiJ.busRbs (++a);
  2819:     }
  2820:     //符号を読み取る
  2821:     double s = 1.0;  //仮数部の符号
  2822:     if (c == '+') {
  2823:       c = XEiJ.busRbs (++a);
  2824:     } else if (c == '-') {
  2825:       s = -s;
  2826:       c = XEiJ.busRbs (++a);
  2827:     }
  2828:     //#NANと#INFを処理する
  2829:     if (c == '#') {
  2830:       c = XEiJ.busRbs (a + 1);
  2831:       if (c == 'N' || c == 'I') {  //小文字は不可
  2832:         c = c << 8 | XEiJ.busRbz (a + 2);
  2833:         if (c == ('N' << 8 | 'A') || c == ('I' << 8 | 'N')) {
  2834:           c = c << 8 | XEiJ.busRbz (a + 3);
  2835:           if (c == ('N' << 16 | 'A' << 8 | 'N') || c == ('I' << 16 | 'N' << 8 | 'F')) {
  2836:             XEiJ.regRn[2] = 0;  //d2
  2837:             XEiJ.regRn[3] = 0;  //d3
  2838:             XEiJ.regRn[8] = a + 4;  //a0。"#NAN"または"#INF"のときだけ直後まで進める。それ以外は'#'の位置で止める
  2839:             XEiJ.regCCR = 0;  //エラーなし。"#INF"はオーバーフローとみなされない
  2840:             return c == ('N' << 16 | 'A' << 8 | 'N') ? Double.NaN : s * Double.POSITIVE_INFINITY;
  2841:           }
  2842:         }
  2843:       }
  2844:       XEiJ.regRn[8] = a;  //a0。'#'の位置で止める
  2845:       XEiJ.regCCR = XEiJ.REG_CCR_N | XEiJ.REG_CCR_C;  //文法エラー
  2846:       return 0.0;
  2847:     }  //if c=='#'
  2848:     //仮数部を読み取る
  2849:     //  数字を1000個並べてからe-1000などと書いてあるとき途中でオーバーフローすると困るので、
  2850:     //  多すぎる数字の並びは先頭の有効数字だけ読み取って残りは桁数だけ数えて読み飛ばす
  2851:     long u = 0L;  //仮数部
  2852:     int n = 0;  //0以外の最初の数字から数えて何桁目か
  2853:     int e = 1;  //-小数部の桁数。1=整数部
  2854:     if (c == '.') {  //仮数部の先頭が小数点
  2855:       e = 0;  //小数部開始
  2856:       c = XEiJ.busRbs (++a);
  2857:     }
  2858:     if (c < '0' || '9' < c) {  //仮数部に数字がない
  2859:       XEiJ.regRn[8] = a;  //a0
  2860:       XEiJ.regCCR = XEiJ.REG_CCR_N | XEiJ.REG_CCR_C;  //文法エラー
  2861:       return 0.0;
  2862:     }
  2863:     double x = 0.0;
  2864:     do {
  2865:       if (0 < n || '0' < c) {  //0以外
  2866:         n++;  //0以外の最初の数字から数えて何桁目か
  2867:       }
  2868:       if (e <= 0 && n <= 18) {  //小数部で18桁目まで
  2869:         e--;  //-小数部の桁数
  2870:       }
  2871:       if (0 < n && n <= 18) {  //1桁目から18桁目まで
  2872:         u = u * 10L + (long) (c - '0');
  2873:       }
  2874:       c = XEiJ.busRbs (++a);
  2875:       if (0 < e && c == '.') {  //整数部で小数点が出てきた
  2876:         e = 0;  //小数部開始
  2877:         c = XEiJ.busRbs (++a);
  2878:       }
  2879:     } while ('0' <= c && c <= '9');
  2880:     if (0 < e) {  //小数点が出てこなかった
  2881:       e = 18 < n ? n - 18 : 0;  //整数部を読み飛ばした桁数が(-小数部の桁数)
  2882:     }
  2883:     //  1<=u<10^18  整数なので誤差はない
  2884:     //  0<e   小数点がなくて整数部が19桁以上あって末尾を読み飛ばした
  2885:     //  e==0  小数点がなくて整数部が18桁以内で末尾を読み飛ばさなかった
  2886:     //        小数点があって小数点で終わっていた
  2887:     //  e<0   小数点があって小数部が1桁以上あった
  2888:     //指数部を読み取る
  2889:     if (c == 'E' || c == 'e') {
  2890:       c = XEiJ.busRbs (++a);
  2891:       int t = 1;  //指数部の符号
  2892:       if (c == '+') {
  2893:         c = XEiJ.busRbs (++a);
  2894:       } else if (c == '-') {
  2895:         t = -t;
  2896:         c = XEiJ.busRbs (++a);
  2897:       }
  2898:       if (c < '0' || '9' < c) {  //指数部に数字がない
  2899:         XEiJ.regRn[8] = a;  //a0
  2900:         XEiJ.regCCR = XEiJ.REG_CCR_N | XEiJ.REG_CCR_C;  //文法エラー
  2901:         return 0.0;
  2902:       }
  2903:       while (c == '0') {  //先頭の0を読み飛ばす
  2904:         c = XEiJ.busRbs (++a);
  2905:       }
  2906:       int p = 0;
  2907:       for (int j = 0; '0' <= c && c <= '9' && j < 9; j++) {  //0以外の数字が出てきてから最大で9桁目まで読み取る。Human68kの環境では数字を1GBも並べることはできないのでオーバーフローの判定には9桁あれば十分
  2908:         p = p * 10 + (c - '0');
  2909:         c = XEiJ.busRbs (++a);
  2910:       }
  2911:       e += t * p;
  2912:     }
  2913:     //符号と仮数部と指数部を合わせる
  2914:     //  x=s*x*10^e
  2915:     //  1<=u<10^18なのでeが範囲を大きく外れている場合を先に除外する
  2916:     if (e < -350) {
  2917:       XEiJ.regRn[2] = 65535;  //d2。-1ではない
  2918:       XEiJ.regRn[3] = 0;  //d3
  2919:       XEiJ.regRn[8] = a;  //a0
  2920:       XEiJ.regCCR = 0;  //エラーなし。アンダーフローはエラーとみなされない
  2921:       return s < 0.0 ? -0.0 : 0.0;
  2922:     }
  2923:     if (350 < e) {
  2924:       XEiJ.regRn[2] = 0;  //d2
  2925:       XEiJ.regRn[3] = 0;  //d3
  2926:       XEiJ.regRn[8] = a;  //a0
  2927:       XEiJ.regCCR = XEiJ.REG_CCR_V | XEiJ.REG_CCR_C;  //オーバーフロー
  2928:       return s * Double.POSITIVE_INFINITY;
  2929:     }
  2930:     if (true) {
  2931:       QFP xx = new QFP (s < 0.0 ? -u : u);  //符号と仮数部
  2932:       if (0 < e) {
  2933:         xx.mul (QFP.QFP_TEN_P16QR[e & 15]);
  2934:         if (16 <= e) {
  2935:           xx.mul (QFP.QFP_TEN_P16QR[16 + (e >> 4 & 15)]);
  2936:           if (256 <= e) {
  2937:             xx.mul (QFP.QFP_TEN_P16QR[33]);
  2938:           }
  2939:         }
  2940:       } else if (e < 0) {
  2941:         xx.mul (QFP.QFP_TEN_M16QR[-e & 15]);
  2942:         if (e <= -16) {
  2943:           xx.mul (QFP.QFP_TEN_M16QR[16 + (-e >> 4 & 15)]);
  2944:           if (e <= -256) {
  2945:             xx.mul (QFP.QFP_TEN_M16QR[33]);
  2946:           }
  2947:         }
  2948:       }
  2949:       x = xx.getd ();
  2950:     } else {
  2951:       x = s * (double) u;  //符号と仮数部
  2952:       if (0 < e) {
  2953:         x *= FPK_TEN_P16QR[e & 15];
  2954:         if (16 <= e) {
  2955:           x *= FPK_TEN_P16QR[16 + (e >> 4 & 15)];
  2956:           if (256 <= e) {
  2957:             x *= FPK_TEN_P16QR[33];  //FPK_TEN_P16QR[32 + (e >> 8)]
  2958:           }
  2959:         }
  2960:       } else if (e < 0) {
  2961:         x /= FPK_TEN_P16QR[-e & 15];
  2962:         if (e <= -16) {
  2963:           x /= FPK_TEN_P16QR[16 + (-e >> 4 & 15)];
  2964:           if (e <= -256) {
  2965:             x /= FPK_TEN_P16QR[33];  //FPK_TEN_P16QR[32 + (-e >> 8)]
  2966:           }
  2967:         }
  2968:       }
  2969:     }
  2970:     if (Double.isInfinite (x)) {
  2971:       XEiJ.regRn[8] = a;  //a0
  2972:       XEiJ.regCCR = XEiJ.REG_CCR_V | XEiJ.REG_CCR_C;  //オーバーフロー
  2973:       return x;
  2974:     }
  2975:     //  アンダーフローで0になっている場合がある
  2976:     if (x == (double) ((int) x)) {  //intで表現できる。+0.0==-0.0==0なので±0.0を含む
  2977:       XEiJ.regRn[2] = 65535;  //d2。-1ではない
  2978:       XEiJ.regRn[3] = (int) x;  //d3
  2979:     } else {  //intで表現できない
  2980:       XEiJ.regRn[2] = 0;  //d2
  2981:       XEiJ.regRn[3] = 0;  //d3
  2982:     }
  2983:     XEiJ.regRn[8] = a;  //a0
  2984:     XEiJ.regCCR = 0;  //エラーなし
  2985:     return x;
  2986:   }  //fpkSTODSub()
  2987: 
  2988:   //fpkDTOS ()
  2989:   //  $FE23  __DTOS
  2990:   //  64bit浮動小数点数を文字列に変換する
  2991:   //  無限大は"#INF"、非数は"#NAN"になる
  2992:   //  指数形式の境目
  2993:   //    x<10^-4または10^14<=xのとき指数形式にする
  2994:   //    FLOAT2.X/FLOAT4.Xの場合
  2995:   //      3f2fffffffffff47  2.4414062499999E-004
  2996:   //      3f2fffffffffff48  0.000244140625
  2997:   //      42d6bcc41e8fffdf  99999999999999
  2998:   //      42d6bcc41e8fffe0  1E+014
  2999:   //  <d0d1.d:64bit浮動小数点数
  3000:   //  <a0.l:文字列バッファの先頭
  3001:   //  >a0.l:末尾の'\0'の位置
  3002:   public static void fpkDTOS () throws M68kException {
  3003:     fpkDTOSSub ((long) XEiJ.regRn[0] << 32 | 0xffffffffL & XEiJ.regRn[1]);  //64bit浮動小数点数
  3004:   }  //fpkDTOS()
  3005:   public static void fpkDTOSSub (long l) throws M68kException {
  3006:     final int len3 = 14;
  3007:     int a = XEiJ.regRn[8];  //文字列バッファの先頭
  3008:     //符号と指数部の処理
  3009:     //  ±0,±Inf,NaNはここで除外する
  3010:     if (l < 0L) {
  3011:       XEiJ.busWb (a++, '-');  //負符号
  3012:       l &= 0x7fffffffffffffffL;  //符号bitを消しておく
  3013:     }
  3014:     double x = Double.longBitsToDouble (l);  //絶対値
  3015:     int e = (int) (l >>> 52) - 1023;  //指数部。ゲタ0。符号bitは消してあるのでマスクは不要
  3016:     l &= 0x000fffffffffffffL;  //仮数部の小数部。正規化数のとき整数部の1が付いていないことに注意
  3017:     if (e == -1023) {  //±0,非正規化数
  3018:       if (l == 0L) {  //±0
  3019:         XEiJ.busWb (a++, '0');  //0
  3020:         XEiJ.busWb (a, '\0');
  3021:         XEiJ.regRn[8] = a;  //末尾の'\0'の位置
  3022:         return;
  3023:       }
  3024:       e -= Long.numberOfLeadingZeros (l) - 12;  //非正規化数の指数部を補正する
  3025:     } else if (e == 1024) {  //±Inf,NaN
  3026:       XEiJ.busWb (a++, '#');
  3027:       if (l == 0L) {  //±Inf
  3028:         XEiJ.busWb (a++, 'I');
  3029:         XEiJ.busWb (a++, 'N');
  3030:         XEiJ.busWb (a++, 'F');
  3031:       } else {  //NaN
  3032:         XEiJ.busWb (a++, 'N');
  3033:         XEiJ.busWb (a++, 'A');
  3034:         XEiJ.busWb (a++, 'N');
  3035:       }
  3036:       XEiJ.busWb (a, '\0');
  3037:       XEiJ.regRn[8] = a;  //末尾の'\0'の位置
  3038:       return;
  3039:     }
  3040:     //10進数で表現したときの指数部を求める
  3041:     //  10^e<=x<10^(e+1)となるeを求める
  3042:     e = (int) Math.floor ((double) e * 0.30102999566398119521373889472);  //log10(2)
  3043:     //10^-eを掛けて1<=x<10にする
  3044:     //  非正規化数の最小値から正規化数の最大値まで処理できなければならない
  3045:     //  10^-eを計算してからまとめて掛ける方法はxが非正規化数のとき10^-eがオーバーフローしてしまうので不可
  3046:     //    doubleは非正規化数の逆数を表現できない
  3047:     if (0 < e) {  //10<=x
  3048:       x *= FPK_TEN_M16QR[e & 15];
  3049:       if (16 <= e) {
  3050:         x *= FPK_TEN_M16QR[16 + (e >> 4 & 15)];
  3051:         if (256 <= e) {
  3052:           x *= FPK_TEN_M16QR[33];  //FPK_TEN_M16QR[32 + (e >> 8)]
  3053:         }
  3054:       }
  3055:     } else if (e < 0) {  //x<1
  3056:       x *= FPK_TEN_P16QR[-e & 15];
  3057:       if (e <= -16) {
  3058:         x *= FPK_TEN_P16QR[16 + (-e >> 4 & 15)];
  3059:         if (e <= -256) {
  3060:           x *= FPK_TEN_P16QR[33];  //FPK_TEN_P16QR[32 + (-e >> 8)]
  3061:         }
  3062:       }
  3063:     }
  3064:     //整数部2桁、小数部16桁の10進数に変換する
  3065:     //  1<=x<10なのでw[1]が先頭になるはずだが誤差で前後にずれる可能性がある
  3066:     int[] w = new int[18];
  3067:     {
  3068:       int d = (int) x;
  3069:       int t = XEiJ.FMT_BCD4[d];
  3070:       w[0] = t >> 4;
  3071:       w[1] = t      & 15;
  3072:       for (int i = 2; i < 18; i += 4) {
  3073:         //xを10000倍して整数部dを引くことで小数部を残すが、このとき情報落ちが発生して誤差が蓄積する
  3074:         //Double-Doubleの乗算の要領で10000倍を正確に行い、誤差の蓄積を回避する
  3075:         //x = (x - (double) d) * 10000.0;
  3076:         double xh = x * 0x8000001p0;
  3077:         xh += x - xh;  //xの上半分
  3078:         x = (xh - (double) d) * 10000.0 + (x - xh) * 10000.0;
  3079:         d = (int) x;
  3080:         t = XEiJ.FMT_BCD4[d];
  3081:         w[i    ] = t >> 12;
  3082:         w[i + 1] = t >>  8 & 15;
  3083:         w[i + 2] = t >>  4 & 15;
  3084:         w[i + 3] = t       & 15;
  3085:       }
  3086:     }
  3087:     //先頭の位置を確認する
  3088:     //  w[h]が先頭(0でない最初の数字)の位置
  3089:     int h = w[0] != 0 ? 0 : w[1] != 0 ? 1 : 2;
  3090:     //14+1桁目を四捨五入する
  3091:     int o = h + 14;  //w[o]は四捨五入する桁の位置。w[]の範囲内
  3092:     if (5 <= w[o]) {
  3093:       int i = o;
  3094:       while (10 <= ++w[--i]) {
  3095:         w[i] = 0;
  3096:       }
  3097:       if (i < h) {  //先頭から繰り上がった。このとき新しい先頭は1でそれ以外はすべて0
  3098:         h--;  //先頭を左にずらす
  3099:         o--;  //末尾を左にずらす
  3100:       }
  3101:     }
  3102:     //先頭の位置に応じて指数部を更新する
  3103:     //  w[h]が整数部、w[h+1..o-1]が小数部。10^eの小数点はw[h]の右側。整数部の桁数はe+1桁
  3104:     e -= h - 1;
  3105:     //末尾の位置を確認する
  3106:     //  w[o-1]が末尾(0でない最後の数字)の位置
  3107:     while (w[o - 1] == 0) {  //全体は0ではないので必ず止まる。小数点よりも左側で止まる場合があることに注意
  3108:       o--;
  3109:     }
  3110:     //指数形式にするかどうか選択して文字列に変換する
  3111:     if (0 <= e && e < len3) {  //1<=x<10^len3。指数形式にしない
  3112:       for (; 0 <= e && h < o; e--) {
  3113:         XEiJ.busWb (a++, '0' + w[h++]);  //整数部
  3114:       }
  3115:       for (; 0 <= e; e--) {
  3116:         XEiJ.busWb (a++, '0');  //整数部。末尾の位置に関係なく1の位まで書く
  3117:       }
  3118:       if (h < o) {  //小数部がある
  3119:         XEiJ.busWb (a++, '.');  //小数部があるときだけ小数点を書く
  3120:         do {
  3121:           XEiJ.busWb (a++, '0' + w[h++]);  //小数部
  3122:         } while (h < o);
  3123:       }
  3124:     } else if (-4 <= e && e < 0) {  //10^-4<=x<1。指数形式にしない
  3125:       XEiJ.busWb (a++, '0');  //整数部の0
  3126:       XEiJ.busWb (a++, '.');  //小数点
  3127:       while (++e < 0) {
  3128:         XEiJ.busWb (a++, '0');  //小数部の先頭の0の並び
  3129:       }
  3130:       do {
  3131:         XEiJ.busWb (a++, '0' + w[h++]);  //小数部
  3132:       } while (h < o);
  3133:     } else {  //x<10^-4または10^len3<=x。指数形式にする
  3134:       XEiJ.busWb (a++, '0' + w[h++]);  //整数部
  3135:       if (h < o) {  //小数部がある
  3136:         XEiJ.busWb (a++, '.');  //小数部があるときだけ小数点を書く
  3137:         do {
  3138:           XEiJ.busWb (a++, '0' + w[h++]);  //小数部
  3139:         } while (h < o);
  3140:       }
  3141:       XEiJ.busWb (a++, 'E');  //指数部の始まり
  3142:       if (0 <= e) {
  3143:         XEiJ.busWb (a++, '+');  //指数部の正符号。省略しない
  3144:       } else {
  3145:         XEiJ.busWb (a++, '-');  //指数部の負符号
  3146:         e = -e;
  3147:       }
  3148:       e = XEiJ.FMT_BCD4[e];
  3149:       XEiJ.busWb (a++, '0' + (e >> 8     ));  //指数部の100の位。0でも省略しない
  3150:       XEiJ.busWb (a++, '0' + (e >> 4 & 15));  //指数部の10の位
  3151:       XEiJ.busWb (a++, '0' + (e      & 15));  //指数部の1の位
  3152:     }
  3153:     XEiJ.busWb (a, '\0');
  3154:     XEiJ.regRn[8] = a;  //末尾の'\0'の位置
  3155:   }  //fpkDTOSSub0()
  3156: 
  3157:   //fpkECVT ()
  3158:   //  $FE24  __ECVT
  3159:   //  64bit浮動小数点数を全体の桁数を指定して文字列に変換する
  3160:   //  文字列に書くのは仮数部の数字のみ
  3161:   //  符号と小数点と指数部は文字列に書かず、小数点の位置と符号をレジスタに入れて返す
  3162:   //  桁数は255桁まで指定できるが、有効桁数は14桁まで
  3163:   //    有効桁数の次の桁で絶対値を四捨五入する
  3164:   //    15桁以上を指定しても14桁に丸められ、15桁目以降はすべて'0'になる
  3165:   //  無限大は"#INF"、非数は"#NAN"に変換する
  3166:   //    "#INF"と"#NAN"のとき小数点の位置は4になる
  3167:   //    "#INF"と"#NAN"で3桁以下のときは途中で打ち切る
  3168:   //    "#INF"と"#NAN"で5桁以上のときは5桁目以降はすべて'\0'になる
  3169:   //  バグ
  3170:   //    FLOATn.Xは"#INF"と"#NAN"で1桁~3桁のとき文字列が"$","$0","$00"になってしまう
  3171:   //      文字数が少なすぎて"#INF"や"#NAN"が入り切らないのは仕方がないが、
  3172:   //      無意味な"$00"という文字列になるのは数字ではない文字列を四捨五入しようとするバグが原因
  3173:   //      例えば3桁のときは4桁目の'F'または'N'が'5'以上なので繰り上げて上の位をインクリメントする
  3174:   //      'N'+1='O'または'A'+1='B'が'9'よりも大きいので'0'を上書きして繰り上げて上の位をインクリメントする
  3175:   //      'I'+1='J'または'N'+1='O'も'9'よりも大きいので'0'を上書きして繰り上げて上の位をインクリメントする
  3176:   //      '#'+1='$'は'9'以下なので"$00"になる
  3177:   //      X-BASICでint i2,i3:print ecvt(val("#INF"),3,i2,i3)とすると再現できる
  3178:   //    FLOATn.Xは"#NAN"と"#INF"で15桁以上のとき5桁目から14桁目までは'\0'だが15桁目以降に'0'が書き込まれる
  3179:   //      通常は5桁目の'\0'で文字列は終了していると見なされるので実害はないが気持ち悪い
  3180:   //    FLOAT2.X 2.02/2.03は0のとき小数点の位置が0になる
  3181:   //      FLOAT4.X 1.02は0のとき小数点の位置が1になる
  3182:   //      ここでは1にしている
  3183:   //  <d0d1.d:64bit浮動小数点数
  3184:   //  <d2.l:全体の桁数
  3185:   //  <a0.l:文字列バッファの先頭。末尾に'\0'を書き込むので桁数+1バイト必要
  3186:   //  >d0.l:先頭から小数点の位置までのオフセット
  3187:   //  >d1.l:符号(0=+,1=-)
  3188:   //  a0.lは変化しない
  3189:   public static void fpkECVT () throws M68kException {
  3190:     fpkECVTSub ((long) XEiJ.regRn[0] << 32 | 0xffffffffL & XEiJ.regRn[1]);  //64bit浮動小数点数
  3191:   }  //fpkECVT()
  3192:   public static void fpkECVTSub (long l) throws M68kException {
  3193:     int len3 = XEiJ.regRn[2];  //全体の桁数
  3194:     int a = XEiJ.regRn[8];  //文字列バッファの先頭
  3195:     if (len3 <= 0) {  //全体の桁数が0
  3196:       XEiJ.busWb (a, '\0');
  3197:       return;
  3198:     }
  3199:     int b = a + len3;  //文字列バッファの末尾+1。'\0'を書き込む位置
  3200:     //符号と指数部の処理
  3201:     //  ±0,±Inf,NaNはここで除外する
  3202:     if (0L <= l) {
  3203:       XEiJ.regRn[1] = 0;  //正符号
  3204:     } else {
  3205:       XEiJ.regRn[1] = 1;  //負符号
  3206:       l &= 0x7fffffffffffffffL;  //符号bitを消しておく
  3207:     }
  3208:     double x = Double.longBitsToDouble (l);  //絶対値
  3209:     int e = (int) (l >>> 52) - 1023;  //指数部。ゲタ0。符号bitは消してあるのでマスクは不要
  3210:     l &= 0x000fffffffffffffL;  //仮数部の小数部。正規化数のとき整数部の1が付いていないことに注意
  3211:     if (e == -1023) {  //±0,非正規化数
  3212:       if (l == 0L) {  //±0
  3213:         //指定された全体の桁数だけ'0'を並べる
  3214:         while (a < b) {
  3215:           XEiJ.busWb (a++, '0');
  3216:         }
  3217:         XEiJ.busWb (a, '\0');
  3218:         XEiJ.regRn[0] = 1;  //小数点の位置
  3219:         return;
  3220:       }
  3221:       e -= Long.numberOfLeadingZeros (l) - 12;  //非正規化数の指数部を補正する
  3222:     } else if (e == 1024) {  //±Inf,NaN
  3223:       for (int s = l != 0L ? '#' | 'N' << 8 | 'A' << 16 | 'N' << 24 : '#' | 'I' << 8 | 'N' << 16 | 'F' << 24; a < b && s != 0; s >>>= 8) {
  3224:         XEiJ.busWb (a++, s);
  3225:       }
  3226:       while (a < b) {
  3227:         XEiJ.busWb (a++, '\0');  //残りは'\0'
  3228:       }
  3229:       XEiJ.busWb (a, '\0');
  3230:       XEiJ.regRn[0] = 4;  //小数点の位置
  3231:       return;
  3232:     }
  3233:     //10進数で表現したときの指数部を求める
  3234:     //  10^e<=x<10^(e+1)となるeを求める
  3235:     e = (int) Math.floor ((double) e * 0.30102999566398119521373889472);  //log10(2)
  3236:     //10^-eを掛けて1<=x<10にする
  3237:     //  非正規化数の最小値から正規化数の最大値まで処理できなければならない
  3238:     //  10^-eを計算してからまとめて掛ける方法はxが非正規化数のとき10^-eがオーバーフローしてしまうので不可
  3239:     //    doubleは非正規化数の逆数を表現できない
  3240:     if (0 < e) {  //10<=x
  3241:       x *= FPK_TEN_M16QR[e & 15];
  3242:       if (16 <= e) {
  3243:         x *= FPK_TEN_M16QR[16 + (e >> 4 & 15)];
  3244:         if (256 <= e) {
  3245:           x *= FPK_TEN_M16QR[33];  //FPK_TEN_M16QR[32 + (e >> 8)]
  3246:         }
  3247:       }
  3248:     } else if (e < 0) {  //x<1
  3249:       x *= FPK_TEN_P16QR[-e & 15];
  3250:       if (e <= -16) {
  3251:         x *= FPK_TEN_P16QR[16 + (-e >> 4 & 15)];
  3252:         if (e <= -256) {
  3253:           x *= FPK_TEN_P16QR[33];  //FPK_TEN_P16QR[32 + (-e >> 8)]
  3254:         }
  3255:       }
  3256:     }
  3257:     //整数部2桁、小数部16桁の10進数に変換する
  3258:     //  1<=x<10なのでw[1]が先頭になるはずだが誤差で前後にずれる可能性がある
  3259:     int[] w = new int[18];
  3260:     {
  3261:       int d = (int) x;
  3262:       int t = XEiJ.FMT_BCD4[d];
  3263:       w[0] = t >> 4;
  3264:       w[1] = t      & 15;
  3265:       for (int i = 2; i < 18; i += 4) {
  3266:         //xを10000倍して整数部dを引くことで小数部を残すが、このとき情報落ちが発生して誤差が蓄積する
  3267:         //Double-Doubleの乗算の要領で10000倍を正確に行い、誤差の蓄積を回避する
  3268:         //x = (x - (double) d) * 10000.0;
  3269:         double xh = x * 0x8000001p0;
  3270:         xh += x - xh;  //xの上半分
  3271:         x = (xh - (double) d) * 10000.0 + (x - xh) * 10000.0;
  3272:         d = (int) x;
  3273:         t = XEiJ.FMT_BCD4[d];
  3274:         w[i    ] = t >> 12;
  3275:         w[i + 1] = t >>  8 & 15;
  3276:         w[i + 2] = t >>  4 & 15;
  3277:         w[i + 3] = t       & 15;
  3278:       }
  3279:     }
  3280:     //先頭の位置を確認する
  3281:     //  w[h]が先頭(0でない最初の数字)の位置
  3282:     int h = w[0] != 0 ? 0 : w[1] != 0 ? 1 : 2;
  3283:     //14+1桁目を四捨五入する
  3284:     int o = h + 14;  //w[o]は四捨五入する桁の位置。w[]の範囲内
  3285:     if (5 <= w[o]) {
  3286:       int i = o;
  3287:       while (10 <= ++w[--i]) {
  3288:         w[i] = 0;
  3289:       }
  3290:       if (i < h) {  //先頭から繰り上がった。このとき新しい先頭は1でそれ以外はすべて0
  3291:         h--;  //先頭を左にずらす
  3292:         o--;  //末尾を左にずらす
  3293:       }
  3294:     }
  3295:     //先頭の位置に応じて指数部を更新する
  3296:     //  w[h]が整数部、w[h+1..o-1]が小数部。10^eの小数点はw[h]の右側。整数部の桁数はe+1桁
  3297:     e -= h - 1;
  3298:     //先頭からlen3+1桁目が先頭から14+1桁目よりも左側にあるときその桁で改めて四捨五入する
  3299:     //  あらかじめ14+1桁目で四捨五入しておかないと、
  3300:     //  1.5の5を四捨五入しなければならないときに誤差で1.499…になったまま4を四捨五入しようとして失敗することがある
  3301:     int s = h + len3;  //w[s]は先頭からlen3+1桁目の位置。w.length<=sの場合があることに注意
  3302:     if (s < o) {
  3303:       o = s;  //w[o]は四捨五入する桁の位置。o<0の場合があることに注意
  3304:       if (0 <= o && 5 <= w[o]) {
  3305:         int i = o;
  3306:         while (10 <= ++w[--i]) {
  3307:           w[i] = 0;
  3308:         }
  3309:         if (i < h) {  //先頭から繰り上がった。このとき新しい先頭は1でそれ以外はすべて0
  3310:           h--;  //先頭を左にずらす
  3311:           o--;  //末尾を左にずらす
  3312:           e++;  //指数部を1増やす
  3313:         }
  3314:       }
  3315:     }
  3316:     //文字列に変換する
  3317:     while (a < b && h < o) {
  3318:       XEiJ.busWb (a++, '0' + w[h++]);  //有効数字
  3319:     }
  3320:     while (a < b) {
  3321:       XEiJ.busWb (a++, '0');  //残りは'0'
  3322:     }
  3323:     XEiJ.busWb (a, '\0');
  3324:     XEiJ.regRn[0] = e + 1;  //小数点の位置
  3325:   }  //fpkECVTSub0()
  3326: 
  3327:   //fpkFCVT ()
  3328:   //  $FE25  __FCVT
  3329:   //  64bit浮動小数点数を小数点以下の桁数を指定して文字列に変換する
  3330:   //  小数点の位置がpのとき[p]の左側に小数点がある
  3331:   //  全体の桁数が制限されないので指数部が大きいとき整数部が収まるサイズのバッファが必要
  3332:   //  0または1以上のとき
  3333:   //    整数部と小数点以下の指定された桁数までを小数部の0を省略せずに出力する
  3334:   //    整数部と小数点以下の指定された桁数が合わせて14桁を超えるときは15桁目が四捨五入されて15桁目以降は0になる
  3335:   //    小数点の位置は整数部の桁数に等しい
  3336:   //    print fcvt(0#,4,i2,i3),i2,i3
  3337:   //    0000     0       0
  3338:   //    print fcvt(2e+12/3#,4,i2,i3),i2,i3
  3339:   //    6666666666666700         12      0
  3340:   //               ↑
  3341:   //  1未満のとき
  3342:   //    小数点以下の桁数の範囲内を先頭の0を省略して出力する
  3343:   //    小数点以下の桁数の範囲内がすべて0のときは""になる
  3344:   //    小数点の位置は指数部+1に等しい
  3345:   //    print fcvt(0.01,3,i2,i3),i2,i3                0.010
  3346:   //    10      -1       0                              <~~
  3347:   //    print fcvt(0.001,3,i2,i3),i2,i3               0.001
  3348:   //    1       -2       0                              <<~
  3349:   //    print fcvt(0.0001,3,i2,i3),i2,i3              0.0001
  3350:   //            -3       0                              <<<
  3351:   //    print fcvt(0.00001,3,i2,i3),i2,i3             0.00001
  3352:   //            -4       0                              <<<<
  3353:   //  #INFと#NAN
  3354:   //    小数点以下の桁数の指定に関係なく4文字出力して小数点の位置4を返す
  3355:   //    print fcvt(val("#INF"),2,i2,i3),i2,i3
  3356:   //    #INF     4       0
  3357:   //    print fcvt(val("#INF"),6,i2,i3),i2,i3
  3358:   //    #INF     4       0
  3359:   //  バグ
  3360:   //    FLOAT4.X 1.02は結果が整数部が大きいとき255文字で打ち切られる
  3361:   //    FLOAT4.X 1.02はFCVT(±0)の整数部が0桁ではなく1桁になる
  3362:   //  <d0d1.d:64bit浮動小数点数
  3363:   //  <d2.l:小数点以下の桁数
  3364:   //  <a0.l:文字列バッファの先頭
  3365:   //  >d0.l:先頭から小数点の位置までのオフセット
  3366:   //  >d1.l:符号(0=+,1=-)
  3367:   public static void fpkFCVT () throws M68kException {
  3368:     fpkFCVTSub ((long) XEiJ.regRn[0] << 32 | 0xffffffffL & XEiJ.regRn[1]);  //64bit浮動小数点数
  3369:   }  //fpkFCVT()
  3370:   public static void fpkFCVTSub (long l) throws M68kException {
  3371:     int len2 = Math.max (0, XEiJ.regRn[2]);  //小数部の桁数
  3372:     int a = XEiJ.regRn[8];  //文字列バッファの先頭
  3373:     //符号と指数部の処理
  3374:     //  ±0,±Inf,NaNはここで除外する
  3375:     if (0L <= l) {
  3376:       XEiJ.regRn[1] = 0;  //正符号
  3377:     } else {
  3378:       XEiJ.regRn[1] = 1;  //負符号
  3379:       l &= 0x7fffffffffffffffL;  //符号bitを消しておく
  3380:     }
  3381:     double x = Double.longBitsToDouble (l);  //絶対値
  3382:     int e = (int) (l >>> 52) - 1023;  //指数部。ゲタ0。符号bitは消してあるのでマスクは不要
  3383:     l &= 0x000fffffffffffffL;  //仮数部の小数部。正規化数のとき整数部の1が付いていないことに注意
  3384:     if (e == -1023) {  //±0,非正規化数
  3385:       if (l == 0L) {  //±0
  3386:         //指定された小数点以下の桁数だけ'0'を並べる
  3387:         while (len2-- > 0) {
  3388:           XEiJ.busWb (a++, '0');
  3389:         }
  3390:         XEiJ.busWb (a, '\0');
  3391:         XEiJ.regRn[0] = 0;  //小数点の位置
  3392:         return;
  3393:       }
  3394:       e -= Long.numberOfLeadingZeros (l) - 12;  //非正規化数の指数部を補正する
  3395:     } else if (e == 1024) {  //±Inf,NaN
  3396:       XEiJ.busWb (a++, '#');
  3397:       if (l == 0L) {  //±Inf
  3398:         XEiJ.busWb (a++, 'I');
  3399:         XEiJ.busWb (a++, 'N');
  3400:         XEiJ.busWb (a++, 'F');
  3401:       } else {  //NaN
  3402:         XEiJ.busWb (a++, 'N');
  3403:         XEiJ.busWb (a++, 'A');
  3404:         XEiJ.busWb (a++, 'N');
  3405:       }
  3406:       XEiJ.busWb (a, '\0');
  3407:       XEiJ.regRn[0] = 4;  //小数点の位置
  3408:       return;
  3409:     }
  3410:     //10進数で表現したときの指数部を求める
  3411:     //  10^e<=x<10^(e+1)となるeを求める
  3412:     e = (int) Math.floor ((double) e * 0.30102999566398119521373889472);  //log10(2)
  3413:     //10^-eを掛けて1<=x<10にする
  3414:     //  非正規化数の最小値から正規化数の最大値まで処理できなければならない
  3415:     //  10^-eを計算してからまとめて掛ける方法はxが非正規化数のとき10^-eがオーバーフローしてしまうので不可
  3416:     //    doubleは非正規化数の逆数を表現できない
  3417:     if (0 < e) {  //10<=x
  3418:       x *= FPK_TEN_M16QR[e & 15];
  3419:       if (16 <= e) {
  3420:         x *= FPK_TEN_M16QR[16 + (e >> 4 & 15)];
  3421:         if (256 <= e) {
  3422:           x *= FPK_TEN_M16QR[33];  //FPK_TEN_M16QR[32 + (e >> 8)]
  3423:         }
  3424:       }
  3425:     } else if (e < 0) {  //x<1
  3426:       x *= FPK_TEN_P16QR[-e & 15];
  3427:       if (e <= -16) {
  3428:         x *= FPK_TEN_P16QR[16 + (-e >> 4 & 15)];
  3429:         if (e <= -256) {
  3430:           x *= FPK_TEN_P16QR[33];  //FPK_TEN_P16QR[32 + (-e >> 8)]
  3431:         }
  3432:       }
  3433:     }
  3434:     //整数部2桁、小数部16桁の10進数に変換する
  3435:     //  1<=x<10なのでw[1]が先頭になるはずだが誤差で前後にずれる可能性がある
  3436:     int[] w = new int[18];
  3437:     {
  3438:       int d = (int) x;
  3439:       int t = XEiJ.FMT_BCD4[d];
  3440:       w[0] = t >> 4;
  3441:       w[1] = t      & 15;
  3442:       for (int i = 2; i < 18; i += 4) {
  3443:         //xを10000倍して整数部dを引くことで小数部を残すが、このとき情報落ちが発生して誤差が蓄積する
  3444:         //Double-Doubleの乗算の要領で10000倍を正確に行い、誤差の蓄積を回避する
  3445:         //x = (x - (double) d) * 10000.0;
  3446:         double xh = x * 0x8000001p0;
  3447:         xh += x - xh;  //xの上半分
  3448:         x = (xh - (double) d) * 10000.0 + (x - xh) * 10000.0;
  3449:         d = (int) x;
  3450:         t = XEiJ.FMT_BCD4[d];
  3451:         w[i    ] = t >> 12;
  3452:         w[i + 1] = t >>  8 & 15;
  3453:         w[i + 2] = t >>  4 & 15;
  3454:         w[i + 3] = t       & 15;
  3455:       }
  3456:     }
  3457:     //先頭の位置を確認する
  3458:     //  w[h]が先頭(0でない最初の数字)の位置
  3459:     int h = w[0] != 0 ? 0 : w[1] != 0 ? 1 : 2;
  3460:     //14+1桁目を四捨五入する
  3461:     int o = h + 14;  //w[o]は四捨五入する桁の位置。w[]の範囲内
  3462:     if (5 <= w[o]) {
  3463:       int i = o;
  3464:       while (10 <= ++w[--i]) {
  3465:         w[i] = 0;
  3466:       }
  3467:       if (i < h) {  //先頭から繰り上がった。このとき新しい先頭は1でそれ以外はすべて0
  3468:         h--;  //先頭を左にずらす
  3469:         o--;  //末尾を左にずらす
  3470:       }
  3471:     }
  3472:     //先頭の位置に応じて指数部を更新する
  3473:     //  w[h]が整数部、w[h+1..o-1]が小数部。10^eの小数点はw[h]の右側。整数部の桁数はe+1桁
  3474:     e -= h - 1;
  3475:     //小数点以下len2+1桁目が先頭から14+1桁目よりも左側にあるときその桁で改めて四捨五入する
  3476:     //  あらかじめ14+1桁目で四捨五入しておかないと、
  3477:     //  1.5の5を四捨五入しなければならないときに誤差で1.499…になったまま4を四捨五入しようとして失敗することがある
  3478:     int s = h + e + 1 + len2;  //w[s]は小数点以下len2+1桁目の位置。w.length<=sの場合があることに注意
  3479:     if (s < o) {
  3480:       o = s;  //w[o]は四捨五入する桁の位置。o<0の場合があることに注意
  3481:       if (0 <= o && 5 <= w[o]) {
  3482:         int i = o;
  3483:         while (10 <= ++w[--i]) {
  3484:           w[i] = 0;
  3485:         }
  3486:         if (i < h) {  //先頭から繰り上がった。このとき新しい先頭は1でそれ以外はすべて0
  3487:           h--;  //先頭を左にずらす
  3488:           o--;  //末尾を左にずらす
  3489:           e++;  //指数部を1増やす
  3490:         }
  3491:       }
  3492:     }
  3493:     //文字列に変換する
  3494:     while (h < o) {
  3495:       XEiJ.busWb (a++, '0' + w[h++]);  //有効数字
  3496:     }
  3497:     while (h++ < s) {
  3498:       XEiJ.busWb (a++, '0');  //残りは'0'
  3499:     }
  3500:     XEiJ.busWb (a, '\0');
  3501:     XEiJ.regRn[0] = e + 1;  //小数点の位置
  3502:   }  //fpkFCVTSub0()
  3503: 
  3504:   //fpkGCVT ()
  3505:   //  $FE26  __GCVT
  3506:   //  64bit浮動小数点数を全体の桁数を指定して文字列に変換する
  3507:   //  指定された桁数で表現できないときは指数表現になる
  3508:   //  メモ
  3509:   //    print gcvt(1e-1,10)
  3510:   //    0.1
  3511:   //    print gcvt(1e-8,10)
  3512:   //    0.00000001
  3513:   //    print gcvt(1.5e-8,10)
  3514:   //    1.5E-008
  3515:   //    print gcvt(1e-9,10)
  3516:   //    1.E-009                 小数点はあるが小数部がない
  3517:   //    print gcvt(2e-1/3#,10)
  3518:   //    6.666666667E-002
  3519:   //    print gcvt(2e+0/3#,10)
  3520:   //    0.6666666667
  3521:   //    print gcvt(2e+1/3#,10)
  3522:   //    6.666666667
  3523:   //    print gcvt(2e+9/3#,10)
  3524:   //    666666666.7
  3525:   //    print gcvt(2e+10/3#,10)
  3526:   //    6666666667
  3527:   //    print gcvt(2e+11/3#,10)
  3528:   //    6.666666667E+010
  3529:   //    print gcvt(0#,4)
  3530:   //    0.
  3531:   //    print gcvt(val("#INF"),4)
  3532:   //    #INF
  3533:   //    print gcvt(val("#INF"),3)
  3534:   //    $.E+003
  3535:   //    print gcvt(val("#INF"),2)
  3536:   //    $.E+003
  3537:   //    print gcvt(val("#INF"),1)
  3538:   //    $.E+003
  3539:   //    FLOAT2.XのGCVTは小数部がなくても桁数の範囲内であれば小数点を書く
  3540:   //    桁数ちょうどのときは小数点も指数部も付かないので、整数でないことを明確にするために小数点を書いているとも言い難い
  3541:   //    ここでは#NANと#INF以外は小数部がなくても小数点を書くことにする
  3542:   //  バグ
  3543:   //    FLOAT2.X 2.02/2.03は#NANと#INFにも小数点を付ける
  3544:   //    FLOAT2.X 2.02/2.03は#NANと#INFのとき桁数が足りないと指数形式にしようとして文字列が壊れる
  3545:   //    FLOAT4.X 1.02は#NANと#INFにも小数点を付ける
  3546:   //    FLOAT4.X 1.02は桁数の少ない整数には小数点を付けて桁数ちょうどの整数には小数点も指数部も付けない
  3547:   //  <d0d1.d:64bit浮動小数点数
  3548:   //  <d2.b:全体の桁数
  3549:   //  <a0.l:文字列バッファの先頭
  3550:   //  >a0.l:末尾の'\0'の位置
  3551:   public static void fpkGCVT () throws M68kException {
  3552:     fpkGCVTSub ((long) XEiJ.regRn[0] << 32 | 0xffffffffL & XEiJ.regRn[1]);  //64bit浮動小数点数
  3553:   }  //fpkGCVT()
  3554:   public static void fpkGCVTSub (long l) throws M68kException {
  3555:     int len3 = XEiJ.regRn[2];  //全体の桁数
  3556:     int a = XEiJ.regRn[8];  //文字列バッファの先頭
  3557:     if (len3 <= 0) {  //全体の桁数が0
  3558:       XEiJ.busWb (a, '\0');
  3559:       return;
  3560:     }
  3561:     //符号と指数部の処理
  3562:     //  ±0,±Inf,NaNはここで除外する
  3563:     if (l < 0L) {
  3564:       XEiJ.busWb (a++, '-');  //負符号
  3565:       l &= 0x7fffffffffffffffL;  //符号bitを消しておく
  3566:     }
  3567:     double x = Double.longBitsToDouble (l);  //絶対値
  3568:     int e = (int) (l >>> 52) - 1023;  //指数部。ゲタ0。符号bitは消してあるのでマスクは不要
  3569:     l &= 0x000fffffffffffffL;  //仮数部の小数部。正規化数のとき整数部の1が付いていないことに注意
  3570:     if (e == -1023) {  //±0,非正規化数
  3571:       if (l == 0L) {  //±0
  3572:         XEiJ.busWb (a++, '0');  //0
  3573:         XEiJ.busWb (a++, '.');  //小数点
  3574:         XEiJ.busWb (a, '\0');
  3575:         XEiJ.regRn[8] = a;  //末尾の'\0'の位置
  3576:         return;
  3577:       }
  3578:       e -= Long.numberOfLeadingZeros (l) - 12;  //非正規化数の指数部を補正する
  3579:     } else if (e == 1024) {  //±Inf,NaN
  3580:       XEiJ.busWb (a++, '#');
  3581:       if (l == 0L) {  //±Inf
  3582:         XEiJ.busWb (a++, 'I');
  3583:         XEiJ.busWb (a++, 'N');
  3584:         XEiJ.busWb (a++, 'F');
  3585:       } else {  //NaN
  3586:         XEiJ.busWb (a++, 'N');
  3587:         XEiJ.busWb (a++, 'A');
  3588:         XEiJ.busWb (a++, 'N');
  3589:       }
  3590:       XEiJ.busWb (a, '\0');
  3591:       XEiJ.regRn[8] = a;  //末尾の'\0'の位置
  3592:       return;
  3593:     }
  3594:     //10進数で表現したときの指数部を求める
  3595:     //  10^e<=x<10^(e+1)となるeを求める
  3596:     e = (int) Math.floor ((double) e * 0.30102999566398119521373889472);  //log10(2)
  3597:     //10^-eを掛けて1<=x<10にする
  3598:     //  非正規化数の最小値から正規化数の最大値まで処理できなければならない
  3599:     //  10^-eを計算してからまとめて掛ける方法はxが非正規化数のとき10^-eがオーバーフローしてしまうので不可
  3600:     //    doubleは非正規化数の逆数を表現できない
  3601:     if (0 < e) {  //10<=x
  3602:       x *= FPK_TEN_M16QR[e & 15];
  3603:       if (16 <= e) {
  3604:         x *= FPK_TEN_M16QR[16 + (e >> 4 & 15)];
  3605:         if (256 <= e) {
  3606:           x *= FPK_TEN_M16QR[33];  //FPK_TEN_M16QR[32 + (e >> 8)]
  3607:         }
  3608:       }
  3609:     } else if (e < 0) {  //x<1
  3610:       x *= FPK_TEN_P16QR[-e & 15];
  3611:       if (e <= -16) {
  3612:         x *= FPK_TEN_P16QR[16 + (-e >> 4 & 15)];
  3613:         if (e <= -256) {
  3614:           x *= FPK_TEN_P16QR[33];  //FPK_TEN_P16QR[32 + (-e >> 8)]
  3615:         }
  3616:       }
  3617:     }
  3618:     //整数部2桁、小数部16桁の10進数に変換する
  3619:     //  1<=x<10なのでw[1]が先頭になるはずだが誤差で前後にずれる可能性がある
  3620:     int[] w = new int[18];
  3621:     {
  3622:       int d = (int) x;
  3623:       int t = XEiJ.FMT_BCD4[d];
  3624:       w[0] = t >> 4;
  3625:       w[1] = t      & 15;
  3626:       for (int i = 2; i < 18; i += 4) {
  3627:         //xを10000倍して整数部dを引くことで小数部を残すが、このとき情報落ちが発生して誤差が蓄積する
  3628:         //Double-Doubleの乗算の要領で10000倍を正確に行い、誤差の蓄積を回避する
  3629:         //x = (x - (double) d) * 10000.0;
  3630:         double xh = x * 0x8000001p0;
  3631:         xh += x - xh;  //xの上半分
  3632:         x = (xh - (double) d) * 10000.0 + (x - xh) * 10000.0;
  3633:         d = (int) x;
  3634:         t = XEiJ.FMT_BCD4[d];
  3635:         w[i    ] = t >> 12;
  3636:         w[i + 1] = t >>  8 & 15;
  3637:         w[i + 2] = t >>  4 & 15;
  3638:         w[i + 3] = t       & 15;
  3639:       }
  3640:     }
  3641:     //先頭の位置を確認する
  3642:     //  w[h]が先頭(0でない最初の数字)の位置
  3643:     int h = w[0] != 0 ? 0 : w[1] != 0 ? 1 : 2;
  3644:     //14+1桁目を四捨五入する
  3645:     int o = h + 14;  //w[o]は四捨五入する桁の位置。w[]の範囲内
  3646:     if (5 <= w[o]) {
  3647:       int i = o;
  3648:       while (10 <= ++w[--i]) {
  3649:         w[i] = 0;
  3650:       }
  3651:       if (i < h) {  //先頭から繰り上がった。このとき新しい先頭は1でそれ以外はすべて0
  3652:         h--;  //先頭を左にずらす
  3653:         o--;  //末尾を左にずらす
  3654:       }
  3655:     }
  3656:     //先頭の位置に応じて指数部を更新する
  3657:     //  w[h]が整数部、w[h+1..o-1]が小数部。10^eの小数点はw[h]の右側。整数部の桁数はe+1桁
  3658:     e -= h - 1;
  3659:     //先頭からlen3+1桁目が先頭から14+1桁目よりも左側にあるときその桁で改めて四捨五入する
  3660:     //  あらかじめ14+1桁目で四捨五入しておかないと、
  3661:     //  1.5の5を四捨五入しなければならないときに誤差で1.499…になったまま4を四捨五入しようとして失敗することがある
  3662:     int s = h + len3;  //w[s]は先頭からlen3+1桁目の位置。w.length<=sの場合があることに注意
  3663:     if (s < o) {
  3664:       o = s;  //w[o]は四捨五入する桁の位置。o<0の場合があることに注意
  3665:       if (0 <= o && 5 <= w[o]) {
  3666:         int i = o;
  3667:         while (10 <= ++w[--i]) {
  3668:           w[i] = 0;
  3669:         }
  3670:         if (i < h) {  //先頭から繰り上がった。このとき新しい先頭は1でそれ以外はすべて0
  3671:           h--;  //先頭を左にずらす
  3672:           o--;  //末尾を左にずらす
  3673:           e++;  //指数部を1増やす
  3674:         }
  3675:       }
  3676:     }
  3677:     //末尾の位置を確認する
  3678:     //  w[o-1]が末尾(0でない最後の数字)の位置
  3679:     while (w[o - 1] == 0) {  //全体は0ではないので必ず止まる。小数点よりも左側で止まる場合があることに注意
  3680:       o--;
  3681:     }
  3682:     //指数形式にするかどうか選択して文字列に変換する
  3683:     if (0 <= e && e < len3) {  //1<=x<10^len3。指数形式にしない
  3684:       for (; 0 <= e && h < o; e--) {
  3685:         XEiJ.busWb (a++, '0' + w[h++]);  //整数部
  3686:       }
  3687:       for (; 0 <= e; e--) {
  3688:         XEiJ.busWb (a++, '0');  //整数部。末尾の位置に関係なく1の位まで書く
  3689:       }
  3690:       XEiJ.busWb (a++, '.');  //小数部がなくても小数点を書く
  3691:       while (h < o) {
  3692:         XEiJ.busWb (a++, '0' + w[h++]);  //小数部
  3693:       }
  3694:     } else if (-4 <= e && e < 0) {  //10^-4<=x<1。指数形式にしない
  3695:       XEiJ.busWb (a++, '0');  //整数部の0
  3696:       XEiJ.busWb (a++, '.');  //小数点
  3697:       while (++e < 0) {
  3698:         XEiJ.busWb (a++, '0');  //小数部の先頭の0の並び
  3699:       }
  3700:       while (h < o) {
  3701:         XEiJ.busWb (a++, '0' + w[h++]);  //小数部
  3702:       }
  3703:     } else {  //x<10^-4または10^len3<=x。指数形式にする
  3704:       XEiJ.busWb (a++, '0' + w[h++]);  //整数部
  3705:       XEiJ.busWb (a++, '.');  //小数部がなくても小数点を書く
  3706:       while (h < o) {
  3707:         XEiJ.busWb (a++, '0' + w[h++]);  //小数部
  3708:       }
  3709:       XEiJ.busWb (a++, 'E');  //指数部の始まり
  3710:       if (0 <= e) {
  3711:         XEiJ.busWb (a++, '+');  //指数部の正符号。省略しない
  3712:       } else {
  3713:         XEiJ.busWb (a++, '-');  //指数部の負符号
  3714:         e = -e;
  3715:       }
  3716:       e = XEiJ.FMT_BCD4[e];
  3717:       XEiJ.busWb (a++, '0' + (e >> 8     ));  //指数部の100の位。0でも省略しない
  3718:       XEiJ.busWb (a++, '0' + (e >> 4 & 15));  //指数部の10の位
  3719:       XEiJ.busWb (a++, '0' + (e      & 15));  //指数部の1の位
  3720:     }
  3721:     XEiJ.busWb (a, '\0');
  3722:     XEiJ.regRn[8] = a;  //末尾の'\0'の位置
  3723:   }  //fpkGCVTSub0()
  3724: 
  3725:   //fpkFVAL ()
  3726:   //  $FE50  __FVAL
  3727:   //  文字列を32bit浮動小数点数に変換する
  3728:   //  __VALとほぼ同じ
  3729:   //  <a0.l:文字列の先頭
  3730:   //  >d0.s:32bit浮動小数点数
  3731:   //  >d2.l:(先頭が'&'でないとき)65535=32bit浮動小数点数をオーバーフローなしでintに変換できる,0=それ以外
  3732:   //  >d3.l:(先頭が'&'でないとき)d2.l==65535のとき32bit浮動小数点数をintに変換した値
  3733:   //  >a0.l:変換された文字列の直後('\0'とは限らない)
  3734:   //  >ccr:0=エラーなし,N|C=文法エラー,V|C=オーバーフロー
  3735:   public static void fpkFVAL () throws M68kException {
  3736:     int a = XEiJ.regRn[8];  //a0
  3737:     //先頭の空白を読み飛ばす
  3738:     int c = XEiJ.busRbs (a++);
  3739:     while (c == ' ' || c == '\t') {
  3740:       c = XEiJ.busRbs (a++);
  3741:     }
  3742:     if (c == '&') {  //&B,&O,&H
  3743:       c = XEiJ.busRbs (a++) & 0xdf;
  3744:       XEiJ.regRn[8] = a;  //&?の直後
  3745:       if (c == 'B') {
  3746:         fpkSTOB ();
  3747:         fpkLTOF ();
  3748:       } else if (c == 'O') {
  3749:         fpkSTOO ();
  3750:         fpkLTOF ();
  3751:       } else if (c == 'H') {
  3752:         fpkSTOH ();
  3753:         fpkLTOF ();
  3754:       } else {
  3755:         XEiJ.regCCR = XEiJ.REG_CCR_N | XEiJ.REG_CCR_C;  //文法エラー
  3756:       }
  3757:     } else {  //&B,&O,&H以外
  3758:       fpkSTOF ();
  3759:     }
  3760:   }  //fpkFVAL()
  3761: 
  3762:   //fpkFUSING ()
  3763:   //  $FE51  __FUSING
  3764:   //  32bit浮動小数点数をアトリビュートを指定して文字列に変換する
  3765:   //  __USINGとほぼ同じ
  3766:   //  <d0.s:32bit浮動小数点数
  3767:   //  <d2.l:整数部の桁数
  3768:   //  <d3.l:小数部の桁数
  3769:   //  <d4.l:アトリビュート
  3770:   //    bit0  左側を'*'で埋める
  3771:   //    bit1  先頭に'\\'を付ける
  3772:   //    bit2  整数部を3桁毎に','で区切る
  3773:   //    bit3  指数形式
  3774:   //    bit4  先頭に符号('+'または'-')を付ける
  3775:   //    bit5  末尾に符号('+'または'-')を付ける
  3776:   //    bit6  末尾に符号(' 'または'-')を付ける
  3777:   //  <a0.l:文字列バッファの先頭
  3778:   //  a0は変化しない
  3779:   public static void fpkFUSING () throws M68kException {
  3780:     fpkUSINGSub (Double.doubleToLongBits ((double) Float.intBitsToFloat (XEiJ.regRn[0])));  //32bit浮動小数点数
  3781:   }  //fpkFUSING()
  3782: 
  3783:   //fpkSTOF ()
  3784:   //  $FE52  __STOF
  3785:   //  文字列を32bit浮動小数点数に変換する
  3786:   //  __STODとほぼ同じ
  3787:   //  <a0.l:文字列の先頭
  3788:   //  >d0.s:32bit浮動小数点数
  3789:   //  >d2.l:65535=32bit浮動小数点数をオーバーフローなしでintに変換できる,0=それ以外
  3790:   //  >d3.l:d2.l==65535のとき32bit浮動小数点数をintに変換した値
  3791:   //  >a0.l:変換された文字列の直後('\0'とは限らない)
  3792:   //  >ccr:0=エラーなし,N|C=文法エラー,V|C=オーバーフロー
  3793:   public static void fpkSTOF () throws M68kException {
  3794:     int h = Float.floatToIntBits ((float) fpkSTODSub ());  //d0
  3795:     if (FPK_FPCP_NAN && h == 0x7fc00000) {
  3796:       h = 0x7fffffff;
  3797:     }
  3798:     XEiJ.regRn[0] = h;
  3799:   }  //fpkSTOF()
  3800: 
  3801:   //fpkFTOS ()
  3802:   //  $FE53  __FTOS
  3803:   //  32bit浮動小数点数を文字列に変換する
  3804:   //  __DTOSとほぼ同じ
  3805:   //  <d0.s:32bit浮動小数点数
  3806:   //  <a0.l:文字列バッファの先頭
  3807:   //  >a0.l:末尾の'\0'の位置
  3808:   public static void fpkFTOS () throws M68kException {
  3809:     fpkDTOSSub (Double.doubleToLongBits ((double) Float.intBitsToFloat (XEiJ.regRn[0])));  //32bit浮動小数点数
  3810:   }  //fpkFTOS()
  3811: 
  3812:   //fpkFECVT ()
  3813:   //  $FE54  __FECVT
  3814:   //  32bit浮動小数点数を全体の桁数を指定して文字列に変換する
  3815:   //  __ECVTとほぼ同じ
  3816:   //  <d0.s:32bit浮動小数点数
  3817:   //  <d2.b:全体の桁数
  3818:   //  <a0.l:文字列バッファの先頭。末尾に'\0'を書き込むので桁数+1バイト必要
  3819:   //  >d0.l:先頭から小数点の位置までのオフセット
  3820:   //  >d1.l:符号(0=+,1=-)
  3821:   //  a0.lは変化しない
  3822:   public static void fpkFECVT () throws M68kException {
  3823:     fpkECVTSub (Double.doubleToLongBits ((double) Float.intBitsToFloat (XEiJ.regRn[0])));  //32bit浮動小数点数
  3824:   }  //fpkFECVT()
  3825: 
  3826:   //fpkFFCVT ()
  3827:   //  $FE55  __FFCVT
  3828:   //  32bit浮動小数点数を小数点以下の桁数を指定して文字列に変換する
  3829:   //  __FCVTとほぼ同じ
  3830:   //  <d0.s:32bit浮動小数点数
  3831:   //  <d2.b:小数点以下の桁数
  3832:   //  <a0.l:文字列バッファの先頭
  3833:   //  >d0.l:先頭から小数点の位置までのオフセット
  3834:   //  >d1.l:符号(0=+,1=-)
  3835:   public static void fpkFFCVT () throws M68kException {
  3836:     fpkFCVTSub (Double.doubleToLongBits ((double) Float.intBitsToFloat (XEiJ.regRn[0])));  //32bit浮動小数点数
  3837:   }  //fpkFFCVT()
  3838: 
  3839:   //fpkFGCVT ()
  3840:   //  $FE56  __FGCVT
  3841:   //  32bit浮動小数点数を全体の桁数を指定して文字列に変換する
  3842:   //  __GCVTとほぼ同じ
  3843:   //  <d0.s:32bit浮動小数点数
  3844:   //  <d2.b:全体の桁数
  3845:   //  <a0.l:文字列バッファの先頭
  3846:   //  >a0.l:末尾の'\0'の位置
  3847:   public static void fpkFGCVT () throws M68kException {
  3848:     fpkGCVTSub (Double.doubleToLongBits ((double) Float.intBitsToFloat (XEiJ.regRn[0])));  //32bit浮動小数点数
  3849:   }  //fpkFGCVT()
  3850: 
  3851:   //fpkCLMUL ()
  3852:   //  $FEE0  __CLMUL
  3853:   //  32bit符号あり整数乗算
  3854:   //  <(a7).l:32bit符号あり整数。被乗数x
  3855:   //  <4(a7).l:32bit符号あり整数。乗数y
  3856:   //  >(a7).l:32bit符号あり整数。積x*y。オーバーフローのときは不定
  3857:   //  >ccr:cs=オーバーフロー。C以外は不定
  3858:   public static void fpkCLMUL () throws M68kException {
  3859:     int a7 = XEiJ.regRn[15];
  3860:     long l = (long) XEiJ.busRls (a7) * (long) XEiJ.busRls (a7 + 4);
  3861:     int h = (int) l;
  3862:     XEiJ.busWl (a7, h);  //オーバーフローのときは積の下位32bit
  3863:     XEiJ.regCCR = (long) h == l ? 0 : XEiJ.REG_CCR_C;
  3864:   }  //fpkCLMUL()
  3865: 
  3866:   //fpkCLDIV ()
  3867:   //  $FEE1  __CLDIV
  3868:   //  32bit符号あり整数除算
  3869:   //  <(a7).l:32bit符号あり整数。被除数x
  3870:   //  <4(a7).l:32bit符号あり整数。除数y
  3871:   //  >(a7).l:32bit符号あり整数。商x/y。ゼロ除算のときは不定
  3872:   //  >ccr:cs=ゼロ除算。C以外は不定
  3873:   public static void fpkCLDIV () throws M68kException {
  3874:     int a7 = XEiJ.regRn[15];
  3875:     int h = XEiJ.busRls (a7 + 4);
  3876:     if (h == 0) {
  3877:       //(a7).lは変化しない
  3878:       XEiJ.regCCR = XEiJ.REG_CCR_C;
  3879:     } else {
  3880:       XEiJ.busWl (a7, XEiJ.busRls (a7) / h);
  3881:       XEiJ.regCCR = 0;
  3882:     }
  3883:   }  //fpkCLDIV()
  3884: 
  3885:   //fpkCLMOD ()
  3886:   //  $FEE2  __CLMOD
  3887:   //  32bit符号あり整数剰余算
  3888:   //  <(a7).l:32bit符号あり整数。被除数x
  3889:   //  <4(a7).l:32bit符号あり整数。除数y
  3890:   //  >(a7).l:32bit符号あり整数。余りx%y。ゼロ除算のときは不定
  3891:   //  >ccr:cs=ゼロ除算。C以外は不定
  3892:   public static void fpkCLMOD () throws M68kException {
  3893:     int a7 = XEiJ.regRn[15];
  3894:     int h = XEiJ.busRls (a7 + 4);
  3895:     if (h == 0) {
  3896:       //(a7).lは変化しない
  3897:       XEiJ.regCCR = XEiJ.REG_CCR_C;
  3898:     } else {
  3899:       XEiJ.busWl (a7, XEiJ.busRls (a7) % h);
  3900:       XEiJ.regCCR = 0;
  3901:     }
  3902:   }  //fpkCLMOD()
  3903: 
  3904:   //fpkCUMUL ()
  3905:   //  $FEE3  __CUMUL
  3906:   //  32bit符号なし整数乗算
  3907:   //  <(a7).l:32bit符号なし整数。被乗数x
  3908:   //  <4(a7).l:32bit符号なし整数。乗数y
  3909:   //  >(a7).l:32bit符号なし整数。積x*y。オーバーフローのときは不定
  3910:   //  >ccr:cs=オーバーフロー。C以外は不定
  3911:   public static void fpkCUMUL () throws M68kException {
  3912:     int a7 = XEiJ.regRn[15];
  3913:     long l = (0xffffffffL & XEiJ.busRls (a7)) * (0xffffffffL & XEiJ.busRls (a7 + 4));
  3914:     int h = (int) l;
  3915:     XEiJ.busWl (a7, h);
  3916:     XEiJ.regCCR = (0xffffffffL & h) == l ? 0 : XEiJ.REG_CCR_C;
  3917:   }  //fpkCUMUL()
  3918: 
  3919:   //fpkCUDIV ()
  3920:   //  $FEE4  __CUDIV
  3921:   //  32bit符号なし整数除算
  3922:   //  <(a7).l:32bit符号なし整数。被除数x
  3923:   //  <4(a7).l:32bit符号なし整数。除数y
  3924:   //  >(a7).l:32bit符号なし整数。商x/y。ゼロ除算のときは不定
  3925:   //  >ccr:cs=ゼロ除算。C以外は不定
  3926:   public static void fpkCUDIV () throws M68kException {
  3927:     int a7 = XEiJ.regRn[15];
  3928:     int h = XEiJ.busRls (a7 + 4);
  3929:     if (h == 0) {
  3930:       //(a7).lは変化しない
  3931:       XEiJ.regCCR = XEiJ.REG_CCR_C;
  3932:     } else {
  3933:       XEiJ.busWl (a7, (int) ((0xffffffffL & XEiJ.busRls (a7)) / (0xffffffffL & h)));
  3934:       XEiJ.regCCR = 0;
  3935:     }
  3936:   }  //fpkCUDIV()
  3937: 
  3938:   //fpkCUMOD ()
  3939:   //  $FEE5  __CUMOD
  3940:   //  32bit符号なし整数剰余算
  3941:   //  <(a7).l:32bit符号なし整数。被除数x
  3942:   //  <4(a7).l:32bit符号なし整数。除数y
  3943:   //  >(a7).l:32bit符号なし整数。余りx%y。ゼロ除算のときは不定
  3944:   //  >ccr:cs=ゼロ除算。C以外は不定
  3945:   public static void fpkCUMOD () throws M68kException {
  3946:     int a7 = XEiJ.regRn[15];
  3947:     int h = XEiJ.busRls (a7 + 4);
  3948:     if (h == 0) {
  3949:       //(a7).lは変化しない
  3950:       XEiJ.regCCR = XEiJ.REG_CCR_C;
  3951:     } else {
  3952:       XEiJ.busWl (a7, (int) ((0xffffffffL & XEiJ.busRls (a7)) % (0xffffffffL & h)));
  3953:       XEiJ.regCCR = 0;
  3954:     }
  3955:   }  //fpkCUMOD()
  3956: 
  3957:   //fpkCLTOD ()
  3958:   //  $FEE6  __CLTOD
  3959:   //  32bit符号あり整数を64bit浮動小数点数に変換する
  3960:   //  <(a7).l:32bit符号あり整数。x
  3961:   //  >(a7).d:64bit浮動小数点数。(double)x
  3962:   public static void fpkCLTOD () throws M68kException {
  3963:     //int→double→[long]→[int,int]
  3964:     int a7 = XEiJ.regRn[15];
  3965:     long l = Double.doubleToLongBits ((double) XEiJ.busRls (a7));
  3966:     XEiJ.busWl (a7, (int) (l >>> 32));
  3967:     XEiJ.busWl (a7 + 4, (int) l);
  3968:   }  //fpkCLTOD()
  3969: 
  3970:   //fpkCDTOL ()
  3971:   //  $FEE7  __CDTOL
  3972:   //  64bit浮動小数点数を32bit符号あり整数に変換する
  3973:   //  <(a7).d:64bit浮動小数点数。x
  3974:   //  >(a7).l:32bit符号あり整数。(int)x
  3975:   //  >ccr:cs=オーバーフロー。C以外は不定
  3976:   public static void fpkCDTOL () throws M68kException {
  3977:     //[int,int]→[long]→double→int
  3978:     int a7 = XEiJ.regRn[15];
  3979:     double d = Double.longBitsToDouble ((long) XEiJ.busRls (a7) << 32 | 0xffffffffL & XEiJ.busRls (a7 + 4));
  3980:     XEiJ.busWl (a7, (int) d);  //オーバーフローのときは最小値または最大値
  3981:     XEiJ.regCCR = (double) Integer.MIN_VALUE - 1.0 < d && d < (double) Integer.MAX_VALUE + 1.0 ? 0 : XEiJ.REG_CCR_C;  //NaN,±Infはエラー
  3982:   }  //fpkCDTOL()
  3983: 
  3984:   //fpkCLTOF ()
  3985:   //  $FEE8  __CLTOF
  3986:   //  32bit符号あり整数を32bit浮動小数点数に変換する
  3987:   //  <(a7).l:32bit符号あり整数。x
  3988:   //  >(a7).s:32bit浮動小数点数。(float)x
  3989:   public static void fpkCLTOF () throws M68kException {
  3990:     //int→float→[int]
  3991:     int a7 = XEiJ.regRn[15];
  3992:     XEiJ.busWl (a7, Float.floatToIntBits ((float) XEiJ.busRls (a7)));
  3993:   }  //fpkCLTOF()
  3994: 
  3995:   //fpkCFTOL ()
  3996:   //  $FEE9  __CFTOL
  3997:   //  32bit浮動小数点数を32bit符号あり整数に変換する
  3998:   //  <(a7).s:32bit浮動小数点数。x
  3999:   //  >(a7).l:32bit符号あり整数。(int)x
  4000:   //  >ccr:cs=オーバーフロー。C以外は不定
  4001:   public static void fpkCFTOL () throws M68kException {
  4002:     //[int]→float→int
  4003:     int a7 = XEiJ.regRn[15];
  4004:     float f = Float.intBitsToFloat (XEiJ.busRls (a7));
  4005:     XEiJ.busWl (a7, (int) f);
  4006:     XEiJ.regCCR = (float) Integer.MIN_VALUE - 1.0F < f && f < (float) Integer.MAX_VALUE + 1.0F ? 0 : XEiJ.REG_CCR_C;  //NaN,±Infはエラー
  4007:   }  //fpkCFTOL()
  4008: 
  4009:   //fpkCFTOD ()
  4010:   //  $FEEA  __CFTOD
  4011:   //  32bit浮動小数点数を64bit浮動小数点数に変換する
  4012:   //  <(a7).s:32bit浮動小数点数。x
  4013:   //  >(a7).d:64bit浮動小数点数。(double)x
  4014:   public static void fpkCFTOD () throws M68kException {
  4015:     //[int]→float→double→[long]→[int,int]
  4016:     int a7 = XEiJ.regRn[15];
  4017:     long l = Double.doubleToLongBits ((double) Float.intBitsToFloat (XEiJ.busRls (a7)));
  4018:     if (FPK_FPCP_NAN && l == 0x7ff8000000000000L) {
  4019:       l = 0x7fffffffffffffffL;
  4020:     }
  4021:     XEiJ.busWl (a7, (int) (l >>> 32));
  4022:     XEiJ.busWl (a7 + 4, (int) l);
  4023:   }  //fpkCFTOD()
  4024: 
  4025:   //fpkCDTOF ()
  4026:   //  $FEEB  __CDTOF
  4027:   //  64bit浮動小数点数を32bit浮動小数点数に変換する
  4028:   //  <(a7).d:64bit浮動小数点数。x
  4029:   //  >(a7).s:32bit浮動小数点数。(float)x
  4030:   //  >ccr:cs=オーバーフロー。C以外は不定
  4031:   public static void fpkCDTOF () throws M68kException {
  4032:     //[int,int]→[long]→double→float→[int]
  4033:     int a7 = XEiJ.regRn[15];
  4034:     double d = Double.longBitsToDouble ((long) XEiJ.busRls (a7) << 32 | 0xffffffffL & XEiJ.busRls (a7 + 4));
  4035:     int h = Float.floatToIntBits ((float) d);
  4036:     if (FPK_FPCP_NAN && h == 0x7fc00000) {
  4037:       h = 0x7fffffff;
  4038:     }
  4039:     XEiJ.busWl (a7, h);
  4040:     XEiJ.regCCR = (Double.isNaN (d) || Double.isInfinite (d) ||
  4041:            Math.abs (d) < (double) Float.MAX_VALUE + 0.5 * (double) Math.ulp (Float.MAX_VALUE) ? 0 : XEiJ.REG_CCR_C);  //アンダーフローはエラーなし
  4042:   }  //fpkCDTOF()
  4043: 
  4044:   //fpkCDCMP ()
  4045:   //  $FEEC  __CDCMP
  4046:   //  64bit浮動小数点数の比較
  4047:   //  x<=>y
  4048:   //  <(a7).d:64bit浮動小数点数。x
  4049:   //  <8(a7).d:64bit浮動小数点数。y
  4050:   //  >ccr:lt=x<y,eq=x==y,gt=x>y
  4051:   public static void fpkCDCMP () throws M68kException {
  4052:     //([int,int]→[long]→double)<=>([int,int]→[long]→double)
  4053:     int a7 = XEiJ.regRn[15];
  4054:     double xd = Double.longBitsToDouble ((long) XEiJ.busRls (a7) << 32 | 0xffffffffL & XEiJ.busRls (a7 + 4));
  4055:     double yd = Double.longBitsToDouble ((long) XEiJ.busRls (a7 + 8) << 32 | 0xffffffffL & XEiJ.busRls (a7 + 12));
  4056:     XEiJ.regCCR = xd < yd ? XEiJ.REG_CCR_N | XEiJ.REG_CCR_C : xd == yd ? XEiJ.REG_CCR_Z : 0;  //どちらかがNaNのときは0
  4057:   }  //fpkCDCMP()
  4058: 
  4059:   //fpkCDADD ()
  4060:   //  $FEED  __CDADD
  4061:   //  64bit浮動小数点数の加算
  4062:   //  <(a7).d:64bit浮動小数点数。被加算数x
  4063:   //  <8(a7).d:64bit浮動小数点数。加算数y
  4064:   //  >(a7).d:64bit浮動小数点数。和x+y
  4065:   //  >ccr:0=エラーなし,C=アンダーフロー,V|C=オーバーフロー
  4066:   public static void fpkCDADD () throws M68kException {
  4067:     //([int,int]→[long]→double)+([int,int]→[long]→double)→[long]→[int,int]
  4068:     int a7 = XEiJ.regRn[15];
  4069:     double xd = Double.longBitsToDouble ((long) XEiJ.busRls (a7) << 32 | 0xffffffffL & XEiJ.busRls (a7 + 4));
  4070:     double yd = Double.longBitsToDouble ((long) XEiJ.busRls (a7 + 8) << 32 | 0xffffffffL & XEiJ.busRls (a7 + 12));
  4071:     double zd = xd + yd;
  4072:     long l = Double.doubleToLongBits (zd);
  4073:     if (FPK_FPCP_NAN && l == 0x7ff8000000000000L) {
  4074:       l = 0x7fffffffffffffffL;
  4075:     }
  4076:     XEiJ.busWl (a7, (int) (l >>> 32));
  4077:     XEiJ.busWl (a7 + 4, (int) l);
  4078:     XEiJ.regCCR = (Double.isNaN (xd) || Double.isNaN (yd) ? 0 :  //引数がNaN
  4079:            Double.isNaN (zd) ? XEiJ.REG_CCR_C :  //引数がNaNでないのに結果がNaNのときはエラー。(+Inf)+(-Inf)=NaN
  4080:            Double.isInfinite (xd) || Double.isInfinite (yd) ? 0 :  //引数が±Inf
  4081:            Double.isInfinite (zd) ? XEiJ.REG_CCR_V | XEiJ.REG_CCR_C :  //引数が±Infでないのに結果が±Infのときはオーバーフロー
  4082:            0);
  4083:   }  //fpkCDADD()
  4084: 
  4085:   //fpkCDSUB ()
  4086:   //  $FEEE  __CDSUB
  4087:   //  64bit浮動小数点数の減算
  4088:   //  <(a7).d:64bit浮動小数点数。被減算数x
  4089:   //  <8(a7).d:64bit浮動小数点数。減算数y
  4090:   //  >(a7).d:64bit浮動小数点数。差x-y
  4091:   //  >ccr:cs=エラー,vs=オーバーフロー
  4092:   public static void fpkCDSUB () throws M68kException {
  4093:     //([int,int]→[long]→double)-([int,int]→[long]→double)→[long]→[int,int]
  4094:     int a7 = XEiJ.regRn[15];
  4095:     double xd = Double.longBitsToDouble ((long) XEiJ.busRls (a7) << 32 | 0xffffffffL & XEiJ.busRls (a7 + 4));
  4096:     double yd = Double.longBitsToDouble ((long) XEiJ.busRls (a7 + 8) << 32 | 0xffffffffL & XEiJ.busRls (a7 + 12));
  4097:     double zd = xd - yd;
  4098:     long l = Double.doubleToLongBits (zd);
  4099:     if (FPK_FPCP_NAN && l == 0x7ff8000000000000L) {
  4100:       l = 0x7fffffffffffffffL;
  4101:     }
  4102:     XEiJ.busWl (a7, (int) (l >>> 32));
  4103:     XEiJ.busWl (a7 + 4, (int) l);
  4104:     XEiJ.regCCR = (Double.isNaN (xd) || Double.isNaN (yd) ? 0 :  //引数がNaN
  4105:            Double.isNaN (zd) ? XEiJ.REG_CCR_C :  //引数がNaNでないのに結果がNaNのときはエラー。(+Inf)-(+Inf)=NaN
  4106:            Double.isInfinite (xd) || Double.isInfinite (yd) ? 0 :  //引数が±Inf
  4107:            Double.isInfinite (zd) ? XEiJ.REG_CCR_V | XEiJ.REG_CCR_C :  //引数が±Infでないのに結果が±Infのときはオーバーフロー
  4108:            0);
  4109:   }  //fpkCDSUB()
  4110: 
  4111:   //fpkCDMUL ()
  4112:   //  $FEEF  __CDMUL
  4113:   //  64bit浮動小数点数の乗算
  4114:   //  <(a7).d:64bit浮動小数点数。被乗数x
  4115:   //  <8(a7).d:64bit浮動小数点数。乗数y
  4116:   //  >(a7).d:64bit浮動小数点数。積x*y
  4117:   //  >ccr:cs=エラー,vs=オーバーフロー
  4118:   public static void fpkCDMUL () throws M68kException {
  4119:     //([int,int]→[long]→double)*([int,int]→[long]→double)→[long]→[int,int]
  4120:     int a7 = XEiJ.regRn[15];
  4121:     double xd = Double.longBitsToDouble ((long) XEiJ.busRls (a7) << 32 | 0xffffffffL & XEiJ.busRls (a7 + 4));
  4122:     double yd = Double.longBitsToDouble ((long) XEiJ.busRls (a7 + 8) << 32 | 0xffffffffL & XEiJ.busRls (a7 + 12));
  4123:     double zd = xd * yd;
  4124:     long l = Double.doubleToLongBits (zd);
  4125:     if (FPK_FPCP_NAN && l == 0x7ff8000000000000L) {
  4126:       l = 0x7fffffffffffffffL;
  4127:     }
  4128:     XEiJ.busWl (a7, (int) (l >>> 32));
  4129:     XEiJ.busWl (a7 + 4, (int) l);
  4130:     XEiJ.regCCR = (Double.isNaN (xd) || Double.isNaN (yd) ? 0 :  //引数がNaN
  4131:            Double.isNaN (zd) ? XEiJ.REG_CCR_C :  //引数がNaNでないのに結果がNaNのときはエラー。(±0)*(±Inf)=NaN
  4132:            Double.isInfinite (xd) || Double.isInfinite (yd) ? 0 :  //引数が±Inf
  4133:            Double.isInfinite (zd) ? XEiJ.REG_CCR_V | XEiJ.REG_CCR_C :  //引数が±Infでないのに結果が±Infのときはオーバーフロー
  4134:            0);
  4135:   }  //fpkCDMUL()
  4136: 
  4137:   //fpkCDDIV ()
  4138:   //  $FEF0  __CDDIV
  4139:   //  64bit浮動小数点数の除算
  4140:   //  <(a7).d:64bit浮動小数点数。被除数x
  4141:   //  <8(a7).d:64bit浮動小数点数。除数y
  4142:   //  >(a7).d:64bit浮動小数点数。商x/y。ゼロ除算のときは不定
  4143:   //  >ccr:cs=エラー,eq=ゼロ除算,vs=オーバーフロー
  4144:   public static void fpkCDDIV () throws M68kException {
  4145:     //([int,int]→[long]→double)/([int,int]→[long]→double)→[long]→[int,int]
  4146:     int a7 = XEiJ.regRn[15];
  4147:     double xd = Double.longBitsToDouble ((long) XEiJ.busRls (a7) << 32 | 0xffffffffL & XEiJ.busRls (a7 + 4));
  4148:     double yd = Double.longBitsToDouble ((long) XEiJ.busRls (a7 + 8) << 32 | 0xffffffffL & XEiJ.busRls (a7 + 12));
  4149:     double zd = xd / yd;
  4150:     long l = Double.doubleToLongBits (zd);
  4151:     if (FPK_FPCP_NAN && l == 0x7ff8000000000000L) {
  4152:       l = 0x7fffffffffffffffL;
  4153:     }
  4154:     XEiJ.busWl (a7, (int) (l >>> 32));
  4155:     XEiJ.busWl (a7 + 4, (int) l);
  4156:     XEiJ.regCCR = (Double.isNaN (xd) || Double.isNaN (yd) ? 0 :  //引数がNaN
  4157:            Double.isNaN (zd) ? XEiJ.REG_CCR_C :  //引数がNaNでないのに結果がNaNのときはエラー。(±0)/(±0)=NaN
  4158:            Double.isInfinite (xd) || Double.isInfinite (yd) ? 0 :  //引数が±Inf。(±Inf)/(±0)=(±Inf)
  4159:            yd == 0.0 ? XEiJ.REG_CCR_Z | XEiJ.REG_CCR_C :  //除数が±0のときはゼロ除算
  4160:            Double.isInfinite (zd) ? XEiJ.REG_CCR_V | XEiJ.REG_CCR_C :  //引数が±Infでないのに結果が±Infのときはオーバーフロー
  4161:            0);
  4162:   }  //fpkCDDIV()
  4163: 
  4164:   //fpkCDMOD ()
  4165:   //  $FEF1  __CDMOD
  4166:   //  64bit浮動小数点数の剰余算
  4167:   //  <(a7).d:64bit浮動小数点数。被除数x
  4168:   //  <8(a7).d:64bit浮動小数点数。除数y
  4169:   //  >(a7).d:64bit浮動小数点数。余りx%y。ゼロ除算のときは不定
  4170:   //  >ccr:cs=エラー,eq=ゼロ除算
  4171:   public static void fpkCDMOD () throws M68kException {
  4172:     //([int,int]→[long]→double)%([int,int]→[long]→double)→[long]→[int,int]
  4173:     int a7 = XEiJ.regRn[15];
  4174:     double xd = Double.longBitsToDouble ((long) XEiJ.busRls (a7) << 32 | 0xffffffffL & XEiJ.busRls (a7 + 4));
  4175:     double yd = Double.longBitsToDouble ((long) XEiJ.busRls (a7 + 8) << 32 | 0xffffffffL & XEiJ.busRls (a7 + 12));
  4176:     double zd = xd % yd;
  4177:     long l = Double.doubleToLongBits (zd);
  4178:     if (FPK_FPCP_NAN && l == 0x7ff8000000000000L) {
  4179:       l = 0x7fffffffffffffffL;
  4180:     }
  4181:     XEiJ.busWl (a7, (int) (l >>> 32));
  4182:     XEiJ.busWl (a7 + 4, (int) l);
  4183:     XEiJ.regCCR = (Double.isNaN (xd) || Double.isNaN (yd) ? 0 :  //引数がNaN
  4184:            yd == 0.0 ? XEiJ.REG_CCR_Z | XEiJ.REG_CCR_C :  //除数が0のときはゼロ除算。(±Inf)%(±0)=NaN, x%(±0)=(±Inf)
  4185:            Double.isNaN (zd) ? XEiJ.REG_CCR_C :  //引数がNaNでないのに結果がNaNのときはエラー。(±Inf)%y=NaN
  4186:            Double.isInfinite (xd) || Double.isInfinite (yd) ? 0 :  //引数が±Inf
  4187:            Double.isInfinite (zd) ? XEiJ.REG_CCR_V | XEiJ.REG_CCR_C :  //引数が±Infでないのに結果が±Infのときはオーバーフロー
  4188:            0);
  4189:   }  //fpkCDMOD()
  4190: 
  4191:   //fpkCFCMP ()
  4192:   //  $FEF2  __CFCMP
  4193:   //  32bit浮動小数点数の比較
  4194:   //  x<=>y
  4195:   //  <(a7).s:32bit浮動小数点数。x
  4196:   //  <4(a7).s:32bit浮動小数点数。y
  4197:   //  >ccr:lt=x<y,eq=x==y,gt=x>y
  4198:   public static void fpkCFCMP () throws M68kException {
  4199:     //([int]→float)<=>([int]→float)
  4200:     int a7 = XEiJ.regRn[15];
  4201:     float xf = Float.intBitsToFloat (XEiJ.busRls (a7));
  4202:     float yf = Float.intBitsToFloat (XEiJ.busRls (a7 + 4));
  4203:     XEiJ.regCCR = xf < yf ? XEiJ.REG_CCR_N | XEiJ.REG_CCR_C : xf == yf ? XEiJ.REG_CCR_Z : 0;  //どちらかがNaNのときは0
  4204:   }  //fpkCFCMP()
  4205: 
  4206:   //fpkCFADD ()
  4207:   //  $FEF3  __CFADD
  4208:   //  32bit浮動小数点数の加算
  4209:   //  <(a7).s:32bit浮動小数点数。被加算数x
  4210:   //  <4(a7).s:32bit浮動小数点数。加算数y
  4211:   //  >(a7).s:32bit浮動小数点数。和x+y
  4212:   //  >ccr:cs=エラー,vs=オーバーフロー
  4213:   public static void fpkCFADD () throws M68kException {
  4214:     //([int]→float)+([int]→float)→[int]
  4215:     int a7 = XEiJ.regRn[15];
  4216:     float xf = Float.intBitsToFloat (XEiJ.busRls (a7));
  4217:     float yf = Float.intBitsToFloat (XEiJ.busRls (a7 + 4));
  4218:     float zf = xf + yf;
  4219:     int h = Float.floatToIntBits (zf);
  4220:     if (FPK_FPCP_NAN && h == 0x7fc00000) {
  4221:       h = 0x7fffffff;
  4222:     }
  4223:     XEiJ.busWl (a7, h);
  4224:     XEiJ.regCCR = (Float.isNaN (xf) || Float.isNaN (yf) ? 0 :  //引数がNaN
  4225:            Float.isNaN (zf) ? XEiJ.REG_CCR_C :  //引数がNaNでないのに結果がNaNのときはエラー。(+Inf)+(-Inf)=NaN
  4226:            Float.isInfinite (xf) || Float.isInfinite (yf) ? 0 :  //引数が±Inf
  4227:            Float.isInfinite (zf) ? XEiJ.REG_CCR_V | XEiJ.REG_CCR_C :  //引数が±Infでないのに結果が±Infのときはオーバーフロー
  4228:            0);
  4229:   }  //fpkCFADD()
  4230: 
  4231:   //fpkCFSUB ()
  4232:   //  $FEF4  __CFSUB
  4233:   //  32bit浮動小数点数の減算
  4234:   //  <(a7).s:32bit浮動小数点数。被減算数x
  4235:   //  <4(a7).s:32bit浮動小数点数。減算数y
  4236:   //  >(a7).s:32bit浮動小数点数。差x-y
  4237:   //  >ccr:cs=エラー,vs=オーバーフロー
  4238:   public static void fpkCFSUB () throws M68kException {
  4239:     //([int]→float)-([int]→float)→[int]
  4240:     int a7 = XEiJ.regRn[15];
  4241:     float xf = Float.intBitsToFloat (XEiJ.busRls (a7));
  4242:     float yf = Float.intBitsToFloat (XEiJ.busRls (a7 + 4));
  4243:     float zf = xf - yf;
  4244:     int h = Float.floatToIntBits (zf);
  4245:     if (FPK_FPCP_NAN && h == 0x7fc00000) {
  4246:       h = 0x7fffffff;
  4247:     }
  4248:     XEiJ.busWl (a7, h);
  4249:     XEiJ.regCCR = (Float.isNaN (xf) || Float.isNaN (yf) ? 0 :  //引数がNaN
  4250:            Float.isNaN (zf) ? XEiJ.REG_CCR_C :  //引数がNaNでないのに結果がNaNのときはエラー。(+Inf)-(+Inf)=NaN
  4251:            Float.isInfinite (xf) || Float.isInfinite (yf) ? 0 :  //引数が±Inf
  4252:            Float.isInfinite (zf) ? XEiJ.REG_CCR_V | XEiJ.REG_CCR_C :  //引数が±Infでないのに結果が±Infのときはオーバーフロー
  4253:            0);
  4254:   }  //fpkCFSUB()
  4255: 
  4256:   //fpkCFMUL ()
  4257:   //  $FEF5  __CFMUL
  4258:   //  32bit浮動小数点数の乗算
  4259:   //  <(a7).s:32bit浮動小数点数。被乗数x
  4260:   //  <4(a7).s:32bit浮動小数点数。乗数y
  4261:   //  >(a7).s:32bit浮動小数点数。積x*y
  4262:   //  >ccr:0=エラーなし,C=アンダーフロー,V|C=オーバーフロー
  4263:   public static void fpkCFMUL () throws M68kException {
  4264:     //([int]→float)*([int]→float)→[int]
  4265:     int a7 = XEiJ.regRn[15];
  4266:     float xf = Float.intBitsToFloat (XEiJ.busRls (a7));
  4267:     float yf = Float.intBitsToFloat (XEiJ.busRls (a7 + 4));
  4268:     float zf = xf * yf;
  4269:     int h = Float.floatToIntBits (zf);
  4270:     if (FPK_FPCP_NAN && h == 0x7fc00000) {
  4271:       h = 0x7fffffff;
  4272:     }
  4273:     XEiJ.busWl (a7, h);
  4274:     XEiJ.regCCR = (Float.isNaN (xf) || Float.isNaN (yf) ? 0 :  //引数がNaN
  4275:            Float.isNaN (zf) ? XEiJ.REG_CCR_C :  //引数がNaNでないのに結果がNaNのときはエラー。(±0)*(±Inf)=NaN
  4276:            Float.isInfinite (xf) || Float.isInfinite (yf) ? 0 :  //引数が±Inf
  4277:            Float.isInfinite (zf) ? XEiJ.REG_CCR_V | XEiJ.REG_CCR_C :  //引数が±Infでないのに結果が±Infのときはオーバーフロー
  4278:            0);
  4279:   }  //fpkCFMUL()
  4280: 
  4281:   //fpkCFDIV ()
  4282:   //  $FEF6  __CFDIV
  4283:   //  32bit浮動小数点数の除算
  4284:   //  <(a7).s:32bit浮動小数点数。被除数x
  4285:   //  <4(a7).s:32bit浮動小数点数。除数y
  4286:   //  >(a7).s:32bit浮動小数点数。商x/y。ゼロ除算のときは不定
  4287:   //  >ccr:cs=エラー,eq=ゼロ除算,vs=オーバーフロー
  4288:   public static void fpkCFDIV () throws M68kException {
  4289:     //([int]→float)/([int]→float)→[int]
  4290:     int a7 = XEiJ.regRn[15];
  4291:     float xf = Float.intBitsToFloat (XEiJ.busRls (a7));
  4292:     float yf = Float.intBitsToFloat (XEiJ.busRls (a7 + 4));
  4293:     float zf = xf / yf;
  4294:     int h = Float.floatToIntBits (zf);
  4295:     if (FPK_FPCP_NAN && h == 0x7fc00000) {
  4296:       h = 0x7fffffff;
  4297:     }
  4298:     XEiJ.busWl (a7, h);
  4299:     XEiJ.regCCR = (Float.isNaN (xf) || Float.isNaN (yf) ? 0 :  //引数がNaN
  4300:            Float.isNaN (zf) ? XEiJ.REG_CCR_C :  //引数がNaNでないのに結果がNaNのときはエラー。(±0)/(±0)=NaN
  4301:            Float.isInfinite (xf) || Float.isInfinite (yf) ? 0 :  //引数が±Inf。(±Inf)/(±0)=(±Inf)
  4302:            yf == 0.0F ? XEiJ.REG_CCR_Z | XEiJ.REG_CCR_C :  //除数が±0のときはゼロ除算
  4303:            Float.isInfinite (zf) ? XEiJ.REG_CCR_V | XEiJ.REG_CCR_C :  //引数が±Infでないのに結果が±Infのときはオーバーフロー
  4304:            0);
  4305:   }  //fpkCFDIV()
  4306: 
  4307:   //fpkCFMOD ()
  4308:   //  $FEF7  __CFMOD
  4309:   //  32bit浮動小数点数の剰余算
  4310:   //  <(a7).s:32bit浮動小数点数。被除数x
  4311:   //  <4(a7).s:32bit浮動小数点数。除数y
  4312:   //  >(a7).s:32bit浮動小数点数。余りx%y。ゼロ除算のときは不定
  4313:   //  >ccr:cs=エラー,eq=ゼロ除算
  4314:   public static void fpkCFMOD () throws M68kException {
  4315:     //([int]→float)%([int]→float)→[int]
  4316:     int a7 = XEiJ.regRn[15];
  4317:     float xf = Float.intBitsToFloat (XEiJ.busRls (a7));
  4318:     float yf = Float.intBitsToFloat (XEiJ.busRls (a7 + 4));
  4319:     float zf = xf % yf;
  4320:     int h = Float.floatToIntBits (zf);
  4321:     if (FPK_FPCP_NAN && h == 0x7fc00000) {
  4322:       h = 0x7fffffff;
  4323:     }
  4324:     XEiJ.busWl (a7, h);
  4325:     XEiJ.regCCR = (Float.isNaN (xf) || Float.isNaN (yf) ? 0 :  //引数がNaN
  4326:            yf == 0.0F ? XEiJ.REG_CCR_Z | XEiJ.REG_CCR_C :  //除数が0のときはゼロ除算。(±Inf)%(±0)=NaN, x%(±0)=(±Inf)
  4327:            Float.isNaN (zf) ? XEiJ.REG_CCR_C :  //引数がNaNでないのに結果がNaNのときはエラー。(±Inf)%y=NaN
  4328:            Float.isInfinite (xf) || Float.isInfinite (yf) ? 0 :  //引数が±Inf
  4329:            Float.isInfinite (zf) ? XEiJ.REG_CCR_V | XEiJ.REG_CCR_C :  //引数が±Infでないのに結果が±Infのときはオーバーフロー
  4330:            0);
  4331:   }  //fpkCFMOD()
  4332: 
  4333:   //fpkCDTST ()
  4334:   //  $FEF8  __CDTST
  4335:   //  64bit浮動小数点数と0の比較
  4336:   //  x<=>0
  4337:   //  <(a7).d:64bit浮動小数点数。x
  4338:   //  >ccr:lt=x<0,eq=x==0,gt=x>0
  4339:   public static void fpkCDTST () throws M68kException {
  4340:     if (true) {
  4341:       int a7 = XEiJ.regRn[15];
  4342:       long l = (long) XEiJ.busRls (a7) << 32 | 0xffffffffL & XEiJ.busRls (a7 + 4);
  4343:       XEiJ.regCCR = l << 1 == 0L ? XEiJ.REG_CCR_Z : 0L <= l ? 0 : XEiJ.REG_CCR_N;  //NaNのときは0
  4344:     } else {
  4345:       //[int,int]→[long]→double
  4346:       int a7 = XEiJ.regRn[15];
  4347:       double d = Double.longBitsToDouble ((long) XEiJ.busRls (a7) << 32 | 0xffffffffL & XEiJ.busRls (a7 + 4));
  4348:       XEiJ.regCCR = d < 0.0 ? XEiJ.REG_CCR_N : d == 0.0 ? XEiJ.REG_CCR_Z : 0;  //NaNのときは0
  4349:     }
  4350:   }  //fpkCDTST()
  4351: 
  4352:   //fpkCFTST ()
  4353:   //  $FEF9  __CFTST
  4354:   //  32bit浮動小数点数と0の比較
  4355:   //  x<=>0
  4356:   //  <(a7).s:32bit浮動小数点数。x
  4357:   //  >ccr:lt=x<0,eq=x==0,gt=x>0
  4358:   public static void fpkCFTST () throws M68kException {
  4359:     //[int]→float
  4360:     if (true) {
  4361:       int h = XEiJ.busRls (XEiJ.regRn[15]);
  4362:       XEiJ.regCCR = h << 1 == 0 ? XEiJ.REG_CCR_Z : 0 <= h ? 0 : XEiJ.REG_CCR_N;  //NaNのときは0
  4363:     } else {
  4364:       //([int]→float)<=>0
  4365:       float f = Float.intBitsToFloat (XEiJ.busRls (XEiJ.regRn[15]));
  4366:       XEiJ.regCCR = f < 0.0F ? XEiJ.REG_CCR_N : f == 0.0F ? XEiJ.REG_CCR_Z : 0;  //NaNのときは0
  4367:     }
  4368:   }  //fpkCFTST()
  4369: 
  4370:   //fpkCDINC ()
  4371:   //  $FEFA  __CDINC
  4372:   //  64bit浮動小数点数に1を加える
  4373:   //  <(a7).d:64bit浮動小数点数。x
  4374:   //  >(a7).d:64bit浮動小数点数。x+1
  4375:   public static void fpkCDINC () throws M68kException {
  4376:     //([int,int]→[long]→double)+1→[long]→[int,int]
  4377:     int a7 = XEiJ.regRn[15];
  4378:     double xd = Double.longBitsToDouble ((long) XEiJ.busRls (a7) << 32 | 0xffffffffL & XEiJ.busRls (a7 + 4));
  4379:     double zd = xd + 1.0;
  4380:     long l = Double.doubleToLongBits (zd);
  4381:     if (FPK_FPCP_NAN && l == 0x7ff8000000000000L) {
  4382:       l = 0x7fffffffffffffffL;
  4383:     }
  4384:     XEiJ.busWl (a7, (int) (l >>> 32));
  4385:     XEiJ.busWl (a7 + 4, (int) l);
  4386:     XEiJ.regCCR = Double.isInfinite (zd) && !Double.isInfinite (xd) ? XEiJ.REG_CCR_V | XEiJ.REG_CCR_C : 0;  //結果が±Infだが引数が±Infでないときはオーバーフロー
  4387:   }  //fpkCDINC()
  4388: 
  4389:   //fpkCFINC ()
  4390:   //  $FEFB  __CFINC
  4391:   //  32bit浮動小数点数に1を加える
  4392:   //  <(a7).s:32bit浮動小数点数。x
  4393:   //  >(a7).s:32bit浮動小数点数。x+1
  4394:   public static void fpkCFINC () throws M68kException {
  4395:     //([int]→float)+1→[int]
  4396:     int a7 = XEiJ.regRn[15];
  4397:     float xf = Float.intBitsToFloat (XEiJ.busRls (a7));
  4398:     float zf = xf + 1.0F;
  4399:     int h = Float.floatToIntBits (zf);
  4400:     if (FPK_FPCP_NAN && h == 0x7fc00000) {
  4401:       h = 0x7fffffff;
  4402:     }
  4403:     XEiJ.busWl (a7, h);
  4404:     XEiJ.regCCR = Double.isInfinite (zf) && !Float.isInfinite (xf) ? XEiJ.REG_CCR_V | XEiJ.REG_CCR_C : 0;  //結果が±Infだが引数が±Infでないときはオーバーフロー
  4405:   }  //fpkCFINC()
  4406: 
  4407:   //fpkCDDEC ()
  4408:   //  $FEFC  __CDDEC
  4409:   //  64bit浮動小数点数から1を引く
  4410:   //  <(a7).d:64bit浮動小数点数。x
  4411:   //  >(a7).d:64bit浮動小数点数。x-1
  4412:   public static void fpkCDDEC () throws M68kException {
  4413:     //([int,int]→[long]→double)-1→[long]→[int,int]
  4414:     int a7 = XEiJ.regRn[15];
  4415:     double xd = Double.longBitsToDouble ((long) XEiJ.busRls (a7) << 32 | 0xffffffffL & XEiJ.busRls (a7 + 4));
  4416:     double zd = xd - 1.0;
  4417:     long l = Double.doubleToLongBits (zd);
  4418:     if (FPK_FPCP_NAN && l == 0x7ff8000000000000L) {
  4419:       l = 0x7fffffffffffffffL;
  4420:     }
  4421:     XEiJ.busWl (a7, (int) (l >>> 32));
  4422:     XEiJ.busWl (a7 + 4, (int) l);
  4423:     XEiJ.regCCR = Double.isInfinite (zd) && !Double.isInfinite (xd) ? XEiJ.REG_CCR_V | XEiJ.REG_CCR_C : 0;  //結果が±Infだが引数が±Infでないときはオーバーフロー
  4424:   }  //fpkCDDEC()
  4425: 
  4426:   //fpkCFDEC ()
  4427:   //  $FEFD  __CFDEC
  4428:   //  32bit浮動小数点数から1を引く
  4429:   //  <(a7).s:32bit浮動小数点数。x
  4430:   //  >(a7).s:32bit浮動小数点数。x-1
  4431:   public static void fpkCFDEC () throws M68kException {
  4432:     //([int]→float)-1→[int]
  4433:     int a7 = XEiJ.regRn[15];
  4434:     float xf = Float.intBitsToFloat (XEiJ.busRls (a7));
  4435:     float zf = xf - 1.0F;
  4436:     int h = Float.floatToIntBits (zf);
  4437:     if (FPK_FPCP_NAN && h == 0x7fc00000) {
  4438:       h = 0x7fffffff;
  4439:     }
  4440:     XEiJ.busWl (a7, h);
  4441:     XEiJ.regCCR = Double.isInfinite (zf) && !Float.isInfinite (xf) ? XEiJ.REG_CCR_V | XEiJ.REG_CCR_C : 0;  //結果が±Infだが引数が±Infでないときはオーバーフロー
  4442:   }  //fpkCFDEC()
  4443: 
  4444: }  //class FEFunction
  4445: 
  4446: 
  4447: