home *** CD-ROM | disk | FTP | other *** search
Text File | 1995-02-06 | 36.7 KB | 1,829 lines | [TEXT/MSET] |
- \ Aug 90 mrh Mops version.
- \ Dec 90 mrh Direct FPU support added - float now 14 bytes long.
- \ Apr 91 mrh More optimization of FPU code. FP source files combined.
- \ Number of parms/locals increased via ExtraLocals area.
-
- \ The floating heap is a region of heap that is divided into 14-byte blocks.
- \ Each block consists of two bytes of status information, along with 12
- \ bytes of data. If the status field is $0001, the block is in use.
- \ Otherwise, the status field holds the offset of the next free block from
- \ the start of the array, and bit 0 is off because the offset must be even.
- \ The data field is a 96-bit floating point number in 68881/68882 FPU
- \ extended format. This is basically the same as the SANE 80-bit
- \ extended format, since the 3rd and 4th bytes are unused (zero), and
- \ the SANE format is identical except that these unused 2 bytes are not
- \ represented. If we don't have an FPU we call SANE, and this means we
- \ have to adjust the format first.
-
- false -> useFPU?
-
- \ floating-point error handlers
-
- : NOTINIT cr ." Uninitialized float argument" abort ;
- : FullErr cr ." Floating point heap is full" abort ;
- : NF cr ." Not a float: " . abort ;
-
-
- :code NoFloat \ Assume A0 -> float that isn't
- push.l a0
- bra.s dic[NF]
- ;code
-
-
- :class FLTHEAP super{ object } 14 indexed
-
- record
- { int FreeHead \ offset of first free block
- }
-
- :mcode NEW: \ ( -- fPtr )
-
- \ Returns a ptr to a new block. Interestingly,
- \ the Mops register usage means that this routine is only
- \ half as long as it was in Neon. Note that unlike Neon,
- \ fPtr points to the floating data, not to the status word.
-
- loc
- move.w (a2),d0 ; D0(lo) = offset of first free block
- beq dic[fullErr]
- lea 0(a2,d0.w),a0 ; A0 -> the block
- move.w (a0),(a2) ; Move next free block
- ; offs to free list hdr
- move.w #1,(a0)+ ; Mark block in use
- push.l a0 ; Return data addr
- ;mcode
-
-
- :mcode RELEASE: \ ( fptr -- ) Disposes of block for fptr
- pop.l a0 ; A0 -> float data
- cmpi.w #1,-(a0) ; Float block must have $0001 in
- ; its status field
- bne dic[noFloat]
- move.w (a2),(a0) ; Move free list hdr to blk
- ; being freed
- sub.l a2,a0 ; Get offs of block
- move.w a0,(a2) ; Store in free head ptr
- ;mcode
-
-
- :m ROOM: { \ offs #free -- #free } \ Returns # of float blocks remaining
- \ in float heap
- get: freeHead -> offs 0 -> #free
- BEGIN offs
- WHILE offs ^base + w@ -> offs 1 ++> #free
- REPEAT
- #free ;m
-
- :m CLASSINIT: \ Sets all blocks to free and links them together.
- limit 1- 0
- DO
- i 1+ ^elem ^base - i ^elem w!
- LOOP
- 0 limit 1- ^elem w!
- 0 ^elem ^base - put: freeHead ;m
-
- :m INIT: classinit: self ;m
-
- ;class
-
-
- 100 fltHeap FLTMEM
-
-
- \ (FLTNEW) is a subroutine which returns a new float ptr in A0.
- \ Uses D0.
-
- :code (FLTNEW)
- loc
- lea dicobj[fltMem],a0
- move.w (a0),d0 ; D0(lo) = offset of first free
- ; block
- beq dic[fullErr]
- add.w d0,a0 ; A0 -> the block
- move.w (a0),dicobj[fltMem] ; Move next free block offs to
- ; free list hdr
- move.w #1,(a0)+ ; Mark block in use, update A0 to
- ; float data addr
- ;code
-
-
- \ (FLTDISP) is a subroutine to dispose of the float in A0. Uses A0.
-
- :code (FLTDISP)
- push.l a1 ; Save a1
- cmpi.w #1,-(a0) ; Float block must have $0001 in
- ; its status field
- bne dic[noFloat]
- lea dicobj[fltMem],a1
- move.w (a1),(a0) ; Move free list hdr to blk being
- ; freed
- sub.l a1,a0 ; Get offset of block
- move.w a0,(a1) ; Store in free list header
- pop.l a1 ; Restore a1
- ;code
-
- :code (FLTDISP2) \ Subroutine to dispose of floats in A0,A1
- \ Uses A0, A1, D0, D1
- move.l a1,d1 ; Save
- cmpi.w #1,-(a0) ; Float must have $0001 in its status field
- bne dic[noFloat]
- lea dicobj[fltMem],a1
- move.w (a1),(a0) ; Move free list hdr to blk being freed
- sub.l a1,a0 ; Get offset of block
- move.w a0,d0 ; Save in D0
- move.l d1,a0 ; Now the other one.
- cmpi.w #1,-(a0) ; Float must have $0001 in its
- ; status field
- bne dic[noFloat]
- move.w d0,(a0) ; Move next free blk offs to blk being freed
- sub.l a1,a0 ; Get offset of block
- move.w a0,(a1) ; Store in free list header
- ;code
-
-
- :code FLIT
- bsr dic[(fltNew)] ; New float ptr to A0
- push.l a0 ; Push it
- move.l (a7),a1
- move.w (a1)+,(a0)+ ; Literal is in 80-bit format
- clr.w (a0)+ ; Expand to FPU format
- move.l (a1)+,(a0)+
- move.l (a1)+,(a0)
- move.l a1,(a7) ; Update return address
- ;code
-
- :code (FPULIT)
- move.l (a7)+,a1
- jmp 12(a1)
- ;code
-
- :code FDUP
- bsr dic[(fltNew)] ; New float to A0
- move.l (a6),a1 ; Float to dup to A1
- push.l a0 ; Push new float
- move.w -2(a1),-2(a0) ; Move status word
- movem.l (a1),d0-d2 ; Move data
- movem.l d0-d2,(a0)
- ;code
-
- :code FOVER
- bsr dic[(fltNew)] ; New float to A0
- move.l 4(a6),a1 ; Float to copy to A1
- push.l a0 ; Push new float
- move.w -2(a1),-2(a0) ; Move status word
- movem.l (a1),d0-d2 ; Move data
- movem.l d0-d2,(a0)
- ;code
-
- : F2DUP fOver fOver ;
-
- :code FDROP
- pop.l a0
- bra dic[(fltDisp)]
- ;code
-
- :code F2DROP
- pop.l a0
- pop.l a1
- bra dic[(fltDisp2)]
- ;code
-
- ( ops opCode -- )
-
- : FP68K \ Call FP68K. Floating-point package.
- makeint call pack4 ;
-
- : ELEMS68K \ Call ELEMS68K. Transcendentals package.
- makeint call pack5 ;
-
-
- \ ==============================
-
- \ FP code words
-
- \ ==============================
-
- $ 4E58 constant XINFOMK \ Must agree with defn in Defn.asm *****
-
- : :FP1 \ ( opcode -- )
- header
- -80 w, \ handler code FP1_h
- xinfoMk w, \ Marks this word as having extra non-code info
- 2 w, \ which is 2 bytes long
- w, \ This is it -- the opcode
- postpone ] \ start compiling
- ; immediate
-
-
- : :FP2 \ ( opcode -- )
- header
- -82 w, \ handler code FP2_h
- xinfoMk w, \ Marks this word as having extra non-code info
- 2 w, \ which is 2 bytes long
- w, \ This is it -- the opcode
- postpone ] \ start compiling
- ; immediate
-
-
- : :FPcmp \ ( opcode -- )
- header
- -84 w, \ handler code FPcmp_h
- xinfoMk w, \ Marks this word as having extra non-code info
- 2 w, \ which is 2 bytes long
- w, \ This is it -- the opcode
- postpone ] \ start compiling
- ; immediate
-
-
- \ =========== Dyadic comparisons ==========
-
- :code FCMP2 \ ( flt0 flt1 -- abs1 abs2) Subroutine to set up stack for
- \ dyadic comparison and kill floats.
- \ Uses D0,D1,D2 and A0,A1.
- loc
- fcmp2 pop.l a1 ; A1 -> flt1
- move.l (a6),a0 ; A0 -> flt0
- move.w (a0)+,(a0) ; Convert both to 80-bit SANE format
- move.w (a1)+,(a1)
- move.l a1,(a6)
- push.l a0 ; Push addrs for SANE call. Note
- ; SANE operands are reversed.
- subq #2,a0 ; Restore original float to A0/1
- ; for (fltDisp2)
- subq #2,a1
- moveq #0,d2 ; Ready for result
- bra dic[(fltDisp2)] ; Kill floats (but data still valid)
- ;code
-
-
- :code FPUCMP2 \ ( flt0 flt1 -- ) Subroutine to set up FPU for comparison.
-
- FPUcmp2 pop.l a1
- pop.l a0
- fmove.x (a0),fp0
- ;code
-
-
- \ Stack frame for all dyadic comparisons:
- \ ( float1 float2 -- b )
-
- \ If we have an FPU, we use it. In this case we defer as much
- \ housekeeping as possible to the time after the floating comparison
- \ but before we test the FPU condition code. This time comes almost
- \ free of charge since it will be overlapped with the comparison op.
-
- $ 3F0E :FPcmp F>
- ToCode
- loc
- tst.b 3(dic[FPU?])
- beq.s noFPU1
- bsr.s dic[FPUcmp2]
- fcmp.x (a1),fp0
- bsr dic[(fltDisp2)]
- fsgt d2
- FixBool ext.w d2
- ext.l d2
- push.l d2
- rts
-
- noFPU1 bsr.s dic[Fcmp2] ; Setup
- push.w #8 ; Code for FCMPX
- exg a6,a7
- call pack4
- exg a6,a7
- sgt d2
- bra.s fixBool
- ;code
-
-
- $ 3F0D :FPcmp F<
- ToCode
- tst.b 3(dic[FPU?])
- beq.s noFPU2
- bsr dic[FPUcmp2]
- fcmp.x (a1),fp0
- bsr dic[(fltDisp2)]
- fslt d2
- bra fixBool
-
- noFPU2 bsr dic[Fcmp2] ; Setup
- push.w #8 ; Code for FCMPX
- exg a6,a7
- call pack4
- exg a6,a7
- slt d2
- bra fixBool
- ;code
-
- $ 3F0C :FPcmp F>=
- ToCode
- tst.b 3(dic[FPU?])
- beq.s noFPU3
- bsr dic[FPUcmp2]
- fcmp.x (a1),fp0
- bsr dic[(fltDisp2)]
- fsge d2
- bra fixBool
-
- noFPU3 bsr dic[Fcmp2] ; Setup
- push.w #8 ; Code for FCMPX
- exg a6,a7
- call pack4
- exg a6,a7
- sge d2
- bra fixBool
- ;code
-
- $ 3F0F :FPcmp F<=
- ToCode
- tst.b 3(dic[FPU?])
- beq.s noFPU4
- bsr dic[FPUcmp2]
- fcmp.x (a1),fp0
- bsr dic[(fltDisp2)]
- fsle d2
- bra fixBool
-
- noFPU4 bsr dic[Fcmp2] ; Setup
- push.w #8 ; Code for FCMPX
- exg a6,a7
- call pack4
- exg a6,a7
- sle d2
- bra fixBool
- ;code
-
- $ 3F07 :FPcmp F=
- ToCode
- tst.b 3(dic[FPU?])
- beq.s noFPU5
- bsr dic[FPUcmp2]
- fcmp.x (a1),fp0
- bsr dic[(fltDisp2)]
- fseq d2
- bra fixBool
-
- noFPU5 bsr dic[Fcmp2] ; Setup
- push.w #8 ; Code for FCMPX
- exg a6,a7
- call pack4
- exg a6,a7
- seq d2
- bra fixBool
- ;code
-
- $ 3F06 :FPcmp F<>
- ToCode
- tst.b 3(dic[FPU?])
- beq.s noFPU6
- bsr dic[FPUcmp2]
- fcmp.x (a1),fp0
- bsr dic[(fltDisp2)]
- fsne d2
- bra fixBool
- rts
-
- noFPU6 bsr dic[Fcmp2] ; Setup
- push.w #8 ; Code for FCMPX
- exg a6,a7
- call pack4
- exg a6,a7
- sne d2
- bra fixBool
- ;code
-
-
- \ ========= Monadic comparisons ==========
-
- variable FZERO 0 , 0 , \ Source of zero
-
- :code FCMP1 \ ( flt -- abs ) Subroutine to set up stack for
- \ monadic comparison and kill float.
- \ Uses D0,D1,D2 and A0,A1.
- loc
- fcmp1 move.l (a6),a0 ; A0 -> flt
- move.w (a0)+,(a0) ; Convert to 80-bit SANE format
- lea dic[FZero],a1
- move.l a1,(a6)
- push.l a0
- subq #2,a0 ; Restore original float to A0 for
- ; (fltDisp)
- moveq #0,d2 ; Ready for result
- bra dic[(fltDisp)] ; Kill float (but data still
- ; valid)
- ;code
-
-
- $ 3F17 :FPcmp F0=
- ToCode
- loc
- tst.b 3(dic[FPU?])
- beq.s noFPU1
- pop.l a0
- ftst.x (a0),fp0
- bsr dic[(fltDisp)]
- fseq d2
- FixBool ext.w d2
- ext.l d2
- push.l d2
- rts
-
- noFPU1 bsr dic[Fcmp1] ; Setup
- push.w #8 ; Code for FCMPX
- exg a6,a7
- call pack4
- exg a6,a7
- seq d2
- bra.s fixBool
- ;code
-
- $ 3F16 :FPcmp F0<>
- ToCode
- tst.b 3(dic[FPU?])
- beq.s noFPU2
- pop.l a0
- ftst.x (a0),fp0
- bsr dic[(fltDisp)]
- fsne d2
- bra fixBool
-
- noFPU2 bsr dic[Fcmp1] ; Setup
- push.w #8 ; Code for FCMPX
- exg a6,a7
- call pack4
- exg a6,a7
- sne d2
- bra fixBool
- ;code
-
- $ 3F1C :FPcmp F0>=
- ToCode
- tst.b 3(dic[FPU?])
- beq.s noFPU3
- pop.l a0
- ftst.x (a0),fp0
- bsr dic[(fltDisp)]
- fsge d2
- bra fixBool
-
- noFPU3 bsr dic[Fcmp1] ; Setup
- push.w #8 ; Code for FCMPX
- exg a6,a7
- call pack4
- exg a6,a7
- sge d2
- bra fixBool
- ;code
-
- $ 3F1D :FPcmp F0<
- ToCode
- tst.b 3(dic[FPU?])
- beq.s noFPU4
- pop.l a0
- ftst.x (a0),fp0
- bsr dic[(fltDisp)]
- fslt d2
- bra fixBool
-
- noFPU4 bsr dic[Fcmp1] ; Setup
- push.w #8 ; Code for FCMPX
- exg a6,a7
- call pack4
- exg a6,a7
- slt d2
- bra fixBool
- ;code
-
- $ 3F1F :FPcmp F0<=
- ToCode
- tst.b 3(dic[FPU?])
- beq.s noFPU5
- pop.l a0
- ftst.x (a0),fp0
- bsr dic[(fltDisp)]
- fsle d2
- bra fixBool
-
- noFPU5 bsr dic[Fcmp1] ; Setup
- push.w #8 ; Code for FCMPX
- exg a6,a7
- call pack4
- exg a6,a7
- sle d2
- bra fixBool
- ;code
-
- $ 3F1E :FPcmp F0>
- ToCode
- tst.b 3(dic[FPU?])
- beq.s noFPU6
- pop.l a0
- ftst.x (a0),fp0
- bsr dic[(fltDisp)]
- fsgt d2
- bra fixBool
-
- noFPU6 bsr dic[Fcmp1] ; Setup
- push.w #8 ; Code for FCMPX
- exg a6,a7
- call pack4
- exg a6,a7
- sgt d2
- bra fixBool
- ;code
-
- \ =============== Arithmetic operators ==============
-
- :code FOP2 \ ( flt0 flt1 -- flt0 addr1 addr0 ) Subroutine to set up for
- \ 2-operand operation, where flt0 takes the result.
- loc
- pop.l a0 ; A0 -> flt1
- move.l (a6),a1 ; A1 -> flt0. Also leave on stk for result.
- move.w (a0)+,(a0) ; Convert both to 80-bit SANE format
- move.w (a1)+,(a1)
- push.l a0 ; Push addrs for SANE call. Note SANE
- push.l a1 ; operands are reversed.
- subq #2,a0 ; Restore original flt1 addr to A0 for (fltDisp)
- bra dic[(fltDisp)] ; Kill flt1 (but data still valid)
- ;code
-
- :code FOP1
- move.l (a6),a0
- move.w (a0)+,(a0)
- push.l a0
- ;code
-
- :code ADJUST_RESULT \ ( flt -- flt )
- move.l (a6),a0
- move.w 2(a0),(a0)
- clr.w 2(a0)
- ;code
-
-
- \ ( f1 f2 -- f1<op>f2 ) Result gets stored in f1's data.
-
- $ 41 :fp2 F+
- ToCode
- loc
- tst.b 3(dic[FPU?])
- beq.s noFPU
- pop.l a0
- move.l (a6),a1
- fmove.x (a1),fp0
- fadd.x (a0),fp0
- bsr dic[(fltDisp)]
- move.l (a6),a1
- fmove.x fp0,(a1)
- rts
-
- noFPU bsr.s dic[fop2] ; Setup
- clr.w -(a6) ; Code for FADDX
- exg a6,a7
- call pack4
- exg a6,a7
- bra dic[adjust_result]
- ;code
-
-
- $ 48 :fp2 F-
- ToCode
- loc
- tst.b 3(dic[FPU?])
- beq.s noFPU
- pop.l a0
- move.l (a6),a1
- fmove.x (a1),fp0
- fsub.x (a0),fp0
- bsr dic[(fltDisp)]
- move.l (a6),a1
- fmove.x fp0,(a1)
- rts
-
- noFPU bsr dic[fop2] ; Setup
- push.w #2 ; Code for FSUBX
- exg a6,a7
- call pack4
- exg a6,a7
- bra dic[adjust_result]
- ;code
-
- $ 42 :fp2 F*
- ToCode
- loc
- tst.b 3(dic[FPU?])
- beq.s noFPU
- pop.l a0
- move.l (a6),a1
- fmove.x (a1),fp0
- fmul.x (a0),fp0
- bsr dic[(fltDisp)]
- move.l (a6),a1
- fmove.x fp0,(a1)
- rts
-
- noFPU bsr dic[fop2] ; Setup
- push.w #4 ; Code for FMULX
- exg a6,a7
- call pack4
- exg a6,a7
- bra dic[adjust_result]
- ;code
-
- $ 49 :fp2 F/
- ToCode
- loc
- tst.b 3(dic[FPU?])
- beq.s noFPU
- pop.l a0
- move.l (a6),a1
- fmove.x (a1),fp0
- fdiv.x (a0),fp0
- bsr dic[(fltDisp)]
- move.l (a6),a1
- fmove.x fp0,(a1)
- rts
-
- noFPU bsr dic[fop2] ; Setup
- push.w #6 ; Code for FDIVX
- exg a6,a7
- call pack4
- exg a6,a7
- bra dic[adjust_result]
- ;code
-
-
- \ ============= Monadic operations ==============
-
- \ FNEGATE and FABS simply operate on the sign bit, so we don't need to
- \ call SANE at all. The SANE manual actually recommends this.
-
- $ 55 :fp1 FNEGATE
- toCode
- move.l (a6),a0
- bchg #7,(a0)
- ;code
-
- $ 54 :fp1 FABS
- toCode
- move.l (a6),a0
- bclr #7,(a0)
- ;code
-
-
- $ 5A :fp1 SQRT
- ToCode
- loc
- tst.b 3(dic[FPU?])
- beq.s noFPU
- move.l (a6),a0
- fsqrt.x (a0),fp0
- fmove.x fp0,(a0)
- rts
-
- noFPU move.l (a6),a0
- move.w (a0)+,(a0)
- push.l a0
- exg a6,a7
- move.w #$12,-(a7) ; FSQRTX
- call pack4
- exg a6,a7
- bra dic[adjust_result]
- ;code
-
- hex
-
- : ROUND fop1 w 14 call pack4 adjust_result ;
- : TRUNC fop1 w 16 call pack4 adjust_result ;
- : LOGBIN fop1 w 1A call pack4 adjust_result ;
-
- decimal
-
- :code SCALEBIN \ ( x n -- x*(2**n) )
- loc
- pop.l hi
- move.l (a6),a0
- exg a6,a7
- pea lo
- move.w (a0)+,(a0)
- move.l a0,-(a7)
- move.w #$18,-(a7) ; FSCALBX
- call pack4
- exg a6,a7
- bra dic[adjust_result]
-
- hi dc.w 0
- lo dc.w 0
- ;code
-
-
- \ =========== Conversion to/from integers ============
-
- :code FLOAT> \ ( flt -- int32 )
-
- \ Special note: the 68040's integrated FP doesn't implement
- \ FINTRZ -- so it's handled via a trap. We definitely need to
- \ avoid this instruction!!! The conversion can simply be done
- \ by FMOVEint the float to a D register.
-
- move.l (a6),d2 ; Source float
- move.l d2,a0
- bsr dic[(fltDisp)] ; Kill it
- move.l d2,a0
- move.b 3(dic[useFPU?]),d0
- beq.s noFPU
- fmove.x (a0),fp0 ; get the number
- fmove.l fp0,(a6) ; convert to integer
- rts
-
- noFPU move.w (a0)+,(a0)
- move.l a6,d0 ; Save result cell addr
- push.l a0 ; Source (the float data)
- push.l d0 ; Dest (the result cell)
- push.w #$2810 ; Extended to Longint
- exg a6,a7
- call pack4
- exg a6,a7
- ;code
-
-
- :code FLOAT>D \ ( flt -- int64 ) We've added this in case someone
- \ needs to convert to a double integer. SANE Comp
- \ format is essentially a double integer (the only
- \ difference is the special NaN value
- \ $8000 0000 0000 0000)
-
- move.l (a6),d2 ; Source float
- move.l d2,a0
- bsr dic[(fltDisp)] ; Kill it
- move.l d2,a0
- move.w (a0)+,(a0)
- subq #4,a6 ; Make room for double result cell
- move.l a6,d0 ; Save result cell addr
- push.l a0 ; Source (the float data)
- push.l d0 ; Dest (the result cell)
- push.w #$3010 ; Extended to Comp
- exg a6,a7
- call pack4
- exg a6,a7
- ;code
-
-
- :code >FLOAT \ ( int32 -- flt )
- push.l a6 ; Push ptr to the longint
- bsr dic[(fltNew)] ; New float to A0
- move.l a0,d2 ; Save in D2
- addq.l #2,d2
- push.l d2
- push.w #$280E ; Longint to Extended
- exg a6,a7
- call pack4
- exg a6,a7
- move.l d2,a0
- move.w (a0),-(a0)
- clr.w 2(a0)
- move.l a0,(a6) ; Replace the long cell with
- ; float ptr
- ;code
-
- :code D>FLOAT \ ( int64 -- flt )
- push.l a6 ; Push ptr to the longint
- bsr dic[(fltNew)] ; New float to A0
- move.l a0,d2 ; Save in D2
- addq.l #2,d2
- push.l d2
- push.w #$300E ; Comp to Extended
- exg a6,a7
- call pack4
- exg a6,a7
- addq #4,a6
- move.l d2,a0
- move.w (a0),-(a0)
- clr.w 2(a0)
- move.l a0,(a6) ; Replace the double cell with
- ; float ptr
- ;code
-
- \ ============= Environmental control =============
-
- 0 value TMP
-
- :code GETENV \ ( -- env )
- exg a6,a7
- pea 2(dic[tmp])
- move.w #3,-(a7) ; FGETENV
- call pack4
- exg a6,a7
- moveq #0,d0
- move.w 2(dic[tmp]),d0
- push.l d0
- ;code
-
- :code SETENV \ ( env -- )
- pop.l dic[tmp]
- exg a6,a7
- pea 2(dic[tmp])
- move.w #1,-(a7) ; FSETENV
- call pack4
- exg a6,a7
- ;code
-
- \ =========== Masks for environment word ===========
-
- hex
-
- \ Rounding
-
- 2000 constant RoundUp
- 4000 constant RoundDown
- 6000 constant RoundToZero
-
- \ Exception flags
-
- 0100 constant Invalid
- 0200 constant Underflow
- 0400 constant Overflow
- 0800 constant Zdivide
- 1000 constant Inexact
-
- \ Halts
-
- 0001 constant InvHalt
- 0002 constant UfHalt
- 0004 constant OvHalt
- 0008 constant ZDHalt
- 0010 constant InxHalt
-
- decimal
-
- : SETHALT \ ( proc-addr -- )
- -> tmp ['] tmp w 5 call pack4 ;
-
- : GETHALT \ ( -- proc-addr )
- ['] tmp w 7 call pack4 tmp ;
-
-
- :proc FPERR ." FP error" cr
- i->l ." opcode " .h cr
- ." dst addr " .h cr
- ." src addr " .h cr
- ." src2 addr " .h cr
- ." misc rec ptr " .h cr ;proc
-
- ' FPerr sethalt
-
-
- \ ===================================
-
- \ FP named parms and locals
-
- \ ===================================
-
- \ In Mops, parms/locals are in D4-D7, and in the ExtraLocals area.
- \ Any floating locals have the float ptr in the D reg or XL location.
- \ To fetch a floating local, we compile
- \
- \ move.l <whatever>,A1
- \ jsr Lfloat
- \
- \ and to store or whatever to a floating local, we compile
- \
- \ move.l <whatever>,D2
- \ move.w #<opcode>,D1
- \ jsr ToLfloat
- \ move.l D2,<whatever>
- \
- \ Handlers does the hard work of generating this code (which isn't very
- \ hard, really). Lfloat and ToLfloat are forward defined in the nucleus,
- \ and are resolved here.
- \ Note also, that for F@ which we use for some floating array accesses,
- \ we JSR to Lfloat+8, thus skipping the check for the status word that
- \ precedes scalar floats.
-
- init: fltMem \ In case we're reloading
-
- :code FPOPS
- fadd.x (a0),fp0
- rts
- nop
- fsub.x (a0),fp0
- rts
- nop
- fmul.x (a0),fp0
- rts
- nop
- fdiv.x (a0),fp0
- ;code
-
- :code (LFLOAT)
- loc
- cmpi.w #1,-2(a1) ; Check source
- bne.s noflt
- ; F@ comes in here.
- bsr dic[(fltNew)] ; Get new float to A0
- push.l a0 ; Push as result
- movit movem.l (a1),d0-d2 ; Move data
- movem.l d0-d2,(a0)
- rts
-
- noflt move.l a1,a0
- bra dic[NoFloat]
- ;code
-
- :code (TOLFLOAT)
- tst.l d1
- bpl.s operate
- tst.l d2
- beq.s noDisp
- move.l d2,a0
- bsr dic[(fltDisp)]
- noDisp pop.l d2
- rts
-
- operate tst.l d2
- beq dic[notInit]
- oprt1 cmpi.w #$003E,d1
- bhs.s AbsNeg
- tst.b 3(dic[FPU?])
- beq.s noFPU
-
- move.l d2,a0
- fmove.x (a0),fp0
- move.l (a6)+,a0
- lea dic[FPops],a1
- lsl.w #2,d1
- jsr 0(a1,d1.w)
- bsr dic[(fltDisp)] ; Do Fxxx (A0),FP0
- move.l d2,a0
- fmove.x fp0,(a0)
- rts
-
- AbsNeg move.l d2,a0 ; Doesn't change CC
- bhi.s Neg
- bclr #7,(a0)
- rts
-
- Neg bchg #7,(a0)
- rts
-
- noFPU move.l (a6),a0
- bsr dic[(fltDisp)]
- move.l (a6),a0
- move.w (a0)+,(a0)
- move.l a0,(a6)
- move.l d2,a0
- move.w (a0)+,(a0)
- push.l a0
- push.w d1
- exg a6,a7
- call pack4
- exg a6,a7
- move.l d2,a0
- move.w 2(a0),(a0)
- clr.w 2(a0)
- ;code
-
- :code (TOFVAL)
- move.l a1,d2
- tst.w d1
- bpl oprt1
- pop.l a0
- movem.l (a0),d0-d2
- movem.l d0-d2,(a1)
- bra dic[(fltDisp)]
- ;code
-
- \ (LFDISP) disposes of floating locals and parms at the end of a definition.
- \ D2 = FltFlg, modified and shifted to exclude any operands in FP regs, so
- \ that the rightmost bit always means D4, and so on. This longword has a
- \ bit set for every operand we need to dispose.
-
- :code (LFDISP)
- loc
- lsr.l #1,d2
- bcc.s chkd5a
- tst.l d4
- beq.s chkd5
- move.l d4,a0
- bsr dic[(fltDisp)]
-
- chkd5 tst.l d2
- chkd5a beq.s end
- lsr.l #1,d2
- bcc.s chkd6a
- tst.l d5
- beq.s chkd6
- move.l d5,a0
- bsr dic[(fltDisp)]
-
- chkd6 tst.l d2
- chkd6a beq.s end
- lsr.l #1,d2
- bcc.s chkd7a
- tst.l d6
- beq.s chkd7
- move.l d6,a0
- bsr dic[(fltDisp)]
-
- chkd7 tst.l d2
- chkd7a beq.s end
- lsr.l #1,d2
- bcc.s chkXLa
- tst.l d7
- beq.s chkXL
- move.l d7,a0
- bsr dic[(fltDisp)]
-
- chkXL tst.l d2
- chkXLa beq.s end
- lea dic[ExtraLocals],a1
-
- XLloop lsr.l #1,d2
- bcc.s XLnxta
- tst.l (a1)
- beq.s XLnxt
- move.l (a1),a0
- bsr dic[(fltDisp)]
-
- XLnxt tst.l d2
- XLnxta beq.s end
- addq.l #4,a1
- bra.s XLloop
- end
- ;code
-
- \ ====================================
-
- \ Fvalues and Fcons
-
- \ ====================================
-
- \ In Mops, we handle Fvalues and Fcons along the same lines as floating
- \ locals (which is logical). Thus, to fetch an Fvalue/Fconstant, we compile
- \
- \ lea <addr>,a1
- \ jsr Lfloat
- \
- \ and to store or whatever to a floating Value, we compile
- \
- \ lea <addr>,a1
- \ move.w #<opcode>,d1
- \ jsr ToFval
- \
- \ As usual, Handlers takes care of this for us. Here, we just have to make
- \ sure that Fvalues and Fcons get the right handler code. We also put a
- \ "1" word in front of the float, so that Lfloat and ToLfloat won't think
- \ it's an error. They handle floating named parameters as well, so they do
- \ need to check.
-
- \ An FCRcon is essentially an Fcon, but is used for constants that are in
- \ the 68881/2 ROM. If we're compiling FPU code we use the ROM version which
- \ is a lot faster. But the floating value is stored in the dic as for an
- \ Fcon as well in case there's no FPU.
-
- : FLIT, \ ( flt -- )
- \ Writes a float into dictionary: analogous to , or c,
- \ We omit the 2 unused bytes. If we're compiling FPU code,
- \ we call CompFPUL instead of coming here.
- dup w@ here w! 2 allot
- dup 4+ here 8 cmove 8 allot fdrop ;
-
- : FCON, \ ( flt -- )
- \ As for FLIT, but we include the 2 unused bytes. We handle
- \ FCONs and FVALs this way, since they are operated on by the
- \ same code as for floating locals.
- dup here 12 cmove 12 allot fdrop ;
-
- : FVALUE
- header
- FvalCode w, \ Handler code
- 1 w, fcon, ;
-
- : FCON
- header
- -76 w, \ Fcon handler code
- 1 w, fcon, ;
-
- : FCRCON \ ( offs -- )
- header
- -88 w, \ FCRcon handler code
- w, \ ROM offset
- 1 w, fcon, ;
-
- header F@
- -100 w, \ handler code
- xinfoMk w, \ "extra non-code info" of zero length means
- 0 w, \ compilation only
-
-
- header F!
- -102 w, \ handler code
- xinfoMk w, \ "extra non-code info" of zero length means
- 0 w, \ compilation only
-
-
- \ =====================================
- \ FP to/from decimal conversion
- \ =====================================
-
- \ Some useful constants:
-
- 256 constant NEG
- 0 constant POS
-
- 256 constant FixedDecimal
- 0 constant FloatDecimal
-
- false value VALID? \ Needed by the scanner. But we never
- \ use it otherwise.
-
- :code FP> \ ( flt -- flt )
- move.l (a6),a0
- cmpi.w #1,-2(a0)
- bne dic[noFloat]
- move.w (a0)+,(a0)
- ;code
-
-
- :class DEC super{ object }
-
- \ SANE Record Decimal ( x = (-1)^sign * 10^exp * digits )
-
- int SIGN
- int EXP
- 22 bytes DIGITS \ to fake string[20] ; 22 to make even
-
- int INDEX \ Used by the scanner.
-
- \ SANE Record DecForm
-
- int STYLE
- int #DIGITS \ # of sig digits,if float;
- \ # dec. places,if fixed.
- :m CLEAR:
- addr: sign 26 erase ;m
-
- :m EINIT: clear: self FloatDecimal put: style 19 put: #digits ;m
- :m FINIT: clear: self FixedDecimal put: style ;m
-
- :m SETSTYLE: put: style ;m
- :m SET#DIGITS: put: #digits ;m
- :m SETEXP: put: exp ;m
- :m EXP: get: exp ;m
- :m SIGN: get: sign ;m
-
- :m ZERO: \ Puts a zero in decimal record
- clear: self $ 0130 addr: #digits w! ;m
-
- :m >FLOAT: { \ flt -- flt }
- ^base \ Addr of decimal record
- new: fltMem -> flt flt 2+ \ Destination address
- $ 0009 \ FFEXT FOD2B + -- Opcode for decimal to
- \ binary; dest=extended
- fp68k flt adjust_result
- ;m
-
- \ =>: converts the passed-in float to decimal.
-
- :m =>: { flt -- }
- addr: style \ Addr of decform record
- flt FP> 2+ \ Addr of source
- ^base \ Addr of decimal record
- $ 000B \ FFEXT FOB2D + -- Opcode for binary to
- \ decimal; source=extended
- fp68k flt fdrop ;m \ Call SANE, dispose of float
-
- \ Ascii input
-
- :m SCAN: \ ( addr len -- )
- str255 1+
- clear: index addr: index
- ^base ['] valid? 3+ w 2 call Pack7 ;m
-
- :m CONV?: { addr len -- b }
- \ Attempts to convert the passed-in string, using SCAN:.
- \ Returns True if all the input was read. Otherwise
- \ we assume the terminating (non-scanned) character is
- \ invalid, and return False.
- addr len scan: self
- get: index len = ;m
-
- \ Ascii output
-
- :m FORMAT: \ ( -- addr len )
- addr: style ^base pad w 3 call Pack7
- pad count ;m
-
- :m PRINT:
- format: self type ;m
-
- :m DUMP:
- ." sign: " get: sign IF & - ELSE & + THEN emit cr
- ." exp: " get: exp . cr
- addr: digits count type cr
- ." style: " get: style IF ." fixed" ELSE ." float" THEN cr
- ." index: " get: index . cr
- ." #digits: " get: #digits . cr ;m
-
- ;class
-
- dec theDec
-
- : #DIGITS set#digits: theDec ;
-
- : E.R { flt wid \ svOut -- }
- out -> svOut
- floatDecimal setStyle: theDec
- wid 6 - #digits \ Allow for point, sign, and e+nn
- flt =>: theDec
- print: theDec
- wid out svOut - - spaces ;
-
- : E. 26 e.r ;
-
- : F.R { flt wid \ #dig svOut -- }
- out -> svOut
- floatDecimal setStyle: theDec
- wid 2- #digits \ Allow for sign and dec point
- flt =>: theDec
- fixedDecimal setStyle: theDec
- exp: theDec negate dup -> #dig #digits
- sign: theDec NIF space THEN
- #dig NIF space THEN \ In this case, no dec point
- print: theDec
- wid out svOut - - spaces ;
-
- : FCONV? { addr len \ flt -- flt T | -- F }
- \ Converts the passed-in ASCII string to
- \ floating, if possible. I like this name better
- \ than ATOF which Neon had, but change it back if
- \ you want to.
- addr len conv?: thedec NIF false EXIT THEN
- new: fltMem -> flt
- thedec flt 2+ 9 FP68K
- flt adjust_result true ;
-
-
- \ ==============================
-
- \ Interpretation
-
- \ ==============================
-
-
- : FNUMBER \ ( addr -- flt T | -- F )
- \ Attempts to convert token at addr to a float.
- count fconv? ;
-
-
- : FLITERAL { flt -- } \ Compiles an in-line float.
- useFPU?
- IF flt 8 + @ flt 4+ @ flt @ compFPUL flt fdrop
- ELSE postpone flit flt flit,
- THEN ;
-
-
- : (FNUM) { addr -- flt T | -- addr F }
- \ Checks if string at Here is a float, defined by containing
- \ a decimal point. Error if there is a point, but not a legal
- \ float.
- addr count & . scan nip NIF addr false EXIT THEN
- addr fnumber ?notFound
- state IF fLiteral THEN true ;
-
-
- : FLOAT? { adr -- b }
- adr 1 and IF false EXIT THEN
- adr ['] fltmem >
- adr ['] (fltnew) <
- and NIF false EXIT THEN
- adr 2- w@ 1 = ;
-
-
- ' (Lfloat) -> ^Lfloat \ So f@ below will compile properly
-
- : (.CELLF) { adr -- } \ FP version of stack cell typing word
- adr @ float?
- IF adr @ f@ e.
- ELSE adr @ .
- THEN ;
-
-
- : FPINIT \ Initialization word for FP package
- init: fltMem
- ['] (fltNew) -> ^FPnew
- ['] (fltDisp) -> ^FPdisp
- ['] (fltDisp2) -> ^FPdisp2
- ['] (Lfloat) -> ^Lfloat
- ['] (ToLfloat) -> ^ToLfloat
- ['] (ToFval) -> ^ToFval
- ['] (LFdisp) -> ^LFdisp
- ['] (FPUlit) -> ^FPULit
- ['] (.cellf) -> .cell
- ;
-
-
- : CLEANFLOAT \ New error word
- cl3 init: fltMem ;
-
-
- : MOPS>FLT
- ['] (Fnum) -> Fnum?
- ['] FPinit add: init_actions
- ['] cleanFloat -> abortVec ;
-
-
- : MOPS>INT
- 0 -> Fnum?
- ['] FPinit removeXT: init_actions
- ['] cl3 -> abortVec ;
-
- FPinit mops>flt
-
-
- \ =================================
- \ Transcendentals
- \ =================================
-
- :code LN \ Natural log
- move.l (a6),a0
- move.w (a0)+,(a0)
- push.l a0
- exg a6,a7
- clr.w -(a7) ; FLNX code
- call pack5
- exg a6,a7
- bra dic[adjust_result]
- ;code
-
- :code LOG2 \ Base 2 log
- move.l (a6),a0
- move.w (a0)+,(a0)
- push.l a0
- exg a6,a7
- move.w #2,-(a7) ; FLOG2X
- call pack5
- exg a6,a7
- bra dic[adjust_result]
- ;code
-
- :code LN1 \ ln(1+x)
- move.l (a6),a0
- move.w (a0)+,(a0)
- push.l a0
- exg a6,a7
- move.w #4,-(a7) ; FLN1X
- call pack5
- exg a6,a7
- bra dic[adjust_result]
- ;code
-
- :code LOG21 \ log2(1+x). I don't think LOG21 is a very helpful name
- \ (pure computerese), but I guess we're stuck with it.
- move.l (a6),a0
- move.w (a0)+,(a0)
- push.l a0
- exg a6,a7
- move.w #6,-(a7) ; FLOG21X
- call pack5
- exg a6,a7
- bra dic[adjust_result]
- ;code
-
- :code EXP \ Base e exponential
- move.l (a6),a0
- move.w (a0)+,(a0)
- push.l a0
- exg a6,a7
- move.w #8,-(a7) ; FEXPX
- call pack5
- exg a6,a7
- bra dic[adjust_result]
- ;code
-
- :code EXP2 \ Base 2 exponential
- move.l (a6),a0
- move.w (a0)+,(a0)
- push.l a0
- exg a6,a7
- move.w #$A,-(a7) ; FEXP2X
- call pack5
- exg a6,a7
- bra dic[adjust_result]
- ;code
-
- :code EXP1 \ e**x - 1
- move.l (a6),a0
- move.w (a0)+,(a0)
- push.l a0
- exg a6,a7
- move.w #$C,-(a7) ; FEXP1X
- call pack5
- exg a6,a7
- bra dic[adjust_result]
- ;code
-
- :code EXP21 \ 2**x - 1
- move.l (a6),a0
- move.w (a0)+,(a0)
- push.l a0
- exg a6,a7
- move.w #$E,-(a7) ; FEXP21X
- call pack5
- exg a6,a7
- bra dic[adjust_result]
- ;code
-
- :code **N \ ( x n -- x**n ) Integer exponentiation. This wasn't
- \ in Neon, but might be useful. Note this operation
- \ ignores the high-order 16 bits of n.
- loc
- pop.l hi
- move.l (a6),a0
- move.w (a0)+,(a0)
- exg a6,a7
- pea lo
- move.l a0,-(a7)
- move.w #$8010,-(a7) ; FXPWRI
- call pack5
- exg a6,a7
- bra dic[adjust_result]
-
- hi dc.w 0
- lo dc.w 0
- ;code
-
- :code F** \ ( x y -- x**y ) General exponentiation - takes 2 floats.
- \ Here I think the Neon name was crazy. But we've still
- \ got it below for compatibility.
- bsr dic[fop2]
- move.w #$8012,-(a6) ; FXPWRY
- exg a6,a7
- call pack5
- exg a6,a7
- bra dic[adjust_result]
- ;code
-
- :code X**Y \ For Neon compatibility
- bra.s dic[f**]
- ;code
-
-
- \ Financial functions. I never have enough finances to need these myself.
-
- :code COMPOUND \ ( rate #periods -- compound_interest)
-
- bsr dic[(fltNew)] ; New float to A0 (will be
- ; result). Must get before
- move.l a0,d2 ; killing src floats. Save in D2
- pop.l a0
- pop.l a1
- move.w (a0)+,(a0)
- move.w (a1)+,(a1)
- push.l a1
- push.l a0
- subq #2,a0
- subq #2,a1
- bsr dic[(fltDisp2)] ; Kill source floats
- move.l d2,a0
- move.w (a0)+,(a0)
- push.l a0 ; Destination
- push.w #$C014
- exg a6,a7
- call pack5
- exg a6,a7
- push.l d2
- bsr dic[adjust_result]
- ;code
-
- :code ANNUITY \ ( rate #periods -- annuity)
- bsr dic[(fltNew)] ; New float to A0 (will be
- ; result). Must get before
- move.l a0,d2 ; killing src floats. Save in D2
- pop.l a0
- pop.l a1
- move.w (a0)+,(a0)
- move.w (a1)+,(a1)
- push.l a1
- push.l a0
- subq #2,a0
- subq #2,a1
- bsr dic[(fltDisp2)] ; Kill source floats
- move.l d2,a0
- move.w (a0)+,(a0)
- push.l a0 ; Destination
- push.w #$C016
- exg a6,a7
- call pack5
- exg a6,a7
- push.l d2
- bsr dic[adjust_result]
- ;code
-
-
- \ Trig functions.
-
- $ 56 :fp1 SIN
- ToCode
- loc
- tst.b 3(dic[FPU?])
- beq.s noFPU
- move.l (a6),a0
- fsin.x (a0),fp0
- fmove.x fp0,(a0)
- rts
-
- noFPU move.l (a6),a0
- move.w (a0)+,(a0)
- push.l a0
- exg a6,a7
- move.w #$18,-(a7) ; FSINX
- call pack5
- exg a6,a7
- bra dic[adjust_result]
- ;code
-
- $ 57 :fp1 COS
- ToCode
- loc
- tst.b 3(dic[FPU?])
- beq.s noFPU
- move.l (a6),a0
- fcos.x (a0),fp0
- fmove.x fp0,(a0)
- rts
-
- noFPU move.l (a6),a0
- move.w (a0)+,(a0)
- push.l a0
- exg a6,a7
- move.w #$1A,-(a7) ; FCOSX
- call pack5
- exg a6,a7
- bra dic[adjust_result]
- ;code
-
- $ 58 :fp1 TAN
- ToCode
- loc
- tst.b 3(dic[FPU?])
- beq.s noFPU
- move.l (a6),a0
- ftan.x (a0),fp0
- fmove.x fp0,(a0)
- rts
-
- noFPU move.l (a6),a0
- move.w (a0)+,(a0)
- push.l a0
- exg a6,a7
- move.w #$1C,-(a7) ; FTANX
- call pack5
- exg a6,a7
- bra dic[adjust_result]
- ;code
-
- $ 59 :fp1 ARCTAN
- ToCode
- loc
- tst.b 3(dic[FPU?])
- beq.s noFPU
- move.l (a6),a0
- fatan.x (a0),fp0
- fmove.x fp0,(a0)
- rts
-
- noFPU move.l (a6),a0
- move.w (a0)+,(a0)
- push.l a0
- exg a6,a7
- move.w #$1E,-(a7) ; FATANX
- call pack5
- exg a6,a7
- bra dic[adjust_result]
- ;code
-
-
- :code FRAND \ floating-pt random number routine
- move.l (a6),a0
- move.w (a0)+,(a0)
- push.l a0
- exg a6,a7
- move.w #$20,-(a7)
- call pack5
- exg a6,a7
- bra dic[adjust_result]
- ;code
-
-
- \ ======================================
- \ Sundry useful constants and operations
- \ ======================================
-
- 1.0 fcon 1.0
- 0.0 fcon 0.0
- 1.0 exp fcon E
- 10.0 ln fcon LN(10)
-
- 0.0 fcon PI \ Not the real value yet!!!
- 0.0 fcon UNDEF \ Ditto
-
- : SetPi { \ adr -- } \ Sets up PI according to the value in the
- \ 68882 ROM.
- ['] pi -> adr
- $ 40000000 adr 2+ !
- $ C90FDAA2 adr 6 + !
- $ 2168C235 adr 10 + ! ;
-
- : SetUndef { \ adr -- } \ Sets up UNDEF to NAN(255).
- ['] undef -> adr
- $ 7FFF0000 adr 2+ !
- $ FFFFFFFF adr 6 + !
- $ FFFFFFFF adr 10 + ! ;
-
- SetPi SetUndef forget SetPi
-
- \ 0 FCRcon PI
-
- : 1/X 1.0 swap f/ ;
-
- : LOG \ ( x -- log(x) ) Log base 10 of x
- ln ln(10) f/ ;
-
- : ANTILOG \ ( x -- antilog(x) ) Antilog ( 10^x ) of x
- ln(10) f* exp ;
-
- : COT \ ( x -- cot(x) ) Cotangent of x
- tan 1/x ;
-
- : DEG2RAD \ ( deg -- rad ) Converts degrees to radians
- pi f* 180. f/ ;
-
- : RAD2DEG \ ( rad -- deg ) Converts radians to degrees
- 180. f* PI f/ ;
-
-
- \ ===================================
- \ Class Float
- \ ===================================
-
- \ Class Float allows a floating value to be a high-level object, which
- \ means it can be an ivar. There is something of a performance
- \ penalty if FPU code is being generated, since a Float object must
- \ be in main memory, which increases the amount of data movement
- \ between the FPU and the integer unit. This is slow on a 68030, but
- \ shouldn't be such a problem on a 68040.
-
-
- :class FLOAT super{ object }
-
- 12 bytes data
-
- :m GET: \ ( -- x ) Pushes private data onto stack
- inline{ obj f@} ^base f@ ;m
-
- :m PUT: \ ( x -- ) store float into private data
- inline{ obj f!} ^base f! ;m
-
- :m ->: \ ( float -- ) Assigns value of passed-in Float to this Float
- inline{ f@ obj f!}
- f@ ^base f! ;m
-
-
- \ ----- Arithmetic operations take a stack float (not a Float obj)
-
- :m +:
- inline{ obj f@ f+ obj f!}
- ^base f@ f+ ^base f! ;m
-
- :m -:
- inline{ obj f@ f- obj f!}
- ^base f@ f- ^base f! ;m
-
- :m *:
- inline{ obj f@ f* obj f!}
- ^base f@ f* ^base f! ;m
-
- :m /:
- inline{ obj f@ f/ obj f!}
- ^base f@ f/ ^base f! ;m
-
- :m SIN: \ ( -- sin ) returns sine of object
- inline{ obj f@ sin}
- ^base f@ sin ;m
-
- :m COS: \ ( -- cos ) returns cosine of object
- inline{ obj f@ cos}
- ^base f@ cos ;m
-
- :m TAN: \ ( -- tan ) returns tangent of object
- inline{ obj f@ tan}
- ^base f@ tan ;m
-
- :m ARCTAN: \ ( -- arcTan) returns arctangent of object
- inline{ obj f@ arctan}
- ^base f@ arctan ;m
-
- :m LN: \ ( -- ln) returns natural log of object
- inline{ obj f@ ln}
- ^base f@ ln ;m
-
- :m EXP: \ ( -- exp ) returns exp of object
- inline{ obj f@ exp}
- ^base f@ exp ;m
-
- :m LOG: \ ( -- log ) returns log base 10 of object
- inline{ obj f@ log}
- ^base f@ log ;m
-
- :m ANTILOG: \ ( -- 10**x ) returns antilog of object
- inline{ obj f@ antilog}
- ^base f@ antilog ;m
-
- :m DEG: \ ( -- degrees ) converts radians to degrees
- inline{ obj f@ rad2deg}
- ^base f@ rad2deg ;m
-
- :m RAD: \ ( -- radians ) converts from radians to degrees
- inline{ obj f@ deg2rad}
- ^base f@ deg2rad ;m
-
- :m ABSVAL: \ ( -- abs ) Returns absolute value.
- inline{ obj f@ fabs}
- ^base f@ fabs ;m
-
- :mcode ABS: \ ( -- ) Replaces obj's data with its absolute. Doesn't
- \ return anything.
- bclr #7,(a2)
- ;mcode
-
- :m NEG: \ ( -- val ) Returns object value with sign negated
- inline{ obj f@ fnegate}
- ^base f@ fnegate ;m
-
- :mcode NEGATE: \ ( -- ) Negates the object's data. Doesn't return anything.
- bchg #7,(a2)
- ;mcode
-
- :m PRINT: ^base f@ e. ;m
-
- ;class
-
-
- \ =================================
- \ Floating arrays
- \ =================================
-
-
- :code (^ELEM) \ ( idx -- ) A subroutine to get the element addr to A1.
- loc
- pop.l d0 ; d0 = index
- move.l a2,a1
- add.w -2(a1),a1 ; now a1 -> ^class
- add.w -2(a1),a1 ; now a1 -> start of indexed area
- tst.w -4(a1) ; Skip bounds check if this is
- bne.s mul12 ; a LARGE farray
- chk -2(a1),d0 ; bounds check
- mul12 move.l d0,d1 ; mult by 12 and add to index base in a1
- add.l d1,d0
- add.l d1,d0
- asl.l #2,d0
- add.l d0,a1 ; Element addr to a1
- ;code
-
-
- :class FARRAY super{ indexed-obj } 12 indexed
-
- :mcode ^ELEM: \ ( idx -- addr )
- bsr.s dic[(^Elem)]
- push.l a1
- ;mcode
-
- :mcode AT:
- bsr dic[(^Elem)] ; Get element addr to a1
- bsr dic[(fltNew)] ; New float to a0
- push.l a0 ; Push it
- movem.l (a1),d0-d2
- movem.l d0-d2,(a0) ; Move data over
- ;mcode
-
- :mcode TO: \ ( flt idx -- )
- bsr dic[(^Elem)] ; Get element addr to a1
- pop.l a0
- movem.l (a0),d0-d2 ; Move data over
- movem.l d0-d2,(a1)
- bsr dic[(fltDisp)] ; Dispose of stack float
- ;mcode
-
- :m FILL: \ ( x -- ) Fills all elements with x
- limit 0 DO fdup i to: self LOOP fdrop ;m
-
- :m PRINT: \ Prints all elements
- limit: self 0 ?DO i dup 4 .r space at: self e. cr
- LOOP ;m
-
- :m CLASSINIT:
- undef
- limit: self FOR fdup i to: self NEXT fdrop ;m
-
- ;class
-