OpenCores
URL https://opencores.org/ocsvn/thor/thor/trunk

Subversion Repositories thor

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /thor
    from Rev 27 to Rev 28
    Reverse comparison

Rev 27 → Rev 28

/trunk/software/boot_tb/keyboard.asm
0,0 → 1,573
 
; ============================================================================
; __
; \\__/ o\ (C) 2015 Robert Finch, Stratford
; \ __ / All rights reserved.
; \/_// robfinch<remove>@finitron.ca
; ||
;
;
; This source file is free software: you can redistribute it and/or modify
; it under the terms of the GNU Lesser General Public License as published
; by the Free Software Foundation, either version 3 of the License, or
; (at your option) any later version.
;
; This source file is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; GNU General Public License for more details.
;
; You should have received a copy of the GNU General Public License
; along with this program. If not, see <http://www.gnu.org/licenses/>.
;
;
; KeyState1_
; 76543210
; + = keyup
;
; KeyState2_
; 76543210
; |||||||+ = shift
; ||||||+- = alt
; |||||+-- = control
; ||||+--- = numlock
; |||+---- = capslock
; ||+----- = scrolllock
; |+------ =
; +------- = extended
;
; ============================================================================
;
; Static Device Control Block for Keyboard
;
align 8
byte 8,"keyboard " ; DCB_Name string: first byte is length, 11 chars max
dh 0 ; DCB_Type 0 = character
dw 0 ; DCB_nBPB
dw 0 ; DCB_LastErc last error code
dw 0 ; DCB_StartBlock starting block number (partitioned devices)
dw 0 ; DCB_nBlocks number of blocks on device
dw KeybdCmdProc ; DCB_pCmdProc pointer to command processor routine
byte 1 ; DCB_ReentCount re-entrancy count (1 to 255)
byte 0 ; DCB_fSingleUser
fill.b 6,0
dw 0 ; DCB_hJob handle to associated job
dw 0 ; DCB_Mbx
dw 0 ; DCB_pSema pointer to device semaphore
dw 0 ; DCB_Resv1 reserved
dw 0 ; DCB_Resv2 reserved
 
align 8
kbd_jmp:
jmp KeybdIRQ[c0]
 
KeybdCmdProc:
rts
 
KeybdInit:
addui sp,sp,#-8
sws c1,[sp]
lla r1,cs:kbd_jmp ; set interrupt vector
ldi r2,#195
bsr set_vector
lws c1,[sp]
addui sp,sp,#8
KeybdClearBuf:
lw r29,zs:RunningJCB_
sb r0,zs:JCB_KeybdHead[r29] ; clear buffer pointers
sb r0,zs:JCB_KeybdTail[r29]
sb r0,zs:JCB_KeyState1[r29]
sb r0,zs:JCB_KeyState2[r29]
sb r0,zs:JCB_KeybdLEDs[r29]
ldi r1,#64
sb r1,zs:JCB_KeybdBufSz[r29]
rts
 
; Check if a key is available
; Returns:
; r1 = non-zero if key is available, otherwise zero
;
public KeybdCheckForKey
addui sp,sp,#-8
sw r2,[sp]
lw r2,zs:RunningJCB_
lcu r1,zs:JCB_KeybdHead[r2]
shrui r2,r1,#8
zxb r1,r1
eor r1,r1,r2
lw r2,[sp]
addui sp,sp,#8
rts
endpublic
 
public KeybdGetCharWait:
ldi r1,#-1
lw r29,zs:RunningJCB_
sb r1,zs:JCB_KeybdWaitFlag[r29]
br KeybdGetChar
endpublic
 
public KeybdGetCharNoWait:
lw r1,zs:RunningJCB_
sb r0,zs:JCB_KeybdWaitFlag[r1]
br KeybdGetChar
endpublic
 
; Wait for a keyboard character to be available
; Returns (-1) if no key available
; Return key >= 0 if key is available
;
;
KeybdGetChar:
KeybdGetChar1:
addui sp,sp,#-64
sw r2,[sp]
sws c1,8[sp] ; save off link register
sws hs,16[sp]
sws hs.lmt,24[sp]
sw r3,32[sp]
sws ds,40[sp]
sws ds.lmt,48[sp]
ldis hs,#$FFD00000
ldis hs.lmt,#$100000
lws ds,zs:RunningJCB_
ldis ds.lmt,#$10000
.0002:
.0003:
; Allow for some interruptible code to occur
nop nop nop nop
nop nop nop nop
nop nop nop nop
 
; Get head and tail pointers as a single load
; then separate
; sei
sync
lcu r1,JCB_KeybdHead ; 1 memory op instead of 2
shrui r2,r1,#8 ; r2 = tail index
zxb r1,r1 ; r1 = head index
cmp p0,r1,r2 ; is there anything in the buffer ?
p0.ne br .0006 ; yes, branch
cli
lb r1,JCB_KeybdWaitFlag ; are we waiting indefinitely for a key ?
tst p0,r1
p0.lt br .0003 ; if yes, branch
br .0008 ; otherwise exit no key available
.0006:
ldi r1,#$300
sc r1,hs:LEDS
lbu r1,JCB_KeybdBuf[r2] ; get scan code from buffer
lbu r3,JCB_KeybdBufSz
addui r2,r2,#1 ; increment tail index
cmp p0,r2,r3
p0.geu mov r2,r0 ; take modulus
sb r2,JCB_KeybdTail ; and store it back
cli
.0001:
cmp p0,r1,#SC_KEYUP ; keyup scan code ?
p0.eq br .doKeyup
cmp p0,r1,#SC_EXTEND; extended scan code ?
p0.eq br .doExtend
cmp p0,r1,#$14 ; control ?
p0.eq br .doCtrl
cmp p0,r1,#$12 ; left shift
p0.eq br .doShift
cmp p0,r1,#$59 ; right shift
p0.eq br .doShift
cmp p0,r1,#SC_NUMLOCK
p0.eq br .doNumLock
cmp p0,r1,#SC_CAPSLOCK
p0.eq br .doCapsLock
cmp p0,r1,#SC_SCROLLLOCK
p0.eq br .doScrollLock
cmp p0,r1,#SC_ALT
p0.eq br .doAlt
lb r2,JCB_KeyState1
sb r0,JCB_KeyState1
biti p0,r2,#1 ; was keyup set ?
p0.ne br .0003 ; if yes, ignore and branch back
lb r2,JCB_KeyState2 ; Is extended code ?
biti p0,r2,#$80
p0.eq br .0010
lb r2,JCB_KeyState2 ; clear extended bit
andi r2,r2,#$7F
sb r2,JCB_KeyState2
sb r0,JCB_KeyState1 ; clear keyup
andi r1,r1,#$7F
lbu r1,cs:keybdExtendedCodes[r1]
br .0008
.0010:
biti p0,r2,#4 ; Is Cntrl down ?
p0.eq br .0009
andi r1,r1,#$7F
lbu r1,cs:keybdControlCodes[r1]
br .0008
.0009:
biti p0,r2,#33 ; Is shift or CAPS-Lock down ?
p0.ne lbu r1,cs:shiftedScanCodes[r1]
p0.eq lbu r1,cs:unshiftedScanCodes[r1]
.0008:
lw r2,[sp]
lws c1,8[sp]
lws hs,16[sp]
lws hs.lmt,24[sp]
lw r3,32[sp]
lws ds,40[sp]
lws ds.lmt,48[sp]
addui sp,sp,#64
rts
 
.doKeyup:
lb r2,JCB_KeyState1 ; set keyup flag
ori r2,r2,#1
sb r2,JCB_KeyState1
br .0003
.doExtend:
lb r2,JCB_KeyState2
ori r2,r2,#$80
sb r2,JCB_KeyState2
br .0003
.doCtrl:
lb r2,JCB_KeyState1
biti p0,r2,#1
lbu r2,JCB_KeyState2
p0.eq ori r2,r2,#4
p0.ne andi r2,r2,#~4
sb r2,JCB_KeyState2
br .0003
.doAlt:
lb r2,JCB_KeyState1
biti p0,r2,#1
lbu r2,JCB_KeyState2
p0.eq ori r2,r2,#2
p0.ne andi r2,r2,#~2
sb r2,JCB_KeyState2
br .0003
.doShift:
lb r2,JCB_KeyState1
biti p0,r2,#1
lbu r2,JCB_KeyState2
p0.eq ori r2,r2,#1
p0.ne andi r2,r2,#~1
sb r2,JCB_KeyState2
br .0003
.doNumLock:
lbu r2,JCB_KeyState2
eori r2,r2,#16
sb r2,JCB_KeyState2
bsr KeybdSetLEDStatus
br .0003
.doCapsLock:
lbu r2,JCB_KeyState2
eori r2,r2,#32
sb r2,JCB_KeyState2
bsr KeybdSetLEDStatus
br .0003
.doScrollLock:
lbu r2,JCB_KeyState2
eori r2,r2,#64
sb r2,JCB_KeyState2
bsr KeybdSetLEDStatus
br .0003
 
;------------------------------------------------------------------------------
; Set the keyboard LED status leds.
; Trashes r1, p0
;------------------------------------------------------------------------------
 
KeybdSetLEDStatus:
addui r27,r27,#-8
sws c1,[r27]
sb r0,KeybdLEDs
lb r1,JCB_KeyState2
biti p0,r1,#16
p0.ne lb r1,KeybdLEDs ; set bit 1 for Num lock, 0 for scrolllock , 2 for caps lock
p0.ne ori r1,r1,#2
p0.ne sb r1,KeybdLEDs
lb r1,JCB_KeyState2
biti p0,r1,#32
p0.ne lb r1,KeybdLEDs
p0.ne ori r1,r1,#4
p0.ne sb r1,KeybdLEDs
lb r1,JCB_KeyState2
biti p0,r1,#64
p0.ne lb r1,KeybdLEDs
p0.ne ori r1,r1,#1
p0.ne sb r1,KeybdLEDs
ldi r1,#$ED
sb r1,hs:KEYBD ; set status LEDs command
bsr KeybdWaitTx
bsr KeybdRecvByte
cmpi p0,r1,#$FA
lb r1,KeybdLEDs
sb r1,hs:KEYBD
bsr KeybdWaitTx
bsr KeybdRecvByte
lws c1,[r27]
addui r27,r27,#8
rts
 
;------------------------------------------------------------------------------
; Receive a byte from the keyboard, used after a command is sent to the
; keyboard in order to wait for a response.
;
; Returns:
; r1 >= 0 if a scancode is available
; r1 = -1 on timeout
;------------------------------------------------------------------------------
;
KeybdRecvByte:
addui r27,r27,#-16
sws c1,8[r27]
sw r3,[r27]
ldi r3,#20 ; wait up to .2s
.0003:
bsr KeybdWaitBusy
lb r1,hs:KEYBD+1 ; wait for response from keyboard
biti p0,r1,#$80 ; is input buffer full ?
p0.ne br .0004 ; yes, branch
bsr Wait10ms ; wait a bit
addui r3,r3,#-1
tst p0,r3
p0.ne br .0003 ; go back and try again
lw r3,[r27] ; timeout
lws c1,8[r27]
addui r27,r27,#16
ldi r1,#-1
rts
.0004:
lvb r1,hs:KEYBD ; get scancode
zxb r1,r1 ; convert to unsigned char
sb r0,hs:KEYBD+1 ; clear recieve state
lw r3,[r27]
lws c1,8[r27]
addui r27,r27,#16
rts ; return char in r1
 
;------------------------------------------------------------------------------
; Wait until the keyboard isn't busy anymore
; Wait until the keyboard transmit is complete
; Returns:
; r1 >= 0 if successful
; r1 < 0 if timed out
;------------------------------------------------------------------------------
;
KeybdWaitBusy: ; alias for KeybdWaitTx
KeybdWaitTx:
addui r27,r27,#-16
sws c1,8[r27]
sw r3,[r27]
ldi r3,#10 ; wait a max of .1s
.0001:
lvb r1,hs:KEYBD+1
biti p0,r1,#$40 ; check for transmit busy bit
p0.eq br .0002 ; branch if bit clear
bsr Wait10ms ; delay a little bit
addui r3,r3,#-1 ; go back and try again
tst p0,r3
p0.ne br .0001
lw r3,[r27] ; timed out
lws c1,8[r27]
addui r27,r27,#16
ldi r1,#-1 ; return -1
rts
.0002:
lw r3,[r27] ; wait complete, return
lws c1,8[r27] ; restore return address
ldi r1,#0 ; return 0 for okay
addui r27,r27,#16
rts
 
;------------------------------------------------------------------------------
; Delay for about 10 ms.
;------------------------------------------------------------------------------
 
Wait10ms:
addui r27,r27,#-16
sw r1,8[r27]
sw r2,[r27]
mfspr r1,tick
addui r1,r1,#250000 ; 10ms at 25 MHz
.0001:
mfspr r2,tick
cmp p0,r2,r1
p0.lt br .0001
lw r2,[r27]
lw r1,8[r27]
addui r27,r27,#16
rts
 
;------------------------------------------------------------------------------
; KeybdIRQ:
; Store scancode in keyboard buffer. Also check for the special key
; sequences ALT-tab and CTRL-ALT-del. If the keyboard buffer is full then
; the newest keystrokes are lost.
;------------------------------------------------------------------------------
 
KeybdIRQ:
sync
addui r31,r31,#-80
sws p0,[r31]
sw r1,8[r31]
sw r2,16[r31]
sws hs,24[r32]
sw r3,32[r31]
sws ds,40[r31]
sws ds.lmt,48[r31]
sws hs.lmt,56[r31]
sw r4,64[r31]
sw r5,72[r31]
 
ldis hs,#$FFD00000
ldis hs.lmt,#$100000
lws ds,zs:IOFocusNdx_ ; set input to correct keyboard buffer
ldis ds.lmt,#$10000
lvb r1,hs:KEYBD ; get the scan code
sb r0,hs:KEYBD+1 ; clear interrupt status
lcu r2,JCB_KeybdHead ; get head/tail index (1 memory op)
shrui r3,r2,#8 ; r3 = tail
zxb r2,r2 ; r2 = head
mov r4,r2 ; make copy of old head index
addui r2,r2,#1 ; increment head index
lbu r5,JCB_KeybdBufSz
cmp p0,r2,r5
p0.geu mov r2,r0 ; modulus buffer size
cmp p0,r2,r3 ; is there room in buffer ?
p0.ne sb r1,JCB_KeybdBuf[r4] ; store scan code in buffer
p0.ne sb r2,JCB_KeybdHead ; save buffer index
lb r2,JCB_KeyState2 ; check for ALT
biti p0,r2,#2
p0.eq br .exit
cmpi p0,r1,#SC_TAB
p0.eq inc.b zs:iof_switch_ ; set IOF switch flag if ALT-Tab pressed.
p0.eq br .exit
cmpi p0,r1,#SC_DEL
p0.ne br .exit
biti p0,r2,#4 ; check for CTRL-ALT-DEL
p0.ne jmp cold_start
.exit:
lws p0,[r31]
lw r1,8[r31]
lw r2,16[r31]
lws hs,24[r32]
lw r3,32[r31]
lws ds,40[r31]
lws ds.lmt,48[r31]
lws hs.lmt,56[r31]
lw r4,64[r31]
lw r5,72[r31]
addui r31,r31,#80
sync
rti
 
;--------------------------------------------------------------------------
; PS2 scan codes to ascii conversion tables.
;--------------------------------------------------------------------------
;
unshiftedScanCodes:
byte $2e,$a9,$2e,$a5,$a3,$a1,$a2,$ac
byte $2e,$aa,$a8,$a6,$a4,$09,$60,$2e
byte $2e,$2e,$2e,$2e,$2e,$71,$31,$2e
byte $2e,$2e,$7a,$73,$61,$77,$32,$2e
byte $2e,$63,$78,$64,$65,$34,$33,$2e
byte $2e,$20,$76,$66,$74,$72,$35,$2e
byte $2e,$6e,$62,$68,$67,$79,$36,$2e
byte $2e,$2e,$6d,$6a,$75,$37,$38,$2e
byte $2e,$2c,$6b,$69,$6f,$30,$39,$2e
byte $2e,$2e,$2f,$6c,$3b,$70,$2d,$2e
byte $2e,$2e,$27,$2e,$5b,$3d,$2e,$2e
byte $ad,$2e,$0d,$5d,$2e,$5c,$2e,$2e
byte $2e,$2e,$2e,$2e,$2e,$2e,$08,$2e
byte $2e,$95,$2e,$93,$94,$2e,$2e,$2e
byte $98,$7f,$92,$2e,$91,$90,$1b,$af
byte $ab,$2e,$97,$2e,$2e,$96,$ae,$2e
 
byte $2e,$2e,$2e,$a7,$2e,$2e,$2e,$2e
byte $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2e
byte $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2e
byte $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2e
byte $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2e
byte $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2e
byte $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2e
byte $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2e
byte $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2e
byte $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2e
byte $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2e
byte $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2e
byte $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2e
byte $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2e
byte $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2e
byte $2e,$2e,$fa,$2e,$2e,$2e,$2e,$2e
 
shiftedScanCodes:
byte $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2e
byte $2e,$2e,$2e,$2e,$2e,$09,$7e,$2e
byte $2e,$2e,$2e,$2e,$2e,$51,$21,$2e
byte $2e,$2e,$5a,$53,$41,$57,$40,$2e
byte $2e,$43,$58,$44,$45,$24,$23,$2e
byte $2e,$20,$56,$46,$54,$52,$25,$2e
byte $2e,$4e,$42,$48,$47,$59,$5e,$2e
byte $2e,$2e,$4d,$4a,$55,$26,$2a,$2e
byte $2e,$3c,$4b,$49,$4f,$29,$28,$2e
byte $2e,$3e,$3f,$4c,$3a,$50,$5f,$2e
byte $2e,$2e,$22,$2e,$7b,$2b,$2e,$2e
byte $2e,$2e,$0d,$7d,$2e,$7c,$2e,$2e
byte $2e,$2e,$2e,$2e,$2e,$2e,$08,$2e
byte $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2e
byte $2e,$7f,$2e,$2e,$2e,$2e,$1b,$2e
byte $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2e
 
byte $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2e
byte $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2e
byte $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2e
byte $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2e
byte $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2e
byte $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2e
byte $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2e
byte $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2e
byte $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2e
byte $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2e
byte $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2e
byte $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2e
byte $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2e
byte $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2e
byte $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2e
byte $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2e
 
; control
keybdControlCodes:
byte $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2e
byte $2e,$2e,$2e,$2e,$2e,$09,$7e,$2e
byte $2e,$2e,$2e,$2e,$2e,$11,$21,$2e
byte $2e,$2e,$1a,$13,$01,$17,$40,$2e
byte $2e,$03,$18,$04,$05,$24,$23,$2e
byte $2e,$20,$16,$06,$14,$12,$25,$2e
byte $2e,$0e,$02,$08,$07,$19,$5e,$2e
byte $2e,$2e,$0d,$0a,$15,$26,$2a,$2e
byte $2e,$3c,$0b,$09,$0f,$29,$28,$2e
byte $2e,$3e,$3f,$0c,$3a,$10,$5f,$2e
byte $2e,$2e,$22,$2e,$7b,$2b,$2e,$2e
byte $2e,$2e,$0d,$7d,$2e,$7c,$2e,$2e
byte $2e,$2e,$2e,$2e,$2e,$2e,$08,$2e
byte $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2e
byte $2e,$7f,$2e,$2e,$2e,$2e,$1b,$2e
byte $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2e
 
keybdExtendedCodes:
byte $2e,$2e,$2e,$2e,$a3,$a1,$a2,$2e
byte $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2e
byte $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2e
byte $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2e
byte $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2e
byte $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2e
byte $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2e
byte $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2e
byte $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2e
byte $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2e
byte $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2e
byte $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2e
byte $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2e
byte $2e,$95,$2e,$93,$94,$2e,$2e,$2e
byte $98,$99,$92,$2e,$91,$90,$2e,$2e
byte $2e,$2e,$97,$2e,$2e,$96,$2e,$2e
 
/trunk/software/boot_tb/boot.asm
22,13 → 22,14
;
; ============================================================================
;
.include "C:\Cores4\Thor\trunk\software\FMTK\source\kernel\FMTK_Equates.inc"
 
SCRSZ EQU 2604
_BS EQU 0x07
CR EQU 0x0D ;ASCII equates
LF EQU 0x0A
TAB EQU 0x09
CTRLC EQU 0x03
BS EQU 0x07
CTRLH EQU 0x08
CTRLI EQU 0x09
CTRLJ EQU 0x0A
40,6 → 41,7
XOFF EQU 0x13
ESC EQU 0x1B
 
SC_TAB EQU $0D
SC_LSHIFT EQU $12
SC_RSHIFT EQU $59
SC_KEYUP EQU $F0
83,11 → 85,24
Milliseconds dw 0
m_w dh 0
m_z dh 0
FMTK_SchedulerIRQ_vec dw 0
Running_ dw 0
IOFocusNdx_ dw 0
iof_switch_ db 0
align 8
NextRdy_ dw 0
PrevRdy_ dw 0
 
KeyState1 db 0
KeyState2 db 0
KeybdLEDs db 0
KeybdWaitFlag db 0
 
align 2
KeybdHead db 0
KeybdTail db 0
KeybdBufSz db 0
KeybdBuf fill.b 128,0
align 2
CursorX dc 0
CursorY dc 0
VideoPos dc 0
171,6 → 186,15
ldi r2,#0
bsr set_vector
 
; setup system scheduler vector
; points to an RTE at startup
lla r1,cs:tms_jmp
ldi r2,#2
bsr set_vector
lla r1,cs:rte_jmp
ldi r2,#3
bsr set_vector
 
; setup Video BIOS vector
lla r1,cs:vb_jmp
ldi r2,#10
200,11 → 224,6
ldi r2,#193
bsr set_vector
 
; setup IRQ vector
lla r1,cs:tms_jmp
ldi r2,#194
bsr set_vector
 
; setup BTNU vector
lla r1,cs:btnu_jmp
ldi r2,#200
220,10 → 239,21
ldi r2,#251
bsr set_vector
 
ldi r1,#JCB_Array
sw r1,zs:RunningJCB_
sw r1,zs:IOFocusNdx_ ; set I/O focus to BIOS
ldi r1,#TCB_Array
sw r1,zs:RunningTCB_
sb r0,zs:iof_switch_ ; reset switch flag
mov tr,r0
bsr KeybdInit
 
jsr FMTKInitialize_
 
; Initialize PIC
ldi r1,#%00000111 ; time slice interrupt is edge sensitive
ldi r1,#%00000111 ; nmi, time slice interrupt is edge sensitive
sh r1,hs:PIC_ES
ldi r1,#%100000111 ; enable time slice interrupt, msi, nmi
ldi r1,#%000001111 ; enable time slice interrupt, msi, nmi
sh r1,hs:PIC_IE
 
; Initialize random number generator
352,14 → 382,18
p0.eq br .0001
cmpi p0,r1,#'d' ; debug ?
p0.eq bsr Debugger
p0.eq br .prompt
cmpi p0,r1,#'g'
p0.eq bsr GoGraphics
p0.eq br .prompt
cmpi p0,r1,#'t'
p0.eq bsr MonGetch
p0.eq cmpi p0,r1,#'x'
p0.eq bsr GoText
p0.eq br .prompt
cmpi p0,r1,'r'
p0.eq bsr RandomDots
p0.eq br .prompt
cmpi p0,r1,#'c'
p0.eq bsr VBClearScreen
p0.eq mov r1,r0
410,6 → 444,7
rts
 
;------------------------------------------------------------------------------
; Go into graphics mode, four lines of text at bottom.
;------------------------------------------------------------------------------
 
GoGraphics:
417,10 → 452,18
ldi r1,#4
sc r1,Textrows
sh r1,hs:4[r3] ; # rows
ldi r1,#720
ldi r1,#240
sh r1,hs:12[r3] ; window top
mov r1,r0 ; reset cursor position
mov r2,r0
ldi r6,#2
sys #10
rts
 
;------------------------------------------------------------------------------
; Go back to full text mode.
;------------------------------------------------------------------------------
 
GoText:
lhu r3,Vidregs
ldi r1,#31
428,6 → 471,10
sh r1,hs:4[r3] ; # rows
ldi r1,#17
sh r1,hs:12[r3] ; window top
mov r1,r0 ; reset cursor position
mov r2,r0
ldi r6,#2
sys #10
rts
 
// ----------------------------------------------------------------------------
472,22 → 519,23
 
RandomDots:
addui r31,r31,#-8
sws c1,[r31]
sws c1,[r31] ; stack the return address
mov r4,r0
.0001:
bsr gen_rand ; get random bitmap memory location
modu r2,r1,#172032 ; mod the memory size
shli r2,r2,#1 ; *2 for 16 bit data
modui r2,r1,#172032 ; mod the memory size
_2addui r2,r2,#$FFA00000 ; *2 for 16 bit data, generate address
bsr gen_rand ; get random color
modui r3,r1,#$1000 ; limit to 12 bits
sc r3,zs:$FFA00000[r2] ; store color in memory
sc r3,zs:[r2] ; store color in memory
addui r4,r4,#1 ; increment loop index
andi r4,r4,#$FFF ;
tst p0,r4 ; check if time to check for keypress
p0.eq bsr KeybdGetCharNoWait ; try get a key, but don't wait
tst p0,r1 ; branch if no key pressed
p0.lt br RandomDots.0001
lws c1,[r31]
tst p1,r4 ; check if time to check for keypress
p1.ne br .0001
bsr KeybdGetCharNoWait ; try get a key, but don't wait
tst p1,r1 ; branch if no key pressed
p1.lt br RandomDots.0001
lws c1,[r31] ; restore return address
addui r31,r31,#8
rts
 
565,70 → 613,66
; Save the register context.
;
; Parameters:
; DS points to app's data space
; tr points to app's TCB
;
;------------------------------------------------------------------------------
 
save_context:
sw r1,reg_save+8*1
sw r2,reg_save+8*2
sw r3,reg_save+8*3
sw r4,reg_save+8*4
sw r5,reg_save+8*5
sw r6,reg_save+8*6
sw r7,reg_save+8*7
sw r8,reg_save+8*8
sw r9,reg_save+8*9
sw r10,reg_save+8*10
sw r11,reg_save+8*11
sw r12,reg_save+8*12
sw r13,reg_save+8*13
sw r14,reg_save+8*14
sw r15,reg_save+8*15
sw r16,reg_save+8*16
sw r17,reg_save+8*17
sw r18,reg_save+8*18
sw r19,reg_save+8*19
sw r20,reg_save+8*20
sw r21,reg_save+8*21
sw r22,reg_save+8*22
sw r23,reg_save+8*23
sw r24,reg_save+8*24
sw r25,reg_save+8*25
sw r26,reg_save+8*26
sw r27,reg_save+8*27
sw r28,reg_save+8*28
sw r29,reg_save+8*29
sw r30,reg_save+8*30
sw r31,reg_save+8*31
sws ds,sreg_save+8*1
sws es,sreg_save+8*2
sws fs,sreg_save+8*3
sws gs,sreg_save+8*4
sws hs,sreg_save+8*5
sws ss,sreg_save+8*6
sws cs,sreg_save+8*7
sws ds.lmt,sreg_save+8*9
sws es.lmt,sreg_save+8*10
sws fs.lmt,sreg_save+8*11
sws gs.lmt,sreg_save+8*12
sws hs.lmt,sreg_save+8*13
sws ss.lmt,sreg_save+8*14
sws cs.lmt,sreg_save+8*15
sws c1,creg_save+8*1
sws c2,creg_save+8*2
sws c3,creg_save+8*3
sws c4,creg_save+8*4
sws c5,creg_save+8*5
sws c6,creg_save+8*6
sws c7,creg_save+8*7
sws c8,creg_save+8*8
sws c9,creg_save+8*9
sws c10,creg_save+8*10
sws c11,creg_save+8*11
sws c13,creg_save+8*13
sws c14,creg_save+8*14
sws pregs,preg_save
sw r1,TCB_r1[tr]
sw r2,TCB_r2[tr]
sw r3,TCB_r3[tr]
sw r4,TCB_r4[tr]
sw r5,TCB_r5[tr]
sw r6,TCB_r6[tr]
sw r7,TCB_r7[tr]
sw r8,TCB_r8[tr]
sw r9,TCB_r9[tr]
sw r10,TCB_r10[tr]
sw r11,TCB_r11[tr]
sw r12,TCB_r12[tr]
sw r13,TCB_r13[tr]
sw r14,TCB_r14[tr]
sw r15,TCB_r15[tr]
sw r16,TCB_r16[tr]
sw r17,TCB_r17[tr]
sw r18,TCB_r18[tr]
sw r19,TCB_r19[tr]
sw r20,TCB_r20[tr]
sw r21,TCB_r21[tr]
sw r22,TCB_r22[tr]
sw r23,TCB_r23[tr]
sw r24,TCB_r24[tr]
sw r25,TCB_r25[tr]
sw r26,TCB_r26[tr]
sw r27,TCB_r27[tr]
sws ds,TCB_ds[tr]
sws es,TCB_es[tr]
sws fs,TCB_fs[tr]
sws gs,TCB_gs[tr]
sws hs,TCB_hs[tr]
sws ss,TCB_ss[tr]
sws cs,TCB_cs[tr]
sws ds.lmt,TCB_dslmt[tr]
sws es.lmt,TCB_eslmt[tr]
sws fs.lmt,TCB_fslmt[tr]
sws gs.lmt,TCB_gslmt[tr]
sws hs.lmt,TCB_hslmt[tr]
sws ss.lmt,TCB_sslmt[tr]
sws cs.lmt,TCB_cslmt[tr]
sws c1,TCB_c1[tr]
sws c2,TCB_c2[tr]
sws c3,TCB_c3[tr]
sws c4,TCB_c4[tr]
sws c5,TCB_c5[tr]
sws c6,TCB_c6[tr]
sws c7,TCB_c7[tr]
sws c8,TCB_c8[tr]
sws c9,TCB_c9[tr]
sws c10,TCB_c10[tr]
sws c11,TCB_c11[tr]
; sws c13,TCB_c13[tr]
; sws c14,TCB_c14[tr]
sws pregs,TCB_pregs[tr]
rte
 
;------------------------------------------------------------------------------
638,70 → 682,67
;------------------------------------------------------------------------------
 
restore_context:
lw r1,reg_save+8*1
lw r2,reg_save+8*2
lw r3,reg_save+8*3
lw r4,reg_save+8*4
lw r5,reg_save+8*5
lw r6,reg_save+8*6
lw r7,reg_save+8*7
lw r8,reg_save+8*8
lw r9,reg_save+8*9
lw r10,reg_save+8*10
lw r11,reg_save+8*11
lw r12,reg_save+8*12
lw r13,reg_save+8*13
lw r14,reg_save+8*14
lw r15,reg_save+8*15
lw r16,reg_save+8*16
lw r17,reg_save+8*17
lw r18,reg_save+8*18
lw r19,reg_save+8*19
lw r20,reg_save+8*20
lw r21,reg_save+8*21
lw r22,reg_save+8*22
lw r23,reg_save+8*23
lw r24,reg_save+8*24
lw r25,reg_save+8*25
lw r26,reg_save+8*26
lw r27,reg_save+8*27
lw r28,reg_save+8*28
lw r29,reg_save+8*29
lw r30,reg_save+8*30
lw r31,reg_save+8*31
; lws ds,sreg_save+8*1
lws es,sreg_save+8*2
lws fs,sreg_save+8*3
lws gs,sreg_save+8*4
lws hs,sreg_save+8*5
lws ss,sreg_save+8*6
lws cs,sreg_save+8*7
; lws ds.lmt,sreg_save+8*9
lws es.lmt,sreg_save+8*10
lws fs.lmt,sreg_save+8*11
lws gs.lmt,sreg_save+8*12
lws hs.lmt,sreg_save+8*13
lws ss.lmt,sreg_save+8*14
lws cs.lmt,sreg_save+8*15
lws c1,creg_save+8*1
lws c2,creg_save+8*2
lws c3,creg_save+8*3
lws c4,creg_save+8*4
lws c5,creg_save+8*5
lws c6,creg_save+8*6
lws c7,creg_save+8*7
lws c8,creg_save+8*8
lws c9,creg_save+8*9
lws c10,creg_save+8*10
lws c11,creg_save+8*11
; lws c13,creg_save+8*13
lws c14,creg_save+8*14
lws pregs,preg_save
lw r1,TCB_r1[tr]
lw r2,TCB_r2[tr]
lw r3,TCB_r3[tr]
lw r4,TCB_r4[tr]
lw r5,TCB_r5[tr]
lw r6,TCB_r6[tr]
lw r7,TCB_r7[tr]
lw r8,TCB_r8[tr]
lw r9,TCB_r9[tr]
lw r10,TCB_r10[tr]
lw r11,TCB_r11[tr]
lw r12,TCB_r12[tr]
lw r13,TCB_r13[tr]
lw r14,TCB_r14[tr]
lw r15,TCB_r15[tr]
lw r16,TCB_r16[tr]
lw r17,TCB_r17[tr]
lw r18,TCB_r18[tr]
lw r19,TCB_r19[tr]
lw r20,TCB_r20[tr]
lw r21,TCB_r21[tr]
lw r22,TCB_r22[tr]
lw r23,TCB_r23[tr]
lw r24,TCB_r24[tr]
lw r25,TCB_r25[tr]
lw r26,TCB_r26[tr]
lw r27,TCB_r27[tr]
lws ds,TCB_ds[tr]
lws es,TCB_es[tr]
lws fs,TCB_fs[tr]
lws gs,TCB_gs[tr]
lws hs,TCB_hs[tr]
lws ss,TCB_ss[tr]
lws cs,TCB_cs[tr]
lws ds.lmt,TCB_dslmt[tr]
lws es.lmt,TCB_eslmt[tr]
lws fs.lmt,TCB_fslmt[tr]
lws gs.lmt,TCB_gslmt[tr]
lws hs.lmt,TCB_hslmt[tr]
lws ss.lmt,TCB_sslmt[tr]
lws cs.lmt,TCB_cslmt[tr]
lws c1,TCB_c1[tr]
lws c2,TCB_c2[tr]
lws c3,TCB_c3[tr]
lws c4,TCB_c4[tr]
lws c5,TCB_c5[tr]
lws c6,TCB_c6[tr]
lws c7,TCB_c7[tr]
lws c8,TCB_c8[tr]
lws c9,TCB_c9[tr]
lws c10,TCB_c10[tr]
lws c11,TCB_c11[tr]
; lws c13,TCB_c13[tr]
; lws c14,TCB_c14[tr]
lws pregs,TCB_pregs[tr]
rte
 
.include "c:\cores4\thor\trunk\software\FMTK\source\kernel\FMTKc.s"
.include "video.asm"
.include "serial.asm"
.include "keyboard.asm"
.include "serial.asm"
.include "debugger.asm"
 
 
712,22 → 753,23
;
btnu_rout:
sync
addui r31,r31,#-16
addui r31,r31,#-24
sw r1,[r31]
sws hs,8[r31]
sws hs.lmt,16[r31]
 
; set I/O segment
ldis hs,#$FFD00000
ldis hs.lmt,#$100000
 
; update on-screen IRQ live indicator
lh r1,hs:TEXTSCR+312
addui r1,r1,#1
sh r1,hs:TEXTSCR+312
inc.h hs:TEXTSCR+312
 
; restore regs and return
lw r1,[r31]
lws hs,8[r31]
addui r31,r31,#16
lws hs.lmt,16[r31]
addui r31,r31,#24
sync
rti
 
736,24 → 778,26
 
spur_rout:
sync
ldi r31,#INT_STACK-16
addui r31,r31,#-24
sw r1,[r31]
sws hs,8[r31]
sws hs.lmt,16[r31]
 
; set I/O segment
ldis hs,#$FFD00000
ldis hs.lmt,#$100000
 
; ldi r1,#18
; sc r1,hs:LEDS
 
; update on-screen IRQ live indicator
lh r1,hs:TEXTSCR+316
addui r1,r1,#1
sh r1,hs:TEXTSCR+316
inc.h hs:TEXTSCR+316
 
; restore regs and return
lw r1,[r31]
lws hs,8[r31]
lws hs.lmt,16[r31]
addui r31,r31,#24
sync
rti
 
762,12 → 806,14
;------------------------------------------------------------------------------
uii_rout:
sync
ldi r31,#INT_STACK-16
addui r31,r31,#-24
sw r1,[r31]
sws hs,8[r31]
sws hs.lmt,16[r31]
 
; set I/O segment
ldis hs,#$FFD00000
ldis hs.lmt,#$100000
 
; update on-screen IRQ live indicator
ldi r1,#'U'|%011000000_111111111_00_00000000
804,6 → 850,8
; restore regs and return
lw r1,[r31]
lws hs,8[r31]
lws hs.lmt,16[r31]
addui r31,r31,#24
sync
rti
 
814,12 → 862,14
;
nmi_rout:
sync
ldi r31,#INT_STACK-16
addui r31,r31,#-24
sw r1,[r31]
sws hs,8[r31]
sws hs.lmt,16[r31]
 
; set I/O segment
ldis hs,#$FFD00000
ldis hs.lmt,#$100000
 
ldi r1,#16
sc r1,hs:LEDS
836,6 → 886,8
; restore regs and return
lw r1,[r31]
lws hs,8[r31]
lws hs.lmt,16[r31]
addui r31,r31,#24
sync
rti
 
846,12 → 898,15
;
msi_rout:
sync
addui r31,r31,#-16
sw r1,[r31]
sws hs,8[r31]
addui sp,sp,#-32
sw r1,[sp]
sws hs,8[sp]
sws hs.lmt,16[sp]
sws c1,24[sp]
 
; set I/O segment
ldis hs,#$FFD00000
ldis hs.lmt,#$100000
 
ldi r1,#24
sc r1,hs:LEDS
861,14 → 916,16
sh r1,hs:PIC_ESR
 
; update milliseconds
lh r1,zs:Milliseconds
lw r1,zs:Milliseconds
addui r1,r1,#1
sh r1,zs:Milliseconds
sw r1,zs:Milliseconds
 
; restore regs and return
lw r1,[r31]
lws hs,8[r31]
addui r31,r31,#16
lw r1,[sp]
lws hs,8[sp]
lws hs.lmt,16[sp]
lws c1,24[sp]
addui sp,sp,#32
sync
rti
 
879,12 → 936,14
;
tms_rout:
sync
addui r31,r31,#-16
addui r31,r31,#-24
sw r1,[r31]
sws hs,8[r31]
sws hs.lmt,16[r31]
 
; set I/O segment
ldis hs,#$FFD00000
ldis hs.lmt,#$100000
 
ldi r1,#32
sc r1,hs:LEDS
894,16 → 953,15
sh r1,hs:PIC_ESR
 
; update on-screen IRQ live indicator
lh r1,hs:TEXTSCR+328
addui r1,r1,#1
sh r1,hs:TEXTSCR+328
inc.h hs:TEXTSCR+328
 
; restore regs and return
lw r1,[r31]
lws hs,8[r31]
addui r31,r31,#16
lws hs.lmt,16[r31]
addui r31,r31,#24
sync
rti
rte
 
;------------------------------------------------------------------------------
; Data bus error routine.
1022,9 → 1080,6
vb_jmp:
jmp VideoBIOSCall[c0]
align 8
ser_jmp:
jmp SerialIRQ[c0]
align 8
dbe_jmp:
jmp dbe_rout[c0]
align 8
1043,6 → 1098,9
rti_jmp:
km_jmp:
rti
align 8
rte_jmp:
rte
 
;------------------------------------------------------------------------------
; Reset Point
/trunk/software/boot_tb/debugger.asm
0,0 → 1,1550
; ============================================================================
; __
; \\__/ o\ (C) 2015 Robert Finch, Stratford
; \ __ / All rights reserved.
; \/_// robfinch<remove>@finitron.ca
; ||
;
;
; This source file is free software: you can redistribute it and/or modify
; it under the terms of the GNU Lesser General Public License as published
; by the Free Software Foundation, either version 3 of the License, or
; (at your option) any later version.
;
; This source file is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; GNU General Public License for more details.
;
; You should have received a copy of the GNU General Public License
; along with this program. If not, see <http://www.gnu.org/licenses/>.
;
;
; ============================================================================
 
 
DBG_DS = $5000
DBG_ATTR = %000011000_111111110_0000000000
 
bss
org $1000
DBGBuf fill.b 84,0
DBGBufndx db 0
 
code
org $FFFFC800
 
;------------------------------------------------------------------------------
; r2 = text output column
; r6 = text output row
; r5 = disassembly address
;------------------------------------------------------------------------------
 
public Debugger:
sys #190 ; save context
ldi sp,#$2bf8
addui sp,sp,#-24
sws c1,[sp]
sws ds,8[sp]
sws ds.lmt,16[sp]
ldis ds,#DBG_DS
ldis ds.lmt,#$8000
sws ds,zs:IOFocusNdx_
sync
bsr KeybdClearBuf
bsr VideoInit2
bsr VBClearScreen
mov r1,r0 ; row = 0
mov r2,r0 ; col = 0
ldi r6,#2 ; set cursor pos
sys #10 ; call video BIOS
; bsr DBGRamTest
lla r1,cs:msgDebugger ; convert address to linear
ldi r6,#$14 ; Try display string
sys #10 ; call video BIOS
mov r6,r0
mov r2,r0
ldi r5,#$FFFF8000
bsr DBGDisassem20
; br Debugger_exit
 
promptAgain:
; Clear input buffer
sb r0,DBGBufndx
ldis lc,#$14 ; (21-1)*4
ldi r1,#DBGBuf
ldi r2,#0 ;
stset.hi r2,[r1] ; clear the buffer
ldi r6,#30 ; move cursor pos to row 30
bsr DBGPrompt
 
; Get character loop
.0001:
bsr KeybdGetCharWait
cmpi p0,r1,#CR
p0.eq br .processInput
cmpi p0,r1,#_BS
p0.eq br .backspace
cmpi p0,r1,#' '
p0.ltu br .0001
; some other character, store in buffer if it will fit
lbu r3,DBGBufndx
cmpi p3,r3,#80 ; max 80 chars
p3.ltu bsr DBGDispChar
p3.ltu sb r1,DBGBuf[r3]
p3.ltu addui r3,r3,#1
p3.ltu sb r3,DBGBufndx
br .0001
.backspace:
lbu r1,DBGBufndx
tst p0,r1 ; is is even possible to backspace ?
p0.eq br .0001
ldi r7,#$80
subu r7,r7,r1
addui r7,r7,#-1 ; loop count is one less
mtspr lc,r7
addui r1,r1,#DBGBuf
mov r4,r1
addui r1,r1,#-1
mov r3,r0
stmov.bi [r4],[r1],r3
 
br .0001
.processInput:
mov r4,r0
.0002:
lbu r1,DBGBuf[r4]
tst p0,r1
p0.eq br promptAgain
cmpi p0,r1,#' '
p0.leu addui r4,r4,#1
p0.leu br .0002
cmpi p0,r1,#'D'
p0.eq addui r4,r4,#1
p0.eq br DoDisassem
cmpi p0,r1,#'M'
p0.eq br DBGDumpMem
cmpi p0,r1,#'x'
p0.eq br Debugger_exit
br promptAgain
Debugger_exit:
lws c1,[sp]
lws ds,8[sp]
lws ds.lmt,16[sp]
sws ds,zs:IOFocusNdx_
sys #191 ; restore context
rts
endpublic
 
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
 
DoDisassem:
bsr DBGGetHexNumber
tst p0,r8
p0.eq br promptAgain
mov r5,r1
bsr VBClearScreen2
bsr DBGDisassem20
br promptAgain
 
;------------------------------------------------------------------------------
; Dump memory bytes
; M <start address>
;------------------------------------------------------------------------------
 
DBGDumpMem:
addui r4,r4,#1 ; advance a character past 'M'
bsr DBGGetHexNumber
mov r12,r1
tst p0,r8
p0.eq jmp promptAgain
bsr VBClearScreen2
addui r13,r12,#200
ldi r6,#2
mov r2,r0
.0002:
mov r14,r0
ldi r1,#'>'
bsr DBGDispChar
mov r4,r12
bsr DBGDisplayHalf
.0001:
bsr space1
lbu r4,zs:[r12+r14]
bsr DBGDisplayByte
addui r14,r14,#1
cmpi p0,r14,#8
p0.ltu br .0001
bsr space1
mov r14,r0
bsr ReverseVideo ; reverse video attribute
.0003:
lbu r1,zs:[r12+r14]
cmpi p0,r1,#' '
p0.ltu ldi r1,#'.'
bsr DBGDispChar
addui r14,r14,#1
cmpi p0,r14,#8
p0.ltu br .0003
bsr ReverseVideo ; put video back to normal
addui r6,r6,#1
addu r12,r12,r14
cmp p0,r12,r13
p0.ltu br .0002
jmp promptAgain
;------------------------------------------------------------------------------
; DBGGetHexNumber:
; Get a hexi-decimal number from the input buffer.
;
; Parameters:
; r4 = text pointer (updated)
; Returns:
; r1 = number
; r8 = number of digits
;------------------------------------------------------------------------------
 
DBGGetHexNumber:
addui sp,sp,#-8
sws c1,[sp]
ldis lc,#80 ; max 80 chars
mov r7,r0 ; working accum.
mov r8,r0 ; number of digits
.0003:
lbu r1,[r4] ; skip leading spaces
cmpi p0,r1,#' '
p0.leu addui r4,r4,#1
p0.leu br .0003
.0002:
lbu r1,[r4]
bsr DBGCharToHex
tst p0,r3
p0.eq br .0001
shli r7,r7,#4
or r7,r7,r1
addui r4,r4,#1
addui r8,r8,#1
loop .0002
.0001:
mov r1,r7
lws c1,[sp]
addui sp,sp,#8
rts
 
;------------------------------------------------------------------------------
; DBGCharToHex:
; Convert a single ascii character to hex nybble.
; Parameters:
; r1 = ascii character to convert
; Returns:
; r1 = binary nybble
; r3 = 1 if conversion successful, 0 otherwise
;------------------------------------------------------------------------------
 
DBGCharToHex:
cmpi p0,r1,#'0'
p0.ltu br .0004
cmpi p0,r1,#'9'
p0.gtu br .0001
addui r1,r1,#-'0'
ldi r3,#1
rts
.0001:
cmpi p0,r1,#'A'
p0.ltu br .0004
cmpi p0,r1,#'F'
p0.gtu br .0003
subui r1,r1,#'A'-10
ldi r3,#1
rts
.0003:
cmpi p0,r1,#'a'
p0.ltu br .0004
cmpi p0,r1,#'f'
p0.gtu br .0004
subui r1,r1,#'a'-10
ldi r3,#1
rts
.0004:
mov r3,r0
.exit:
rts
 
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
 
public DebugIRQ:
sw sp,reg_save+8*27
ldi sp,#$2bf8
addui sp,sp,#-104
sws c1,[sp]
sws ds,8[sp]
sws ds.lmt,16[sp]
sw r1,24[sp]
sw r2,32[sp]
sw r3,40[sp]
sw r4,48[sp]
sw r5,56[sp]
sw r6,64[sp]
sw r7,72[sp]
sw r8,80[sp]
sw r9,88[sp]
sw r10,96[sp]
 
ldis ds,#DBG_DS
ldis ds.lmt,#$8000
sync
bsr VBClearScreen2
mov r2,r0
mov r6,r0
ldi r1,#msgDebugger
bsr DBGDispString
mfspr r5,dpc
bsr DBGDisassem20
 
lws c1,[sp]
lws ds,8[sp]
lws ds.lmt,16[sp]
lw r1,24[sp]
lw r2,32[sp]
lw r3,40[sp]
lw r4,48[sp]
lw r5,56[sp]
lw r6,64[sp]
lw r7,72[sp]
lw r8,80[sp]
lw r9,88[sp]
lw r10,96[sp]
lw sp,reg_save+8*27
rtd
endpublic
 
;------------------------------------------------------------------------------
; Disassemble 20 lines of code.
;------------------------------------------------------------------------------
 
DBGDisassem20:
addui sp,sp,#-8
sws c1,[sp]
ldis lc,#19
ldi r6,#3
.0001:
bsr Disassem
addu r5,r5,r10
addui r6,r6,#1
loop .0001
lws c1,[sp]
addui sp,sp,#8
rts
 
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
 
DBGPrompt:
addui sp,sp,#-8
sws c1,[sp]
mov r2,r0
ldi r1,#'D'
bsr DBGDispChar
ldi r1,#'B'
bsr DBGDispChar
ldi r1,#'G'
bsr DBGDispChar
ldi r1,#'>'
bsr DBGDispChar
lws c1,[sp]
addui sp,sp,#8
rts
 
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
 
Disassem:
addui sp,sp,#-16
sws c1,[sp]
sws c2,8[sp]
ldi r2,#1 ; column one
bsr DisplayAddr
bsr DisplayBytes
ldi r2,#38 ; tab to column 38
bsr DBGDisplayPred
ldi r2,#46 ; tab to column 46
mov r3,r0
lbu r1,zs:[r5]
cmpi p0,r1,#$00
p0.eq ldi r3,#mne_brk
cmpi p0,r1,#$10
p0.eq ldi r3,#mne_nop
cmpi p0,r1,#$11
p0.eq ldi r3,#mne_rts
cmpi p0,r1,#$20
p0.eq ldi r3,#mne_imm
cmpi p0,r1,#$30
p0.eq ldi r3,#mne_imm
cmpi p0,r1,#$40
p0.eq ldi r3,#mne_imm
cmpi p0,r1,#$50
p0.eq ldi r3,#mne_imm
cmpi p0,r1,#$60
p0.eq ldi r3,#mne_imm
cmpi p0,r1,#$70
p0.eq ldi r3,#mne_imm
cmpi p0,r1,#$80
p0.eq ldi r3,#mne_imm
tst p0,r3
p0.ne bsr DBGDisplayMne
p0.eq br .0001
br .exit
.0001:
lbu r1,zs:1[r5] ; get the opcode
shli r1,r1,#1
lcu r1,cs:DBGInsnMne[r1]
cmpi p0,r1,#$FFF0
p0.geu br .0002
.dispMne:
ori r3,r1,#Debugger & $FFFF0000 ; set high order address bits
bsr DBGDisplayMne
br .dispOper
.0002:
andi r1,r1,#15
lcu r3,cs:DBGInsnMneT[r1]
ori r3,r3,#Debugger & $FFFF0000
bsr DBGGetFunc
lcu r3,cs:[r3+r1*2]
br .dispMne
.dispOper:
lbu r1,zs:1[r5]
lbu r1,cs:DBGOperFmt[r1]
jci c1,cs:DBGOperFmtT[r1]
ldi r1,#48
sc r1,hs:LEDS
; lcu r1,cs:DBGOperFmtT[r1]
; ori r1,r1,#Debugger & $FFFF0000
; mtspr c2,r1
; jsr [c2]
.exit:
lws c1,[sp]
lws c2,8[sp]
addui sp,sp,#16
rts
 
;------------------------------------------------------------------------------
; Display the disassembly address.
;------------------------------------------------------------------------------
 
DisplayAddr:
addui sp,sp,#-8
sws c1,[sp]
mov r4,r5
bsr DBGDisplayHalf
bsr space3
lws c1,[sp]
addui sp,sp,#8
rts
space1:
addui sp,sp,#-8
sws c1,[sp]
ldi r1,#' '
bsr DBGDispChar
lws c1,[sp]
addui sp,sp,#8
rts
space3:
addui sp,sp,#-8
sws c1,[sp]
bsr space1
bsr space1
bsr space1
lws c1,[sp]
addui sp,sp,#8
rts
 
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
 
DBGDisplayHalf:
addui sp,sp,#-8
sws c1,[sp]
rori r4,r4,#16
bsr DBGDisplayCharr
roli r4,r4,#16
bsr DBGDisplayCharr
lws c1,[sp]
addui sp,sp,#8
rts
 
DBGDisplayCharr:
addui sp,sp,#-8
sws c1,[sp]
rori r4,r4,#8
bsr DBGDisplayByte
roli r4,r4,#8
bsr DBGDisplayByte
lws c1,[sp]
addui sp,sp,#8
rts
 
DBGDisplayByte:
addui sp,sp,#-8
sws c1,[sp]
rori r4,r4,#4
bsr DBGDisplayNybble
roli r4,r4,#4
bsr DBGDisplayNybble
lws c1,[sp]
addui sp,sp,#8
rts
 
DBGDisplayNybble:
addui sp,sp,#-8
sws c1,[sp]
andi r1,r4,#15
cmpi p0,r1,#9
p0.gtu addui r1,r1,#7
addui r1,r1,#'0'
bsr DBGDispChar
lws c1,[sp]
addui sp,sp,#8
rts
 
;------------------------------------------------------------------------------
; DBGDispChar:
;
; Display a character on the debug screen.
;
; Parameters:
; r1 = character to display
; r2 = text column
; r6 = text row
; Returns:
; r2 incremented
;------------------------------------------------------------------------------
 
DBGDispChar:
addui sp,sp,#-16
sws c1,[sp] ; save return address
sw r7,8[sp] ; save r7 work register
andi r1,r1,#$7F ; make sure in range
bsr VBAsciiToScreen ; convert to screen char
ori r1,r1,#DBG_ATTR ; add in attribute
lcu r7,Textcols ; figure out memory index
mulu r7,r6,r7 ; row * num cols
_4addui r7,r7,#$10000 ; + text base + (row * num cols) * 4
_4addu r7,r2,r7 ; + column * 4
sh r1,hs:[r7] ; store the char
addui r2,r2,#1 ; increment text position
lws c1,[sp] ; restore return address
lw r7,8[sp]
addui sp,sp,#16
rts
 
;------------------------------------------------------------------------------
; Display a string of text on the debug screen.
;------------------------------------------------------------------------------
 
DBGDispString:
addui sp,sp,#-16
sws c1,[sp]
sw r7,8[sp]
mov r7,r1
.0001:
lbu r1,zs:[r7]
tst p0,r1
p0.eq br .0002
bsr DBGDispChar
addui r7,r7,#1
br .0001
.0002:
lws c1,[sp]
lw r7,8[sp]
addui sp,sp,#16
rts
;------------------------------------------------------------------------------
; Get the length of an instruction.
;------------------------------------------------------------------------------
 
public DBGGetInsnLength:
addui r31,r31,#-8
sws c1,[r31]
lbu r1,zs:[r5]
; Test for special predicate values which are one byte long.
cmpi p0,r1,#$00 ; BRK
p0.eq ldi r1,#1
p0.eq br .0001
cmpi p0,r1,#$10 ; NOP
p0.eq ldi r1,#1
p0.eq br .0001
cmpi p0,r1,#$11 ; RTS
p0.eq ldi r1,#1
p0.eq br .0001
; Test for special immediate predicates these vary in length.
cmpi p0,r1,#$20
p0.eq ldi r1,#2
p0.eq br .0001
cmpi p0,r1,#$30
p0.eq ldi r1,#3
p0.eq br .0001
cmpi p0,r1,#$40
p0.eq ldi r1,#4
p0.eq br .0001
cmpi p0,r1,#$50
p0.eq ldi r1,#5
p0.eq br .0001
cmpi p0,r1,#$60
p0.eq ldi r1,#6
p0.eq br .0001
cmpi p0,r1,#$70
p0.eq ldi r1,#7
p0.eq br .0001
cmpi p0,r1,#$80
p0.eq ldi r1,#8
p0.ne lbu r1,zs:1[r5]
p0.ne lbu r1,cs:DBGInsnLength[r1]
.0001:
lws c1,[r31]
addui r31,r31,#8
rts
endpublic
 
;------------------------------------------------------------------------------
; Display the bytes associated with an instruction. There may be up to eight
; bytes displayed.
; r7 = offset from r5 the dump address
;------------------------------------------------------------------------------
 
DisplayBytes:
addui sp,sp,#-24
sws c1,[sp]
sws lc,8[sp]
sw r7,16[sp]
sei
ldi r31,#INT_STACK
bsr DBGGetInsnLength
mov r10,r1
cli
addui r1,r1,#-1 ; loop count is one less
mtspr lc,r1
mov r7,r0
.next:
lbu r4,zs:[r5+r7]
bsr DBGDisplayByte
bsr space1 ; skip a space
addui r7,r7,#1 ; increment offset to next byte
loop .next
lws c1,[sp]
lws lc,8[sp]
lw r7,16[sp]
addui sp,sp,#24
rts
 
;------------------------------------------------------------------------------
; Display a predicate.
;
; The always true predicate and special predicate values don't display.
;------------------------------------------------------------------------------
 
DBGDisplayPred:
addui sp,sp,#-8
sws c1,[sp]
lbu r1,zs:[r5]
cmpi p0,r1,#$00 ; brk special
p0.eq br .noDisp
cmpi p0,r1,#$01 ; always true predicate doesn't display
p0.eq br .noDisp
cmpi p0,r1,#$11 ; rts special
p0.eq br .noDisp
cmpi p0,r1,#$10 ; nop special
p0.eq br .noDisp
cmpi p0,r1,#$20
p0.eq br .noDisp
cmpi p0,r1,#$30
p0.eq br .noDisp
cmpi p0,r1,#$40
p0.eq br .noDisp
cmpi p0,r1,#$50
p0.eq br .noDisp
cmpi p0,r1,#$60
p0.eq br .noDisp
cmpi p0,r1,#$70
p0.eq br .noDisp
cmpi p0,r1,#$80
p0.eq br .noDisp
ldi r1,#'p'
bsr DBGDispChar
lbu r4,zs:[r5]
shrui r4,r4,#4
bsr DBGDisplayNybble
ldi r1,#'.'
bsr DBGDispChar
lbu r1,zs:[r5]
bsr DBGDispCond
br .exit
.noDisp:
addui r2,r2,#7
.exit
lws c1,[sp]
addui sp,sp,#8
rts
 
;------------------------------------------------------------------------------
; Display the condition portion of the predicate.
;------------------------------------------------------------------------------
 
DBGDispCond:
addui sp,sp,#-8
sws c1,[sp]
andi r7,r1,#15
addu r7,r7,r7
addu r7,r7,r1
lbu r1,cs:DBGPredCons[r7]
bsr DBGDispChar
lbu r1,cs:DBGPredCons+1[r7]
bsr DBGDispChar
lbu r1,cs:DBGPredCons+2[r7]
bsr DBGDispChar
lws c1,[sp]
addui sp,sp,#8
rts
 
;------------------------------------------------------------------------------
; Display a mnemonic.
; Parameters:
; r3 = pointer to mnemonic string
;------------------------------------------------------------------------------
 
DBGDisplayMne:
addui sp,sp,#-8
sws c1,[sp]
bsr space1
; Mnemonics are always at least 2 chars
lbu r1,cs:[r3]
bsr DBGDispChar
; second char
lbu r1,cs:1[r3]
biti p1,r1,#$80 ; test high bit
bsr DBGDispChar
p1.ne br .exit
; third char
lbu r1,cs:2[r3]
biti p1,r1,#$80 ; test high bit
bsr DBGDispChar
p1.ne br .exit
; fourth char
lbu r1,cs:3[r3]
biti p1,r1,#$80 ; test high bit
bsr DBGDispChar
p1.ne br .exit
; fifth char
lbu r1,cs:4[r3]
bsr DBGDispChar
.exit:
addui r2,r2,#1 ; 1 space
lws c1,[sp]
addui sp,sp,#8
rts
 
;------------------------------------------------------------------------------
; Display a register
;------------------------------------------------------------------------------
 
DBGDispReg:
addui sp,sp,#-16
sws c1,[sp]
sw r7,8[sp]
mov r7,r1
ldi r1,#'r'
DBGDispBx1:
bsr DBGDispChar
cmpi p0,r7,#10
p0.geu divui r1,r7,#10
p0.geu addui r1,r1,#'0'
p0.geu bsr DBGDispChar
modui r1,r7,#10
addui r1,r1,#'0'
bsr DBGDispChar
lws c1,[sp]
lw r7,8[sp]
addui sp,sp,#16
rts
 
;------------------------------------------------------------------------------
; Display a bit number
;------------------------------------------------------------------------------
 
DBGDispBReg:
addui sp,sp,#-16
sws c1,[sp]
sw r7,8[sp]
mov r7,r1
ldi r1,#'b'
br DBGDispBx1
 
;------------------------------------------------------------------------------
; Display a special purpose register
;------------------------------------------------------------------------------
 
DBGDispSpr:
addui sp,sp,#-16
sws c1,[sp]
sw r7,8[sp]
addu r7,r1,r1
addu r7,r7,r1 ; r7 = r1 * 3
lbu r1,cs:DBGSpr[r7]
bsr DBGDispChar
lbu r1,cs:DBGSpr+1[r7]
bsr DBGDispChar
lbu r1,cs:DBGSpr+2[r7]
cmpi p0,r1,#' '
p0.ne bsr DBGDispChar
lws c1,[sp]
lw r7,8[sp]
addui sp,sp,#16
rts
 
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
 
DBGComma:
addui sp,sp,#-8
sws c1,[sp]
ldi r1,#','
bsr DBGDispChar
lws c1,[sp]
addui sp,sp,#8
rts
 
;------------------------------------------------------------------------------
; Display registers for TST instruction.
;------------------------------------------------------------------------------
 
DBGDispTstregs:
addui sp,sp,#-8
sws c1,[sp]
ldi r2,#54 ; tab out to column 54
lbu r1,zs:1[r5]
andi r1,r1,#15
bsr DBGDispSpr
bsr DBGComma
lbu r1,zs:2[r5]
andi r1,r1,#$3f
bsr DBGDispReg
lws c1,[sp]
addui sp,sp,#8
rts
 
DBGDispCmpregs:
addui sp,sp,#-8
sws c1,[sp]
ldi r2,#54 ; tab out to column 54
lbu r1,zs:1[r5]
andi r1,r1,#15
bsr DBGDispSpr
bsr DBGComma
lbu r1,zs:2[r5]
andi r1,r1,#$3f
bsr DBGDispReg
bsr DBGComma
lbu r1,zs:2[r5]
shrui r1,r1,#6
lbu r7,zs:3[r5]
andi r7,r7,#15
shli r7,r7,#2
or r1,r7,r1
bsr DBGDispReg
lws c1,[sp]
addui sp,sp,#8
rts
 
DBGDispBrDisp:
addui sp,sp,#-8
sws c1,[sp]
ldi r2,#54 ; tab out to column 54
lbu r1,zs:1[r5]
lbu r7,zs:2[r5]
andi r1,r1,#15
shli r7,r7,#4
or r1,r7,r1
addui r1,r1,#3 ; instruction size
addu r4,r1,r5 ; instruction address
ldi r1,#'$'
bsr DBGDispChar
bsr DBGDisplayHalf
lws c1,[sp]
addui sp,sp,#8
rts
 
DBGDispCmpimm:
addui sp,sp,#-8
sws c1,[sp]
ldi r2,#54 ; tab out to column 54
lbu r1,zs:1[r5]
andi r1,r1,#15
bsr DBGDispSpr
bsr DBGComma
lbu r1,zs:2[r5]
andi r1,r1,#$3f
bsr DBGDispReg
bsr DBGComma
lbu r1,zs:2[r5]
shrui r1,r1,#6
lbu r7,zs:3[r5]
shli r7,r7,#2
or r4,r7,r1
ldi r1,#'#'
bsr DBGDispChar
ldi r1,#'$'
bsr DBGDispChar
bsr DBGDisplayHalf
lws c1,[sp]
addui sp,sp,#8
rts
 
; Used by mtspr
DBGDispSprRx:
addui sp,sp,#-16
sws c1,[sp]
sw r7,8[sp]
ldi r2,#54 ; tab out to column 54
lbu r1,zs:2[r5]
lbu r7,zs:3[r5]
shrui r1,r1,#6
andi r7,r7,#15
shli r7,r7,#2
or r1,r7,r1
bsr DBGDispSpr
bsr DBGComma
lbu r1,zs:2[r5]
andi r1,r1,#63
bsr DBGDispReg
lws c1,[sp]
lw r7,8[sp]
addui sp,sp,#16
rts
 
; Format #4
;
DBGDispRxRxRx:
addui sp,sp,#-16
sws c1,[sp]
sw r7,8[sp]
ldi r2,#54 ; tab out to column 54
lbu r1,zs:3[r5]
shrui r1,r1,#4
lbu r7,zs:4[r5]
andi r7,r7,#3
shli r7,r7,#4
or r1,r7,r1
bsr DBGDispReg
bsr DBGComma
lbu r1,zs:2[r5]
andi r1,r1,#63
bsr DBGDispReg
bsr DBGComma
lbu r1,zs:2[r5]
shrui r1,r1,#6
lbu r7,zs:3[r5]
andi r7,r7,#15
shli r7,r7,#2
or r1,r7,r1
bsr DBGDispReg
lws c1,[sp]
lw r7,8[sp]
addui sp,sp,#16
rts
 
; Format #5
;
DBGDispRxRx:
addui sp,sp,#-16
sws c1,[sp]
sw r7,8[sp]
ldi r2,#54 ; tab out to column 54
lbu r1,zs:2[r5]
shrui r1,r1,#6
lbu r7,zs:3[r5]
andi r7,r7,#15
shli r7,r7,#2
or r1,r7,r1
bsr DBGDispReg
bsr DBGComma
lbu r1,zs:2[r5]
andi r1,r1,#63
bsr DBGDispReg
lws c1,[sp]
lw r7,8[sp]
addui sp,sp,#16
rts
 
; Format #6
;
DBGDispPxPxPx:
addui sp,sp,#-16
sws c1,[sp]
sw r7,8[sp]
ldi r2,#54 ; tab out to column 54
lbu r1,zs:3[r5]
shrui r1,r1,#4
lbu r7,zs:4[r5]
andi r7,r7,#3
shli r7,r7,#4
or r1,r7,r1
bsr DBGDispBReg
bsr DBGComma
lbu r1,zs:2[r5]
andi r1,r1,#63
bsr DBGDispBReg
bsr DBGComma
lbu r1,zs:2[r5]
shrui r1,r1,#6
lbu r7,zs:3[r5]
andi r7,r7,#15
shli r7,r7,#2
or r1,r7,r1
bsr DBGDispBReg
lws c1,[sp]
lw r7,8[sp]
addui sp,sp,#16
rts
 
; Format #7
;
DBGDispNone:
rts
 
; Format #8 (biti)
;
DBGDispPxRxImm:
addui sp,sp,#-16
sws c1,[sp]
ldi r2,#54 ; tab out to column 54
lbu r1,zs:2[r5]
shrui r1,r1,#6
lbu r7,zs:3[r5]
andi r7,r7,#3
_4addu r1,r7,r1
bsr DBGDispSpr
bsr DBGComma
lbu r1,zs:2[r5]
andi r1,r1,#63
bsr DBGDispReg
bsr DBGComma
lbu r1,zs:3[r5]
shrui r1,r1,#4
lbu r7,zs:4[r5]
_16addu r1,r7,r1
bsr DBGDispImm
lws c1,[sp]
addui sp,sp,#16
rts
 
; Format #9 (adduis)
;
DBGDispRxImm:
addui sp,sp,#-8
sws c1,[sp]
lbu r1,zs:2[r5]
andi r1,r1,#63
bsr DBGDispReg
bsr DBGComma
lbu r1,zs:2[r2]
shrui r1,r1,#6
lbu r7,zs:3[r2]
_4addu r1,r7,r1
bsr DBGDispImm
lws c1,[sp]
addui sp,sp,#8
rts
 
;------------------------------------------------------------------------------
; Display an immediate value.
;------------------------------------------------------------------------------
 
DBGDispImm:
addui sp,sp,#-16
sws c1,[sp]
sw r4,8[sp]
mov r4,r1
ldi r1,#'#'
bsr DBGDispChar
ldi r1,#'$'
bsr DBGDispChar
cmpi p0,r4,#$FFFF
p0.gtu bsr DBGDisplayHalf
p0.gtu br .exit
cmpi p0,r4,#$FF
p0.gtu bsr DBGDisplayCharr
p0.gtu br .exit
bsr DBGDisplayByte
.exit:
lw c1,[sp]
lw r4,8[sp]
addui sp,sp,#16
rts
 
;------------------------------------------------------------------------------
; DBGGetFunc:
; Get the function code bits from the instruction. These come from one of
; four different locations depending on the opcode.
;
; Parameters:
; r1 = opcode group (0 to 15)
; Returns:
; r1 = function code
;------------------------------------------------------------------------------
 
DBGGetFunc:
jci c0,cs:DBGFuncT[r1]
gf0:
gf2:
gf3:
gf4:
gf6:
gfB:
lbu r1,zs:4[r5]
shrui r1,r1,#2
rts
gf1:
gf5:
gf7:
gf8:
lbu r1,zs:3[r5]
shrui r1,r1,#4
rts
gf9:
lbu r1,zs:5[r5]
andi r1,r1,#15
rts
gfA:
lbu r1,zs:2[r5]
andi r1,r1,#15
rts
 
;------------------------------------------------------------------------------
; Checker-board RAM testing routine.
;
; Ram is tested from $6000 to $7FFFFFF. The first 24k of RAM is not tested,
; as 16k underlays the scratchpad RAM and is unaccessible and 8kb is used by
; the kernel.
;
; First uses the pattern AAAAAAAA to memory
; 55555555
;
; Then uses the pattern 55555555 to memory
; AAAAAAAA
;------------------------------------------------------------------------------
 
DBGRamTest:
addui sp,sp,#-8
sws c1,[sp]
ldi r10,#$AAAAAAAA
ldi r11,#$55555555
bsr DBGRamTest1
ldi r10,#$55555555
ldi r11,#$AAAAAAAA
bsr DBGRamTest1
lws c1,[sp]
addui sp,sp,#8
rts
 
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
 
DBGRamTest1:
addui sp,sp,#-8
sws c1,[sp]
 
mov r1,r10
mov r3,r11
ldi r5,#$6000
ldi lc,#$3FF3FF ; (32MB - 24kB)/8 - 1
mov r8,r0
.0001:
sh r1,zs:[r5]
sh r3,zs:4[r5]
addui r5,r5,#8
andi r4,r5,#$FFF
tst p0,r4
p0.eq shrui r4,r5,#12
p0.eq ldi r2,#0
p0.eq ldi r6,#1
p0.eq bsr DBGDisplayCharr
loop .0001
 
ldi r5,#$6000
ldi lc,#$3FF3FF ; (32MB - 24kB)/8 - 1
.0002:
lh r1,zs:[r5]
lh r3,zs:4[r5]
cmp p0,r1,r10
p0.ne mov r7,r1
p0.ne bsr DBGBadRam
cmp p0,r3,r11
p0.ne mov r7,r3
p0.ne bsr DBGBadRam
addui r5,r5,#8
andi r4,r5,#$FFF
tst p0,r4
p0.eq shrui r4,r5,#12
p0.eq ldi r2,#0
p0.eq ldi r6,#1
p0.eq bsr DBGDisplayCharr
loop .0002
lws c1,[sp]
addui sp,sp,#8
rts
 
;------------------------------------------------------------------------------
; Dispay bad ram nessage with address and data.
;------------------------------------------------------------------------------
 
DBGBadRam:
addui sp,sp,#-8
sws c1,[sp]
lla r1,cs:msgBadRam
ldi r2,#0
ldi r6,#2
addu r6,r6,r8
bsr DBGDispString
mov r4,r5
bsr DBGDisplayHalf
bsr space1
mov r4,r7
bsr DBGDisplayHalf
addui r8,r8,#1
andi r8,r8,#15
cmpi p0,r8,#15
p0.eq ldis lc,#1
lws c1,[sp]
addui sp,sp,#8
rts
 
msgBadRam:
byte "Menory failed at: ",0
 
;------------------------------------------------------------------------------
; Reverse the video attribute.
;------------------------------------------------------------------------------
 
ReverseVideo:
lhu r1,NormAttr
shrui r2,r1,#9
shli r3,r1,#9
andi r2,r2,#%111111111_0000000000
andi r3,r3,#%111111111_000000000_0000000000
or r1,r2,r3
rts
 
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
; Tables
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
 
align 2
DBGFuncT:
dc gf0,gf1,gf2,gf3,gf4,gf5,gf6,gf7,gf8,gf9,gfA,gfB,gf0,gf0,gf0,gf0
 
align 2
DBGLineTbl:
dc 0
dc 1*84
dc 2*84
dc 3*84
dc 4*84
dc 5*84
dc 6*84
dc 7*84
dc 8*84
dc 9*84
dc 10*84
dc 11*84
dc 12*84
dc 13*84
dc 14*84
dc 15*84
dc 16*84
dc 17*84
dc 18*84
dc 19*84
dc 20*84
dc 21*84
dc 22*84
dc 23*84
dc 24*84
dc 25*84
dc 26*84
dc 27*84
dc 28*84
dc 29*84
dc 30*84
dc 31*84
 
; Table of the length of each instruction.
;
DBGInsnLength:
byte 3,3,3,3, 3,3,3,3, 3,3,3,3, 3,3,3,3 ; TST
byte 4,4,4,4, 4,4,4,4, 4,4,4,4, 4,4,4,4 ; CMP
byte 4,4,4,4, 4,4,4,4, 4,4,4,4, 4,4,4,4 ; CMPI
byte 3,3,3,3, 3,3,3,3, 3,3,3,3, 3,3,3,3 ; BR
 
byte 5,4,5,1, 1,1,5,4, 5,5,5,5, 5,5,5,5
byte 5,5,1,5, 5,5,1,1, 5,1,1,1, 1,1,1,1
byte 1,1,1,1, 1,1,1,1, 1,1,1,5, 5,5,5,4
byte 1,1,5,1, 1,1,1,4, 5,4,1,1, 1,1,1,1
 
byte 5,5,5,5, 5,5,5,1, 1,1,1,5, 5,1,5,5
byte 5,5,5,5, 1,1,5,6, 5,5,5,5, 1,4,5,4
byte 3,5,6,3, 3,4,4,4, 4,4,6,4, 5,5,5,5
byte 5,5,5,5, 5,5,5,1, 1,1,1,1, 1,1,1,1
 
byte 5,5,5,5, 1,1,5,6, 3,5,3,5, 3,1,1,1
byte 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1
byte 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1
byte 4,2,4,2, 2,5,4,2, 2,2,2,2, 2,1,1,2
 
; Table of operand format indexes
;
; 0 = px,rx
; 1 = px,rx,rx
; 2 = px,rx,#imm
; 3 = disp12
; 4 = rx,rx,rx
; 5 = rx,rx
; 6 = px,px,px
; 7 = none
; 8 = px,rx,#imm (biti)
; 9 = rx,#imm (addui short)
; 10 = rx,rx,#imm
; 11 = mlo
; 12 = shift
; 13 = rx,#imm (ldi)
; 14 = rx,rx,rx,rx (mux format)
; 15 = rx,mem (load/store)
; 16 = rx,rx,rx,[rx] (cas)
; 17 = rx,[rx] (stset)
; 18 = [rx],[rx],rx (stmov/stcmp)
; 19 = rx,#imm (cache)
; 20 = [cx] jsr
; 21 = jsr
; 22 = jsr
; 23 = rts
; 24 = loop
; 25 = sys/int
; 26 = rx,spr
; 27 = spr,rx
; 28 = bitfield
; 29 = spr,spr
; 30 = rx,[rx+rx*sc] (load/store)
; 31 = stix
; 32 = inc
; 33 = tlb
; 34 = rts
; 35 = bcd
; 36 = stp
; 37 = imm
 
DBGOperFmt:
byte 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 ; TST px,rx
byte 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1 ; CMP px,rx,rx
byte 2,2,2,2, 2,2,2,2, 2,2,2,2, 2,2,2,2 ; CMPI px,rx,#imm
byte 3,3,3,3, 3,3,3,3, 3,3,3,3, 3,3,3,3 ; BR
 
byte 4,5,6,7, 7,7,8,9, 10,10,10,10, 10,10,10,10
byte 4,11,7,10, 10,10,7,7, 12,7,7,7, 7,7,7,7
byte 7,7,7,7, 7,7,7,7, 7,7,7,10, 10,10,10,13
byte 7,7,14,7, 7,7,7,5, 4,6,7,7, 7,7,7,7
 
byte 15,15,15,15, 15,15,15,7, 7,7,7,15, 15,7,15,15
byte 15,15,15,15, 7,7,15,16, 17,18,18,17, 7,38,15,19
byte 20,21,22,23, 24,25,25,5, 26,27,28,29, 15,15,15,15
byte 30,30,30,30, 30,30,30,7, 7,7,7,7, 7,7,7,7
 
byte 30,30,30,30, 7,7,31,32, 7,7,7,7, 7,7,7,7
byte 7,7,7,7, 7,7,7,7, 7,7,7,7, 7,7,7,7
byte 7,7,7,7, 7,7,7,7, 7,7,7,7, 7,7,7,7
byte 33,7,34,7, 7,35,36,7, 7,7,7,7, 7,7,7,37
 
align 2
 
DBGOperFmtT:
dc DBGDispTstregs,DBGDispCmpregs,DBGDispBrDisp,DBGDispCmpimm,DBGDispRxRxRx,DBGDispRxRx,DBGDispPxPxPx,DBGDispNone
dc DBGDispPxRxImm,DBGDispRxImm,DBGDispNone,DBGDispNone,DBGDispNone,DBGDispRxImm,DBGDispNone,DBGDispNone
dc DBGDispNone,DBGDispNone,DBGDispNone,DBGDispNone,DBGDispNone,DBGDispNone,DBGDispNone,DBGDispNone
dc DBGDispNone,DBGDispNone,DBGDispNone,DBGDispSprRx,DBGDispNone,DBGDispNone,DBGDispNone,DBGDispNone
dc DBGDispNone,DBGDispNone,DBGDispNone,DBGDispNone,DBGDispNone,DBGDispNone,DBGDispNone,DBGDispNone
 
; Table of instruction mnemonic string addresses
; If the most signficant 12 bits are $FFF then a second table is referred to.
;
align 2
DBGInsnMne:
dc mne_tst,mne_tst,mne_tst,mne_tst,mne_tst,mne_tst,mne_tst,mne_tst,mne_tst,mne_tst,mne_tst,mne_tst,mne_tst,mne_tst,mne_tst,mne_tst
dc mne_cmp,mne_cmp,mne_cmp,mne_cmp,mne_cmp,mne_cmp,mne_cmp,mne_cmp,mne_cmp,mne_cmp,mne_cmp,mne_cmp,mne_cmp,mne_cmp,mne_cmp,mne_cmp
dc mne_cmpi,mne_cmpi,mne_cmpi,mne_cmpi,mne_cmpi,mne_cmpi,mne_cmpi,mne_cmpi,mne_cmpi,mne_cmpi,mne_cmpi,mne_cmpi,mne_cmpi,mne_cmpi,mne_cmpi,mne_cmpi
dc mne_br,mne_br,mne_br,mne_br,mne_br,mne_br,mne_br,mne_br,mne_br,mne_br,mne_br,mne_br,mne_br,mne_br,mne_br,mne_br
dc $FFF0,$FFF1,$FFF2,mne_q,mne_q,mne_q,mne_biti,mne_addui,mne_addi,mne_subi,mne_muli,mne_divi,mne_addui,mne_subui,mne_mului,mne_divui
dc $FFF3,mne_mlo,mne_q,mne_andi,mne_ori,mne_eori,mne_q,mne_q,$FFF4,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q
dc mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_2addui,mne_4addui,mne_8addui,mne_16addui,mne_ldi
dc mne_q,mne_q,mne_mux,mne_q,mne_q,mne_q,mne_q,$FFF5,$FFF6,$FFF7,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q
dc mne_lb,mne_lbu,mne_lc,mne_lcu,mne_lh,mne_lhu,mne_lw,mne_q,mne_q,mne_q,mne_q,mne_lvwar,mne_swcr,mne_q,mne_lws,mne_lcl
dc mne_sb,mne_sc,mne_sh,mne_sw,mne_q,mne_q,mne_sti,mne_cas,mne_stset,mne_stmov,mne_stcmp,mne_stfnd,mne_q,mne_ldis,mne_sws,mne_cache
dc mne_jsr,mne_jsr,mne_jsr,mne_rts,mne_loop,mne_sys,mne_int,$FFF8,mne_mfspr,mne_mtspr,$FFF9,mne_movs,mne_lvb,mne_lvc,mne_lvh,mne_lvw
dc mne_lb,mne_lbu,mne_lc,mne_lcu,mne_lh,mne_lhu,mne_lw,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q
dc mne_sbx,mne_scx,mne_sh,mne_sw,mne_q,mne_q,mne_sti,mne_inc,mne_push,mne_pea,mne_pop,mne_link,mne_unlink,mne_q,mne_q,mne_q
dc mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q
dc mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q
dc $FFFA,mne_nop,mne_rts,mne_rte,mne_rti,$FFFB,mne_stp,mne_sync,mne_memsb,mne_memdb,mne_cli,mne_sei,mne_rtd,mne_q,mne_q,mne_imm
DBGInsnMne0:
dc mne_add,mne_sub,mne_mul,mne_div,mne_addu,mne_subu,mne_mulu,mne_divu,mne_2addu,mne_4addu,mne_8addu,mne_16addu,mne_q,mne_q,mne_q,mne_q
dc mne_min,mne_max,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q
dc mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q
dc mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q
DBGInsnMne1:
dc mne_cpuid,mne_redor,mne_redand,mne_par,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q
DBGInsnMne2:
dc mne_pand,mne_por,mne_peor,mne_pnand,mne_pnor,mne_penor,mne_pandc,mne_porc,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q
dc mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q
dc mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q
dc mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q
DBGInsnMne3:
dc mne_and,mne_or,mne_eor,mne_nand,mne_nor,mne_enor,mne_andc,mne_orc,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q
dc mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q
dc mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q
dc mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q
DBGInsnMne4:
dc mne_shl,mne_shr,mne_shlu,mne_shru,mne_rol,mne_ror,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q
dc mne_shli,mne_shri,mne_shlui,mne_shrui,mne_roli,mne_rori,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q
dc mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q
dc mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q
DBGInsnMne5:
dc mne_fmov,mne_q,mne_ftoi,mne_itof,mne_fneg,mne_fabs,mne_fsign,mne_fman,mne_fnabs,mne_q,mne_q,mne_q,mne_fstat,mne_frm,mne_q,mne_q
DBGInsnMne6:
dc mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_fcmp,mne_fadd,mne_fsub,mne_fmul,mne_fdiv,mne_q,mne_q,mne_q,mne_q
dc mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_fcmp,mne_fadd,mne_fsub,mne_fmul,mne_fdiv,mne_q,mne_q,mne_q,mne_q
dc mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q
dc mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q
DBGInsnMne7:
DBGInsnMne8:
dc mne_mov,mne_neg,mne_not,mne_abs,mne_sign,mne_cntlz,mne_cntlo,mne_cntpop,mne_sxb,mne_sxc,mne_sxh,mne_com,mne_zxb,mne_zxc,mne_zxh,mne_q
DBGInsnMne9:
dc mne_bfins,mne_bfset,mne_bfclr,mne_bfchg,mne_bfextu,mne_bfext,mne_bfinsi,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q
DBGInsnMneA:
dc mne_q,mne_q,mne_tlbrdreg,mne_tlbwrreg,mne_tlbwi,mne_tlben,mne_tlbdis,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q
DBGInsnMneB:
dc mne_bcdadd,mne_bcdsub,mne_bcdmul,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q,mne_q
DBGInsnMneT:
dc DBGInsnMne0,DBGInsnMne1,DBGInsnMne2,DBGInsnMne3,DBGInsnMne4,DBGInsnMne5,DBGInsnMne6,DBGInsnMne7,DBGInsnMne8,DBGInsnMne9,DBGInsnMneA,DBGInsnMneB
 
; Table of predicate conditions
;
DBGPredCons:
byte "f ","f ","eq ","ne ","le ","gt ","lt ","ge ","leu","gtu","ltu","geu"," "," "," "," "
 
; Special purpose register names
;
DBGSpr:
byte "p0 ","p1 ","p2 ","p3 ","p4 ","p5 ","p6 ","p7 ","p8 ","p9 ","p10","p11","p12","p13","p14","p15"
byte "c0 ","c1 ","c2 ","c3 ","c4 ","c5 ","c6 ","c7 ","c8 ","c9 ","c10","c11","c12","c13","c14","c15"
byte "zs ","ds ","es ","fs ","gs ","hs ","ss ","cs ","zsl","dsl","esl","fsl","gsl","hsl","ssl","csl"
byte "pra"," ","tck","lc "," "," ","asd","sr "," "," "," "," "," "," "," "," "
 
; Table of mnemonics
;
mne_16addu: byte "16add",'u'|$80
mne_2addu: byte "2add",'u'|$80
mne_4addu: byte "4add",'u'|$80
mne_8addu: byte "8add",'u'|$80
mne_16addui: byte "16addu",'i'|$80
mne_2addui: byte "2addu",'i'|$80
mne_4addui: byte "4addu",'i'|$80
mne_8addui: byte "8addu",'i'|$80
mne_add: byte "ad",'d'|$80
mne_addi: byte "add",'i'|$80
mne_addu: byte "add",'u'|$80
mne_addui: byte "addu",'i'|$80
mne_and: byte "an",'d'|$80
mne_andi: byte "and",'i'$80
mne_bfchg: byte "bfch",'g'|$80
mne_bfclr: byte "bfcl",'r'|$80
mne_bfext: byte "bfex",'t'|$80
mne_bfextu: byte "bfext",'u'|$80
mne_bfins: byte "bfin",'s'|$80
mne_bfinsi: byte "bfins",'i'|$80
mne_bfset: byte "bfse",'t'|$80
mne_biti: byte "bit",'i'|$80
mne_br: byte "b",'r'|$80
mne_brk: byte "br",'k'|$80
mne_bsr: byte "bs",'r'|$80
mne_cmp: byte "cm",'p'|$80
mne_cmpi: byte "cmp",'i'|$80
mne_div: byte "di",'v'|$80
mne_divi: byte "div",'i'|$80
mne_divu: byte "div",'u'|$80
mne_divui: byte "divu",'i'|$80
mne_eor: byte "eo",'r'|$80
mne_eori: byte "eor",'i'|$80
mne_imm: byte "im",'m'|$80
mne_jsr byte "js",'r'|$80
mne_lb: byte "l",'b'|$80
mne_lbu: byte "lb",'u'|$80
mne_lc: byte "l",'c'|$80
mne_lcu: byte "lc",'u'|$80
mne_ldi: byte "ld",'i'|$80
mne_ldis: byte "ldi",'s'|$80
mne_lh: byte "l",'h'|$80
mne_lhu: byte "lh",'u'|$80
mne_loop: byte "loo",'p'|$80
mne_lvb: byte "lv",'b'|$80
mne_lvc: byte "lv",'c'|$80
mne_lvh: byte "lv",'h'|$80
mne_lvw: byte "lv",'w'|$80
mne_lw: byte "l",'w'|$80
mne_lws: byte "lw",'s'|$80
mne_mfspr: byte "mfsp",'r'|$80
mne_mtspr: byte "mtsp",'r'|$80
mne_mov: byte "mo",'v'|$80
mne_movs: byte "mov",'s'|$80
mne_mul: byte "mu",'l'|$80
mne_muli: byte "mul",'i'|$80
mne_mulu: byte "mul",'u'|$80
mne_mului: byte "mulu",'i'|$80
mne_nop: byte "no",'p'|$80
mne_or: byte "o",'r'|$80
mne_ori: byte "or",'i'|$80
mne_q: byte "??",'?'|$80
mne_rol: byte "ro",'l'|$80
mne_roli: byte "rol",'i'|$80
mne_ror: byte "ro",'r'|$80
mne_rori: byte "ror",'i'|$80
mne_rtd: byte "rt",'d'|$80
mne_rte: byte "rt",'e'|$80
mne_rti: byte "rt",'i'|$80
mne_rts: byte "rt",'s'|$80
mne_sb: byte "s",'b'|$80
mne_sc: byte "s",'c'|$80
mne_sh: byte "s",'h'|$80
mne_shl: byte "sh",'l'|$80
mne_shli: byte "shl",'i'|$80
mne_shr: byte "sh",'r'|$80
mne_shri: byte "shr",'i'|$80
mne_shru: byte "shr",'u'|$80
mne_shrui: byte "shru",'i'|$80
mne_stp: byte "st",'p'|$80
mne_sub: byte "su",'b'|$80
mne_subu: byte "sub",'u'|$80
mne_sw: byte "s",'w'|$80
mne_sync: byte "syn",'c'|$80
mne_sys: byte "sy",'s'|$80
mne_tlben: byte "tlbe",'n'|$80
mne_tlbdis: byte "tlbdi",'s'|$80
mne_tlbrdreg: byte "tlbrdre",'g'|$80
mne_tlbwi: byte "tlbw",'i'|$80
mne_tlbwrreg: byte "tlbwrre",'g'|$80
mne_tst: byte "ts",'t'|$80
 
msgDebugger:
byte "Thor Debugger (C) 2015 Robert Finch",0
 
/trunk/software/boot_tb/video.asm
0,0 → 1,1048
; ============================================================================
; __
; \\__/ o\ (C) 2015 Robert Finch, Stratford
; \ __ / All rights reserved.
; \/_// robfinch<remove>@finitron.ca
; ||
;
;
; This source file is free software: you can redistribute it and/or modify
; it under the terms of the GNU Lesser General Public License as published
; by the Free Software Foundation, either version 3 of the License, or
; (at your option) any later version.
;
; This source file is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; GNU General Public License for more details.
;
; You should have received a copy of the GNU General Public License
; along with this program. If not, see <http://www.gnu.org/licenses/>.
;
;
; Video BIOS routines don't touch the data segment. It is assumed that a
; different data segment will be is use for each text controller.
; ============================================================================
 
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
 
public VBClearScreen:
ldi r1,#' '
lh r2,NormAttr
andi r2,r2,#-1024
or r2,r2,r1
ldis lc,#SCRSZ-1
lh r1,Vidptr
; ldi r1,#TEXTSCR
stset.hi r2,hs:[r1]
rts
endpublic
 
public VBClearScreen2:
ldis lc,#SCRSZ-1
ldi r2,#' '|%000011000_111111111_00_00000000;
ldi r1,#TEXTSCR2
stset.hi r2,hs:[r1]
rts
endpublic
 
;------------------------------------------------------------------------------
; Scroll the screen upwards.
;------------------------------------------------------------------------------
 
ScrollUp:
addui r31,r31,#-8
sws c1,[r31]
mov r1,r0
mov r2,r0
lcu r3,Textcols
lcu r4,Textrows
ldi r5,#1
bsr VBScrollWindowUp
addui r1,r4,#-1
bsr BlankLine
lws c1,[r31]
addui r31,r31,#8
rts
 
;------------------------------------------------------------------------------
; Blank out a line on the screen.
;
; Parameters:
; r1 = line number to blank
; Trashes:
; r2,r3,r4
;------------------------------------------------------------------------------
 
BlankLine:
lcu r2,Textcols
mulu r1,r1,r2
_4addu r3,r1,r0
lh r1,NormAttr
ori r1,r1,#$20
lh r4,Vidptr
.0001:
sh r1,[r4+r3]
addui r3,r3,#4
addui r2,r2,#-1
tst p0,r2
p0.ne br .0001
rts
 
;------------------------------------------------------------------------------
; Turn cursor on or off.
;------------------------------------------------------------------------------
 
VBCursorOn:
CursorOn:
addui r31,r31,#-16
sw r1,zs:8[r31]
sw r2,zs:[r31]
lh r2,Vidregs
ldi r1,#$40
sh r1,hs:32[r2]
ldi r1,#$1F
sh r1,hs:36[r2]
lw r2,zs:[r31]
lw r1,zs:8[r31]
addui r31,r31,#16
mov r6,r0
rts
 
VBCursorOff:
CursorOff:
addui r31,r31,#-16
sw r1,zs:8[r31]
sw r2,zs:[r31]
lh r2,Vidregs
ldi r1,#$20
sh r1,hs:32[r2]
mov r1,r0
sh r1,hs:36[r2]
lw r2,zs:[r31]
lw r1,zs:8[r31]
addui r31,r31,#16
mov r6,r0
rts
 
;------------------------------------------------------------------------------
; Get the number of text rows and columns from the video controller.
;------------------------------------------------------------------------------
 
GetTextRowscols:
lh r2,Vidregs
lvc r1,hs:0[r2]
sc r1,Textcols
lvc r1,hs:4[r2]
sc r1,Textrows
rts
 
;------------------------------------------------------------------------------
; Set cursor to home position.
;------------------------------------------------------------------------------
 
public HomeCursor:
sc r0,CursorX
sc r0,CursorY
endpublic
 
;------------------------------------------------------------------------------
; SyncVideoPos:
;
; Synchronize the absolute video position with the cursor co-ordinates.
; Does not modify any predicates. Leaf routine.
;------------------------------------------------------------------------------
 
SyncVideoPos:
addui r31,r31,#-32
sw r1,16[r31] ; save off some working regs
sw r2,8[r31]
sw r3,[r31]
sws hs,24[r31]
ldis hs,#$FFD00000
ldi r1,#5
sc r1,hs:LEDS
lc r2,CursorY
lc r3,Textcols
mulu r1,r2,r3
lc r2,CursorX
addu r1,r1,r2
sc r1,VideoPos
lh r3,Vidregs ; r3 = address of video registers
sh r1,hs:44[r3] ; Update the position in the text controller
lws hs,24[r31]
lw r3,[r31] ; restore the regs
lw r2,8[r31]
lw r1,16[r31]
addui r31,r31,#32
rts
 
;------------------------------------------------------------------------------
; Video BIOS
; Video Exception #10
;
; Parameters:
; r1 to r5 as needed
; r6 = Function
; Returns:
; r6 = 0 if everything ok, otherwise BIOS error code
;
; 0x02 = Set Cursor Position r1 = row, r2 = col
; 0x03 = Get Cursor position returns r1 = row, r2 = col
; 0x06 = Scroll Window up r1=left, r2=top, r3=right, r4=bottom, r5=#lines
; 0x0A = Display character at cursor position, r1 = char, r2 = # times
; 0x14 = Display String r1 = pointer to string
; 0x15 = Display number r1 = number, r2 = # digits
; 0x17 = Display Word r1 as hex = word
; 0x18 = Display Half word as hex r1 = half word
; 0x19 = Display Charr char in hex r1 = char
; 0x1A = Display Byte in hex r1 = byte
; 0x20 = Convert ascii to screen r1 = char to convert
; 0x21 = Convert screen to ascii r1 = char to convert
; 0x22 = clear screen
; 0x23 = set attribute r1 = attribute
; 0x24 = turn cursor on
; 0x25 = turn cursor off
;------------------------------------------------------------------------------
 
MAX_VIDEO_BIOS_CALL = 0x25
 
code
align 2
VideoBIOS_FuncTable:
dc VBUnsupported ; 0x00
dc VBUnsupported
dc VBSetCursorPos ; 0x02
dc VBGetCursorPos ; 0x03
dc VBUnsupported
dc VBUnsupported
dc VBScrollWindowUp ; 0x06
dc VBUnsupported
dc VBUnsupported ; 0x08
dc VBUnsupported
dc VBDisplayCharRep
dc VBUnsupported
dc VBUnsupported
dc VBUnsupported
dc VBUnsupported
dc VBUnsupported
dc VBUnsupported ; 0x10
dc VBUnsupported
dc VBUnsupported
dc VBUnsupported
dc VBDisplayString
dc PRTNUM
dc VBUnsupported
dc VBDispWord
dc VBDispHalf
dc VBDispCharr
dc VBDispByte
dc VBUnsupported
dc VBUnsupported
dc VBUnsupported
dc VBUnsupported
dc VBUnsupported
dc VBAsciiToScreen ; 0x20
dc VBScreenToAscii
dc VBClearScreen
dc VBSetNormAttribute
dc VBCursorOn
dc VBCursorOff ; 0x25
 
VideoBIOSCall:
addui r31,r31,#-16
sws c1,[r31]
sws hs,8[r31]
ldis hs,#$FFD00000
cmpi p0,r6,#MAX_VIDEO_BIOS_CALL
p0.ge br .badCallno
jci c1,cs:VideoBIOS_FuncTable[r6]
.0004:
; bsr UnlockVideoBIOS
lws c1,[r31]
lws hs,8[r31]
addui r31,r31,#16
rte
.badCallno:
ldi r2,#E_BadFuncno
br .0004
 
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
 
VBUnsupported:
ldi r2,#E_Unsupported
rts
 
VBSetCursorPos:
addui r31,r31,#-8
sws c1,[r31]
sc r1,CursorY
sc r2,CursorX
bsr SyncVideoPos
mov r6,r0
lws c1,[r31]
addui r31,r31,#8
rts
 
VBGetCursorPos:
lcu r1,CursorY
lcu r2,CursorX
mov r6,r0
rts
 
;------------------------------------------------------------------------------
; Set the attribute to use for subsequent video output.
;------------------------------------------------------------------------------
 
VBSetNormAttribute:
sh r1,NormAttr
mov r6,r0
rts
 
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
 
VBDisplayCharRep:
addui r31,r31,#-8
sws c1,[r31]
tst p0,r2 ; check if zero chars requested
p0.eq br .0002
addui r31,r31,#-16
sws c1,zs:[r31]
sws lc,zs:8[r31]
addui r2,r2,#-1
mtspr lc,r2 ; loop count is one less
addui r2,r2,#1 ; leaves r2 unchanged
.0001:
bsr VBDisplayChar
loop .0001
lws lc,zs:8[r31]
lws c1,zs:[r31]
addui r31,r31,#16
.0002:
lws c1,[r31]
addui r31,r31,#8
mov r6,r0
rts
 
;------------------------------------------------------------------------------
; Convert Ascii character to screen character.
;------------------------------------------------------------------------------
 
VBAsciiToScreen:
zxb r1,r1
cmp p0,r1,#' '
p0.le ori r1,r1,#$100
p0.le br .0003
cmp p0,r1,#$5B ; special test for [ ] characters
p0.eq br .0002
cmp p0,r1,#$5D
p0.eq br .0002
ori r1,r1,#$100
biti p0,r1,#$20 ; if bit 5 isn't set
p0.eq br .0003
biti p0,r1,#$40 ; or bit 6 isn't set
p0.ne andi r1,r1,#$19F
.0003:
mov r6,r0
rts
.0002:
andi r1,r1,#~$40
mov r6,r0
rts
 
;------------------------------------------------------------------------------
; Convert screen character to ascii character
;------------------------------------------------------------------------------
;
VBScreenToAscii:
zxb r1,r1
cmpi p0,r1,#$1B
p0.eq br .0004
cmpi p0,r1,#$1D
p0.eq br .0004
cmpi p0,r1,#27
p0.le addui r1,r1,#$60
mov r6,r0
rts
.0004:
ori r1,r1,#$40
mov r6,r0
rts
 
;------------------------------------------------------------------------------
; Display a string on the screen.
; Parameters:
; r1 = linear address pointer to string
;------------------------------------------------------------------------------
 
public VBDisplayString:
addui r31,r31,#-32
sws c1,[r31] ; save return address
sws lc,8[r31] ; save loop counter
sw r2,16[r31]
sws p0,24[r31]
ldis lc,#$FFF ; set max 4k
mov r2,r1
.0001:
lbu r1,zs:[r2]
tst p0,r1
p0.eq br .0002
bsr VBDisplayChar
addui r2,r2,#1
loop .0001
.0002:
lws c1,[r31] ; restore return address
lws lc,8[r31] ; restore loop counter
lw r2,16[r31]
lws p0,24[r31]
addui r31,r31,#32
mov r6,r0
rts
endpublic
 
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
 
VBDispWord:
addui r31,r31,#-8
sws c1,[r31]
roli r1,r1,#32
bsr VBDispHalf
roli r1,r1,#32
bsr VBDispHalf
lws c1,[r31]
addui r31,r31,#8
rts
 
VBDispHalf:
addui r31,r31,#-8
sws c1,[r31]
rori r1,r1,#16
bsr VBDispCharr
roli r1,r1,#16
bsr VBDispCharr
lws c1,[r31]
addui r31,r31,#8
rts
VBDispCharr:
addui r31,r31,#-8
sws c1,[r31]
rori r1,r1,#8
bsr VBDispByte
roli r1,r1,#8
bsr VBDispByte
lws c1,[r31]
addui r31,r31,#8
rts
 
VBDispByte:
addui r31,r31,#-8
sws c1,[r31]
rori r1,r1,#4
bsr VBDispNybble
roli r1,r1,#4
bsr VBDispNybble
lws c1,[r31]
addui r31,r31,#8
rts
 
VBDispNybble:
addui r31,r31,#-16
sws c1,[r31]
sw r1,8[r31]
andi r1,r1,#15
cmpi p0,r1,#10
p0.ge addui r1,r1,#7
ori r1,r1,#'0'
bsr VBDisplayChar
lws c1,[r31]
lw r1,8[r31]
addui r31,r31,#16
mov r6,r0
rts
 
;------------------------------------------------------------------------------
; 'PRTNUM' prints the 64 bit number in r1, leading blanks are added if
; needed to pad the number of spaces to the number in r2.
; However, if the number of digits is larger than the no. in
; r2, all digits are printed anyway. Negative sign is also
; printed and counted in, positive sign is not.
;
; r1 = number to print
; r2 = number of digits
; Register Usage
; r5 = number of padding spaces
;------------------------------------------------------------------------------
PRTNUM:
addui r31,r31,#-48
sws c1,zs:[r31]
sw r3,zs:8[r31]
sw r5,zs:16[r31]
sw r6,zs:24[r31]
sw r7,zs:32[r31]
lw r4,zs:40[r31]
ldi r7,#NUMWKA ; r7 = pointer to numeric work area
mov r6,r1 ; save number for later
mov r5,r2 ; r5 = min number of chars
tst p0,r1 ; is it negative? if not
p0.lt subu r1,r0,r1 ; else make it positive
p0.lt addui r5,r5,#-1 ; one less for width count
PN2:
ldi r3,#10
PN1:
divui r3,r1,#10 ; r3 = r1/10 divide by 10
mului r4,r3,#10
subu r2,r1,r4 ; r2 = r1 mod 10
mov r1,r3 ; r1 = r1 / 10
addui r2,r2,#'0' ; convert remainder to ascii
sb r2,[r7] ; and store in buffer
addui r7,r7,#1
addui r5,r5,#-1 ; decrement width
tst p0,r1
p0.ne br PN1
PN6:
tst p0,r5 ; test pad count, skip padding if not needed
p0.le br PN4
ldi r1,#' '
mov r2,r5
bsr VBDisplayCharRep ; display the required leading spaces
PN4:
tst p0,r6 ; is number negative?
p0.ge br PN5
ldi r1,#'-' ; if so, display the sign
bsr VBDisplayChar
PN5:
subui r7,r7,#1
lb r1,[r7] ; now unstack the digits and display
bsr VBDisplayChar
cmpi p0,r7,#NUMWKA
p0.gt br PN5
PNRET:
lws c1,zs:[r31]
lw r3,zs:8[r31]
lw r5,zs:16[r31]
lw r6,zs:24[r31]
lw r7,zs:32[r31]
lw r4,zs:40[r31]
addui r31,r31,#48
mov r6,r0
rts
 
;------------------------------------------------------------------------------
; Parameters:
; r1 = row
; r2 = col
; Returns:
; r1 = char+attrib
;------------------------------------------------------------------------------
 
VBGetCharAt:
shli r1,r1,#1
lcu r1,cs:LineTbl[r1]
_4addu r1,r2,r1
lhu r3,Vidptr
lhu r1,[r3+r1]
mov r6,r0
rts
 
;------------------------------------------------------------------------------
; Parameters:
; r1 = left
; r2 = top
; r3 = right
; r4 = bottom
;------------------------------------------------------------------------------
 
VBScrollWindowUp:
addui r31,r31,#-96
sw r1,[r31]
sw r2,8[r31]
sw r3,16[r31]
sw r4,24[r31]
sw r5,32[r31]
sw r7,48[r31]
sw r9,56[r31]
sw r10,64[r31]
sw r11,72[r31]
sw r12,80[r31]
sw r13,88[r31]
mov r7,r1 ; r7 = left
mov r6,r2
lhu r11,Vidptr
lcu r13,Textcols ; r13 = # cols
.next:
mulu r9,r2,r13 ; r9 = row offset
_4addu r9,r9,r0 ; r9 *= 4 for half-words
_4addu r9,r1,r9 ; r9 += col * 4
mulu r10,r13,r5 ; r10 = #lines to scroll * #cols
_4addu r10,r10,r9 ; r10 = 4* r10 + r9
lhu r12,[r11+r10] ; r12 = char+atrrib
sh r12,[r11+r9] ; mem = char + attrib
; Now increment the video position
addui r1,r1,#1
cmp p0,r1,r3 ; hit right edge ?
p0.eq mov r1,r7 ; if yes, reset back to left
p0.eq addui r2,r2,#1 ; and increment row
cmp p0,r2,r4 ; hit bottom ?
p0.ne br .next
lw r1,[r31]
lw r2,8[r31]
lw r3,16[r31]
lw r4,24[r31]
lw r5,32[r31]
lw r7,48[r31]
lw r9,56[r31]
lw r10,64[r31]
lw r11,72[r31]
lw r12,80[r31]
lw r13,88[r31]
addui r31,r31,#96
mov r6,r0
rts
 
;------------------------------------------------------------------------------
; Display a character on the screen device
;------------------------------------------------------------------------------
;
public VBDisplayChar:
addui r31,r31,#-56
sws c1,[r31]
sws pregs,8[r31]
sw r1,16[r31]
sw r2,24[r31]
sw r3,32[r31]
sw r4,40[r31]
sws hs,48[r31]
ldis hs,#$FFD00000
zxb r1,r1
lb r2,EscState
tst p0,r2
p0.lt br processEsc
cmpi p0,r1,#_BS
p0.eq br doBackSpace
cmpi p0,r1,#$91 ; cursor right
p0.eq br doCursorRight
cmpi p0,r1,#$93 ; cursor left
p0.eq br doCursorLeft
cmpi p0,r1,#$90 ; cursor up
p0.eq br doCursorUp
cmpi p0,r1,#$92 ; cursor down
p0.eq br doCursorDown
cmpi p0,r1,#$99 ; delete
p0.eq br doDelete
cmpi p0,r1,#CR
p0.eq br doCR
cmpi p0,r1,#LF
p0.eq br doLF
cmpi p0,r1,#$94 ; cursor home
p0.eq br doCursorHome
cmpi p0,r1,#ESC
p0.ne br _0003
ldi r1,#1
sb r1,EscState
exitDC:
lws c1,[r31]
lws pregs,8[r31]
lw r1,16[r31]
lw r2,24[r31]
lw r3,32[r31]
lw r4,40[r31]
lws hs,48[r31]
addui r31,r31,#56
mov r6,r0
rts
_0003:
andi r1,r1,#$7F
bsr VBAsciiToScreen
lhu r2,NormAttr
andi r2,r2,#-1024
or r1,r1,r2
lcu r3,VideoPos
lhu r2,Vidptr
sh r1,hs:[r2+r3*4]
lcu r1,CursorX
addui r1,r1,#1
lcu r2,Textcols
cmp p0,r1,r2
p0.ltu br .0001
sc r0,CursorX
lcu r1,CursorY
addui r1,r1,#1
lcu r2,Textrows
cmp p0,r1,r2
p0.ltu sc r1,CursorY
p0.ltu bsr SyncVideoPos ; wont affect p0
p0.ltu br exitDC
bsr SyncVideoPos
bsr ScrollUp
br exitDC
.0001:
sc r1,CursorX
bsr SyncVideoPos
br exitDC
 
doCR:
sc r0,CursorX
bsr SyncVideoPos
br exitDC
doLF:
lcu r1,CursorY
addui r1,r1,#1
lcu r2,Textrows
cmp p1,r1,r2
p1.ge bsr ScrollUp
p1.ge br exitDC
sc r1,CursorY
bsr SyncVideoPos
br exitDC
 
processEsc:
ldi r4,#22
sc r4,hs:LEDS
lb r2,EscState
cmpi p0,r2,#-1
p0.ne br .0006
cmpi p0,r1,#'T' ; clear to EOL
p0.ne br .0003
lcu r3,VideoPos
lcu r2,CursorX
addui r2,r2,#1
.0001:
lcu r1,Textcols
cmp p0,r2,r1
p0.ge br .0002
ldi r1,#' '
lhu r4,NormAttr
or r1,r1,r4
lhu r4,Vidptr
sh r1,hs:[r4+r3*4]
addui r2,r2,#1
addui r3,r3,#1
br .0001
.0002:
sb r0,EscState
br exitDC
 
.0003:
cmpi p0,r1,#'W'
p0.eq sb r0,EscState
p0.eq br doDelete
cmpi p0,r1,#'`'
p0.eq ldi r1,#-2
p0.eq sb r1,EscState
p0.eq br exitDC
cmp p0,r1,#'('
p0.eq ldi r1,#-3
p0.eq sb r1,EscState
p0.eq br exitDC
.0008:
sb r0,EscState
br exitDC
.0006:
cmpi p0,r2,#-2
p0.ne br .0007
sb r0,EscState
cmpi p0,r1,#'1'
p0.eq bsr CursorOn
p0.eq br exitDC
cmpi p0,r1,#'0'
p0.eq bsr CursorOff
br exitDC
.0007:
cmpi p0,r2,#-3
p0.ne br .0009
cmpi p0,r1,#ESC
p0.ne br .0008
ldi r1,#-4
sb r1,EscState
br exitDC
.0009:
cmpi p0,r2,#-4
p0.ne br .0010
cmpi p0,r1,#'G'
p0.ne br .0008
ldi r1,#-5
sb r1,EscState
br exitDC
.0010:
cmpi p0,r2,#-5
p0.ne br .0008
sb r0,EscState
cmpi p0,r1,#'4'
p0.ne br .0011
lhu r1,NormAttr
mov r2,r1
shli r1,r1,#9
andi r1,r1,#%111111111_000000000_00_00000000
shrui r2,r2,#9
andi r2,r2,#%000000000_111111111_00_00000000
or r1,r1,r2
sh r1,NormAttr
br exitDC
.0011:
cmpi p0,r1,#'0'
p0.ne br .0012
; Light grey on dark grey
ldi r1,#%001001001_011011011_00_00000000
sh r1,NormAttr
br exitDC
.0012:
; Light grey on dark grey
ldi r1,#%001001001_011011011_00_00000000
sh r1,NormAttr
br exitDC
 
doBackSpace:
ldi r4,#23
sc r4,hs:LEDS
lc r2,CursorX
tst p0,r2
p0.eq br exitDC ; Can't backspace anymore
lcu r3,VideoPos
.0002:
lh r4,Vidptr
lh r1,hs:[r4+r3*4]
addui r3,r3,#-1
sh r1,hs:[r4+r3*4]
addui r3,r3,#2
lc r4,Textcols
addui r2,r2,#1
cmp p0,r2,r4
p0.ne br .0002
.0003:
ldi r1,#' '
lh r4,NormAttr
or r1,r1,r4
lh r4,Vidptr
sh r1,hs:[r4+r3*4]
inc CursorX,#-1
bsr SyncVideoPos
br exitDC
 
; Deleting a character does not change the video position so there's no need
; to resynchronize it.
 
doDelete:
lc r2,CursorX
lh r3,VideoPos
.0002:
addui r2,r2,#1
lc r4,Textcols
cmp p0,r2,r4
p0.ge br .0001
addui r2,r2,#-1
addui r3,r3,#1
lh r4,Vidptr
lh r1,hs:[r4+r3*4]
addui r3,r3,#-1
sh r1,hs:[r4+r3*4]
addui r3,r3,#1
addui r2,r2,#1
br .0002
.0001:
ldi r1,#' '
lhu r2,NormAttr
or r1,r1,r2
lhu r4,Vidptr
sh r1,hs:[r4+r3*4]
br exitDC
 
doCursorHome:
lcu r1,CursorX
tst p0,r1
p0.eq br doCursor1
sc r0,CursorX
bsr SyncVideoPos
br exitDC
doCursorRight:
lcu r1,CursorX
addui r1,r1,#1
lcu r2,Textcols
cmp p0,r1,r2
p0.ge br exitDC
doCursor2:
sc r1,CursorX
bsr SyncVideoPos
br exitDC
doCursorLeft:
lcu r1,CursorX
tst p0,r1
p0.eq br exitDC
addui r1,r1,#-1
br doCursor2
doCursorUp:
lcu r1,CursorY
tst p0,r1
p0.eq br exitDC
addui r1,r1,#-1
br doCursor1
doCursorDown:
lcu r1,CursorY
addui r1,r1,#1
lcu r2,Textrows
cmp p0,r1,r2
p0.ge br exitDC
doCursor1:
sc r1,CursorY
bsr SyncVideoPos
br exitDC
 
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
 
public VideoInit:
ldi r1,#84
sc r1,Textcols
ldi r1,#31
sc r1,Textrows
ldi r1,#%011000000_111111111_00_00000000
sh r1,NormAttr
ldi r1,#TEXTREG
sh r1,Vidregs
ldi r1,#TEXTSCR
sh r1,Vidptr
 
ldi r2,#TC1InitData
ldis lc,#11 ; initialize loop counter ( one less)
lhu r3,Vidregs
.0001:
lvh r1,cs:[r2]
sh r1,hs:[r3]
addui r2,r2,#4
addui r3,r3,#4
loop .0001
mov r6,r0
rts
endpublic
 
;------------------------------------------------------------------------------
; Initialize the second video controller.
; Meant to be called with a different data segment.
;------------------------------------------------------------------------------
 
public VideoInit2:
ldi r1,#84
sc r1,Textcols
ldi r1,#31
sc r1,Textrows
ldi r1,#%000011000_111111111_00_00000000
sh r1,NormAttr
ldi r1,#TEXTREG2
sh r1,Vidregs
ldi r1,#TEXTSCR2
sh r1,Vidptr
 
ldi r2,#TC2InitData
ldis lc,#11 ; initialize loop counter ( one less)
lhu r3,Vidregs
.0001:
lvh r1,cs:[r2]
sh r1,hs:[r3]
addui r2,r2,#4
addui r3,r3,#4
loop .0001
mov r6,r0
rts
endpublic
 
;------------------------------------------------------------------------------
; Text controller initialization data.
;------------------------------------------------------------------------------
align 4
 
TC1InitData:
dc 84 ; #columns
dc 3 ; #char out delay
dc 31 ; #rows
dc 0
dc 84 ; window left
dc 0
dc 17 ; window top
dc 0
dc 7 ; max scan line
dc 0
dc $21 ; pixel size (hhhhvvvv)
dc 0
dc 0 ; not used
dc 0
dc $1FF ; transparent color
dc 0
dc $40 ; cursor blink, start line
dc 0
dc 31 ; cursor end
dc 0
dc 0 ; start address
dc 0
dc 0 ; cursor position
dc 0
 
align 4
TC2InitData:
dc 84
dc 3
dc 31
dc 0
dc 676
dc 0
dc 64 ; window top
dc 0
dc 7
dc 0
dc $10
dc 0
dc 0
dc 0
dc $1FF
dc 0
dc $40
dc 0
dc 31
dc 0
dc 0
dc 0
dc 0
dc 0
 
;------------------------------------------------------------------------------
; Screen line offset table.
;------------------------------------------------------------------------------
 
align 2
LineTbl:
dc 0
dc TEXTCOLS*4
dc TEXTCOLS*8
dc TEXTCOLS*12
dc TEXTCOLS*16
dc TEXTCOLS*20
dc TEXTCOLS*24
dc TEXTCOLS*28
dc TEXTCOLS*32
dc TEXTCOLS*36
dc TEXTCOLS*40
dc TEXTCOLS*44
dc TEXTCOLS*48
dc TEXTCOLS*52
dc TEXTCOLS*56
dc TEXTCOLS*60
dc TEXTCOLS*64
dc TEXTCOLS*68
dc TEXTCOLS*72
dc TEXTCOLS*76
dc TEXTCOLS*80
dc TEXTCOLS*84
dc TEXTCOLS*88
dc TEXTCOLS*92
dc TEXTCOLS*96
dc TEXTCOLS*100
dc TEXTCOLS*104
dc TEXTCOLS*108
dc TEXTCOLS*112
dc TEXTCOLS*116
dc TEXTCOLS*120
dc TEXTCOLS*124
 
/trunk/software/boot_tb/Serial.asm
0,0 → 1,370
UART EQU 0xC0A00
UART_TX EQU 0xC0A00
UART_RX EQU 0xC0A00
UART_LS EQU 0xC0A01
UART_MS EQU 0xC0A02
UART_IS EQU 0xC0A03
UART_IE EQU 0xC0A04
UART_FF EQU 0xC0A05
UART_MC EQU 0xC0A06
UART_CTRL EQU 0xC0A07
UART_CM0 EQU 0xC0A08
UART_CM1 EQU 0xC0A09
UART_CM2 EQU 0xC0A0A
UART_CM3 EQU 0xC0A0B
UART_SPR EQU 0xC0A0F
 
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
 
;==============================================================================
; Serial port
;==============================================================================
code
;------------------------------------------------------------------------------
; Initialize UART
;------------------------------------------------------------------------------
 
align 8
ser_jmp:
jmp SerialIRQ[c0]
 
SerialInit:
addui sp,sp,#-8
sws c1,[sp]
ldis hs,#$FFD00000
ldis hs.lmt,#$100000
; ldi r1,#$0218DEF4 ; constant for clock multiplier with 18.75MHz clock for 9600 baud
; ldi r1,#$03254E6E ; constant for clock multiplier with 12.5MHz clock for 9600 baud
ldi r1,#$00C9539B ; constant for clock multiplier with 50.0MHz clock for 9600 baud
shrui r1,r1,#8 ; drop the LSB (not used)
sb r1,hs:UART_CM1
shrui r1,r1,#8
sb r1,hs:UART_CM2
shrui r1,r1,#8
sb r1,hs:UART_CM3
sb r0,hs:UART_CTRL ; no hardware flow control
sc r0,Uart_rxhead ; reset buffer indexes
sc r0,Uart_rxtail
ldi r1,#0x1f0
sc r1,Uart_foff ; set threshold for XOFF
ldi r1,#0x010
sc r1,Uart_fon ; set threshold for XON
ldi r1,#1
sb r1,hs:UART_IE ; enable receive interrupt only
sb r0,Uart_rxrts ; no RTS/CTS signals available
sb r0,Uart_txrts ; no RTS/CTS signals available
sb r0,Uart_txdtr ; no DTR signals available
sb r0,Uart_rxdtr ; no DTR signals available
ldi r1,#1
sb r1,Uart_txxon ; for now
ldi r1,#1
; sb r1,SERIAL_SEMA
; setup IRQ vector
lla r1,cs:ser_jmp
ldi r2,#199
bsr set_vector
lws c1,[sp]
addui sp,sp,#8
rts
 
;---------------------------------------------------------------------------------
; Get character directly from serial port. Blocks until a character is available.
;---------------------------------------------------------------------------------
;
SerialGetCharDirect:
sgc1:
lvb r1,hs:UART_LS ; uart status
biti p0,r1,#1 ; is there a char available ?
p0.eq br sgc1
lvb r1,hs:UART_RX
rts
 
;------------------------------------------------
; Check for a character at the serial port
; returns r1 = 1 if char available, 0 otherwise
;------------------------------------------------
;
SerialCheckForCharDirect:
lvb r1,hs:UART_LS ; uart status
andi r1,r1,#rxfull ; is there a char available ?
rts
 
;-----------------------------------------
; Put character to serial port
; r1 = char to put
;-----------------------------------------
;
SerialPutChar:
addui sp,sp,#-48
sw r2,[sp]
sw r3,8[sp]
sw r4,16[sp]
sw r5,24[sp]
sws p0,32[sp]
sws lc,40[sp]
lvb r2,hs:UART_MC
ori r2,r2,#3 ; assert DTR / RTS
sb r2,hs:UART_MC
lb r2,Uart_txrts
tst p0,r2
p0.eq br spcb1
lw r4,Milliseconds
ldis lc,#999 ; delay count (1 s)
spcb3:
lvb r2,hs:UART_MS
biti p0,r2,#$10 ; is CTS asserted ?
p0.ne br spcb1
lw r5,Milliseconds
cmp p0,r4,r5
p0.eq br spcb3
mov r4,r5
loop spcb3
br spcabort
spcb1:
lb r2,Uart_txdtr
tst p0,r2
p0.eq br spcb2
lw r4,Milliseconds
ldis lc,#999 ; delay count
spcb4:
lvb r2,hs:UART_MS
biti p0,r2,#$20 ; is DSR asserted ?
p0.ne br spcb2
lw r5,Milliseconds
cmp p0,r4,r5
p0.eq br spcb4
mov r4,r5
loop spcb4
br spcabort
spcb2:
lb r2,Uart_txxon
tst p0,r2
p0.eq br spcb5
spcb6:
lb r2,Uart_txxonoff
tst p0,r2
p0.eq br spcb5
lvb r4,hs:UART_MS
biti p0,r4,#0x80 ; DCD ?
p0.ne br spcb6
spcb5:
lw r4,Milliseconds
ldis lc,#999 ; wait up to 1s
spcb8:
lvb r2,hs:UART_LS
biti p0,r2,#0x20 ; tx not full ?
p0.ne br spcb7
lw r5,Milliseconds
cmp p0,r4,r5
p0.eq br spcb8
mov r4,r5
loop spcb8
br spcabort
spcb7:
sb r1,hs:UART_TX
spcabort:
lw r2,[sp]
lw r3,8[sp]
lw r4,16[sp]
lw r5,24[sp]
lws p0,32[sp]
lws lc,40[sp]
addui sp,sp,#40
rts
 
;-------------------------------------------------
; Compute number of characters in recieve buffer.
; r4 = number of chars
;-------------------------------------------------
CharsInRxBuf:
lcu r4,Uart_rxhead
lcu r3,Uart_rxtail
subu r4,r4,r3
tst p0,r4
p0.gt br cirxb1
ldi r4,#0x200
addu r4,r4,r3
lcu r3,Uart_rxhead
subu r4,r4,r3
cirxb1:
rts
 
;----------------------------------------------
; Get character from rx fifo
; If the fifo is empty enough then send an XON
;----------------------------------------------
;
SerialGetChar:
addui sp,sp,#-40
sw r2,[sp]
sw r3,8[sp]
sw r4,16[sp]
sw r5,24[sp]
sws c1,32[sp]
lcu r3,Uart_rxhead
lcu r2,Uart_rxtail
cmp p0,r2,r3
p0.eq br sgcfifo1 ; is there a char available ?
lbu r1,Uart_rxfifo[r2] ; get the char from the fifo into r1
addui r2,r2,#1 ; increment the fifo pointer
andi r2,r2,#$1ff
sc r2,Uart_rxtail
lb r2,Uart_rxflow ; using flow control ?
tst p0,r2
p0.eq br sgcfifo2
lcu r3,Uart_fon ; enough space in Rx buffer ?
bsr CharsInRxBuf
cmp p0,r4,r3
p0.gt br sgcfifo2
sb r0,Uart_rxflow ; flow off
lb r4,Uart_rxrts
tst p0,r4
p0.eq br sgcfifo3
lb r4,hs:UART_MC ; set rts bit in MC
ori r4,r4,#2
sb r4,hs:UART_MC
sgcfifo3:
lb r4,Uart_rxdtr
tst p0,r4
p0.eq br sgcfifo4
lb r4,hs:UART_MC ; set DTR
ori r4,r4,#1
sb r4,hs:UART_MC
sgcfifo4:
lb r4,Uart_rxxon
tst p0,r4
p0.eq br sgcfifo5
ldi r4,#XON
sb r4,hs:UART
sgcfifo5:
sgcfifo2: ; return with char in r1
lw r2,[sp]
lw r3,8[sp]
lw r4,16[sp]
lw r5,24[sp]
lws c1,32[sp]
addui sp,sp,#40
rts
sgcfifo1:
ldi r1,#-1 ; no char available
lw r2,[sp]
lw r3,8[sp]
lw r4,16[sp]
lw r5,24[sp]
lws c1,32[sp]
addui sp,sp,#40
rts
 
 
;-----------------------------------------
; Serial port IRQ
;-----------------------------------------
;
SerialIRQ:
sync
addui r31,r31,#-64
sw r1,[r31]
sw r2,8[r31]
sw r4,16[r31]
sws p0,24[r31]
sw r3,32[r31]
sws c1,40[r31]
sws hs,48[r31]
sws hs.lmt,56[r31]
ldis hs,#$FFD00000
ldis hs.lmt,#$100000
 
lb r1,hs:UART_IS ; get interrupt status
tst p0,r1
p0.gt br sirq1 ; no interrupt
andi r1,r1,#0x7f ; switch on interrupt type
biti p0,r1,#4
p0.ne br srxirq
biti p0,r1,#$0C
p0.ne br stxirq
biti p0,r1,#$10
p0.ne br smsirq
; unknown IRQ type
sirq1:
lw r1,[r31]
lw r2,8[r31]
lw r4,16[r31]
lws p0,24[r31]
lw r3,32[r31]
lws c1,40[r31]
lws hs,48[r31]
lws hs.lmt,56[r31]
addui r31,r31,#64
sync
rti
 
; Get the modem status and record it
smsirq:
lbu r1,hs:UART_MS
sb r1,Uart_ms
br sirq1
 
stxirq:
br sirq1
 
; Get a character from the uart and store it in the rx fifo
srxirq:
srxirq1:
lbu r1,hs:UART_RX ; get the char (clears interrupt)
lbu r3,Uart_txxon
tst p0,r3
p0.eq br srxirq3
cmpi p0,r1,#XOFF
p0.ne br srxirq2
ldi r1,#1
sb r1,Uart_txxonoff
br srxirq5
srxirq2:
cmpi p0,r1,#XON
p0.ne br srxirq3
sb r0,Uart_txxonoff
br srxirq5
srxirq3:
sb r0,Uart_txxonoff
lcu r4,Uart_rxhead
sb r1,Uart_rxfifo[r4] ; store in buffer
addui r4,r4,#1
andi r4,r4,#$1ff
sc r4,Uart_rxhead
srxirq5:
lb r1,hs:UART_LS ; check for another ready character
biti p0,r1,#1 ; check rxfull bit
p0.ne br srxirq1 ; loop back for another character
lb r1,Uart_rxflow ; are we using flow controls?
tst p0,r1
p0.ne br srxirq8
bsr CharsInRxBuf
lb r1,Uart_foff
cmp p0,r4,r1
p0.lt br srxirq8
ldi r1,#1
sb r1,Uart_rxflow
lb r1,Uart_rxrts
tst p0,r1
p0.eq br srxirq6
lb r1,hs:UART_MC
andi r1,r1,#$FD ; turn off RTS
sb r1,hs:UART_MC
srxirq6:
lb r1,Uart_rxdtr
tst p0,r1
 
p0.eq br srxirq7
lb r1,hs:UART_MC
andi r1,r1,#$FE ; turn off DTR
sb r1,hs:UART_MC
srxirq7:
lb r1,Uart_rxxon
tst p0,r1
p0.eq br srxirq8
ldi r1,#XOFF
sb r1,hs:UART_TX
srxirq8:
br sirq1
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.