📄 nios_germs_monitor.s
字号:
NOP
BR doMWrite_did
NOP
doMWrite16:
BSR Stash16
NOP
.else
; Send in two bytes to the StashByte routine
; so that it handles writing to flash
BSR StashByte
MOV %l6,%o1 ; reserve high (later) byte
LSRI %l6,8
MOV %o1,%l6 ; send the high byte
BSR StashByte
ADDI %i2,1 ; (delay slot) to the next address
.endif
doMWrite_did:
CMPI %l7,13 ; %l7 has break char from GetHex
IFS cc_ne
BR doMWriteLoop
ADD %i2,%g3 ; (delay slot) increment address
BR ReceiveCommand
NOP
doMFill:
MOV %l6,%o4 ; preserve low end of range
BSR GetHex
MOV %l5,%o1 ; (delay slot) preserve end of range
BSR FillRAM
MOV %o3,%l6 ; preserve for <CR> later
BR ReceiveCommand
MOV %l5,%o3 ; restore for <CR> later to show from start of range
;--------------
; FillRAM
;
; %l6 = start, %l5 = end, %o1 = value
;
FillRAM:
fillRAMLoop:
G_ST16 %l6,%o1
ADDI %l6,2 ; go by twos and hit every 16 bit word (nios16 _and_ 32)
CMP %l6,%l5
IFS cc_ne
BR fillRAMLoop
NOP
JMP %o7
NOP
; -------------------------
; S-Record handlin'
;
doS:
BSR GetChar ; Fetch the record type
NOP
MOV %i0,%o0 ; record type stashed
BSR GetHexBytes
MOVI %o3,1 ; (delay slot) Fetch record length
MOV %i1,%o1 ; record length (including address) stashed
SUBI %i1,1 ; decrement to ignore the checksum @ the end
AND %i0,%g5 ; mask of low bits of presumed ascii digit
IFS cc_eq ; zero?
BR ignoreS ; that's a kind we ignore
CMPI %i0,4 ; data record?
IFS cc_lt
BR doS123 ; yup! go do data record
NOP
SUBI %i0,7 ; 789->012
IFS cc_mi ; was a 45 or 6...
BR ignoreS
CMPI %i0,3
IFS cc_lt
BR doS789
NOP
ignoreS:
happyWaitForEOL: ; Ignores until the end of line, then begins anew.
BSR WaitForEOL
NOP
BR ReceiveCommand
NOP
doS123:
ADDI %i0,1 ; got here with %i0 = 12 or 3, change to addr bytes
SUB %i1,%i0 ; %i1 = number of data bytes to absorb, now
BSR GetHexBytes
MOV %o3,%i0 ; (delay slot) count of bytes to get
MOV %i2,%o1 ; %i2 = address to read into
; -----------------
; Come here with %i2 = address to read bytes into
; %i1 = number of bytes to read
; %l4 = forced offset (relocation) to apply to all addresses (or zero)
doSReadData:
ADD %i2,%l4 ; Override the start address with %l4 (force address)
doSReadData1:
BSR GetHexBytes ; Read a byte of data
MOVI %o3,1 ; (delay slot) bytecount = 1
BSR StashByte ; puts %o1 into [%i2], and does FLASH stuff if needed
SUBI %i1,1 ; (delay slot, but OK)
IFRnz %i1 ; zero bytes remaining?
BR doSReadData1 ; no: loop back around
ADDI %i2,1 ; (delay slot) bump to next byte in any case
BR ignoreS ; ignore the checksum, and continue onward
NOP
doS789:
NEG %i0 ; got here with %i0=012 for 789
ADDI %i0,4 ; now 987->234, byte count for GO address
BSR GetHexBytes
MOV %o3,%i0 ; (delay slot) bytes of address to read
BSR WaitForEOL ; don't do anything until the line is finished
NOP
BR Go ; %o1 is ready...
NOP
doG:
BSR GetHex
NOP
Go:
LSRI %o1,1 ; divide in half for JMP action
CALL %o1
NOP
BR postFlash_start
NOP
doE:
BSR GetHex
NOP
ANDN %o1,%g6 ; mask off low 2 bits if address
.ifdef GM_FlashTop
BSR InFlashRange
MOV %i2,%o1 ; (delay slot, put address to check in %i2) see if it's flash
IFS cc_ne ; if not, just skip
BR ReceiveCommand
NOP
;
; Begin strange Flash-Erase sequence
;
BSR flash555aa
NOP
BSR flash2AA55
NOP
MOVIP %g0,0x80
BSR flash555g0
NOP
BSR flash555aa
NOP
BSR flash2AA55
NOP
; And finally tell the Flash what sector to erase...
MOVIP %g0,0x30
G_ST16 %i2,%g0
; Loop until the data reads as 0xFFFF (and we dont know whats in the high word)
.ifdef __nios32__
BGEN %g2,25 ; watchdog timeout, an excessive number
.else
BGEN %g2,15 ; (or a less-excessive number, scaled, on n16)
.endif
flashEraseLoop:
.ifdef __nios16__
BGEN %g1,10 ; for nios 16, nest a loop here
flashEraseLoop_16:
IFRnz %g1
BR flashEraseLoop_16
SUBI %g1,1
.endif
IFRz %g2
BR ReceiveCommand
SUBI %g2,1
LD %g0,[%i2]
.ifdef __nios32__
SEXT16 %g0
.endif
ADDI %g0,1 ; IF done, %g0 == 0 now
IFRnz %g0
BR flashEraseLoop
NOP ; safety first
;
; Now, count to a million, just to be terribly sure.
;
.ifdef __nios32__
BGEN %g0,20 ; m32 only, eh.
.else
BGEN %g0,15 ; (or a less-excessive number, scaled, on n16)
.endif
flashErasePostLoop:
IFRnz %g0
BR flashErasePostLoop
SUBI %g0,#1 ; (delay slot)
BR ReceiveCommand
NOP
.endif ; GM_FlashTop
; -------------------------
; doR: Set Relocate
; usage:
; +r10800 <--- add 0x10800 to addresses in s-records/i-hex
; +r40000-180000 <--- add 0x140000 to addresses in s-records/i-hex
doR:
BSR GetHex
NOP
SUB %o1,%o4 ; offset end address - start address (or just end)
BR ReceiveCommand
MOV %l4,%o1 ; (delay slot)
; -----------------------
; GetChar and PutChar
; both work on %o0
; GetChar always echoes
getCharLFEcho: ; front end loopover *just* for echoing those ignored Linefeeds.
LDP %g0,[%l0,np_uartstatus] ; status register
IF0 %g0,6
BR getCharLFEcho
NOP
STP [%l0,1],%o0 ; (delay slot) send %o0 out
GetChar:
LDP %g0,[%l0,np_uartstatus]
IF0 %g0,np_uartstatus_rrdy_bit ; bit 7: RRdy
BR GetChar
NOP
LDP %o0,[%l0,np_uartrxdata]
CMPI %o0,0x0A ; Ignore LF's
SKPS cc_ne
BR getCharLFEcho ; (echo the LF, but don't return it)
CMPI %o0,0x1B ; <ESC> restarts monitor: the only line editing.
IFS cc_eq
BR postFlash_start
NOP
; and fall into PutChar for echo
.ifdef __supportGDB__
;
; Unless we're supporting GDB! in which
; case, a $ immediately yanks us over
; to the echo-less GDB parser!
;
; Once we get a $ and start doing GDB commands,
; we stay in GDB mode.
;
CMPIP %o0,'$'
IFS cc_eq
BR doGDBCommand
.endif
PutChar:
LDP %g0,[%l0,np_uartstatus] ; status register
SKP1 %g0,6 ; bit 6: TRdy
BR PutChar
NOP
JMP %o7
STP [%l0,1],%o0 ; (delay slot) send %o0 out
PutHash:
MOVIP %o0,'#'
BR PutChar ; (watch out for delay slot below...)
WaitForEOL:
MOV %o5,%o7
waitForEOLLoop:
BSR GetChar
NOP
CMPI %o0,0x0D
SKPS cc_eq
BR waitForEOLLoop
NOP
JMP %o5
NOP
; --------------
; PutHex %o1
;
; Prints four characters (16 bit value)
;
; Uses %o2 for shift amount
; Uses %o5 as alternate return address
;
PutHex: ; value %o1
MOV %o5,%o7
MOVI %o2,12
putHexLoop:
MOV %o0,%o1
LSR %o0,%o2
AND %o0,%g5
CMPI %o0,9
SKPS cc_le
ADDI %o0,'A'-'0'-10
ADDIP %o0,'0'
BSR PutChar
NOP
SKPRz %o2
BR putHexLoop
SUBI %o2,4 ; (delay slot) decrement shift amount
JMP %o5
NOP
; -----------------------
; GetHex
;
; In: %o3 - number of characters to read (GetHexBytes only)
; %o2 - character to break on, in addition to CR
;
; Out: %o1 - value read
; %o0 - last character typed (CR or %o2 break char)
; %g3 - number of bytes read (if caller cleared %g3 first)
;
;
; Gets hex value until CR
; returns value in %o1
; A hyphen-separated pair returns
; the 2nd on %o1, and the 1st in %o4
;
; GetHexUntil will scan hex chars until either a CR
; or the character in %o2 (still with a hyphen moving
; stuff to %o4).
;
; Return number of bytes read in %g3 (caller MUST clear
; %g3 first, for this feature to work)
GetHexUntil:
BR getHexEntry1 ; dive in with user's %o2 and 31 char limit
MOVI %o3,31
GetHex:
MOVI %o3,31 ; maximum character count
GetHexBytes: ; entry point to use %o3 to signify byte count
MOVI %o2,13 ; default return-break char
getHexEntry1:
ADD %o3,%o3 ; double for chars
MOV %o5,%o7 ; return address...
MOVI %o1,0 ; result
getNextHex:
MOV %o4,%o1 ; come here after a hypen, too
MOVI %o1,0 ; result'
getHexLoop:
BSR GetChar
ADDI %g3,1 ; bump char count
CMPIP %o0,'-' ; hyphen separated pair...
IFS cc_eq
BR getNextHex
CMP %o0,%o2 ; user-passed return character?
IFS cc_eq ; go home
BR getHexDone ; exit loop from here
CMPI %o0,13 ; carriage return?
IFS cc_eq ; go home
BR getHexDone ; exit loop from here
SUBI %o3,1 ; decrement char count
SKP0 %o0,6 ; bit 6 indicates alpha char
ADDI %o0,9 ; if so, move up to 10-15
AND %o0,%g5 ; and with 0x0f.
LSLI %o1,4
SKPRz %o3 ; was this the last character?
BR getHexLoop ; loop back if not
ADD %o1,%o0 ; (delay slot) last or not, add in the last nibble
getHexDone:
JMP %o5 ; return
LSRI %g3,1 ; turn char count to byte count
;--------------------
; Return Z flag set if %i2 is in flash range.
; Trash %l1.
.ifdef GM_FlashTop ; nonzero FlashTop means we have some flash
InFlashRange:
.if ((GM_FlashBase==0x100000)&&(GM_FlashTop==0x200000))
; Clever trick because flash range is [0x100000,0x200000)
MOV %l1,%i2
LSRI %l1,20
JMP %o7
CMPI %l1,1
.else
MOVI %l1,1
MOVIP %r0,GM_FlashBase
CMP %i2,%r0
IFS cc_mi
MOVI %l1,0 ; out of range
MOVIP %r0,GM_FlashTop
CMP %i2,%r0
IFS cc_pl
MOVI %l1,0 ; out of range
JMP %o7
CMPI %l1,1
.endif
.endif
.if GM_WIDTHS
;--------------------
; Stash16 -- either
; do a st16 (or st, on nios16)
; or pass it off to flashwrite
Stash16:
.ifdef GM_FlashTop
MOV %o4,%o7 ; stash return address, deeper than usual!
BSR InFlashRange
NOP
IFS cc_eq
BR FlashWrite16
NOP
G_ST16 %i2,%o1
JMP %o4
NOP
.else
G_ST16 %i2,%o1
JMP %o7
NOP
.endif
.endif
;--------------------
; Stash byte routine shared
; by S-records and 'W' command
;
; Store byte %o1 into address %i2
; and don't corrupt anything important!
;
StashByte:
MOV %o4,%o7 ; stash return address, deeper than usual!
.ifdef GM_FlashTop
BSR InFlashRange
NOP
IFS cc_ne
BR stashByteRAM
NOP
; --------------
; We're storing to flash here...
IF1 %i2,0 ; odd address? then do the FlashWrite routine
BR FlashWrite
EXT8s %o1,0 ; (delay slot) always clear out the high bits
JMP %o4 ; return
MOV %g7,%o1 ; (delay slot) save the low byte
FlashWrite:
LSLI %o1,8
OR %o1,%g7 ; %o1 has word to write, and %i2 is address+1
FlashWrite16: ; %o4 must have return address already...
; -----------
; Begin bizarre Write Word flash sequence
BSR flash555aa
NOP
BSR flash2AA55
NOP
MOVIP %g0,0xa0
BSR flash555g0
NOP
;
; And the actual data halfword
;
G_ST16 %i2,%o1
;
; Now, follow the AMD polling algorithm...
;
.ifdef __nios32__
MOVIP %g2,0x80000 ; watchdog timeout, an excessive number, n32 only (~.5M)
.else
MOVIP %g2,0x8000
.endif
flashWriteLoop:
;
; Decrement watchdog
;
IFRz %g2
BR flashWriteFail
SUBI %g2,1
.ifdef __nios16__
MOVI %g1,20 ; add extra cycles on n16, !!! could be made a subroutine?
flashWriteLoop_16:
IFRnz %g1
BR flashWriteLoop_16
SUBI %g1,1
.endif
LD %g0,[%i2] ; (historically, this line of code was missing for a while...)
.ifdef __nios32__
;
; On Nios 32, be sure to look only at
; the correct 16 bits
;
EXT16d %g0,%i2
.endif
CMP %o1,%g0 ; match originally written data?
IFS cc_eq
BR flashWriteOK ; yes, we're done
NOP ; (delay slot);
BR flashWriteLoop ; no, keep trying
NOP ; (delay slot);
flashWriteFail:
;
; the write failed, we shall print '!' for error.
;
MOVIP %o0,'!'
BSR PutChar
NOP
flashWriteOK:
JMP %o4
NOP
stashByteRAM:
.endif ; if not handling flash case...
FILL8 %r0,%o1
JMP %o4 ; return
ST8d [%i2],%r0 ; (delay slot) actually stash the byte
; ----------------------------------
; particles of flash routines...
.ifdef GM_FlashTop
flash555aa: ; write aa to 555
MOVIP %g0,0xAA
flash555g0: ; write %r0 to 555
MOVIP %l1,GM_FlashBase+(2*0x555) ; magic programming address 1
flashSharedWrite:
G_ST16 %l1,%g0 ; do the store in the delay slot
JMP %o7 ; return
NOP
flash2AA55: ; write 55 to 2AA
MOVIP %g0,0x55
MOVIP %l1,GM_FlashBase+(2*0x2AA) ; magic programming address 2
BR flashSharedWrite
NOP
.endif ; GM_FlashTop
.else
# GM_UARTBase -- no uart, the monitor is empty
; There is no monitor here, since the system has no UART.
; Here's an infinite loop for your CPU to enjoy.
NoUART:
BR NoUART
NOP
.asciz "There is no monitor here."
.endif
# End of file
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -