; HDT C5 BOOT PROM

; commented by Holger Veit 2013
; The file was produced from CPU-C5.BIN from bitsavers.org
; by a self-written IDA module. IDA is a software by Hexrays/Datarescue.
;
; This work is Creative Commons CC-BY-SA
;
; This is the ROM version of HDT. 
;
; This ROM can boot from the built-in floppy drive
; as well as from a PRIAM QBUS HD controller.
; Functions to examine and modify memory locations
; are not present (were removed in favor of PRIAM boot code).
; Only commands 'R' and 'P' are present.
;

; Processor:        WD9000
; Target assembler: P-Code Pseudo Assembler
; Note: this is no valid assembler and not intended to be 
; converted back into machine code.

BOOTTIB:0000 ; File Name   : C:\hv\ucsd\pdq3\simh\hdt\CPU_C5.bin
BOOTTIB:0000 ; Format      : Binary file
BOOTTIB:0000 ; Base Address: 0000h Range: F400h - F800h Loaded length: 0400h^
BOOTTIB:0000
BOOTTIB:0000 ; This is C5 version of HDT code - this is apparently
BOOTTIB:0000 ; a boot PROM which can boot from FDC and PRIAM HD
BOOTTIB:0000 ; Processor:        WD9000
BOOTTIB:0000 ; Target assembler: P-Code Pseudo Assembler

BOOTTIB:0000 ; Segment type: Regular
BOOTTIB:0000                 ; START OF SEGMENT
BOOTTIB:0000                 .WORD   $f401           ; fc68 points here - start of ROM, "MR"
BOOTTIB:0002                 .WORD   $f404           ; MR=0: CTP
BOOTTIB:0004                 .WORD   $f410           ; MR=1: SSV
BOOTTIB:0006                 .WORD   $fc00           ; MR=2: RQ
BOOTTIB:0008                 .WORD   $fc00           ; ---TIB---
BOOTTIB:0008                                         ; f404: waitq
BOOTTIB:000A                 .WORD   $00ff           ; f405: flags/prior
BOOTTIB:000C                 .WORD   $0000           ; f406: SPlow
BOOTTIB:000E                 .WORD   $0200           ; f407: SPupr
BOOTTIB:0010                 .WORD   $01e7           ; f408: SP
BOOTTIB:0012                 .WORD   $01e7           ; f409: MP
BOOTTIB:0014                 .WORD   $01e7           ; f40a: BP
BOOTTIB:0016                 .WORD   $0368           ; f40b: IPC
BOOTTIB:0018                 .WORD   $f418           ; f40c: SEGB
BOOTTIB:001A                 .WORD   $fc00           ; f40d: hangp
BOOTTIB:001C                 .WORD   $0000           ; f40e: iorslt
BOOTTIB:001E                 .WORD   $fc00           ; f40f: sibs - NIL: no segs > 127
BOOTTIB:0020                 .WORD   $fc00           ; ---Seg dictionary---
BOOTTIB:0020                                         ; f410 ptr to sib 00
BOOTTIB:0022                 .WORD   $f412           ; f411 ptr to sib 01
BOOTTIB:0024                 .WORD   $f418           ; f412 sib01->segbase
BOOTTIB:0026                 .WORD   $01df           ; f413 sib01->segleng
BOOTTIB:0028                 .WORD   $0001           ; f414 sib01->segrefs
BOOTTIB:002A                 .WORD   $0000           ; f415 sib01->segaddr
BOOTTIB:002C                 .WORD   $0000           ; f416 sib01->segunit
BOOTTIB:002E                 .WORD   $0000           ; f417 seg01->prevsp
BOOTTIB:002E                 ; END OF SEGMENT

HDT:0000 ; segment global variables
HDT:0000 ; global1  char received from console (input)
HDT:0000 ; global2  integer 'current address'
HDT:0000 ; global3  boolean flag: has a 'current address'
HDT:0000 ; global4  address of console 0xfc10
HDT:0000 ; global5  temporary for TIB->SEGB address
HDT:0000 ; global6-7 HDT semaphore (HDT halts on this)
HDT:0000 ; global8  address of HDT info structure (0x22)
HDT:0000 ; global9-16 string(16): "0123456789abcdef"
HDT:0000 ; global17-22 Set of HEX chars ['0'..'9','A'..'F']
HDT:0000
HDT:0000 ; Segment type: Pure code
HDT:0000                 ; START OF SEGMENT
HDT:0000                 .WPTR   proctbl           ; ptr to proctbl
HDT:0002 ;
HDT:0002 ; procedure bootfd(loadbase : memp, unit: integer);
HDT:0002 ;
HDT:0002 ; local stack frame
HDT:0002 ; local1
HDT:0002 ; local2 address 0xff20
HDT:0002 ; local3
HDT:0002 ; local4
HDT:0002 ; local5
HDT:0002 ; local6 temporary value for argument1
HDT:0002 ; local7 temporary value for unit
HDT:0002 ; local8/argument1 loadbase
HDT:0002 ; local9/argument2 unit
HDT:0002                 .CPTR   exitic_bootpriam
HDT:0004 bootpriam       .WORD   $0007
HDT:0006                 LLA     6               ; copy loadbase/unit arguments into temporary
HDT:0008                 LLA     8
HDT:000A                 MOV     2
HDT:000C                 LDCI    $FF20           ; store address 0xff20 into local2
HDT:000F                 STL     2
HDT:0011                 SLDL    2               ; copy 0xff20 into local3
HDT:0012                 STL     3
HDT:0014                 SLDL    3               ; copy 0xff20 into local4
HDT:0015                 STL     4
HDT:0017                 SLDL    4               ; copy 0xff20 into local5
HDT:0018                 STL     5
HDT:001A                 SLDL    4               ; copy 0xff20 into local8/loadbase
HDT:001B                 STL     8
HDT:001D                 SLDL    3               ; copy 0xff25 into local9/argument2
HDT:001E                 INC     5
HDT:0020                 STL     9
HDT:0022 loc_F452                                ;
HDT:0022                 SLDL    9               ; store 0 into 0xff25
HDT:0023                 SLDC    0
HDT:0024                 STO
HDT:0025                 SLDL    9               ; set bit 10 of 0xff25 to 1
HDT:0026                 SLDC    1
HDT:0027                 SLDC    $A
HDT:0028                 SLDC    1
HDT:0029                 STP
HDT:002A loop_F45A                               ;
HDT:002A                 SLDL    8               ; address 0xff23
HDT:002B                 INC     3
HDT:002D                 SLDC    1               ; check bit 6 of 0xff23
HDT:002E                 SLDC    6
HDT:002F                 LDP
HDT:0030                 FJP     loc_F46B        ; exit if bit6 = 0
HDT:0032                 SLDL    8               ; address 0xff23
HDT:0033                 INC     3
HDT:0035                 SLDC    8               ; clear low 8 bits of 0xff23
HDT:0036                 SLDC    0
HDT:0037                 SLDC    0
HDT:0038                 STP
HDT:0039                 UJP     loop_F45A       ; wait loop until bit6 is 1
HDT:003B loc_F46B                                ;
HDT:003B                 SLDL    9               ; set bit11 of 0xff25 to 1
HDT:003C                 SLDC    1
HDT:003D                 SLDC    $B
HDT:003E                 SLDC    1
HDT:003F                 STP
HDT:0040                 SLDL    9               ; set bit 11 of 0xff25 to 0
HDT:0041                 SLDC    1
HDT:0042                 SLDC    $B
HDT:0043                 SLDC    0
HDT:0044                 STP
HDT:0045 loop_F475                               ;
HDT:0045                 SLDL    8               ; address 0xff23
HDT:0046                 INC     3
HDT:0048                 SLDC    1               ; check bit6 of 0xff23
HDT:0049                 SLDC    6
HDT:004A                 LDP
HDT:004B                 FJP     loop_F475       ; loop until bit6 = 1
HDT:004D                 SLDL    8               ; address 0xff23
HDT:004E                 INC     3
HDT:0050                 SLDC    8               ; clear low word of 0xff23
HDT:0051                 SLDC    0
HDT:0052                 SLDC    0
HDT:0053                 STP
HDT:0054                 SLDL    9               ; set bit10 of 0xff25 to 0
HDT:0055                 SLDC    1
HDT:0056                 SLDC    $A
HDT:0057                 SLDC    0
HDT:0058                 STP
HDT:0059                 SLDL    5               ; address 0xff21
HDT:005A                 INC     1
HDT:005C                 SLDC    $16             ; set 0xff21 = 22 (0x16)
HDT:005D                 STO
HDT:005E                 SLDL    5               ; address 0xff22
HDT:005F                 INC     2
HDT:0061                 SLDC    0               ; set 0xff22 = 0
HDT:0062                 STO
HDT:0063                 SLDL    5               ; address 0xff23
HDT:0064                 INC     3
HDT:0066                 SLDC    0               ; set 0xff23 = 0
HDT:0067                 STO
HDT:0068                 SLDL    9               ; set bit10 of 0xff25 = 1
HDT:0069                 SLDC    1
HDT:006A                 SLDC    $A
HDT:006B                 SLDC    1
HDT:006C                 STP
HDT:006D                 SLDL    8               ; set 0xff20 = 0
HDT:006E                 SLDC    0
HDT:006F                 STO
HDT:0070                 SLDL    8               ; address 0xff21
HDT:0071                 INC     1
HDT:0073                 SLDC    8
HDT:0074                 SLDC    0
HDT:0075                 SLDL    7               ; get unit number
HDT:0076                 SLDC    $10             ; restrict to unit 0..15
HDT:0077                 MODI
HDT:0078                 STP                     ; store into low byte of 0xff21
HDT:0079                 SLDL    3               ; address 0xff26
HDT:007A                 INC     6
HDT:007C                 SLDL    6               ; get loadbase
HDT:007D                 SLDC    2               ; multiply with 2 (make byte address)
HDT:007E                 MPI
HDT:007F                 SLDC    1               ; subtract 1
HDT:0080                 SBI
HDT:0081                 STO                     ; store into 0xff26
HDT:0082                 SLDL    3               ; address 0xff27
HDT:0083                 INC     7
HDT:0085                 LDCI    $D3FF           ; store 0xd3ff (-0x2301) into 0xff27
HDT:0088                 STO
HDT:0089                 SLDL    8               ; address 0xff23
HDT:008A                 INC     3
HDT:008C                 SLDC    8               ; store 0x53 into 0xff23
HDT:008D                 SLDC    0
HDT:008E                 LDCB    $53
HDT:0090                 STP
HDT:0091 loop_F4C1                               ;
HDT:0091                 SLDL    9               ; address 0xff25
HDT:0092                 SLDC    1               ; check bit 15 of 0xff25
HDT:0093                 SLDC    $F
HDT:0094                 LDP
HDT:0095                 FJP     loop_F4C1       ; loop until it becomes 1
HDT:0097                 SLDL    8               ; address 0xff21
HDT:0098                 INC     1
HDT:009A                 SLDC    2
HDT:009B                 SLDC    4               ; get bits 2-5 of 0xff21
HDT:009C                 LDP
HDT:009D                 SLDC    0               ; is code = 0?
HDT:009E                 EQUI
HDT:009F                 FJP     loc_F452        ; no, retry
HDT:00A1 exitic_bootpriam                        ; exit boot priam
HDT:00A1                 RPU     9
HDT:00A3                 .ALIGN
HDT:00A4                 .CPTR   exitic_proc4
HDT:00A6 proc4           .WORD   $0000
HDT:00A8                 LOD     1,1
HDT:00AB                 LDCI    $4153
HDT:00AE                 LOD     1,2
HDT:00B1                 ADI
HDT:00B2                 STO
HDT:00B3 loc_F4E3
HDT:00B3                 LOD     1,1
HDT:00B6                 SIND    0
HDT:00B7                 BNOT
HDT:00B8                 FJP     loc_F4E3
HDT:00BA loc_F4EA
HDT:00BA                 LOD     1,1
HDT:00BD                 LDCI    $41D0
HDT:00C0                 LOD     1,2
HDT:00C3                 ADI
HDT:00C4                 STO
HDT:00C5                 LOD     1,1
HDT:00C8                 INC     4
HDT:00CA                 SLDC    0
HDT:00CB                 STO
HDT:00CC                 LOD     1,1
HDT:00CF                 INC     5
HDT:00D1                 SLDC    0
HDT:00D2                 STO
HDT:00D3                 LOD     1,1
HDT:00D6                 SIND    0
HDT:00D7                 BNOT
HDT:00D8                 FJP     loc_F4EA
HDT:00DA exitic_proc4
HDT:00DA                 RPU     0
HDT:00DC ;
HDT:00DC ; procedure bootfd(loadbase : memp, unit : integer);
HDT:00DC ;
HDT:00DC ; boot from onboard floppy
HDT:00DC ;
HDT:00DC ; local stack frame
HDT:00DC ; local1 address 0xfc34
HDT:00DC ; local2
HDT:00DC ; local3
HDT:00DC ; local4
HDT:00DC ; local5
HDT:00DC ; argument1
HDT:00DC ; argument2
HDT:00DC
HDT:00DC                 .CPTR   exitic_bootfd   ; also temporary
HDT:00DE bootfd          .WORD   $0005
HDT:00E0                 LDCI    $100            ; shift unit# 8 bit left
HDT:00E3                 SLDL    7
HDT:00E4                 MPI
HDT:00E5                 STL     2               ; store as temporary
HDT:00E7                 LLA     1               ; store address 0xfc34 into local1
HDT:00E9                 LDCI    $3CC
HDT:00EC                 NGI
HDT:00ED                 STO
HDT:00EE retry                                   ;
HDT:00EE                 CPL     4               ; init FDC and DMA
HDT:00F0                 CPL     4               ; init again
HDT:00F2                 CPL     4               ; and again - now it should be really done!
HDT:00F4                 SLDL    1
HDT:00F5                 LDCI    $410F           ; issue command RESTORE
HDT:00F8                 SLDL    2               ; merge in unit#
HDT:00F9                 ADI
HDT:00FA                 STO
HDT:00FB loop_F52B                               ;
HDT:00FB                 SLDC    3               ; calc 12
HDT:00FC                 SLDC    4
HDT:00FD                 MPI
HDT:00FE                 STL     7               ; store in temporary
HDT:0100                 SLDL    1               ; get 0xfc34 (FD status)
HDT:0101                 SIND    0
HDT:0102                 BNOT                    ; check bit0 (BUSY)
HDT:0103                 FJP     loop_F52B       ; loop until BUSY=1
HDT:0105                 SLDL    1               ; programm DMA byte count = 0xf300 (0x0d00 bytes to read)
HDT:0106                 INC     6
HDT:0108                 SLDC    0
HDT:0109                 STO
HDT:010A                 SLDL    1
HDT:010B                 INC     7
HDT:010D                 SLDC    $D              ; 0xf3
HDT:010E                 NGI
HDT:010F                 STO
HDT:0110                 SLDL    1               ; program DMA base = 2* loadbase
HDT:0111                 INC     8
HDT:0113                 SLDL    6
HDT:0114                 SLDL    6
HDT:0115                 ADI
HDT:0116                 STO
HDT:0117                 SLDL    1
HDT:0118                 INC     9
>HDT:011A                 SLDL    6
HDT:011B                 SLDL    6
HDT:011C                 ADI
HDT:011D                 LDCI    $100
HDT:0120                 DVI
HDT:0121                 STO
HDT:0122                 SLDL    1               ; clear DMA address extension
HDT:0123                 INC     $A
HDT:0125                 SLDC    0
HDT:0126                 STO
HDT:0127                 SLDL    1               ; clear DMA status flags (interrupts and TCZI)
HDT:0128                 INC     5
HDT:012A                 SLDC    0
HDT:012B                 STO
HDT:012C                 SLDL    1               ; program DMA for RUN and IOM=fdc-to-ram
HDT:012D                 INC     4
HDT:012F                 SLDC    $11
HDT:0130                 STO
HDT:0131                 SLDL    1               ; set FDC sector =1
HDT:0132                 INC     2
HDT:0134                 SLDC    1
HDT:0135                 STO
HDT:0136                 SLDL    1               ; program FDC for READ MULTIPLE
HDT:0137                 LDCI    $4194
HDT:013A                 SLDL    2
HDT:013B                 ADI
HDT:013C                 STO
HDT:013D loop_F56D                               ; read DMA status
HDT:013D                 SLDL    1
HDT:013E                 SIND    5
HDT:013F                 SLDC    $A              ; select bits TCZI and DINT
HDT:0140                 LAND
HDT:0141                 SLDC    0
HDT:0142                 NEQI
HDT:0143                 FJP     loop_F56D       ; loop as long as they are 0
HDT:0145                 SLDL    1
HDT:0146                 SIND    5
HDT:0147                 SLDC    8               ; select bit TCZI
HDT:0148                 LAND
HDT:0149                 SLDC    0
HDT:014A                 EQUI
HDT:014B                 FJP     exitic_bootfd   ; if set, done
HDT:014D                 UJPL    retry           ; loop retry booting
HDT:0150 exitic_bootfd
HDT:0150                 RPU     7
HDT:0152 ;
HDT:0152 ; procedure emit(local4: char);
HDT:0152 ;
HDT:0152 ; send argument to console output
HDT:0152 ;
HDT:0152 ; local stack frame
HDT:0152 ; local1 dummy
HDT:0152 ; local2 dummy
HDT:0152 ; local3 dummy
HDT:0152 ; argument1 (local4)
HDT:0152                 .CPTR   exitic_emit
HDT:0154 emit            .WORD   $0003
HDT:0156 loc_F586                                ; load 0xfc12 (console status register)
HDT:0156                 SLDO    4
HDT:0157                 SIND    2
HDT:0158                 SLDC    1               ; mask out bit 1 (transmitter ready)
HDT:0159                 LAND
HDT:015A                 SLDC    0               ; is zero?
HDT:015B                 EQUI
HDT:015C                 FJP     loc_F586        ; no, loop
HDT:015E                 SLDO    4               ; load address 0xfc13 (console transmit)
HDT:015F                 INC     3
HDT:0161                 LDCB    $FF             ; load 255
HDT:0163                 SLDL    4               ; load char to emit
HDT:0164                 SBI                     ; invert (negative logic)
HDT:0165                 STO                     ; transmit
HDT:0166 exitic_emit                             ; exit
HDT:0166                 RPU     4
HDT:0168 ;
HDT:0168 ; procedure inchar;
HDT:0168 ;
HDT:0168 ; waits for char from console, echoes it
HDT:0168 ; and returns in global1
HDT:0168                 .CPTR   exitic_inchar
HDT:016A inchar          .WORD   $0000
HDT:016C loc_F59C                                ; address 0xfc12 (console status)
HDT:016C                 SLDO    4
HDT:016D                 SIND    2
HDT:016E                 SLDC    2               ; mask bit 2 (receiver full)
HDT:016F                 LAND
HDT:0170                 SLDC    0               ; is 0?
HDT:0171                 EQUI
HDT:0172                 FJP     loc_F59C        ; no, loop - no char received
HDT:0174                 LDCB    $7F             ; load 0x7f
HDT:0176                 SLDO    4               ; read 0xfc13 (receive buffer)
HDT:0177                 SIND    3
HDT:0178                 LDCB    $7F             ; mask out 7 bits
HDT:017A                 LAND
HDT:017B                 SBI                     ; invert (negative logic)
HDT:017C                 SRO     1               ; save received char
HDT:017E                 SLDO    1               ; get char
HDT:017F                 LDCB    $61             ; lower case?
HDT:0181                 GEQI
HDT:0182                 FJP     loc_F5BA        ; no, skip
HDT:0184                 SLDO    1               ; get char
HDT:0185                 LDCB    $20             ; convert to upper case
HDT:0187                 SBI
HDT:0188                 SRO     1               ; save it again
HDT:018A loc_F5BA                                ; get char
HDT:018A                 SLDO    1
HDT:018B                 CPG     5               ; echo
HDT:018D exitic_inchar                           ; exit
HDT:018D                 RPU     0
HDT:018F                 .ALIGN
HDT:0190 ;
HDT:0190 ; function readnumber : integer;
HDT:0190 ;
HDT:0190 ; read hex characters until a non-hex is found
HDT:0190 ; collect as a number, return it to caller
HDT:0190 ;
HDT:0190 ; local stack frame
HDT:0190 ; local1 variant record(integer, packed array(1..4) of 0..15)
HDT:0190 ; local2 dummy
HDT:0190 ; local3 dummy
HDT:0190 ; local4 dummy
HDT:0190 ; return value
HDT:0190                 .CPTR   exitic_readnumber
HDT:0192 readnumber      .WORD   $0004
HDT:0194                 SLDC    0               ; clear number collector variable
HDT:0195                 STL     1
HDT:0197 loc_F5C7                                ; address of local1
HDT:0197                 LLA     1
HDT:0199                 SLDC    4               ; array[4] (4 bits)
HDT:019A                 SLDC    $C
HDT:019B                 LLA     1               ; address of local1
HDT:019D                 SLDC    4               ; array(3) (4 bits)
HDT:019E                 SLDC    8
HDT:019F                 LDP                     ; copy array(4) := array(3)
HDT:01A0                 STP
HDT:01A1                 LLA     1               ; copy array(3) := array(2)
HDT:01A3                 SLDC    4
HDT:01A4                 SLDC    8
HDT:01A5                 LLA     1
HDT:01A7                 SLDC    4
HDT:01A8                 SLDC    4
HDT:01A9                 LDP
HDT:01AA                 STP
HDT:01AB                 LLA     1               ; copy array(2) := array(1)
HDT:01AD                 SLDC    4
HDT:01AE                 SLDC    4
HDT:01AF                 LLA     1
HDT:01B1                 SLDC    4
HDT:01B2                 SLDC    0
HDT:01B3                 LDP
HDT:01B4                 STP
HDT:01B5                 SLDO    1               ; get char read
HDT:01B6                 LDCB    $39             ; is less equal '9'?
HDT:01B8                 LEQI
HDT:01B9                 FJP     loc_F5F6        ; no, skip
HDT:01BB                 LLA     1               ; address array(1)
HDT:01BD                 SLDC    4
HDT:01BE                 SLDC    0
HDT:01BF                 SLDO    1               ; ord(input char)
HDT:01C0                 LDCB    $30             ; subtract ord('0') from char
HDT:01C2                 SBI
HDT:01C3                 STP                     ; store into array(1)
HDT:01C4                 UJP     loc_F601        ; skip else part
HDT:01C6 loc_F5F6                                ; address of array(1)
HDT:01C6                 LLA     1
HDT:01C8                 SLDC    4
HDT:01C9                 SLDC    0
HDT:01CA                 SLDO    1               ; ord(input char)
HDT:01CB                 LDCB    $41             ; subtract ord('A')
HDT:01CD                 SBI
HDT:01CE                 SLDC    $A              ; add 10
HDT:01CF                 ADI
HDT:01D0                 STP                     ; store in array(1)
HDT:01D1 loc_F601                                ; expect another char
HDT:01D1                 CPG     6
HDT:01D3                 SLDO    1               ; get it
HDT:01D4                 LAO     17              ; if char in ['0'..'9', 'A'..'F'] then
HDT:01D6                 LDM     5
HDT:01D8                 SLDC    5
HDT:01D9                 INN
HDT:01DA                 BNOT
HDT:01DB                 FJP     loc_F5C7        ; loop
HDT:01DD                 SLDL    1               ; return local1 (collected number)
HDT:01DE                 STL     5
HDT:01E0 exitic_readnumber                       ; exit
HDT:01E0                 RPU     4
HDT:01E2 ;
HDT:01E2 ; procedure reboot
HDT:01E2 ;
HDT:01E2 ; boot from the specified unit, if any, otherwise
HDT:01E2 ; boot from unit 0
HDT:01E2 ;
HDT:01E2 ; local stack frame
HDT:01E2 ; local1 temporary
HDT:01E2                 .CPTR   exitic_reboot
HDT:01E4 reboot          .WORD   $0001
HDT:01E6                 SLDO    3               ; get global3 (number flag)
HDT:01E7                 BNOT                    ; if "has a number" then skip
HDT:01E8                 FJP     loc_F61D
HDT:01EA                 SLDC    0               ; otherwise clear number (boot device 0)
HDT:01EB                 SRO     2
HDT:01ED loc_F61D                                ; load address 0x2000
HDT:01ED                 LDCI    $2000
HDT:01F0                 STL     1               ; store as temporary
HDT:01F2                 SLDO    8               ; get global8
HDT:01F3                 SLDO    2               ; get unit number (either 0 or number entered before 'R')
HDT:01F4                 STO                     ; save it (in HDT info at 0x22)
HDT:01F5                 SLDO    2               ; get unit number
HDT:01F6                 SLDC    $10             ; shift 4 bits right (i.e. bits 7..4)
HDT:01F7                 DVI
HDT:01F8                 SLDC    0               ; are there some bits set?
HDT:01F9                 EQUI
HDT:01FA                 FJP     loc_F632        ; no skip
HDT:01FC                 SLDO    2               ; push unit
HDT:01FD                 SLDL    1               ; push address
HDT:01FE                 CPG     2               ; boot from PRIAM drive
HDT:0200                 UJP     loc_F636        ; continue
HDT:0202 loc_F632                                ; push unit
HDT:0202                 SLDO    2
HDT:0203                 SLDL    1               ; push address
HDT:0204                 CPG     3               ; boot from FDC
HDT:0206 loc_F636                                ; address 0x2008 (TIB->SEGB)
HDT:0206                 SLDL    1
HDT:0207                 SLDC    8
HDT:0208                 ADI
HDT:0209                 SRO     5               ; store in temporary
HDT:020B                 SLDO    5               ; get TIB->SEGB address
HDT:020C                 SLDO    5               ; get SEGB value
HDT:020D                 SIND    0
HDT:020E                 SLDC    $C              ; add offset to actual segment (byte addr 0x2030)
HDT:020F                 ADI
HDT:0210                 STO                     ; set it into SEGB
HDT:0211                 LDCI    -3              ; address RQ for SPR
HDT:0214                 SLDL    1               ; get address of TIB to execute (boot TIB)
HDT:0215                 SPR                     ; set RQ
HDT:0216                 LAO     6               ; wait on HDT semaphore, switch context to boot code
HDT:0218                 WAIT
HDT:0219 exitic_reboot                           ; exit booter
HDT:0219                 RPU     1
HDT:021B                 .ALIGN
HDT:021C casetbl_F64C    .WORD   $0000           ; case low index
HDT:021E                 .WORD   $0007           ; case high index
HDT:0220                 .WORD   $0002           ; case idx 0 case0_F70A
HDT:0222                 .WORD   $0007           ; case idx 1 case1_F70F
HDT:0224                 .WORD   $000c           ; case idx 2 case2_F714
HDT:0226                 .WORD   $0011           ; case idx 3 case3_F719
HDT:0228                 .WORD   $0016           ; case idx 4 case4_F71E
HDT:022A                 .WORD   $001c           ; case idx 5 case5_F724
HDT:022C                 .WORD   $0022           ; case idx 6 case6_F72A
HDT:022E                 .WORD   $0028           ; case idx 7 case7_F730
HDT:0230 a0123456789abcd .ASC    '0123456789ABCDEF'
HDT:0240 set_of_hex      .WORD   $0000           ; Set of HEX chars: [ '0'..'9', 'A'..'F' ]
HDT:0240                                         ; bitmap 0000 0000 0000 0000
HDT:0242                 .WORD   $0000           ; bitmap 0000 0000 0000 0000
HDT:0244                 .WORD   $0000           ; bitmap 0000 0000 0000 0000
HDT:0246                 .WORD   $03ff           ; bitmap 0000 0011 1111 1111
HDT:0248                 .WORD   $007e           ; bitmap 0000 0000 0111 1110
HDT:024A ; local stack frame
HDT:024A ; local1 temporary value for high byte of timer0 init
HDT:024A ; local2 temporary init value for CTRL1
HDT:024A ; temp3 boolean: is hdt sema initialized?
HDT:024A ; temp4 memp: temporary for various addresses
HDT:024A                 .CPTR   exitic_init
HDT:024C init            .WORD   $0004
HDT:024E                 LAO     6               ; address of global6: semaphore
HDT:0250                 DUP1                    ; seminit(global6,0);
HDT:0251                 SLDC    0               ; |
HDT:0252                 STO                     ; |
HDT:0253                 INC     1               ; |
HDT:0255                 LDCN                    ; |
HDT:0256                 STO                     ; |------
HDT:0257                 LDCI    $3F0            ; load 0xfc10 (address of console)
HDT:025A                 NGI
HDT:025B                 STL     4               ; save temporary
HDT:025D                 SLDL    4               ; copy console address to global4
HDT:025E                 SRO     4
HDT:0260                 SLDO    4               ; load 0xfc18 (system environment switch)
HDT:0261                 IND     8
HDT:0263                 LDCB    $80             ; mask out bit 7 (boot into HDT)
HDT:0265                 LAND
HDT:0266                 SLDC    0
HDT:0267                 EQUI
HDT:0268                 FJP     enter_hdt       ; branch if bit is 1 (enter monitor)
HDT:026A                 LDCI    -3              ; This code is not yet understood:
HDT:026A                                         ; if SES bit 7 is 0, this will be called.
HDT:026A                                         ; This is possibly for custom configurations or ROMs.
HDT:026A                                         ;
HDT:026A                                         ; -3 address RQ register to be set
HDT:026D                 LDCI    $4000           ; load 0x4000
HDT:0270                 LDCI    $401            ; load 0x401
HDT:0273                 SLDO    4               ; address 0xfc18 (system environment switch)
HDT:0274                 IND     8
HDT:0276                 LDCB    $20             ; test bit 5 (undocumented - reserved for user apps!)
HDT:0278                 LAND                    ; is either 0x00 or 0x20
HDT:0279                 MPI                     ; multiply: results in 0x0000 or 0x8020
HDT:027A                 ADI                     ; add offset 0x4000 -> 0x4000 or 0xc020
HDT:027B                 SPR                     ; put into request queue
HDT:027C                 LAO     6               ; wait on semaphore
HDT:027E                 WAIT
HDT:027F ; area 0x22
HDT:027F ; offset 0,1 HDT semaphore?
HDT:027F ; offset 2 SSV for HDT segment
HDT:027F ; offset 3 RQ for HDT segment
HDT:027F enter_hdt                               ; HDT info structure
HDT:027F                 LDCB    $22
HDT:0281                 SRO     8               ; store as global8
HDT:0283                 SLDO    8               ; get address of sema
HDT:0284                 SIND    0               ; count
HDT:0285                 SLDO    8
HDT:0286                 SIND    1               ; link
HDT:0287                 ADI
HDT:0288                 LDCI    $4005           ; load 0xbffb
HDT:028B                 NGI
HDT:028C                 EQUI                    ; compare semaphore with init value
HDT:028C                                         ; is 0 in cold start
HDT:028D                 STL     3               ; save it temporary
HDT:028F                 SLDL    3
HDT:0290                 FJP     cold_init
HDT:0292                 LDCI    -2              ; ---reentering HDT---
HDT:0292                                         ; address SSV for SPR
HDT:0295                 SLDO    8               ; get SSV for HDT
HDT:0296                 SIND    2
HDT:0297                 SPR                     ; set it in CPU register
HDT:0298                 LDCI    -3              ; address RQ for SPR
HDT:029B                 SLDO    8               ; get RQ for HDT
HDT:029C                 SIND    3
HDT:029D                 SPR                     ; set it in CPU register
HDT:029E cold_init                               ; invert init flag
HDT:029E                 SLDL    3
HDT:029F                 BNOT
HDT:02A0                 SLDO    8               ; semaphore count
HDT:02A1                 SIND    0
HDT:02A2                 LOR                     ; merge
HDT:02A3                 FJPL    loc_F777        ; is not cold start and no waiting on semaphore, branch
HDT:02A6                 LDCI    $3E0            ; ---reinitialize---
HDT:02A9                 NGI                     ; load 0xfc20 (console baud rate)
HDT:02AA                 STL     4               ; store as temporary
HDT:02AC                 SLDL    4               ; address 0xfc24 (system status register)
HDT:02AD                 INC     4
HDT:02AF                 LDCB    $80             ; enforce bus init (BINIT)
HDT:02B1                 STO
HDT:02B2                 SLDL    4               ; address 0xfc24 (system status register)
HDT:02B3                 INC     4
HDT:02B5                 SLDC    1               ; clear BERR flag by writing a 1
HDT:02B5                                         ; disable interrupt system
HDT:02B6                 STO
HDT:02B7                 SLDL    4               ; address 0xfc23 (timer mode register)
HDT:02B8                 INC     3
HDT:02BA                 LDCB    $34             ; program counter 0 for 16 bit operation, mode 2
HDT:02BC                 STO
HDT:02BD                 SLDL    4               ; address 0xfc23 (timer mode register)
HDT:02BE                 INC     3
HDT:02C0                 LDCB    $70             ; program counter 1 for 16 bit operation, mode 0
HDT:02C2                 STO
HDT:02C3                 SLDL    4               ; address 0xfc23 (timer mode register)
HDT:02C4                 INC     3
HDT:02C6                 LDCB    $B0             ; program counter 2 for 16 bit operation, mode 0
HDT:02C8                 STO
HDT:02C9                 SLDC    0               ; default value for timer0 high byte (=0)
HDT:02CA                 STL     1
HDT:02CC                 LDCB    $58             ; default console CTRL1 reg value (negative logic):
HDT:02CC                                         ; bit 7: normal mode
HDT:02CC                                         ; bit 6: non break mode
HDT:02CC                                         ; bit 5: single stop bit
HDT:02CC                                         ; bit 4: non echo mode
HDT:02CC                                         ; bit 3: no parity
HDT:02CC                                         ; bit 2: receiver enabled
HDT:02CC                                         ; bit 1: RTSbar=0
HDT:02CC                                         ; bit 0: DTRbar=0
HDT:02CE                 STL     2
HDT:02D0                 SLDO    4               ; address 0xfc18 (sytem environment switch)
HDT:02D1                 IND     8
HDT:02D3                 SLDC    7               ; mask out low 3 bits for baud rate
HDT:02D4                 LAND
HDT:02D5                 XJP     casetbl_F64C    ; case of baudrate value
HDT:02D8 loc_F708                                ; compiler generates this even if not used
HDT:02D8                 UJP     otherwise_F73D
HDT:02DA case0_F70A                              ; address 0xfc20
HDT:02DA                 SLDL    4
HDT:02DB                 SLDC    2               ; timer value for 19200Bd
HDT:02DC                 STO
HDT:02DD                 UJP     otherwise_F73D  ; exit case
HDT:02DF case1_F70F                              ; address 0xfc20
HDT:02DF                 SLDL    4
HDT:02E0                 SLDC    4               ; timer value for 9600Bd
HDT:02E1                 STO
HDT:02E2                 UJP     otherwise_F73D  ; exit case
HDT:02E4 case2_F714                              ; address 0xfc20
HDT:02E4                 SLDL    4
HDT:02E5                 SLDC    8               ; timer value for 4800 Bd
HDT:02E6                 STO
HDT:02E7                 UJP     otherwise_F73D  ; exit case
HDT:02E9 case3_F719                              ; address 0xfc20
HDT:02E9                 SLDL    4
HDT:02EA                 SLDC    $10             ; timer value for 2400Bd
HDT:02EB                 STO
HDT:02EC                 UJP     otherwise_F73D
HDT:02EE case4_F71E                              ; address 0xfc20
HDT:02EE                 SLDL    4
HDT:02EF                 LDCB    $21             ; timer value for 1200Bd
HDT:02F1                 STO
HDT:02F2                 UJP     otherwise_F73D  ; exit case
HDT:02F4 case5_F724                              ; address 0xfc20
HDT:02F4                 SLDL    4
HDT:02F5                 LDCB    $41             ; timer value for 600Bd
HDT:02F7                 STO
HDT:02F8                 UJP     otherwise_F73D  ; exit case
HDT:02FA case6_F72A                              ; address 0xfc20
HDT:02FA                 SLDL    4
HDT:02FB                 LDCB    $82             ; timer value for 300Bd
HDT:02FD                 STO
HDT:02FE                 UJP     otherwise_F73D  ; exit case
HDT:0300 case7_F730                              ; address 0xfc20
HDT:0300                 SLDL    4
HDT:0301                 LDCB    $5D             ; timer value low for 110Bd
HDT:0303                 STO
HDT:0304                 SLDC    1               ; fix high byte for timer 0
HDT:0305                 STL     1
HDT:0307                 LDCB    $78             ; Modify settings for console CTRL1 register:
HDT:0307                                         ; as above, but
HDT:0307                                         ; bit 5: 2 stop bits
HDT:0309                 STL     2
HDT:030B                 UJP     otherwise_F73D
HDT:030D otherwise_F73D                          ; address 0xfc20 (high byte)
HDT:030D                 SLDL    4
HDT:030E                 SLDL    1               ; get high byte value, is 1 for 110 Bd, 0 else
HDT:030F                 STO                     ; store and activate timer
HDT:0310                 SLDL    4               ; address 0xfc21 (timer1)
HDT:0311                 INC     1               ; initialize timer1 wit 0x0001
HDT:0313                 SLDC    1               ; |
HDT:0314                 STO                     ; |low byte
HDT:0315                 SLDL    4               ; |
HDT:0316                 INC     1               ; |
HDT:0318                 SLDC    0               ; |high byte
HDT:0319                 STO                     ; |------
HDT:031A                 SLDL    4               ; initialize timer2 with 0x0001
HDT:031B                 INC     2               ; |
HDT:031D                 SLDC    1               ; |low byte
HDT:031E                 STO                     ; |
HDT:031F                 SLDL    4               ; |
HDT:0320                 INC     2               ; |
HDT:0322                 SLDC    0               ; | high byte
HDT:0323                 STO                     ; |------
HDT:0324                 SLDO    4               ; address 0xfc10 (console)
HDT:0325                 INC     2               ; address 0xfc12 (console status/DLE register)
HDT:0327                 SLDO    4               ; read out status (should be 00 after BINIT/bus reset)
HDT:0328                 SIND    2
HDT:0329                 STO                     ; store to DLE register
HDT:0329                                         ; Note: this is a weird way of getting a 00 into DLE register
HDT:0329                                         ; Note2: the console is used in ASYNC mode anyway
HDT:032A                 SLDO    4               ; address 0xfc10 (console CTRL1)
HDT:032B                 SLDL    2               ; get default value (0x58 or 0x78)
HDT:032C                 STO                     ; store it
HDT:032D                 SLDO    4               ; address 0xfc11 (console CTRL2)
HDT:032E                 INC     1
HDT:0330                 LDCB    $FE             ; set CTRL mode (negative logic):
HDT:0330                                         ; bit 7,6 = 00: 8 bits
HDT:0330                                         ; bit 5 = 0 asynchronous mode
HDT:0330                                         ; bit 4 = 0 even parity (ignored)
HDT:0330                                         ; bit 3 = 0 receiver clock rate1 (x32)
HDT:0330                                         ; bit 2-0 = 001: clock rate1 (x32)
HDT:0332                 STO                     ; store
HDT:0333                 SLDL    3               ; get cold start flag (=0 on boot)
HDT:0334                 FJP     loc_F769        ; skip if cold start
HDT:0336                 LAO     6               ; wait on HDT semaphore
HDT:0338                 WAIT
HDT:0339 loc_F769                                ; load 0xfc24 (system status register)
HDT:0339                 SLDL    4
HDT:033A                 SIND    4
HDT:033B                 LDCB    $80             ; mask INIT bit
HDT:033D                 LAND
HDT:033E                 SLDC    0               ; is it 0?
HDT:033F                 EQUI
HDT:0340                 FJP     loc_F777        ; no, skip
HDT:0342                 SLDC    0               ; set hasnumber flag := false
HDT:0343                 SRO     3
HDT:0345                 CPG     8               ; goto reboot (does not return)
HDT:0347 loc_F777                                ; global8 index 1
HDT:0347                 SLDO    8
HDT:0348                 INC     1
HDT:034A                 SLDC    0               ; clear
HDT:034B                 STO
HDT:034C                 LAO     9               ; globa lstring store (16 bytes)
HDT:034E                 LCA     a0123456789abcd ; address of HEX conversion constants
HDT:0351                 MOV     8               ; move into global
HDT:0353                 LAO     17              ; global set of hex chars
HDT:0355                 LDC     set_of_hex,5    ; load initial values ['0'..'9','A'..'F']
HDT:0359                 SLDC    5               ; length of init value
HDT:035A                 ADJ     5               ; pack to 5 words
HDT:035C                 STM     5               ; store in global
HDT:035E exitic_init                             ; done with initialization
HDT:035E                 RPU     4
HDT:0360 ; local stack frame
HDT:0360 ; hmmm: this is the top level procedure,
HDT:0360 ; so global == local
HDT:0360 ; SLDL1 is the same as SLDO1
HDT:0360 ; so look up the various globals...
HDT:0360                 .CPTR   exitic_proc1
HDT:0362 proc1           .WORD   $0015
HDT:0364                 SLDC    6
HDT:0365                 LSL     0
HDT:0367                 SPR
HDT:0368 ENTRY_POINT                             ; IPC start on reset points here
HDT:0368                 CPG     9               ; initialize timers/console
HDT:036A loc_F79A                                ; load CR
HDT:036A                 SLDC    $D
HDT:036B                 CPG     5               ; emit
HDT:036D                 SLDC    $A              ; load LF
HDT:036E                 CPG     5               ; emit
HDT:0370                 LDCB    '#'             ; load '#'
HDT:0372                 CPG     5               ; emit
HDT:0374                 SLDC    0               ; global2 := 0 (current address)
HDT:0375                 STL     2
HDT:0377                 SLDC    0               ; global3 := 0 (flag T/F, has address)
HDT:0378                 STL     3
HDT:037A                 CPG     6               ; wait for input char from console
HDT:037C                 SLDL    1               ; get char received
HDT:037D                 LLA     17              ; address of set of hex (global17)
HDT:037F                 LDM     5               ; load 5 words of set
HDT:0381                 SLDC    5               ; set is 5 words
HDT:0382                 INN                     ; check if inchar in ['0'-'9','A'-'F']
HDT:0383                 FJP     loc_F7BD        ; no, skip
HDT:0385                 SLDC    0               ; return value
HDT:0386                 CPG     7               ; read a number
HDT:0388                 STL     2               ; store global2 (current address)
HDT:038A                 SLDC    1               ; set flag: has address
HDT:038B                 STL     3
HDT:038D loc_F7BD                                ; arrives here if non-hex char found
HDT:038D                 SLDL    1               ; load input char
HDT:038E                 LDCB    'R'             ; is it 'R' (reboot)
HDT:0390                 EQUI
HDT:0391                 FJP     loc_F7C5        ; no, skip
HDT:0393                 CPG     8               ; go reboot
HDT:0395 loc_F7C5                                ; load input char
HDT:0395                 SLDL    1
HDT:0396                 LDCB    'P'             ; is it 'P'?
HDT:0398                 EQUI
HDT:0399                 FJP     loc_F7CE        ; no, skip
HDT:039B                 LLA     6               ; wait on HDT sema, i.e. context switch back to
HDT:039B                                         ; interrupted process
HDT:039D                 WAIT
HDT:039E loc_F7CE                                ; emit '?'
HDT:039E                 LDCB    '?'
HDT:03A0                 CPG     5
HDT:03A2                 UJPL    loc_F79A        ; loop
HDT:03A5 exitic_proc1
HDT:03A5                 CXG     3,$18
HDT:03A8                 RPU     $15

HDT:03AA proctbl
HDT:03AA                 .WPTR   init
HDT:03AC                 .WPTR   reboot
HDT:03AE                 .WPTR   readnumber
HDT:03B0                 .WPTR   inchar
HDT:03B2                 .WPTR   emit
HDT:03B4                 .WPTR   proc4
HDT:03B6                 .WPTR   bootfd
HDT:03B8                 .WPTR   bootpriam
HDT:03BA                 .WPTR   proc1
HDT:03BC byte_F7EC       .BYTE   $01             ; seg#: seg01
HDT:03BD                 .BYTE   $09             ; # of procs in segment
HDT:03BE                 .BYTE   $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 ; padding
HDT:03BE                 .BYTE   $00,$00
HDT:03BE                 ; END OF SEGMENT
