Line 1... |
Line 1... |
; ============================================================================
|
; ============================================================================
|
; (C) 2012,2013 Robert Finch, Stratford
|
; __
|
; All Rights Reserved.
|
; \\__/ o\ (C) 2012-2013 Robert Finch, Stratford
|
; robfinch<remove>@opencores.org
|
; \ __ / All rights reserved.
|
|
; \/_// robfinch<remove>@opencores.org
|
|
; ||
|
|
;
|
;
|
;
|
; This source file is free software: you can redistribute it and/or modify
|
; 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
|
; 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
|
; by the Free Software Foundation, either version 3 of the License, or
|
; (at your option) any later version.
|
; (at your option) any later version.
|
Line 21... |
Line 24... |
CR EQU 0x0D ;ASCII equates
|
CR EQU 0x0D ;ASCII equates
|
LF EQU 0x0A
|
LF EQU 0x0A
|
TAB EQU 0x09
|
TAB EQU 0x09
|
CTRLC EQU 0x03
|
CTRLC EQU 0x03
|
CTRLH EQU 0x08
|
CTRLH EQU 0x08
|
|
CTRLI EQU 0x09
|
|
CTRLJ EQU 0x0A
|
|
CTRLK EQU 0x0B
|
|
CTRLM EQU 0x0D
|
CTRLS EQU 0x13
|
CTRLS EQU 0x13
|
CTRLX EQU 0x18
|
CTRLX EQU 0x18
|
XON EQU 0x11
|
XON EQU 0x11
|
XOFF EQU 0x13
|
XOFF EQU 0x13
|
|
|
|
EX_IRQ EQU 449
|
|
|
DATA_PRESENT EQU 0x01 ; there is data preset at the serial port bc_uart3
|
DATA_PRESENT EQU 0x01 ; there is data preset at the serial port bc_uart3
|
XMIT_NOT_FULL EQU 0x20
|
XMIT_NOT_FULL EQU 0x20
|
|
|
BUFLEN EQU 80 ; length of keyboard input buffer
|
BUFLEN EQU 80 ; length of keyboard input buffer
|
|
|
Line 88... |
Line 97... |
TCBr28 EQU 0xD8
|
TCBr28 EQU 0xD8
|
TCBr29 EQU 0xE0
|
TCBr29 EQU 0xE0
|
TCBr30 EQU 0xE8
|
TCBr30 EQU 0xE8
|
TCBr31 EQU 0xF0
|
TCBr31 EQU 0xF0
|
|
|
|
SCREENGATE EQU 0x00
|
|
KEYBDGATE EQU 0x01
|
|
VIDEOGATE EQU 0x02
|
|
CARDGATE EQU 0x03
|
warmStart EQU 0x1020
|
warmStart EQU 0x1020
|
usrJmp EQU 0x1028
|
usrJmp EQU 0x1028
|
TickIRQAddr EQU 0x1030
|
TickIRQAddr EQU 0x1030
|
TaskBlock EQU 0x1038
|
TaskBlock EQU 0x1038
|
tencount EQU 0x13F8
|
|
Milliseconds EQU 0x1400
|
Milliseconds EQU 0x1400
|
Lastloc EQU 0x1408
|
Lastloc EQU 0x1408
|
|
CharColor EQU 0x1410
|
ScreenColor EQU 0x1414
|
ScreenColor EQU 0x1414
|
CursorRow EQU 0x1416
|
CursorRow EQU 0x1417
|
CursorCol EQU 0x1418
|
CursorCol EQU 0x1418
|
CursorFlash EQU 0x141A
|
CursorFlash EQU 0x141A
|
KeybdEcho EQU 0x141C
|
KeybdEcho EQU 0x141C
|
KeybdBuffer EQU 0x1440
|
KeybdBuffer EQU 0x1440
|
KeybdHead EQU 0x1450
|
KeybdHead EQU 0x1450
|
KeybdTail EQU 0x1451
|
KeybdTail EQU 0x1451
|
|
sp_save EQU 0x1460
|
|
lr_save EQU 0x1468
|
|
r1_save EQU 0x1470
|
|
r2_save EQU 0x1478
|
|
r26_save EQU 0x1480
|
Score EQU 0x1500
|
Score EQU 0x1500
|
Manpos EQU 0x1508
|
Manpos EQU 0x1508
|
MissileActive EQU 0x1510
|
MissileActive EQU 0x1510
|
MissileX EQU 0x1512
|
MissileX EQU 0x1512
|
MissileY EQU 0x1514
|
MissileY EQU 0x1514
|
Line 146... |
Line 164... |
NextToRunTCB EQU 0x20A8
|
NextToRunTCB EQU 0x20A8
|
r1save EQU 0x20B0
|
r1save EQU 0x20B0
|
r2save EQU 0x20B8
|
r2save EQU 0x20B8
|
AXCstart EQU 0x20C0
|
AXCstart EQU 0x20C0
|
|
|
|
; Context startup address table
|
|
;
|
|
ctx0start EQU 0x20D0
|
|
ctx1start EQU 0x20D8
|
|
ctx2start EQU 0x20E0
|
|
ctx3start EQU 0x20E8
|
|
ctx4start EQU 0x20F0
|
|
ctx5start EQU 0x20F8
|
|
ctx6start EQU 0x2100
|
|
ctx7start EQU 0x2108
|
|
ctx8start EQU 0x2110
|
|
ctx9start EQU 0x2118
|
|
ctx10start EQU 0x2120
|
|
ctx11start EQU 0x2128
|
|
ctx12start EQU 0x2130
|
|
ctx13start EQU 0x2138
|
|
ctx14start EQU 0x2140
|
|
ctx15start EQU 0x2148
|
|
sp_saves EQU 0x2200
|
|
sp_saves_end EQU 0x2280
|
p100IRQvec EQU 0x3000
|
p100IRQvec EQU 0x3000
|
keybdIRQvec EQU 0x3008
|
keybdIRQvec EQU 0x3008
|
serialIRQvec EQU 0x3010
|
serialIRQvec EQU 0x3010
|
rasterIRQvec EQU 0x3018
|
rasterIRQvec EQU 0x3018
|
|
|
|
startSector EQU 0x30F8
|
|
BPB EQU 0x3100
|
|
|
TEXTSCR EQU 0xD0_0000
|
TEXTSCR EQU 0xD0_0000
|
COLORSCR EQU 0xD1_0000
|
COLORSCR EQU 0xD1_0000
|
TEXTREG EQU 0xDA_0000
|
TEXTREG EQU 0xDA_0000
|
TEXT_COLS EQU 0x0
|
TEXT_COLS EQU 0x0
|
TEXT_ROWS EQU 0x2
|
TEXT_ROWS EQU 0x2
|
Line 167... |
Line 208... |
UART_MS EQU 0xDC_0A02
|
UART_MS EQU 0xDC_0A02
|
UART_IS EQU 0xDC_0A03
|
UART_IS EQU 0xDC_0A03
|
UART_IE EQU 0xDC_0A04
|
UART_IE EQU 0xDC_0A04
|
UART_MC EQU 0xDC_0A06
|
UART_MC EQU 0xDC_0A06
|
DATETIME EQU 0xDC_0400
|
DATETIME EQU 0xDC_0400
|
|
|
|
SPIMASTER EQU 0xDC_0500
|
|
SPI_MASTER_VERSION_REG EQU 0x00
|
|
SPI_MASTER_CONTROL_REG EQU 0x01
|
|
SPI_TRANS_TYPE_REG EQU 0x02
|
|
SPI_TRANS_CTRL_REG EQU 0x03
|
|
SPI_TRANS_STATUS_REG EQU 0x04
|
|
SPI_TRANS_ERROR_REG EQU 0x05
|
|
SPI_DIRECT_ACCESS_DATA_REG EQU 0x06
|
|
SPI_SD_ADDR_7_0_REG EQU 0x07
|
|
SPI_SD_ADDR_15_8_REG EQU 0x08
|
|
SPI_SD_ADDR_23_16_REG EQU 0x09
|
|
SPI_SD_ADDR_31_24_REG EQU 0x0a
|
|
SPI_RX_FIFO_DATA_REG EQU 0x10
|
|
SPI_RX_FIFO_DATA_COUNT_MSB EQU 0x12
|
|
SPI_RX_FIFO_DATA_COUNT_LSB EQU 0x13
|
|
SPI_RX_FIFO_CTRL_REG EQU 0x14
|
|
SPI_TX_FIFO_DATA_REG EQU 0x20
|
|
SPI_TX_FIFO_CTRL_REG EQU 0x24
|
|
SPI_INIT_SD EQU 0x01
|
|
SPI_TRANS_START EQU 0x01
|
|
SPI_TRANS_BUSY EQU 0x01
|
|
SPI_INIT_NO_ERROR EQU 0x00
|
|
SPI_READ_NO_ERROR EQU 0x00
|
|
RW_READ_SD_BLOCK EQU 0x02
|
|
RW_WRITE_SD_BLOCK EQU 0x03
|
|
|
|
|
PIC EQU 0xDC_0FF0
|
PIC EQU 0xDC_0FF0
|
PIC_IE EQU 0xDC_0FF2
|
PIC_IE EQU 0xDC_0FF2
|
|
|
PSG EQU 0xD5_0000
|
PSG EQU 0xD5_0000
|
PSGFREQ0 EQU 0xD5_0000
|
PSGFREQ0 EQU 0xD5_0000
|
Line 178... |
Line 247... |
PSGCTRL0 EQU 0xD5_0004
|
PSGCTRL0 EQU 0xD5_0004
|
PSGADSR0 EQU 0xD5_0006
|
PSGADSR0 EQU 0xD5_0006
|
|
|
SPRRAM EQU 0xD8_0000
|
SPRRAM EQU 0xD8_0000
|
AC97 EQU 0xDC_1000
|
AC97 EQU 0xDC_1000
|
|
TMP EQU 0xDC_0300
|
LED EQU 0xDC_0600
|
LED EQU 0xDC_0600
|
|
ETHMAC EQU 0xDC_2000
|
|
CONFIGREC EQU 0xDC_FFFF
|
|
MIIMODER EQU 0x28
|
|
MIIADDRESS EQU 0x30
|
GACCEL EQU 0xDA_E000
|
GACCEL EQU 0xDA_E000
|
RASTERIRQ EQU 0xDA_0100
|
RASTERIRQ EQU 0xDA_0100
|
BOOT_STACK EQU 0xFFFF_FFFF_FFFE_FFF8
|
BOOT_STACK EQU 0xFFFF_FFFF_FFFE_FFF8
|
SPRITEREGS EQU 0xDA_D000
|
SPRITEREGS EQU 0xDA_D000
|
BITMAPSCR EQU 0x00000001_00200000
|
BITMAPSCR EQU 0x00000001_00200000
|
|
|
|
BOOTJMP EQU 0x100800204
|
|
|
txempty EQU 0x40
|
txempty EQU 0x40
|
rxfull EQU 0x01
|
rxfull EQU 0x01
|
|
|
;
|
;
|
; Internal variables follow:
|
; Internal variables follow:
|
;
|
;
|
bss
|
bss
|
org 0x1038
|
org 0x1048
|
txtWidth db 0 ; BIOS var =56
|
txtWidth db 0 ; BIOS var =56
|
txtHeight db 0 ; BIOS var =31
|
txtHeight db 0 ; BIOS var =31
|
cursx db 0 ; cursor x position
|
cursx db 0 ; cursor x position
|
cursy db 0 ; cursor y position
|
cursy db 0 ; cursor y position
|
pos dh 0 ; text screen position
|
pos dh 0 ; text screen position
|
org 0x1040
|
|
charToPrint dc 0
|
charToPrint dc 0
|
fgColor db 0
|
fgColor db 0
|
bkColor db 0
|
bkColor db 0
|
cursFlash db 0 ; flash the cursor ?
|
cursFlash db 0 ; flash the cursor ?
|
|
|
lineLinkTbl fill.b 25,0 ; screen line link table
|
lineLinkTbl fill.b 47,0 ; screen line link table
|
align 8
|
|
|
|
org 0x1080
|
|
typef db 0 ; variable / expression type
|
typef db 0 ; variable / expression type
|
align 8
|
align 8
|
OSSP dw 1 ; OS value of sp
|
OSSP dw 1 ; OS value of sp
|
CURRNT dw 1 ; Current line pointer
|
CURRNT dw 1 ; Current line pointer
|
STKGOS dw 1 ; Saves stack pointer in 'GOSUB'
|
STKGOS dw 1 ; Saves stack pointer in 'GOSUB'
|
Line 254... |
Line 326... |
jmp SetKeyboardEcho
|
jmp SetKeyboardEcho
|
jmp KeybdCheckForKey
|
jmp KeybdCheckForKey
|
jmp KeybdGetChar
|
jmp KeybdGetChar
|
jmp DisplayChar
|
jmp DisplayChar
|
jmp DisplayString
|
jmp DisplayString
|
|
jmp DisplayNum
|
|
jmp CalcScreenLoc
|
|
jmp ClearScreen
|
|
jmp DisplayWord
|
|
|
start:
|
start:
|
; lea MSGRAM,a1
|
; lea MSGRAM,a1
|
; jsr DisplayString
|
; jsr DisplayString
|
|
|
ColdStart:
|
ColdStart:
|
icache_on ; turn on the ICache
|
icache_off ; turn on the ICache
|
dcache_off ; turn on the DCache
|
dcache_off ; turn on the DCache
|
|
|
|
; Make sure semaphores are available by closing the gates.
|
|
; We don't know what power up state is.
|
|
|
|
cmgi #KEYBDGATE
|
|
cmgi #VIDEOGATE
|
|
|
|
; Initialize the context startup address table with NULL
|
|
|
|
xor r1,r1,r1
|
|
sw r1,ctx0start
|
|
sw r1,ctx1start
|
|
sw r1,ctx2start
|
|
sw r1,ctx3start
|
|
sw r1,ctx4start
|
|
sw r1,ctx5start
|
|
sw r1,ctx6start
|
|
sw r1,ctx7start
|
|
sw r1,ctx8start
|
|
sw r1,ctx9start
|
|
sw r1,ctx10start
|
|
sw r1,ctx11start
|
|
sw r1,ctx12start
|
|
sw r1,ctx13start
|
|
sw r1,ctx14start
|
|
sw r1,ctx15start
|
|
|
; Initialize the context schedule with all contexts treated equally
|
; Initialize the context schedule with all contexts treated equally
|
; There are only 16 contexts, but 256 schedule slots. Each context is
|
; There are only 16 contexts, but 256 schedule slots. Each context is
|
; given 16 slots distributed evenly throughout the execution pattern
|
; given 16 slots distributed evenly throughout the execution pattern
|
; table.
|
; table.
|
;
|
;
|
Line 282... |
Line 384... |
; occurs.
|
; occurs.
|
;
|
;
|
; We cannot use a loop for this. Fortunately there's only 16 contexts.
|
; We cannot use a loop for this. Fortunately there's only 16 contexts.
|
;
|
;
|
lea r25,ctxstart
|
lea r25,ctxstart
|
|
mtspr IPC,r25
|
lea r30,STACKTOP0
|
lea r30,STACKTOP0
|
iepp
|
iepp
|
nop
|
|
nop
|
|
lea r25,ctxstart
|
lea r25,ctxstart
|
|
mtspr IPC,r25
|
lea r30,STACKTOP1
|
lea r30,STACKTOP1
|
iepp
|
iepp
|
nop
|
|
nop
|
|
lea r25,ctxstart
|
lea r25,ctxstart
|
|
mtspr IPC,r25
|
lea r30,STACKTOP2
|
lea r30,STACKTOP2
|
iepp
|
iepp
|
nop
|
|
nop
|
|
lea r25,ctxstart
|
lea r25,ctxstart
|
|
mtspr IPC,r25
|
lea r30,STACKTOP3
|
lea r30,STACKTOP3
|
iepp
|
iepp
|
nop
|
|
nop
|
|
|
|
lea r25,ctxstart
|
lea r25,ctxstart
|
|
mtspr IPC,r25
|
lea r30,STACKTOP4
|
lea r30,STACKTOP4
|
iepp
|
iepp
|
nop
|
|
nop
|
|
lea r25,ctxstart
|
lea r25,ctxstart
|
|
mtspr IPC,r25
|
lea r30,STACKTOP5
|
lea r30,STACKTOP5
|
iepp
|
iepp
|
nop
|
|
nop
|
|
lea r25,ctxstart
|
lea r25,ctxstart
|
|
mtspr IPC,r25
|
lea r30,STACKTOP6
|
lea r30,STACKTOP6
|
iepp
|
iepp
|
nop
|
|
nop
|
|
lea r25,ctxstart
|
lea r25,ctxstart
|
|
mtspr IPC,r25
|
lea r30,STACKTOP7
|
lea r30,STACKTOP7
|
iepp
|
iepp
|
nop
|
|
nop
|
|
|
|
lea r25,ctxstart
|
lea r25,ctxstart
|
|
mtspr IPC,r25
|
lea r30,STACKTOP8
|
lea r30,STACKTOP8
|
iepp
|
iepp
|
nop
|
|
nop
|
|
lea r25,ctxstart
|
lea r25,ctxstart
|
|
mtspr IPC,r25
|
lea r30,STACKTOP9
|
lea r30,STACKTOP9
|
iepp
|
iepp
|
nop
|
|
nop
|
|
lea r25,ctxstart
|
lea r25,ctxstart
|
|
mtspr IPC,r25
|
lea r30,STACKTOP10
|
lea r30,STACKTOP10
|
iepp
|
iepp
|
nop
|
|
nop
|
|
lea r25,ctxstart
|
lea r25,ctxstart
|
|
mtspr IPC,r25
|
lea r30,STACKTOP11
|
lea r30,STACKTOP11
|
iepp
|
iepp
|
nop
|
|
nop
|
|
|
|
lea r25,ctxstart
|
lea r25,ctxstart
|
|
mtspr IPC,r25
|
lea r30,STACKTOP12
|
lea r30,STACKTOP12
|
iepp
|
iepp
|
nop
|
|
nop
|
|
lea r25,ctxstart
|
lea r25,ctxstart
|
|
mtspr IPC,r25
|
lea r30,STACKTOP13
|
lea r30,STACKTOP13
|
iepp
|
iepp
|
nop
|
|
nop
|
|
lea r25,ctxstart
|
lea r25,ctxstart
|
|
mtspr IPC,r25
|
lea r30,STACKTOP14
|
lea r30,STACKTOP14
|
iepp
|
iepp
|
nop
|
|
nop
|
|
lea r25,ctxstart
|
lea r25,ctxstart
|
|
mtspr IPC,r25
|
lea r30,STACKTOP15
|
lea r30,STACKTOP15
|
iepp
|
iepp
|
nop
|
|
nop
|
|
|
|
; Ensure that context zero is the active context
|
; Ensure that context zero is the active context
|
;
|
;
|
ctxstart3:
|
ctxstart3:
|
mfspr r1,AXC
|
mfspr r1,AXC
|
beq r1,r0,ctxstart2
|
beq r1,r0,ctxstart2
|
iepp
|
iepp
|
nop
|
|
nop
|
|
bra ctxstart3
|
bra ctxstart3
|
ctxstart2:
|
ctxstart2:
|
sb r1,AXCstart ; save off the startup context which should be context zero
|
sb r1,AXCstart ; save off the startup context which should be context zero
|
|
|
; Entry point for context startup
|
; Entry point for context startup
|
Line 398... |
Line 482... |
lea r1,nmirout
|
lea r1,nmirout
|
csj5:
|
csj5:
|
sw r1,[r3]
|
sw r1,[r3]
|
addui r3,r3,#8
|
addui r3,r3,#8
|
loop r2,csj5
|
loop r2,csj5
|
|
lea r1,VideoSC ; Video BIOS vector
|
|
sw r1,0xCD0
|
|
lea r1,SCCARDSC ; SD Card BIOS vector
|
|
sw r1,0xCE8
|
|
lea r1,RTCSC ; Real time clock vector
|
|
sw r1,0xD00
|
lea r1,KeybdSC ; keyboard BIOS vector
|
lea r1,KeybdSC ; keyboard BIOS vector
|
sw r1,0xD08
|
sw r1,0xD08
|
lea r1,irqrout
|
lea r1,irqrout
|
sw r1,0xE08 ; set IRQ vector
|
sw r1,0xE08 ; set IRQ vector
|
|
lea r1,ui_irout
|
|
sw r1,0xF78 ; set unimplemented instruction vector
|
lea r1,dberr_rout
|
lea r1,dberr_rout
|
sw r1,0xFE0 ; set Bus error vector
|
sw r1,0xFE0 ; set Bus error vector
|
lea r1,iberr_rout
|
lea r1,iberr_rout
|
sw r1,0xFE8 ; set Bus error vector
|
sw r1,0xFE8 ; set Bus error vector
|
lea r1,nmirout
|
lea r1,nmirout
|
sw r1,0xFF0 ; set NMI vector
|
sw r1,0xFF0 ; set NMI vector
|
|
|
|
; set system interrupt hook vectors
|
|
|
lea r1,KeybdIRQ
|
lea r1,KeybdIRQ
|
sw r1,keybdIRQvec
|
sw r1,keybdIRQvec
|
lea r1,Pulse100
|
lea r1,Pulse100
|
sw r1,p100IRQvec
|
sw r1,p100IRQvec
|
lea r1,SerialIRQ
|
lea r1,SerialIRQ
|
Line 421... |
Line 515... |
sw r1,rasterIRQvec
|
sw r1,rasterIRQvec
|
|
|
;-------------------------------
|
;-------------------------------
|
; Initialize I/O devices
|
; Initialize I/O devices
|
;-------------------------------
|
;-------------------------------
|
|
inbu r1,CONFIGREC
|
|
bfext r1,r1,#4,#4
|
|
beq r1,r0,skip5
|
|
call tmp_init
|
|
skip5:
|
|
inbu r1,CONFIGREC
|
|
bfext r1,r1,#5,#5
|
|
beq r1,r0,skip4
|
call SerialInit
|
call SerialInit
|
|
skip4:
|
call KeybdInit
|
call KeybdInit
|
call PICInit
|
call PICInit
|
call SetupRasterIRQ
|
call SetupRasterIRQ
|
cli ; enable interrupts
|
cli ; enable interrupts
|
; call HelloWorld
|
; call HelloWorld
|
setlo r3,#0xCE ; blue on blue
|
setlo r3,#0xCE ; blue on blue
|
sc r3,ScreenColor
|
sc r3,ScreenColor
|
|
sc r3,CharColor
|
lc r3,0x1414
|
lc r3,0x1414
|
setlo r3,#32
|
setlo r3,#32
|
sc r3,0x1416 ; we do a store, then a load through the dcache
|
sc r3,0x1416 ; we do a store, then a load through the dcache
|
lc r2,0x1416 ;
|
lc r2,0x1416 ;
|
beq r2,r3,dcokay
|
beq r2,r3,dcokay
|
dcache_off ; data cache failed
|
dcache_off ; data cache failed
|
dcokay:
|
dcokay:
|
sc r0,NextToRunTCB
|
sc r0,NextToRunTCB
|
sc r0,RunningTCB
|
sc r0,RunningTCB
|
|
lw r1,#2 ; get rid of startup keyboard glitchs by trying to get a character
|
|
syscall #417
|
|
lw r1,#2 ; get rid of startup keyboard glitchs by trying to get a character
|
|
syscall #417
|
|
|
|
; wait for screen to be available
|
call ClearScreen
|
call ClearScreen
|
call ClearBmpScreen
|
call ClearBmpScreen
|
|
|
|
; Test whether or not the sprite controller is present. Skip
|
|
; Initialization if it isn't.
|
|
|
|
inb r1,CONFIGREC
|
|
bfext r1,r1,#0,#0
|
|
beq r1,r0,skip1
|
call RandomizeSprram
|
call RandomizeSprram
|
sc r0,CursorRow
|
skip1:
|
sc r0,CursorCol
|
|
setlo r1,#1
|
sb r0,CursorRow
|
|
sb r0,CursorCol
|
|
lw r1,#1
|
sb r1,CursorFlash
|
sb r1,CursorFlash
|
lea r1,MSGSTART
|
lea r1,MSGSTART
|
call DisplayStringCRLF
|
call DisplayStringCRLF
|
jmp Monitor
|
|
|
; Test whether or not sound generator is present
|
|
; skip initialization and beep if not present
|
|
|
|
inb r1,CONFIGREC
|
|
bfext r1,r1,#2,#2
|
|
beq r1,r0,skip2
|
call SetupAC97 ; and Beep
|
call SetupAC97 ; and Beep
|
setlo r3,#4
|
lw r1,#4
|
outb r3,LED
|
outb r1,LED
|
call Beep
|
call Beep
|
|
skip2:
|
|
|
|
lea r1,context1disp ; start a display
|
|
sw r1,ctx1start
|
|
|
|
; Startup Ethernet access ?
|
|
;
|
|
inb r1,CONFIGREC
|
|
bfext r1,r1,#1,#1
|
|
beq r1,r0,skip3
|
|
lea r1,eth_main
|
|
sw r1,ctx2start
|
|
skip3:
|
|
|
|
lea r1,RandomLines
|
|
sw r1,ctx3start
|
|
call spi_init
|
|
bne r1,r0,skip_spi_read
|
|
call spi_read_boot
|
|
call loadBootFile
|
|
skip_spi_read:
|
|
jmp Monitor
|
|
|
j4:
|
j4:
|
jmp Monitor
|
jmp Monitor
|
bra j4
|
bra j4
|
|
|
; for now hang the contexts
|
; The contexts wait for a context startup address to be placed in the
|
|
; startup table. Once an address is in the table, a call to the context
|
|
; code will be made. The default is a NULL pointer, which
|
|
; causes the context to loop around back to here while waiting for a
|
|
; code to run.
|
;
|
;
|
ctxstart1:
|
ctxstart1:
|
|
lea r1,ctx0start ; r1 = context start table base
|
|
mfspr r2,AXC ; r2 = index into start table
|
|
lw r1,[r1+r2*8] ; r1 = context start address
|
|
beq r1,r0,ctx12
|
|
jal lr,[r1] ; perform a call to the context code
|
|
|
|
; We might as well move to the next context, since there's nothing
|
|
; to do. This can be accomplished by tirggering a IRQ interrupt.
|
|
; We can't just increment the excution pattern pointer, because that
|
|
; would only switch the register set and not the program counter.
|
|
; An interrupt saves the program counter, and restores it from the
|
|
; IPC context register.
|
|
;
|
|
ctx12:
|
|
sei ; causes a priv violation. don't allow interrupts during syscall
|
|
nop ; wait for sei to take effect
|
|
nop
|
|
nop
|
|
syscall #EX_IRQ
|
bra ctxstart1
|
bra ctxstart1
|
|
|
; call ramtest
|
; call ramtest
|
|
|
|
context1disp:
|
|
|
|
; once we've started, clear the start vector so that the context
|
|
; isn't continuously restarted.
|
|
;
|
|
sw r0,ctx1start
|
|
lea r3,TEXTSCR
|
|
lw r1,#'V'
|
|
lw r2,#330
|
|
lw r4,#47
|
|
call AsciiToScreen
|
|
ctx11:
|
|
inch r1,[r3+r2]
|
|
addui r1,r1,#1
|
|
outc r1,[r3+r2]
|
|
addui r2,r2,#168
|
|
loop r4,ctx11
|
|
bra context1disp
|
|
|
;-----------------------------------------
|
;-----------------------------------------
|
; Hello World!
|
; Hello World!
|
;-----------------------------------------
|
;-----------------------------------------
|
HelloWorld:
|
HelloWorld:
|
subui r30,r30,#24
|
subui r30,r30,#24
|
Line 496... |
Line 685... |
|
|
align 16
|
align 16
|
|
|
;----------------------------------------------------------
|
;----------------------------------------------------------
|
; Initialize programmable interrupt controller (PIC)
|
; Initialize programmable interrupt controller (PIC)
|
; 0 = nmi
|
; 0 = nmi (parity error)
|
; 1 = keyboard reset
|
; 1 = keyboard reset
|
; 2 = 1000Hz pulse (context switcher)
|
; 2 = 1000Hz pulse (context switcher)
|
; 3 = 100Hz pulse (cursor flash)
|
; 3 = 100Hz pulse (cursor flash)
|
|
; 4 = ethmac
|
; 8 = uart
|
; 8 = uart
|
; 13 = raster interrupt
|
; 13 = raster interrupt
|
; 15 = keyboard char
|
; 15 = keyboard char
|
;----------------------------------------------------------
|
;----------------------------------------------------------
|
PICInit:
|
PICInit:
|
lea r1,PICret
|
lea r1,PICret
|
sw r1,TickIRQAddr
|
sw r1,TickIRQAddr
|
; enable: raster irq,
|
; enable: raster irq,
|
setlo r1,#0xA00F ; enable nmi,kbd_rst,and kbd_irq
|
setlo r1,#0x800F ; enable nmi,kbd_rst,and kbd_irq
|
; A10F enable serial IRQ
|
; A10F enable serial IRQ
|
outc r1,PIC_IE
|
outc r1,PIC_IE
|
PICret:
|
PICret:
|
ret
|
ret
|
|
|
Line 791... |
Line 981... |
outb r1,UART
|
outb r1,UART
|
srxirq8:
|
srxirq8:
|
bra sirq1
|
bra sirq1
|
|
|
;==============================================================================
|
;==============================================================================
|
|
; Video BIOS
|
|
; Video interrupt #410
|
|
;
|
|
; Function in R1
|
|
; 0x02 = Set Cursor Position r2 = row, r3 = col
|
|
; 0x03 = Get Cursor position returns r1 = row, r2 = col
|
|
; 0x06 = Scroll screen up
|
|
; 0x09 = Display character+attribute, r2=char, r3=attrib, r4=#times
|
|
; 0x0A = Display character, r2 = char, r3 = # times
|
|
; 0x0C = Display Pixel r2 = x, r3 = y, r4 = color
|
|
; 0x0D = Get pixel r2 = x, r3 = y
|
|
; 0x14 = Display String r2 = pointer to string
|
|
; 0x15 = Display number r2 = number, r3 = # digits
|
|
; 0x16 = Display String + CRLF r2 = pointer to string
|
|
; 0x17 = Display Word r2 as hex = word
|
|
; 0x18 = Display Half word as hex r2 = half word
|
|
; 0x19 = Display Charr char in hex r2 = char
|
|
; 0x1A = Display Byte in hex r2 = byte
|
|
;==============================================================================
|
|
;
|
|
VideoSC:
|
|
mfspr r26,AXC ; get context
|
|
shlui r26,r26,#3 ; *8
|
|
sw sp,sp_saves[r26] ; save sp in save area
|
|
shlui r26,r26,#8 ; 2k for stack
|
|
mov sp,r26
|
|
addui sp,sp,#0x100008000 ; base stacks address
|
|
subui sp,sp,#8
|
|
sw lr,[sp]
|
|
Video1:
|
|
omgi lr,#VIDEOGATE
|
|
bne lr,r0,Video1
|
|
beqi r1,#0x02,Video_x02
|
|
beqi r1,#0x03,Video_x03
|
|
beqi r1,#0x06,Video_x06
|
|
beqi r1,#0x09,Video_x09
|
|
beqi r1,#0x0A,Video_x0A
|
|
beqi r1,#0x0C,Video_x0C
|
|
beqi r1,#0x0C,Video_x0D
|
|
beqi r1,#0x14,Video_x14
|
|
beqi r1,#0x15,Video_x15
|
|
beqi r1,#0x16,Video_x16
|
|
beqi r1,#0x17,Video_x17
|
|
beqi r1,#0x1A,Video_x1A
|
|
bra VideoRet
|
|
|
|
Video_x02:
|
|
sb r2,CursorRow
|
|
sb r3,CursorCol
|
|
call CalcScreenLoc
|
|
bra VideoRet
|
|
|
|
Video_x03:
|
|
lbu r1,CursorRow
|
|
lbu r2,CursorCol
|
|
bra VideoRet
|
|
|
|
Video_x06:
|
|
call ScrollUp
|
|
bra VideoRet
|
|
|
|
Video_x09:
|
|
sc r3,CharColor
|
|
mov r1,r2
|
|
Video_x09a:
|
|
call DisplayChar
|
|
loop r4,Video_x09a
|
|
bra VideoRet
|
|
|
|
Video_x0A:
|
|
mov r1,r2
|
|
Video_x0Aa:
|
|
call DisplayChar
|
|
loop r3,Video_x0Aa
|
|
bra VideoRet
|
|
|
|
Video_x0C:
|
|
sh r2,GACCEL+8 ; x0
|
|
sh r3,GACCEL+12 ; y0
|
|
sh r4,GACCEL+0 ; color
|
|
lw r1,#1
|
|
sh r1,GACCEL+60 ; DRAW PIXEL command
|
|
bra VideoRet
|
|
|
|
Video_x0D:
|
|
sh r2,GACCEL+8 ; x0
|
|
sh r3,GACCEL+12 ; y0
|
|
lw r1,#8
|
|
sh r1,GACCEL+60 ; GET PIXEL command
|
|
nop ; let command start
|
|
nop
|
|
nop
|
|
vxd1:
|
|
lhu r1,GACCEL+56 ; wait for state = IDLE
|
|
bne r1,r0,vxd1
|
|
lhu r1,GACCEL+52
|
|
bra VideoRet
|
|
|
|
Video_x14:
|
|
mov r1,r2
|
|
call DisplayString
|
|
bra VideoRet
|
|
|
|
Video_x15:
|
|
mov r1,r2
|
|
mov r2,r3
|
|
call DisplayNum
|
|
bra VideoRet
|
|
|
|
Video_x16:
|
|
mov r1,r2
|
|
call DisplayStringCRLF
|
|
bra VideoRet
|
|
|
|
Video_x17:
|
|
mov r1,r2
|
|
call DisplayWord
|
|
bra VideoRet
|
|
|
|
Video_x1A:
|
|
mov r1,r2
|
|
call DisplayByte
|
|
bra VideoRet
|
|
|
|
VideoRet:
|
|
cmgi #VIDEOGATE
|
|
lw lr,[sp]
|
|
mfspr r26,AXC ; get context
|
|
shlui r26,r26,#3 ; *8
|
|
lw sp,sp_saves[r26] ; get back the stack
|
|
eret
|
|
|
|
;==============================================================================
|
|
; BIOS interrupt #413
|
|
; 0x00 initialize
|
|
; 0x01 read sector r2 = sector #, r3 = pointer to buffer
|
|
; 0x02 write sector
|
|
;==============================================================================
|
|
;
|
|
SDCARDSC:
|
|
mfspr r26,AXC ; get context
|
|
shlui r26,r26,#3 ; *8
|
|
sw sp,sp_saves[r26] ; save sp in save area
|
|
shlui r26,r26,#8 ; 2k for stack
|
|
mov sp,r26
|
|
addui sp,sp,#0x100008000 ; base stacks address
|
|
subui sp,sp,#8
|
|
sw lr,[sp]
|
|
SDC_1:
|
|
omgi lr,#CARDGATE
|
|
bne lr,r0,SDC_1
|
|
beqi r1,#0,SDC_x00
|
|
beqi r1,#1,SDC_x01
|
|
beqi r1,#2,SDC_x02
|
|
bra SDCRet
|
|
SDC_x00:
|
|
call spi_init
|
|
bra SDCRet
|
|
SDC_x01:
|
|
mov r1,r2
|
|
mov r2,r3
|
|
call spi_read_sector
|
|
bra SDCRet
|
|
SDC_x02:
|
|
SDCRet:
|
|
cmgi #CARDGATE
|
|
lw lr,[sp]
|
|
mfspr r26,AXC ; get context
|
|
shlui r26,r26,#3 ; *8
|
|
lw sp,sp_saves[r26] ; get back the stack
|
|
eret
|
|
|
|
;==============================================================================
|
|
; Real time clock BIOS
|
|
; BIOS interrupt #416
|
|
;
|
|
; Function
|
|
; 0x00 = get system tick
|
|
; 0x01 = get date/time
|
|
; 0x02 = set date/time
|
|
;==============================================================================
|
|
;
|
|
RTCSC:
|
|
mfspr r26,AXC ; get context
|
|
shlui r26,r26,#3 ; *8
|
|
sw sp,sp_saves[r26] ; save sp in save area
|
|
shlui r26,r26,#8 ; 2k for stack
|
|
mov sp,r26
|
|
addui sp,sp,#0x100008000 ; base stacks address
|
|
subui sp,sp,#8
|
|
sw lr,[sp]
|
|
;
|
|
beqi r1,#0x00,RTC_x00
|
|
beqi r1,#0x01,RTC_x01
|
|
RTC_x00:
|
|
mfspr r1,TICK
|
|
bra RTCRet
|
|
RTC_x01:
|
|
outw r0,DATETIME+24 ; trigger a snapshot
|
|
nop
|
|
inw r1,DATETIME ; get the snapshotted date and time
|
|
bra RTCRet
|
|
RTCRet:
|
|
lw lr,[sp]
|
|
mfspr r26,AXC ; get context
|
|
shlui r26,r26,#3 ; *8
|
|
lw sp,sp_saves[r26] ; get back the stack
|
|
eret
|
|
|
|
;==============================================================================
|
; Keyboard BIOS
|
; Keyboard BIOS
|
; BIOS interrupt #417
|
; BIOS interrupt #417
|
;
|
;
|
; Function in R1
|
; Function in R1
|
; 0 = initialize keyboard
|
; 0x00 = initialize keyboard
|
; 1 = set keyboard echo
|
; 0x01 = set keyboard echo
|
; 2 = get keyboard character
|
; 0x02 = get keyboard character from buffer
|
; 3 = check for key available
|
; 0x03 = check for key available in buffer
|
|
; 0x04 = check for key directly at keyboard port
|
|
; 0x05 = get keyboard character directly from keyboard port (blocks)
|
;==============================================================================
|
;==============================================================================
|
;
|
;
|
KeybdSC:
|
KeybdSC:
|
|
mfspr r26,AXC ; get context
|
|
shlui r26,r26,#3 ; *8
|
|
sw sp,sp_saves[r26] ; save sp in save area
|
|
shlui r26,r26,#8 ; 2k for stack
|
|
mov sp,r26
|
|
addui sp,sp,#0x100008000 ; base stacks address
|
subui sp,sp,#8
|
subui sp,sp,#8
|
sw lr,[sp]
|
sw lr,[sp]
|
bnei r1,#0,kbdsc1
|
kbdsc5:
|
|
omgi lr,#KEYBDGATE
|
|
bne lr,r0,kbdsc5
|
|
beqi r1,#0,kbd_x00
|
|
beqi r1,#1,kbd_x01
|
|
beqi r1,#2,kbd_x02
|
|
beqi r1,#3,kbd_x03
|
|
beqi r1,#4,kbd_x04
|
|
beqi r1,#5,kbd_x05
|
|
bra kbdscRet
|
|
kbd_x00:
|
call KeybdInit
|
call KeybdInit
|
bra kbdscRet
|
bra kbdscRet
|
kbdsc1:
|
kbd_x01:
|
bnei r1,#1,kbdsc2
|
|
mov r1,r2
|
mov r1,r2
|
call SetKeyboardEcho
|
call SetKeyboardEcho
|
bra kbdscRet
|
bra kbdscRet
|
kbdsc2:
|
kbd_x02:
|
bnei r1,#2,kbdsc3
|
|
call KeybdGetChar
|
call KeybdGetChar
|
bra kbdscRet
|
bra kbdscRet
|
kbdsc3:
|
kbd_x03:
|
bnei r1,#3,kbdsc4
|
|
call KeybdCheckForKey
|
call KeybdCheckForKey
|
bra kbdscRet
|
bra kbdscRet
|
kbdsc4:
|
kbd_x04:
|
|
call KeybdCheckForKeyDirect
|
|
bra kbdscRet
|
|
kbd_x05:
|
|
call KeybdGetCharDirect
|
|
bra kbdscRet
|
kbdscRet:
|
kbdscRet:
|
|
cmgi #KEYBDGATE
|
lw lr,[sp]
|
lw lr,[sp]
|
addui sp,sp,#8
|
mfspr r26,AXC ; get context
|
|
shlui r26,r26,#3 ; *8
|
|
lw sp,sp_saves[r26] ; get back the stack
|
eret
|
eret
|
|
|
;------------------------------------------------------------------------------
|
;------------------------------------------------------------------------------
|
; Initialize keyboard
|
; Initialize keyboard
|
;------------------------------------------------------------------------------
|
;------------------------------------------------------------------------------
|
Line 948... |
Line 1371... |
lw lr,8[sp]
|
lw lr,8[sp]
|
ret #16
|
ret #16
|
|
|
;==============================================================================
|
;==============================================================================
|
;==============================================================================
|
;==============================================================================
|
|
tmp_init:
|
|
; wait for the rst1626 to go low
|
|
lw r2,#10000000 ; retry for up to several seconds
|
|
tmp_init4:
|
|
beq r2,r0,tmp_init5
|
|
subui r2,r2,#1
|
|
inch r1,TMP+2 ; read the status reg
|
|
blt r1,r0,tmp_init4
|
|
tmp_init5:
|
|
|
|
lw r1,#0x51 ; Start temperature conversion
|
|
outc r1,TMP
|
|
|
|
; wait a bit for the trigger to take effect
|
|
lw r1,#2500
|
|
tmp_init1:
|
|
loop r1,tmp_init1
|
|
|
|
; wait for the rst1626 to go low
|
|
lw r2,#10000000 ; retry for up to several seconds
|
|
tmp_init2:
|
|
beq r2,r0,tmp_init3
|
|
subui r2,r2,#1
|
|
inch r1,TMP+2 ; read the status reg
|
|
blt r1,r0,tmp_init2
|
|
tmp_init3:
|
|
ret
|
|
|
|
tmp_read:
|
|
subui sp,sp,#24
|
|
sw lr,[sp]
|
|
sw r1,8[sp]
|
|
sw r2,16[sp]
|
|
|
|
lw r1,#25000000 ; wait about 1 second or so
|
|
tmp_read1:
|
|
loop r1,tmp_read1
|
|
lw r1,#0xAC ; issue read temperature conversion
|
|
outc r1,TMP
|
|
|
|
; wait a bit for the trigger to take effect
|
|
lw r1,#2500
|
|
tmp_read3:
|
|
loop r1,tmp_read3
|
|
|
|
; wait for the rst1626 to go low
|
|
lw r2,#10000000
|
|
tmp_read2:
|
|
inch r1,TMP+2 ; read the status reg
|
|
beq r2,r0,tmp_read4
|
|
subui r2,r2,#1
|
|
blt r1,r0,tmp_read2
|
|
tmp_read4:
|
|
inch r1,TMP+2 ; read the temperature
|
|
lw r2,#5 ; five digits
|
|
call DisplayNum
|
|
lw lr,[sp]
|
|
lw r1,8[sp]
|
|
lw r2,16[sp]
|
|
ret #24
|
|
|
|
;==============================================================================
|
|
;==============================================================================
|
;------------------------------------------------------------------------------
|
;------------------------------------------------------------------------------
|
; 100 Hz interrupt
|
; 100 Hz interrupt
|
; - takes care of "flashing" the cursor
|
; - takes care of "flashing" the cursor
|
;------------------------------------------------------------------------------
|
;------------------------------------------------------------------------------
|
;
|
;
|
Line 960... |
Line 1446... |
sw lr,[sp]
|
sw lr,[sp]
|
lea r2,TEXTSCR
|
lea r2,TEXTSCR
|
inch r1,334[r2]
|
inch r1,334[r2]
|
addui r1,r1,#1
|
addui r1,r1,#1
|
outc r1,334[r2]
|
outc r1,334[r2]
|
call DisplayDatetime
|
; call DisplayDatetime
|
call SelectNextToRunTCB
|
call SelectNextToRunTCB
|
call SwitchTask
|
call SwitchTask
|
sb r0,0xFFFF_FFFF_FFFF_0010 ; clear interrupt
|
outb r0,0xDCFFFC ; clear interrupt
|
; lw r1,TickIRQAddr
|
; lw r1,TickIRQAddr
|
; jal r31,[r1]
|
; jal r31,[r1]
|
; lw r1,Milliseconds
|
; lw r1,Milliseconds
|
; andi r1,r1,#0x0f
|
; andi r1,r1,#0x0f
|
; bnei r1,#5,p1001
|
; bnei r1,#5,p1001
|
Line 1184... |
Line 1670... |
inch r2,TEXT_ROWS[r3]
|
inch r2,TEXT_ROWS[r3]
|
mulu r2,r1,r2 ; calc number of chars to scroll
|
mulu r2,r1,r2 ; calc number of chars to scroll
|
subu r2,r2,r1 ; one less row
|
subu r2,r2,r1 ; one less row
|
lea r3,TEXTSCR
|
lea r3,TEXTSCR
|
scrup1:
|
scrup1:
|
inch r4,[r3+r1] ; indexed addressing example
|
inch r4,[r3+r1*2] ; indexed addressing example
|
outc r4,[r3]
|
outc r4,[r3]
|
addui r3,r3,#2
|
addui r3,r3,#2
|
loop r2,scrup1
|
loop r2,scrup1
|
|
|
lea r3,TEXTREG
|
lea r3,TEXTREG
|
Line 1235... |
Line 1721... |
andi r1,r1,#0x00ff
|
andi r1,r1,#0x00ff
|
bltui r1,#'A',atoscr1
|
bltui r1,#'A',atoscr1
|
bleui r1,#'Z',atoscr1
|
bleui r1,#'Z',atoscr1
|
bgtui r1,#'z',atoscr1
|
bgtui r1,#'z',atoscr1
|
bltui r1,#'a',atoscr1
|
bltui r1,#'a',atoscr1
|
subi r1,r1,#0x60
|
subui r1,r1,#0x60
|
atoscr1:
|
atoscr1:
|
ori r1,r1,#0x100
|
ori r1,r1,#0x100
|
ret
|
ret
|
|
|
;------------------------------------------------------------------------------
|
;------------------------------------------------------------------------------
|
Line 1259... |
Line 1745... |
; Destroys r1,r2,r3
|
; Destroys r1,r2,r3
|
; r1 = screen location
|
; r1 = screen location
|
;------------------------------------------------------------------------------
|
;------------------------------------------------------------------------------
|
;
|
;
|
CalcScreenLoc:
|
CalcScreenLoc:
|
lc r1,CursorRow
|
lbu r1,CursorRow
|
andi r1,r1,#0x7f
|
andi r1,r1,#0x7f
|
lea r3,TEXTREG
|
lea r3,TEXTREG
|
inch r2,TEXT_COLS[r3]
|
inch r2,TEXT_COLS[r3]
|
mulu r2,r2,r1
|
mulu r2,r2,r1
|
lc r1,CursorCol
|
lbu r1,CursorCol
|
andi r1,r1,#0x7f
|
andi r1,r1,#0x7f
|
addu r2,r2,r1
|
addu r2,r2,r1
|
outc r2,TEXT_CURPOS[r3]
|
outc r2,TEXT_CURPOS[r3]
|
shli r2,r2,#1
|
shlui r2,r2,#1
|
addui r1,r2,#TEXTSCR ; r1 = screen location
|
addui r1,r2,#TEXTSCR ; r1 = screen location
|
ret
|
ret
|
|
|
;------------------------------------------------------------------------------
|
;------------------------------------------------------------------------------
|
; Display a character on the screen
|
; Display a character on the screen
|
Line 1284... |
Line 1770... |
subui sp,sp,#32
|
subui sp,sp,#32
|
sw r1,[sp]
|
sw r1,[sp]
|
sw r2,8[sp]
|
sw r2,8[sp]
|
sw r3,16[sp]
|
sw r3,16[sp]
|
sw lr,24[sp]
|
sw lr,24[sp]
|
sc r0,CursorCol ; just set cursor column to zero on a CR
|
sb r0,CursorCol ; just set cursor column to zero on a CR
|
bra dcx7
|
bra dcx7
|
dccr:
|
dccr:
|
|
; beqi r1,#CTRLK,dccr1
|
bnei r1,#0x91,dcx6 ; cursor right ?
|
bnei r1,#0x91,dcx6 ; cursor right ?
|
|
dccr1:
|
subui sp,sp,#32
|
subui sp,sp,#32
|
sw r1,[sp]
|
sw r1,[sp]
|
sw r2,8[sp]
|
sw r2,8[sp]
|
sw r3,16[sp]
|
sw r3,16[sp]
|
sw lr,24[sp]
|
sw lr,24[sp]
|
lc r2,CursorCol
|
lbu r2,CursorCol
|
beqi r2,#56,dcx7
|
beqi r2,#56,dcx7
|
addui r2,r2,#1
|
addui r2,r2,#1
|
sc r2,CursorCol
|
sb r2,CursorCol
|
dcx7:
|
dcx7:
|
call CalcScreenLoc
|
call CalcScreenLoc
|
lw lr,24[sp]
|
lw lr,24[sp]
|
lw r3,16[sp]
|
lw r3,16[sp]
|
lw r2,8[sp]
|
lw r2,8[sp]
|
lw r1,[sp]
|
lw r1,[sp]
|
ret #32
|
ret #32
|
dcx6:
|
dcx6:
|
|
; beqi r1,#CTRLI,dccu1
|
bnei r1,#0x90,dcx8 ; cursor up ?
|
bnei r1,#0x90,dcx8 ; cursor up ?
|
|
dccu1:
|
subui sp,sp,#32
|
subui sp,sp,#32
|
sw r1,[sp]
|
sw r1,[sp]
|
sw r2,8[sp]
|
sw r2,8[sp]
|
sw r3,16[sp]
|
sw r3,16[sp]
|
sw lr,24[sp]
|
sw lr,24[sp]
|
lc r2,CursorRow
|
lbu r2,CursorRow
|
beqi r2,#0,dcx7
|
beqi r2,#0,dcx7
|
subui r2,r2,#1
|
subui r2,r2,#1
|
sc r2,CursorRow
|
sb r2,CursorRow
|
bra dcx7
|
bra dcx7
|
dcx8:
|
dcx8:
|
|
; beqi r1,#CTRLJ,dccl1
|
bnei r1,#0x93,dcx9 ; cursor left ?
|
bnei r1,#0x93,dcx9 ; cursor left ?
|
|
dccl1:
|
subui sp,sp,#32
|
subui sp,sp,#32
|
sw r1,[sp]
|
sw r1,[sp]
|
sw r2,8[sp]
|
sw r2,8[sp]
|
sw r3,16[sp]
|
sw r3,16[sp]
|
sw lr,24[sp]
|
sw lr,24[sp]
|
lc r2,CursorCol
|
lbu r2,CursorCol
|
beqi r2,#0,dcx7
|
beqi r2,#0,dcx7
|
subui r2,r2,#1
|
subui r2,r2,#1
|
sc r2,CursorCol
|
sb r2,CursorCol
|
bra dcx7
|
bra dcx7
|
dcx9:
|
dcx9:
|
|
; beqi r1,#CTRLM,dccd1
|
bnei r1,#0x92,dcx10 ; cursor down ?
|
bnei r1,#0x92,dcx10 ; cursor down ?
|
|
dccd1:
|
subui sp,sp,#32
|
subui sp,sp,#32
|
sw r1,[sp]
|
sw r1,[sp]
|
sw r2,8[sp]
|
sw r2,8[sp]
|
sw r3,16[sp]
|
sw r3,16[sp]
|
sw lr,24[sp]
|
sw lr,24[sp]
|
lc r2,CursorRow
|
lbu r2,CursorRow
|
beqi r2,#30,dcx7
|
beqi r2,#30,dcx7
|
addui r2,r2,#1
|
addui r2,r2,#1
|
sc r2,CursorRow
|
sb r2,CursorRow
|
bra dcx7
|
bra dcx7
|
dcx10:
|
dcx10:
|
bnei r1,#0x94,dcx11 ; cursor home ?
|
bnei r1,#0x94,dcx11 ; cursor home ?
|
subui sp,sp,#32
|
subui sp,sp,#32
|
sw r1,[sp]
|
sw r1,[sp]
|
sw r2,8[sp]
|
sw r2,8[sp]
|
sw r3,16[sp]
|
sw r3,16[sp]
|
sw lr,24[sp]
|
sw lr,24[sp]
|
lc r2,CursorCol
|
lbu r2,CursorCol
|
beq r2,r0,dcx12
|
beq r2,r0,dcx12
|
sc r0,CursorCol
|
sb r0,CursorCol
|
bra dcx7
|
bra dcx7
|
dcx12:
|
dcx12:
|
sc r0,CursorRow
|
sb r0,CursorRow
|
bra dcx7
|
bra dcx7
|
dcx11:
|
dcx11:
|
subui sp,sp,#48
|
subui sp,sp,#48
|
sw r1,[sp]
|
sw r1,[sp]
|
sw r2,8[sp]
|
sw r2,8[sp]
|
Line 1364... |
Line 1858... |
sw r4,24[sp]
|
sw r4,24[sp]
|
sw r5,32[sp]
|
sw r5,32[sp]
|
sw lr,40[sp]
|
sw lr,40[sp]
|
bnei r1,#0x99,dcx13 ; delete ?
|
bnei r1,#0x99,dcx13 ; delete ?
|
call CalcScreenLoc
|
call CalcScreenLoc
|
or r3,r0,r1 ; r3 = screen location
|
mov r3,r1 ; r3 = screen location
|
lc r1,CursorCol ; r1 = cursor column
|
lbu r1,CursorCol ; r1 = cursor column
|
bra dcx5
|
bra dcx5
|
dcx13:
|
dcx13:
|
bnei r1,#CTRLH,dcx3 ; backspace ?
|
bnei r1,#CTRLH,dcx3 ; backspace ?
|
lc r2,CursorCol
|
lbu r2,CursorCol
|
beq r2,r0,dcx4
|
beq r2,r0,dcx4
|
subui r2,r2,#1
|
subui r2,r2,#1
|
sc r2,CursorCol
|
sb r2,CursorCol
|
call CalcScreenLoc ; a0 = screen location
|
call CalcScreenLoc ; a0 = screen location
|
or r3,r0,r1 ; r3 = screen location
|
mov r3,r1 ; r3 = screen location
|
lc r1,CursorCol
|
lbu r1,CursorCol
|
dcx5:
|
dcx5:
|
inch r2,2[r3]
|
inch r2,2[r3]
|
outc r2,[r3]
|
outc r2,[r3]
|
addui r3,r3,#2
|
addui r3,r3,#2
|
addui r1,r1,#1
|
addui r1,r1,#1
|
Line 1390... |
Line 1884... |
call AsciiToScreen
|
call AsciiToScreen
|
outc r1,-2[r3]
|
outc r1,-2[r3]
|
bra dcx4
|
bra dcx4
|
dcx3:
|
dcx3:
|
beqi r1,#'\n',dclf ; linefeed ?
|
beqi r1,#'\n',dclf ; linefeed ?
|
or r4,r0,r1 ; save r1 in r4
|
mov r4,r1 ; save r1 in r4
|
call CalcScreenLoc ; r1 = screen location
|
call CalcScreenLoc ; r1 = screen location
|
or r3,r0,r1 ; r3 = screen location
|
mov r3,r1 ; r3 = screen location
|
or r1,r0,r4 ; restore r1
|
mov r1,r4 ; restore r1
|
call AsciiToScreen ; convert ascii char to screen char
|
call AsciiToScreen ; convert ascii char to screen char
|
outc r1,[r3]
|
outc r1,[r3]
|
|
lc r1,CharColor
|
|
outc r1,0x10000[r3]
|
call IncCursorPos
|
call IncCursorPos
|
bra dcx4
|
bra dcx4
|
dclf:
|
dclf:
|
call IncCursorRow
|
call IncCursorRow
|
dcx4:
|
dcx4:
|
Line 1420... |
Line 1916... |
subui sp,sp,#32
|
subui sp,sp,#32
|
sw r1,[sp]
|
sw r1,[sp]
|
sw r2,8[sp]
|
sw r2,8[sp]
|
sw r3,16[sp]
|
sw r3,16[sp]
|
sw lr,24[sp]
|
sw lr,24[sp]
|
lc r1,CursorCol
|
lbu r1,CursorCol
|
addui r1,r1,#1
|
addui r1,r1,#1
|
sc r1,CursorCol
|
sb r1,CursorCol
|
inch r2,TEXTREG+TEXT_COLS
|
inch r2,TEXTREG+TEXT_COLS
|
bleu r1,r2,icc1
|
bleu r1,r2,icc1
|
sc r0,CursorCol ; column = 0
|
sb r0,CursorCol ; column = 0
|
bra icr1
|
bra icr1
|
IncCursorRow:
|
IncCursorRow:
|
subui sp,sp,#32
|
subui sp,sp,#32
|
sw r1,[sp]
|
sw r1,[sp]
|
sw r2,8[sp]
|
sw r2,8[sp]
|
sw r3,16[sp]
|
sw r3,16[sp]
|
sw lr,24[sp]
|
sw lr,24[sp]
|
icr1:
|
icr1:
|
lc r1,CursorRow
|
lbu r1,CursorRow
|
addui r1,r1,#1
|
addui r1,r1,#1
|
sc r1,CursorRow
|
sb r1,CursorRow
|
inch r2,TEXTREG+TEXT_ROWS
|
inch r2,TEXTREG+TEXT_ROWS
|
bleu r1,r2,icc1
|
bleu r1,r2,icc1
|
subui r2,r2,#1 ; backup the cursor row, we are scrolling up
|
subui r2,r2,#1 ; backup the cursor row, we are scrolling up
|
sc r2,CursorRow
|
sb r2,CursorRow
|
call ScrollUp
|
call ScrollUp
|
icc1:
|
icc1:
|
call CalcScreenLoc
|
call CalcScreenLoc
|
lw lr,24[sp]
|
lw lr,24[sp]
|
lw r3,16[sp]
|
lw r3,16[sp]
|
Line 1455... |
Line 1951... |
;------------------------------------------------------------------------------
|
;------------------------------------------------------------------------------
|
; Display a string on the screen.
|
; Display a string on the screen.
|
;------------------------------------------------------------------------------
|
;------------------------------------------------------------------------------
|
;
|
;
|
DisplayString:
|
DisplayString:
|
subi sp,sp,#24
|
subui sp,sp,#24
|
sw r1,[sp]
|
sw r1,[sp]
|
sw r2,8[sp]
|
sw r2,8[sp]
|
sw lr,16[sp]
|
sw lr,16[sp]
|
mov r2,r1 ; r2 = pointer to string
|
mov r2,r1 ; r2 = pointer to string
|
dspj1:
|
dspj1:
|
Line 1480... |
Line 1976... |
call DisplayString
|
call DisplayString
|
lw r31,[r30]
|
lw r31,[r30]
|
addui r30,r30,#8
|
addui r30,r30,#8
|
|
|
CRLF:
|
CRLF:
|
subui r30,r30,#16
|
subui sp,sp,#16
|
sw r1,[sp]
|
sw r1,[sp]
|
sw lr,8[sp]
|
sw lr,8[sp]
|
setlo r1,#'\r'
|
setlo r1,#'\r'
|
call DisplayChar
|
call DisplayChar
|
setlo r1,#'\n'
|
setlo r1,#'\n'
|
call DisplayChar
|
call DisplayChar
|
lw lr,8[sp]
|
lw lr,8[sp]
|
lw r1,[sp]
|
lw r1,[sp]
|
ret #16
|
ret #16
|
|
|
|
; Call the Tiny BASIC routine to display a number
|
|
;
|
|
DisplayNum:
|
|
jmp PRTNUM
|
|
|
;------------------------------------------------------------------------------
|
;------------------------------------------------------------------------------
|
; Display nybble in r1
|
; Display nybble in r1
|
;------------------------------------------------------------------------------
|
;------------------------------------------------------------------------------
|
;
|
;
|
DisplayNybble:
|
DisplayNybble:
|
Line 1526... |
Line 2027... |
lw lr,8[sp]
|
lw lr,8[sp]
|
lw r1,[sp]
|
lw r1,[sp]
|
ret #16
|
ret #16
|
|
|
;------------------------------------------------------------------------------
|
;------------------------------------------------------------------------------
|
|
; Display the char in r1
|
|
;------------------------------------------------------------------------------
|
|
;
|
|
DisplayCharr:
|
|
subui sp,sp,#16
|
|
sw r1,[sp]
|
|
sw lr,8[sp]
|
|
rori r1,r1,#8
|
|
call DisplayByte
|
|
roli r1,r1,#8
|
|
call DisplayByte
|
|
lw lr,8[sp]
|
|
lw r1,[sp]
|
|
ret #16
|
|
|
|
;------------------------------------------------------------------------------
|
|
; Display the half-word in r1
|
|
;------------------------------------------------------------------------------
|
|
;
|
|
DisplayHalf:
|
|
subui sp,sp,#16
|
|
sw r1,[sp]
|
|
sw lr,8[sp]
|
|
rori r1,r1,#16
|
|
call DisplayCharr
|
|
roli r1,r1,#16
|
|
call DisplayCharr
|
|
lw lr,8[sp]
|
|
lw r1,[sp]
|
|
ret #16
|
|
|
|
;------------------------------------------------------------------------------
|
; Display the 64 bit word in r1
|
; Display the 64 bit word in r1
|
;------------------------------------------------------------------------------
|
;------------------------------------------------------------------------------
|
;
|
;
|
DisplayWord:
|
DisplayWord:
|
subui sp,sp,#24
|
subui sp,sp,#24
|
Line 1549... |
Line 2082... |
;------------------------------------------------------------------------------
|
;------------------------------------------------------------------------------
|
; Display memory pointed to by r2.
|
; Display memory pointed to by r2.
|
; destroys r1,r3
|
; destroys r1,r3
|
;------------------------------------------------------------------------------
|
;------------------------------------------------------------------------------
|
;
|
;
|
DisplayMem:
|
DisplayMemB:
|
subui sp,sp,#24
|
subui sp,sp,#24
|
sw r1,[sp]
|
sw r1,[sp]
|
sw r3,8[sp]
|
sw r3,8[sp]
|
sw lr,16[sp]
|
sw lr,16[sp]
|
setlo r1,#':'
|
setlo r1,#':'
|
Line 1562... |
Line 2095... |
call DisplayWord
|
call DisplayWord
|
setlo r3,#7
|
setlo r3,#7
|
dspmem1:
|
dspmem1:
|
setlo r1,#' '
|
setlo r1,#' '
|
call DisplayChar
|
call DisplayChar
|
lb r1,[r2]
|
lbu r1,[r2]
|
call DisplayByte
|
call DisplayByte
|
addui r2,r2,#1
|
addui r2,r2,#1
|
loop r3,dspmem1
|
loop r3,dspmem1
|
call CRLF
|
call CRLF
|
lw lr,16[sp]
|
lw lr,16[sp]
|
lw r3,8[sp]
|
lw r3,8[sp]
|
lw r1,[sp]
|
lw r1,[sp]
|
ret #24
|
ret #24
|
|
|
|
DisplayMemC:
|
|
subui sp,sp,#24
|
|
sw r1,[sp]
|
|
sw r3,8[sp]
|
|
sw lr,16[sp]
|
|
setlo r1,#':'
|
|
call DisplayChar
|
|
mov r1,r2
|
|
call DisplayWord
|
|
setlo r3,#3
|
|
dspmemc1:
|
|
setlo r1,#' '
|
|
call DisplayChar
|
|
lcu r1,[r2]
|
|
call DisplayCharr
|
|
addui r2,r2,#2
|
|
loop r3,dspmemc1
|
|
call CRLF
|
|
lw lr,16[sp]
|
|
lw r3,8[sp]
|
|
lw r1,[sp]
|
|
ret #24
|
|
|
|
DisplayMemW:
|
|
subui sp,sp,#24
|
|
sw r1,[sp]
|
|
sw lr,16[sp]
|
|
setlo r1,#':'
|
|
call DisplayChar
|
|
mov r1,r2
|
|
call DisplayWord
|
|
setlo r1,#' '
|
|
call DisplayChar
|
|
lw r1,[r2]
|
|
call DisplayWord
|
|
addui r2,r2,#8
|
|
call CRLF
|
|
lw lr,16[sp]
|
|
lw r1,[sp]
|
|
ret #24
|
|
|
;------------------------------------------------------------------------------
|
;------------------------------------------------------------------------------
|
; Converts binary number in r1 into BCD number in r2 and r1.
|
; Converts binary number in r1 into BCD number in r2 and r1.
|
;------------------------------------------------------------------------------
|
;------------------------------------------------------------------------------
|
;
|
;
|
BinToBCD:
|
BinToBCD:
|
Line 1587... |
Line 2161... |
sw r7,32[sp]
|
sw r7,32[sp]
|
sw r8,40[sp]
|
sw r8,40[sp]
|
setlo r2,#10
|
setlo r2,#10
|
setlo r8,#19 ; number of digits to produce - 1
|
setlo r8,#19 ; number of digits to produce - 1
|
bta1:
|
bta1:
|
mod r3,r1,r2
|
modu r3,r1,r2
|
shli r3,r3,#60 ; shift result to uppermost bits
|
shli r3,r3,#60 ; shift result to uppermost bits
|
shli r7,r5,#60 ; copy low order nybble of r5 to r4 topmost nybble
|
shli r7,r5,#60 ; copy low order nybble of r5 to r4 topmost nybble
|
shrui r4,r4,#4
|
shrui r4,r4,#4
|
or r4,r4,r7
|
or r4,r4,r7
|
shrui r5,r5,#4
|
shrui r5,r5,#4
|
Line 1693... |
Line 2267... |
lw lr,48[sp]
|
lw lr,48[sp]
|
ret #56
|
ret #56
|
|
|
|
|
;==============================================================================
|
;==============================================================================
|
|
; System Monitor Program
|
;==============================================================================
|
;==============================================================================
|
|
;
|
Monitor:
|
Monitor:
|
lea sp,STACKTOP0 ; top of stack; reset the stack pointer
|
lea sp,STACKTOP0 ; top of stack; reset the stack pointer
|
sb r0,KeybdEcho ; turn off keyboard echo
|
sb r0,KeybdEcho ; turn off keyboard echo
|
PromptLn:
|
PromptLn:
|
call CRLF
|
call CRLF
|
Line 1705... |
Line 2281... |
call DisplayChar
|
call DisplayChar
|
|
|
; Get characters until a CR is keyed
|
; Get characters until a CR is keyed
|
;
|
;
|
Prompt3:
|
Prompt3:
|
|
; lw r1,#2 ; get keyboard character
|
|
; syscall #417
|
call KeybdGetChar
|
call KeybdGetChar
|
beqi r1,#-1,Prompt3 ; wait for a character
|
beqi r1,#-1,Prompt3 ; wait for a character
|
beqi r1,#CR,Prompt1
|
beqi r1,#CR,Prompt1
|
call DisplayChar
|
call DisplayChar
|
bra Prompt3
|
bra Prompt3
|
|
|
; Process the screen line that the CR was keyed on
|
; Process the screen line that the CR was keyed on
|
;
|
;
|
Prompt1:
|
Prompt1:
|
sc r0,CursorCol ; go back to the start of the line
|
sb r0,CursorCol ; go back to the start of the line
|
call CalcScreenLoc ; r1 = screen memory location
|
call CalcScreenLoc ; r1 = screen memory location
|
or r3,r1,r0
|
mov r3,r1
|
inch r1,[r3]
|
inch r1,[r3]
|
addui r3,r3,#2
|
addui r3,r3,#2
|
call ScreenToAscii
|
call ScreenToAscii
|
bnei r1,#'$',Prompt2 ; skip over '$' prompt character
|
bnei r1,#'$',Prompt2 ; skip over '$' prompt character
|
inch r1,[r3]
|
inch r1,[r3]
|
Line 1730... |
Line 2308... |
; Dispatch based on command character
|
; Dispatch based on command character
|
;
|
;
|
Prompt2:
|
Prompt2:
|
beqi r1,#':',Editmem ; $: - edit memory
|
beqi r1,#':',Editmem ; $: - edit memory
|
beqi r1,#'D',Dumpmem ; $D - dump memory
|
beqi r1,#'D',Dumpmem ; $D - dump memory
|
beqi r1,#'B',CSTART ; $B - start tiny basic
|
beqi r1,#'F',Fillmem ; $F - fill memory
|
|
Prompt7:
|
|
bnei r1,#'B',Prompt4 ; $B - start tiny basic
|
|
jmp CSTART
|
|
Prompt4:
|
beqi r1,#'J',ExecuteCode ; $J - execute code
|
beqi r1,#'J',ExecuteCode ; $J - execute code
|
beqi r1,#'L',LoadS19 ; $L - load S19 file
|
bnei r1,#'L',Prompt9 ; $L - load S19 file
|
beqi r1,#'?',DisplayHelp ; $? - display help
|
jmp LoadSector
|
|
Prompt9:
|
|
bnei r1,#'?',Prompt10 ; $? - display help
|
|
lea r1,HelpMsg
|
|
call DisplayString
|
|
jmp Monitor
|
|
Prompt10:
|
beqi r1,#'C',TestCLS ; $C - clear screen
|
beqi r1,#'C',TestCLS ; $C - clear screen
|
beqi r1,#'R',RandomLinesCall
|
bnei r1,#'R',Prompt12
|
beqi r1,#'I',Invaders
|
jmp RandomLinesCall
|
beqi r1,#'P',Piano
|
Prompt12:
|
bra Monitor
|
bnei r1,#'I',Prompt13
|
|
jmp Invaders
|
|
Prompt13:
|
|
bnei r1,#'P',Prompt14
|
|
jmp Piano
|
|
Prompt14:
|
|
bnei r1,#'T',Prompt15
|
|
call tmp_read
|
|
Prompt15:
|
|
jmp Monitor
|
|
|
RandomLinesCall:
|
RandomLinesCall:
|
call RandomLines
|
call RandomLines
|
bra Monitor
|
jmp Monitor
|
|
|
TestCLS:
|
TestCLS:
|
inch r1,[r3]
|
inch r1,[r3]
|
addui r3,r3,#2
|
addui r3,r3,#2
|
call ScreenToAscii
|
call ScreenToAscii
|
Line 1757... |
Line 2354... |
bnei r1,#'S',Monitor
|
bnei r1,#'S',Monitor
|
call ClearScreen
|
call ClearScreen
|
sb r0,CursorCol
|
sb r0,CursorCol
|
sb r0,CursorRow
|
sb r0,CursorRow
|
call CalcScreenLoc
|
call CalcScreenLoc
|
bra Monitor
|
jmp Monitor
|
|
|
DisplayHelp:
|
|
setlo r1,HelpMsg
|
|
call DisplayString
|
|
bra Monitor
|
|
|
|
align 16
|
|
HelpMsg:
|
HelpMsg:
|
db "? = Display help",CR,LF
|
db "? = Display help",CR,LF
|
db "CLS = clear screen",CR,LF
|
db "CLS = clear screen",CR,LF
|
db ": = Edit memory bytes",CR,LF
|
db ": = Edit memory bytes",CR,LF
|
db "L = Load S19 file",CR,LF
|
db "L = Load S19 file",CR,LF
|
db "D = Dump memory",CR,LF
|
db "D[B|C|H|W] = Dump memory",CR,LF
|
|
db "F[B|C|H|W] = Fill memory",CR,LF
|
db "B = start tiny basic",CR,LF
|
db "B = start tiny basic",CR,LF
|
db "J = Jump to code",CR,LF
|
db "J = Jump to code",CR,LF
|
db "I = Invaders",CR,LF
|
db "I = Invaders",CR,LF
|
db "R = Random lines",CR,LF
|
db "R = Random lines",CR,LF
|
|
db "T = get temperature",CR,LF
|
db "P = Piano",CR,LF,0
|
db "P = Piano",CR,LF,0
|
align 16
|
align 4
|
|
|
;------------------------------------------------------------------------------
|
;------------------------------------------------------------------------------
|
; Ignore blanks in the input
|
; Ignore blanks in the input
|
; r3 = text pointer
|
; r3 = text pointer
|
; r1 destroyed
|
; r1 destroyed
|
Line 1811... |
Line 2404... |
call ignBlanks
|
call ignBlanks
|
call GetHexNumber
|
call GetHexNumber
|
sb r1,[r5]
|
sb r1,[r5]
|
addui r5,r5,#1
|
addui r5,r5,#1
|
loop r4,edtmem1
|
loop r4,edtmem1
|
bra Monitor
|
jmp Monitor
|
|
|
;------------------------------------------------------------------------------
|
;------------------------------------------------------------------------------
|
; Execute code at the specified address.
|
; Execute code at the specified address.
|
;------------------------------------------------------------------------------
|
;------------------------------------------------------------------------------
|
;
|
;
|
ExecuteCode:
|
ExecuteCode:
|
call ignBlanks
|
call ignBlanks
|
call GetHexNumber
|
call GetHexNumber
|
jal r31,[r1]
|
jal r31,[r1]
|
bra Monitor
|
jmp Monitor
|
|
|
|
LoadSector:
|
|
call ignBlanks
|
|
call GetHexNumber
|
|
lw r2,#0x3800
|
|
call spi_read_sector
|
|
jmp Monitor
|
|
|
;------------------------------------------------------------------------------
|
;------------------------------------------------------------------------------
|
; Do a memory dump of the requested location.
|
; Do a memory dump of the requested location.
|
;------------------------------------------------------------------------------
|
;------------------------------------------------------------------------------
|
;
|
;
|
DumpMem:
|
DumpMem:
|
|
inch r1,[r3]
|
|
addui r3,r3,#2
|
|
call ScreenToAscii
|
|
mov r6,r1 ; r6 = fill type character
|
call ignBlanks
|
call ignBlanks
|
call GetHexNumber
|
call GetHexNumber ; get start address of dump
|
mov r2,r1
|
mov r2,r1
|
|
call ignBlanks
|
|
call GetHexNumber ; get number of bytes to dump
|
|
shrui r1,r1,#3 ; 1/8 as many dump rows
|
|
bnei r1,#0,Dumpmem2
|
|
lw r1,#1 ; dump at least one row
|
|
Dumpmem2:
|
call CRLF
|
call CRLF
|
call DisplayMem
|
beqi r6,#'W',DumpmemW
|
call DisplayMem
|
; beqi r6,#'H',DumpmemH
|
call DisplayMem
|
beqi r6,#'C',DumpmemC
|
call DisplayMem
|
DumpmemB:
|
call DisplayMem
|
call DisplayMemB
|
call DisplayMem
|
loop r1,DumpmemB
|
call DisplayMem
|
jmp Monitor
|
call DisplayMem
|
DumpmemC:
|
|
call DisplayMemC
|
|
loop r1,DumpmemC
|
|
jmp Monitor
|
|
DumpmemW:
|
|
call DisplayMemW
|
|
loop r1,DumpmemW
|
|
jmp Monitor
|
|
|
|
; call DisplayMem
|
|
; call DisplayMem
|
|
; call DisplayMem
|
|
; call DisplayMem
|
|
; call DisplayMem
|
|
; call DisplayMem
|
|
; call DisplayMem
|
bra Monitor
|
bra Monitor
|
|
|
|
Fillmem:
|
|
inch r1,[r3]
|
|
addui r3,r3,#2
|
|
call ScreenToAscii
|
|
mov r6,r1 ; r6 = fill type character
|
|
call ignBlanks
|
|
call GetHexNumber ; get start address of dump
|
|
mov r2,r1
|
|
call ignBlanks
|
|
call GetHexNumber ; get number of bytes to fill
|
|
mov r5,r1
|
|
call ignBlanks
|
|
call GetHexNumber ; get the fill byte
|
|
beqi r6,#'C',FillmemC
|
|
beqi r6,#'H',FillmemH
|
|
beqi r6,#'W',FillmemW
|
|
FillmemB:
|
|
sb r1,[r2]
|
|
addui r2,r2,#1
|
|
loop r5,FillmemB
|
|
jmp Monitor
|
|
FillmemC:
|
|
sc r1,[r2]
|
|
addui r2,r2,#2
|
|
loop r5,FillmemC
|
|
jmp Monitor
|
|
FillmemH:
|
|
sh r1,[r2]
|
|
addui r2,r2,#4
|
|
loop r5,FillmemH
|
|
jmp Monitor
|
|
FillmemW:
|
|
sw r1,[r2]
|
|
addui r2,r2,#8
|
|
loop r5,FillmemW
|
|
jmp Monitor
|
|
|
;------------------------------------------------------------------------------
|
;------------------------------------------------------------------------------
|
; Get a hexidecimal number. Maximum of sixteen digits.
|
; Get a hexidecimal number. Maximum of sixteen digits.
|
; R3 = text pointer (updated)
|
; R3 = text pointer (updated)
|
; R1 = hex number
|
; R1 = hex number
|
;------------------------------------------------------------------------------
|
;------------------------------------------------------------------------------
|
Line 1979... |
Line 2641... |
sw r5,S19StartAddress
|
sw r5,S19StartAddress
|
bra Monitor
|
bra Monitor
|
ProcessS9:
|
ProcessS9:
|
call S19Get16BitAddress
|
call S19Get16BitAddress
|
sw r5,S19StartAddress
|
sw r5,S19StartAddress
|
bra Monitor
|
jmp Monitor
|
|
|
S19Get16BitAddress:
|
S19Get16BitAddress:
|
subui sp,sp,#8
|
subui sp,sp,#8
|
sw r31,[sp]
|
sw r31,[sp]
|
call sGetChar
|
call sGetChar
|
Line 2061... |
Line 2723... |
ret #8
|
ret #8
|
|
|
;--------------------------------------------------------------------------
|
;--------------------------------------------------------------------------
|
; Draw random lines on the bitmap screen.
|
; Draw random lines on the bitmap screen.
|
;--------------------------------------------------------------------------
|
;--------------------------------------------------------------------------
|
|
;
|
RandomLines:
|
RandomLines:
|
subui sp,sp,#24
|
subui sp,sp,#24
|
sw r1,[sp]
|
sw r1,[sp]
|
sw r3,8[sp]
|
sw r3,8[sp]
|
sw lr,16[sp]
|
sw lr,16[sp]
|
|
sw r0,ctx3start ; prevent restarting context over and over again
|
rl5:
|
rl5:
|
gran
|
gran
|
mfspr r1,rand ; select a random color
|
mfspr r1,rand ; select a random color
|
outh r1,GACCEL
|
outh r1,GACCEL
|
rl1: ; random X0
|
rl1: ; random X0
|
gran
|
gran
|
mfspr r1,rand
|
mfspr r1,rand
|
lw r3,#1364
|
lw r3,#1364
|
mod r1,r1,r3
|
modu r1,r1,r3
|
outh r1,GACCEL+8
|
outh r1,GACCEL+8
|
rl2: ; random X1
|
rl2: ; random X1
|
gran
|
gran
|
mfspr r1,rand
|
mfspr r1,rand
|
lw r3,#1364
|
lw r3,#1364
|
mod r1,r1,r3
|
modu r1,r1,r3
|
outh r1,GACCEL+16
|
outh r1,GACCEL+16
|
rl3: ; random Y0
|
rl3: ; random Y0
|
gran
|
gran
|
mfspr r1,rand
|
mfspr r1,rand
|
lw r3,#768
|
lw r3,#768
|
mod r1,r1,r3
|
modu r1,r1,r3
|
outh r1,GACCEL+12
|
outh r1,GACCEL+12
|
rl4: ; random Y1
|
rl4: ; random Y1
|
gran
|
gran
|
mfspr r1,rand
|
mfspr r1,rand
|
lw r3,#768
|
lw r3,#768
|
mod r1,r1,r3
|
modu r1,r1,r3
|
outh r1,GACCEL+20
|
outh r1,GACCEL+20
|
setlo r1,#2 ; draw line command
|
setlo r1,#2 ; draw line command
|
outh r1,GACCEL+60
|
outh r1,GACCEL+60
|
rl8:
|
rl8:
|
call KeybdGetChar
|
; call KeybdGetChar
|
beqi r1,#CTRLC,rl7
|
; beqi r1,#CTRLC,rl7
|
beqi r1,#'r',rl5
|
inch r1,GACCEL+56 ; ensure controller is in IDLE state
|
bra rl8
|
bne r1,r0,rl8
|
|
bra rl5
|
rl7:
|
rl7:
|
lw lr,16[sp]
|
lw lr,16[sp]
|
lw r3,8[sp]
|
lw r3,8[sp]
|
lw r1,[sp]
|
lw r1,[sp]
|
ret #24
|
ret #24
|
Line 2136... |
Line 2801... |
sac974:
|
sac974:
|
outc r0,AC97+0x26 ; trigger a read of register 26 (status reg)
|
outc r0,AC97+0x26 ; trigger a read of register 26 (status reg)
|
sac971: ; wait for status to register 0xF (all ready)
|
sac971: ; wait for status to register 0xF (all ready)
|
call KeybdGetChar ; see if we needed to CTRL-C
|
call KeybdGetChar ; see if we needed to CTRL-C
|
beqi r1,#CTRLC,sac973
|
beqi r1,#CTRLC,sac973
|
outc r1,AC97+0x68 ; wait for dirty bit to clear
|
inch r1,AC97+0x68 ; wait for dirty bit to clear
|
bne r1,r0,sac971
|
bne r1,r0,sac971
|
outc r1,AC97+0x26 ; check status at reg h26, wait for
|
inch r1,AC97+0x26 ; check status at reg h26, wait for
|
andi r1,r1,#0x0F ; analogue to be ready
|
andi r1,r1,#0x0F ; analogue to be ready
|
bnei r1,#0x0F,sac974
|
bnei r1,#0x0F,sac974
|
sac973:
|
sac973:
|
outc r0,AC97+2 ; master volume, 0db attenuation, mute off
|
outc r0,AC97+2 ; master volume, 0db attenuation, mute off
|
outc r0,AC97+4 ; headphone volume, 0db attenuation, mute off
|
outc r0,AC97+4 ; headphone volume, 0db attenuation, mute off
|
Line 2151... |
Line 2816... |
setlo r1,#0x8000 ; bypass 3D sound
|
setlo r1,#0x8000 ; bypass 3D sound
|
outc r1,AC97+0x20
|
outc r1,AC97+0x20
|
sac972:
|
sac972:
|
call KeybdGetChar
|
call KeybdGetChar
|
beqi r1,#CTRLC,sac975
|
beqi r1,#CTRLC,sac975
|
outc r1,AC97+0x68 ; wait for dirty bits to clear
|
inch r1,AC97+0x68 ; wait for dirty bits to clear
|
bne r1,r0,sac972 ; wait a while for the settings to take effect
|
bne r1,r0,sac972 ; wait a while for the settings to take effect
|
sac975:
|
sac975:
|
lw lr,8[sp]
|
lw lr,8[sp]
|
lw r1,[sp]
|
lw r1,[sp]
|
ret #16
|
ret #16
|
Line 2182... |
Line 2847... |
; sustain level C
|
; sustain level C
|
setlo r1,#0xCA12
|
setlo r1,#0xCA12
|
outc r1,PSGADSR0
|
outc r1,PSGADSR0
|
ori r1,r0,#0x1104 ; gate, output enable, triangle waveform
|
ori r1,r0,#0x1104 ; gate, output enable, triangle waveform
|
outc r1,PSGCTRL0
|
outc r1,PSGCTRL0
|
ori r1,r0,#25000000 ; delay about 1s
|
ori r1,r0,#2500000 ; delay about 1s
|
beep1:
|
beep1:
|
loop r1,beep1
|
loop r1,beep1
|
setlo r1,#13
|
setlo r1,#13
|
outb r1,LED
|
outb r1,LED
|
ori r1,r0,#0x0104 ; gate off, output enable, triangle waveform
|
ori r1,r0,#0x0104 ; gate off, output enable, triangle waveform
|
outc r1,PSGCTRL0
|
outc r1,PSGCTRL0
|
ori r1,r0,#25000000 ; delay about 1s
|
ori r1,r0,#2500000 ; delay about 1s
|
beep2:
|
beep2:
|
loop r1,beep2
|
loop r1,beep2
|
setlo r1,#16
|
setlo r1,#16
|
outb r1,LED
|
outb r1,LED
|
ori r1,r0,#0x0000 ; gate off, output enable off, no waveform
|
ori r1,r0,#0x0000 ; gate off, output enable off, no waveform
|
Line 2326... |
Line 2991... |
ret
|
ret
|
|
|
;------------------------------------------------------------------------------
|
;------------------------------------------------------------------------------
|
;------------------------------------------------------------------------------
|
;------------------------------------------------------------------------------
|
DisplayDatetime:
|
DisplayDatetime:
|
subui sp,sp,#32
|
subui sp,sp,#48
|
sw r1,[sp]
|
sw r1,[sp]
|
sw r2,8[sp]
|
sw r2,8[sp]
|
sw r3,16[sp]
|
sw r3,16[sp]
|
|
sw r4,24[sp]
|
|
sw r5,32[sp]
|
sw lr,24[sp]
|
sw lr,24[sp]
|
call CursorOff
|
call CursorOff
|
lc r2,CursorRow
|
lw r1,#3 ; get cursor position
|
lc r3,CursorCol
|
syscall #410
|
outw r0,DATETIME+24 ; trigger a snapshot
|
mov r4,r1 ; r4 = row
|
lw r1,#46 ; move cursor down to last display line
|
mov r5,r2 ; r5 = col
|
sc r1,CursorRow
|
lw r1,#2 ; set cursor position
|
lw r1,#64
|
lw r2,#46 ; move cursor down to last display line
|
sc r1,CursorCol
|
lw r3,#64
|
inw r1,DATETIME ; get the snapshotted date and time
|
syscall #410
|
|
lw r1,#1 ; get the snapshotted date and time
|
|
syscall #416
|
call DisplayWord ; display on screen
|
call DisplayWord ; display on screen
|
sc r2,CursorRow ; restore cursor position
|
lw r1,#2 ; restore cursor position
|
sc r3,CursorCol
|
mov r2,r4 ; r2 = row
|
call CalcScreenLoc
|
mov r3,r5 ; r3 = col
|
|
syscall #410
|
call CursorOn
|
call CursorOn
|
lw lr,24[sp]
|
lw lr,24[sp]
|
lw r3,16[sp]
|
lw r3,16[sp]
|
lw r2,8[sp]
|
lw r2,8[sp]
|
lw r1,[sp]
|
lw r1,[sp]
|
ret #32
|
lw r4,24[sp]
|
|
lw r5,32[sp]
|
|
ret #48
|
|
|
;==============================================================================
|
;==============================================================================
|
;==============================================================================
|
;==============================================================================
|
InitializeGame:
|
InitializeGame:
|
subui sp,sp,#16
|
subui sp,sp,#16
|
Line 2535... |
Line 3207... |
addui sp,sp,#240
|
addui sp,sp,#240
|
bra Monitor
|
bra Monitor
|
|
|
;==============================================================================
|
;==============================================================================
|
;==============================================================================
|
;==============================================================================
|
|
;
|
|
; Initialize the SD card
|
|
; Returns
|
|
; r = 0 if successful, 1 otherwise
|
|
;
|
|
spi_init:
|
|
subui sp,sp,#24
|
|
sw lr,[sp]
|
|
sw r2,8[sp]
|
|
sw r3,16[sp]
|
|
lea r3,SPIMASTER
|
|
lw r1,#SPI_INIT_SD
|
|
outb r1,SPI_TRANS_TYPE_REG[r3]
|
|
lw r1,#SPI_TRANS_START
|
|
outb r1,SPI_TRANS_CTRL_REG[r3]
|
|
nop
|
|
spi_init1:
|
|
inb r1,SPI_TRANS_STATUS_REG[r3]
|
|
mov r2,r1 ; note: some time needs to be wasted
|
|
mov r1,r2 ; between status reads.
|
|
beqi r1,#SPI_TRANS_BUSY,spi_init1
|
|
inb r1,SPI_TRANS_ERROR_REG[r3]
|
|
bfext r1,r1,#1,#0
|
|
bne r1,#SPI_INIT_NO_ERROR,spi_error
|
|
lea r1,spi_init_ok_msg
|
|
call DisplayString
|
|
xor r1,r1,r1
|
|
bra spi_init_exit
|
|
spi_error:
|
|
call DisplayByte
|
|
lea r1,spi_init_error_msg
|
|
call DisplayString
|
|
lw r1,#1
|
|
spi_init_exit:
|
|
lw lr,[sp]
|
|
lw r2,8[sp]
|
|
lw r3,16[sp]
|
|
ret #24
|
|
|
|
|
|
; SPI read sector
|
|
;
|
|
; r1= sector number to read
|
|
; r2= address to place read data
|
|
; Returns:
|
|
; r1 = 0 if successful
|
|
;
|
|
spi_read_sector:
|
|
subui sp,sp,#40
|
|
sw lr,[sp]
|
|
sw r5,8[sp]
|
|
sw r2,16[sp]
|
|
sw r3,24[sp]
|
|
sw r4,32[sp]
|
|
lea r3,SPIMASTER
|
|
|
|
; spi master wants a byte address, so we multiply the sector number
|
|
; by 512.
|
|
shlui r1,r1,#9
|
|
outb r1,SPI_SD_ADDR_7_0_REG[r3]
|
|
shrui r1,r1,#8
|
|
outb r1,SPI_SD_ADDR_15_8_REG[r3]
|
|
shrui r1,r1,#8
|
|
outb r1,SPI_SD_ADDR_23_16_REG[r3]
|
|
shrui r1,r1,#8
|
|
outb r1,SPI_SD_ADDR_31_24_REG[r3]
|
|
|
|
; Force the reciever fifo to be empty, in case a prior error leaves it
|
|
; in an unknown state.
|
|
lw r1,#1
|
|
outb r1,SPI_RX_FIFO_CTRL_REG[r3]
|
|
|
|
lw r1,#RW_READ_SD_BLOCK
|
|
outb r1,SPI_TRANS_TYPE_REG[r3]
|
|
lw r1,#SPI_TRANS_START
|
|
outb r1,SPI_TRANS_CTRL_REG[r3]
|
|
nop
|
|
spi_read_sect1:
|
|
inb r1,SPI_TRANS_STATUS_REG[r3]
|
|
mov r4,r1 ; just a delay between consecutive status reg reads
|
|
mov r1,r4
|
|
beqi r1,#SPI_TRANS_BUSY,spi_read_sect1
|
|
inb r1,SPI_TRANS_ERROR_REG[r3]
|
|
bfext r1,r1,#3,#2
|
|
bnei r1,#SPI_READ_NO_ERROR,spi_read_error
|
|
lw r4,#512 ; read 512 bytes from fifo
|
|
spi_read_sect2:
|
|
inb r1,SPI_RX_FIFO_DATA_REG[r3]
|
|
sb r1,[r2]
|
|
addui r2,r2,#1
|
|
loop r4,spi_read_sect2
|
|
xor r1,r1,r1
|
|
bra spi_read_ret
|
|
spi_read_error:
|
|
call DisplayByte
|
|
lea r1,spi_read_error_msg
|
|
call DisplayString
|
|
lw r1,#1
|
|
spi_read_ret:
|
|
lw lr,[sp]
|
|
lw r5,8[sp]
|
|
lw r2,16[sp]
|
|
lw r3,24[sp]
|
|
lw r4,32[sp]
|
|
ret #40
|
|
|
|
; Read the boot sector from the disk.
|
|
; Must find it first by looking for the signature bytes 'EB' and '55AA'.
|
|
;
|
|
spi_read_boot:
|
|
subui sp,sp,#32
|
|
sw lr,[sp]
|
|
sw r2,8[sp]
|
|
sw r3,16[sp]
|
|
sw r5,24[sp]
|
|
sw r0,startSector ; default starting sector
|
|
lw r3,#500 ;1934720 ; number of sectors to read (up to 1GB)
|
|
lw r5,#0 ; r5 = starting address
|
|
spi_read_boot1:
|
|
mov r1,r5 ; r1 = sector number
|
|
lw r2,#8 ; eight digits
|
|
sb r0,CursorCol
|
|
call DisplayNum ; Display the sector number being checked
|
|
mov r1,r5 ; r1 = sector number
|
|
lw r2,#0x100800000 ; r2 = target address
|
|
call spi_read_sector
|
|
|
|
; The following displays the contents of the sector
|
|
; lw r1,#0x10
|
|
; lw r2,#0x3800
|
|
;spi_read_boot5:
|
|
; call DisplayMemB
|
|
; loop r1,spi_read_boot5
|
|
|
|
addui r5,r5,#1 ; move to next sector
|
|
lbu r1,0x100800000
|
|
cmpui r2,r1,#0xEB
|
|
beq r2,r0,spi_read_boot2
|
|
spi_read_boot3:
|
|
loop r3,spi_read_boot1
|
|
lw r1,#1 ; r1 = 1 for error
|
|
bra spi_read_boot4
|
|
spi_read_boot2:
|
|
lea r1,msgFoundEB
|
|
call DisplayString
|
|
lbu r1,0x1008001FE ; check for 0x55AA signature
|
|
bnei r1,#0x55,spi_read_boot3
|
|
lbu r1,0x1008001FF
|
|
bnei r1,#0xAA,spi_read_boot3
|
|
subui r1,r5,#1
|
|
sw r1,startSector
|
|
xor r1,r1,r1 ; r1 = 0, for okay status
|
|
spi_read_boot4:
|
|
lw lr,[sp]
|
|
lw r2,8[sp]
|
|
lw r3,16[sp]
|
|
lw r5,24[sp]
|
|
ret #32
|
|
|
|
msgFoundEB:
|
|
db "Found EB code.",CR,LF,0
|
|
.align 4
|
|
|
|
; Load the FAT tables into memory
|
|
;
|
|
loadFAT:
|
|
subui sp,sp,#8
|
|
sw lr,[sp]
|
|
lcu r3,0x100800016 ; sectors per FAT
|
|
lbu r2,0x100800010 ; number of FATs
|
|
mulu r3,r3,r2 ; offset
|
|
lea r2,0x100800200 ; where to place FAT
|
|
lcu r5,0x10080000E ; r5 = # reserved sectors before FAT
|
|
lw r6,startSector
|
|
addu r5,r5,r6
|
|
loadFAT1:
|
|
mov r1,r5 ; r1 = sector #
|
|
call spi_read_sector
|
|
addui r5,r5,#1
|
|
addui r2,r2,#512 ; advance 512 bytes
|
|
loop r3,loadFAT1
|
|
lw lr,[sp]
|
|
ret #8
|
|
|
|
; Load the root directory from disk
|
|
; r2 = where to place root directory in memory
|
|
;
|
|
loadRootDirectory:
|
|
lcu r3,0x100800016 ; sectors per FAT
|
|
lbu r4,0x100800010 ; number of FATs
|
|
mulu r3,r3,r4 ; offset
|
|
lcu r4,0x10080000E ; r2 = # reserved sectors before FAT
|
|
addu r3,r3,r4 ; r3 = root directory sector number
|
|
lw r6,startSector
|
|
addu r5,r3,r6 ; r5 = root directory sector number
|
|
; we have to use two byte loads here because the number is at an unaligned data address
|
|
lbu r7,0x100800011 ; r7 <= number of root directory entries
|
|
lbu r8,0x100800012
|
|
shlui r8,r8,#8
|
|
or r7,r7,r8
|
|
mov r8,r7 ; r8 = number of root directory entries
|
|
shlui r7,r7,#5 ; r7 *=32 = size of root directory table (bytes)
|
|
shrui r7,r7,#9 ; r7 /= 512 = number of sectors in root directory
|
|
mov r3,r7
|
|
loadRootDir1:
|
|
mov r1,r5
|
|
call spi_read_sector
|
|
addui r5,r5,#1
|
|
addui r2,r2,#512
|
|
loop r3,loadRootDir1
|
|
|
|
loadBootFile:
|
|
; For now we cheat and just go directly to sector 512.
|
|
bra loadBootFileTmp
|
|
|
|
lcu r3,0x100800016 ; sectors per FAT
|
|
lbu r2,0x100800010 ; number of FATs
|
|
mulu r3,r3,r2 ; offset
|
|
lcu r2,0x10080000E ; r2 = # reserved sectors before FAT
|
|
addu r3,r3,r2 ; r3 = root directory sector number
|
|
; we have to use two byte loads here because the number is at an unaligned data address
|
|
lbu r7,0x100800011 ; r7 <= number of root directory entries
|
|
lbu r8,0x100800012
|
|
shlui r8,r8,#8
|
|
or r7,r7,r8
|
|
mov r8,r7 ; r8 = number of root directory entries
|
|
shlui r7,r7,#5 ; r7 *=32 = size of root directory table (bytes)
|
|
shrui r7,r7,#9 ; r7 /= 512 = number of sectors in root directory
|
|
|
|
; now we need to fetch the sectors of the root directory and put them somewhere in
|
|
; memory
|
|
;
|
|
loadBootFile4:
|
|
lw r1,[r3] ; get filename
|
|
cmpui r1,r1,#0x454C4946544F4F42 ; "BOOTFILE"
|
|
beq r1,r0,loadBootFile5
|
|
loadBootFile3:
|
|
addui r3,r3,#32 ; move to next directory entry
|
|
loop r7,loadBootFile4
|
|
; boot file not found
|
|
|
|
; here we found the file in the directory
|
|
;
|
|
loadBootFile5:
|
|
lcu r2,0x1a[r3] ; get starting cluster
|
|
lcu r7,0x100800011 ; r7 = number of root directory entries
|
|
shlui r7,r7,#5 ; r7 *=32 = size of root directory table (bytes)
|
|
shrui r7,r7,#9 ; r7 /= 512 = number of sectors in root directory
|
|
|
|
loadBootFileTmp:
|
|
; We load the number of sectors per cluster, then load a single cluster of the file.
|
|
; This is 16kib
|
|
lbu r3,0x10080000D ; sectors per cluster
|
|
lea r2,0x100800200 ; where to place FAT in memory
|
|
lw r5,startSector ; r5=start sector of disk
|
|
addui r5,r5,#512 ; r5= sector 512
|
|
loadBootFile1:
|
|
mov r1,r5 ; r1=sector to read
|
|
call spi_read_sector
|
|
addui r5,r5,#1 ; r5 = next sector
|
|
addui r2,r2,#512
|
|
loop r3,loadBootFile1
|
|
lhu r1,0x100800200 ; make sure it's bootable
|
|
bnei r1,#0x544F4F42,loadBootFile2
|
|
lw r1,#0x16
|
|
lea r1,msgJumpingToBoot
|
|
call DisplayString
|
|
lw r1,#0x100800204
|
|
jal lr,[r1]
|
|
jmp Monitor
|
|
loadBootFile2:
|
|
lea r1,msgNotBootable
|
|
call DisplayString
|
|
jmp Monitor
|
|
|
|
msgJumpingToBoot:
|
|
db "Jumping to boot",0
|
|
msgNotBootable:
|
|
db "SD card not bootable.",0
|
|
spi_init_ok_msg:
|
|
db "SD card initialized okay.",0
|
|
spi_init_error_msg:
|
|
db ": error occurred initializing the SD card.",0
|
|
spi_boot_error_msg:
|
|
db "SD card boot error",0
|
|
spi_read_error_msg:
|
|
db "SD card read error",0
|
|
|
|
.align 4
|
|
|
|
;==============================================================================
|
|
; Ethernet
|
|
;==============================================================================
|
|
my_MAC1 EQU 0x00
|
|
my_MAC2 EQU 0xFF
|
|
my_MAC3 EQU 0xEE
|
|
my_MAC4 EQU 0xF0
|
|
my_MAC5 EQU 0xDA
|
|
my_MAC6 EQU 0x42
|
|
|
|
.bss
|
|
eth_unique_id dw 0
|
|
|
|
.code
|
|
|
|
; Initialize the ethmac controller.
|
|
; Supply a MAC address, set MD clock
|
|
;
|
|
eth_init:
|
|
lea r3,ETHMAC
|
|
lw r1,#0x64 ; 100
|
|
sh r1,MIIMODER[r3]
|
|
lw r1,#7 ; PHY address
|
|
sh r1,MIIADDRESS[r3]
|
|
lw r1,#0xEEF0DA42
|
|
sh r1,0x40[r3] ; MAC0
|
|
lw r1,#0x00FF
|
|
sh r1,0x44[r3] ; MAC1
|
|
ret
|
|
|
|
; Request a packet and display on screen
|
|
; r1 = address where to put packet
|
|
;
|
|
eth_request_packet:
|
|
subui sp,sp,#24
|
|
sw r3,[sp]
|
|
sw r2,8[sp]
|
|
sw r4,16[sp]
|
|
lea r3,ETHMAC
|
|
lw r2,#4 ; clear rx interrupt
|
|
sh r2,4[r3]
|
|
sh r1,0x604[r3] ; storage address
|
|
lw r2,#0xe000 ; enable interrupt
|
|
sh r2,0x600[r3]
|
|
eth1:
|
|
nop
|
|
inh r2,4[r3]
|
|
bfext r2,r2,#2,#2 ; get bit #2
|
|
beq r2,r0,eth1
|
|
inh r2,0x600[r3] ; get from descriptor
|
|
shrui r2,r2,#16
|
|
lw r3,#0
|
|
lea r4,TEXTSCR+7560 ; second last line of screen
|
|
eth20:
|
|
lbu r2,[r1+r3] ; get byte
|
|
sc r2,[r4+r3*2] ; store to screen
|
|
addui r3,r3,#1
|
|
cmpui r2,r3,#83
|
|
bne r2,r0,eth20
|
|
lw r3,[sp]
|
|
lw r2,8[sp]
|
|
lw r4,16[sp]
|
|
ret #24
|
|
|
|
; r1 = packet address
|
|
;
|
|
eth_interpret_packet:
|
|
subui sp,sp,#16
|
|
sw r3,[sp]
|
|
sw r2,8[sp]
|
|
lbu r2,12[r1]
|
|
lbu r3,13[r1]
|
|
bnei r2,#8,eth2 ; 0x806 ?
|
|
bnei r3,#6,eth2
|
|
lw r1,#2 ; return r1 = 2 for ARP
|
|
eth5:
|
|
lw r3,[sp]
|
|
lw r2,8[sp]
|
|
ret #16
|
|
eth2:
|
|
bnei r2,#8,eth3 ; 0x800 ?
|
|
bnei r3,#0,eth3
|
|
lbu r2,23[r1]
|
|
bnei r2,#1,eth4
|
|
lw r1,#1
|
|
bra eth5 ; return 1 ICMP
|
|
eth4:
|
|
bnei r2,#0x11,eth6
|
|
lw r1,#3 ; return 3 for UDP
|
|
bra eth5
|
|
eth6:
|
|
bnei r2,#6,eth7
|
|
lw r1,#4 ; return 4 for TCP
|
|
bra eth5
|
|
eth7:
|
|
eth3:
|
|
xor r1,r1,r1 ; return zero for unknown
|
|
lw r3,[sp]
|
|
lw r2,8[sp]
|
|
ret #16
|
|
|
|
; r1 = address of packet to send
|
|
; r2 = packet length
|
|
;
|
|
eth_send_packet:
|
|
subui sp,sp,#16
|
|
sw r3,[sp]
|
|
sw r4,8[sp]
|
|
lea r3,ETHMAC
|
|
; wait for tx buffer to be clear
|
|
eth8:
|
|
inh r4,0x400[r3]
|
|
bfext r4,r4,#15,#15
|
|
beqi r4,#1,eth8
|
|
lw r4,#1 ; clear tx interrupt
|
|
sh r4,4[r3]
|
|
; set address
|
|
sh r1,0x404[r3]
|
|
; set the packet length field and enable interrupts
|
|
shlui r2,r2,#16
|
|
ori r2,r2,#0xF000
|
|
sh r2,0x400[r3]
|
|
lw r4,8[sp]
|
|
lw r3,[sp]
|
|
ret #16
|
|
|
|
; Only for IP type packets (not ARP)
|
|
; r1 = rx buffer address
|
|
; r2 = swap flag
|
|
; Returns:
|
|
; r1 = data start index
|
|
;
|
|
eth_build_packet:
|
|
subui sp,sp,#64
|
|
sw r3,[sp]
|
|
sw r4,8[sp]
|
|
sw r5,16[sp]
|
|
sw r6,24[sp]
|
|
sw r7,32[sp]
|
|
sw r8,40[sp]
|
|
sw r9,48[sp]
|
|
sw r10,56[sp]
|
|
lbu r3,6[r1]
|
|
lbu r4,7[r1]
|
|
lbu r5,8[r1]
|
|
lbu r6,9[r1]
|
|
lbu r7,10[r1]
|
|
lbu r8,11[r1]
|
|
; write to destination header
|
|
sb r3,[r1]
|
|
sb r4,1[r1]
|
|
sb r5,2[r1]
|
|
sb r6,3[r1]
|
|
sb r7,4[r1]
|
|
sb r8,5[r1]
|
|
; write to source header
|
|
lw r3,#my_MAC1
|
|
sb r3,6[r1]
|
|
lw r3,#my_MAC2
|
|
sb r3,7[r1]
|
|
lw r3,#my_MAC3
|
|
sb r3,8[r1]
|
|
lw r3,#my_MAC4
|
|
sb r3,9[r1]
|
|
lw r3,#my_MAC5
|
|
sb r3,10[r1]
|
|
lw r3,#my_MAC6
|
|
sb r3,11[r1]
|
|
bnei r2,#1,eth16 // if (swap)
|
|
lbu r3,26[r1]
|
|
lbu r4,27[r1]
|
|
lbu r5,28[r1]
|
|
lbu r6,29[r1]
|
|
; read destination
|
|
lbu r7,30[r1]
|
|
lbu r8,31[r1]
|
|
lbu r9,32[r1]
|
|
lbu r10,33[r1]
|
|
; write to sender
|
|
sb r7,26[r1]
|
|
sb r8,27[r1]
|
|
sb r9,28[r1]
|
|
sb r10,29[r1]
|
|
; write destination
|
|
sb r3,30[r1]
|
|
sb r4,31[r1]
|
|
sb r5,32[r1]
|
|
sb r6,33[r1]
|
|
eth16:
|
|
lw r3,eth_unique_id
|
|
addui r3,r3,#1
|
|
sw r3,eth_unique_id
|
|
sb r3,19[r1]
|
|
shrui r3,r3,#8
|
|
sb r3,18[r1]
|
|
lbu r3,14[r1]
|
|
andi r3,r3,#0xF
|
|
shlui r3,r3,#2 ; *4
|
|
addui r1,r3,#14 ; return datastart in r1
|
|
lw r3,[sp]
|
|
lw r4,8[sp]
|
|
lw r5,16[sp]
|
|
lw r6,24[sp]
|
|
lw r7,32[sp]
|
|
lw r8,40[sp]
|
|
lw r9,48[sp]
|
|
lw r10,56[sp]
|
|
ret #64
|
|
|
|
; Compute IPv4 checksum of header
|
|
; r1 = packet address
|
|
; r2 = data start
|
|
;
|
|
eth_checksum:
|
|
subui sp,sp,#24
|
|
sw r3,[sp]
|
|
sw r4,8[sp]
|
|
sw r5,16[sp]
|
|
; set checksum to zero
|
|
sb r0,24[r1]
|
|
sb r0,25[r1]
|
|
xor r3,r3,r3 ; r3 = sum = zero
|
|
lw r4,#14
|
|
eth15:
|
|
mov r5,r2
|
|
subui r5,r5,#1 ; r5 = datastart - 1
|
|
bge r4,r5,eth14
|
|
lbu r5,[r1+r4] ; shi = [rx_addr+i]
|
|
lbu r6,1[r1+r4] ; slo = [rx_addr+i+1]
|
|
shlui r5,r5,#8
|
|
or r5,r5,r6 ; shilo
|
|
addu r3,r3,r5 ; sum = sum + shilo
|
|
addui r4,r4,#2 ; i = i + 2
|
|
bra eth15
|
|
eth14:
|
|
mov r5,r3 ; r5 = sum
|
|
andi r3,r3,#0xffff
|
|
shrui r5,r5,#16
|
|
addu r3,r3,r5
|
|
com r3,r3
|
|
sb r3,25[r1] ; low byte
|
|
shrui r3,r3,#8
|
|
sb r3,24[r1] ; high byte
|
|
sw r3,[sp]
|
|
sw r4,8[sp]
|
|
sw r5,16[sp]
|
|
ret #24
|
|
|
|
; r1 = packet address
|
|
; returns r1 = 1 if this IP
|
|
;
|
|
eth_verifyIP:
|
|
subui sp,sp,#32
|
|
sw r2,[sp]
|
|
sw r3,8[sp]
|
|
sw r4,16[sp]
|
|
sw r5,24[sp]
|
|
lbu r2,30[r1]
|
|
lbu r3,31[r1]
|
|
lbu r4,32[r1]
|
|
lbu r5,33[r1]
|
|
; Check for general broadcast
|
|
bnei r2,#0xFF,eth11
|
|
bnei r3,#0xFF,eth11
|
|
bnei r4,#0xFF,eth11
|
|
bnei r5,#0xFF,eth11
|
|
eth12:
|
|
lw r1,#1
|
|
eth13:
|
|
lw r2,[sp]
|
|
lw r3,8[sp]
|
|
lw r4,16[sp]
|
|
lw r5,24[sp]
|
|
ret #32
|
|
eth11:
|
|
mov r1,r2
|
|
shlui r1,r1,#8
|
|
or r1,r1,r3
|
|
shlui r1,r1,#8
|
|
or r1,r1,r4
|
|
shlui r1,r1,#8
|
|
or r1,r1,r5
|
|
beqi r1,#0xC0A8012A,eth12
|
|
xor r1,r1,r1
|
|
bra eth13
|
|
|
|
|
|
eth_main:
|
|
call eth_init
|
|
eth_loop:
|
|
xor r1,r1,r1
|
|
lw r1,#0x1_00000000 ; memory address zero
|
|
call eth_request_packet
|
|
call eth_interpret_packet ; r1 = packet type
|
|
|
|
bnei r1,#1,eth10
|
|
mov r2,r1 ; save off r1, r2 = packet type
|
|
lw r1,#0x1_00000000 ; memory address zero
|
|
call eth_verifyIP
|
|
mov r3,r1
|
|
mov r1,r2 ; r1 = packet type again
|
|
bnei r3,#1,eth10
|
|
|
|
lw r1,#0x1_00000000 ; memory address zero
|
|
lw r2,#1
|
|
call eth_build_packet
|
|
mov r3,r1 ; r3 = icmpstart
|
|
lw r1,#0x1_00000000 ; memory address zero
|
|
sb r0,[r1+r3] ; [rx_addr+icmpstart] = 0
|
|
lbu r2,17[r1]
|
|
addui r2,r2,#14 ; r2 = len
|
|
mov r6,r2 ; r6 = len
|
|
lbu r4,2[r1+r3] ; shi
|
|
lbu r5,3[r1+r3] ; slo
|
|
shlui r4,r4,#8
|
|
or r4,r4,r5 ; sum = {shi,slo};
|
|
com r4,r4 ; sum = ~sum
|
|
subui r4,r4,#0x800 ; sum = sum - 0x800
|
|
com r4,r4 ; sum = ~sum
|
|
sb r4,3[r1+r3]
|
|
shrui r4,r4,#8
|
|
sb r4,2[r1+r3]
|
|
mov r2,r3
|
|
call eth_checksum
|
|
lw r1,#0x1_00000000 ; memory address zero
|
|
mov r2,r6
|
|
call eth_send_packet
|
|
jmp eth_loop
|
|
eth10:
|
|
; r2 = rx_addr
|
|
bnei r1,#2,eth_loop ; Do we have ARP ?
|
|
; xor r2,r2,r2 ; memory address zero
|
|
lw r2,#1_00000000
|
|
; get the opcode
|
|
lbu r13,21[r2]
|
|
bnei r13,#1,eth_loop ; ARP request
|
|
; get destination IP address
|
|
lbu r9,38[r2]
|
|
lbu r10,39[r2]
|
|
lbu r11,40[r2]
|
|
lbu r12,41[r2]
|
|
; set r15 = destination IP
|
|
mov r15,r9
|
|
shlui r15,r15,#8
|
|
or r15,r15,r10
|
|
shlui r15,r15,#8
|
|
or r15,r15,r11
|
|
shlui r15,r15,#8
|
|
or r15,r15,r12
|
|
; Is it our IP ?
|
|
bnei r15,#0xC0A8012A,eth_loop; //192.168.1.42
|
|
; get source IP address
|
|
lbu r5,28[r2]
|
|
lbu r6,29[r2]
|
|
lbu r7,30[r2]
|
|
lbu r8,31[r2]
|
|
; set r14 = source IP
|
|
mov r14,r5
|
|
shlui r14,r14,#8
|
|
or r14,r14,r6
|
|
shlui r14,r14,#8
|
|
or r14,r14,r7
|
|
shlui r14,r14,#8
|
|
or r14,r14,r8
|
|
; Get the source MAC address
|
|
lbu r16,22[r2]
|
|
lbu r17,23[r2]
|
|
lbu r18,24[r2]
|
|
lbu r19,25[r2]
|
|
lbu r20,26[r2]
|
|
lbu r21,27[r2]
|
|
; write to destination header
|
|
sb r16,[r2]
|
|
sb r17,1[r2]
|
|
sb r18,2[r2]
|
|
sb r19,3[r2]
|
|
sb r20,4[r2]
|
|
sb r21,5[r2]
|
|
; and write to ARP destination
|
|
sb r16,32[r2]
|
|
sb r17,33[r2]
|
|
sb r18,34[r2]
|
|
sb r19,35[r2]
|
|
sb r20,36[r2]
|
|
sb r21,37[r2]
|
|
; write to source header
|
|
; stbc #0x00,6[r2]
|
|
; stbc #0xFF,7[r2]
|
|
; stbc #0xEE,8[r2]
|
|
; stbc #0xF0,9[r2]
|
|
; stbc #0xDA,10[r2]
|
|
; stbc #0x42,11[r2]
|
|
sb r0,6[r2]
|
|
lw r1,#0xFF
|
|
sb r1,7[r2]
|
|
lw r1,#0xEE
|
|
sb r1,8[r2]
|
|
lw r1,#0xF0
|
|
sb r1,9[r2]
|
|
lw r1,#0xDA
|
|
sb r1,10[r2]
|
|
lw r1,#0x42
|
|
sb r1,11[r2]
|
|
; write to ARP source
|
|
; stbc #0x00,22[r2]
|
|
; stbc #0xFF,23[r2]
|
|
; stbc #0xEE,24[r2]
|
|
; stbc #0xF0,25[r2]
|
|
; stbc #0xDA,26[r2]
|
|
; stbc #0x42,27[r2]
|
|
sb r0,22[r2]
|
|
lw r1,#0xFF
|
|
sb r1,23[r2]
|
|
lw r1,#0xEE
|
|
sb r1,24[r2]
|
|
lw r1,#0xF0
|
|
sb r1,25[r2]
|
|
lw r1,#0xDA
|
|
sb r1,26[r2]
|
|
lw r1,#0x42
|
|
sb r1,27[r2]
|
|
; swap sender / destination IP
|
|
; write sender
|
|
sb r9,28[r2]
|
|
sb r10,29[r2]
|
|
sb r11,30[r2]
|
|
sb r12,31[r2]
|
|
; write destination
|
|
sb r5,38[r2]
|
|
sb r6,39[r2]
|
|
sb r7,40[r2]
|
|
sb r8,41[r2]
|
|
; change request to reply
|
|
; stbc #2,21[r2]
|
|
lw r1,#2
|
|
sb r1,21[r2]
|
|
mov r1,r2 ; r1 = packet address
|
|
lw r2,#0x2A ; r2 = packet length
|
|
call eth_send_packet
|
|
jmp eth_loop
|
|
|
|
|
|
;==============================================================================
|
|
;==============================================================================
|
;****************************************************************;
|
;****************************************************************;
|
; ;
|
; ;
|
; Tiny BASIC for the Raptor64 ;
|
; Tiny BASIC for the Raptor64 ;
|
; ;
|
; ;
|
; Derived from a 68000 derivative of Palo Alto Tiny BASIC as ;
|
; Derived from a 68000 derivative of Palo Alto Tiny BASIC as ;
|
Line 2608... |
Line 4014... |
sw lr,[sp]
|
sw lr,[sp]
|
sw sp,OSSP
|
sw sp,OSSP
|
lw sp,ENDMEM ; initialize stack pointer
|
lw sp,ENDMEM ; initialize stack pointer
|
subui sp,sp,#8
|
subui sp,sp,#8
|
sw lr,[sp] ; save off return address
|
sw lr,[sp] ; save off return address
|
sc r0,CursorRow ; set screen output
|
sb r0,CursorRow ; set screen output
|
sc r0,CursorCol
|
sb r0,CursorCol
|
sb r0,CursorFlash
|
sb r0,CursorFlash
|
sw r0,pos
|
sh r0,pos
|
lw r2,#0x10000020 ; black chars, yellow background
|
lw r2,#0x10000020 ; black chars, yellow background
|
sh r2,charToPrint
|
; sh r2,charToPrint
|
call ClearScreen
|
call ClearScreen
|
lea r1,msgInit ; tell who we are
|
lea r1,msgInit ; tell who we are
|
call PRMESGAUX
|
; call PRMESGAUX
|
lea r1,msgInit ; tell who we are
|
lea r1,msgInit ; tell who we are
|
call PRMESG
|
call PRMESG
|
lw r1,TXTBGN ; init. end-of-program pointer
|
lw r1,TXTBGN ; init. end-of-program pointer
|
sw r1,TXTUNF
|
sw r1,TXTUNF
|
lw r1,ENDMEM ; get address of end of memory
|
lw r1,ENDMEM ; get address of end of memory
|
subui r1,r1,#2048 ; reserve 2K for the stack
|
subui r1,r1,#4096 ; reserve 4K for the stack
|
sw r1,STKBOT
|
sw r1,STKBOT
|
subui r1,r1,#8192 ; 1000 vars
|
subui r1,r1,#16384 ; 1000 vars
|
sw r1,VARBGN
|
sw r1,VARBGN
|
call clearVars ; clear the variable area
|
call clearVars ; clear the variable area
|
lw r1,VARBGN ; calculate number of bytes free
|
lw r1,VARBGN ; calculate number of bytes free
|
lw r3,TXTUNF
|
lw r3,TXTUNF
|
sub r1,r1,r3
|
subu r1,r1,r3
|
setlo r2,#0
|
setlo r2,#0
|
call PRTNUM
|
call PRTNUM
|
lea r1,msgBytesFree
|
lea r1,msgBytesFree
|
call PRMESG
|
call PRMESG
|
WSTART:
|
WSTART:
|
Line 2749... |
Line 4155... |
; The end of the character table is a 0 byte which corresponds
|
; The end of the character table is a 0 byte which corresponds
|
; to the default routine in the execution table, which is
|
; to the default routine in the execution table, which is
|
; executed if none of the other table items are matched.
|
; executed if none of the other table items are matched.
|
;
|
;
|
; Character-matching tables:
|
; Character-matching tables:
|
align 8
|
|
TAB1:
|
TAB1:
|
db "LIS",'T'+0x80 ; Direct commands
|
db "LIS",'T'+0x80 ; Direct commands
|
db "LOA",'D'+0x80
|
db "LOA",'D'+0x80
|
db "NE",'W'+0x80
|
db "NE",'W'+0x80
|
db "RU",'N'+0x80
|
db "RU",'N'+0x80
|
Line 2871... |
Line 4277... |
dw XP_ANDX
|
dw XP_ANDX
|
TAB10_1
|
TAB10_1
|
dw XP_OR
|
dw XP_OR
|
dw XP_ORX
|
dw XP_ORX
|
|
|
.align 16
|
.align 4
|
|
|
;*
|
;*
|
; r3 = match flag (trashed)
|
; r3 = match flag (trashed)
|
; r9 = text table
|
; r9 = text table
|
; r10 = exec table
|
; r10 = exec table
|
Line 4650... |
Line 6056... |
; r1 = pointer to string
|
; r1 = pointer to string
|
; r2 = stop character
|
; r2 = stop character
|
; return r1 = pointer to end of line + 1
|
; return r1 = pointer to end of line + 1
|
|
|
PRTSTG:
|
PRTSTG:
|
sub sp,sp,#32
|
subui sp,sp,#32
|
sw r5,[sp]
|
sw r5,[sp]
|
sw r5,8[sp]
|
sw r5,8[sp]
|
sw r7,16[sp]
|
sw r7,16[sp]
|
sw lr,24[sp]
|
sw lr,24[sp]
|
mov r5,r1 ; r5 = pointer
|
mov r5,r1 ; r5 = pointer
|
Line 4680... |
Line 6086... |
|
|
QTSTG:
|
QTSTG:
|
subui sp,sp,#8
|
subui sp,sp,#8
|
sw lr,[sp]
|
sw lr,[sp]
|
setlo r3,#'"'
|
setlo r3,#'"'
|
setlo r4,#<QT3
|
lea r4,QT3
|
sethi r4,#>QT3
|
|
call TSTC ; *** QTSTG ***
|
call TSTC ; *** QTSTG ***
|
setlo r2,#'"' ; it is a "
|
setlo r2,#'"' ; it is a "
|
QT1:
|
QT1:
|
or r1,r8,r0
|
or r1,r8,r0
|
call PRTSTG ; print until another
|
call PRTSTG ; print until another
|
Line 4693... |
Line 6098... |
bne r2,#LF,QT2 ; was last one a CR?
|
bne r2,#LF,QT2 ; was last one a CR?
|
addui sp,sp,#8
|
addui sp,sp,#8
|
bra RUNNXL ; if so, run next line
|
bra RUNNXL ; if so, run next line
|
QT3:
|
QT3:
|
setlo r3,#''''
|
setlo r3,#''''
|
setlo r4,#<QT4
|
lea r4,QT4
|
sethi r4,#>QT4
|
|
call TSTC ; is it a single quote?
|
call TSTC ; is it a single quote?
|
setlo r2,#'''' ; if so, do same as above
|
setlo r2,#'''' ; if so, do same as above
|
bra QT1
|
bra QT1
|
QT4:
|
QT4:
|
setlo r3,#'_'
|
setlo r3,#'_'
|
setlo r4,#<QT5
|
lea r4,QT5
|
sethi r4,#>QT5
|
|
call TSTC ; is it an underline?
|
call TSTC ; is it an underline?
|
setlo r1,#CR ; if so, output a CR without LF
|
setlo r1,#CR ; if so, output a CR without LF
|
call GOOUT
|
call GOOUT
|
QT2:
|
QT2:
|
lw lr,[sp]
|
lw lr,[sp]
|
Line 4738... |
Line 6141... |
sw r3,[sp]
|
sw r3,[sp]
|
sw r5,8[sp]
|
sw r5,8[sp]
|
sw r6,16[sp]
|
sw r6,16[sp]
|
sw r7,24[sp]
|
sw r7,24[sp]
|
sw lr,32[sp]
|
sw lr,32[sp]
|
ori r7,r0,#NUMWKA ; r7 = pointer to numeric work area
|
lea r7,NUMWKA ; r7 = pointer to numeric work area
|
mov r6,r1 ; save number for later
|
mov r6,r1 ; save number for later
|
mov r5,r2 ; r5 = min number of chars
|
mov r5,r2 ; r5 = min number of chars
|
bgt r1,r0,PN1 ; is it negative? if not
|
bgt r1,r0,PN2 ; is it negative? if not
|
neg r1,r1 ; else make it positive
|
neg r1,r1 ; else make it positive
|
subui r5,r5,#1 ; one less for width count
|
subui r5,r5,#1 ; one less for width count
|
PN1:
|
PN2:
|
lw r3,#10
|
lw r3,#10
|
mod r2,r1,r3 ; r2 = r1 mod 10
|
PN1:
|
|
modu r2,r1,r3 ; r2 = r1 mod 10
|
divui r1,r1,#10 ; r1 /= 10 divide by 10
|
divui r1,r1,#10 ; r1 /= 10 divide by 10
|
addui r2,r2,#'0' ; convert remainder to ascii
|
addui r2,r2,#'0' ; convert remainder to ascii
|
sb r2,[r7] ; and store in buffer
|
sb r2,[r7] ; and store in buffer
|
addui r7,r7,#1
|
addui r7,r7,#1
|
subui r5,r5,#1 ; decrement width
|
subui r5,r5,#1 ; decrement width
|
Line 4760... |
Line 6164... |
PN3:
|
PN3:
|
setlo r1,#' ' ; display the required leading spaces
|
setlo r1,#' ' ; display the required leading spaces
|
call GOOUT
|
call GOOUT
|
loop r5,PN3
|
loop r5,PN3
|
PN4:
|
PN4:
|
bgt r6,r0,PN5 ; is number negative?
|
bge r6,r0,PN5 ; is number negative?
|
setlo r1,#'-' ; if so, display the sign
|
setlo r1,#'-' ; if so, display the sign
|
call GOOUT
|
call GOOUT
|
PN5:
|
PN5:
|
subui r7,r7,#1
|
subui r7,r7,#1
|
lb r1,[r7] ; now unstack the digits and display
|
lb r1,[r7] ; now unstack the digits and display
|
Line 4787... |
Line 6191... |
sw r5,[sp]
|
sw r5,[sp]
|
sw r6,8[sp]
|
sw r6,8[sp]
|
sw r7,16[sp]
|
sw r7,16[sp]
|
sw r8,24[sp]
|
sw r8,24[sp]
|
sw lr,32[sp]
|
sw lr,32[sp]
|
setlo r7,#<NUMWKA ; r7 = pointer to numeric work area
|
lea r7,NUMWKA ; r7 = pointer to numeric work area
|
sethi r7,#>NUMWKA
|
|
or r6,r1,r0 ; save number for later
|
or r6,r1,r0 ; save number for later
|
setlo r5,#20 ; r5 = min number of chars
|
setlo r5,#20 ; r5 = min number of chars
|
or r4,r1,r0
|
mov r4,r1
|
bgt r4,r0,PHN1 ; is it negative? if not
|
bgt r4,r0,PHN1 ; is it negative? if not
|
neg r4,r4 ; else make it positive
|
neg r4,r4 ; else make it positive
|
sub r5,r5,#1 ; one less for width count
|
subui r5,r5,#1 ; one less for width count
|
setlo r8,#20 ; maximum of 10 digits
|
setlo r8,#20 ; maximum of 10 digits
|
PHN1:
|
PHN1:
|
or r1,r4,r0
|
mov r1,r4
|
andi r1,r1,#15
|
andi r1,r1,#15
|
blt r1,#10,PHN7
|
blt r1,#10,PHN7
|
addui r1,r1,#'A'-10
|
addui r1,r1,#'A'-10
|
bra PHN8
|
bra PHN8
|
PHN7:
|
PHN7:
|
add r1,r1,#'0' ; convert remainder to ascii
|
add r1,r1,#'0' ; convert remainder to ascii
|
PHN8:
|
PHN8:
|
sb r1,[r7] ; and store in buffer
|
sb r1,[r7] ; and store in buffer
|
add r7,r7,#1
|
addui r7,r7,#1
|
sub r5,r5,#1 ; decrement width
|
subui r5,r5,#1 ; decrement width
|
shru r4,r4,#4
|
shrui r4,r4,#4
|
beq r4,r0,PHN6 ; is it zero yet ?
|
beq r4,r0,PHN6 ; is it zero yet ?
|
loop r8,PHN1 ; safety
|
loop r8,PHN1 ; safety
|
PHN6: ; test pad count
|
PHN6: ; test pad count
|
ble r5,r0,PHN4 ; skip padding if not needed
|
ble r5,r0,PHN4 ; skip padding if not needed
|
PHN3:
|
PHN3:
|
Line 4822... |
Line 6225... |
PHN4:
|
PHN4:
|
bgt r6,r0,PHN5 ; is number negative?
|
bgt r6,r0,PHN5 ; is number negative?
|
setlo r1,#'-' ; if so, display the sign
|
setlo r1,#'-' ; if so, display the sign
|
call GOOUT
|
call GOOUT
|
PHN5:
|
PHN5:
|
sub r7,r7,#1
|
subui r7,r7,#1
|
lb r1,[r7] ; now unstack the digits and display
|
lb r1,[r7] ; now unstack the digits and display
|
call GOOUT
|
call GOOUT
|
cmpui r1,r7,#NUMWKA
|
cmpui r1,r7,#NUMWKA
|
bgt r1,r0,PHN5
|
bgt r1,r0,PHN5
|
PHNRET:
|
PHNRET:
|
Line 4881... |
Line 6284... |
lw r1,8[sp]
|
lw r1,8[sp]
|
lw lr,[sp]
|
lw lr,[sp]
|
addui sp,sp,#16
|
addui sp,sp,#16
|
jal r0,[r4] ; jump to the routine
|
jal r0,[r4] ; jump to the routine
|
TC1:
|
TC1:
|
add r8,r8,#1 ; if equal, bump text pointer
|
addui r8,r8,#1 ; if equal, bump text pointer
|
lw r1,8[sp]
|
lw r1,8[sp]
|
lw lr,[sp]
|
lw lr,[sp]
|
ret #16
|
ret #16
|
|
|
; ===== See if the text pointed to by r8 is a number. If so,
|
; ===== See if the text pointed to by r8 is a number. If so,
|
Line 4906... |
Line 6309... |
setlo r2,#0
|
setlo r2,#0
|
TN1:
|
TN1:
|
lb r3,[r8]
|
lb r3,[r8]
|
bltui r3,#'0',TSNMRET ; is it less than zero?
|
bltui r3,#'0',TSNMRET ; is it less than zero?
|
bgtui r3,#'9',TSNMRET ; is it greater than nine?
|
bgtui r3,#'9',TSNMRET ; is it greater than nine?
|
setlo r4,#0xFFFFFFFF
|
lw r4,#0x07FFFFFF_FFFFFFFF
|
sethi r4,#0x07FFFFFF
|
|
bleu r1,r4,TN2 ; see if there's room for new digit
|
bleu r1,r4,TN2 ; see if there's room for new digit
|
setlo r1,msgNumTooBig
|
lea r1,msgNumTooBig
|
bra ERROR ; if not, we've overflowd
|
bra ERROR ; if not, we've overflowd
|
TN2:
|
TN2:
|
mului r1,r1,#10 ; quickly multiply result by 10
|
mului r1,r1,#10 ; quickly multiply result by 10
|
addi r8,r8,#1 ; adjust text pointer
|
addui r8,r8,#1 ; adjust text pointer
|
andi r3,r3,#0x0F ; add in the new digit
|
andi r3,r3,#0x0F ; add in the new digit
|
add r1,r1,r3
|
addu r1,r1,r3
|
addi r2,r2,#1 ; increment the no. of digits
|
addui r2,r2,#1 ; increment the no. of digits
|
bra TN1
|
bra TN1
|
TSNMRET:
|
TSNMRET:
|
lw lr,[sp]
|
lw lr,[sp]
|
ret #8
|
ret #8
|
|
|
Line 4938... |
Line 6340... |
IGB2:
|
IGB2:
|
lb r1,[r8] ; get char
|
lb r1,[r8] ; get char
|
beqi r1,#' ',IGB1 ; see if it's a space
|
beqi r1,#' ',IGB1 ; see if it's a space
|
bnei r1,#'\t',IGBRET ; or a tab
|
bnei r1,#'\t',IGBRET ; or a tab
|
IGB1:
|
IGB1:
|
add r8,r8,#1 ; increment the text pointer
|
addui r8,r8,#1 ; increment the text pointer
|
bra IGB2
|
bra IGB2
|
IGBRET:
|
IGBRET:
|
lw r1,[sp]
|
lw r1,[sp]
|
ret #8
|
ret #8
|
|
|
Line 4956... |
Line 6358... |
; r8 = pointing to end of text in buffer
|
; r8 = pointing to end of text in buffer
|
;
|
;
|
TOUPBUF:
|
TOUPBUF:
|
subui sp,sp,#8
|
subui sp,sp,#8
|
sw lr,[sp]
|
sw lr,[sp]
|
setlo r8,BUFFER ; set up text pointer
|
lea r8,BUFFER ; set up text pointer
|
setlo r3,#0 ; clear quote flag
|
setlo r3,#0 ; clear quote flag
|
TOUPB1:
|
TOUPB1:
|
lb r1,[r8] ; get the next text char.
|
lb r1,[r8] ; get the next text char.
|
add r8,r8,#1
|
addui r8,r8,#1
|
beqi r1,#CR,TOUPBRT ; is it end of line?
|
beqi r1,#CR,TOUPBRT ; is it end of line?
|
beqi r1,#'"',DOQUO ; a double quote?
|
beqi r1,#'"',DOQUO ; a double quote?
|
beqi r1,#'''',DOQUO ; or a single quote?
|
beqi r1,#'''',DOQUO ; or a single quote?
|
bne r3,r0,TOUPB1 ; inside quotes?
|
bne r3,r0,TOUPB1 ; inside quotes?
|
call toUpper ; convert to upper case
|
call toUpper ; convert to upper case
|
sb r1,-1[r8] ; store it
|
sb r1,-1[r8] ; store it
|
bra TOUPB1 ; and go back for more
|
bra TOUPB1 ; and go back for more
|
DOQUO:
|
DOQUO:
|
bne r3,r0,DOQUO1; are we inside quotes?
|
bne r3,r0,DOQUO1; are we inside quotes?
|
or r3,r1,r0 ; if not, toggle inside-quotes flag
|
mov r3,r1 ; if not, toggle inside-quotes flag
|
bra TOUPB1
|
bra TOUPB1
|
DOQUO1:
|
DOQUO1:
|
bne r3,r1,TOUPB1 ; make sure we're ending proper quote
|
bne r3,r1,TOUPB1 ; make sure we're ending proper quote
|
setlo r3,#0 ; else clear quote flag
|
setlo r3,#0 ; else clear quote flag
|
bra TOUPB1
|
bra TOUPB1
|
Line 4984... |
Line 6386... |
|
|
|
|
; ===== Convert the character in r1 to upper case
|
; ===== Convert the character in r1 to upper case
|
;
|
;
|
toUpper
|
toUpper
|
blt r1,#'a',TOUPRET ; is it < 'a'?
|
blti r1,#'a',TOUPRET ; is it < 'a'?
|
bgt r1,#'z',TOUPRET ; or > 'z'?
|
bgti r1,#'z',TOUPRET ; or > 'z'?
|
sub r1,r1,#32 ; if not, make it upper case
|
subui r1,r1,#32 ; if not, make it upper case
|
TOUPRET
|
TOUPRET
|
ret
|
ret
|
|
|
|
|
; 'CHKIO' checks the input. If there's no input, it will return
|
; 'CHKIO' checks the input. If there's no input, it will return
|
Line 5000... |
Line 6402... |
;
|
;
|
CHKIO:
|
CHKIO:
|
subui sp,sp,#8 ; save link reg
|
subui sp,sp,#8 ; save link reg
|
sw lr,[sp]
|
sw lr,[sp]
|
call GOIN ; get input if possible
|
call GOIN ; get input if possible
|
beq r1,#-1,CHKRET2 ; if Zero, no input
|
beqi r1,#-1,CHKRET2 ; if Zero, no input
|
bnei r1,#CTRLC,CHKRET ; is it control-C?
|
bnei r1,#CTRLC,CHKRET ; is it control-C?
|
jmp WSTART ; if so, do a warm start
|
jmp WSTART ; if so, do a warm start
|
CHKRET2:
|
CHKRET2:
|
xor r1,r1,r1
|
xor r1,r1,r1
|
CHKRET:
|
CHKRET:
|
Line 5026... |
Line 6428... |
subui sp,sp,#16
|
subui sp,sp,#16
|
sw r5,[sp]
|
sw r5,[sp]
|
sw lr,8[sp]
|
sw lr,8[sp]
|
mov r5,r1 ; r5 = pointer to message
|
mov r5,r1 ; r5 = pointer to message
|
PRMESG1:
|
PRMESG1:
|
add r5,r5,#1
|
addui r5,r5,#1
|
lb r1,-1[r5] ; get the char.
|
lbu r1,-1[r5] ; get the char.
|
beq r1,r0,PRMRET
|
beq r1,r0,PRMRET
|
call GOOUT ;else display it trashes r4
|
call GOOUT ;else display it trashes r4
|
bra PRMESG1
|
bra PRMESG1
|
PRMRET:
|
PRMRET:
|
mov r1,r5
|
mov r1,r5
|
Line 5072... |
Line 6474... |
;
|
;
|
OUTC:
|
OUTC:
|
jmp DisplayChar
|
jmp DisplayChar
|
|
|
|
|
; ===== Input a character from the console into register D0 (or
|
; ===== Input a character from the console into register R1 (or
|
; return Zero status if there's no character available).
|
; return Zero status if there's no character available).
|
;
|
;
|
INC:
|
INC:
|
jmp KeybdGetChar
|
jmp KeybdGetChar
|
|
|
Line 5126... |
Line 6528... |
ret #8
|
ret #8
|
|
|
; MOVE.B #228,D7 return to Tutor
|
; MOVE.B #228,D7 return to Tutor
|
; TRAP #14
|
; TRAP #14
|
|
|
.align 16
|
msgInit db CR,LF,"Raptor64 Tiny BASIC v1.0",CR,LF,"(C) 2013 Robert Finch",CR,LF,LF,0
|
msgInit db CR,LF,"Raptor64 Tiny BASIC v1.0",CR,LF,"(C) 2012 Robert Finch",CR,LF,LF,0
|
|
OKMSG db CR,LF,"OK",CR,LF,0
|
OKMSG db CR,LF,"OK",CR,LF,0
|
msgWhat db "What?",CR,LF,0
|
msgWhat db "What?",CR,LF,0
|
SRYMSG db "Sorry."
|
SRYMSG db "Sorry."
|
CLMSG db CR,LF,0
|
CLMSG db CR,LF,0
|
msgReadError db "Compact FLASH read error",CR,LF,0
|
msgReadError db "Compact FLASH read error",CR,LF,0
|
Line 5237... |
Line 6638... |
mfspr r1,EPC
|
mfspr r1,EPC
|
call DisplayWord
|
call DisplayWord
|
wait
|
wait
|
jmp start
|
jmp start
|
dberr_rout:
|
dberr_rout:
|
|
lw sp,#0x100200100
|
lea r1,msgdberr
|
lea r1,msgdberr
|
call DisplayString
|
call DisplayString
|
mfspr r1,ERRADR
|
mfspr r1,ERRADR
|
call DisplayWord
|
call DisplayWord
|
lea r1,msgEPC
|
lea r1,msgEPC
|
Line 5265... |
Line 6667... |
db "Data bus error at: ",0
|
db "Data bus error at: ",0
|
msgEPC:
|
msgEPC:
|
db " EPC: ",0
|
db " EPC: ",0
|
msgiberr:
|
msgiberr:
|
db "Err fetching instruction at: ",0
|
db "Err fetching instruction at: ",0
|
.align 16
|
.align 4
|
|
|
;------------------------------------------------------------------------------
|
;------------------------------------------------------------------------------
|
; IRQ routine
|
; IRQ routine
|
|
;
|
|
; Interrupts are automatically disabled at the time of the interrupt in order
|
|
; to prevent nested interrupts from occuring. Interrupts are re-enabled by
|
|
; the IRET instruction at the end of the interrupt routine. If the interrupt
|
|
; turns out to not match a hardware interrupt, then a software context
|
|
; switching interrupt is assumed.
|
|
;
|
|
; This routine uses it's own private interrupt stack; the stack of the
|
|
; interrupted context is not used at all. A couple of working registers are
|
|
; saved off not on the stack. We can get away with this because nested
|
|
; interrupts are not allowed.
|
;------------------------------------------------------------------------------
|
;------------------------------------------------------------------------------
|
;
|
;
|
irqrout:
|
irqrout:
|
subui sp,sp,#32
|
sw sp,sp_save ; use our own private stack for interrupt processing
|
sw r1,[sp] ; save off a working register
|
sw lr,lr_save ; so, save off the sp and working registers
|
sw r2,8[sp] ; and a second work register
|
sw r26,r26_save
|
sw r26,16[sp] ; save off implicit constant builder reg
|
sw r1,r1_save
|
sw lr,24[sp]
|
sw r2,r2_save
|
|
|
|
lw sp,#0x1_00001000 ; the second two kbytes
|
inch r1,PIC ; r1= which IRQ line is active
|
inch r1,PIC ; r1= which IRQ line is active
|
|
|
|
; Dispatch fork, in order of required timeliness
|
|
|
|
beqi r1,#2,irq1000Hz
|
|
beqi r1,#3,irq100Hz
|
|
beqi r1,#8,irqSerial
|
|
beqi r1,#13,irqRaster
|
|
beqi r1,#15,irqKeybd
|
|
beqi r1,#1,irqColdStart ; CTRL-ALT-DEL interrupt
|
|
|
|
; Here, none of the hardware interrupts were active so
|
|
; assume software context switch interrupt
|
|
;
|
|
lw sp,sp_save
|
|
lw lr,lr_save
|
|
lw r26,r26_save
|
|
lw r1,r1_save
|
|
lw r2,r2_save
|
|
iepp
|
|
iret
|
|
|
; 1000 Hz interrupt
|
; 1000 Hz interrupt
|
; This IRQ must be fast, so it's placed inline
|
; This IRQ must be fast, so it's placed inline. It's also the first
|
|
; IRQ checked for in the interrupt dispatch.
|
; Increments the millisecond counter, and switches to the next context
|
; Increments the millisecond counter, and switches to the next context
|
;
|
;
|
irq1000Hz:
|
irq1000Hz:
|
bnei r1,#2,irq100Hz
|
outb r0,0xDCFFFD ; acknowledge interrupt
|
outb r0,0xFFFFFFFF_FFFF0000 ; acknowledge interrupt
|
|
lw r1,Milliseconds ; increment milliseconds count
|
lw r1,Milliseconds ; increment milliseconds count
|
addui r1,r1,#1
|
addui r1,r1,#1
|
sw r1,Milliseconds
|
sw r1,Milliseconds
|
lea r2,TEXTSCR
|
lw sp,sp_save
|
inch r1,332[r2]
|
lw lr,lr_save
|
addui r1,r1,#1
|
lw r26,r26_save
|
outc r1,332[r2]
|
lw r1,r1_save
|
lw lr,24[sp]
|
lw r2,r2_save
|
lw r26,16[sp] ; restore registers from stack
|
|
lw r2,8[sp]
|
|
lw r1,[sp]
|
|
addui sp,sp,#32 ; restore stack pointer
|
|
iepp ; move to the next context
|
iepp ; move to the next context
|
nop
|
|
nop
|
|
nop
|
|
iret ; return to the next context
|
iret ; return to the next context
|
|
|
; 100 Hz interrupt
|
; 100 Hz interrupt
|
; This IRQ could have some work to do, including flashing a cursor. So
|
; This IRQ could have some work to do, including flashing a cursor. So
|
; we call a subroutine.
|
; we call a subroutine.
|
;
|
;
|
irq100Hz:
|
irq100Hz:
|
bnei r1,#3,irqSerial
|
|
lw r1,p100IRQvec
|
lw r1,p100IRQvec
|
; jal lr,[r1]
|
; jal lr,[r1]
|
call Pulse100
|
call Pulse100
|
bra irqret
|
irqret:
|
|
lw sp,sp_save
|
|
lw lr,lr_save
|
|
lw r26,r26_save
|
|
lw r1,r1_save
|
|
lw r2,r2_save
|
|
iret
|
|
|
irqSerial:
|
irqSerial:
|
bnei r1,#8,irqRaster
|
|
lw r1,serialIRQvec
|
lw r1,serialIRQvec
|
jal lr,[r1]
|
jal lr,[r1]
|
bra irqret
|
bra irqret
|
|
|
irqRaster:
|
irqRaster:
|
bnei r1,#13,irqKeybd
|
|
lw r1,rasterIRQvec
|
lw r1,rasterIRQvec
|
; jal lr,[r1]
|
; jal lr,[r1]
|
call RasterIRQfn
|
call RasterIRQfn
|
bra irqret
|
bra irqret
|
|
|
irqKeybd:
|
irqKeybd:
|
beqi r1,#1,ColdStart ; CTRL-ALT-DEL interrupt
|
|
bnei r1,#15,irqret
|
|
lw r1,keybdIRQvec
|
lw r1,keybdIRQvec
|
call KeybdIRQ
|
call KeybdIRQ
|
; jal lr,[r1]
|
; jal lr,[r1]
|
|
bra irqret
|
|
|
irqret:
|
irqColdStart:
|
lw lr,24[sp]
|
jmp ColdStart
|
lw r26,16[sp] ; restore registers from stack
|
|
lw r2,8[sp]
|
;------------------------------------------------------------------------------
|
lw r1,[sp]
|
; NMI routine
|
addui sp,sp,#32 ; restore stack pointer
|
;
|
|
; The NMI line is tied to the parity error signal. But also any non-initialized
|
|
; interrupts get sent here.
|
|
;------------------------------------------------------------------------------
|
|
;
|
|
nmirout:
|
|
sw sp,sp_save
|
|
sw r1,r1_save
|
|
sw r26,r26_save
|
|
lw sp,#0x100001000
|
|
outb r0,0xDCFFFE ; acknowledge interrupt
|
|
lea r1,msgPerr
|
|
call DisplayString
|
|
mfspr r1,IPC
|
|
call DisplayWord
|
|
call CRLF
|
|
lw sp,sp_save
|
|
lw r1,r1_save
|
|
lw r26,r26_save
|
iret
|
iret
|
|
|
|
msgPerr:
|
|
db "Parity error at: ",0
|
|
|
|
|
;-------------------------------------------
|
;-------------------------------------------
|
; NMI routine
|
; Unimplemented instructions end up here
|
;-------------------------------------------
|
;-------------------------------------------
|
nmirout:
|
.align 4
|
|
ui_irout:
|
|
subui sp,sp,#8
|
|
sw r1,[sp]
|
|
lea r1,msgUnimp
|
|
call DisplayString
|
|
mfspr r1,IPC
|
|
call DisplayWord
|
|
call CRLF
|
|
lw r1,[sp]
|
|
addui sp,sp,#8
|
|
; hang the context
|
|
ui_irout1:
|
|
bra ui_irout1
|
iret
|
iret
|
|
|
|
msgUnimp:
|
|
db "Unimplemented instruction at: ",0
|
|
|
;-------------------------------------------
|
;-------------------------------------------
|
; Handle miss on Data TLB
|
; Handle miss on Data TLB
|
;-------------------------------------------
|
;-------------------------------------------
|
|
.align 4
|
DTLBHandler:
|
DTLBHandler:
|
sw r1,0xFFFF_FFFF_FFFF_0000
|
sw r1,0xFFFF_FFFF_FFFF_0000
|
sw r2,0xFFFF_FFFF_FFFF_0008
|
sw r2,0xFFFF_FFFF_FFFF_0008
|
dh1:
|
dh1:
|
omgi r1,#0 ; try open mutex gate #0 (TLB protector)
|
omgi r1,#0 ; try open mutex gate #0 (TLB protector)
|
Line 5385... |
Line 6854... |
org 0xFFFF_FFFF_FFFF_FFC0
|
org 0xFFFF_FFFF_FFFF_FFC0
|
jmp DTLBHandler
|
jmp DTLBHandler
|
nop
|
nop
|
nop
|
nop
|
|
|
; NMI vector
|
|
org 0xFFFF_FFFF_FFFF_FFE0
|
org 0xFFFF_FFFF_FFFF_FFE0
|
jmp nmirout
|
dw 0 ;
|
nop
|
dw 0 ;
|
nop
|
|
|
|
; RST vector
|
; RST vector
|
org 0xFFFF_FFFF_FFFF_FFF0
|
org 0xFFFF_FFFF_FFFF_FFF0
|
jmp start
|
jmp start
|
nop
|
|
nop
|
|
|
|
|
; ROM checksum goes here
|
|
|
|
org 0xFFFF_FFFF_FFFF_FFF8
|
|
dw 0
|
|
|
No newline at end of file
|
No newline at end of file
|