; > FindCSR searches through the top 8K of memory (the I/O page)
;   for valid addresses.  Invalid addresses cause a trap to location
;   4, from which the program recovers. Valid addresses are printed.
;
        ORG      O1000
        MOV     #O1000,R6       ; init stack
        MOV     #trap,@#4       ; set bus timeout trap vector at 4
        MOV     #O340,@#6       ; set new PSW
        MOV     #O160000,R5     ; start of I/O page
loop:   MOV     (R5),R0         ; read location
exists: JSR     R7,@#CRLF       ; move these 2 lines (NOT the label) past...
        JSR     R7,@#PRTO       ; ...the MOV if you want only real addresses
        JSR     R3,@#MSSG       ; if we get here, no trap - so tell console
        DEF     32              ; pretend it's R/O
        DEF     ASC("R")
        DEF     ASC("O")+&8000
        MOV     R0,(R5)         ; write location
        JSR     R3,@#MSSG       ; if here - no trap, so really was R/W
        DEF     8               ; backspace
        DEF     ASC("/")
        DEF     ASC("W")+&8000
next:   INC     R5
        INC     R5              ; twice to stay on even address
        CMP     R5,#O177560
        BMI     test
        CMP     R5,#O177570
        BMI     consol          ; don't test the console, just include it
test:   TST     R5
        BNE     loop
        JSR     R7,@#CRLF
stop:   HALT                    ; stop when R5 wraps round
        BR      stop
trap:   ADD     #4,R6           ; "remove" old (pre-trap) PC and PSW from stack
        BR      next
;
consol: JSR     R7,@#CRLF
        JSR     R7,@#PRTO
        JSR     R3,@#MSSG
        DEF     32
        DEF     ASC("C")
        DEF     ASC("o")
        DEF     ASC("n")
        DEF     ASC("s")
        DEF     ASC("o")
        DEF     ASC("l")
        DEF     ASC("e")+&8000
        BR      next        
;
CRLF:   MOV     R5,R1
        MOV     #13,R5          ; print <CR> and <LF> on console
        JSR     R7,@#PRTA
        MOV     #10,R5
        JSR     R7,@#PRTA
        MOV     R1,R5
        RTS     R7
;
PRTA:   TSTB    @#O177564       ; wait for console XBUFF to be ready
        BPL     PRTA
        MOV     R5,@#O177566
        RTS     R7
;
PRTO:   MOV     R0,-(R6)        ; save R0,R4,R5 on stack
        MOV     R4,-(R6)
        MOV     R5,-(R6)
        MOV     R5,R4
        MOV     #O30,R5         ; R4 will be 6x after shifts
        ROL     R4              ; rotate 1 bit from R4 to R5
        ROL     R5
        JSR     R7,@#PRTA       ; print - as ASCII since it's 6x
        MOV     #5,R0           ; set to do five octets
CLOOP:  MOV     #6,R5           ; 6>>3 becomes octal 60, ie "0"
        ROL     R4              ; rotate R4>R5: 3 bits of octal number
        ROL     R5              ; could use ASHC R4,#3 if we have EIS
        ROL     R4
        ROL     R5
        ROL     R4
        ROL     R5
        JSR     R7,@#PRTA       ; print a digit
        DEC     R0              ; one less digit to do
        BNE     CLOOP
        MOV     (R6)+,R5        ; restore caller's R5,R4,R0
        MOV     (R6)+,R4
        MOV     (R6)+,R0
        RTS     R7
;
MSSG:   TSTB    @#O177564       ; prints message at word following call
        BPL     MSSG
        MOV     (R3),@#O177566  ; print char just past where we were
        TST     (R3)+           ; see if it was last, and point to next
        BPL     MSSG            ; top bit set = finished
        RTS     R3
