// ================================
// MCOC115 Combinational Test
//		isqrt; square root function for uint16
//		(c) 2022	1YEN Toru
//
//
//		2022/10/15	ver.1.00
//
// ================================
asm		"mcoc_irom.mem"
incl	"mcoc115.incl"
# ================================

#// set NH=1
#sesr	sreg_b_nh

// 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

// inhibit simulation time out
ldwi	r7,simctrl
ldbiu	r0,simc_noto
stw		[r7],r0

// print unit setting
ldwi	r7,princtl
ldbiu	r0,prin_nld
stw		[r7],r0

// isqrt test
ldwi	r5,lab_isqrt_tab
tst_loop:
ldw		r1,[r5]
mov		r1,r1
beq		tstpass
jalwr7	isqrt
pushw	r0
// print
ldwi	r6,prindec
ldwi	r1,lab_str_isqrt
jalwr7	print
ldw		r0,[r5]
addi	r5,2
stw		[r6],r0
jalwr7	print
popw	r2
stw		[r6],r2
jalwr7	print
ldw		r3,[r5]
addi	r5,2
stw		[r6],r3
jalwr7	print
ldbiu	r0,0ao
cmp		r2,r3
beq		pcnt+2
ldbiu	r0,0ax
stw		[r7],r0
jalwr7	print
// check
cmp		r2,r3
bne		tstfail
// end of loop
bra		tst_loop

str_isqrt:
dats	"isqrt (\0)=\0 [\0]\0\n\0"

// print ; disturbed r0,r1,r7
print:
ldwi	r7,princhr
prn_loop:
ldb		r0,[r1]
addi	r1,1
mov		r0,r0
beq		prn_break
stw		[r7],r0
bra		prn_loop
prn_break:
rtnw


// ================================
// r0=isqrt (r1) ; disturbed r2~r4,Sr[DR]
// ================================
isqrt:
#	procedure	isqrt	x
#	{
#		// int (sqrt (x))
clsr	sreg_b_dr
#		var		ll=0;
ldbiu	r2,0
#		var		rr=x/2;
mov		r3,r1
#lsfti	r3,-1
lsri	r3,1
#		var		mm;
#		var		y;
#		if (x<=3)
#		{
#			isqrt=( x!=0 );
mov		r0,r1
beq		pcnt+2
ldbiu	r0,1
#			return;
#		}
cmpi	r1,3+1
blo		isqr_return
#		while (ll<=rr)
isqr_while:
cmp		r3,r2
blo		isqr_break
#		{
#			mm=int ((rr + ll)/2);
mov		r0,r2
add		r0,r3
#lsfti	r0,-1
lsri	r0,1
#			y=int (x/mm);
mov		r4,r1
divu	r4,r0
#			if (y<=mm)
cmp		r0,r4
blo		isqr_ymm_else
#			{
#				rr=mm - ( rr=mm );
cmp		r0,r3
bne		pcnt+6
mov		r3,r0
subi	r3,1
bra		pcnt+2
mov		r3,r0
bra		isqr_ymm_endif
#			}
#			else
#			{
isqr_ymm_else:
#				ll=mm + ( ll=mm );
cmp		r0,r2
bne		pcnt+6
mov		r2,r0
addi	r2,1
bra		pcnt+2
mov		r2,r0
#			}
isqr_ymm_endif:
bra		isqr_while
#		}
isqr_break:
#		isqrt=mm;
#		minv	isqrt=y;
cmp		r4,r0
bhs		pcnt+2
mov		r0,r4
#	}
isqr_return:
rtnw


// ================================
// isqrt table
//		datw x, int (sqrt (x))
isqrt_tab:
datw	1,1
datw	2,1
datw	3,1
datw	4,2
datw	5,2
datw	6,2
datw	7,2
datw	8,2
datw	9,3
datw	16,4
datw	30654,175
datw	65535,255
// random load test
datw	0x00F1,0x000F
datw	0x0107,0x0010
datw	0x0126,0x0011
datw	0x0141,0x0011
datw	0x015D,0x0012
datw	0x017F,0x0013
datw	0x01BD,0x0015
datw	0x01BE,0x0015
datw	0x01D3,0x0015
datw	0x01D4,0x0015
datw	0x0213,0x0017
datw	0x0236,0x0017
datw	0x028F,0x0019
datw	0x0314,0x001C
datw	0x031C,0x001C
datw	0x0338,0x001C
datw	0x0342,0x001C
datw	0x035C,0x001D
datw	0x03A9,0x001E
datw	0x040C,0x0020
datw	0x0428,0x0020
datw	0x04B1,0x0022
datw	0x04CE,0x0023
datw	0x057A,0x0025
datw	0x05E7,0x0026
datw	0x0674,0x0028
datw	0x0689,0x0028
datw	0x06A8,0x0029
datw	0x06B3,0x0029
datw	0x06B8,0x0029
datw	0x0713,0x002A
datw	0x0771,0x002B
datw	0x07B4,0x002C
datw	0x07D5,0x002C
datw	0x07D8,0x002C
datw	0x07E6,0x002C
datw	0x0802,0x002D
datw	0x095D,0x0030
datw	0x09A5,0x0031
datw	0x09CC,0x0032
datw	0x09E4,0x0032
datw	0x09F7,0x0032
datw	0x0A1B,0x0032
datw	0x0A2B,0x0033
datw	0x0A52,0x0033
datw	0x0AA4,0x0034
datw	0x0AEF,0x0034
datw	0x0B4B,0x0035
datw	0x0C27,0x0037
datw	0x0C69,0x0038
datw	0x0C70,0x0038
datw	0x0CFC,0x0039
datw	0x0D0A,0x0039
datw	0x0D1B,0x0039
datw	0x0D5B,0x003A
datw	0x0D7F,0x003A
datw	0x0D84,0x003A
datw	0x0DB5,0x003B
datw	0x0E0C,0x003B
datw	0x0EC9,0x003D
datw	0x0ED3,0x003D
datw	0x0F25,0x003E
datw	0x0F47,0x003E
datw	0x0FC4,0x003F
datw	0x10AF,0x0041
datw	0x15B8,0x004A
datw	0x18E1,0x004F
datw	0x19D1,0x0051
datw	0x1E61,0x0058
datw	0x29E2,0x0067
datw	0x2EB7,0x006D
datw	0x2F97,0x006E
datw	0x3438,0x0073
datw	0x3750,0x0076
datw	0x3A61,0x007A
datw	0x3B5A,0x007B
datw	0x4038,0x0080
datw	0x407A,0x0080
datw	0x478E,0x0087
datw	0x4AE7,0x008A
datw	0x4F94,0x008E
datw	0x5538,0x0093
datw	0x57BE,0x0095
datw	0x57E7,0x0096
datw	0x609A,0x009D
datw	0x60B3,0x009D
datw	0x6161,0x009D
datw	0x63FC,0x009F
datw	0x644D,0x00A0
datw	0x653F,0x00A0
datw	0x69BB,0x00A4
datw	0x6AEF,0x00A5
datw	0x6CEE,0x00A6
datw	0x725B,0x00AB
datw	0x7479,0x00AC
datw	0x7F00,0x00B4
datw	0x847D,0x00B8
datw	0x8481,0x00B8
datw	0x87E6,0x00BA
datw	0x8942,0x00BB
datw	0x8B81,0x00BC
datw	0x9417,0x00C2
datw	0x954A,0x00C3
datw	0x9AB3,0x00C7
datw	0x9BB3,0x00C7
datw	0x9EA7,0x00C9
datw	0xA6EC,0x00CE
datw	0xA7A9,0x00CF
datw	0xADC1,0x00D2
datw	0xAE5F,0x00D3
datw	0xAEBE,0x00D3
datw	0xB813,0x00D9
datw	0xB868,0x00D9
datw	0xBB4A,0x00DA
datw	0xCA7E,0x00E3
datw	0xCD12,0x00E5
datw	0xD3C7,0x00E8
datw	0xD532,0x00E9
datw	0xDD4B,0x00EE
datw	0xE335,0x00F1
datw	0xE64C,0x00F2
datw	0xED8D,0x00F6
datw	0xEE76,0x00F7
datw	0xEF1F,0x00F7
datw	0xEF43,0x00F7
datw	0xF186,0x00F8
datw	0xFAA9,0x00FD
// end mark
datw	0,0


// ================================
tstpass:
ldwi	r0,simpass						// pass: LED=blue
bra		tstfnsh
tstfail:
ldwi	r0,simfail						// fail: LED=red
tstfnsh:
ldwi	r7,simfnsh
stw		[r7],r0
bra		pcnt-2
nop
// ================================

