;*
; memmap.mac
;
;               Copyright (c) 2002 by Megan Gentry
;
; Abstract:
;       This program is designed to locate and report ranges
;       of memory in the low 64kb which can be referenced on
;       a PDP-11 and report them to the terminal.
;
;       The program was designed to be used to map the memory
;       on a proto desktop portable pdp-11 which only has a
;       4 line x 40 character LCD screen, which is why it
;       displays 3 lines and waits for character input to
;       proceed.
;-

       .asect
       . = 0

       reset                           ;reset the world
       br      start                   ; and jump to the code

       .word   nxmtrp                  ; : Address of NXM handler
       .word   340                     ; : PR7

       . = 300

start:  mov     #m.head,r0              ;Announce us
       call    ttostr                  ; ...

       clr     r1                      ;R1 = Location under test
       mov     #2,r4                   ;R4 = Count of lines before wait

10$:    mov     r1,r2                   ;R2 = Low limit of memory range

; Here we look for the end of region of memory which exists
; (we assume that location 0 works)

20$:    clc                             ;Clear carry (NXM will set carry)
       tstb    @r1                     ;Test the location
       bcs     30$                     ;If it is non-existant...
       mov     r1,r3                   ;R3 = Hi limit of memory range
       inc     r1                      ;Update location under test
       bne     20$                     ; !loop!
       br      100$                    ;When we wrap in 64kb, we're done

30$:    call    report                  ;Report the range (R2,R3)

; Here we start looking for the start of the next region of
; responding memory.

40$:    clc                             ;Clear carry (NXM will set carry)
       tstb    @r1                     ;Test the location
       bcc     10$                     ;We've found memory...
       inc     r1                      ;Update location under test
       bne     40$                     ; !loop!
;       br      100$                    ;When we wrap in 64kb, we're done

100$:   call    report                  ;Report the range (R2,R3)

110$:   halt                            ;Stop the world...
       br      110$                    ; and don't let it restart...


report: mov     r2,r0                   ;Print out region low address
       call    octout                  ; ...
       mov     #m.del,r0               ;Print a delimiter
       call    ttostr                  ; ...
       mov     r3,r0                   ;Print out region hi address
       call    octout                  ; ...
       movb    #11,r0                  ;Another delimiter
       call    ttochr                  ; ...
       mov     r3,r0                   ;Determine number of words (octal)
       sub     r2,r0                   ; ...
       inc     r0                      ; ...
       call    octout                  ;Print it out
       mov     #m.crlf,r0              ;On to next line
       call    ttostr                  ; ...
       dec     r4                      ;Should we delay a bit?
       bgt     10$                     ;Nope...
       mov     #m.pak,r0               ;Yes, print out a prompt
       call    ttostr                  ; ...
       call    ttichr                  ;Get any character (where is that
                                       ; found on a keyboard?)
       mov     #m.crlf,r0              ;On to next line
       call    ttostr                  ; ...
       mov     #3,r4                   ;Reset the line count
10$:    return


octout: mov     r0,-(sp)                ;Save value
       bic     #177770,@sp             ;Isolate an octal digit
       add     #^O60,@sp               ;Make it printable
       ror     r0                      ;Shift right
       asr     r0                      ; three bits
       asr     r0                      ;  for next digit
       beq     10$                     ;If done... print out
       call    octout                  ;Not yet, recurse !!
10$:    mov     (sp)+,r0                ;Print a digit
       call    ttochr                  ; ...
       return                          ;Unwind the stack and return


ttostr: mov     r1,-(sp)                ;Save R1 for awhile
       mov     r0,r1                   ;Save pointer to string
10$:    movb    (r1)+,r0                ;Get a character of string
       beq     20$                     ;If null, add a <CR><LF>
       cmpb    r0,#200                 ;If a <200>, we're done
       beq     30$                     ; ...
       call    ttochr                  ;Print the character
       br      10$                     ; !loop!

20$:    movb    #15,r0                  ;output a <CR><LF> on a <NUL>
       call    ttochr                  ; ...
       movb    #12,r0                  ; ...
       call    ttochr                  ; ...
30$:    mov     (sp)+,r1                ;Restore previously saved R1
       return


ttochr: tstb    @#177564                ;Terminal ready for output?
       bpl     ttochr                  ;Nope...
       movb    r0,@#177566             ;Yes... output character
       return


ttichr: tstb    @#177560                ;Has a key been typed?
       bpl     ttichr                  ;Nope...
       movb    @#177562,r0             ;Yes... get it...
       return


nxmtrp: bis     #1,2(sp)                ;Set PSW<C> for return
       rti                             ; from interrupt


m.head: .asciz  /Memory Map:/
m.del:  .ascii  / - /<200>
m.pak:  .ascii  /Press any key to continue.../<200>
m.crlf: .byte   0
       .even

       .end