// // SANE stack-based Floating Point Unit library // include "inc/cmdsys.plh" include "inc/sane.plh" include "inc/fpstr.plh" // // External interface to FPU library // predef reset, getEnv, setEnv(env), testExcept(except), setExcept(except), enterProc(pEnv), exitProc(env) predef constPi, constE predef pushInt(pInt), pushSgl(pSgl), pushDbl(pDbl), pushExt(pExt), pushStr(pStr) predef pullInt(pInt), pullSgl(pSgl), pullDbl(pDbl), pullExt(pExt), pullStr(pStr,intdigits,fracdigits,format) predef loadInt(pInt,reg), loadSgl(pSgl,reg), loadDbl(pDbl,reg), loadExt(pExt,reg), loadStr(pStr,reg) predef storInt(pInt,reg), storSgl(pSgl,reg), storDbl(pDbl,reg), storExt(pExt,reg), storStr(pStr,intdigits,fracdigits,format,reg) predef shiftUp, shiftDown, rotateUp, rotateDown, dup, swap, clear predef add, sub, mul, div, rem predef neg, abs, type, cmp, logb, scalb(scale), trunc, round, sqrt, squared predef cos, sin, tan, atan predef log2X, log21X, lnX, ln1X, pow2X, pow21X, powEX, powE1X, powE21X, powXInt(powInt), powXY predef compXY, annuityXY, randNum(pSeed) // // FP6502 functions // //export word fpu = @reset word fpu = @reset word = @setEnv, @getEnv, @testExcept, @setExcept, @enterProc, @exitProc word = @constPi, @constE word = @pushInt, @pushSgl, @pushDbl, @pushExt, @pushStr word = @pullInt, @pullSgl, @pullDbl, @pullExt, @pullStr word = @loadInt, @loadSgl, @loadDbl, @loadExt, @loadStr word = @storInt, @storSgl, @storDbl, @storExt, @storStr word = @shiftUp, @shiftDown, @rotateUp, @rotateDown, @dup, @swap, @clear word = @add, @sub, @mul, @div, @rem word = @neg, @abs, @type, @cmp word = @logb, @scalb, @trunc, @round, @sqrt, @squared // // ELEMS6502 functions // word = @cos, @sin, @tan, @atan word = @log2X, @log21X, @lnX, @ln1X, @pow2X, @pow21X, @powEX, @powE1X, @powE21X, @powXInt, @powXY word = @compXY, @annuityXY, @randNum // // Useful constants // byte ext_pi[t_extended] = $35,$C2,$68,$21,$A2,$DA,$0F,$C9,$00,$40 byte ext_e[t_extended] = $9B,$4A,$BB,$A2,$5B,$54,$F8,$AD,$00,$40 // // FP Stack // byte stack[t_extended*4] word stackRegs[4] // // Environment access // def setEnv(env) sane:saveZP() return sane:restoreZP(sane:op1FP(FOSETENV, env)) end def getEnv sane:saveZP() return sane:restoreZP(sane:op0FP(FOGETENV)) end def testExcept(except) sane:saveZP() return sane:restoreZP(sane:op1FP(FOTESTXCP, except)) end def setExcept(except) sane:saveZP() return sane:restoreZP(sane:op1FP(FOSETXCP, except)) end def enterProc(pEnv) sane:saveZP() return sane:restoreZP(sane:op1FP(FOPROCENTRY, pEnv)) end def exitProc(env) sane:saveZP() return sane:restoreZP(sane:op1FP(FOPROCEXIT, env)) end // // Stack manipulation routines // def rotateUp stackRegs[0], stackRegs[1], stackRegs[2], stackRegs[3] = stackRegs[3], stackRegs[0], stackRegs[1], stackRegs[2] return 0 end def rotateDown stackRegs[0], stackRegs[1], stackRegs[2], stackRegs[3] = stackRegs[1], stackRegs[2], stackRegs[3], stackRegs[0] return 0 end def shiftUp stackRegs[0], stackRegs[1], stackRegs[2], stackRegs[3] = stackRegs[3], stackRegs[0], stackRegs[1], stackRegs[2] memcpy(stackRegs[0], stackRegs[1], t_extended) return 0 end def shiftDown // drop stackRegs[0], stackRegs[1], stackRegs[2], stackRegs[3] = stackRegs[1], stackRegs[2], stackRegs[3], stackRegs[0] memcpy(stackRegs[3], stackRegs[2], t_extended) return 0 end def _drop(passthru) // Internal version with passthru stackRegs[0], stackRegs[1], stackRegs[2], stackRegs[3] = stackRegs[1], stackRegs[2], stackRegs[3], stackRegs[0] memcpy(stackRegs[3], stackRegs[2], t_extended) return passthru end def swap stackRegs[0], stackRegs[1] = stackRegs[1], stackRegs[0] return 0 end def _swap(passthru) // Internal version with passthru stackRegs[0], stackRegs[1] = stackRegs[1], stackRegs[0] return passthru end def dup stackRegs[0], stackRegs[1], stackRegs[2], stackRegs[3] = stackRegs[3], stackRegs[0], stackRegs[1], stackRegs[2] memcpy(stackRegs[0], stackRegs[1], t_extended) return 0 end def clear word zero zero = 0 sane:saveZP() return sane:restoreZP(sane:op2FP(FFINT|FOZ2X, stackRegs[0], @zero)) end // // Stack access // def pushInt(pInt) stackRegs[0], stackRegs[1], stackRegs[2], stackRegs[3] = stackRegs[3], stackRegs[0], stackRegs[1], stackRegs[2] sane:saveZP() return sane:restoreZP(sane:op2FP(FFINT|FOZ2X, stackRegs[0], pInt)) end def pullInt(pInt) sane:saveZP() return _drop(sane:restoreZP(sane:op2FP(FFINT|FOX2Z, pInt, stackRegs[0]))) end def loadInt(pInt, reg) sane:saveZP() return sane:restoreZP(sane:op2FP(FFINT|FOZ2X, stackRegs[reg & $03], pInt)) end def storInt(pInt, reg) sane:saveZP() return sane:restoreZP(sane:op2FP(FFINT|FOX2Z, pInt, stackRegs[reg & $03])) end def pushSgl(pSgl) stackRegs[0], stackRegs[1], stackRegs[2], stackRegs[3] = stackRegs[3], stackRegs[0], stackRegs[1], stackRegs[2] sane:saveZP() return sane:restoreZP(sane:op2FP(FFSGL|FOZ2X, stackRegs[0], pSgl)) end def pullSgl(pSgl) sane:saveZP() return _drop(sane:restoreZP(sane:op2FP(FFSGL|FOX2Z, pSgl, stackRegs[0]))) end def loadSgl(pSgl, reg) sane:saveZP() return sane:restoreZP(sane:op2FP(FFSGL|FOZ2X, stackRegs[reg & $03], pSgl)) end def storSgl(pSgl, reg) sane:saveZP() return sane:restoreZP(sane:op2FP(FFSGL|FOX2Z, pSgl, stackRegs[reg & $03])) end def pushDbl(pDbl) stackRegs[0], stackRegs[1], stackRegs[2], stackRegs[3] = stackRegs[3], stackRegs[0], stackRegs[1], stackRegs[2] sane:saveZP() return sane:restoreZP(sane:op2FP(FFDBL|FOZ2X, stackRegs[0], pDbl)) end def pullDbl(pDbl) sane:saveZP() return _drop(sane:restoreZP(sane:op2FP(FFDBL|FOX2Z, pDbl, stackRegs[0]))) end def loadDbl(pDbl, reg) sane:saveZP() return sane:restoreZP(sane:op2FP(FFDBL|FOZ2X, stackRegs[reg & $03], pDbl)) end def storDbl(pDbl, reg) sane:saveZP() return sane:restoreZP(sane:op2FP(FFDBL|FOX2Z, pDbl, stackRegs[reg & $03])) end def pushExt(pExt) stackRegs[0], stackRegs[1], stackRegs[2], stackRegs[3] = stackRegs[3], stackRegs[0], stackRegs[1], stackRegs[2] sane:saveZP() return sane:restoreZP(sane:op2FP(FFEXT|FOZ2X, stackRegs[0], pExt)) end def pullExt(pExt) sane:saveZP() return _drop(sane:restoreZP(sane:op2FP(FFEXT|FOX2Z, pExt, stackRegs[0]))) end def loadExt(pExt, reg) sane:saveZP() return sane:restoreZP(sane:op2FP(FFEXT|FOZ2X, stackRegs[reg & $03], pExt)) end def storExt(pExt, reg) sane:saveZP() return sane:restoreZP(sane:op2FP(FFEXT|FOX2Z, pExt, stackRegs[reg & $03])) end def pushStr(pStr) stackRegs[0], stackRegs[1], stackRegs[2], stackRegs[3] = stackRegs[3], stackRegs[0], stackRegs[1], stackRegs[2] return str2ext(pStr, stackRegs[0]) end def pullStr(pStr, intdigits, fracdigits, format) return _drop(ext2str(stackRegs[0], pStr, intdigits, fracdigits, format)) end def loadStr(pStr, reg) return str2ext(pStr, stackRegs[reg]) end def storStr(pStr, intdigits, fracdigits, format, reg) return ext2str(stackRegs[reg], pStr, intdigits, fracdigits, format) end // // Basic math operations // def add sane:saveZP() return _drop(sane:restoreZP(sane:op2FP(FFEXT|FOADD, stackRegs[1], stackRegs[0]))) end def sub sane:saveZP() return _drop(sane:restoreZP(sane:op2FP(FFEXT|FOSUB, stackRegs[1], stackRegs[0]))) end def mul sane:saveZP() return _drop(sane:restoreZP(sane:op2FP(FFEXT|FOMUL, stackRegs[1], stackRegs[0]))) end def div sane:saveZP() return _drop(sane:restoreZP(sane:op2FP(FFEXT|FODIV, stackRegs[1], stackRegs[0]))) end def rem sane:saveZP() return _drop(sane:restoreZP(sane:op2FP(FFEXT|FOREM, stackRegs[1], stackRegs[0]))) end def neg sane:saveZP() return sane:restoreZP(sane:op1FP(FFEXT|FONEG, stackRegs[0])) end def abs sane:saveZP() return sane:restoreZP(sane:op1FP(FFEXT|FOABS, stackRegs[0])) end def type sane:saveZP() return sane:restoreZP(sane:op1FP(FFEXT|FOCLASS, stackRegs[0])) end def cmp sane:saveZP() return sane:restoreZP(sane:op2FP(FFEXT|FOCMP, stackRegs[1], stackRegs[0])) end def trunc sane:saveZP() return sane:restoreZP(sane:op1FP(FFEXT|FOTTI, stackRegs[0])) end def round sane:saveZP() return sane:restoreZP(sane:op1FP(FFEXT|FORTI, stackRegs[0])) end def sqrt sane:saveZP() return sane:restoreZP(sane:op1FP(FFEXT|FOSQRT, stackRegs[0])) end def squared sane:saveZP() return sane:restoreZP(sane:op2FP(FFEXT|FOMUL, stackRegs[0], stackRegs[0])) end def logb sane:saveZP() return sane:restoreZP(sane:op1FP(FFEXT|FOLOGB, stackRegs[0])) end def scalb(scale) sane:saveZP() return sane:restoreZP(sane:op2FP(FFEXT|FOSCALB, stackRegs[0], scale)) end // // Elems operations // def cos sane:saveZP() return sane:restoreZP(sane:op1ELEM(FFEXT|FOCOSX, stackRegs[0])) end def sin sane:saveZP() return sane:restoreZP(sane:op1ELEM(FFEXT|FOSINX, stackRegs[0])) end def tan sane:saveZP() return sane:restoreZP(sane:op1ELEM(FFEXT|FOTANX, stackRegs[0])) end def atan sane:saveZP() return sane:restoreZP(sane:op1ELEM(FFEXT|FOATANX, stackRegs[0])) end def log2X sane:saveZP() return sane:restoreZP(sane:op1ELEM(FFEXT|FOLOG2X, stackRegs[0])) end def log21X sane:saveZP() return sane:restoreZP(sane:op1ELEM(FFEXT|FOLOG21X, stackRegs[0])) end def lnX sane:saveZP() return sane:restoreZP(sane:op1ELEM(FFEXT|FOLNX, stackRegs[0])) end def ln1X sane:saveZP() return sane:restoreZP(sane:op1ELEM(FFEXT|FOLN1X, stackRegs[0])) end def pow2X sane:saveZP() return sane:restoreZP(sane:op1ELEM(FFEXT|FOEXP2X, stackRegs[0])) end def pow21X sane:saveZP() return sane:restoreZP(sane:op1ELEM(FFEXT|FOEXP21X, stackRegs[0])) end def powEX sane:saveZP() return sane:restoreZP(sane:op1ELEM(FFEXT|FOEXPX, stackRegs[0])) end def powE1X sane:saveZP() return sane:restoreZP(sane:op1ELEM(FFEXT|FOEXP1X, stackRegs[0])) end def powE21X sane:saveZP() return sane:restoreZP(sane:op1ELEM(FFEXT|FOEXP21X, stackRegs[0])) end def powXInt(powInt) sane:saveZP() return sane:restoreZP(sane:op2ELEM(FFEXT|FOXPWRI, stackRegs[0], powInt)) end def powXY sane:saveZP() return sane:restoreZP(_drop(_swap(sane:op2ELEM(FFEXT|FOXPWRY, stackRegs[0], stackRegs[1])))) end def compXY sane:saveZP() return sane:restoreZP(_drop(_swap(sane:op2ELEM(FFEXT|FOCOMPND, stackRegs[0], stackRegs[1])))) end def annuityXY sane:saveZP() return sane:restoreZP(_drop(_swap(sane:op2ELEM(FFEXT|FOANNUIT, stackRegs[0], stackRegs[1])))) end def randNum(pSeed) sane:saveZP() return sane:restoreZP(sane:op1ELEM(FFEXT|FORANDX, pSeed)) end // // Push useful constants // def constPi return pushExt(@ext_pi) end def constE return pushExt(@ext_e) end // // Reset FPU and SANE // def reset byte i word zero zero = 0 sane:initFP() sane:saveZP() for i = 0 to 3 stackRegs[i] = @stack[i * t_extended] sane:op2FP(FFINT|FOZ2X, stackRegs[i], @zero) next return sane:restoreZP(0) end done