;Program CPUSet by Nic Wilson Assembled with Macro68                

;This source code is copyright Nic Wilson Software
;it may not be used in whole or in part without
;permission of Nic Wilson.  It is supplied here as
;example of how to manipulate the caches of the
;68020, 68030, 68040 processors.  This source
;calls some macros that are not included in this
;source code.  This source code uses the new
;Motorola syntax and was assembled with Macro68

                
                incdir "includes:"     
                MC68040
                super
                exeobj
                maclib  "includes:commonmac/allmacs.mac
                include "commonmac/macs.i"
                SECTION main,CODE               

                StartCode                               ;startup stuff
main            move.l    (_argv),d0
                beq.b     noargs  
                movea.l   d0,a0
                movea.l   (a0),a0
                cmpi.b    #'?',(a0)
                beq.w     dispusage
noargs          movea.l   (4).w,a6                      ;get execbase
                move.w    (AttnFlags,a6),d0             ;check for 040
                btst      #AFB_68040,d0                 ;have we got one?
                bne.w     do040                         ;yup! do 40 code
                btst      #AFB_68030,d0                 ;else check 030
                bne.b     do030                         ;yup! do 30 code
                btst      #AFB_68020,d0                 ;check for 020
                beq.w     error                         ;minimum not found
                movea.l   (4).w,a6
                cmpi.w    #36,(LIB_VERSION,a6)
                bge.b     noneed
                lea       (checkproc,pc),a5
                CALLEXEC  Supervisor
                tst.l     d1
                bpl.b     no040
                bset.b    #AFB_68040,(AttnFlags+1,a6)
                bset.b    #AFB_68030,(AttnFlags+1,a6)   ;020 should already be
                bra.w     do040                         ;set
no040           btst      #CACRB_DBE,d1
                beq.b     noneed
                bset.b    #AFB_68030,(AttnFlags+1,a6)
                bra.b     do030
noneed          lea       (iburst,pc),a0                ;get data burst gad
                ori.w     #GFLG_DISABLED,(gg_Flags,a0)  ;disable it
                lea       (dburst,pc),a0                ;get ins burst gad
                ori.w     #GFLG_DISABLED,(gg_Flags,a0)  ;disable it
                move.b    #-2,(procflag)                ;set 020 flag
                bra.b     do020                         ;jump into 030 code
do030           move.b    #-1,(procflag)                ;set 030 flag
do020           lea       (winddatc,pc),a0              ;get second gadget
                move.l    #dburst,(a0)                  ;put burst gadgets in
                
;*********************************************************
;Initialise the gadgets for the 68020 and 68030 processors
;*********************************************************                

                tst.l     (_argv)                       ;have we CLI args?
                bne.w     dodos                         ;do CLI code if so
                bsr.w     getstat                       ;get current cache modes
                btst      #CACRB_EnableI,d0             ;check for ICACHE
                bne.b     checkdc1                      ;if on default settings
                move.l    #ICText2,(Icache)             ;else put off bg text
                move.l    #ICText2,(ICa)                ;and put off  fg text
                ori.w     #SELECTED,(inflag)            ;make gadget selected
                move.b    #1,(ICText)                   ;reverse bg colour
                move.b    #2,(ICTextb)                  ;reverse fg colour

checkdc1        btst      #CACRB_EnableD,d0             ;check for DCACHE
                bne.b     checkib1                      ;if on use default
                move.l    #DCText2,(Dcache)             ;else put off bg text
                move.l    #DCText2,(DCa)                ;and put on fg text
                ori.w     #SELECTED,(dflag)             ;make gadget selected
                move.b    #1,(DCText)                   ;reverse bg colour
                move.b    #2,(DCTextb)                  ;reverse fg colour

                                                        ;we allow 020 through
                                                        ;so they will show 'off'
checkib1        btst      #CACRB_IBE,d0                 ;check for IBURST
                bne.b     checkdb1                      ;if on use default
                move.l    #IBText2,(IB)                 ;else put off bg text
                move.l    #IBText2,(IBa)                ;and put on fg text
                ori.w     #SELECTED,(ibflag)            ;make it selected
                move.b    #1,(IBText)                   ;reverse bg colour
                move.b    #2,(IBTextb)                  ;reverse fg colour

checkdb1        btst      #CACRB_DBE,d0                 ;check for DBURST
                bne.w     dowindow                      ;if on go open window
                move.l    #DBText2,(DB)                 ;else put off bg text
                move.l    #DBText2,(DBa)                ;and put on fg text
                ori.w     #SELECTED,(dbflag)            ;select the gadget
                move.b    #1,(DBText)                   ;reverse the bg colour
                move.b    #2,(DBTextb)                  ;reverse the fg colour
                bra.w     dowindow                      ;and go open the window
        
;**********************************************
;Initialise the gadgets for the 68040 processor
;**********************************************                

do040           tst.l     (_argv)                       ;do we have CLI args?
                bne.w     dodos                         ;do dos code if so
                bsr.w     getstat                       ;get current cache modes
                btst      #15,d0                        ;check for ICACHE
                bne.b     checkdc                       ;default if its on
                move.l    #ICText2,(Icache)             ;else put off bg text
                move.l    #ICText2,(ICa)                ;and put on fg text
                ori.w     #SELECTED,(inflag)            ;select the gadget
                move.b    #1,(ICText)                   ;reverse the bg colour
                move.b    #2,(ICTextb)                  ;reverse the fg colour

checkdc         btst      #31,d0                        ;check for DCACHE
                bne.b     checkcb                       ;default if on 
                move.l    #DCText2,(Dcache)             ;else put off bg text
                move.l    #DCText2,(DCa)                ;and put on fg text
                ori.w     #SELECTED,(dflag)             ;select the gadget
                move.b    #1,(DCText)                   ;reverse the bg colour
                move.b    #2,(DCTextb)                  ;reverse the fg colour
checkcb         andi.b    #$20,d1                       ;check for Copyback
                bne.b     dowindow                      ;default if on
                move.l    #CBText2,(CB)                 ;else put off bg text
                move.l    #CBText2,(CBa)                ;and put on fg text
                ori.w     #SELECTED,(cflag)             ;select the gadget
                move.b    #1,(CBText)                   ;reverse the bg colour
                move.b    #2,(CBTextb)                  ;reverse the fg colour

dowindow        lea       (window,pc),a0                ;get the window
                CALLINT   OpenWindow                    ;open it
                tst.l     d0                            ;did it open?
                beq.w     error                         ;error out if not
                move.l    d0,(windsave)                 ;save the ptr

waitloop        movea.l   (windsave,pc),a0              ;get window ptr
                movea.l   (wd_UserPort,a0),a0           ;get the msg port
                moveq     #0,d0                         ;set do WaitPort
                moveq     #0,d1                         ;set for ReplyMsg
                WaitMsg                                 ;wait for a msg
                cmpi.w    #1,(gg_GadgetID,a1)           ;was it ICACHE
                beq.w     doi                           ;do it if so
                cmpi.w    #2,(gg_GadgetID,a1)           ;was it DCACHE
                beq.w     dod                           ;do it if so
                cmpi.w    #3,(gg_GadgetID,a1)           ;was it third gad
                beq.w     docb                          ;do it if so
                cmpi.w    #4,(gg_GadgetID,a1)           ;was it IBURST
                bne.w     exitwb                        ;must be close so exit
                
                bsr.w     getstate                      ;get the gads state
                tst.l     d0                            ;test the return
                bmi.b     setiboff                      ;turn it off
                move.l    #IBText1,(IB)                 ;else on bg text
                move.l    #IBText1,(IBa)                ;and on fg text
                move.b    #2,(IBText)                   ;reverse the fg colour
                move.b    #1,(IBTextb)                  ;reverse the bg colour
                bsr.w     refresh                       ;refresh the gadget
                moveq     #0,d3                         ;clear cache bits reg
                bset      #CACRB_IBE,d3                 ;set cache bits on
                move.l    d3,d2                         ;set the cache mask
                bra.w     doit
                
setiboff        move.l    #IBText2,(IB)                 ;the rest of these are
                move.l    #IBText2,(IBa)                ;the similar as ones
                move.b    #1,(IBText)                   ;above
                move.b    #2,(IBTextb)
                bsr.w     refresh
                moveq     #0,d2
                move.l    d2,d3
                bset      #CACRB_IBE,d2                 ;set the cache mask
                bra.w     doit          
                                
dodb            bsr.w     getstate
                tst.l     d0
                bmi.b     setdboff
                move.l    #DBText1,(DB)
                move.l    #DBText1,(DBa)
                move.b    #2,(DBText)
                move.b    #1,(DBTextb) 
                bsr.w     refresh
                moveq     #0,d3
                bset      #CACRB_DBE,d3
                move.l    d3,d2
                bra.b     doit
                
setdboff        move.l    #DBText2,(DB)
                move.l    #DBText2,(DBa)
                move.b    #1,(DBText)
                move.b    #2,(DBTextb)
                bsr.w     refresh
                moveq     #0,d2
                move.l    d2,d3
                bset      #CACRB_DBE,d2
                bra.b     doit          

docb            tst.b     (procflag)
                bmi.b     dodb
                bsr.w     getstate
                tst.l     d0
                bmi.b     setcboff
                move.l    #CBText1,(CB)
                move.l    #CBText1,(CBa)
                move.b    #2,(CBText)
                move.b    #1,(CBTextb)
                bsr.w     refresh
                moveq     #0,d3
                bset      #CACRB_CopyBack,d3
                move.l    d3,d2
doit            bsr.w     dowb
                bra.w     waitloop
                
setcboff        move.l    #CBText2,(CB)
                move.l    #CBText2,(CBa)
                move.b    #1,(CBText)
                move.b    #2,(CBTextb)
                bsr.w     refresh
                moveq     #0,d3
                move.l    d3,d2
                bset      #CACRB_CopyBack,d2
                bra.b     doit          
                
dod             bsr.w     getstate
                tst.l     d0
                bmi.b     setdcoff
                move.l    #DCText1,(Dcache)
                move.l    #DCText1,(DCa)
                move.b    #2,(DCText)
                move.b    #1,(DCTextb) 
                bsr.w     refresh
                moveq     #0,d3
                bset      #CACRB_EnableD,d3
                move.l    d3,d2
                bra.b     doit
                
setdcoff        move.l    #DCText2,(Dcache)
                move.l    #DCText2,(DCa)
                move.b    #1,(DCText)
                move.b    #2,(DCTextb)
                bsr.w     refresh
                moveq     #0,d3
                move.l    d3,d2
                bset      #CACRB_EnableD,d2
                bra.w     doit          
                
doi             bsr.w     getstate
                tst.l     d0
                bmi.b     seticoff
                move.l    #ICText1,(Icache)
                move.l    #ICText1,(ICa)
                move.b    #2,(ICText)
                move.b    #1,(ICTextb)
                bsr.b     refresh
                moveq     #0,d3
                bset      #CACRB_EnableI,d3
                move.l    d3,d2
                bra.w     doit
                
seticoff        move.l    #ICText2,(Icache)
                move.l    #ICText2,(ICa)
                move.b    #1,(ICText)
                move.b    #2,(ICTextb)
                bsr.b     refresh
                moveq     #0,d3
                move.l    d3,d2
                bset      #CACRB_EnableI,d2
                bra.w     doit          
                
                
exitwb          movea.l   (windsave,pc),a0              ;get the window
                JMPINT    CloseWindow                   ;close it
                   
                                                                
refresh         movea.l   a1,a0                         ;refresh the gadget
                movea.l   (windsave,pc),a1              ;in a1
                suba.l    a2,a2
                moveq     #1,d0
                JMPINT    RefreshGList
                             
                
;****************************************************                
;depending on the processor this routine will go into
;supervisor and return either the cacr in d0 or cacr
;in d0 and dtt1 in d1                
;****************************************************
                
getstat         lea       (supcode,pc),a5
                JMPEXEC  Supervisor

supcode         movec     cacr,d0                     
                tst.b     (procflag)
                bmi.b     sc_xit
                movec     dtt1,d1               
sc_xit          rte

;*********************************************
;Test the state of the gadget in a1 and return
;a boolean result in d0                       
;*********************************************    

getstate        move.w    (gg_Flags,a1),d0
                andi.w    #GFLG_SELECTED,d0
                bne.b     gadset
                moveq     #0,d0
                rts
gadset          moveq     #-1,d0
                rts             
                
;**************************************************                
;error routine, display credits, do an audible beep
;and flash the screen and exit                
;**************************************************
                
error           bsr.b     dispcredit
                moveq     #0,d0                         
                moveq     #0,d1
                Beep
                suba.l    a0,a0
                CALLINT   DisplayBeep
                lea       (errmsg,pc),a0
                bsr.w     print
                bra.b     errorout
dispusage       bsr.b     dispcredit
                lea       (usage,pc),a0
                bsr.w     print
                bra.b     errorout
                
dispcredit      lea       (credit,pc),a0
                bsr.w     print
errorout        rts                
                
dodos           lea       (credit,pc),a0
                bsr.w     print
                tst.l     (_argv)
                beq.w     exit
                movea.l   (_argv),a2
                move.l    (_argc),d7
                subq.l    #1,d7
                tst.l     (a2)
                beq.w     exit
                moveq     #0,d2
                moveq     #0,d3
                
loop            lea       (cbon,pc),a1          ;CopyBack on
                bsr.b     docmp
                bne.b     nocbon
                tst.b     (procflag)
                bmi.w     next
                bset      #CACRB_CopyBack,d3
                bset      #CACRB_CopyBack,d2
                lea       (cben,pc),a0
                bsr.b     print
                bra.w     next
                
nocbon          lea       (cboff,pc),a1         ;CopyBack off
                bsr.b     docmp
                bne.b     nocboff
                tst.b     (procflag)
                bmi.w     next
                bset      #CACRB_CopyBack,d2
                bclr      #CACRB_CopyBack,d3
                lea       (cbdis,pc),a0
                bsr.b     print
                bra.w     next
                
nocboff         lea       (icon,pc),a1          ;Ins cache on
                bsr.b     docmp
                bne.b     noicon
                bset      #CACRB_EnableI,d3
                bset      #CACRB_EnableI,d2
                lea       (icen,pc),a0
                bsr.b     print
                bra.w     next

docmp           movea.l   (a2),a0
                moveq     #-1,d0
                StringCmp
                tst.l     d0
                rts

print           move.l    (_stdout),d1
                beq.b     prexit
                DosAPrint
prexit          rts

noicon          lea       (icoff,pc),a1         ;Inc Cache off
                bsr.b     docmp
                bne.b     noicoff
                bclr      #CACRB_EnableI,d3
                bset      #CACRB_EnableI,d2
                lea       (icdis,pc),a0
                bsr.b     print
                bra.w     next
                
noicoff         lea       (dcon,pc),a1          ;Data Cache on
                bsr.b     docmp
                bne.b     nodcon
                bset      #CACRB_EnableD,d3
                bset      #CACRB_EnableD,d2
                lea       (dcen,pc),a0
                bsr.b     print
                bra.w     next
                
nodcon          lea       (dcoff,pc),a1         ;Data Cache off
                bsr.b     docmp
                bne.b     nodcoff
                bclr      #CACRB_EnableD,d3
                bset      #CACRB_EnableD,d2
                lea       (dcdis,pc),a0
                bsr.w     print
                bra.w     next
                
nodcoff         cmpi.b    #-1,(procflag)        ;is it the 030
                bne.w     next                  ;if not rest are invalid
                lea       (ibon,pc),a1          ;Ins Burst on
                bsr.w     docmp
                bne.b     noibon
                bset      #CACRB_IBE,d3
                bset      #CACRB_IBE,d2
                lea       (iben,pc),a0
                bsr.w     print
                bra.b     next
                
noibon          lea       (iboff,pc),a1         ;Ins Burst off
                bsr.w     docmp
                bne.b     noiboff
                bclr      #CACRB_IBE,d3
                bset      #CACRB_IBE,d2
                lea       (ibdis,pc),a0
                bsr.w     print
                bra.b     next
                
noiboff         lea       (dbon,pc),a1          ;Data Burst on
                bsr.w     docmp
                bne.b     nodbon
                bset      #CACRB_DBE,d3
                bset      #CACRB_DBE,d2
                lea       (dben,pc),a0
                bsr.w     print
                bra.b     next
                
nodbon          lea       (dboff,pc),a1         ;Data Burst off
                bsr.w     docmp
                bne.b     next
                bclr      #CACRB_DBE,d3
                bset      #CACRB_DBE,d2
                lea       (dbdis,pc),a0
                bsr.w     print
                
next            addq.l    #4,a2
                dbf       d7,loop
                
dowb            lea       (do030code,pc),a5
                                                ;if we're under V2.0x
                movea.l   (4).w,a6              ;then there is no need
                cmpi.w    #36,(LIB_VERSION,a6)  ;to do our own code
                blt.b     isneed                ;we'll call the V2.0x
                                                ;function instead with
                move.l    d3,d0                 ;the same parameters as
                move.l    d2,d1                 ;we use
                JMPEXEC  CacheControl
                
                
isneed          and.l     d2,d3                 ;d3=cache bits
                not.l     d2                    ;d2=cache mask (inverted)      
                
                                                ;< 68040 ?
                tst.b     (procflag)            ;branch if not 68040
                bmi.b     super
                
                lea       (docode,pc),a5        ;get 68040 code
super           CALLEXEC  Supervisor
exit            rts
                
;****************************************************************                
;This is to check for the presence of the 68040, 68030 or 68020
;cpu, we try to set specific modes for each and return the result
;in d1, this is need if we are running under kickstart 1.3  
;****************************************************************

checkproc       movec     cacr,d0               
                move.l    d0,d1         ;I dont use the name CACR_Copyback      
                bset      #31,d1        ;in this place it is misleading
                bset      #CACRB_DBE,d1
                movec     d1,cacr
                movec     cacr,d1
                movec     d0,cacr
                rte         
                
;*******************************************************
;Set the required modes of the 68030 or 68020 processors
;This is called if under kickstart 1.3
;*******************************************************
                
do030code       movec     cacr,d0       ;get cache control        
                or.l      d3,d0         ;add our manipulate bits
                or.l      d3,d2         ;add any set bits to the mask
                and.l     d2,d0         ;clear unwanted
                movec     d0,cacr       ;set new settings        
                rte          
                
;*********************************************                
;Set the required modes of the 68040 processor
;This is called if under kickstart 1.3
;*********************************************                
                
docode          movec     cacr,d4       ;get cache control register 
                move.l    d2,d0         ;make a copy of new bits
                move.l    d3,d1         ;make a copy of the mask
                andi.l    #$0101,d1     ;clear any cback bit
                bset      #31,d0        ;set the bit in the mask
                moveq     #15,d7        ;get 15 into a data reg
                lsl.l     d7,d1         ;get icache into bit 15
                lsl.l     d7,d0         ;and do the mask
                swap      d1            ;swap the 16 bit halves
                swap      d0            ;swap the mask too
                lsl.w     #8,d1         ;shift dcache to bit 31
                lsl.w     #8,d0         ;shift any dcache to bit 31
                swap      d1            ;return the halves
                swap      d0            ;and the mask
                or.l      d1,d4         ;set the bits were gonna manipulate
                or.l      d1,d0         ;add the set bits in the mask
                and.l     d0,d4         ;clear the bits not in the mask 
                andi.l    #$80000000,d3 ;clear all except any copyback 
                rol.l     #6,d3         ;shift to its correct position
                or.l      #$7fffffff,d2 ;add the cleared bits to the mask
                rol.l     #6,d2         ;shift it too
                cpusha    dc            ;push the data cache to update memory
                movec     dtt1,d6       ;get transparent trans reg
                andi.b    #$9f,d6       ;clear the CacheMode bits
                or.l      d3,d6         ;set our manipulate bit
                or.l      d3,d2         ;add the bit to the mask
                and.l     d2,d6         ;clear the unwanted bit
                movec     d6,dtt1       ;set the reg
                cpusha    bc            ;push data/ins caches to update memory
                movec     d4,cacr       ;and set the cache control
                rte     
                
                INCLUDE  /cpuset/cpuset.window                
                even
                
windsave        dc.l    0
procflag        dc.b    0
cbon            dc.b    'CBACK_ON',0
cboff           dc.b    'CBACK_OFF',0
icon            dc.b    'ICACHE_ON',0
icoff           dc.b    'ICACHE_OFF',0 
dcon            dc.b    'DCACHE_ON',0
dcoff           dc.b    'DCACHE_OFF',0 
ibon            dc.b    'IBURST_ON',0
iboff           dc.b    'IBURST_OFF',0
dbon            dc.b    'DBURST_ON',0
dboff           dc.b    'DBURST_OFF',0
cben            dc.b    'COPYBACK CACHE ENABLED',$0a,0
cbdis           dc.b    'COPYBACK CACHE DISABLED',$0a,0
icen            dc.b    'INSTRUCTION CACHE ENABLED',$0a,0
icdis           dc.b    'INSTRUCTION CACHE DISABLED',$0a,0 
dcen            dc.b    'DATA CACHE ENABLED',$0a,0
dcdis           dc.b    'DATA CACHE DISABLED',$0a,0
iben            dc.b    'INSTRUCTION BURST ENABLED',$0a,0
ibdis           dc.b    'INSTRUCTION BURST DISABLED',$0a,0 
dben            dc.b    'DATA BURST ENABLED',$0a,0
dbdis           dc.b    'DATA BURST DISABLED',$0a,0
credit          dc.b    $0a,$1b,'[0;33m     CPUSet V1.5 ',$1b,'[0;32mWritten in Assembler ',$1b,'[0;m © Nic Wilson',$0a
                dc.b    '     For 68020, 68030 & 68040 Processors',$0a
                dc.b    $1b,'[0;32m     This program is Shareware',$1b,'[0;m',$0a,$0a,0
errmsg          dc.b    'You ',$1b,'[0;33mMUST ',$1b,'[0mhave a 68020, 68030 or 68040 Processor',$1b,'[0;32mCPU',$1b,'[0m',$0a,$0a,0
usage           dc.b    $0a,$1b,'[0;33m68040-> ',$1b,'[0;32mCPUSet  ',$1b,'[0;mICACHE_ON/S,ICACHE_OFF/S,DCACHE_ON/S,DCACHE_OFF/S',$0a
                dc.b    '                CBACK_ON/S,CBACK_OFF/S',$0a 
                dc.b    $0a,$1b,'[0;33m68030-> ',$1b,'[0;32mCPUSet  ',$1b,'[0;mICACHE_ON/S,ICACHE_OFF/S,DCACHE_ON/S,DCACHE_OFF/S',$0a
                dc.b    '                IBURST_ON] IBURST_OFF/S,DBURST_ON/S,DBURST_ON/S',$0a
                dc.b    $0a,$1b,'[0;33m68020-> ',$1b,'[0;32mCPUSet  ',$1b,'[0;mICACHE_ON/S,ICACHE_OFF/S,DCACHE_ON/S,DCACHE_OFF/S',$0a,$0a,0
                
                END
                