URL
https://opencores.org/ocsvn/rf68000/rf68000/trunk
Subversion Repositories rf68000
[/] [rf68000/] [trunk/] [software/] [examples/] [boot.asm] - Rev 2
Go to most recent revision | Compare with Previous | Blame | View Log
;-------------------------------------------------------------------------------;; system memory map;;; 00000000 +----------------+ <+; | startup sp,pc | 8 B |; 00000008 +----------------+ |; | vectors | pair shared+; 00000400 +----------------+ |; | bios mem | |; 00001000 +----------------+ |; | bios code | |; 00008000 +----------------+ <+; | unused |; 00040000 +----------------+; | local ram |; 00042000 +----------------+; | unused |; 00100000 +----------------+; | global ram |; 00101000 +----------------+; | serial rcvbuf |; 00102000 +----------------+; | unused |; 20000000 +----------------+; | |; | |; | |; : dram memory : 512 MB; | |; | |; | |; 40000000 +----------------+; | |; : unused :; | |; FD000000 +----------------+; | |; : I/O area : 1.0 M; | |; FFE00000 +----------------+; | |; : unused :; | |; FFFFFFFF +----------------+;;-------------------------------------------------------------------------------;CTRLC EQU $03CTRLH EQU $08CTRLS EQU $13CTRLX EQU $18CTRLZ EQU $1ALF EQU $0ACR EQU $0DXON EQU $11XOFF EQU $13SC_F12 EQU $07SC_C EQU $21SC_T EQU $2CSC_Z EQU $1ASC_KEYUP EQU $F0SC_EXTEND EQU $E0SC_CTRL EQU $14SC_RSHIFT EQU $59SC_NUMLOCK EQU $77SC_SCROLLLOCK EQU $7ESC_CAPSLOCK EQU $58SC_ALT EQU $11SC_LSHIFT EQU $12SC_DEL EQU $71 ; extendSC_LCTRL EQU $58SC_TAB EQU $0DTEXTREG EQU $1E3FF00 ; virtual addressestxtscreen EQU $1E00000semamem EQU $1E50000ACIA EQU $1E60000ACIA_RX EQU 0ACIA_TX EQU 0ACIA_STAT EQU 4ACIA_CMD EQU 8ACIA_CTRL EQU 12PLIC EQU $1E90000MMU EQU $FDC00000 ; physical addressleds EQU $1EFFF00 ; virtual addresseskeybd EQU $1EFFE00KEYBD EQU $1EFFE00RAND EQU $1EFFD00RAND_NUM EQU $1EFFD00RAND_STRM EQU $1EFFD04RAND_MZ EQU $1EFFD08RAND_MW EQU $1EFFD0CRST_REG EQU $1EFFC00IO_BITMAP EQU $1F00000IOFocus EQU $0100000SERIAL_SEMA EQU 2KEYBD_SEMA EQU 3RAND_SEMA EQU 4SCREEN_SEMA EQU 5MEMORY_SEMA EQU 6TCB_SEMA EQU 7datadc.l $00040FFCdc.l startdc.l bus_errdc.l 0dc.l illegal_trap * ILLEGAL instructiondc.l 0dc.l EXCEPTION_6 * CHKdc.l EXCEPTION_7 * TRAPVdc.l 0dc.l 0; 10dc.l 0dc.l 0dc.l 0dc.l 0dc.l 0dc.l 0dc.l 0dc.l 0dc.l 0dc.l 0; 20dc.l 0dc.l 0dc.l 0dc.l 0dc.l SpuriousIRQdc.l 0dc.l 0dc.l irq3_routdc.l 0dc.l 0; 30dc.l TickIRQ ; IRQ 30 - timer / keyboarddc.l nmi_routdc.l 0dc.l 0dc.l 0dc.l trap3 ; breakpointdc.l 0dc.l 0dc.l 0dc.l 0; 40dc.l 0dc.l 0dc.l 0dc.l 0dc.l 0dc.l 0dc.l 0dc.l TRAP15dc.l 0dc.l 0; 50dc.l 0dc.l 0dc.l 0dc.l 0dc.l 0dc.l 0dc.l 0dc.l 0dc.l 0dc.l io_irq; 60dc.l KeybdIRQdc.l SerialIRQdc.l 0dc.l brdisp_trapdc.l 0dc.l 0dc.l 0dc.l 0dc.l 0dc.l 0org $400InstalledIRQ:dc.l 0dc.l 0dc.l 0dc.l 0dc.l 0dc.l 0dc.l 0dc.l 0dc.l 0dc.l 0dc.l 0dc.l 0dc.l 0dc.l 0dc.l 0dc.l 0dc.l 0dc.l 0dc.l 0dc.l 0dc.l 0dc.l 0dc.l 0dc.l 0dc.l 0dc.l 0dc.l 0dc.l 0dc.l 0dc.l 0dc.l 0dc.l 0dc.l 0dc.l 0dc.l 0dc.l 0dc.l 0dc.l 0dc.l 0dc.l 0dc.l 0dc.l 0dc.l 0dc.l 0dc.l 0dc.l 0dc.l 0dc.l 0dc.l 0dc.l 0dc.l 0dc.l 0dc.l 0dc.l 0dc.l 0dc.l 0dc.l 0dc.l 0dc.l 0dc.l 0dc.l 0dc.l 0dc.l 0dc.l 0org $500;-------------------------------------------------------------------------------;-------------------------------------------------------------------------------; BIOS variables which must be local (not shared) to each coreCursorRow equ $40000CursorCol equ $40001TextPos equ $40002TextCurpos equ $40002TextScr equ $40004S19StartAddress equ $40008KeybdEcho equ $4000CKeybdWaitFlag equ $4000DCmdBuf equ $40040CmdBufEnd equ $40080fgColor equ $40084bkColor equ $40088TextRows equ $4008CTextCols equ $4008DRegsave equ $40100numBreakpoints equ 8BreakpointFlag equ $40200NumSetBreakpoints equ $40202 ; to $40203Breakpoints equ $40220 ; to $40240BreakpointWords equ $40280 ; to $402A0;RunningTCB equ $40300TimerStack equ $40BFC; Keyboard buffer is in shared memorymemend equ $00100004KeybdLEDs equ $0010000E_KeyState1 equ $0010000F_KeyState2 equ $00100010_KeybdHead equ $00100011_KeybdTail equ $00100012_KeybdCnt equ $00100013KeybdID equ $00100016_KeybdBuf equ $00100020S19Checksum equ $00100150SerTailRcv equ $00100160SerHeadRcv equ $00100162SerRcvXon equ $00100164SerRcvXoff equ $00100165SerRcvBuf equ $00101000include "..\Femtiki\source\kernel\Femtiki_vars.x68"codealign 2start:move.w #$2700,sr ; enable level 6 and higher interruptsmoveq #0,d0 ; set address space zeromovec d0,asid; Prepare local variable storagemove.w #1023,d0 ; 1024 longs to clearlea $40000,a0 ; non shared local memory address.0111:clr.l (a0)+ ; clear the memory areadbra d0,.0111move.l #$1fffff,fgColor ; set foreground / background colormove.l #$00003f,bkColormovec.l coreno,d0 ; get core number (2 to 9)subi.b #2,d0 ; adjust (0 to 7)mulu #16384,d0 ; compute screen locationaddi.l #$FD000000,d0move.l d0,TextScrmove.b #64,TextCols ; set rows and columnsmove.b #32,TextRowsmovec.l coreno,d0 ; get core numbercmpi.b #2,d0bne start_othermove.b d0,IOFocus ; Set the IO focus in global memorybsr InitMMU ; Can't access anything till this is donebsr InitIOBitmap ; not going to get far without thisbsr InitSemaphoresbsr InitRandbsr Delay3s ; give devices time to resetbsr clear_screenbsr _KeybdInit; bsr InitIRQbsr SerialInit; Write startup message to screenlea msg_start,a1bsr DisplayString; bsr FemtikiInitmovec coreno,d0swap d0moveq #1,d1bsr UnlockSemaphore ; allow another cpu accessmoveq #0,d1bsr UnlockSemaphore ; allow other cpus to proceedmove.w #$A4A4,leds ; diagnosticsbsr init_plic ; initialize platform level interrupt controllerbra StartMonbsr cpu_test; lea brdisp_trap,a0 ; set brdisp trap vector; move.l a0,64*4loop2:move.l #-1,d0loop1:move.l d0,d1lsr.l #8,d1lsr.l #8,d1move.b d1,ledsdbra d0,loop1bra loop2start_other:bsr Delay3s2 ; need time for system setup (io_bitmap etc.)bsr clear_screenmovec coreno,d1bsr DisplayBytelea msg_core_start,a1bsr DisplayString; bsr FemtikiInitIRQdo_nothing:bra StartMonbra do_nothing;------------------------------------------------------------------------------; Initialize the MMU to allow thread #0 access to IO;------------------------------------------------------------------------------align 2mmu_adrtbl: ; virtual address[24:16], physical address[31:16] bytes reversed!dc.l $0010,$10000300 ; global scratch paddc.l $01E0,$00FD0300dc.l $01E1,$01FD0300dc.l $01E2,$02FD0300dc.l $01E3,$03FD0300dc.l $01E5,$05FD0300dc.l $01E6,$06FD0300dc.l $01E9,$09FD0300dc.l $01EF,$0FFD0300dc.l $01F0,$10FD0300evenInitMMU:lea MMU+8,a0 ; first 128kB is local RAMmove.l #$32000,d2 ; map all pages to DRAMmove.l #510,d0 ; then override for IO later.0002move.l d2,d1bsr rbomove.l d1,(a0)+addi.w #1,d2 ; increment DRAM page numberdbra d0,.0002lea MMU,a0 ; now program IO accesslea mmu_adrtbl,a1moveq #9,d0.0001move.l (a1)+,d2lsl.l #2,d2move.l (a1)+,(a0,d2.w)dbra d0,.0001rts;------------------------------------------------------------------------------; The IO bitmap needs to be initialized to allow access to IO.;------------------------------------------------------------------------------InitIOBitmap:; mark all IO inaccessiblemove.w #8191,d0lea IO_BITMAP,a0.0001clr.l (a0)+dbra d0,.0001; Give the system asid=0 complete access to the IO areamove.w #127,d0moveq #-1,d1lea IO_BITMAP,a0.0002move.l d1,(a0)+dbra d0,.0002; Give all cores access to the screenlea IO_BITMAP+128,a0moveq #-1,d1move.w #62,d0 ; 63 more bitmaps to fill.0004swap d0move.w #31,d0 ; 32 bytes for the screen area per bitmap.0003move.l d1,(a0)+dbra d0,.0003swap d0lea 96(a0),a0dbra d0,.0004rts;------------------------------------------------------------------------------; RandInit; Initialize random number generator.;; Modifies:; none; Parameters:; none; Returns:; none;------------------------------------------------------------------------------InitRand:RandInit:movem.l d0/d1,-(a7)movec coreno,d0swap d0moveq #RAND_SEMA,d1bsr LockSemaphoreswap d0lsl.l #6,d0 ; allow 64 streams per coremove.l d0,RAND_STRM ; select the streammove.l #$12345678,RAND_MZ ; initialize to some valuemove.l #$98765432,RAND_MWmove.l #777777777,RAND_NUM ; generate first numbermovec coreno,d0swap d0moveq #RAND_SEMA,d1bsr UnlockSemaphoremovem.l (a7)+,d0/d1rts;------------------------------------------------------------------------------;------------------------------------------------------------------------------RandGetNum:movem.l d0/d2,-(a7)movec coreno,d0swap d0moveq #RAND_SEMA,d1bsr LockSemaphorelsl.l #6,d0move.l d0,RAND_STRM ; select the streammove.l RAND_NUM,d2clr.l RAND_NUM ; generate next numbermovec coreno,d0swap d0moveq #RAND_SEMA,d1bsr UnlockSemaphoremove.l d2,d1movem.l (a7)+,d0/d2rts;------------------------------------------------------------------------------; RandWait; Wait some random number of clock cycles before returning.;------------------------------------------------------------------------------RandWait:movem.l d0/d1,-(a7)bsr RandGetNumandi.w #15,d1.0001:nopdbra d1,.0001movem.l (a7)+,d0/d1rts;------------------------------------------------------------------------------; Initialize semaphores; - all semaphores are set to unlocked except the first one, which is locked; for core #2.;; Parameters:; <none>; Modifies:; <none>; Returns:; <none>;------------------------------------------------------------------------------InitSemaphores:movem.l d1/a0,-(a7)lea semamem,a0move.l #$20000,$2000(a0) ; lock the first semaphore for core #2, thread #0move.w #254,d1.0001:lea 4(a0),a0clr.l $2000(a0) ; write zeros to unlockdbra d1,.0001movem.l (a7)+,d1/a0rts; -----------------------------------------------------------------------------; Parameters:; d1 semaphore number;; Side Effects:; increments semaphore, saturates at 255;; Returns:; z flag set if semaphore was zero; -----------------------------------------------------------------------------;IncrementSemaphore:; movem.l d1/a0,-(a7) ; save registers; lea semamem,a0 ; point to semaphore memory; ext.w d1 ; make d1 word value; asl.w #4,d1 ; align to memory; tst.b 1(a0,d1.w) ; read (test) value for zero; movem.l (a7)+,a0/d1 ; restore regs; rts; -----------------------------------------------------------------------------; Parameters:; d1 semaphore number;; Side Effects:; decrements semaphore, saturates at zero;; Returns:; z flag set if semaphore was zero; -----------------------------------------------------------------------------;DecrementSemaphore:; movem.l d1/a0,-(a7) ; save registers; lea semamem,a0 ; point to semaphore memory; andi.w #255,d1 ; make d1 word value; asl.w #4,d1 ; align to memory; tst.b 1(a0,d1.w) ; read (test) value for zero; movem.l (a7)+,a0/d1 ; restore regs; rts; -----------------------------------------------------------------------------; Lock a semaphore;; Parameters:; d0 = key; d1 = semaphore number; -----------------------------------------------------------------------------LockSemaphore:movem.l d1/a0,-(a7) ; save registerslea semamem,a0 ; point to semaphore memory lock areaandi.w #255,d1 ; make d1 word valuelsl.w #2,d1 ; align to memory.0001:move.l d0,(a0,d1.w) ; try and write the semaphorecmp.l (a0,d1.w),d0 ; did it lock?bne.s .0001 ; no, try againmovem.l (a7)+,a0/d1 ; restore regsrts; -----------------------------------------------------------------------------; Unlocks a semaphore even if not the owner.;; Parameters:; d1 semaphore number; -----------------------------------------------------------------------------ForceUnlockSemaphore:movem.l d1/a0,-(a7) ; save registerslea semamem+$3000,a0 ; point to semaphore memory read/write areaandi.w #255,d1 ; make d1 word valuelsl.w #2,d1 ; align to memoryclr.l (a0,d1.w) ; write zero to unlockmovem.l (a7)+,a0/d1 ; restore regsrts; -----------------------------------------------------------------------------; Unlocks a semaphore. Must be the owner to have effect.; Three cases:; 1) the owner, the semaphore will be reset to zero; 2) not the owner, the write will be ignored; 3) already unlocked, the write will be ignored;; Parameters:; d0 = key; d1 = semaphore number; -----------------------------------------------------------------------------UnlockSemaphore:movem.l d1/a0,-(a7) ; save registerslea semamem+$1000,a0 ; point to semaphore memory unlock areaandi.w #255,d1 ; make d1 word valuelsl.w #2,d1 ; align to memorymove.l d0,(a0,d1.w) ; write matching value to unlockmovem.l (a7)+,a0/d1 ; restore regsrts; -----------------------------------------------------------------------------; Parameters:; d1 = semaphore to lock / unlock; -----------------------------------------------------------------------------T15LockSemaphore:movec coreno,d0or.l RunningTCB,d0bra LockSemaphoreT15UnlockSemaphore:movec coreno,d0or.l RunningTCB,d0bra UnlockSemaphore; -----------------------------------------------------------------------------; Delay for a few seconds to allow some I/O reset operations to take place.; -----------------------------------------------------------------------------Delay3s:move.l #3000000,d0 ; this should take a few seconds to looplea leds,a0 ; a0 = address of LED output registerbra dly3s1 ; branch to the loopdly3s2:swap d0 ; loop is larger than 16-bitsdly3s1:move.l d0,d1 ; the counter cycles fast, so use upper bits for displayrol.l #8,d1 ; could use swap here, but lets test rolrol.l #8,d1move.b d1,(a0) ; set the LEDsdbra d0,dly3s1 ; decrement and branch backswap d0dbra d0,dly3s2rtsDelay3s2:movec coreno,d0 ; vary delay by core to stagger startuplsl.l #8,d0addi.l #3000000,d0 ; this should take a few seconds to loopbra .0001 ; branch to the loop.0002swap d0 ; loop is larger than 16-bits.0001dbra d0,.0001 ; decrement and branch backswap d0dbra d0,.0002rtsinclude "cputest.asm"include "TinyBasic.asm"include "..\Femtiki\source\kernel\Femtiki.x68"; -----------------------------------------------------------------------------; Gets the screen color in d0 and d1.; -----------------------------------------------------------------------------get_screen_color:move.l fgColor,d0 ; get foreground colorasl.l #5,d0 ; shift into positionori.l #$40000000,d0 ; set prioritymove.l bkColor,d1lsr.l #8,d1lsr.l #8,d1andi.l #31,d1 ; mask off extra bitsor.l d1,d0 ; set background color bits in upper long wordmove.l bkColor,d1 ; get background colorasl.l #8,d1 ; shift into position for display ramasl.l #8,d1rts; -----------------------------------------------------------------------------; -----------------------------------------------------------------------------get_screen_address:move.l TextScr,a0rts; -----------------------------------------------------------------------------; -----------------------------------------------------------------------------clear_screen:movem.l d0/d1/d2/a0,-(a7)movec coreno,d0swap d0moveq #SCREEN_SEMA,d1bsr LockSemaphorebsr get_screen_address ; a0 = pointer to screen areamove.b TextRows,d0 ; d0 = rowsmove.b TextCols,d2 ; d2 = colsext.w d0 ; convert to wordext.w d2 ; convert to wordmulu d0,d2 ; d2 = number of character cells to clearbsr get_screen_color ; get the color bitsori.w #32,d1 ; load space characterrol.w #8,d1 ; swap endian, text controller expects little endianswap d1rol.w #8,d1rol.w #8,d0 ; swap endianswap d0rol.w #8,d0loop3:move.l d1,(a0)+ ; copy char plus bkcolor to cellmove.l d0,(a0)+ ; copy fgcolor to celldbra d2,loop3movec coreno,d0swap d0moveq #SCREEN_SEMA,d1bsr UnlockSemaphoremovem.l (a7)+,d0/d1/d2/a0rtsCRLF:move.l d1,-(a7)move.b #13,d1bsr DisplayCharmove.b #10,d1bsr DisplayCharmove.l (a7)+,d1rts;------------------------------------------------------------------------------;------------------------------------------------------------------------------UpdateTextPos:move.b CursorRow,d0 ; compute screen locationandi.w #$7f,d0move.b TextCols,d2ext.w d2mulu.w d2,d0move.l d0,d3move.b CursorCol,d2andi.w #$ff,d2add.w d2,d0move.w d0,TextPos ; save cursor posrts;------------------------------------------------------------------------------; Calculate screen memory location from CursorRow,CursorCol.; Destroys d0,d2,a0;------------------------------------------------------------------------------CalcScreenLoc:bsr UpdateTextPosext.l d0 ; make it into a longasl.l #3,d0 ; 8 bytes per charbsr get_screen_addressadd.l d0,a0 ; a0 = screen locationrts;------------------------------------------------------------------------------; Display a character on the screen; d1.b = char to display;------------------------------------------------------------------------------DisplayChar:movem.l d1/d2/d3,-(a7)movec coreno,d2cmpi.b #2,d2; bne.s .0001; bsr SerialPutChar.0001:andi.l #$ff,d1 ; zero out upper bytes of d1cmpi.b #13,d1 ; carriage return ?bne dccrclr.b CursorCol ; just set cursor column to zero on a CRdcx14:bsr SyncCursor ; set position in text controllerdcx7:movem.l (a7)+,d1/d2/d3rtsdccr:cmpi.b #$91,d1 ; cursor right ?bne.s dcx6move.b TextCols,d2sub.b #1,d2sub.b CursorCol,d2beq.s dcx7addi.b #1,CursorColbra.s dcx14dcx6:cmpi.b #$90,d1 ; cursor up ?bne.s dcx8cmpi.b #0,CursorRowbeq.s dcx7subi.b #1,CursorRowbra.s dcx14dcx8:cmpi.b #$93,d1 ; cursor left?bne.s dcx9cmpi.b #0,CursorColbeq.s dcx7subi.b #1,CursorColbra.s dcx14dcx9:cmpi.b #$92,d1 ; cursor down ?bne.s dcx10move.b TextRows,d2sub.b #1,d2cmp.b CursorRow,d2beq.s dcx7addi.b #1,CursorRowbra.s dcx14dcx10:cmpi.b #$94,d1 ; cursor home ?bne.s dcx11cmpi.b #0,CursorColbeq.s dcx12clr.b CursorColbra dcx14dcx12:clr.b CursorRowbra dcx14dcx11:movem.l d0/d1/d2/a0,-(a7)cmpi.b #$99,d1 ; delete ?beq.s doDeletecmpi.b #CTRLH,d1 ; backspace ?beq.s doBackspacecmpi.b #CTRLX,d1 ; delete line ?beq doCtrlXcmpi.b #10,d1 ; linefeed ?beq.s dclf; regular charbsr CalcScreenLoc ; a0 = screen locationmove.l d1,d2 ; d2 = charbsr get_screen_color ; d0,d1 = coloror.l d2,d1 ; d1 = char + colorrol.w #8,d1 ; text controller expects little endian dataswap d1rol.w #8,d1move.l d1,(a0)rol.w #8,d0 ; swap bytesswap d0 ; swap halfsrol.w #8,d0 ; swap remaining bytesmove.l d0,4(a0)bsr IncCursorPosbsr SyncCursorbra dcx4dclf:bsr IncCursorRowdcx16:bsr SyncCursordcx4:movem.l (a7)+,d0/d1/d2/a0 ; get back a0movem.l (a7)+,d1/d2/d3rts;---------------------------; CTRL-H: backspace;---------------------------doBackspace:cmpi.b #0,CursorCol ; if already at start of linebeq.s dcx4 ; nothing to dosubi.b #1,CursorCol ; decrement column;---------------------------; Delete key;---------------------------doDelete:movem.l d0/d1/a0,-(a7) ; save off screen locationbsr CalcScreenLoc ; a0 = screen locationmove.b CursorCol,d0.0001:move.l 8(a0),(a0) ; pull remaining characters on line over 1move.l 12(a0),4(a0) ; pull remaining characters on line over 1lea 8(a0),a0addi.b #1,d0cmp.b TextCols,d0blo.s .0001bsr get_screen_colormove.w #' ',d1 ; terminate line with a spacerol.w #8,d1swap d1rol.w #8,d1move.l d1,-8(a0)movem.l (a7)+,d0/d1/a0bra.s dcx16 ; finished;---------------------------; CTRL-X: erase line;---------------------------doCtrlX:clr.b CursorCol ; Reset cursor to start of linemove.b TextCols,d0 ; and display TextCols number of spacesext.w d0ext.l d0move.b #' ',d1 ; d1 = space char.0001:; DisplayChar is called recursively here; It's safe to do because we know it won't recurse again due to the; fact we know the character being displayed is a space charbsr DisplayCharsubq #1,d0bne.s .0001clr.b CursorCol ; now really go back to start of linebra.s dcx16 ; we're done;------------------------------------------------------------------------------; Increment the cursor position, scroll the screen if needed.;------------------------------------------------------------------------------IncCursorPos:addi.w #1,TextCurposaddi.b #1,CursorColmove.b TextCols,d0cmp.b CursorCol,d0bhs.s icc1clr.b CursorColIncCursorRow:addi.b #1,CursorRowmove.b TextRows,d0cmp.b CursorRow,d0bhi.s icc1move.b TextRows,d0move.b d0,CursorRow ; in case CursorRow is way oversubi.b #1,CursorRowext.w d0asl.w #1,d0sub.w d0,TextCurposbsr ScrollUpicc1:rts;------------------------------------------------------------------------------; Scroll screen up.;------------------------------------------------------------------------------ScrollUp:movem.l d0/d1/a0/a5,-(a7) ; save off some regsmovec coreno,d0swap d0moveq #SCREEN_SEMA,d1bsr LockSemaphorebsr get_screen_addressmove.l a0,a5 ; a5 = pointer to text screen.0003:move.b TextCols,d0 ; d0 = columnsmove.b TextRows,d1 ; d1 = rowsext.w d0 ; make cols into a word valueext.w d1 ; make rows into a word valueasl.w #3,d0 ; make into cell indexlea 0(a5,d0.w),a0 ; a0 = pointer to second row of text screenlsr.w #3,d0 ; get back d0subq #1,d1 ; number of rows-1mulu d1,d0 ; d0 = count of characters to move.0001:move.l (a0)+,(a5)+ ; each char is 64 bitsmove.l (a0)+,(a5)+dbra d0,.0001movec coreno,d0swap d0moveq #SCREEN_SEMA,d1bsr UnlockSemaphoremovem.l (a7)+,d0/d1/a0/a5; Fall through into blanking out last line;------------------------------------------------------------------------------; Blank out the last line on the screen.;------------------------------------------------------------------------------BlankLastLine:movem.l d0/d1/d2/a0,-(a7)movec coreno,d0swap d0moveq #SCREEN_SEMA,d1bsr LockSemaphorebsr get_screen_addressmove.b TextRows,d0 ; d0 = rowsmove.b TextCols,d1 ; d1 = columnsext.w d0ext.w d1subq #1,d0 ; last row = #rows-1mulu d1,d0 ; d0 = index of last linelsl.w #3,d0 ; *8 bytes per charlea (a0,d0.w),a0 ; point a0 to last rowmove.b TextCols,d2 ; number of text cells to clearext.w d2subi.w #1,d2 ; count must be one less than desiredbsr get_screen_color ; d0,d1 = screen colormove.w #32,d1 ; set the character for display in low 16 bitsbsr rbo ; reverse the byte orderrol.w #8,d0swap d0rol.w #8,d0.0001:move.l d0,(a0)+move.l d1,(a0)+dbra d2,.0001movec coreno,d0swap d0moveq #SCREEN_SEMA,d1bsr UnlockSemaphoremovem.l (a7)+,d0/d1/d2/a0rts;------------------------------------------------------------------------------; Display a string on the screen.;------------------------------------------------------------------------------DisplayString:movem.l d0/d1/a1,-(a7)dspj1:clr.l d1 ; clear upper bits of d1move.b (a1)+,d1 ; move string char into d1beq.s dsret ; is it end of string ?bsr DisplayChar ; display characterbra.s dspj1 ; go back for next characterdsret:movem.l (a7)+,d0/d1/a1rts;------------------------------------------------------------------------------; Display a string on the screen followed by carriage return / linefeed.;------------------------------------------------------------------------------DisplayStringCRLF:bsr DisplayStringbra CRLF;------------------------------------------------------------------------------; Display a string on the screen limited to 255 chars max.;------------------------------------------------------------------------------DisplayStringLimited:movem.l d0/d1/d2/a1,-(a7)move.w d1,d2 ; d2 = max countandi.w #$00FF,d2 ; limit to 255 charsbra.s .0003 ; enter loop at bottom.0001:clr.l d1 ; clear upper bits of d1move.b (a1)+,d1 ; move string char into d1beq.s .0002 ; is it end of string ?bsr DisplayChar ; display character.0003:dbra d2,.0001 ; go back for next character.0002:movem.l (a7)+,d0/d1/d2/a1rtsDisplayStringLimitedCRLF:bsr DisplayStringLimitedbra CRLF;------------------------------------------------------------------------------; Set cursor position to top left of screen.;; Parameters:; <none>; Returns:; <none>; Registers Affected:; <none>;------------------------------------------------------------------------------HomeCursor:clr.b CursorRowclr.b CursorColclr.w TextPos; fall through;------------------------------------------------------------------------------; SyncCursor:;; Sync the hardware cursor's position to the text cursor position but only for; the core with the IO focus.;; Parameters:; <none>; Returns:; <none>; Registers Affected:; <none>;------------------------------------------------------------------------------SyncCursor:movem.l d0/d2,-(a7)bsr UpdateTextPosmovec coreno,d2cmp.b IOFocus,d2bne.s .0001subi.w #2,d2 ; factor in location of screen in controllermulu #2048,d2 ; 2048 cells per screenadd.w d2,d0rol.w #8,d0 ; swap byte ordermove.w d0,TEXTREG+$24.0001:movem.l (a7)+,d0/d2rts;==============================================================================; TRAP #15 handler;; Parameters:; d0.w = function number to perform;==============================================================================TRAP15:movem.l d0/a0,-(a7)lea T15DispatchTable,a0asl.l #2,d0move.l (a0,d0.w),a0jsr (a0)movem.l (a7)+,d0/a0rtealign 2T15DispatchTable:dc.l DisplayStringLimitedCRLFdc.l DisplayStringLimiteddc.l StubRoutdc.l StubRoutdc.l StubRoutdc.l GetKeydc.l DisplayChardc.l CheckForKeydc.l StubRoutdc.l StubRout; 10dc.l StubRoutdc.l Cursor1dc.l SetKeyboardEchodc.l DisplayStringCRLFdc.l DisplayStringdc.l StubRoutdc.l StubRoutdc.l StubRoutdc.l StubRoutdc.l StubRout; 20dc.l StubRoutdc.l StubRoutdc.l StubRoutdc.l StubRoutdc.l StubRoutdc.l StubRoutdc.l StubRoutdc.l StubRoutdc.l StubRoutdc.l StubRout; 30dc.l StubRoutdc.l StubRoutdc.l rotate_iofocusdc.l SerialPeekCharDirectdc.l SerialPutChardc.l SerialPeekChardc.l SerialGetChardc.l T15LockSemaphoredc.l T15UnlockSemaphoredc.l StubRout;------------------------------------------------------------------------------; Cursor positioning / Clear screen; - out of range settings are ignored;; Parameters:; d1.w cursor position, bits 0 to 7 are row, bits 8 to 15 are column.; Returns:; none;------------------------------------------------------------------------------Cursor1:move.l d1,-(a7)cmpi.w #$FF00,d1bne.s .0002bsr clear_screenbra HomeCursor.0002:cmp.b TextRows,d1 ; if cursor pos out of range, ignore settingbhs.s .0003move.b d1,CursorRow.0003:ror.w #8,d1cmp.b TextCols,d1bhs.s .0001move.b d1,CursorCol.0001:bsr SyncCursor ; update hardware cursormove.l (a7)+,d1rts;------------------------------------------------------------------------------; Stub routine for unimplemented functionality.;------------------------------------------------------------------------------StubRout:rts;------------------------------------------------------------------------------; Select a specific IO focus.;------------------------------------------------------------------------------select_iofocus:cmpi.b #2,d1blo.s .0001cmpi.b #9,d1bhi.s .0001move.l d1,d0bra.s select_focus1.0001:rts;------------------------------------------------------------------------------; Rotate the IO focus, done when ALT-Tab is pressed.;; Modifies:; d0, IOFocus BIOS variable;------------------------------------------------------------------------------rotate_iofocus:move.b IOFocus,d0 ; d0 = focus, we can trash d0add.b #1,d0 ; increment the focuscmp.b #9,d0 ; limit to 2 to 9bls.s .0001move.b #2,d0.0001:select_focus1:move.b d0,IOFocus ; set IO focussubi.b #2,d0 ; screen is 0 to 7, focus is 2 to 9ext.w d0 ; make into long valuemulu #2048,d0 ; * 2048 cells per screenrol.w #8,d0 ; swap byte ordermove.w d0,TEXTREG+$28 ; update screen address in text controllerbra SyncCursor ; set cursor position;==============================================================================; PLIC - platform level interrupt controller;; Register layout:; bits 0 to 7 = cause code to issue (vector number); bits 8 to 11 = irq level to issue; bit 16 = irq enable; bit 17 = edge sensitivity; bit 18 = 0=vpa, 1=inta; bit 24 to 29 target core;; Note byte order must be reversed for PLIC.;==============================================================================init_plic:lea PLIC,a0 ; a0 points to PLIClea $80+4*29(a0),a1 ; point to timer registers (29)move.l #$0006033F,(a1) ; initialize, core=63,edge sensitive,enabled,irq6,vpalea 4(a1),a1 ; point to keyboard registers (30)move.l #$3C060502,(a1) ; core=2,level sensitive,enabled,irq6,intalea 4(a1),a1 ; point to nmi button register (31)move.l #$00070302,(a1) ; initialize, core=2,edge sensitive,enabled,irq7,vpalea $80+4*16(a0),a1 ; a1 points to ACIA registermove.l #$3D030502,(a1) ; core=2,level sensitive,enabled,irq3,intalea $80+4*4(a0),a1 ; a1 points to io_bitmap irqmove.l #$3B060702,(a1) ; core=2,edge sensitive,enabled,irq6,intarts;==============================================================================; Keyboard stuff;; KeyState2_; 876543210; ||||||||+ = shift; |||||||+- = alt; ||||||+-- = control; |||||+--- = numlock; ||||+---- = capslock; |||+----- = scrolllock; ||+------ =; |+------- =; +-------- = extended;;==============================================================================; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; Get ID - get the keyboards identifier code.;; Parameters: none; Returns: d = $AB83, $00 on fail; Modifies: d, KeybdID updated; Stack Space: 2 words; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -KeybdGetID:move.w #$F2,d1bsr KeybdSendBytebsr KeybdWaitTxbsr KeybdRecvBytebtst #7,d1bne kgnotKbdcmpi.b #$AB,d1bne kgnotKbdbsr KeybdRecvBytebtst #7,d1bne kgnotKbdcmpi.b #$83,d1bne kgnotKbdmove.l #$AB83,d1kgid1:move.w d1,KeybdIDrtskgnotKbd:moveq #0,d1bra kgid1; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; Set the LEDs on the keyboard.;; Parameters:; d1.b = LED state; Modifies:; none; Returns:; none; Stack Space:; 1 long word; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -KeybdSetLED:move.l d1,-(a7)move.b #$ED,d1bsr KeybdSendBytebsr KeybdWaitTxbsr KeybdRecvBytetst.b d1bmi .0001cmpi.b #$FA,d1move.l (a7),d1bsr KeybdSendBytebsr KeybdWaitTxbsr KeybdRecvByte.0001:move.l (a7)+,d1rts; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; Initialize the keyboard.;; Parameters:; none; Modifies:; none; Returns:; none; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -_KeybdInit:KeybdInit:; movem.l d0/d1/d3/a1,-(a7)clr.b _KeyState1 ; records key up/down stateclr.b _KeyState2 ; records shift,ctrl,alt statertsbsr Wait300msbsr _KeybdGetStatus ; wait for response from keyboardtst.b d1bpl .0001 ; is input buffer full ? no, branchbsr _KeybdGetScancodecmpi.b #$AA,d1 ; keyboard Okaybeq kbdi0005.0001:moveq #10,d3kbdi0002:bsr Wait10msclr.b KEYBD+1 ; clear receive register (write $00 to status reg)moveq #-1,d1 ; send reset code to keyboardmove.b d1,KEYBD+1 ; write $FF to status reg to clear TX statebsr KeybdSendByte ; now write ($FF) to transmit register for resetbsr KeybdWaitTx ; wait until no longer busytst.l d1bmi kbdiXmitBusybsr KeybdRecvByte ; look for an ACK ($FA)cmpi.b #$FA,d1bne .0001bsr KeybdRecvByte ; look for BAT completion code ($AA).0001:cmpi.b #$FC,d1 ; reset error ?beq kbdiTryAgaincmpi.b #$AA,d1 ; reset complete okay ?bne kbdiTryAgain; After a reset, scan code set #2 should be active.config:move.w #$F0,d1 ; send scan code selectmove.b d1,ledsbsr KeybdSendBytebsr KeybdWaitTxtst.l d1bmi kbdiXmitBusybsr KeybdRecvByte ; wait for response from keyboardtst.w d1bmi kbdiTryAgaincmpi.b #$FA,d1 ; ACKbeq kbdi0004kbdiTryAgain:dbra d3,kbdi0002.keybdErr:lea msgBadKeybd,a1bsr DisplayStringCRLFbra ledxitkbdi0004:moveq #2,d1 ; select scan code set #2bsr KeybdSendBytebsr KeybdWaitTxtst.l d1bmi kbdiXmitBusybsr KeybdRecvByte ; wait for response from keyboardtst.w d1bmi kbdiTryAgaincmpi.b #$FA,d1bne kbdiTryAgainkbdi0005:bsr KeybdGetIDledxit:moveq #$07,d1bsr KeybdSetLEDbsr Wait300msmoveq #$00,d1bsr KeybdSetLEDmovem.l (a7)+,d0/d1/d3/a1rtskbdiXmitBusy:lea msgXmitBusy,a1bsr DisplayStringCRLFmovem.l (a7)+,d0/d1/d3/a1rtsmsgBadKeybd:dc.b "Keyboard error",0msgXmitBusy:dc.b "Keyboard transmitter stuck",0even_KeybdGetStatus:moveq #0,d1move.b KEYBD+1,d1rts; Get the scancode from the keyboard port_KeybdGetScancode:moveq #0,d1move.b KEYBD,d1 ; get the scan codemove.b #0,KEYBD+1 ; clear receive registerrts; Recieve a byte from the keyboard, used after a command is sent to the; keyboard in order to wait for a response.;KeybdRecvByte:move.l d3,-(a7)move.w #100,d3 ; wait up to 1s.0003:bsr _KeybdGetStatus ; wait for response from keyboardtst.b d1bmi .0004 ; is input buffer full ? yes, branchbsr Wait10ms ; wait a bitdbra d3,.0003 ; go back and try againmove.l (a7)+,d3moveq #-1,d1 ; return -1rts.0004:bsr _KeybdGetScancodemove.l (a7)+,d3rts; Wait until the keyboard transmit is complete; Returns -1 if timedout, 0 if transmit completed;KeybdWaitTx:movem.l d2/d3,-(a7)moveq #100,d3 ; wait a max of 1s.0001:bsr _KeybdGetStatusbtst #6,d1 ; check for transmit complete bitbne .0002 ; branch if bit setbsr Wait10ms ; delay a little bitdbra d3,.0001 ; go back and try againmovem.l (a7)+,d2/d3moveq #-1,d1 ; return -1rts.0002:movem.l (a7)+,d2/d3moveq #0,d1 ; return 0rts;------------------------------------------------------------------------------; d1.b 0=echo off, non-zero = echo on;------------------------------------------------------------------------------SetKeyboardEcho:move.b d1,KeybdEchorts;------------------------------------------------------------------------------; Get key pending status into d1.b;; Returns:; d1.b = 1 if a key is available, otherwise zero.;------------------------------------------------------------------------------CheckForKey:moveq.l #0,d1 ; clear high order bits; move.b KEYBD+1,d1 ; get keyboard port status; smi.b d1 ; set true/false; andi.b #1,d1 ; return true (1) if key available, 0 otherwisetst.b _KeybdCntsne.b d1rts;------------------------------------------------------------------------------; GetKey; Get a character from the keyboard.;; Modifies:; d1; Returns:; d1 = -1 if no key available or not in focus, otherwise key;------------------------------------------------------------------------------GetKey:move.l d0,-(a7) ; push d0move.b IOFocus,d1 ; Check if the core has the IO focusmovec.l coreno,d0cmp.b d0,d1bne.s .0004 ; go return no key available, if not in focusbsr KeybdGetCharNoWait ; get a charactertst.l d1 ; was a key available?bmi.s .0004tst.b KeybdEcho ; is keyboard echo on ?beq.s .0003 ; no echo, just return the keycmpi.b #CR,d1 ; convert CR keystroke into CRLFbne.s .0005bsr CRLFbra.s .0003.0005:bsr DisplayChar.0003:move.l (a7)+,d0 ; pop d0rts ; return key; Return -1 indicating no char was available.0004:move.l (a7)+,d0 ; pop d0moveq #-1,d1 ; return no key availablertsCheckForCtrlC:bsr KeybdGetCharNoWaitcmpi.b #CTRLC,d1beq Monitorrts;------------------------------------------------------------------------------;------------------------------------------------------------------------------KeybdGetCharNoWait:clr.b KeybdWaitFlagbra KeybdGetCharKeybdGetCharWait:move.b #-1,KeybdWaitFlagKeybdGetChar:movem.l d0/d2/d3/a0,-(a7).0003:movec coreno,d0swap d0moveq #KEYBD_SEMA,d1bsr LockSemaphoremove.b _KeybdCnt,d2 ; get count of buffered scan codesbeq.s .0015 ;move.b _KeybdHead,d2 ; d2 = buffer headext.w d2lea _KeybdBuf,a0 ; a0 = pointer to keyboard bufferclr.l d1move.b (a0,d2.w),d1 ; d1 = scan code from bufferaddi.b #1,d2 ; increment keyboard head indexandi.b #31,d2 ; and wrap around at buffer sizemove.b d2,_KeybdHeadsubi.b #1,_KeybdCnt ; decrement count of scan codes in bufferexg d1,d2 ; save scancode value in d2movec coreno,d0swap d0moveq #KEYBD_SEMA,d1bsr UnlockSemaphoreexg d2,d1 ; restore scancode valuebra .0001 ; go process scan code.0014:bsr _KeybdGetStatus ; check keyboard status for key availablebmi .0006 ; yes, go process.0015:movec coreno,d0swap d0moveq #KEYBD_SEMA,d1bsr UnlockSemaphoretst.b KeybdWaitFlag ; are we willing to wait for a key ?bmi .0003 ; yes, branch backmovem.l (a7)+,d0/d2/d3/a0moveq #-1,d1 ; flag no char availablerts.0006:bsr _KeybdGetScancode.0001:move.w #1,ledscmp.b #SC_KEYUP,d1beq .doKeyupcmp.b #SC_EXTEND,d1beq .doExtendcmp.b #SC_CTRL,d1beq .doCtrlcmp.b #SC_LSHIFT,d1beq .doShiftcmp.b #SC_RSHIFT,d1beq .doShiftcmp.b #SC_NUMLOCK,d1beq .doNumLockcmp.b #SC_CAPSLOCK,d1beq .doCapsLockcmp.b #SC_SCROLLLOCK,d1beq .doScrollLockcmp.b #SC_ALT,d1beq .doAltmove.b _KeyState1,d2 ; check key up/downmove.b #0,_KeyState1 ; clear keyup statustst.b d2bne .0003 ; ignore key upcmp.b #SC_TAB,d1beq .doTab.0013:move.b _KeyState2,d2bpl .0010 ; is it extended code ?and.b #$7F,d2 ; clear extended bitmove.b d2,_KeyState2move.b #0,_KeyState1 ; clear keyuplea _keybdExtendedCodes,a0move.b (a0,d1.w),d1bra .0008.0010:btst #2,d2 ; is it CTRL code ?beq .0009and.w #$7F,d1lea _keybdControlCodes,a0move.b (a0,d1.w),d1bra .0008.0009:btst #0,d2 ; is it shift down ?beq .0007lea _shiftedScanCodes,a0move.b (a0,d1.w),d1bra .0008.0007:lea _unshiftedScanCodes,a0move.b (a0,d1.w),d1move.w #$0202,leds.0008:move.w #$0303,ledsmovem.l (a7)+,d0/d2/d3/a0rts.doKeyup:move.b #-1,_KeyState1bra .0003.doExtend:or.b #$80,_KeyState2bra .0003.doCtrl:move.b _KeyState1,d1clr.b _KeyState1tst.b d1bpl.s .0004bclr #2,_KeyState2bra .0003.0004:bset #2,_KeyState2bra .0003.doAlt:move.b _KeyState1,d1clr.b _KeyState1tst.b d1bpl .0011bclr #1,_KeyState2bra .0003.0011:bset #1,_KeyState2bra .0003.doTab:move.l d1,-(a7)move.b _KeyState2,d1btst #1,d1 ; is ALT down ?beq .0012; inc _iof_switchmove.l (a7)+,d1bra .0003.0012:move.l (a7)+,d1bra .0013.doShift:move.b _KeyState1,d1clr.b _KeyState1tst.b d1bpl.s .0005bclr #0,_KeyState2bra .0003.0005:bset #0,_KeyState2bra .0003.doNumLock:bchg #4,_KeyState2bsr KeybdSetLEDStatusbra .0003.doCapsLock:bchg #5,_KeyState2bsr KeybdSetLEDStatusbra .0003.doScrollLock:bchg #6,_KeyState2bsr KeybdSetLEDStatusbra .0003KeybdSetLEDStatus:movem.l d2/d3,-(a7)clr.b KeybdLEDsbtst #4,_KeyState2beq.s .0002move.b #2,KeybdLEDs.0002:btst #5,_KeyState2beq.s .0003bset #2,KeybdLEDs.0003:btst #6,_KeyState2beq.s .0004bset #0,KeybdLEDs.0004:move.b KeybdLEDs,d1bsr KeybdSetLEDmovem.l (a7)+,d2/d3rtsKeybdSendByte:move.b d1,KEYBDrts; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; Wait for 10 ms;; Parameters: none; Returns: none; Modifies: none; Stack Space: 2 long words; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Wait10ms:movem.l d0/d1,-(a7)movec tick,d0addi.l #400000,d0 ; 400,000 cycles at 40MHz.0001:movec tick,d1cmp.l d1,d0bhi .0001movem.l (a7)+,d0/d1rts; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -; Wait for 300 ms;; Parameters: none; Returns: none; Modifies: none; Stack Space: 2 long words; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Wait300ms:movem.l d0/d1,-(a7)movec tick,d0addi.l #12000000,d0 ; 12,000,000 cycles at 40MHz.0001:movec tick,d1cmp.l d1,d0bhi .0001movem.l (a7)+,d0/d1rts;--------------------------------------------------------------------------; Keyboard IRQ routine.;; Returns:; d1 = -1 if keyboard routine handled interrupt, otherwise positive.;--------------------------------------------------------------------------KeybdIRQ:move.w #$2600,sr ; disable lower interruptsmovem.l d0/d1/a0,-(a7)bsr _KeybdGetStatus ; check if keyboardtst.b d1bpl .0001 ; branch if not keyboardmovec coreno,d0swap d0moveq #KEYBD_SEMA,d1bsr LockSemaphorebtst #1,_KeyState2 ; Is Alt down?beq.s .0003move.b KEYBD,d0 ; get scan codecmpi.b #SC_TAB,d0 ; is Alt-Tab?bne.s .0003bsr _KeybdGetScancode ; grab the scan code (clears interrupt)bsr rotate_iofocusclr.b _KeybdHead ; clear keyboard bufferclr.b _KeybdTailclr.b _KeybdCntbra .0002 ; do not store Alt-Tab.0003:; Insert keyboard scan code into raw keyboard bufferbsr _KeybdGetScancode ; grab the scan code (clears interrupt)cmpi.b #32,_KeybdCnt ; see if keyboard buffer fullbhs.s .0002move.b _KeybdTail,d0 ; keyboard buffer not full, add to tailext.w d0lea _KeybdBuf,a0 ; a0 = pointer to buffermove.b d1,(a0,d0.w) ; put scancode in bufferaddi.b #1,d0 ; increment tail indexandi.b #31,d0 ; wrap at buffer limitmove.b d0,_KeybdTail ; update tail indexaddi.b #1,_KeybdCnt ; increment buffer count.0002:movec coreno,d0swap d0moveq #KEYBD_SEMA,d1bsr UnlockSemaphore.0001:movem.l (a7)+,d0/d1/a0 ; returnrte;--------------------------------------------------------------------------; PS2 scan codes to ascii conversion tables.;--------------------------------------------------------------------------;_unshiftedScanCodes:dc.b $2e,$a9,$2e,$a5,$a3,$a1,$a2,$acdc.b $2e,$aa,$a8,$a6,$a4,$09,$60,$2edc.b $2e,$2e,$2e,$2e,$2e,$71,$31,$2edc.b $2e,$2e,$7a,$73,$61,$77,$32,$2edc.b $2e,$63,$78,$64,$65,$34,$33,$2edc.b $2e,$20,$76,$66,$74,$72,$35,$2edc.b $2e,$6e,$62,$68,$67,$79,$36,$2edc.b $2e,$2e,$6d,$6a,$75,$37,$38,$2edc.b $2e,$2c,$6b,$69,$6f,$30,$39,$2edc.b $2e,$2e,$2f,$6c,$3b,$70,$2d,$2edc.b $2e,$2e,$27,$2e,$5b,$3d,$2e,$2edc.b $ad,$2e,$0d,$5d,$2e,$5c,$2e,$2edc.b $2e,$2e,$2e,$2e,$2e,$2e,$08,$2edc.b $2e,$95,$2e,$93,$94,$2e,$2e,$2edc.b $98,$7f,$92,$2e,$91,$90,$1b,$afdc.b $ab,$2e,$97,$2e,$2e,$96,$ae,$2edc.b $2e,$2e,$2e,$a7,$2e,$2e,$2e,$2edc.b $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2edc.b $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2edc.b $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2edc.b $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2edc.b $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2edc.b $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2edc.b $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2edc.b $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2edc.b $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2edc.b $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2edc.b $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2edc.b $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2edc.b $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2edc.b $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2edc.b $2e,$2e,$fa,$2e,$2e,$2e,$2e,$2e_shiftedScanCodes:dc.b $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2edc.b $2e,$2e,$2e,$2e,$2e,$09,$7e,$2edc.b $2e,$2e,$2e,$2e,$2e,$51,$21,$2edc.b $2e,$2e,$5a,$53,$41,$57,$40,$2edc.b $2e,$43,$58,$44,$45,$24,$23,$2edc.b $2e,$20,$56,$46,$54,$52,$25,$2edc.b $2e,$4e,$42,$48,$47,$59,$5e,$2edc.b $2e,$2e,$4d,$4a,$55,$26,$2a,$2edc.b $2e,$3c,$4b,$49,$4f,$29,$28,$2edc.b $2e,$3e,$3f,$4c,$3a,$50,$5f,$2edc.b $2e,$2e,$22,$2e,$7b,$2b,$2e,$2edc.b $2e,$2e,$0d,$7d,$2e,$7c,$2e,$2edc.b $2e,$2e,$2e,$2e,$2e,$2e,$08,$2edc.b $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2edc.b $2e,$7f,$2e,$2e,$2e,$2e,$1b,$2edc.b $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2edc.b $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2edc.b $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2edc.b $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2edc.b $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2edc.b $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2edc.b $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2edc.b $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2edc.b $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2edc.b $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2edc.b $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2edc.b $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2edc.b $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2edc.b $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2edc.b $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2edc.b $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2edc.b $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2e; control_keybdControlCodes:dc.b $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2edc.b $2e,$2e,$2e,$2e,$2e,$09,$7e,$2edc.b $2e,$2e,$2e,$2e,$2e,$11,$21,$2edc.b $2e,$2e,$1a,$13,$01,$17,$40,$2edc.b $2e,$03,$18,$04,$05,$24,$23,$2edc.b $2e,$20,$16,$06,$14,$12,$25,$2edc.b $2e,$0e,$02,$08,$07,$19,$5e,$2edc.b $2e,$2e,$0d,$0a,$15,$26,$2a,$2edc.b $2e,$3c,$0b,$09,$0f,$29,$28,$2edc.b $2e,$3e,$3f,$0c,$3a,$10,$5f,$2edc.b $2e,$2e,$22,$2e,$7b,$2b,$2e,$2edc.b $2e,$2e,$0d,$7d,$2e,$7c,$2e,$2edc.b $2e,$2e,$2e,$2e,$2e,$2e,$08,$2edc.b $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2edc.b $2e,$7f,$2e,$2e,$2e,$2e,$1b,$2edc.b $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2e_keybdExtendedCodes:dc.b $2e,$2e,$2e,$2e,$a3,$a1,$a2,$2edc.b $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2edc.b $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2edc.b $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2edc.b $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2edc.b $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2edc.b $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2edc.b $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2edc.b $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2edc.b $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2edc.b $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2edc.b $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2edc.b $2e,$2e,$2e,$2e,$2e,$2e,$2e,$2edc.b $2e,$95,$2e,$93,$94,$2e,$2e,$2edc.b $98,$99,$92,$2e,$91,$90,$2e,$2edc.b $2e,$2e,$97,$2e,$2e,$96,$2e,$2e;==============================================================================;==============================================================================; Monitor;==============================================================================;==============================================================================cmdString:dc.b '?'+$80 ; ? display helpdc.b 'L'+$80 ; L load S19 filedc.b 'F','B'+$80 ; FB fill with bytedc.b 'F','W'+$80 ; FW fill with wydedc.b 'F','L'+$80 ; FL fill with long wydedc.b 'B','A'+$80 ; BA start Tiny Basicdc.b 'B','R'+$80 ; BR breakpointdc.b 'D','R'+$80 ; DR dump registersdc.b 'D'+$80 ; D dump memorydc.b 'J'+$80 ; J jump to codedc.b ':'+$80 ; : edit memorydc.b "CL",'S'+$80 ; CLS clear screendc.b "COR",'E'+$80 ; CORE <n> switch to coredc.b "TRA",'M'+$80 ; TRAM test RAMdc.b 'T','R'+$80 ; TR test serial receivedc.b 'T'+$80 ; T test CPUdc.b 'S'+$80 ; S send serialdc.b "RESE",'T'+$80 ; RESET <n>dc.b "CLOC",'K'+$80 ; CLOCK <n>dc.b 'R'+$80 ; R receive serialalign 2cmdTable:dc.w cmdHelpdc.w cmdLoadS19dc.w cmdFillBdc.w cmdFillWdc.w cmdFillLdc.w cmdTinyBasicdc.w cmdBreakpointdc.w cmdDumpRegsdc.w cmdDumpMemorydc.w cmdJumpdc.w cmdEditMemorydc.w cmdClearScreendc.w cmdCoredc.w cmdTestRAMdc.w cmdTestSerialReceivedc.w cmdTestCPUdc.w cmdSendSerialdc.w cmdResetdc.w cmdClockdc.w cmdReceiveSerialdc.w cmdMonitor; Get a word from screen memory and swap byte orderFromScreen:move.l (a0),d1bsr rbolea 8(a0),a0 ; increment screen pointerrtsStartMon:clr.w NumSetBreakpointsbsr ClearBreakpointListcmdMonitor:Monitor:; Reset the stack pointer on each entry into the monitormove.l #$40FFC,sp ; reset core's stackmove.w #$2200,sr ; enable level 2 and higher interruptsmovec coreno,d0swap d0moveq #1,d1bsr UnlockSemaphoreclr.b KeybdEcho ; turn off keyboard echoPromptLn:bsr CRLFmove.b #'$',d1bsr DisplayChar; Get characters until a CR is keyed;Prompt3:bsr GetKeycmpi.b #-1,d1beq.s Prompt3cmpi.b #CR,d1beq.s Prompt1bsr DisplayCharbra.s Prompt3; Process the screen line that the CR was keyed onPrompt1:clr.b CursorCol ; go back to the start of the linebsr CalcScreenLoc ; a0 = screen memory location.0001:bsr FromScreen ; grab character off screencmpi.b #'$',d1 ; skip over '$' prompt characterbeq.s .0001; Dispatch based on command stringcmdDispatch:lea cmdString,a2clr.l d4 ; command counterlea -8(a0),a0 ; backup a charactermove.l a0,a3 ; a3 = start of command on screen.checkNextCmd:bsr FromScreen ; d1 = char from input screenmove.b (a2)+,d5eor.b d5,d1 ; does it match with command string?beq.s .checkNextCmd ; If it does, keep matching for longest matchcmpi.b #$80,d1 ; didn't match, was it the end of the command?beq.s .foundCmdtst.b -1(a2) ; was end of table hit?beq.s .endOfTableaddi.w #2,d4 ; increment command countermove.l a3,a0 ; reset input pointertst.b -1(a2) ; were we at the end of the command?bmi.s .checkNextCmd ; if were at end continue, otherwise scan for enf of cmd.scanToEndOfCmdtst.b (a2)+ ; scan to end of commandbeq.s .endOfTablebpl.s .scanToEndOfCmdbmi.s .checkNextCmd.endOfTablelea msgUnknownCmd,a1bsr DisplayStringCRLFbra Monitor.foundCmd:lea cmdTable,a1 ; a1 = pointer to command address tablemove.w (a1,d4.w),a1 ; fetch command routine address from tablejmp (a1) ; go execute commandcmdBreakpoint:bsr ignBlanksbsr FromScreencmpi.b #'+',d1beq ArmBreakpointcmpi.b #'-',d1beq DisarmBreakpointcmpi.b #'L',d1beq ListBreakpointsbra MonitorcmdTinyBasic:bra CSTARTcmdTestCPU:bsr cpu_testlea msg_test_done,a1bsr DisplayStringCRLFbra MonitorcmdClearScreen:bsr ClearScreenbsr HomeCursorbra MonitorcmdCore:bsr ignBlanksbsr FromScreencmpi.b #'2',d1 ; check rangeblo Monitorcmpi.b #'9',d1bhi Monitorsubi.b #'0',d1 ; convert ascii to binarybsr select_iofocusbra Monitor;-------------------------------------------------------------------------------; CLOCK <n>; Set the clock register to n which will turn off or on clocks to the CPUs.;-------------------------------------------------------------------------------cmdClock:bsr ignBlanksbsr GetHexNumbertst.b d0 ; was there a number?beq Monitorori.w #4,d0 ; primary core's clock cannot be turned offrol.w #8,d1 ; switch byte ordermove.w d1,RST_REG+2bra Monitor;-------------------------------------------------------------------------------; RESET <n>; Reset the specified core. Resetting the core automatically turns on the; core's clock.;-------------------------------------------------------------------------------cmdReset:bsr ignBlanksbsr FromScreencmpi.b #'2',d1 ; check rangeblo Monitorcmpi.b #'9',d1bhi Monitorsubi.b #'0',d1 ; convert ascii to binarylsl.w #1,d1 ; make into indexlea tblPow2,a1move.w (a1,d1.w),d1rol.w #8,d1 ; reverse byte ordermove.w d1,RST_REGbra MonitortblPow2:dc.w 1dc.w 2dc.w 4dc.w 8dc.w 16dc.w 32dc.w 64dc.w 128dc.w 256dc.w 512dc.w 1024dc.w 2048dc.w 4096dc.w 8192dc.w 16384dc.w 32768evencmdHelp:DisplayHelp:lea HelpMsg,a1bsr DisplayStringbra MonitorHelpMsg:dc.b "? = Display help",LF,CRdc.b "CORE n = switch to core n, n = 2 to 7",LF,CRdc.b "RESET n = reset core n",LF,CRdc.b "CLS = clear screen",LF,CRdc.b ": = Edit memory bytes",LF,CRdc.b "FB = Fill memory bytes, FW, FL",LF,CRdc.b "L = Load S19 file",LF,CRdc.b "D = Dump memory, DR = dump registers",LF,CRdc.b "BA = start tiny basic",LF,CRdc.b "BR = set breakpoint",LF,CRdc.b "J = Jump to code",LF,CRdc.b "S = send to serial port",LF,CRdc.b "T = cpu test program",LF,CRdc.b "TRAM = test RAM",LF,CR,0msgUnknownCmd:dc.b "command unknown",0msgHello:dc.b LF,CR,"Hello World!",LF,CR,0even;------------------------------------------------------------------------------; This routine borrowed from Gordo's Tiny Basic interpreter.; Used to fetch a command line. (Not currently used).;; d0.b - command prompt;------------------------------------------------------------------------------GetCmdLine:bsr DisplayChar ; display promptmove.b #' ',d0bsr DisplayCharlea CmdBuf,a0.0001:bsr GetKeycmp.b #CTRLH,d0beq.s .0003cmp.b #CTRLX,d0beq.s .0004cmp.b #CR,d0beq.s .0002cmp.b #' ',d0bcs.s .0001.0002:move.b d0,(a0)lea 8(a0),a0bsr DisplayCharcmp.b #CR,d0beq .0007cmp.l #CmdBufEnd-1,a0bcs.s .0001.0003:move.b #CTRLH,d0bsr DisplayCharmove.b #' ',d0bsr DisplayCharcmp.l #CmdBuf,a0bls.s .0001move.b #CTRLH,d0bsr DisplayCharsubq.l #1,a0bra.s .0001.0004:move.l a0,d1sub.l #CmdBuf,d1beq.s .0006subq #1,d1.0005:move.b #CTRLH,d0bsr DisplayCharmove.b #' ',d0bsr DisplayCharmove.b #CTRLH,d0bsr DisplayChardbra d1,.0005.0006:lea CmdBuf,a0bra .0001.0007:move.b #LF,d0bsr DisplayCharrts;------------------------------------------------------------------------------; S <address> <length>; Send data buffer to serial port; S 40000 40;------------------------------------------------------------------------------cmdSendSerial:bsr ignBlanksbsr GetHexNumberbeq Monitormove.l d1,d6 ; d6 points to bufferbsr ignBlanksbsr GetHexNumberbne.s .0003moveq #16,d1.0003:move.l d6,a1 ; a1 points to buffermove.l d1,d2 ; d2 = count of bytes to sendbra.s .0002 ; enter loop at bottom.0001:move.b (a1)+,d1move.w #34,d0 ; serial putchartrap #15.0002:dbra d2,.0001bra Monitor;------------------------------------------------------------------------------; R <address> <length>; Send data buffer to serial port; R 10000 40;------------------------------------------------------------------------------cmdReceiveSerial:bsr ignBlanksbsr GetHexNumberbeq Monitormove.l d1,d6 ; d6 points to bufferbsr ignBlanksbsr GetHexNumberbne.s .0003moveq #16,d1.0003:move.l d6,a1 ; a1 points to buffermove.l d1,d2 ; d2 = count of bytes to sendbra.s .0002 ; enter loop at bottom.0001:move.w #36,d0 ; serial peek chartrap #15tst.l d1bmi.s .0001move.b d1,(a1)+.0002:dbra d2,.0001bra Monitor;------------------------------------------------------------------------------; Fill memory;; FB = fill bytes FB 00000010 100 FF ; fill starting at 10 for 256 bytes; FW = fill words; FL = fill longs; F = fill bytes;------------------------------------------------------------------------------cmdFillB:bsr ignBlanksbsr GetHexNumbermove.l d1,a1 ; a1 = startbsr ignBlanksbsr GetHexNumbermove.l d1,d3 ; d3 = countbeq Monitorbsr ignBlanksbsr GetHexNumber ; fill value.fmem:move.b d1,(a1)+sub.l #1,d3bne.s .fmembra MonitorcmdFillW:bsr ignBlanksbsr GetHexNumbermove.l d1,a1 ; a1 = startbsr ignBlanksbsr GetHexNumbermove.l d1,d3 ; d3 = countbeq Monitorbsr ignBlanksbsr GetHexNumber ; fill value.fmem:move.w d1,(a1)+sub.l #1,d3bne.s .fmembra MonitorcmdFillL:bsr ignBlanksbsr GetHexNumbermove.l d1,a1 ; a1 = startbsr ignBlanksbsr GetHexNumbermove.l d1,d3 ; d3 = countbeq Monitorbsr ignBlanksbsr GetHexNumber ; fill value.fmem:move.l d1,(a1)+sub.l #1,d3bne.s .fmembra Monitor;------------------------------------------------------------------------------; Modifies:; a0 - text pointer;------------------------------------------------------------------------------ignBlanks:move.l d1,-(a7).0001:bsr FromScreencmpi.b #' ',d1beq.s .0001lea -8(a0),a0move.l (a7)+,d1rts;------------------------------------------------------------------------------; Edit memory byte.; Bytes are built into long words in case the memory is only longword; accessible.;------------------------------------------------------------------------------cmdEditMemory:bsr ignBlanksbsr GetHexNumbermove.l d1,a1edtmem1:clr.l d2bsr ignBlanksbsr GetHexNumbermove.b d1,d2; move.b d1,(a1)+bsr ignBlanksbsr GetHexNumberlsl.l #8,d2move.b d1,d2; move.b d1,(a1)+bsr ignBlanksbsr GetHexNumberlsl.l #8,d2move.b d1,d2; move.b d1,(a1)+bsr ignBlanksbsr GetHexNumberlsl.l #8,d2move.b d1,d2move.l d2,(a1)+; move.b d1,(a1)+clr.l d2bsr ignBlanksbsr GetHexNumbermove.b d1,d2; move.b d1,(a1)+bsr ignBlanksbsr GetHexNumberlsl.l #8,d2move.b d1,d2; move.b d1,(a1)+bsr ignBlanksbsr GetHexNumberlsl.l #8,d2move.b d1,d2; move.b d1,(a1)+bsr ignBlanksbsr GetHexNumberlsl.l #8,d2move.b d1,d2; move.b d1,(a1)+move.l d2,(a1)+bra Monitor;------------------------------------------------------------------------------; Execute code at the specified address.;------------------------------------------------------------------------------cmdJump:ExecuteCode:bsr ignBlanksbsr GetHexNumbermove.l d1,a0jsr (a0)bra Monitor;------------------------------------------------------------------------------; Do a memory dump of the requested location.; D 0800 0850;------------------------------------------------------------------------------cmdDumpMemory:bsr ignBlanksbsr GetHexNumberbeq Monitor ; was there a number ? no, other garbage, just ignoremove.l d1,d3 ; save off start of rangebsr ignBlanksbsr GetHexNumberbne.s DumpMem1move.l d3,d1addi.l #64,d1 ; no end specified, just dump 64 bytesDumpMem1:move.l d3,a0move.l d1,a1bsr CRLF.0001:cmpa.l a0,a1bls Monitorbsr DisplayMembra.s .0001;------------------------------------------------------------------------------; Display memory dump in a format suitable for edit.;; :12345678 00 11 22 33 44 55 66 77 "........";; Modifies:; d1,d2,a0;------------------------------------------------------------------------------DisplayMem:move.b #':',d1bsr DisplayCharmove.l a0,d1bsr DisplayTetramoveq #7,d2dspmem1:move.b #' ',d1bsr DisplayCharmove.b (a0)+,d1bsr DisplayBytedbra d2,dspmem1bsr DisplayTwoSpacesmove.b #34,d1bsr DisplayCharlea -8(a0),a0moveq #7,d2.0002:move.b (a0)+,d1cmp.b #' ',d1blo.s .0003cmp.b #127,d1bls.s .0001.0003:move.b #'.',d1.0001:bsr DisplayChardbra d2,.0002move.b #34,d1bsr DisplayCharbsr CheckForCtrlCbra CRLF;------------------------------------------------------------------------------; Dump Registers; The dump is in a format that allows the register value to be edited.;; RegD0 12345678; RegD1 77777777; ... etc;------------------------------------------------------------------------------cmdDumpRegs:bsr CRLFmove.w #15,d0 ; number of registers-1lea msg_reglist,a0 ;lea msg_regs,a1lea Regsave,a2 ; a2 points to register save area.0001:bsr DisplayStringmove.b (a0)+,d1bsr DisplayCharmove.b (a0)+,d1bsr DisplayCharbsr DisplaySpacemove.l (a2)+,d1bsr DisplayTetrabsr CRLFdbra d0,.0001bsr DisplayStringmove.b (a0)+,d1bsr DisplayCharmove.b (a0)+,d1bsr DisplayCharbsr DisplaySpacemove.l Regsave+$44,d1bsr DisplayTetrabsr CRLFbsr DisplayStringmove.b (a0)+,d1bsr DisplayCharmove.b (a0)+,d1bsr DisplayCharbsr DisplaySpacemove.w Regsave+$40,d1bsr DisplayWydebsr CRLFbra Monitormsg_regs:dc.b "Reg",0msg_reglist:dc.b "D0D1D2D3D4D5D6D7A0A1A2A3A4A5A6A7PCSR",0align 1;------------------------------------------------------------------------------;------------------------------------------------------------------------------cmdTestSerialReceive:.0002:moveq #36,d0 ; serial get char from buffertrap #15; bsr SerialPeekCharDirecttst.w d1bmi.s .0001cmpi.b #CTRLZ,d1beq .0003bsr DisplayChar.0001:bsr CheckForCtrlCbra .0002.0003:bsr _KeybdInitbra Monitor;------------------------------------------------------------------------------; Get a hexidecimal number. Maximum of eight digits.;; Returns:; d0 = number of digits; d1 = value of number; zf = number of digits == 0;------------------------------------------------------------------------------GetHexNumber:move.l d2,-(a7)clr.l d2moveq #0,d0.0002:bsr FromScreenbsr AsciiToHexNybblecmp.b #$ff,d1beq.s .0001lsl.l #4,d2andi.l #$0f,d1or.l d1,d2addq #1,d0cmpi.b #8,d0blo.s .0002.0001:move.l d2,d1move.l (a7)+,d2tst.b d0rts;------------------------------------------------------------------------------; Convert ASCII character in the range '0' to '9', 'a' tr 'f' or 'A' to 'F'; to a hex nybble.;------------------------------------------------------------------------------AsciiToHexNybble:cmpi.b #'0',d1blo.s gthx3cmpi.b #'9',d1bhi.s gthx5subi.b #'0',d1rtsgthx5:cmpi.b #'A',d1blo.s gthx3cmpi.b #'F',d1bhi.s gthx6addi.b #10-'A',d1rtsgthx6:cmpi.b #'a',d1blo.s gthx3cmpi.b #'f',d1bhi.s gthx3addi.b #10-'a',d1rtsgthx3:moveq #-1,d1 ; not a hex numberrts;------------------------------------------------------------------------------;------------------------------------------------------------------------------DisplayTwoSpaces:move.l d1,-(a7)move.b #' ',d1bsr DisplayChardspspc1:bsr DisplayCharmove.l (a7)+,d1rtsDisplaySpace:move.l d1,-(a7)move.b #' ',d1bra dspspc1;------------------------------------------------------------------------------; Display the 32 bit word in D1.L;------------------------------------------------------------------------------DisplayTetra:swap d1bsr DisplayWydeswap d1;------------------------------------------------------------------------------; Display the byte in D1.W;------------------------------------------------------------------------------DisplayWyde:ror.w #8,d1bsr DisplayByterol.w #8,d1;------------------------------------------------------------------------------; Display the byte in D1.B;------------------------------------------------------------------------------DisplayByte:ror.b #4,d1bsr DisplayNybblerol.b #4,d1;------------------------------------------------------------------------------; Display nybble in D1.B;------------------------------------------------------------------------------DisplayNybble:move.l d1,-(a7)andi.b #$F,d1addi.b #'0',d1cmpi.b #'9',d1bls.s .0001addi.b #7,d1.0001:bsr DisplayCharmove.l (a7)+,d1rts;------------------------------------------------------------------------------;------------------------------------------------------------------------------;;DisplayHexNumber:; move.w #$A6A6,leds ; diagnostics; move.l #VDGREG,a6; move.w #7,d2 ; number-1 of digits to display;disphnum1:; move.b d1,d0 ; get digit into d0.b; andi.w #$0f,d0; cmpi.w #$09,d0; bls.s disphnum2; addi.w #7,d0;disphnum2:; addi.w #$30,d0 ; convert to display char; move.w d2,d3 ; char count into d3; asl.w #3,d3 ; scale * 8;disphnum3:; move.w $42C(a6),d4 ; read character queue index into d4; cmp.w #28,d4 ; allow up 28 entries to be in progress; bhs.s disphnum3 ; branch if too many chars queued; ext.w d0 ; zero out high order bits; move.w d0,$420(a6) ; set char code; move.w #WHITE,$422(a6) ; set fg color; move.w #DARK_BLUE,$424(a6) ; set bk color; move.w d3,$426(a6) ; set x pos; move.w #8,$428(a6) ; set y pos; move.w #$0707,$42A(a6) ; set font x,y extent; move.w #0,$42E(a6) ; pulse character queue write signal; ror.l #4,d1 ; rot to next digit; dbeq d2,disphnum1; jmp (a5);===============================================================================; Perform ram test. (Uses checkerboard testing).;; Local ram, which does not get tested, is used for the stack.;===============================================================================DisplayAddr:move.l a0,d1lsr.l #8,d1lsr.l #8,d1lsr.l #4,d1subi.w #512,d1bin2bcd d1bsr DisplayWydemove.b #CR,d1bra DisplayCharbtst #$83,d0cmdTestRAM:ramtest:move.w #$A5A5,leds ; diagnosticsmove.l #$aaaaaaaa,d3move.l #$55555555,d4bsr ramtest0; switch checkerboard pattern and repeat test.exg d3,d4bsr ramtest0; Save last ram address in end of memory pointer.rmtst5:moveq #37,d0 ; lock semaphoremoveq #MEMORY_SEMA,d1trap #15move.l a0,memend; Create very first memory block.suba.l #12,a0move.l a0,$20000004 ; length of blockmove.l #$46524545,$20000000moveq #38,d0 ; unlock semaphoremoveq #MEMORY_SEMA,d1trap #15rtsramtest0:move.l d3,d0movea.l #$20000000,a0;-----------------------------------------------------------; Write checkerboard pattern to ram then read it back to; find the highest usable ram address (maybe). This address; must be lower than the start of the rom (0xe00000).;-----------------------------------------------------------ramtest1:move.l d3,(a0)+move.l d4,(a0)+move.l a0,d1tst.w d1bne.s rmtst1bsr DisplayAddrbsr CheckForCtrlCrmtst1:cmpa.l #$3FFFFFF8,a0blo.s ramtest1bsr CRLF;------------------------------------------------------; Save maximum useable address for later comparison.;------------------------------------------------------ramtest6:move.w #$A7A7,leds ; diagnosticsmovea.l a0,a2movea.l #$20000000,a0;--------------------------------------------; Read back checkerboard pattern from ram.;--------------------------------------------ramtest2move.l (a0)+,d5move.l (a0)+,d6cmpa.l a2,a0bhs.s ramtest3move.l a0,d1tst.w d1bne.s rmtst2bsr DisplayAddrbsr CheckForCtrlCrmtst2cmp.l d3,d5bne.s rmtst3cmp.l d4,d6beq.s ramtest2;----------------------------------; Report error in ram.;----------------------------------rmtst3bsr CRLFmoveq #'E',d1bsr DisplayCharbsr DisplaySpacemove.l a0,d1bsr DisplayTetrabsr DisplaySpacemove.l d5,d1bsr DisplayTetrabsr CheckForCtrlCbra ramtest2ramtest3rts;==============================================================================; Load an S19 format file;==============================================================================cmdLoadS19:bsr CRLFbra ProcessRecNextRec:bsr sGetCharcmpi.b #LF,d1bne NextRecmove.b #'.',d1bsr DisplayCharProcessRec:bsr CheckForCtrlC ; check for CTRL-C once per recordbsr sGetCharcmpi.b #CR,d1beq.s ProcessRecclr.b S19Checksummove.b d1,d4cmpi.b #CTRLZ,d4 ; CTRL-Z ?beq Monitorcmpi.b #'S',d4 ; All records must begin with an 'S'bne.s NextRecbsr sGetCharmove.b d1,d4cmpi.b #'0',d4 ; Record type must be between '0' and '9'blo.s NextReccmpi.b #'9',d4 ; d4 = record typebhi.s NextRecbsr sGetChar ; get byte count for recordbsr AsciiToHexNybblemove.b d1,d2bsr sGetCharbsr AsciiToHexNybblelsl.b #4,d2or.b d2,d1 ; d1 = byte countmove.b d1,d3 ; d3 = byte countadd.b d3,S19Checksumcmpi.b #'0',d4 ; manufacturer ID record, ignorebeq NextReccmpi.b #'1',d4beq ProcessS1cmpi.b #'2',d4beq ProcessS2cmpi.b #'3',d4beq ProcessS3cmpi.b #'5',d4 ; record count record, ignorebeq NextReccmpi.b #'7',d4beq ProcessS7cmpi.b #'8',d4beq ProcessS8cmpi.b #'9',d4beq ProcessS9bra NextRecpcssxa:move.l a1,d1bsr DisplayTetramove.b #CR,d1bsr DisplayCharandi.w #$ff,d3subi.w #1,d3 ; one less for dbra.0001:clr.l d2bsr sGetCharbsr AsciiToHexNybblelsl.l #4,d2or.b d1,d2bsr sGetCharbsr AsciiToHexNybblelsl.l #4,d2or.b d1,d2add.b d2,S19Checksummove.b d2,(a1)+ ; move byte to memorydbra d3,.0001; Get the checksum byteclr.l d2bsr sGetCharbsr AsciiToHexNybblelsl.l #4,d2or.b d1,d2bsr sGetCharbsr AsciiToHexNybblelsl.l #4,d2or.b d1,d2eor.b #$FF,d2cmp.b S19Checksum,d2beq NextRecmove.b #'E',d1bsr DisplayCharbra NextRecProcessS1:bsr S19Get16BitAddressbra pcssxaProcessS2:bsr S19Get24BitAddressbra pcssxaProcessS3:bsr S19Get32BitAddressbra pcssxaProcessS7:bsr S19Get32BitAddressmove.l a1,S19StartAddressbsr _KeybdInitbra MonitorProcessS8:bsr S19Get24BitAddressmove.l a1,S19StartAddressbsr _KeybdInitbra MonitorProcessS9:bsr S19Get16BitAddressmove.l a1,S19StartAddressbsr _KeybdInitbra MonitorS19Get16BitAddress:clr.l d2bsr sGetCharbsr AsciiToHexNybblemove.b d1,d2bra S1932bS19Get24BitAddress:clr.l d2bsr sGetCharbsr AsciiToHexNybblemove.b d1,d2bra S1932aS19Get32BitAddress:clr.l d2bsr sGetCharbsr AsciiToHexNybblemove.b d1,d2bsr sGetCharbsr AsciiToHexNybblelsl.l #4,d2or.b d1,d2bsr sGetCharbsr AsciiToHexNybblelsl.l #4,d2or.b d1,d2S1932a:bsr sGetCharbsr AsciiToHexNybblelsl.l #4,d2or.b d1,d2bsr sGetCharbsr AsciiToHexNybblelsl.l #4,d2or.b d1,d2S1932b:bsr sGetCharbsr AsciiToHexNybblelsl.l #4,d2or.b d1,d2bsr sGetCharbsr AsciiToHexNybblelsl.l #4,d2or.b d1,d2bsr sGetCharbsr AsciiToHexNybblelsl.l #4,d2or.b d1,d2clr.l d4move.l d2,a1; Add bytes from address value to checksumadd.b d2,S19Checksumlsr.l #8,d2add.b d2,S19Checksumlsr.l #8,d2add.b d2,S19Checksumlsr.l #8,d2add.b d2,S19Checksumrts;------------------------------------------------------------------------------; Get a character from auxillary input. Waiting for a character is limited to; 32000 tries. If a character is not available within the limit, then a return; to the monitor is done.;; Parameters:; none; Returns:; d1 = character from receive buffer or -1 if no char available;------------------------------------------------------------------------------sGetChar:movem.l d0/d2,-(a7)move.w #32000,d2.0001:moveq #36,d0 ; serial get char from buffertrap #15tst.w d1 ; was there a char available?bpl.s .0002dbra d2,.0001 ; no - try againmovem.l (a7)+,d0/d2.0003:bsr _KeybdInitbra Monitor ; ran out of tries.0002:movem.l (a7)+,d0/d2cmpi.b #CTRLZ,d1 ; receive end of file?beq .0003rtsAudioInputTest:rtsBouncingBalls:rtsGraphicsDemo:rtsClearScreen:bra clear_screenrts;------------------------------------------------------------------------------; Reverse the order of bytes in d1.;------------------------------------------------------------------------------rbo:rol.w #8,d1swap d1rol.w #8,d1rts;==============================================================================; Serial I/O routines;==============================================================================;------------------------------------------------------------------------------; Initialize the serial port an enhanced 6551 circuit.;; Select internal baud rate clock divider for 9600 baud; Reset fifos, set threshold to 3/4 full on transmit and 3/4 empty on receive; Note that the byte order is swapped.;------------------------------------------------------------------------------SerialInit:clr.w SerHeadRcv ; clear receive buffer indexesclr.w SerTailRcvclr.b SerRcvXon ; and Xon,Xoff flagsclr.b SerRcvXoffmove.l #$09000000,d0 ; dtr,rts active, rxint enabled, no paritymove.l d0,ACIA+ACIA_CMD; move.l #$1E00F700,d0 ; fifos enabledmove.l #$1E000000,d0 ; fifos disabledmove.l d0,ACIA+ACIA_CTRLrts; move.l #$0F000000,d0 ; transmit a break for a while; move.l d0,ACIA+ACIA_CMD; move.l #300000,d2 ; wait 100 ms; bra .0001;.0003:; swap d2;.0001:; nop; dbra d2,.0001;.0002:; swap d2; dbra d2,.0003; move.l #$07000000,d0 ; clear break; move.l d0,ACIA+ACIA_CMD; rts;------------------------------------------------------------------------------; SerialGetChar;; Check the serial port buffer to see if there's a char available. If there's; a char available then return it. If the buffer is almost empty then send an; XON.;; Stack Space:; 2 long words; Parameters:; none; Modifies:; d0,a0; Returns:; d1 = character or -1;------------------------------------------------------------------------------SerialGetChar:move.l d2,-(a7)movec coreno,d0swap d0moveq #SERIAL_SEMA,d1bsr LockSemaphorebsr SerialRcvCount ; check number of chars in receive buffercmpi.w #8,d0 ; less than 8?bhi .sgc2tst.b SerRcvXon ; skip sending XON if already sentbne .sgc2 ; XON already sent?move.b #XON,d1 ; if <8 send an XONclr.b SerRcvXoff ; clear XOFF statusmove.b d1,SerRcvXon ; flag so we don't send it multiple timesbsr SerialPutChar ; send it.sgc2:move.w SerHeadRcv,d1 ; check if anything is in buffercmp.w SerTailRcv,d1beq .NoChars ; no?lea SerRcvBuf,a0move.b (a0,d1.w),d1 ; get byte from bufferaddi.w #1,SerHeadRcvandi.w #$FFF,SerHeadRcv ; 4k wrap aroundandi.l #$FF,d1bra .Xit.NoChars:moveq #-1,d1.Xit:exg d1,d2movec coreno,d0swap d0moveq #SERIAL_SEMA,d1bsr UnlockSemaphoreexg d2,d1move.l (a7)+,d2rts;------------------------------------------------------------------------------; SerialPeekChar;; Check the serial port buffer to see if there's a char available. If there's; a char available then return it. But don't update the buffer indexes. No need; to send an XON here.;; Stack Space:; 0 words; Parameters:; none; Modifies:; d0,d2,a0; Returns:; d1 = character or -1;------------------------------------------------------------------------------SerialPeekChar:movec coreno,d0swap d0moveq #SERIAL_SEMA,d1bsr LockSemaphoremove.w SerHeadRcv,d2 ; check if anything is in buffercmp.w SerTailRcv,d2beq .NoChars ; no?lea SerRcvBuf,a0move.b (a0,d2.w),d2 ; get byte from bufferbra .Xit.NoChars:moveq #-1,d2.Xit:movec coreno,d0swap d0moveq #SERIAL_SEMA,d1bsr LockSemaphoremove d2,d1rts;------------------------------------------------------------------------------; SerialPeekChar; Get a character directly from the I/O port. This bypasses the input; buffer.;; Stack Space:; 0 words; Parameters:; none; Modifies:; d; Returns:; d1 = character or -1;------------------------------------------------------------------------------SerialPeekCharDirect:move.b ACIA+ACIA_STAT,d1 ; get serial statusbtst #3,d1 ; look for Rx not emptybeq.s .0001moveq.l #0,d1 ; clear upper bits of return valuemove.b ACIA+ACIA_RX,d1 ; get data from ACIArts ; return.0001:moveq #-1,d1rts;------------------------------------------------------------------------------; SerialPutChar; Put a character to the serial transmitter. This routine blocks until the; transmitter is empty.;; Stack Space; 0 words; Parameters:; d1.b = character to put; Modifies:; none;------------------------------------------------------------------------------SerialPutChar:movem.l d0/d1,-(a7) ; push d0,d1.0001:move.b ACIA+ACIA_STAT,d0 ; wait until the uart indicates tx emptybtst #4,d0 ; bit #4 of the status regbeq.s .0001 ; branch if transmitter is not emptymove.b d1,ACIA+ACIA_TX ; send the bytemovem.l (a7)+,d0/d1 ; pop d0,d1rts;------------------------------------------------------------------------------; Reverse the order of bytes in d1.;------------------------------------------------------------------------------SerialRbo:rol.w #8,d1swap d1rol.w #8,d1rts;------------------------------------------------------------------------------; Calculate number of character in input buffer;; Returns:; d0 = number of bytes in buffer.;------------------------------------------------------------------------------SerialRcvCount:move.w SerTailRcv,d0sub.w SerHeadRcv,d0bge .0001move.w #$1000,d0sub.w SerHeadRcv,d0add.w SerTailRcv,d0.0001:rts;------------------------------------------------------------------------------; Serial IRQ routine;; Keeps looping as long as it finds characters in the ACIA recieve buffer/fifo.; Received characters are buffered. If the buffer becomes full, new characters; will be lost.;; Parameters:; none; Modifies:; none; Returns:; d1 = -1 if IRQ handled, otherwise zero;------------------------------------------------------------------------------SerialIRQ:move.w #$2300,sr ; disable lower level IRQsmovem.l d0/d1/d2/a0,-(a7)movec coreno,d0swap d0moveq #SERIAL_SEMA,d1bsr LockSemaphoresirqNxtByte:move.b ACIA+ACIA_STAT,d1 ; check the statusbtst #3,d1 ; bit 3 = rx fullbeq notRxIntmove.b ACIA+ACIA_RX,d1sirq0001:move.w SerTailRcv,d0 ; check if recieve buffer fulladdi.w #1,d0andi.w #$FFF,d0cmp.w SerHeadRcv,d0beq sirqRxFullmove.w d0,SerTailRcv ; update tail pointersubi.w #1,d0 ; backupandi.w #$FFF,d0lea SerRcvBuf,a0 ; a0 = buffer addressmove.b d1,(a0,d0.w) ; store recieved byte in buffertst.b SerRcvXoff ; check if xoff already sentbne sirqNxtBytebsr SerialRcvCount ; if more than 4080 chars in buffercmpi.w #4080,d0blo sirqNxtBytemove.b #XOFF,d1 ; send an XOFFclr.b SerRcvXon ; clear XON statusmove.b d1,SerRcvXoff ; set XOFF statusbsr SerialPutChar ; send XOFFbra sirqNxtByte ; check the status for another bytesirqRxFull:notRxInt:movec coreno,d0swap d0moveq #SERIAL_SEMA,d1bsr UnlockSemaphoremovem.l (a7)+,d0/d1/d2/a0rtenmeSerial:dc.b "Serial",0;------------------------------------------------------------------------------;------------------------------------------------------------------------------evenbus_err:.0001:nopbra .0001trap3:; First save all registersmovem.l d0/d1/d2/d3/d4/d5/d6/d7/a0/a1/a2/a3/a4/a5/a6/a7,Regsavemove.w (a7)+,Regsave+$40move.l (a7)+,Regsave+$44move.l #$40FFC,a7 ; reset stack pointermove.w #$2500,sr ; enable interruptsmove.w NumSetBreakpoints,d0subi.w #1,d0lea Breakpoints,a0move.l Regsave+$44,d1.0001:cmp.l (a0)+,d1beq.s ProcessBreakpointdbra d0,.0001bra Monitor ; not a breakpointProcessBreakpoint:bsr DisarmAllBreakpointsbra cmdDumpRegs;------------------------------------------------------------------------------; DisarmAllBreakpoints, used when entering the monitor.;------------------------------------------------------------------------------DisarmAllBreakpoints:movem.l d0/a0/a1/a2,-(a7) ; stack some regsmove.w NumSetBreakpoints,d0 ; d0 = number of breakpoints that are setcmpi.w #numBreakpoints,d0 ; check for valid numberbhs.s .0001lea Breakpoints,a2 ; a2 = pointer to breakpoint address tablelea BreakpointWords,a0 ; a0 = pointer to breakpoint instruction word tablebra.s .0003 ; enter loop at bottom.0002:move.l (a2)+,a1 ; a1 = address of breakpointmove.w (a0)+,(a1) ; copy instruction word back to code.0003:dbra d0,.0002movem.l (a7)+,d0/a0/a1/a2 ; restore regs.0001:rts;------------------------------------------------------------------------------; ArmAllBreakpoints, used when entering the monitor.;------------------------------------------------------------------------------ArmAllBreakpoints:movem.l d0/a0/a1/a2,-(a7) ; stack some regsmove.w NumSetBreakpoints,d0 ; d0 = number of breakpointscmpi.w #numBreakpoints,d0 ; is the number valid?bhs.s .0001lea Breakpoints,a2 ; a2 = pointer to breakpoint address tablelea BreakpointWords,a0 ; a0 = pointer to instruction word tablebra.s .0003 ; enter loop at bottom.0002:move.l (a2)+,a1 ; a1 = address of breakpointmove.w (a1),(a0) ; copy instruction word to tablemove.w #$4E43,(a0)+ ; set instruction = TRAP3.0003:dbra d0,.0002movem.l (a7)+,d0/a0/a1/a2 ; restore regs.0001:rts;------------------------------------------------------------------------------;------------------------------------------------------------------------------ArmBreakpoint:movem.l d0/d1/d2/a0/a1/a2,-(a7)move.w NumSetBreakpoints,d0 ; d0 = number of breakpointscmpi.w #numBreakpoints,d0 ; check if too manybhs.s .0001addi.w #1,NumSetBreakpoints ; increment number of breakpointsmove.l d0,d2bsr ignBlanksbsr GetHexNumberbeq.s .0001 ; was there an address?btst #0,d1 ; address value must be evenbne.s .0001; See if the breakpoint is in the table alreadylea Breakpoints,a1 ; a1 points to breakpoint tablemove.w #numBreakpoints-1,d2.0002:cmp.l (a1)+,d1beq.s .0003 ; breakpoint is in table alreadydbra d2,.0002; Add breakpoint to table; Search for empty entrylea Breakpoints,a1 ; a1 = pointer to breakpoint address tableclr.w d2 ; d2 = count.0006:tst.l (a1) ; is the entry empty?beq.s .0005 ; branch if found empty entrylea 4(a1),a1 ; point to next entryaddi.w #1,d2 ; increment countcmpi.w #numBreakpoints,d2 ; safety: check against max numberblo.s .0006bra.s .0001 ; what? no empty entries found, table corrupt?.0005:asl.w #2,d2 ; d2 = long word indexmove.l d1,(a1,d2.w) ; move breakpoint address to tablemove.l d1,a2lsr.w #1,d2 ; d2 = word index.0004:lea BreakpointWords,a1move.w (a2),(a1,d2.w) ; copy instruction word to tablemove.w #$4E43,(a2) ; replace word with TRAP3.0001:movem.l (a7)+,d0/d1/d2/a0/a1/a2rts.0003:move.l -4(a1),a2 ; a2 = pointer to breakpoint address from tablecmpi.w #$4E43,(a2) ; see if breakpoint already armedbeq.s .0001asl.l #1,d2 ; d2 = word indexbra.s .0004;------------------------------------------------------------------------------;------------------------------------------------------------------------------DisarmBreakpoint:movem.l d0/d1/d2/a0/a1/a2,-(a7)move.w NumSetBreakpoints,d0 ; d0 = number of breakpointscmpi.w #numBreakpoints,d0 ; check if too manybhi.s .0001move.l d0,d2bsr ignBlanksbsr GetHexNumberbeq.s .0001 ; was there an address?btst #0,d1 ; address value must be evenbne.s .0001; See if the breakpoint is in the table alreadylea Breakpoints,a1 ; a1 points to breakpoint tablesubi.w #1,d2.0002:cmp.l (a1)+,d1beq.s .0003 ; breakpoint is in table alreadydbra d2,.0002bra .0001 ; breakpoint was not in table.0003:; Remove breakpoint from tablesubi.w #1,NumSetBreakpoints ; decrement number of breakpointsmove.l -4(a1),a2 ; a2 = pointer to breakpoint address from tableclr.l -4(a1) ; empty out breakpointlea BreakpointWords,a1asl.l #1,d2 ; d2 = word indexmove.w (a1,d2.w),(a2) ; copy instruction from table back to code.0001:movem.l (a7)+,d0/d1/d2/a0/a1/a2rts;------------------------------------------------------------------------------;------------------------------------------------------------------------------ListBreakpoints:bsr CRLFmove.w #numBreakpoints,d2lea Breakpoints,a1.0001:move.l (a1)+,d1bsr DisplayTetrabsr CRLFdbra d2,.0001bra Monitor;------------------------------------------------------------------------------;------------------------------------------------------------------------------ClearBreakpointList:move.w #numBreakpoints,d2lea Breakpoints,a1.0001:clr.l (a1)+dbra d2,.0001rts;------------------------------------------------------------------------------; SendMsg; 00100xy0;; Parameters:; d1 = target core number; d2 = argument 1; d3 = argument 2; d4 = argument 3;;------------------------------------------------------------------------------SendMsg:movem.l d5/a1,-(a7)lsl.w #8,d1movec coreno,d5lsl.w #4,d5or.w d5,d1lea $00100000,a1tst.l 0(a1,d1.w)bne .msgFullmovec coreno,d5move.l d5,0(a1,d1.w)move.l d2,4(a1,d1.w)move.l d3,8(a1,d1.w)move.l d4,12(a1,d1.w)movem.l (a7)+,d5/a1moveq #0,d1rts.msgFull:movem.l (a7)+,d5/a1moveq #-1,d1rts;------------------------------------------------------------------------------; ReceiveMsg; Scan the message table for messages and dispatch them.; 00100xy0;; Parameters:;------------------------------------------------------------------------------ReceiveMsg:movem.l d1/d2/d3/d4/d5/d6/d7/a1,-(a7)lea $00100000,a1movec coreno,d5lsl.w #8,d5moveq #2,d6.nextCore:move.w d6,d7lsl.w #4,d7add.w d5,d7tst.l 0(a1,d7.w) ; Is there a message from core d6?beq .noMsgmove.l 0(a1,d7.w),d1move.l 4(a1,d7.w),d2move.l 8(a1,d7.w),d3move.l 12(a1,d7.w),d4clr.l 0(a1,d7.w) ; indicate message was receivedbsr DispatchMsg.noMsg:addq #1,d6cmp.w #9,d6bls .nextCoremovem.l (a7)+,d1/d2/d3/d4/d5/d6/d7/a1rts;------------------------------------------------------------------------------;------------------------------------------------------------------------------DispatchMsg:rts;------------------------------------------------------------------------------;------------------------------------------------------------------------------InitIRQ:moveq #6,d0lea KeybdIRQ,a0bsr InstallIRQlea TickIRQ,a0bsr InstallIRQmoveq #3,d0lea SerialIRQ,a0; fall through;------------------------------------------------------------------------------; Install an IRQ handler.;; Parameters:; d0 = IRQ level; a0 = pointer to IRQ routine; Returns:; d1 = -1 if successfully added, 0 otherwise; nf = 1, zf = 0 if successfully added, otherwise nf = 0, zf = 1;------------------------------------------------------------------------------InstallIRQ:move.l d0,-(a7) ; save working registerlea InstalledIRQ,a1 ; a1 points to installed IRQ listlsl.w #5,d0 ; multiply by 8 long words per IRQ level.nextSpot:cmpa.l (a1,d0.w),a0 ; Is the IRQ already installed?beq.s .foundtst.l (a1,d0.w) ; test for an empty spotbeq.s .foundSpotaddi.w #4,d0 ; increment to next slotmove.w d0,d1andi.w #$1F,d1 ; check to see if spots exhaustedbeq.s .noEmptiesbra.s .nextSpot.foundSpot:move.l a0,(a1,d0.w) ; add IRQ routine to table.found:move.l (a7)+,d0moveq #-1,d1 ; return successrts.noEmpties:move.l (a7)+,d0moveq #0,d1 ; return failed to addrts;------------------------------------------------------------------------------;------------------------------------------------------------------------------TickIRQ:move.w #$2600,sr ; disable lower level IRQsmovem.l d1/d2/a0,-(a7); ToDo: detect a tick interrupt; move.l PLIC+$00,d1; rol.l #8,d1; cmpi.b #29,d1; bne.s .notTickmovec coreno,d1 ; d1 = core numbercmpi.b #2,d1bne.s .0001move.l #$1D000000,PLIC+$14 ; reset edge sense circuit.0001:move.l TextScr,a0 ; a0 = screen addressmove.l (a0),d2rol.w #8,d2 ; reverse byte order of d2swap d2rol.w #8,d2addi.b #'0',d1 ; binary to ascii core numberadd.b d2,d1rol.w #8,d1 ; put bytes back in orderswap d1rol.w #8,d1move.l d1,4(a0) ; update onscreen IRQ flagaddi.l #1,(a0) ; flashy colors; addi.l #1,40(a0) ; nice effectbsr ReceiveMsgmovem.l (a7)+,d1/d2/a0rte;.notTick:; movem.l (a7)+,d1/a0; rte;------------------------------------------------------------------------------;------------------------------------------------------------------------------irq3_rout:movem.l d0/d1/a0/a1,-(a7)lea InstalledIRQ+8*4*3,a0bra irq_routirq6_rout:movem.l d0/d1/a0/a1,-(a7)lea InstalledIRQ+8*4*6,a0irq_rout:moveq #7,d0.nextHandler:move.l (a0)+,a1beq.s .0003jsr (a1)tst.l d1 ; was IRQ handled?bmi.s .0002 ; first one to return handled quits loop.0003:dbra d0,.nextHandler.0002:movem.l (a7)+,d0/d1/a0/a1 ; returnSpuriousIRQ:rte; bsr KeybdIRQ; tst.l d1 ; handled by KeybdIRQ?; bmi.s .0002 ; if yes, go return;.0001:; move.l #$1D000000,PLIC+$14 ; reset edge sense circuit; move.l TextScr,a0 ; a0 = screen address; addi.l #1,40(a0) ; update onscreen IRQ flag;.0002:; movem.l (a7)+,d0/d1/a0/a1 ; return; rtenmi_rout:movem.l d0/d1/a0,-(a7)move.b #'N',d1bsr DisplayCharmovem.l (a7)+,d0/d1/a0 ; returnrtebrdisp_trap:movem.l d0/d1/d2/d3/d4/d5/d6/d7/a0/a1/a2/a3/a4/a5/a6/a7,Regsavemove.w (a7)+,Regsave+$40move.l (a7)+,Regsave+$44move.l #$40FFC,a7 ; reset stack pointermove.w #$2500,sr ; enable interruptslea msg_bad_branch_disp,a1bsr DisplayStringbsr DisplaySpacemove.l Regsave+$44,d1 ; exception addressbsr DisplayTetra ; and display it; move.l (sp)+,d1 ; pop format word 68010 mode onlybra cmdDumpRegsillegal_trap:addq #2,sp ; get rid of srmove.l (sp)+,d1 ; pop exception addressbsr DisplayTetra ; and display itlea msg_illegal,a1 ; followed by messagebsr DisplayString.0001:bra .0001bra Monitorio_irq:addq #2,spmove.l (sp)+,d1bsr DisplayTetralea msg_io_access,a1bsr DisplayStringbra cmdDumpRegs; -----------------------------------------------------------------------------; -----------------------------------------------------------------------------msg_start:dc.b "Femtiki rf68k Multi-core OS Starting",LF,CR,0; dc.b "rf68k System Starting",CR,LF,0msg_core_start:dc.b " core starting",CR,LF,0msg_illegal:dc.b " illegal opcode",CR,LF,0msg_bad_branch_disp:dc.b " branch selfref: ",0msg_test_done:dc.b " CPU test done.",0msg_io_accessdc.b " unpermitted access to I/O",0
Go to most recent revision | Compare with Previous | Blame | View Log
