1
0
mirror of https://github.com/dschmenk/PLASMA.git synced 2026-03-12 01:41:40 +00:00
Files
PLASMA/src/libsrc/fpu.pla
2018-01-13 11:53:21 -08:00

373 lines
11 KiB
Plaintext

//
// 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