// ================================
// sdram marching test program
//		(c) 2022	1YEN Toru
//
//
//		2022/04/16	ver.1.04
//			corresponding to Nihonium
//
//		2022/03/12	ver.1.02
//			corresponding to cache2w4k unit
//
//		2022/02/19	ver.1.00
//
// ================================
asm		"mcoc_irom.mif"
#asm		"mcoc_irom.mem"
#asm		"mcoc_irom.dat2",bit16,list
incl	"mcoc115.incl"
# ================================
# string macros
def		prog_name,"test_sdram"
def		prog_vers,"1.04"
def		s,"#"							// simulation="" / real fpga="#"
# constants
equ		max_lbuf,64						// size of lbuf
equ		baud,9600						// baud rate
equ		uart_baud,fcpu/baud-1			// uartbaud setting
equ		chr_lf,0x0a						// lf code
equ		chr_cr,0x0d						// cr code
equ		chr_cma,0x2c					// comma ',' code
equ		mch_top,0x800000				// mch: start address (24 bit)
equ		mch_end,0xffffff				// mch: end address (24 bit)
equ		mch_inc,0x0002					// mch: address increment (16 bit)
equ		cchc_max_idx,128				// cch: cache maximum index address
$(s)// ********************************
$(s)equ		mch_inc,0xfedc				// march: address increment (for sim)
$(s)// ********************************
# variables
equ		va,ramtop
equ		acc_adr,va						// address to access (32 bit)
equ		va,va+4
equ		acc_dat,va						// data for access (16 bit)
equ		va,va+2
equ		mch_err_adr,va					// mch: fail address (32 bit)
equ		va,va+4
equ		mch_err_dat,va					// mch: fail data (16 bit)
equ		va,va+2
equ		cche_sw,va						// cch: cache on(1)/off(0)
equ		va,va+2
equ		static_va,va
# array variables
equ		lbuf,va							// receive data buffer
equ		va,va+max_lbuf
equ		array_va,va
# ================================

// ================================
// setup
// ================================

// set sp to the bottom of ram area
ldwi	r7,idrgramt						// idrg: ram top addr.
ldw		r7,[r7]
ldwi	r6,idrgrams						// idrg: ram size
ldw		r6,[r6]
add		r7,r6
movtc	sp,r7

// clear variables
ldwi	r7,ramtop
ldwi	r1,static_va
ldbiu	r0,0
st_clrvar:
stw		[r7],r0
addi	r7,2
cmp		r7,r1
blo		st_clrvar

// port setting
ldbiu	r0,led_builtin
ldwi	r7,porset
stw		[r7],r0
ldwi	r7,pordir
ldw		r0,[r7]
andi	r0,~led_builtin
stw		[r7],r0

// uart setting: RXE, TXE, baud rate
ldwi	r7,uartbaud
ldwi	r0,uart_baud
stw		[r7],r0
ldwi	r7,uartctl
ldbiu	r0,uart_rxe|uart_txe
stw		[r7],r0

// wait for sdram controller ready
ldwi	r7,sdrcctl
ldw		r0,[r7]
andi	r0,sdrc_sdrm
bne		sd_go_init
// ERROR: no SDRAM found
ldwi	r1,lab_str_err_nosd
jalwr7	print
bra		sd_skip_init
sd_go_init:
$(s)// ********************************
$(s)// test mode enable
$(s)ldbih	r0,0x80
$(s)stw		[r7],r0
$(s)// ********************************
// polling SRDY flag
ldw		r0,[r7]
andi	r0,sdrc_srdy
beq		pcnt-6
sd_skip_init:

// @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
// show sdram initialization time
ldwi	r1,lab_dbg_init
jalwr7	print
pushw	r1
ldwi	r7,sytmmcrh
ldw		r1,[r7]
jalwr7	print_hex
ldwi	r7,sytmmcrl
ldw		r1,[r7]
jalwr7	print_hex
popw	r1
jalwr7	print
bra		dbg_init_sdram
dbg_init:
dats	"DBG: sdram initialization time: 0x\0[us]\r\n\0"
dbg_init_sdram:
// @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

// send RDY
ldwi	r1,lab_str_msg_rdy
jalwr7	print

$(s)// ********************************
$(s)// for simulation
#1# ================================
#1$(s)// all write -> read
#1$(s)ldwi	r7,acc_dat
#1$(s)ldwi	r0,0xaaaa
#1$(s)stw		[r7],r0
#1$(s)jalwr7	sim_writea
# ================================
$(s)jalwr7	sim_march
#3$(s)ldbiu	r0,0
$(s)// simulation finish
$(s)mov		r0,r0
$(s)beq		pcnt+6
$(s)ldwi	r0,simfail
$(s)bra		pcnt+4
$(s)ldwi	r0,simpass
$(s)ldwi	r7,simfnsh
$(s)stw		[r7],r0
$(s)bra		pcnt-2
$(s)// ********************************

// ================================
// loop
// ================================
loop:

// ================================
// serial monitor handling
// check uartctl.RAVL
ldwi	r7,uartctl
ldw		r0,[r7]
andi	r0,uart_ravl
beq		no_data
jalwr7	get_line

// check "rd," command
ldwi	r1,lbuf
ldwi	r2,lab_str_cmd_rd
ldbiu	r5,3
jalwr7	strncmp
mov		r0,r0
bne		rd_notid
// ================================
// rd,<adr_hex6>
ldwi	r1,lbuf
// <adr_hex6>
addi	r1,3
jalwr7	xtol
andi	r3,0xff
ldwi	r7,acc_adr
stw		[r7],r3
addi	r7,2
stw		[r7],r0

// read from <adr_hex6>
ldwi	r7,acc_adr
ldw		r0,[r7]
movtc	tr,r0
addi	r7,2
ldw		r7,[r7]
ldwx	r0,[r7]
ldwi	r7,acc_dat
stw		[r7],r0

// response
ldwi	r1,lab_str_msg_read
jalwr7	print
pushw	r1
// acc_adr
ldwi	r7,acc_adr
ldw		r1,[r7]
jalwr7	print_hex
ldwi	r7,acc_adr+2
ldw		r1,[r7]
jalwr7	print_hex
popw	r1
jalwr7	print
pushw	r1
// acc_dat
ldwi	r7,acc_dat
ldw		r1,[r7]
jalwr7	print_hex
popw	r1
jalwr7	print
bra		no_data
rd_notid:

// check "wr," command
ldwi	r1,lbuf
ldwi	r2,lab_str_cmd_wr
ldbiu	r5,3
jalwr7	strncmp
mov		r0,r0
bne		wr_notid
// ================================
// wr,<adr_hex6>,<dat_hex4>
ldwi	r1,lbuf
// <adr_hex6>
addi	r1,3
jalwr7	xtol
andi	r3,0xff
ldwi	r7,acc_adr
stw		[r7],r3
addi	r7,2
stw		[r7],r0
// ,
ldb		r0,[r1]
cmpi	r0,chr_cma
bne		err_syntx
// <dat_hex4>
addi	r1,1
jalwr7	xtoi
ldwi	r7,acc_dat
stw		[r7],r0

// write <dat_hex4> to <adr_hex6>
ldwi	r7,acc_dat
ldw		r1,[r7]
ldwi	r7,acc_adr
ldw		r0,[r7]
movtc	tr,r0
addi	r7,2
ldw		r7,[r7]
stwx	[r7],r1

// response
ldwi	r1,lab_str_msg_write
jalwr7	print
pushw	r1
// acc_adr
ldwi	r7,acc_adr
ldw		r1,[r7]
jalwr7	print_hex
ldwi	r7,acc_adr+2
ldw		r1,[r7]
jalwr7	print_hex
popw	r1
jalwr7	print
pushw	r1
// acc_dat
ldwi	r7,acc_dat
ldw		r1,[r7]
jalwr7	print_hex
popw	r1
jalwr7	print
bra		no_data
wr_notid:

// check "rda," command
ldwi	r1,lbuf
ldwi	r2,lab_str_cmd_rda
ldbiu	r5,4
jalwr7	strncmp
mov		r0,r0
bne		rda_notid
// ================================
// rda,<dat_hex4>
ldwi	r1,lbuf
// <dat_hex4>
addi	r1,4
jalwr7	xtoi
ldwi	r7,acc_dat
stw		[r7],r0

$(s)// ********************************
$(s)sim_reada:
$(s)// ********************************
// read all <dat_hex4>
ldwi	r7,acc_dat
ldw		r1,[r7]
ldbiu	r2,0
ldwi	r4,mch_end>>16
ldwi	r5,mch_end&0xffff
ldwi	r6,mch_top>>16
ldwi	r7,mch_top&0xffff
rda_loop:
movtc	tr,r6
ldwx	r0,[r7]
$(s)// ********************************
$(s)ldwi	r3,mch_inc
$(s)add		r7,r3
$(s)bra		pcnt+2
$(s)// ********************************
addi	r7,2
adc		r6,r2
cmp		r0,r1
beq		rda_pass
// ERROR:
mov		r1,r7
subi	r1,2
sbb		r6,r2
ldwi	r7,acc_adr
stw		[r7],r6
addi	r7,2
stw		[r7],r1
ldwi	r7,acc_dat
stw		[r7],r0
ldbiu	r0,1
bra		rda_break
rda_pass:
cmp		r7,r5
cmb		r6,r4
blo		rda_loop
ldbiu	r0,0
rda_break:
// check sytmctl[MLOE]
pushw	r0
ldwi	r7,sytmctl
ldw		r0,[r7]
andi	r0,sytm_mloe
beq		rda_no_mloe
// show elapsed time
ldwi	r1,lab_str_msg_ellaps
jalwr7	print
pushw	r1
ldwi	r7,sytmmilh
ldw		r1,[r7]
jalwr7	print_hex
ldwi	r7,sytmmill
ldw		r1,[r7]
jalwr7	print_hex
popw	r1
jalwr7	print
rda_no_mloe:
// clear sytmctl[MLOE]
ldwi	r7,sytmctl
ldw		r0,[r7]
andi	r0,~sytm_mloe
stw		[r7],r0
popw	r0

// response
mov		r0,r0
beq		rda_pass_msg
// ERROR:
ldwi	r1,lab_str_err_reada
jalwr7	print
pushw	r1
// acc_adr.high
ldwi	r7,acc_adr
ldw		r1,[r7]
jalwr7	print_hex
// acc_adr.low
ldwi	r7,acc_adr+2
ldw		r1,[r7]
jalwr7	print_hex
popw	r1
jalwr7	print
pushw	r1
// acc_dat
ldwi	r7,acc_dat
ldw		r1,[r7]
jalwr7	print_hex
popw	r1
jalwr7	print
$(s)// ********************************
$(s)ldbiu	r0,1
$(s)rtnw
$(s)// ********************************
bra		no_data

rda_pass_msg:
ldwi	r1,lab_str_msg_reada
jalwr7	print
pushw	r1
// acc_dat
ldwi	r7,acc_dat
ldw		r1,[r7]
jalwr7	print_hex
popw	r1
jalwr7	print
$(s)// ********************************
$(s)ldbiu	r0,0
$(s)rtnw
$(s)// ********************************
bra		no_data
rda_notid:

// check "wra," command
ldwi	r1,lbuf
ldwi	r2,lab_str_cmd_wra
ldbiu	r5,4
jalwr7	strncmp
mov		r0,r0
bne		wra_notid
// ================================
// wra,<dat_hex4>
ldwi	r1,lbuf
// <dat_hex4>
addi	r1,4
jalwr7	xtoi
ldwi	r7,acc_dat
stw		[r7],r0

$(s)// ********************************
$(s)sim_writea:
$(s)// ********************************
// write all <dat_hex4>
ldwi	r7,acc_dat
ldw		r1,[r7]
ldbiu	r2,0
ldwi	r4,mch_end>>16
ldwi	r5,mch_end&0xffff
ldwi	r6,mch_top>>16
ldwi	r7,mch_top&0xffff
wra_loop:
movtc	tr,r6
stwx	[r7],r1
$(s)// ********************************
$(s)ldwi	r3,mch_inc
$(s)add		r7,r3
$(s)bra		pcnt+2
$(s)// ********************************
addi	r7,2
adc		r6,r2
cmp		r7,r5
cmb		r6,r4
blo		wra_loop
// set sytmctl[MLOE]
ldwi	r7,sytmctl
ldw		r0,[r7]
andi	r0,~sytm_mloe
stw		[r7],r0
ori		r0,sytm_mloe
stw		[r7],r0

// response
ldwi	r1,lab_str_msg_writea
jalwr7	print
pushw	r1
// acc_dat
ldwi	r7,acc_dat
ldw		r1,[r7]
jalwr7	print_hex
popw	r1
jalwr7	print
$(s)// ********************************
$(s)jmpr7	sim_reada
$(s)// ********************************
bra		no_data
wra_notid:

// check "march" command
ldwi	r1,lbuf
ldwi	r2,lab_str_cmd_march
ldbiu	r5,5
jalwr7	strncmp
mov		r0,r0
bne		march_notid
// ================================
// march

$(s)// ********************************
$(s)sim_march:
$(s)// ********************************
// set sytmctl[MLOE]
ldwi	r7,sytmctl
ldw		r0,[r7]
andi	r0,~sytm_mloe
stw		[r7],r0
ori		r0,sytm_mloe
stw		[r7],r0
// try set NH=1
sesr	sreg_b_nh
movfc	r0,sr
lsfti	r0,-sreg_b_nh
andi	r0,1
// marching test
beq		mch_nh_else
// Nihonium
jalwr7	march_test_nh
clsr	sreg_b_nh
bra		mch_nh_endif
mch_nh_else:
// Moscovium
jalwr7	march_test
mch_nh_endif:

// response
mov		r0,r0
beq		march_ok
// ERROR:
ldwi	r1,lab_str_err_march
jalwr7	print
pushw	r1
// mch_err_adr.high
ldwi	r7,mch_err_adr
ldw		r1,[r7]
jalwr7	print_hex
// mch_err_adr.low
ldwi	r7,mch_err_adr+2
ldw		r1,[r7]
jalwr7	print_hex
popw	r1
jalwr7	print
pushw	r1
// mch_err_dat
ldwi	r7,mch_err_dat
ldw		r1,[r7]
jalwr7	print_hex
popw	r1
jalwr7	print
$(s)// ********************************
$(s)ldbiu	r0,1
$(s)rtnw
$(s)// ********************************
bra		no_data

march_ok:
ldwi	r1,lab_str_msg_march
jalwr7	print
pushw	r1
// elapsed time
ldwi	r7,sytmmilh
ldw		r1,[r7]
jalwr7	print_hex
ldwi	r7,sytmmill
ldw		r1,[r7]
jalwr7	print_hex
// clear sytmctl[MLOE]
ldwi	r7,sytmctl
ldw		r0,[r7]
andi	r0,~sytm_mloe
stw		[r7],r0
popw	r1
jalwr7	print
$(s)// ********************************
$(s)ldbiu	r0,0
$(s)rtnw
$(s)// ********************************
bra		no_data
march_notid:

// check "cche," command
ldwi	r1,lbuf
ldwi	r2,lab_str_cmd_cche
ldbiu	r5,5
jalwr7	strncmp
mov		r0,r0
bne		cche_notid
// ================================
// cche,<on1_off0>
ldwi	r1,lbuf
// <on1_off0>
addi	r1,5
jalwr7	xtoi
mov		r0,r0
beq		pcnt+2
ldbiu	r0,1
ldwi	r7,cche_sw
stw		[r7],r0

// cache control
ldwi	r7,cche_sw
ldw		r0,[r7]
mov		r0,r0
bne		cche_else
// cache off
ldwi	r7,cachctl
ldbiu	r0,0
stw		[r7],r0
// show hit counter
ldwi	r1,lab_str_msg_cche_shwcnt
jalwr7	print
pushw	r1
ldwi	r7,cachhith
ldw		r1,[r7]
jalwr7	print_hex
ldwi	r7,cachhitl
ldw		r1,[r7]
jalwr7	print_hex
popw	r1
jalwr7	print
pushw	r1
// show access counter
ldwi	r7,cachcnth
ldw		r1,[r7]
jalwr7	print_hex
ldwi	r7,cachcntl
ldw		r1,[r7]
jalwr7	print_hex
popw	r1
jalwr7	print
bra		cche_endif

cche_else:
// cache on
// clear tag array
ldwi	r7,cachtag
ldwi	r0,cchc_vclr
ldwi	r1,cchc_vclr+2*cchc_max_idx			// 2 way
stw		[r7],r0
addi	r0,1
cmp		r0,r1
blo		pcnt-8
// clear lfu counter
ldwi	r7,cachlfu
ldwi	r0,cchc_cclr
ldwi	r1,cchc_cclr+cchc_max_idx
stw		[r7],r0
addi	r0,1
cmp		r0,r1
blo		pcnt-8
// clear access/hit counter
ldbiu	r0,0
ldwi	r7,cachcnth
stw		[r7],r0
addi	r7,2
stw		[r7],r0
addi	r7,2
stw		[r7],r0
addi	r7,2
stw		[r7],r0
// cache enable
ldwi	r7,cachctl
ldbiu	r0,cchc_cche
stw		[r7],r0
ldw		r0,[r7]
andi	r0,cchc_cche
ldwi	r7,cche_sw
stw		[r7],r0
cche_endif:

// response
ldwi	r1,lab_str_msg_cche
jalwr7	print
pushw	r1
ldwi	r7,cche_sw
ldw		r1,[r7]
jalwr7	print_hex
popw	r1
jalwr7	print
bra		no_data
cche_notid:

// check "who" command
ldwi	r1,lbuf
ldwi	r2,lab_str_cmd_who
jalwr7	strcmp
mov		r0,r0
bne		who_notid
// ================================
// who
// response
ldwi	r1,lab_str_msg_who
jalwr7	print
bra		no_data
who_notid:

// check "help" command
ldwi	r1,lbuf
ldwi	r2,lab_str_cmd_help
jalwr7	strcmp
mov		r0,r0
bne		help_notid
// ================================
// help
// response
ldwi	r1,lab_str_msg_help
jalwr7	print_lst
bra		no_data
help_notid:

// ================================
// ignore empty line
ldwi	r1,lbuf
ldb		r0,[r1]
mov		r0,r0
beq		no_data
// ================================
// ERROR: unsupported command
ldwi	r1,lab_str_err_unspt
jalwr7	print
ldwi	r1,lbuf
jalwr7	print
ldwi	r1,lab_str_crlf
jalwr7	print
bra		no_data

// ERROR: syntax
err_syntx:
ldwi	r1,lab_str_err_syntx
jalwr7	print
bra		no_data

no_data:

// ================================
// end of loop
bra		loop


// ================================
// sdram marching test
//	return: r0 (error, or not)
// ================================
march_test:
// led: blue
ldwi	r7,porset
ldbiu	r0,led_builtin
stw		[r7],r0
ldwi	r7,porclr
ldbiu	r0,led_builtin_b
stw		[r7],r0
// initialize
//		r6:r7=addr
//		r4:r5=end of addr
//		r0=0x0000
//		r1=0xffff
//		r2=inc
//		r3=temporal data
ldwi	r4,mch_end>>16
ldwi	r5,mch_end&0xffff
ldbiu	r0,0
ldwi	r1,0xffff
ldwi	r2,mch_inc

// write all 0
// @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
ldcl	sr,sreg_bk_1
ldwi	r1,lab_dbg_mes
jalwr7	print
ldcl	sr,sreg_bk_0
bra		dbg_next
dbg_mes:
dats	"DBG: write all 0\r\n\0"
dbg_next:
// @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
ldwi	r6,mch_top>>16
ldwi	r7,mch_top&0xffff
mch_wr0_loop:
movtc	tr,r6
stwx	[r7],r0
add		r7,r2
adc		r6,r0
cmp		r7,r5
cmb		r6,r4
blo		mch_wr0_loop

// read 0, write 1
// @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
ldcl	sr,sreg_bk_1
ldwi	r1,lab_dbg_mes2
jalwr7	print
ldcl	sr,sreg_bk_0
bra		dbg_next2
dbg_mes2:
dats	"DBG: read 0, write 1\r\n\0"
dbg_next2:
// @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
ldwi	r6,mch_top>>16
ldwi	r7,mch_top&0xffff
mch_r0w1_loop:
movtc	tr,r6
ldwx	r3,[r7]
stwx	[r7],r1
add		r7,r2
adc		r6,r0
cmp		r3,r0
bne		mch_fail						// adr=r6:r7, dat=r3
cmp		r7,r5
cmb		r6,r4
blo		mch_r0w1_loop

// read 1, write 0
// @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
ldcl	sr,sreg_bk_1
ldwi	r1,lab_dbg_mes3
jalwr7	print
ldcl	sr,sreg_bk_0
bra		dbg_next3
dbg_mes3:
dats	"DBG: read 1, write 0\r\n\0"
dbg_next3:
// @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
ldwi	r6,mch_top>>16
ldwi	r7,mch_top&0xffff
mch_r1w0_loop:
movtc	tr,r6
ldwx	r3,[r7]
stwx	[r7],r0
add		r7,r2
adc		r6,r0
cmp		r3,r1
bne		mch_fail						// adr=r6:r7, dat=r3
cmp		r7,r5
cmb		r6,r4
blo		mch_r1w0_loop

// read all 0
// @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
ldcl	sr,sreg_bk_1
ldwi	r1,lab_dbg_mes4
jalwr7	print
ldcl	sr,sreg_bk_0
bra		dbg_next4
dbg_mes4:
dats	"DBG: read all 0\r\n\0"
dbg_next4:
// @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
ldwi	r6,mch_top>>16
ldwi	r7,mch_top&0xffff
mch_rd0_loop:
movtc	tr,r6
ldwx	r3,[r7]
add		r7,r2
adc		r6,r0
cmp		r3,r0
bne		mch_fail						// adr=r6:r7, dat=r3
cmp		r7,r5
cmb		r6,r4
blo		mch_rd0_loop

mch_pass:
// led: green
ldwi	r7,porset
ldbiu	r0,led_builtin
stw		[r7],r0
ldwi	r7,porclr
ldbiu	r0,led_builtin_g
stw		[r7],r0
ldbiu	r0,0
bra		mch_return

mch_fail:
// fail address and data
mov		r1,r7
subi	r1,2
sbb		r6,r0
ldwi	r7,mch_err_adr
stw		[r7],r6
addi	r7,2
stw		[r7],r1
ldwi	r7,mch_err_dat
stw		[r7],r3
// led: red
ldwi	r7,porset
ldbiu	r0,led_builtin
stw		[r7],r0
ldwi	r7,porclr
ldbiu	r0,led_builtin_r
stw		[r7],r0
ldbiu	r0,1
bra		mch_return

// return
mch_return:
rtnw


// ================================
// sdram marching test for Nihonium
//	return: r0 (error, or not)
// ================================
march_test_nh:
// @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
ldcl	sr,sreg_bk_1
ldwi	r1,lab_dbg_nh_mes0
jalwr7	print
ldcl	sr,sreg_bk_0
bra		dbg_nh_next0
dbg_nh_mes0:
dats	"DBG: Nihonium mode\r\n\0"
dbg_nh_next0:
// @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
// led: blue
ldwi	r7,porset
ldbiu	r0,led_builtin
stw		[r7],r0
ldwi	r7,porclr
ldbiu	r0,led_builtin_b
stw		[r7],r0
// initialize
//		r7=addr
//		r5=end of addr
//		r0=0x0000
//		r1=0xffff
//		r2=inc
//		r3=temporal data
ldli	r5,mch_end
ldbiu	r0,0
ldwi	r1,0xffff
ldwi	r2,mch_inc

// write all 0
// @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
ldcl	sr,sreg_bk_1
ldwi	r1,lab_dbg_nh_mes
jalwr7	print
ldcl	sr,sreg_bk_0
bra		dbg_nh_next
dbg_nh_mes:
dats	"DBG: write all 0\r\n\0"
dbg_nh_next:
// @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
ldli	r7,mch_top
mch_nh_wr0_loop:
stw		[r7],r0
add		r7,r2
cmp		r7,r5
blo		mch_nh_wr0_loop

// read 0, write 1
// @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
ldcl	sr,sreg_bk_1
ldwi	r1,lab_dbg_nh_mes2
jalwr7	print
ldcl	sr,sreg_bk_0
bra		dbg_nh_next2
dbg_nh_mes2:
dats	"DBG: read 0, write 1\r\n\0"
dbg_nh_next2:
// @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
ldli	r7,mch_top
mch_nh_r0w1_loop:
ldw		r3,[r7]
stw		[r7],r1
add		r7,r2
cmp		r3,r0
bne		mch_nh_fail						// adr=r7, dat=r3
cmp		r7,r5
blo		mch_nh_r0w1_loop

// read 1, write 0
// @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
ldcl	sr,sreg_bk_1
ldwi	r1,lab_dbg_nh_mes3
jalwr7	print
ldcl	sr,sreg_bk_0
bra		dbg_nh_next3
dbg_nh_mes3:
dats	"DBG: read 1, write 0\r\n\0"
dbg_nh_next3:
// @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
ldli	r7,mch_top
mch_nh_r1w0_loop:
ldw		r3,[r7]
stw		[r7],r0
add		r7,r2
cmp		r3,r1
bne		mch_nh_fail						// adr=r7, dat=r3
cmp		r7,r5
blo		mch_nh_r1w0_loop

// read all 0
// @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
ldcl	sr,sreg_bk_1
ldwi	r1,lab_dbg_nh_mes4
jalwr7	print
ldcl	sr,sreg_bk_0
bra		dbg_nh_next4
dbg_nh_mes4:
dats	"DBG: read all 0\r\n\0"
dbg_nh_next4:
// @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
ldli	r7,mch_top
mch_nh_rd0_loop:
ldw		r3,[r7]
add		r7,r2
cmp		r3,r0
bne		mch_nh_fail						// adr=r7, dat=r3
cmp		r7,r5
blo		mch_nh_rd0_loop

mch_nh_pass:
// led: green
ldwi	r7,porset
ldbiu	r0,led_builtin
stw		[r7],r0
ldwi	r7,porclr
ldbiu	r0,led_builtin_g
stw		[r7],r0
ldbiu	r0,0
bra		mch_nh_return

mch_nh_fail:
// fail address and data
subi	r7,2
ldwi	r6,mch_err_adr
stl		[r6],r7
ldwi	r6,mch_err_dat
stw		[r6],r3
// led: red
ldwi	r7,porset
ldbiu	r0,led_builtin
stw		[r7],r0
ldwi	r7,porclr
ldbiu	r0,led_builtin_r
stw		[r7],r0
ldbiu	r0,1
bra		mch_nh_return

// return
mch_nh_return:
rtnw


// ================================
// get line from uart ; disturbed r0,r5~r7
// ================================
get_line:
ldwi	r7,uartrdat
ldwi	r6,uartctl
ldwi	r5,lbuf
gl_loop:
// polling until RAVL=1
ldw		r0,[r6]
andi	r0,uart_ravl
beq		gl_loop
// get byte
ldw		r0,[r7]
stb		[r5],r0
addi	r5,1
// LF code check
cmpi	r0,chr_lf
beq		gl_got
// size check
ldwi	r0,lbuf+max_lbuf-1
cmp		r5,r0
blo		gl_loop
// got line
gl_got:
// string terminate
ldbiu	r0,0
subi	r5,1
stb		[r5],r0
// check CR code
subi	r5,1
ldb		r0,[r5]
cmpi	r0,chr_cr
bne		gl_notcr
ldbiu	r0,0
stb		[r5],r0
gl_notcr:
rtnw

// ================================
// print r1 ; disturbed r0~r2,r6,r7
// ================================
print:
ldwi	r7,uarttdat
ldwi	r6,uartctl
pr_loop:
// get 1 byte
ldb		r2,[r1]
addi	r1,1
mov		r2,r2
beq		pr_finish
$(s)// ********************************
$(s)ldwi	r7,princhr
$(s)stw		[r7],r2
$(s)bra		pr_loop
$(s)// ********************************
// polling uartctl.TFUL=0
pr_poll:
ldw		r0,[r6]
andi	r0,uart_tful
bne		pr_poll
// send data
stw		[r7],r2
bra		pr_loop
pr_finish:
rtnw

// ================================
// print_lst r1 ; disturbed r0~r2,r6,r7
// ================================
print_lst:
jalwr7	print
ldb		r0,[r1]
mov		r0,r0
bne		print_lst
rtnw

// ================================
// print_hex r1 ; disturbed r0~r7
//		print r1 as 4 digits hexadecimal number
// ================================
print_hex:
ldbiu	r3,4
$(s)// ********************************
$(s)ldwi	r7,princtl
$(s)ldbiu	r0,prin_nld
$(s)stw		[r7],r0
$(s)ldwi	r7,prinhex
$(s)cmpi	r3,4
$(s)beq		pcnt+6
$(s)lsfti	r1,-8
$(s)stb		[r7],r1
$(s)bra		pcnt+2
$(s)stw		[r7],r1
$(s)rtnw
$(s)// ********************************
ldwi	r7,uarttdat
ldwi	r6,uartctl
ldwi	r5,lab_ph_hexdig
ph_loop:
// print nibble
mov		r0,r1
mov		r4,r5
lsfti	r0,-12
andi	r0,0x0f
add		r4,r0
ldb		r2,[r4]
// polling uartctl.TFUL=0
ph_poll:
ldw		r0,[r6]
andi	r0,uart_tful
bne		ph_poll
// send data
stw		[r7],r2
// loop
lsfti	r1,4
subi	r3,1
bne		ph_loop
rtnw

ph_hexdig:
dats	"0123456789abcdef"

// ================================
// print_chr r1 ; disturbed r0,r7
// ================================
print_chr:
$(s)// ********************************
$(s)ldwi	r7,princhr
$(s)stw		[r7],r1
$(s)rtnw
$(s)// ********************************
// polling uartctl.TFUL=0
ldwi	r7,uartctl
pc_poll:
ldw		r0,[r7]
andi	r0,uart_tful
bne		pc_poll
// send data
ldwi	r7,uarttdat
stw		[r7],r1
rtnw

// ================================
// string compare: r0=strcmp (r1,r2) ; disturbed r1~r4
// ================================
strcmp:
ldb		r3,[r1]
addi	r1,1
ldb		r4,[r2]
addi	r2,1
mov		r0,r3
sub		r0,r4
bne		sc_finish
// check nil code
mov		r3,r3
beq		sc_finish
mov		r4,r4
bne		strcmp
sc_finish:
rtnw

// ================================
// string n compare: r0=strncmp (r1,r2,r5) ; disturbed r1~r5
// ================================
strncmp:
ldb		r3,[r1]
addi	r1,1
ldb		r4,[r2]
addi	r2,1
mov		r0,r3
sub		r0,r4
bne		snc_finish
// check n character
subi	r5,1
beq		snc_finish
// check nil code
mov		r3,r3
beq		snc_finish
mov		r4,r4
bne		strncmp
snc_finish:
rtnw

// ================================
// hexadecimal to integer: r0=xtoi (r1) ; disturbed r1,r2
// ================================
xtoi:
ldbiu	r0,0
// r2=[r1]-'0'
ldb		r2,[r1]
subi	r2,0a0
blo		x2i_finish						// [r1]<'0'
cmpi	r2,10
blo		x2i_next						// [r1]<='9'
subi	r2,(0aA-0x20)-0a0-10
blo		x2i_finish						// [r1]<'A'
cmpi	r2,16
blo		x2i_next						// [r1]<='F'
subi	r2,0aa-(0aA-0x20)
blo		x2i_finish						// [r1]<'a'
cmpi	r2,16
bhs		x2i_finish						// [r1]>'f'
x2i_next:
// r0=16*r0+r2
lsfti	r0,4
add		r0,r2
// loop
addi	r1,1
bra		xtoi+2
x2i_finish:
rtnw

// ================================
// hexadecimal to long: r3:r0=xtol (r1) ; disturbed r1,r2,r4
// ================================
xtol:
ldbiu	r0,0
ldbiu	r3,0
// r2=[r1]-'0'
ldb		r2,[r1]
subi	r2,0a0
blo		x2l_finish						// [r1]<'0'
cmpi	r2,10
blo		x2l_next						// [r1]<='9'
subi	r2,(0aA-0x20)-0a0-10
blo		x2l_finish						// [r1]<'A'
cmpi	r2,16
blo		x2l_next						// [r1]<='F'
subi	r2,0aa-(0aA-0x20)
blo		x2l_finish						// [r1]<'a'
cmpi	r2,16
bhs		x2l_finish						// [r1]>'f'
x2l_next:
// r3:r0=16*r0+r2
mov		r4,r0
lsfti	r4,-12
lsfti	r3,4
add		r3,r4
lsfti	r0,4
add		r0,r2
// loop
addi	r1,1
bra		xtol+4
x2l_finish:
rtnw

// ================================
// c string data
// ================================
str_msg_who:
dats	"OK: $(prog_name) ver.$(prog_vers)\r\n\0"
str_msg_rdy:
dats	"RDY\r\n\0"
str_msg_help:
dats	"OK+ rd,<adr_hex6>\r\n"
dats	"OK+ wr,<adr_hex6>,<dat_hex4>\r\n"
dats	"OK+ rda,<dat_hex4>\r\n"
dats	"OK+ wra,<dat_hex4>\r\n"
dats	"OK+ march\r\n"
dats	"OK+ cche,<on1_off0>\r\n"
dats	"OK+ who\r\n"
dats	"OK: help\r\n\0\0"
str_msg_read:
dats	"OK: read[0x\0]=0x\0\r\n\0"
str_msg_write:
dats	"OK: write[0x\0]=0x\0\r\n\0"
str_msg_reada:
dats	"OK: read all=0x\0\r\n\0"
str_msg_ellaps:
dats	"OK+ elapsed time=0x\0[ms]\r\n\0"
str_msg_writea:
dats	"OK: write all=0x\0\r\n\0"
str_msg_march:
dats	"OK: marching finished: 0x\0[ms]\r\n\0"
str_msg_cche_shwcnt:
dats	"OK+ hit/acc cnt=0x\0/0x\0\r\n\0"
str_msg_cche:
dats	"OK: cache on1/off0=\0\r\n\0"
str_err_unspt:
dats	"ERR: unsupported command: \0"
str_err_syntx:
dats	"ERR: syntax\r\n\0"
str_err_nosd:
dats	"ERR: no SDRAM found.\r\n\0"
str_err_reada:
dats	"ERR: read all terminated [0x\0] 0x\0\r\n\0"
str_err_march:
dats	"ERR: marching terminated [0x\0] 0x\0\r\n\0"
str_cmd_rd:
dats	"rd,\0"
str_cmd_wr:
dats	"wr,\0"
str_cmd_rda:
dats	"rda,\0"
str_cmd_wra:
dats	"wra,\0"
str_cmd_march:
dats	"march\0"
str_cmd_cche:
dats	"cche,\0"
str_cmd_who:
dats	"who\0"
str_cmd_help:
dats	"help\0"
str_crlf:
dats	"\r\n\0"

