******************************************************************************
*       CyberPI 1.0  1996 by Sam Jordan
*       based on Pi_Warp 1.4 by Sam Jordan
*
*       Calculation of PI using the formula
*       PI = 4*44*arctan(1/57) + 4*7*arctan(1/239) + 4*12*arctan(1/682)
*            + 4*24*arctan(1/12943)
*       with
*       arctan(1/x) = (1/x) + (1/(3*x^3)) + (1/(5*x^5)) + ...
*
*       included 060 Support
*       included PowerPC Support
*
*       © 1997 HAAGE&PARTNER Computer GmbH
*
******************************************************************************

                mc68020

TRUE            =       -1
FALSE           =       0

NOOUTPUT        =       0
COUNTVALUE      =       100

;// includes
                include exec_lib.i
                include dos_lib.i
                include powerpc_lib.i

                include exec/execbase.i
                include exec/types.i
                include exec/memory.i
                include exec/nodes.i
                include dos/dos.i
                include debug.i
                include powerpc/powerpc.i
;;/
;// XREF / XDEF
                xref    BinToASCII
                xref    Calculation
                xref    BinToASCIIPPC
                xref    CalculationPPC
                xref    _LinkerDB

                xdef    Area_Quotient
                xdef    Area_Quotient2
                xdef    Area_Quotient3
                xdef    Area_Quotient4
                xdef    Area_ArcTan
                xdef    Area_Result
                xdef    Area_Q_Actual
                xdef    Len_Q_Actual
                xdef    Area_Q2_Actual
                xdef    Len_Q2_Actual
                xdef    Area_Q3_Actual
                xdef    Len_Q3_Actual
                xdef    Area_Q4_Actual
                xdef    Len_Q4_Actual
                xdef    Area_AT_Actual
                xdef    Len_AT_Actual
                xdef    Num_ArcTan_57
                xdef    Num_ArcTan_239
                xdef    Num_ArcTan_682
                xdef    Num_ArcTan_12943
                xdef    ConvertMem
                xdef    Count
                xdef    _060Flag
;;/

WRITEDBG        macro
                movem.l d0-d3/a0/a1,-(sp)
                move.l  _DOSBase,a6
                move.l  OutHandle,d1
                lea     \1,a0
                move.l  a0,d2
                move.l  #Len_\1,d3
                CALLDOS Write
                movem.l (sp)+,d0-d3/a0/a1
                endm


DB_DEBUG        set     DB_OFF

                near    a4,-1
                near    code

                section "code",code

;// start
                XDEF    _main
_main
                movem.l d0-a6,-(sp)
                lea     _LinkerDB,a4
                move.l  $4.w,_SysBase
                DB_OPENDEBUG
                DB_ALLOCDEBUG   DB1,10000
                DB_ALLOCGROUP   DB1,TEMP,<temp>,0
                IFEQ    DB_DEBUG-DB_ON
                DB_XDEF
                XDEF    DB1
                XDEF    TEMP
                ENDC

                OPENPOWERPC
                bsr     OpenLibs        ;open libraries
                beq.w   ErrorMessage
                bsr     CheckCPU        ;get cpu type
                beq.w   ErrorMessage    ;error when not 68020+
                move.l  #100,Count  ;default value (numbers of decimals)
                bsr     GetArgs         ;read the arguments
                beq.w   Exit
                tst.b   _PPCFlag
                bne.b   .noppc
                move.l  #CPU_Text1,CPU_OutPut
.noppc
                IFNE    NOOUTPUT
                move.l  #COUNTVALUE,Count
                ENDC

                move.l  Count,d0
                bsr     CalcAreaLen     ;calc the areasize
                bsr     GetMemory       ;alloc mem
                beq.w   ErrorMessage
                bsr     CreateTable     ;then create an ASCII-Table
                lea     Title_OutPut,a0
                bsr     DisplayText     ;displays the title message
                move.l  Count,d0
                move.l  Length_Area,d1
                move.l  Area,a0
                bsr     CalcPI          ;main calculation
                bsr     CalcTime        ;calculate time
                move.l  Area,a0
                move.l  Count,d0
                bsr     DisplayPI       ;display PI
                tst.b   _PPCFlag
                beq.b   .noppc1
                bsr     CheckPPCCPU
.noppc1
                lea     Accuracy_Value,a0
                move.l  Count,d0
                moveq   #10,d1
                bsr     BinToDec        ;converts the accuracy to ASCII
                lea     Accuracy_Output,a0
                bsr     DisplayText     ;displays the accuracy
                lea     CPU_OutPut,a0
                bsr     DisplayText     ;displays the CPU-type
                lea     Timing_Output,a0
                bsr     DisplayText     ;displays the timing statistics
Exit
                CLOSEPOWERPC
                DB_ADDVALUE     DB1,TEMP,Area_Quotient
                DB_ADDVALUE     DB1,TEMP,Area_Quotient2
                DB_ADDVALUE     DB1,TEMP,Area_Quotient3
                DB_ADDVALUE     DB1,TEMP,Area_Quotient4
                DB_ADDVALUE     DB1,TEMP,Area_ArcTan
                DB_ADDVALUE     DB1,TEMP,Area_Result
                DB_ADDVALUE     DB1,TEMP,Area_Q_Actual
                DB_ADDVALUE     DB1,TEMP,Area_Q2_Actual
                DB_ADDVALUE     DB1,TEMP,Area_Q3_Actual
                DB_ADDVALUE     DB1,TEMP,Area_Q4_Actual
                DB_ADDVALUE     DB1,TEMP,Area_AT_Actual
                lea     Area_Q_Actual,a0
                DB_ADDVALUE     DB1,TEMP,a0,Q
                lea     Area_Q2_Actual,a0
                DB_ADDVALUE     DB1,TEMP,a0,Q2
                lea     Area_Q3_Actual,a0
                DB_ADDVALUE     DB1,TEMP,a0,Q3
                lea     Area_Q4_Actual,a0
                DB_ADDVALUE     DB1,TEMP,a0,Q4
                lea     Area_AT_Actual,a0
                DB_ADDVALUE     DB1,TEMP,a0,AT
                DB_ADDVALUE     DB1,TEMP,Num_ArcTan_57
                DB_ADDVALUE     DB1,TEMP,Num_ArcTan_239
                DB_ADDVALUE     DB1,TEMP,Num_ArcTan_682
                DB_ADDVALUE     DB1,TEMP,Num_ArcTan_12943
                move.l  Area_Quotient,a0
                DB_ADDDUMP      DB1,TEMP,(a0),,100
                move.l  Area_Quotient2,a0
                DB_ADDDUMP      DB1,TEMP,(a0),,100
                move.l  Area_Quotient3,a0
                DB_ADDDUMP      DB1,TEMP,(a0),,100
                move.l  Area_Quotient4,a0
                DB_ADDDUMP      DB1,TEMP,(a0),,100
                move.l  Area_ArcTan,a0
                DB_ADDDUMP      DB1,TEMP,(a0),,100
                move.l  Area_Result,a0
                DB_ADDDUMP      DB1,TEMP,(a0),,100

                bsr     CloseAll        ;close libraries, free mem ...

                DB_WRITEDEBUG   DB1,<t:debug.txt>,<;//>,<;;/>,DB_ALL
                DB_FREEDEBUG    DB1
                DB_CLOSEDEBUG
                movem.l (sp)+,d0-a6
                moveq   #0,d0
                rts

ErrorMessage
                tst.l   OutHandle
                beq.w   Exit
                move.l  Error_Ptr,a0
                move.l  Error_Length,d0
                bsr     WriteErrorMessage
                bra.w   Exit
;;/
;// OpenLibs
******************************************************************************
*       d0 = OpenLibs
*
*       Opens all libraries
*
*       d0 [.L] = return value (0=error,-1=success)
******************************************************************************
OpenLibs
                move.l  $4.w,a6
                cmp     #36,$14(a6)     ;are we running under OS 2.0+ ?
                blt.w   Version_Error
                lea     dos_name,a1
                moveq   #36,d0
                CALLEXEC        OpenLibrary     ;open dos.library
                move.l  d0,_DOSBase
                beq.w   OpenDos_Error
                IFEQ    NOOUTPUT
                CALLDOS Output
                move.l  d0,OutHandle
                beq.b   Output_Error
                ENDC
OpenEnd
                rts
Output_Error
OpenDos_Error
                moveq   #0,d0
                bra.b   OpenEnd
Version_Error
                move.l  #Error_Version,Error_Ptr;os version is < 2.0
                move.l  #Len_Error_Version,Error_Length
                move.l  $4.w,a6
                lea     dos_name,a1
                moveq   #0,d0
                CALLEXEC        OpenLibrary     ;try to open dos.library V0
                move.l  d0,_DOSBase             ;(because of output)
                move.l  d0,a6
                CALLDOS Output
                move.l  d0,OutHandle
                moveq   #0,d0
                bra.b   OpenEnd
;;/
;// CheckCPU
******************************************************************************
*       d0 = CheckCPU
*
*       Looks for the CPU-type. If <68020 then return an error
*
*       d0 [.L] = return value (0=error,-1=success)
******************************************************************************
CheckCPU
                sf      _060Flag
                moveq   #-1,d1
                move.l  $4.w,a6
                lea     CPU_Text1,a0
                move    AttnFlags(a6),d0
                btst    #AFB_68020,d0
                beq.b   CPU_Error       ;error when not 68020+
                btst    #AFB_68030,d0
                beq.b   CPU_Done
                move.b  #"3",18(a0)
                btst    #AFB_68040,d0
                beq.b   CPU_Done
                move.b  #"4",18(a0)
                btst    #7,d0           ;68060-Bit not in include file yet
                beq.b   CPU_Done
                move.b  #"6",18(a0)
                st      _060Flag
CPU_Done
                move    d1,d0
                rts
CPU_Error
                move.l  #Error_CPU,Error_Ptr
                move.l  #Len_Error_CPU,Error_Length
                moveq   #0,d1
                bra.b   CPU_Done
;;/
;// CheckPPCCPU
******************************************************************************
*       d0 = CheckPPCCPU
*
*       Looks for the PPCCPU-type.
******************************************************************************
CheckPPCCPU
                CALLPOWERPC     GetCPU
                tst.l   d0
                beq.b   .nocpu
                lea     CPU_PPC,a1
                move.l  #"603 ",(a1)
                btst    #CPUB_603,d0
                bne.b   .nocpu
                move.l  #"603e",(a1)
                btst    #CPUB_603E,d0
                bne.b   .nocpu
                move.l  #"604 ",(a1)
                btst    #CPUB_604,d0
                bne.b   .nocpu
                move.l  #"604e",(a1)
                btst    #CPUB_604E,d0
                bne.b   .nocpu
                move.l  #"620 ",(a1)
                btst    #CPUB_620,d0
                bne.b   .nocpu
                move.l  #"    ",(a1)
.nocpu
                rts
;;/
;// GetArgs
******************************************************************************
*       d0 = GetArgs
*
*       Reads the arguments and does some error-handling
*
*       d0 [.L] = return value (0=error,-1=success)
******************************************************************************
GetArgs
                IFEQ    NOOUTPUT
                move.l  #Template,d1
                move.l  #Array,d2
                moveq   #0,d3
                CALLDOS ReadArgs
                move.l  d0,d5
                beq.b   Error_Arg
                lea     Array,a0
                tst.l   (a0)
                beq.b   Defaultvalue
                move.l  ([0.w,a0]),Count    ;get number of decimals
Defaultvalue
                sf      _PPCFlag
                tst.l   _PowerPCBase
                beq.b   .noppc
                st      _PPCFlag
                tst.l   4(a0)
                beq.b   .noppc
                sf      _PPCFlag
.noppc
                move.l  d5,d1
                CALLDOS FreeArgs
                ENDC
                moveq   #-1,d0
GetArgs_end
                rts
Error_Arg
                CALLDOS IoErr           ;get error code
                move.l  d0,d1
                moveq   #0,d2
                CALLDOS PrintFault      ;write error message
                moveq   #0,d0
                bra.b   GetArgs_end
;;/
;// GetMemory
******************************************************************************
*       d0 = GetMemory
*
*       Allocates memory
*
*       d0 [.L] = return value (0=error,-1=success)
******************************************************************************
GetMemory
                move.l  Length_Area,d0              ;now allocate the memory
                move.l  d0,d2
                lsl.l   #2,d0
                mulu.l  #6,d0
                add.l   #64,d0
                move.l  #MEMF_PUBLIC!MEMF_CLEAR,d1
                CALLEXEC        AllocVec        ;first the main memory
                move.l  d0,MemPtr
                beq.b   Memory_Error
                lsl.l   #2,d2
                add.l   #32,d0
                lea     Area_Quotient,a0
                moveq   #6-1,d7
GM_loop
                move.l  d0,(a0)+
                add.l   d2,d0
                dbra    d7,GM_loop

                move.l  #40000,d0
                move.l  #MEMF_PUBLIC!MEMF_CLEAR,d1
                CALLEXEC        AllocVec        ;now the ASCII-table-memory
                beq.b   Memory_Error
                move.l  d0,ConvertMem
                moveq   #-1,d0
AllocEnd
                rts
Memory_Error
                move.l  #Error_Mem,Error_Ptr
                move.l  #Len_Error_Mem,Error_Length
                moveq   #0,d0
                bra.b   AllocEnd
;;/
;// CloseAll
******************************************************************************
*       CloseAll
*
*       Closes all libraries and frees the memory
*
******************************************************************************
CloseAll
                movem.l d0/a0,-(sp)
                move.l  MemPtr,d0
                beq.b   FreeNext1
                move.l  d0,a1
                CALLEXEC        FreeVec
FreeNext1
                move.l  ConvertMem,d0
                beq.b   FreeNext2
                move.l  d0,a1
                CALLEXEC        FreeVec
FreeNext2
                move.l  _DOSBase,d0
                beq.b   NoDosBase
                move.l  d0,a1
                CALLEXEC        CloseLibrary
NoDosBase
                movem.l (sp)+,d0/a0
                rts
;;/
;// WriteErrorMessage
******************************************************************************
*       WriteErrorMessage (a0,d0)
*
*       Displays an errortext
*
*       a0 -> Text
*       d0 = Length
******************************************************************************
WriteErrorMessage
                move.l  _DOSBase,a6
                move.l  OutHandle,d1
                move.l  a0,d2
                move.l  d0,d3
                CALLDOS Write
                rts
;;/
;// DisplayText
******************************************************************************
*       DisplayText (a0)
*
*       Displays an Text
*
*       a0 -> Textstruct (contains ptrs to all texts, -1 terminated)
******************************************************************************
DisplayText
                movem.l d0/d1/a0/a1,-(sp)
                move.l  a0,a2
DT_loop
                move.l  (a2)+,d0
                bmi.b   DT_end
                move.l  d0,a0
                bsr     StrLen          ;get the length of the text
                move.l  d0,d3
                move.l  a0,d2
                move.l  OutHandle,d1
                CALLDOS Write
                bra.b   DT_loop
DT_end
                movem.l (sp)+,d0/d1/a0/a1
                rts
;;/
;// StrLen
******************************************************************************
*       d0 = StrLen(a0)
*
*       Calculates the length of a string
*       zeros are not counted, returns instead are
*
*       a0 -> String (zero or return-terminated)
*       d0 = return value (string length)
******************************************************************************
StrLen
                movem.l d1/a0,-(sp)
                moveq   #0,d0
SL_loop
                move.b  (a0)+,d1
                beq.b   SL_end2
                cmp.b   #10,d1
                beq.b   SL_end
                addq    #1,d0
                bra.b   SL_loop
SL_end
                addq    #1,d0
SL_end2
                movem.l (sp)+,d1/a0
                rts
;;/
;// CalcAreaLen
******************************************************************************
*       CalcAreaLen (d0)
*
*       Calcs the length of the areas using the formula:
*       length = (d0 / (32 * log (2)) * 4 ) + 3
*
*       d0 [.L] = number of decimals
*
*       the result is stored in Length_Area
******************************************************************************
CalcAreaLen
                movem.l d0/a0,-(sp)
                move.l  d0,d3
                lsr.l   #4,d0           ; create an 64 bit value (d0 * 2^28)
                move.l  d0,d1
                ror.l   #4,d1
                and.l   #$f0000000,d1
                move.l  Term_5,d2
                divu.l  d2,d0:d1        ; len (long)= count / (32*log(2)) +3
                addq.l  #3,d1
                move.l  d1,Length_Area
                movem.l (sp)+,d0/a0
                rts
;;/
;// CreateTable
******************************************************************************
*       CreateTable
*
*       Creates a table with 10000 entries (each number -> 1 ASCII-Longword)
*
******************************************************************************
CreateTable
                move.l  ConvertMem,a0
                moveq   #10-1,d7
                moveq   #"0",d0
CT_loop1
                moveq   #10-1,d6
                moveq   #"0",d1
CT_loop2
                moveq   #10-1,d5
                moveq   #"0",d2
CT_loop3
                moveq   #10-1,d4
                moveq   #"0",d3
CT_loop4
                move.b  d0,(a0)+
                move.b  d1,(a0)+
                move.b  d2,(a0)+
                move.b  d3,(a0)+
                addq.b  #1,d3
                dbra    d4,CT_loop4
                addq.b  #1,d2
                dbra    d5,CT_loop3
                addq.b  #1,d1
                dbra    d6,CT_loop2
                addq.b  #1,d0
                dbra    d7,CT_loop1
                rts
;;/
;// CalcTime
******************************************************************************
*       CalcTime
*
*       Calculates the time for each pass and converts it into an Timestring
*
******************************************************************************
CalcTime
                movem.l d0/a0,-(sp)
                lea     ConvertStruct,a3
CAT_loop
                move.l  (a3)+,d0
                bmi.b   CAT_end
                move.l  d0,a0
                move.l  (a3)+,a1
                move.l  (a3)+,a2
                bsr     ConvertTime
                bra.b   CAT_loop
CAT_end
                movem.l (sp)+,d0/a0
                rts
;;/
;// ConvertTime
******************************************************************************
*       ConvertTime (a0,a1,a2)
*
*       Calculates the difference between a0-> and a1-> and convert this time
*       into a timestring (a2->)
*
*       a0 [.L] -> first time
*       a1 [.L] -> second time
*       a2 [.L] -> timestring
******************************************************************************
ConvertTime
                movem.l d0-d7/a0-a3,-(sp)
                move.l  (a0),d0
                move.l  (a1),d1
                sub.l   d0,d1           ;number of days = day 2 - day 1
                move.l  d1,d2

                move.l  4(a0),d0
                move.l  4(a1),d1
                sub.l   d0,d1           ;number of mins = min2 - min1
                bpl.b   CT_cont         ;negative ?
                add.l   #1440,d1        ;correct
                subq.l  #1,d2           ;and day = day - 1
CT_cont
                move.l  d1,d3
                move.l  8(a0),d0
                move.l  8(a1),d1
                sub.l   d0,d1           ;number of ticks = ticks2 - ticks1
                bpl.b   CT_cont2        ;negative ?
                add.l   #3000,d1        ;correct
                subq.l  #1,d3           ;and min = min - 1
                bpl.b   CT_cont2        ;min negative ?
                add.l   #1440,d3        ;correct
                subq.l  #1,d2           ;and day = day - 1
CT_cont2
                move.l  d1,d7
                divul.l #365,d4:d2      ;day -> d4, years -> d2
                divul.l #60,d5:d3       ;min -> d5, hours -> d3
                divul.l #50,d6:d7       ;sec -> d7, ticks -> d6
                lsl     #1,d6           ;value after decimal point
                move.l  a2,a0
                move.l  d2,d0           ;now convert the values into decimal
                moveq   #7,d1           ;and store them into the timestring
                bsr     BinToDec
                lea     10(a2),a0
                move.l  d4,d0
                moveq   #3,d1
                bsr     BinToDec
                lea     10+6(a2),a0
                move.l  d3,d0
                moveq   #2,d1
                bsr     BinToDec
                lea     10+6+5(a2),a0
                move.l  d5,d0
                moveq   #2,d1
                bsr     BinToDec
                lea     10+6+5+5(a2),a0
                move.l  d7,d0
                moveq   #2,d1
                bsr     BinToDec
                lea     10+6+5+5+3(a2),a0
                move.l  d6,d0
                moveq   #2,d1
                bsr     BinToDec
                cmp.b   #" ",(a0)
                bne.w   CT_end
                move.b  #"0",(a0)
CT_end
                movem.l (sp)+,d0-d7/a0-a3
                rts
;;/
;// BinToDec
******************************************************************************
*       BinToDec
*
*       Converts an integer value to an ASCII-String and stores it at the
*       location at a0 ->
*       leading zeros are converted to blanks
*
*       a0 [.L] -> destination
*       d0 [.L] = integer value
*       d1 [.L] = number of decimals
******************************************************************************
BinToDec
                movem.l d0-d5/a0,-(sp)
                moveq   #0,d3           ;zero flag
                move    d1,d2
                neg     d2
                add     #10,d2          ;offset to the powertab
                lea     PowerTab,a1
                lea     0(a1,d2.w*4),a1
                subq    #1,d1           ;loop counter
BTD_loop
                move.l  (a1)+,d4
                divul.l d4,d5:d0        ;first decimal -> d0
                tst.b   d0              ;d0 <> 0 ?
                bne.b   BTD_cont
                tst.b   d3              ;d0 = 0 and d3 <> 0?
                bne.b   BTD_cont1
                move.b  #" ",d0         ;so it's a leading zero
                bra.b   BTD_cont2
BTD_cont
                moveq   #-1,d3          ;no more leading zeros
BTD_cont1
                add.b   #"0",d0
BTD_cont2
                move.b  d0,(a0)+
                move.l  d5,d0           ;remainder -> divisor
                dbra    d1,BTD_loop
                tst     d3              ;was the result = 0?
                bne.b   BTD_end
                move.b  #"0",-1(a0)     ;so write a zero
BTD_end
                movem.l (sp)+,d0-d5/a0
                rts
;;/
;// DisplayPI
******************************************************************************
*       DisplayPI
*
*       Displays PI on stdout
*
*       a0 [.L] -> ASCII-String
*       d0 [.L] = number of decimals
******************************************************************************
DisplayPI
                move.l  a0,d4
                move.l  OutHandle,d5
                addq.l  #2,d0
                move.l  d0,d6
                divul.l #80,d7:d6       ; we'll write lines of 80 chars
                                        ; (useful when using the >file
                                        ; option to write the result to
                                        ; a file)
                tst.l   d6              ; is there a whole line to write?
                beq.b   PartOfLine      ; no -> jump
Display_loop
                move.l  d5,d1
                move.l  d4,d2
                move.l  #80,d3
                CALLDOS Write           ; write a line
                bsr     LineFeed
                add.l   #80,d4
                subq.l  #1,d6
                bne.b   Display_loop
PartOfLine
                move.l  d5,d1
                move.l  d4,d2
                move.l  d7,d3
                CALLDOS Write
                bsr     LineFeed
                rts
;;/
;// LineFeed
******************************************************************************
*       LineFeed
*
*       Writes a LineFeed ($10)
*
******************************************************************************
LineFeed
                move.l  OutHandle,d1
                move.l  #Return,d2
                moveq   #1,d3
                CALLDOS Write
                rts
;;/
;// CalcPI
******************************************************************************
*       d0 = CalcPI (a0,d0,d1)
*
*       Calculation of PI
*       Additionally the time for calculation and conversion is measured
*
*       a0 [.L] -> empty area
*       d0 [.L] = number of decimals
*       d1 [.L] = length of the areas in Longwords
*
*       d0 = return value (0=error,-1=success)
*
******************************************************************************

CalcPI
                move.l  d0,-(sp)
                bsr     Prepare         ; calc the numbers of terms
                move.l  d1,-(sp)
                move.l  #Date1,d1
                CALLDOS DateStamp       ; get first time
                move.l  (sp)+,d1
                lea     Area_Q_Actual,a0
                lea     Area_Quotient,a1
                move.l  Length_Area,d0
                moveq   #5-1,d7         ; now copy the areaptrs to the
CP_loop                                 ; 'actual'-ptrs
                move.l  (a1)+,(a0)+
                move.l  d0,(a0)+
                dbra    d7,CP_loop
                tst.b   _PPCFlag
                beq.b   .noppc
                RUNPOWERPC      CalculationPPC
                bra.b   .ppc
.noppc
                bsr     Calculation     ; action
.ppc
                move.l  d1,-(sp)
                move.l  #Date2,d1
                CALLDOS DateStamp       ;get second time
                move.l  (sp)+,d1
                move.l  Area,a1
                move.l  Area_Result,a0
                move.l  (sp)+,d0
                move.l  d0,Count
                tst.b   _PPCFlag
                beq.b   .noppc2
                RUNPOWERPC      BinToASCIIPPC
                bra.b   .ppc2
.noppc2
                bsr     BinToASCII      ; converts the binary to ASCII
.ppc2

                move.l  Area,a0
                DB_ADDDUMP      DB1,TEMP,(a0),,256

                move.l  #Date3,d1
                CALLDOS DateStamp       ; get the third time
                moveq   #-1,d0
CalcPI_End
                rts
;;/
;// Prepare
******************************************************************************
*       Prepare (a0,d0,d1)
*
*       Initializing work
*       - Calculation of the numbers of the terms of each arctan-serie needed
*
*       a0 [.L] -> empty area
*       d0 [.L] = number of decimals
*       d1 [.L] = length of the areas in Longwords
******************************************************************************
Prepare
                movem.l d0/d1/a0/a1,-(sp)
                lea     Term_1,a1

                move.l  d0,d4
                lsr.l   #4,d0           ; create an 64 bit value (d0 * 2^28)
                ror.l   #4,d4
                and.l   #$f0000000,d4
                move.l  d0,d3
                move.l  d4,d5

                move.l  (a1)+,d2
                divu.l  d2,d0:d4        ; n = num of decimals / (2 * log 57)
                addq.l  #1,d4
                move.l  d4,Num_ArcTan_57    ; number of terms

                move.l  d3,d0
                move.l  d5,d4
                move.l  (a1)+,d2
                divu.l  d2,d0:d4        ; n = num of decimals / (2 * log 239)
                addq.l  #1,d4
                move.l  d4,Num_ArcTan_239

                move.l  d3,d0
                move.l  d5,d4
                move.l  (a1)+,d2

                divu.l  d2,d0:d4        ; n = num of decimals / (2 * log 682)
                addq.l  #1,d4
                move.l  d4,Num_ArcTan_682

                move.l  d3,d0
                move.l  d5,d4
                move.l  (a1)+,d2

                divu.l  d2,d0:d4        ; n = num of decimals / (2 * log 12943)
                addq.l  #1,d4
                move.l  d4,Num_ArcTan_12943

                movem.l (sp)+,d0/d1/a0/a1
                rts
;;/

                section "data",data
                POWERDATA

_SysBase        dc.l    0
_DOSBase        dc.l    0

Term_1          dc.l    942678135       ; 2*log(57) * 2^28
Term_2          dc.l    1276892650      ; 2*log(239) * 2^28
Term_3          dc.l    1521376402      ; 2*log(682) * 2^28
Term_4          dc.l    2207631954      ; 2*log(12943) * 2^28
Term_5          dc.l    2585827973      ; 32*log(2) * 2^28

PowerTab
                dc.l    1000000000
                dc.l    100000000
                dc.l    10000000
                dc.l    1000000
                dc.l    100000
                dc.l    10000
                dc.l    1000
                dc.l    100
                dc.l    10
                dc.l    1

ConvertStruct
                dc.l    Date1,Date2,TimeString1
                dc.l    Date2,Date3,TimeString2
                dc.l    Date1,Date3,TimeString3
                dc.l    -1

Date1           dcb.l   3,0
Date2           dcb.l   3,0
Date3           dcb.l   3,0

TimeString1     dc.b    "        y     d    h    m   .   s",10
TimeString2     dc.b    "        y     d    h    m   .   s",10
TimeString3     dc.b    "        y     d    h    m   .   s",10

Timing_Output
                dc.l    Return
                dc.l    Timing_Title
                dc.l    Timing_Line1
                dc.l    Timing_Text1
                dc.l    TimeString1
                dc.l    Timing_Text2
                dc.l    TimeString2
                dc.l    Timing_Line2
                dc.l    Timing_Text3
                dc.l    TimeString3
                dc.l    Return
                dc.l    -1

Timing_Title
                dc.b    "Timing statistics",10
Timing_Line1
                dc.b    "-----------------",10
Timing_Text1
                dc.b    "Calculation:",0
Timing_Text2
                dc.b    "BinToASCII :",0
Timing_Text3
                dc.b    "Total      :",0
Timing_Line2
                dc.b    "---------------------------------------------",10
                even

Accuracy_Output
                dc.l    Return
                dc.l    Accuracy_Text1
                dc.l    Accuracy_Value
                dc.l    Accuracy_Dec
                dc.l    -1

Accuracy_Text1  
                dc.b    "Accuracy: ",0
Accuracy_Value  
                dc.b    "           ",0
Accuracy_Dec    
                dc.b    "decimals",10


CPU_OutPut
                dc.l    CPU_Text2
                dc.l    Return
                dc.l    -1
CPU_Text1
                dc.b    "CPU     :      68020",0
CPU_Text2
                dc.b    "CPU     :    PPC"
CPU_PPC
                dc.b    "    ",0
                dc.b    0
                even

Title_OutPut
                dc.l    Return
                dc.l    Title_Text1
                dc.l    Title_Text2a
                dc.l    Title_Text3
                dc.l    Return
                dc.l    -1
Title_Text1     
                dc.b    "CyberPI V1.1  21.9.97 by Sam Jordan",10
Title_Text2a
                dc.b    "68K and PowerPC supported",10
Title_Text3
                dc.b    "-----------------------------------",10


Error_Version   dc.b    "This program requires OS2.0+",10
Len_Error_Version       =       *-Error_Version

Error_Mem       dc.b    "Not enough memory",10
Len_Error_Mem   =       *-Error_Mem

Error_CPU       dc.b    "This program requires 68020+",10
Len_Error_CPU   =       *-Error_CPU

Return          dc.b    10

Test1           dc.b    "test1",10
Len_Test1       =       *-Test1
Test2           dc.b    "test2",10
Len_Test2       =       *-Test2
Test3           dc.b    "test3",10
Len_Test3       =       *-Test3
Test4           dc.b    "test4",10
Len_Test4       =       *-Test4


                dc.b    "$VER: CyberPI 1.1 (21.9.97)",0


Template        dc.b    "DECIMALS/N,M=M68K/S",0
                even
Array           dc.l    0,0

dos_name        DOSNAME
                even

                section "bss",bss
Area
Area_Quotient   ds.l    1
Area_Quotient2  ds.l    1
Area_Quotient3  ds.l    1
Area_Quotient4  ds.l    1
Area_ArcTan     ds.l    1
Area_Result     ds.l    1

Area_Q_Actual   ds.l    1
Len_Q_Actual    ds.l    1
Area_Q2_Actual  ds.l    1
Len_Q2_Actual   ds.l    1
Area_Q3_Actual  ds.l    1
Len_Q3_Actual   ds.l    1
Area_Q4_Actual  ds.l    1
Len_Q4_Actual   ds.l    1
Area_AT_Actual  ds.l    1
Len_AT_Actual   ds.l    1

Num_ArcTan_57   ds.l    1               ; number of terms needed
Num_ArcTan_239  ds.l    1
Num_ArcTan_682  ds.l    1
Num_ArcTan_12943       ds.l    1

Length_Area     ds.l    1
Error_Ptr       ds.l    1
Error_Length    ds.l    1
OutHandle       ds.l    1
MemPtr          ds.l    1
ConvertMem      ds.l    1
Count           ds.l    1
_060Flag        ds.b    1
_PPCFlag        ds.b    1

