URL
https://opencores.org/ocsvn/thor/thor/trunk
Subversion Repositories thor
Compare Revisions
- This comparison shows the changes necessary to convert path
/thor/trunk
- from Rev 23 to Rev 24
- ↔ Reverse comparison
Rev 23 → Rev 24
/software/source/keybd2.asm
0,0 → 1,17
public KeybdGetStatus_: |
lvb r1,zs:$FFDC0001 |
rts |
endpublic |
|
public KeybdClearRcv_: |
sb r0,zs:$FFDC0001 |
rts |
endpublic |
|
public KeybdGetScancode_: |
memdb |
lvb r1,zs:$FFDC0000 |
zxb r1,r1 |
rts |
endpublic |
|
/software/source/keyboard.asm
0,0 → 1,461
|
; ============================================================================ |
; __ |
; \\__/ 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,#194 |
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 |
/software/source/call.bat
0,0 → 1,29
rem This batch file compiles everything then assembles it into an image suitable to be used as |
rem initialization data for system ROM. The final output product is a file called "boot.ve0" |
rem |
set path=$PATH;..\c64\bin\;..\a64\bin\ |
set INCLUDE=c:\Cores4\Thor\trunk\software\source\;c:\Cores4\Thor\trunk\software\FMTK\source\kernel\ |
c64 -pThor32 -w -S ..\FMTK\source\kernel\FMTKc.c |
c64 -pThor32 -w ..\FMTK\source\kernel\FMTKmsg.c |
c64 -pThor32 -w ..\FMTK\source\kernel\TCB.c |
c64 -pThor32 -w ..\FMTK\source\kernel\IOFocusc.c |
c64 -pThor32 -w ..\FMTK\source\kernel\console.c |
c64 -pThor32 -w ..\FMTK\source\kernel\keybd.c |
c64 -pThor32 -w ..\FMTK\source\kernel\PIC.c |
c64 -pThor32 -w ..\FMTK\source\kernel\LockSemaphore.c |
c64 -pThor32 -w ..\FMTK\source\kernel\UnlockSemaphore.c |
c64 -pThor32 -w ..\FMTK\source\shell.c |
c64 -pThor32 -w ..\FMTK\source\memmgnt.c |
c64 -pThor32 -w ..\c64libc\source\stdio.c |
c64 -pThor32 -w ..\c64libc\source\ctype.c |
c64 -pThor32 -w ..\c64libc\source\string.c |
c64 -pThor32 -w ..\c64libc\source\prtdbl.c |
c64 -pThor32 -w ..\c64libc\source\gfx.c |
c64 -pThor32 -w ..\c64libc\source\Thor\getCPU.c |
c64 -pThor32 -w ..\c64libc\source\Thor\outb.c |
c64 -pThor32 -w ..\c64libc\source\Thor\outc.c |
c64 -pThor32 -w ..\c64libc\source\Thor\outh.c |
c64 -pThor32 -w ..\c64libc\source\Thor\outw.c |
c64 -pThor32 -w debugger.c disassem.c set_time_serial.c highest_data_word.c |
c64 -pThor32 -w sd_controller.c sdc_test.c |
a64 +gT boot.asm |
/software/source/boot.asm
0,0 → 1,996
|
; ============================================================================ |
; __ |
; \\__/ 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/>. |
; |
; ============================================================================ |
; |
.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 |
CTRLH EQU 0x08 |
CTRLI EQU 0x09 |
CTRLJ EQU 0x0A |
CTRLK EQU 0x0B |
CTRLM EQU 0x0D |
CTRLS EQU 0x13 |
CTRLX EQU 0x18 |
XON EQU 0x11 |
XOFF EQU 0x13 |
ESC EQU 0x1B |
|
SC_TAB EQU $0D |
SC_LSHIFT EQU $12 |
SC_RSHIFT EQU $59 |
SC_KEYUP EQU $F0 |
SC_EXTEND EQU $E0 |
SC_CTRL EQU $14 |
SC_ALT EQU $11 |
SC_DEL EQU $71 ; extend |
SC_LCTRL EQU $58 |
SC_NUMLOCK EQU $77 |
SC_SCROLLLOCK EQU $7E |
SC_CAPSLOCK EQU $58 |
|
E_BadFuncno EQU 1 |
BIOS_E_Timeout EQU 2 |
E_Unsupported EQU 3 |
|
BIOS_STACKTOP EQU $3bf8 |
INT_STACK EQU $37f8 |
VIDEO_BIOS_STACKTOP EQU $3ff8 |
|
IOBASE_ADDR EQU 0xFFD00000 |
IOLMT EQU 0x100000 |
LEDS EQU 0xC0600 |
TEXTSCR EQU 0x00000 |
TEXTSCR2 EQU 0x10000 |
TEXTREG EQU 0xA0000 |
TEXTREG2 EQU 0xA0040 |
TEXT_COLS EQU 0x0 |
TEXT_ROWS EQU 0x2 |
TEXT_CURPOS EQU 0x16 |
KEYBD EQU 0xC0000 |
|
PIC_IS EQU 0xC0FC0 |
PIC_IE EQU 0xC0FC8 |
PIC_ES EQU 0xC0FE0 |
PIC_ESR EQU 0xC0FE8 ; edge sense reset |
|
bss |
org $C00000 |
dw 0 ; the first word is unused |
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 |
align 4 |
NormAttr dh 0 |
Vidregs dh 0 |
Vidptr dh 0 |
EscState dc 0 |
Textrows dc 0 |
Textcols dc 0 |
align 8 |
reg_save fill.w 64,0 |
creg_save fill.w 16,0 |
sreg_save fill.w 16,0 |
preg_save dw 0 |
|
|
rxfull EQU 1 |
Uart_ms db 0 |
Uart_txxonoff db 0 |
Uart_rxhead dc 0 |
Uart_rxtail dc 0 |
Uart_rxflow db 0 |
Uart_rxrts db 0 |
Uart_rxdtr db 0 |
Uart_rxxon db 0 |
Uart_foff dc 0 |
Uart_fon dc 0 |
Uart_txrts db 0 |
Uart_txdtr db 0 |
Uart_txxon db 0 |
Uart_rxfifo fill.b 512,0 |
|
NUMWKA fill.b 64,0 |
|
code 17 bits |
org $FFFC0000 |
|
;------------------------------------------------------------------------------ |
; Reset Point |
;------------------------------------------------------------------------------ |
|
cold_start: |
; Initialize segment registers for flat model |
mtspr zs,r0 |
ldis zs.lmt,#-1 |
mtspr ds,r0 |
ldis ds.lmt,#-1 |
mtspr es,r0 |
ldis es.lmt,#-1 |
mtspr fs,r0 |
ldis fs.lmt,#-1 |
mtspr gs,r0 |
ldis gs.lmt,#-1 |
ldis hs,#IOBASE_ADDR |
ldis hs.lmt,#IOLMT |
|
; set SS:SP |
ldi r31,#$03ef8 ; initialize kernel SP |
ldi sp,#sys_stacks_+511*8 |
mtspr ss,r0 |
ldis ss.lmt,#-1 |
|
; switch processor to full speed |
stp #$FFFF |
|
; set interrupt table at $1000 |
ldis c12,#$1000 |
|
; set all vectors to the uninitialized interrupt vector |
mov r4,r0 |
ldis lc,#255 ; 256 vectors to set |
su1: |
ldi r1,#uii_jmp |
mov r2,r4 |
bsr set_vector ; trashes r2,r3 |
addui r4,r4,#1 |
loop su1 |
|
; setup break vector |
lla r1,cs:brk_jmp |
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 |
bsr set_vector |
|
; setup NMI vector |
lla r1,cs:nmi_jmp |
ldi r2,#254 |
bsr set_vector |
|
lla r1,cs:svc_jmp |
ldi r2,#190 |
bsr set_vector |
lla r1,cs:rsc_jmp |
ldi r2,#191 |
bsr set_vector |
|
; spurious interrupt |
; |
lla r1,cs:spur_jmp |
ldi r2,#192 |
bsr set_vector |
|
; setup MSI vector |
sh r0,Milliseconds |
lla r1,cs:msi_jmp |
ldi r2,#193 |
bsr set_vector |
|
; setup BTNU vector |
lla r1,cs:btnu_jmp |
ldi r2,#200 |
bsr set_vector |
|
; setup KM vector |
lla r1,cs:km_jmp |
ldi r2,#245 |
bsr set_vector |
|
; setup data bus error vector |
lla r1,cs:dbe_jmp |
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 ; nmi, time slice interrupt is edge sensitive |
sh r1,hs:PIC_ES |
ldi r1,#%000000111 ; enable time slice interrupt, msi, nmi |
sh r1,hs:PIC_IE |
|
; Initialize random number generator |
; m_z and m_w must not be zero |
ldi r1,#$88888888 |
sh r1,m_w |
ldi r1,#$77777777 |
sh r1,m_z |
|
mov r1,r0 |
mov r2,r0 |
mov r3,r0 |
mov r4,r0 |
mov r5,r0 |
|
ldi r1,#1 |
sc r1,hs:LEDS |
|
tlbwrreg DMA,r0 ; clear TLB miss registers |
tlbwrreg IMA,r0 |
ldi r1,#2 ; 2 wired registers |
tlbwrreg Wired,r1 |
ldi r1,#$2 ; 64kiB page size |
tlbwrreg PageSize,r1 |
|
; setup the first translation |
; virtual page $FFFF0000 maps to physical page $FFFF0000 |
; This places the BIOS ROM at $FFFFxxxx in the memory map |
ldi r1,#$80000101 ; ASID=zero, G=1,valid=1 |
tlbwrreg ASID,r1 |
ldi r1,#$0FFFF |
tlbwrreg VirtPage,r1 |
tlbwrreg PhysPage,r1 |
tlbwrreg Index,r0 ; select way #0 |
tlbwi ; write to TLB entry group #0 with hold registers |
|
; setup second translation |
; virtual page 0 maps to physical page 0 |
ldi r1,#$80000101 ; ASID=zero, G=1,valid=1 |
tlbwrreg ASID,r1 |
tlbwrreg VirtPage,r0 |
tlbwrreg PhysPage,r0 |
ldi r1,#8 ; select way#1 |
tlbwrreg Index,r1 |
tlbwi ; write to TLB entry group #0 with hold registers |
|
; turn on the TLB |
; tlben |
|
; enable maskable interrupts |
; Interrupts also are not enabled until an RTI instruction is executed. |
; there will likely be a timer interrupt outstanding so this |
; should go to the timer IRQ. |
cli |
|
; now globally enable interrupts using the RTI instruction, this will also |
; switch to core to application/user mode. |
ldis c14,#j1 ; c14 contains RTI return address |
sync |
rti |
j1: |
ldi r1,#2 |
sc r1,hs:LEDS |
sb r0,EscState |
bsr SerialInit |
; bsr Debugger |
ldi r2,#msgStartup |
ldis lc,#msgStartupEnd-msgStartup-1 |
j3: |
; lbu r1,[r2] |
; addui r2,r2,#1 |
; tst p0,r1 |
;p0.eq br j2 |
; bsr SerialPutChar |
; loop j3 |
j2: |
bsr VideoInit |
bsr VBClearScreen |
; bsr VBClearScreen2 |
ldi r1,#3 |
sc r1,hs:LEDS |
mov r1,r0 |
mov r2,r0 |
ldi r6,#2 ; Set Cursor Pos |
sys #10 |
ldi r1,#6 |
sc r1,hs:LEDS |
bsr alphabet |
lla r1,cs:msgStartup ; convert to linear address |
ldi r6,#$14 |
sys #10 |
|
;------------------------------------------------------------------------------ |
;------------------------------------------------------------------------------ |
; Monitor |
;------------------------------------------------------------------------------ |
;------------------------------------------------------------------------------ |
|
Monitor: |
lla r1,cs:msgMonitor |
bsr VBDisplayString |
|
; Display monitor prompt |
.prompt: |
ldi r1,#CR |
bsr VBDisplayChar |
ldi r1,#LF |
bsr VBDisplayChar |
ldi r1,#'$' |
bsr VBDisplayChar |
bsr CursorOn |
.getkey: |
bsr KeybdGetCharWait |
bsr VBDisplayChar |
cmpi p0,r1,#CR |
p0.ne br .getkey |
bsr CursorOff |
lcu r1,CursorY |
lcu r7,Textcols |
mtspr lc,r7 ; use loop counter as safety |
mulu r10,r1,r7 ; pos = row * cols |
_4addu r10,r10,r0 ; pos *= 4 |
.0001: |
bsr MonGetch1 ; get character skipping spaces |
cmpi p0,r1,#'$' ; skip over prompt |
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 |
p0.eq mov r2,r0 |
p0.eq ldi r6,#2 |
p0.eq sys #10 |
br .prompt |
|
;------------------------------------------------------------------------------ |
; Returns: |
; r1 ascii code for character |
; r10 incremented |
; lc decremented |
;------------------------------------------------------------------------------ |
|
MonGetch: |
addui r31,r31,#-8 |
sws c1,[r31] |
lhu r1,hs:[r10] |
andi r1,r1,#$3ff |
bsr VBScreenToAscii |
addui r10,r10,#4 |
loop .0001 ; decrement loop counter |
.0001: |
lws c1,[r31] |
addui r31,r31,#8 |
rts |
|
;------------------------------------------------------------------------------ |
; Returns: |
; r1 ascii code for character |
; r10 incremented by number of spaces + 1 |
; lc decremented by number of spaces + 1 |
;------------------------------------------------------------------------------ |
|
MonGetch1: |
addui r31,r31,#-8 |
sws c1,[r31] |
.0001: |
lhu r1,hs:[r10] |
andi r1,r1,#$3ff |
bsr VBScreenToAscii |
addui r10,r10,#4 |
cmpi p0,r1,#' ' |
p0.leu loop .0001 |
lws c1,[r31] |
addui r31,r31,#8 |
rts |
|
;------------------------------------------------------------------------------ |
; Go into graphics mode, four lines of text at bottom. |
;------------------------------------------------------------------------------ |
|
GoGraphics: |
lhu r3,Vidregs |
ldi r1,#4 |
sc r1,Textrows |
sh r1,hs:4[r3] ; # rows |
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 |
sc r1,Textrows |
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 |
|
// ---------------------------------------------------------------------------- |
// Uses George Marsaglia's multiply method |
// |
// m_w = <choose-initializer>; /* must not be zero */ |
// m_z = <choose-initializer>; /* must not be zero */ |
// |
// uint get_random() |
// { |
// m_z = 36969 * (m_z & 65535) + (m_z >> 16); |
// m_w = 18000 * (m_w & 65535) + (m_w >> 16); |
// return (m_z << 16) + m_w; /* 32-bit result */ |
// } |
// ---------------------------------------------------------------------------- |
// |
gen_rand: |
addui r31,r31,#-8 |
sw r2,[r31] |
lhu r1,m_z |
mului r2,r1,#36969 |
shrui r1,r1,#16 |
addu r2,r2,r1 |
sh r2,m_z |
|
lhu r1,m_w |
mului r2,r1,#18000 |
shrui r1,r1,#16 |
addu r2,r2,r1 |
sh r2,m_w |
rand: |
lhu r1,m_z |
shli r1,r1,#16 |
addu r1,r1,r2 |
lw r2,[r31] |
addui r31,r31,#8 |
rts |
|
// ---------------------------------------------------------------------------- |
// Display random dots on the graphics screen. |
// ---------------------------------------------------------------------------- |
|
RandomDots: |
addui r31,r31,#-8 |
sws c1,[r31] ; stack the return address |
mov r4,r0 |
.0001: |
bsr gen_rand ; get random bitmap memory location |
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:[r2] ; store color in memory |
addui r4,r4,#1 ; increment loop index |
andi r4,r4,#$FFF ; |
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 |
|
;------------------------------------------------------------------------------ |
|
msgStartup: |
byte "Thor Test System Starting...",CR,LF,0 |
msgStartupEnd: |
msgMonitor: |
byte CR,LF |
byte "d - run debugger",CR,LF |
byte "g - graphics mode",CR,LF |
byte "tx - text mode",CR,LF |
byte "r - random dots",CR,LF |
byte 0 |
|
bad_ram: |
ldi r1,#'B' |
bsr VBAsciiToScreen |
ori r1,r1,#%011000000_111111111_00_00000000 |
sh r1,hs:TEXTSCR+16 |
.bram1: br .bram1 |
|
;------------------------------------------------------------------------------ |
; alphabet: |
; |
; Display the alphabet across the top of the screen. |
;------------------------------------------------------------------------------ |
|
alphabet: |
addui sp,sp,#-8 |
sws c1,[sp] ; store off return address |
ldi r5,#'A' ; the first char |
ldi r3,#TEXTSCR ; screen address |
ldis lc,#25 ; 25 chars |
.0001: |
mov r1,r5 ; r1 = ascii letter |
bsr VBAsciiToScreen ; r1 = screen char |
lhu r2,NormAttr ; r2 = attribute |
or r1,r1,r2 ; r1 = screen char + attribute |
sh r1,hs:[r3] ; store r1 to screen |
addui r5,r5,#1 ; increment to next char |
addui r3,r3,#4 ; increment to next screen loc |
loop .0001 ; loop back |
lws c1,[sp] ; restore return address |
addui sp,sp,#8 |
rts |
|
;------------------------------------------------------------------------------ |
; Set interrupt vector |
; |
; Parameters: |
; r1 = linear address of jump code |
; r2 = vector number to set |
; Trashes: r2,r3,r5,p0 |
;------------------------------------------------------------------------------ |
|
set_vector: |
mfspr r3,c12 ; get base address of interrupt table |
_16addu r2,r2,r3 |
lh r3,zs:[r1] |
cmpi p0,r3,#$003F6F01 ; unitialized interrupt number load |
p0.eq shli r5,r2,#18 |
p0.eq or r3,r3,r5 |
sh r3,zs:[r2] |
lh r3,zs:4[r1] |
sh r3,zs:4[r2] |
lh r3,zs:8[r1] |
sh r3,zs:8[r2] |
lh r3,zs:12[r1] |
sh r3,zs:12[r2] |
rts |
|
.include "c:\cores4\thor\trunk\software\FMTK\source\kernel\FMTKc.s" |
.include "c:\cores4\thor\trunk\software\FMTK\source\kernel\FMTKmsg.s" |
.include "c:\cores4\thor\trunk\software\FMTK\source\kernel\TCB.s" |
.include "c:\cores4\thor\trunk\software\FMTK\source\kernel\IOFocusc.s" |
.include "c:\cores4\thor\trunk\software\FMTK\source\kernel\console.s" |
.include "c:\cores4\thor\trunk\software\FMTK\source\kernel\keybd.s" |
.include "c:\cores4\thor\trunk\software\FMTK\source\kernel\PIC.s" |
.include "c:\cores4\thor\trunk\software\FMTK\source\kernel\LockSemaphore.s" |
.include "c:\cores4\thor\trunk\software\FMTK\source\kernel\UnlockSemaphore.s" |
.include "c:\cores4\thor\trunk\software\FMTK\source\shell.s" |
.include "c:\cores4\thor\trunk\software\FMTK\source\memmgnt.s" |
.include "c:\cores4\thor\trunk\software\c64libc\source\stdio.s" |
.include "c:\cores4\thor\trunk\software\c64libc\source\ctype.s" |
.include "c:\cores4\thor\trunk\software\c64libc\source\string.s" |
;.include "c:\cores4\thor\trunk\software\c64libc\source\prtdbl.s" |
.include "c:\cores4\thor\trunk\software\c64libc\source\Thor\getCPU.s" |
.include "c:\cores4\thor\trunk\software\c64libc\source\Thor\outb.s" |
.include "c:\cores4\thor\trunk\software\c64libc\source\Thor\outc.s" |
.include "c:\cores4\thor\trunk\software\c64libc\source\Thor\outh.s" |
.include "c:\cores4\thor\trunk\software\c64libc\source\Thor\outw.s" |
.include "video.asm" |
.include "serial.asm" |
.include "keyboard_codes.asm" |
.include "keybd2.asm" |
;.include "keyboard.asm" |
.include "debugger.asm" |
|
;------------------------------------------------------------------------------ |
; BTNU IRQ routine. |
; |
;------------------------------------------------------------------------------ |
; |
btnu_rout: |
sync |
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 |
inc.h hs:TEXTSCR+312 |
|
; restore regs and return |
lw r1,[r31] |
lws hs,8[r31] |
lws hs.lmt,16[r31] |
addui r31,r31,#24 |
sync |
rti |
|
;------------------------------------------------------------------------------ |
;------------------------------------------------------------------------------ |
|
spur_rout: |
sync |
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 |
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 |
|
;------------------------------------------------------------------------------ |
; Uninitialized interrupt |
;------------------------------------------------------------------------------ |
uii_rout: |
sync |
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 |
sh r1,hs:TEXTSCR+320 |
|
mov r5,r63 |
sc r63,hs:LEDS |
bsr DisplayAddr |
|
ldi r6,#2 |
ldi r2,#0 |
ldi r7,#0 |
.0001: |
ldis 60,#18 ; set breakout index to 18 |
sync |
mtspr 61,r7 ; select history reg # |
sync |
ldis 60,#16 ; set breakout index to 16 |
sync |
mfspr r5,61 ; get address |
bsr DisplayAddr |
addui r2,r2,#1 |
ldis 60,#17 ; set breakout index to 17 |
sync |
mfspr r5,61 ; get address |
bsr DisplayAddr |
addui r2,r2,#1 |
addui r7,r7,#1 |
cmpi p0,r7,#63 |
p0.ltu br .0001 |
|
uii_hang: |
br uii_hang |
; restore regs and return |
lw r1,[r31] |
lws hs,8[r31] |
lws hs.lmt,16[r31] |
addui r31,r31,#24 |
sync |
rti |
|
;------------------------------------------------------------------------------ |
; Non-maskable interrupt routine. |
; |
;------------------------------------------------------------------------------ |
; |
nmi_rout: |
sync |
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 |
|
; reset the edge sense circuit to re-enable interrupts |
ldi r1,#0 |
sh r1,hs:PIC_ESR |
|
; update on-screen IRQ live indicator |
lh r1,hs:TEXTSCR+324 |
addui r1,r1,#1 |
sh r1,hs:TEXTSCR+324 |
|
; restore regs and return |
lw r1,[r31] |
lws hs,8[r31] |
lws hs.lmt,16[r31] |
addui r31,r31,#24 |
sync |
rti |
|
;------------------------------------------------------------------------------ |
; Millisecond (1024 Hz) interrupt routine. |
; |
;------------------------------------------------------------------------------ |
; |
msi_rout: |
sync |
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 |
|
; reset the edge sense circuit to re-enable interrupts |
ldi r1,#1 |
sh r1,hs:PIC_ESR |
|
; update milliseconds |
lw r1,zs:Milliseconds |
addui r1,r1,#1 |
sw r1,zs:Milliseconds |
|
; restore regs and return |
lw r1,[sp] |
lws hs,8[sp] |
lws hs.lmt,16[sp] |
lws c1,24[sp] |
addui sp,sp,#32 |
sync |
rti |
|
;------------------------------------------------------------------------------ |
; Time Slice IRQ routine. |
; |
;------------------------------------------------------------------------------ |
; |
tms_rout: |
sync |
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 |
|
; reset the edge sense circuit to re-enable interrupts |
ldi r1,#2 |
sh r1,hs:PIC_ESR |
|
; update on-screen IRQ live indicator |
inc.h hs:TEXTSCR+328 |
|
; restore regs and return |
lw r1,[r31] |
lws hs,8[r31] |
lws hs.lmt,16[r31] |
addui r31,r31,#24 |
sync |
rte |
|
;------------------------------------------------------------------------------ |
; Data bus error routine. |
; |
; |
;------------------------------------------------------------------------------ |
; |
dbe_rout: |
sync |
ldi r31,#INT_STACK-24 |
sw r1,[r31] |
sws hs,8[r31] |
sw r5,16[r31] |
|
; set I/O segment |
ldis hs,#$FFD00000 |
|
ldi r1,#64 |
sc r1,hs:LEDS |
|
; reset the bus error circuit to re-enable interrupts |
sh r0,hs:$CFFE0 |
|
; update on-screen DBE indicator |
ldi r1,'D'|%011000000_000000110_0000000000 |
sh r1,hs:TEXTSCR+320 |
|
; Advance the program to the next address |
mfspr r5,c14 |
bsr DBGGetInsnLength |
addu r1,r5,r1 |
mtspr c14,r1 |
|
; restore regs and return |
lw r1,[r31] |
lws hs,8[r31] |
lw r5,16[r31] |
sync |
rti |
|
;------------------------------------------------------------------------------ |
; Break routine |
; |
; Currently uses only registers in case memory is bad, and sets an indicator |
; on-screen. |
;------------------------------------------------------------------------------ |
; |
brk_rout: |
sync |
ldi r1,#'B' |
bsr VBAsciiToScreen |
ori r1,r1,#|%011000000_111111111_00_00000000 |
sh r1,zs:$FFD10140 |
ldi r1,#'R' |
bsr VBAsciiToScreen |
ori r1,r1,#|%011000000_111111111_00_00000000 |
sh r1,zs:$FFD10144 |
ldi r1,#'K' |
bsr VBAsciiToScreen |
ori r1,r1,#|%011000000_111111111_00_00000000 |
sh r1,zs:$FFD10148 |
ldi r2,#10 |
ldi r6,#0 |
mfspr r5,c13 |
bsr DisplayAddr |
ldi r2,#10 |
ldi r6,#1 |
mfspr r5,c14 |
bsr DisplayAddr |
ldi r6,#2 |
ldi r2,#0 |
ldi r7,#0 |
.0001: |
ldis 60,#18 ; set breakout index to 18 |
sync |
mtspr 61,r7 ; select history reg # |
sync |
ldis 60,#16 ; set breakout index to 16 |
sync |
mfspr r5,61 ; get address |
bsr DisplayAddr |
addui r2,r2,#1 |
ldis 60,#17 ; set breakout index to 17 |
sync |
mfspr r5,61 ; get address |
bsr DisplayAddr |
addui r2,r2,#1 |
addui r7,r7,#1 |
cmpi p0,r7,#63 |
p0.ltu br .0001 |
|
brk_lockup: |
br brk_lockup[c0] |
|
; code snippet to jump to the break routine, copied to the break vector |
; |
; vector table jumps |
; |
align 8 |
brk_jmp: |
jmp brk_rout[c0] |
align 8 |
tms_jmp: |
jmp tms_rout[c0] |
align 8 |
msi_jmp: |
jmp msi_rout[c0] |
align 8 |
nmi_jmp: |
jmp nmi_rout[c0] |
align 8 |
uii_jmp: |
ldi r63,#00 |
jmp uii_rout[c0] |
align 8 |
vb_jmp: |
jmp VideoBIOSCall[c0] |
align 8 |
dbe_jmp: |
jmp dbe_rout[c0] |
align 8 |
svc_jmp: |
jmp save_context[c0] |
align 8 |
rsc_jmp: |
jmp restore_context[c0] |
align 8 |
spur_jmp: |
jmp spur_rout[c0] |
align 8 |
btnu_jmp: |
jmp btnu_rout[c0] |
align 8 |
rti_jmp: |
km_jmp: |
rti |
align 8 |
rte_jmp: |
rte |
|
|
/software/source/Debugger.asm
0,0 → 1,1554
; ============================================================================ |
; __ |
; \\__/ 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 |
DBGBuf fill.b 84,0 |
DBGBufndx db 0 |
|
code |
align 256 |
|
;------------------------------------------------------------------------------ |
; 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,#0 |
ldis ds.lmt,#-1 |
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_abs: byte "ab",'s'|$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_andc: byte "and",'c'|$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_cli: byte "cl",'i'|$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_lvwar: byte "lvwa",'r'|$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_sei: byte "se",'i'|$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 |
|
/software/source/video.asm
0,0 → 1,1013
; ============================================================================ |
; __ |
; \\__/ 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. |
; ============================================================================ |
|
;------------------------------------------------------------------------------ |
;------------------------------------------------------------------------------ |
code |
|
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. |
;------------------------------------------------------------------------------ |
|
VBScrollUp: |
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 |
; 0x0E = Teletype output r1=char to display |
; 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 VBDisplayChar |
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: |
lcu r3,Textcols |
mulu r1,r1,r3 |
shli r1,r1,#2 |
_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 |
|
/software/source/keyboard_codes.asm
0,0 → 1,111
;-------------------------------------------------------------------------- |
; 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 |
|
/software/source/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 |
|