; > CacheAsm2

        GET     $.Arm.HDR.ListOpts
        GET     $.Arm.HDR.Macros
        GET     $.Arm.HDR.System

start
        &       0   ; No language
        &       init - start
        &       final - start
        &       service - start
        &       title - start
        &       helpstring - start
        &       helptable - start
        &       &280               ; Chunk number
        &       swihandler - start ; SWI handle
        &       switable - start   ; SWI name table
        &       0

title
        =       "ARM3Support",0

helpstring
        =       "ARM3 support",9,"1.10 (09 Nov 1989)",0

copyright
        =       "(c) N. van Someren for Aleph One Ltd. 9 Oct 1989",0

help
        =       "*Cache turns the cache on or off, or gives the cache state."
        =       13,10
syntax
        =       "Syntax: *Cache [On|Off]",0

confhelp
        =       "*Configure Cache <On|Off> determines the default state of the cache."
        =       13,10
confsyntax
        =       "Syntax: *Configure Cache <On|Off>"
        =       13,10,0
        ALIGN

helptable
        =       "Cache",0
        ALIGN
        &       cachecommand - start
        &       &00010100
        &       syntax - start
        &       help - start
        
        =       "Cache",0
        ALIGN
        &       cacheconfig - start
        &       &40010101
        &       confsyntax - start
        &       confhelp - start

        &       0

switable
        =       "Cache",0
        =       "Control",0
        =       "Cacheable",0
        =       "Updateable",0
        =       "Disruptive",0
        =       "Flush",0
        =       0
        ALIGN

init

        STMFD   R13!,{R14}

        MOV     R0,#4
        LDR     R1,[R0]
        ADR     R2,undefinst
        LDR     R3,toundefinst

        MOV     R5,#0

        MOV     R6,PC
        ORR     R4,R6,#3<<26
        CMPP    R4,#0

        STR     R3,[R0]
        &       &EE105F10     ; MCR 15,0,R5,C0,0
toundefinst
        MOV     PC,R2
undefinst

        STR     R1,[R0]
        CMPP    R6,#0

;R5 now has 0 if there is no co-proc and C0 if there is
        LDR     R0,IDmask
        LDR     R1,IDvalue
        AND     R5,R5,R0
        TEQ     R5,R1

        BEQ     haveanARM3

        SWI     OS_WriteS
        =       "No ARM3 connected, calls will be ignored."
        =       13,10,0
        MOV     R0,#1
        STR     R0,[R12]
        
        LDMFD   R13!,{PC}

haveanARM3
        BL      startcache

        MVN     R0,#0
        STR     R0,[R12]
        
        LDMFD   R13!,{PC}

startcache
; This routine needs to be register preserving...
        STMFD   R13!,{R0-R2,R14}
;Load up the controle registers
        LDR     R0,cacheable
        &       &EE030F10          ; MCC 15,0,R0,C3,0
        LDR     R0,updateable
        &       &EE040F10          ; MCC 15,0,R0,C4,0
        LDR     R0,disruptive
        &       &EE050F10          ; MCC 15,0,R0,C5,0

;Switch the cache on or off acording to CMOS RAM.
        MOV     R0,#161
        MOV     R1,#&C3
        SWI     OS_Byte
        AND     R0,R2,#1<<5
        MOV     R0,R0,LSR #5
        ORR     R0,R0,#2
        &       &EE010F10          ; MCC 15,0,R0,C1,0
        &       &EE020F10          ; MCC 15,0,R0,C2,0

        SWI     OS_WriteS
        =       "ARM3 installed, cache o",0
        ALIGN
        AND     R0,R0,#1
        BL      nff
        SWI     OS_NewLine

        LDMFD   R13!,{R0-R2,PC}

final
        LDR     R0,[R12]
        CMP     R0,#0
        BPL     nofinal
        
        MOV     R0,#2
        &       &EE020F10           ; MCC 15,0,R0,C2,0

nofinal
        MOV     PC,R14

service
        CMP     R1,#&27
        BEQ     doreset
        CMP     R1,#&45
        BEQ     doprereset
        MOV     PC,R14

doreset 
        STMFD   R13!,{R0}
        LDR     R0,[R12]
        CMP     R0,#0
        LDMFD   R13!,{R0}
        BMI     startcache
        MOV     PC,R14

doprereset
        LDR     R1,[R12]
        CMP     R1,#0
        MOVMI   R1,#2
        &       &4E021F10           ; MCCMI 15,0,R1,C2,0
        MOV     R1,#&45
        MOV     PC,R14

swihandler
        STMFD   R13!,{R1,R2}
        CMP     R11,#5
        ADDCC   PC,PC,R11,LSL #2
        B       unknownSWIerror
jumptable
        B       docachectrl
        B       docacheable
        B       doupdateable
        B       dodisruptive
        B       doflush

unknownSWIerror
        LDMFD   R13!,{R1,R2}
        ADR     R0,swierrorblock
        ORR     R14,R14,#1<<28
        MOVS    PC,R14

swierrorblock
        &       &800811
        =       "Unknown Cache SWI number",0
        ALIGN

swigoodreturn
        LDMFD   R13!,{R1,R2}
        BIC     R14,R14,#1<<28
        MOVS    PC,R14

docachectrl
        LDR     R2,[R12]
        CMP     R2,#0
        MOVPL   R0,#0
        BPL     swigoodreturn

        &       &EE122F10          ; MRC 15,0,R2,C2,0
        AND     R2,R2,R1            ; AND R2 with R1
        EOR     R0,R0,R2            ; EOR R2 with R0
        AND     R0,R0,#1            ; take only bit 0
        ORR     R0,R0,#2            ; set bit 1
        &       &EE020F10          ; MCR 15,0,R0,C2,0
        AND     R0,R0,#1
        B       swigoodreturn

docacheable
        LDR     R2,[R12]
        CMP     R2,#0
        BPL     swigoodreturn
        &       &EE132F10          ; MRC 15,0,R2,C3,0
        AND     R2,R2,R1
        EOR     R0,R0,R2
        &       &EE030F10          ; MCR 15,0,R0,C3,0
        B       swigoodreturn

doupdateable
        LDR     R2,[R12]
        CMP     R2,#0
        BPL     swigoodreturn
        &       &EE142F10          ; MRC 15,0,R2,C4,0
        AND     R2,R2,R1
        EOR     R0,R0,R2
        &       &EE040F10          ; MCR 15,0,R0,C4,0
        B       swigoodreturn

dodisruptive
        LDR     R2,[R12]
        CMP     R2,#0
        BPL     swigoodreturn
        &       &EE152F10          ; MRC 15,0,R2,C5,0
        AND     R2,R2,R1
        EOR     R0,R0,R2
        &       &EE050F10          ; MCR 15,0,R0,C5,0
        B       swigoodreturn

doflush
        LDR     R2,[R12]
        CMP     R2,#0
        BPL     swigoodreturn
        &       &EE010F10          ; MCR 15,0,R0,C5,0
        B       swigoodreturn

;Notes - The screen RAM is not cached as it is used double mapped.

;Address
;        33333333222222221111111100000000
;        ECA86420ECA86420ECA86420ECA86420
;Bit
;        33222222222211111111110000000000
;        10987654321098765432109876543210

;ROM and the logical RAM not in the screen are cachable.
cacheable
;       %11111100000000000111111111111111
        &       &FC007FFF
;Only logical RAM not in the screen is updatable.
updateable
;       %00000000000000000111111111111111
        &       &00007FFF
;Writes to MEMC mapping registers are disruptive.
disruptive
;       %11110000000000000000000000000000
        &       &F0000000
;We only care if it is an ARM3, not who made it or what version.
IDvalue
        &       &00000300
IDmask
        &       &0000FF00

cachecommand
        BIC     R14,R14,#1<<28
        STMFD   R13!,{R14}
        CMP     R1,#0
        BEQ     docacheread
        BL      decodenff
        CMP     R0,#0
        BEQ     docacheoff
        BPL     docacheon

badonoff
        ADR     R0,onofferror
        LDMFD   R13!,{R14}
        ORR     R14,R14,#1<<28
        MOVS    PC,R14

onofferror
        &       &800810
        =       "*Cache takes ON, OFF or no parameter to read cache state.",0
        ALIGN

decodenff
        STMFD   R13!,{R2,R14}
        LDRB    R2,[R0],#1
        ORR     R2,R2,#&20
        CMP     R2,#"o"

        MVNNE   R0,#0
        BNE     endnff

        LDRB    R2,[R0],#1
        ORR     R2,R2,#&20
        CMP     R2,#"n"
        MOVEQ   R0,#1
        BEQ     endnff

        CMP     R2,#"f"
        MVNNE   R0,#0
        BNE     endnff

        LDRB    R2,[R0],#1
        ORR     R2,R2,#&20
        CMP     R2,#"f"
        MOVEQ   R0,#0
        MVNNE   R0,#0
endnff
        LDMFD   R13!,{R2,PC}

docacheon
        LDR     R2,[R12]
        CMP     R2,#0
        LDMPLFD R13!,{PC}
        MOV     R2,#3
        &       &EE022F10            ; MCR 15,0,R2,C2,0
        LDMFD   R13!,{PC}^

docacheoff
        LDR     R2,[R12]
        CMP     R2,#0
        LDMPLFD R13!,{PC}
        MOV     R2,#2
        &       &EE022F10            ; MCR 15,0,R2,C2,0
        LDMFD   R13!,{PC}^

docacheread
        LDR     R2,[R12]
        CMP     R2,#0
        BPL     nocacheread
        &       &EE122F10            ; MRC 15,0,R2,C2,0

        AND     R0,R2,#1
        SWI     OS_WriteS
        =       "Cache O"
        =       0
        ALIGN
        BL      nff
        LDMFD   R13!,{PC}^

nff
        STMFD   R13!,{R14}
        CMP     R0,#0
        SWIEQ   &100+"f"
        SWIEQ   &100+"f"
        SWINE   &100+"n"
        SWI     OS_NewLine
        LDMFD   R13!,{PC}

nocacheread
        SWI     OS_WriteS
        =       "No cache fitted"
        =       13
        =       10
        =       0
        ALIGN
        LDMFD   R13!,{PC}^

cacheconfig
        STMFD   R13!,{R14}
        STMFD   R13!,{R0,R1}
        MOV     R0,#161
        MOV     R1,#&C3
        SWI     OS_Byte
        AND     R3,R2,#1<<5
        LDMFD   R13!,{R0,R1}
        CMP     R0,#1
        BEQ     dostatus
        BLO     doconfsyntax

        BL      decodenff
        CMP     R0,#0
        BLT     configerror
        BIC     R2,R2,#1<<5
        ORR     R2,R2,R0,LSL #5
        MOV     R0,#162
        MOV     R1,#&C3
        SWI     OS_Byte
        LDMFD   R13!,{PC}
configerror
        MOV     R0,#0
        LDMFD   R13!,{R14}
        ORR     R14,R14,#1<<28
        MOVS    PC,R14
        
dostatus
        MOV     R0,R3
        SWI     OS_WriteS
        =       "Cache      O"
        =       0
        ALIGN
        BL      nff
        LDMFD   R13!,{PC}

doconfsyntax
        ADR     R0,confsyntax2
        SWI     OS_Write0
        LDMFD   R13!,{PC}

confsyntax2
        =       "Cache      <On|Off>"
        =       13,10,0
        ALIGN

essential_data
        &       &53764EA9

        END
