#
# Blitz-64 ISA Program to exercise and test the MMU
#
# Program Name: PageTester.s
#
# Harry Porter III - 6 March 2023      --  Cannibalizing ISAValidator code
# Harry Porter III - 11 December 2023  --  updates to eliminate Kernel Exception

#
# This program is intended to be loaded and executed by a Blitz-64 processor core, either
# emulated or physical. The purpose is to test and exercise the Memory Management Unit (MMU)
# reasonably thoroughly.
#
# This program may be assembled into HEX format (for downloading to hardware) like this:
#
#     % asm PageTester.s -o PageTester.o -l > PageTester.listing
#     % link PageTester.o -o PageTester.exe -k
#     % hexify PageTester.exe -hex -silent > PageTester.hex
#
# It may also be assembled and executed with the emulator like this:
#
#     % asm PageTester.s -o PageTester.o -l > PageTester.listing
#     % link PageTester.o -o PageTester.exe -k
#     % blitz PageTester.hex -g -nowarn -nodebug
#
# This program uses the following memory:
#      LOWEST ADDRESS USED:     0x 0_0000_0008
#      HIGHET ADDRESS USED:     0x 0_0000_2a7f  (10871 bytes)
#      MAX LENGTH OF CODE:      0x 0_0000_FFFF  (about 64 KiBytes)
# This program requires the presence of RAM memory.
#
# This program does no input; result are printed using the CONTROL SERIAL_STAT/SERIAL_SEND
# instructions.
#
# This program should be started in kernel mode.
#



	.begin		startaddr = 0x000000008,kernel,gp=undefined
	.sourcefile	"PageTester", "hand-coded assembly"
	.function	"NamelessFunction",line=0,framesize=0


TRAP_CAUSE_ARITHMETIC:			.equ	0x2000		# 8192  Arithmetic Exception
TRAP_CAUSE_UNALIGNED_LOAD_STORE:	.equ	0x2008		# 8200  Unaligned LOAD/STORE Exception
TRAP_CAUSE_NULL_ADDRESS:		.equ	0x2010		# 8208  Null Address Exception
TRAP_CAUSE_ILLEGAL_INSTRUCTION:		.equ	0x2018		# 8216  Illegal Instruction, privilege violation

TRAP_CAUSE_PAGE_PRIVILEGE:       	.equ	0x2020   	# 8224  Page Privilege Exception - attempt to access kernel space
TRAP_CAUSE_PAGE_TABLE:            	.equ	0x2028   	# 8232  Page Table Exception - bad csr_pgtable
TRAP_CAUSE_PAGE_INVALID:            	.equ	0x2030   	# 8240  Page Invalid Exception - either index page or PTE
TRAP_CAUSE_PAGE_WRITE:              	.equ	0x2038   	# 8248  Page Write Exception
TRAP_CAUSE_PAGE_FETCH:              	.equ	0x2040   	# 8256  Page Fetch Exception
TRAP_CAUSE_PAGE_COPY_ON_WRITE:      	.equ	0x2048   	# 8264  Page Copy-On-Write Exception
TRAP_CAUSE_PAGE_FIRST_DIRTY:        	.equ	0x2050   	# 8272  Page First Dirty Exception

TRAP_CAUSE_DEBUG:			.equ	0x2058		# 8280  Debug Exception
TRAP_CAUSE_BREAKPOINT:			.equ	0x2060		# 8288  Breakpoint Exception
TRAP_CAUSE_SINGLESTEP:			.equ	0x2068		# 8296  Singlestep Exception
TRAP_CAUSE_EMULATED_INSTRUCTION:	.equ	0x2070		# 8304  Emulated Instruction Exception
TRAP_CAUSE_HARDWARE_FAULT:		.equ	0x2078		# 8312  Hardware Fault Exception
TRAP_CAUSE_BAD_ARRAY_INDEX:		.equ	0x2080		# 8320  Bad Array Index Exception

ADDRESS_ZERO:		.equ	0
ADDRESS_ONE:		.equ	1  

DIGITAL_READ:		.equ	0	# controlu   XXX,r0,DIGITAL_READ
DIGITAL_WRITE:		.equ	1	# controlu   r0,XXX,DIGITAL_WRITE
HALT:			.equ	2	# controlu   r0,r0,HALT
SERIAL_STAT:		.equ	3	# controlu   XXX,r0,SERIAL_STAT
SERIAL_RECV:		.equ	4	# controlu   XXX,r0,SERIAL_RECV
SERIAL_SEND:		.equ	5	# controlu   r0,XXX,SERIAL_SEND
ENABLE_KERNEL:		.equ	6	# controlu   XXX,r0,ENABLE_KERNEL  # grab csr_status; then set mode
SET_STATUS:		.equ	7	# controlu   r0,XXX,SET_STATUS     # set csr_status from reg.


############################################################################
###
###  Entry Point
###
############################################################################

_entry:
	.export	_entry

	movi		r1,0x0000_0000_0000_0001	# Singlestep = 0, Interrupts=0, Kernel=1
	csrwrite	csr_status,r1

	movi		sp,StackRegionX			# Initialize the stack
	movi		r1,0x0000

	movi		r1,0x7fffffffffffffff		# Make sure we don't get a timer interrupt next
	csrwrite	csr_timer,r1

	controlu	r0,r0,DIGITAL_WRITE
	movi		sp,StackRegionX	

	movi		r1,WelcomeMessage
	call		PrintString

	movi		r1,EndOfCode			# Make sure that we have no more than 4 pages of code
	bgei		r1,0x0000_0000_0001_0000,FAILURE

	jump		BEGIN_TESTS

############################################################################
###
###   SUCCESS  --  IF WE REACH HERE, WE HAVE PASSED ALL TESTS!
###
############################################################################

SUCCESS:
	movi		r1,0x1234
	controlu	r0,r1,DIGITAL_WRITE
	movi		r1,SuccessMessage
	call		PrintString
	controlu	r0,r0,HALT

############################################################################
###
###  FAILURE  --  Come here after any test fails.
###
###  Assumes SP is valid.
###
############################################################################

FAILURE:
	call		PrintRegs	# Print regs before they lose old values	
	call		PrintCSRs
#	movi		r1,0xEEEE
#	controlu	r0,r1,DIGITAL_WRITE
	movi		r1,FailureMessage
	call		PrintString

	controlu	r0,r0,HALT

WelcomeMessage:	.string		"\n**********  PageTester Running  **********\n\n\0"
SuccessMessage:	.string		"\n**********  SUCCESS!  **********\n\0"
FailureMessage:	.string		"\n**********  THIS TEST HAS FAILED!  **********\n\n\0"
	.align	4

############################################################################
##
##  STACK AREA
##
############################################################################
			.align		8	# Doubleword alignment is required for the stack 
StackRegion:		.skip		8*100
StackRegionX:





BEGIN_TESTS:



############################################################################
############################################################################
###
### Test B.EQ, B.NE, B.LT, and B.LE
###
### Each of these synthetic Bxx instructions will assemble as a
### single B.xx instruction since the targets are always quite close. 
###
############################################################################
############################################################################

	movi		r1,TestMessage_1
	call		PrintString
	jump		TestAM_1
TestMessage_1:
	.string		"Test_1: B.EQ, B.NE, B.LT, and B.LE\n\0"
	.align		4
TestAM_1:


	movi	r1,0x0000000000000001
	movi	r2,0x0000000000000000
	beq	r1,r2,FAILURE
	bne	r1,r2,OK_39_2
	jump	FAILURE
OK_39_2:

	movi	r1,0x0000000000000000
	movi	r2,0x0000000000000001
	beq	r1,r2,FAILURE
	bne	r1,r2,OK_39_3
	jump	FAILURE
OK_39_3:

	movi	r1,0x0000000000000001
	movi	r2,0x0000000000000001
	bne	r1,r2,FAILURE
	beq	r1,r2,OK_39_4
	jump	FAILURE
OK_39_4:

	movi	r1,0x1000000000000000
	movi	r2,0x0000000000000000
	beq	r1,r2,FAILURE
	bne	r1,r2,OK_39_5
	jump	FAILURE
OK_39_5:

	movi	r1,0x0000000000000000
	movi	r2,0x1000000000000000
	beq	r1,r2,FAILURE
	bne	r1,r2,OK_39_6
	jump	FAILURE
OK_39_6:

	movi	r1,0x1000000000000000
	movi	r2,0x1000000000000000
	bne	r1,r2,FAILURE
	beq	r1,r2,OK_39_7
	jump	FAILURE
OK_39_7:

	movi	r1,0x0000004000000000
	movi	r2,0x0000000000000000
	beq	r1,r2,FAILURE
	bne	r1,r2,OK_39_8
	jump	FAILURE
OK_39_8:

	movi	r1,0x0000000000000000
	movi	r2,0x0000000000400000
	beq	r1,r2,FAILURE
	bne	r1,r2,OK_39_9
	jump	FAILURE
OK_39_9:



	movi	r1,0x123
	movi	r2,0x456
	blt	r1,r2,OK_40_1
	jump	FAILURE
OK_40_1:
	ble	r1,r2,OK_40_2
	jump	FAILURE
OK_40_2:


	movi	r1,0x8000000000000000
	movi	r2,0x8000000000000001
	blt	r1,r2,OK_40_3
	jump	FAILURE
OK_40_3:
	ble	r1,r2,OK_40_4
	jump	FAILURE
OK_40_4:

	movi	r1,0x7ffffffffffffffe
	movi	r2,0x7fffffffffffffff
	blt	r1,r2,OK_40_5
	jump	FAILURE
OK_40_5:
	ble	r1,r2,OK_40_6
	jump	FAILURE
OK_40_6:

	movi	r2,1
	blt	r0,r2,OK_40_7
	jump	FAILURE
OK_40_7:
	ble	r0,r2,OK_40_8
	jump	FAILURE
OK_40_8:

	movi	r1,-0x456
	movi	r2,-0x123
	blt	r1,r2,OK_40_9
	jump	FAILURE
OK_40_9:
	ble	r1,r2,OK_40_10
	jump	FAILURE
OK_40_10:


	movi	r1,0x124
	movi	r2,0x123
	blt	r1,r2,FAILURE
	ble	r1,r2,FAILURE

	movi	r1,0x8000000000000001
	movi	r2,0x8000000000000000
	blt	r1,r2,FAILURE
	ble	r1,r2,FAILURE

	movi	r1,0x7fffffffffffffff
	movi	r2,0x7ffffffffffffffe
	blt	r1,r2,FAILURE
	ble	r1,r2,FAILURE

	movi	r1,0x7fffffffffffffff
	movi	r2,0x8000000000000000
	blt	r1,r2,FAILURE
	ble	r1,r2,FAILURE

	movi	r1,0
	movi	r2,-1
	blt	r1,r2,FAILURE
	ble	r1,r2,FAILURE

	movi	r1,1
	movi	r2,0
	blt	r1,r2,FAILURE
	ble	r1,r2,FAILURE

	movi	r1,1
	blt	r1,r0,FAILURE
	ble	r1,r0,FAILURE

#
	movi	r1,123
	movi	r2,123
	blt	r1,r2,FAILURE
	ble	r1,r2,OK_40_11
	jump	FAILURE
OK_40_11:

	movi	r1,0x8000000000000000
	movi	r2,0x8000000000000000
	blt	r1,r2,FAILURE
	ble	r1,r2,OK_40_13
	jump	FAILURE
OK_40_13:

	movi	r1,0x7fffffffffffffff
	movi	r2,0x7fffffffffffffff
	blt	r1,r2,FAILURE
	ble	r1,r2,OK_40_14
	jump	FAILURE
OK_40_14:

	movi	r1,0
	blt	r1,r0,FAILURE
	ble	r1,r0,OK_40_15
	jump	FAILURE
OK_40_15:

	movi	r2,0
	blt	r0,r2,FAILURE
	ble	r0,r2,OK_40_16
	jump	FAILURE
OK_40_16:


############################################################################
############################################################################
###
###  Test LOAD.B, LOAD.H, LOAD.W, and LOAD.D (properly aligned, no exceptions)
###
############################################################################
############################################################################

	movi		r1,TestMessage_2
	call		PrintString
	jump		TestAM_2
TestMessage_2:
	.string		"Test_2: LOAD.B, LOAD.H, LOAD.W, and LOAD.D (properly aligned, no exceptions)\n\0"
	.align		4
TestAM_2:


	jump	Test_50_Continue

	.align	8
addr0:	.byte	0x12
addr1:	.byte	0x34
addr2:	.byte	0x56
addr3:	.byte	0x78
addr4:	.byte	0xffffffffffffff90
addr5:	.byte	0xffffffffffffffab
addr6:	.byte	0xffffffffffffffcd
addr7:	.byte	0xffffffffffffffef
addr8:

Test_50_Continue:

# Check that the assumed alignment of the memory array is met...
	movi	r1,addr0
	andi	r1,r1,0x7
	bnez	r1,FAILURE

	movi	r1,addr0
	movi	r2,addr8

	load.b	r3,3(r1)
	bnei	r3,0x0000000000000078,FAILURE

	load.b	r3,6(r1)
	bnei	r3,0xffffffffffffffcd,FAILURE

	load.b	r3,-8(r2)
	bnei	r3,0x0000000000000012,FAILURE
#
	load.h	r3,2(r1)
	bnei	r3,0x0000000000005678,FAILURE

	load.h	r3,6(r1)
	bnei	r3,0xffffffffffffcdef,FAILURE

	load.h	r3,-8(r2)
	bnei	r3,0x0000000000001234,FAILURE
#
	load.w	r3,0(r1)
	bnei	r3,0x0000000012345678,FAILURE

	load.w	r3,4(r1)
	bnei	r3,0xffffffff90abcdef,FAILURE

	load.w	r3,-8(r2)
	bnei	r3,0x0000000012345678,FAILURE
#
	load.d	r3,0(r1)
	bnei	r3,0x1234567890abcdef,FAILURE

	load.d	r3,-8(r2)
	bnei	r3,0x1234567890abcdef,FAILURE


############################################################################
############################################################################
###
###  Test STORE.B, STORE.H, STORE.W, and STORE.D (properly aligned, no exceptions)
###
############################################################################
############################################################################

	movi		r1,TestMessage_3
	call		PrintString
	jump		TestAM_3
TestMessage_3:
	.string		"Test_3: STORE.B, STORE.H, STORE.W, and STORE.D (properly aligned, no exceptions)\n\0"
	.align		4
TestAM_3:

	jump	Test_51_Continue

# A memory array in which we will store values

		.align	8
addr_0:		.byte	-1
addr_1:		.byte	-1	# 0x68  will go here
addr_2:		.byte	-1
addr_3:		.byte	-1
addr_4:		.byte	-1	# 0x65666868  will go here
addr_5:		.byte	-1	#
addr_6:		.byte	-1	#
addr_7:		.byte	-1	#
addr_8:		.byte	-1
addr_9:		.byte	-1
addr_a:		.byte	-1	# 0x6768  will go here
addr_b:		.byte	-1	#
addr_c:		.byte	-1
addr_d:		.byte	-1
addr_e:		.byte	-1
addr_f:		.byte	-1
addr_10:	.byte	-1	# 0x6162636465666768  will go here
addr_11:	.byte	-1	#
addr_12:	.byte	-1	#
addr_13:	.byte	-1	#
addr_14:	.byte	-1	#
addr_15:	.byte	-1	#
addr_16:	.byte	-1	#
addr_17:	.byte	-1	#
addr_18:	.byte	-1
addr_19:	.byte	-1
addr_1a:	.byte	-1
addr_1b:	.byte	-1
addr_1c:	.byte	-1
addr_1d:	.byte	-1
addr_1e:	.byte	-1
addr_1f:	.byte	-1
addr_20:	.byte	0
addr_21:	.byte	0	# 0xb8 will go here
addr_22:	.byte	0
addr_23:	.byte	0
addr_24:	.byte	0	# 0xb5b6b7b8 will go here
addr_25:	.byte	0	#
addr_26:	.byte	0	#
addr_27:	.byte	0	#
addr_28:	.byte	0
addr_29:	.byte	0
addr_2a:	.byte	0	# 0xb7b8 will go here
addr_2b:	.byte	0	#
addr_2c:	.byte	0
addr_2d:	.byte	0
addr_2e:	.byte	0
addr_2f:	.byte	0
addr_30:	.byte	0	# 0xb1b2b3b4b5b6b7b8 will go here
addr_31:	.byte	0	#
addr_32:	.byte	0	#
addr_33:	.byte	0	#
addr_34:	.byte	0	#
addr_35:	.byte	0	#
addr_36:	.byte	0	#
addr_37:	.byte	0	#
addr_38:	.byte	0
addr_39:	.byte	0
addr_3a:	.byte	0
addr_3b:	.byte	0
addr_3c:	.byte	0
addr_3d:	.byte	0
addr_3e:	.byte	0
addr_3f:	.byte	0
addr_40:

Test_51_Continue:

# Check that the assumed alignment of the memory array is met...
	movi	r1,addr_0
	andi	r1,r1,0x7
	bnez	r1,FAILURE

# Store positive values among lots of 0xFFs...

	movi	r2,0x6162636465666768
	movi	r1,addr_0
	store.b	0x01(r1),r2
	store.w	0x04(r1),r2
	store.h	0x0a(r1),r2
	store.d	0x10(r1),r2

# Store negative values among lots of 0x00s...
# Use negative offsets for good measure...

	movi	r2,0xb1b2b3b4b5b6b7b8
	movi	r7,addr_40		# Previous used r15, but this messed up stack ptr sp.
	store.b	-31(r7),r2
	store.w	-28(r7),r2
	store.h	-22(r7),r2
	store.d	-16(r7),r2

# Check that every byte in the above memory array is correct...
	load.b	r3,0x00(r1)
	bnei	r3,-1,FAILURE
	load.b	r3,0x01(r1)			#
	bnei	r3,0x68,FAILURE
	load.b	r3,0x02(r1)
	bnei	r3,-1,FAILURE
	load.b	r3,0x03(r1)
	bnei	r3,-1,FAILURE
	load.b	r3,0x04(r1)			#
	bnei	r3,0x65,FAILURE
	load.b	r3,0x05(r1)			#
	bnei	r3,0x66,FAILURE
	load.b	r3,0x06(r1)			#
	bnei	r3,0x67,FAILURE
	load.b	r3,0x07(r1)			#
	bnei	r3,0x68,FAILURE
	load.b	r3,0x08(r1)
	bnei	r3,-1,FAILURE
	load.b	r3,0x09(r1)
	bnei	r3,-1,FAILURE
	load.b	r3,0x0a(r1)			#
	bnei	r3,0x67,FAILURE
	load.b	r3,0x0b(r1)			#
	bnei	r3,0x68,FAILURE
	load.b	r3,0x0c(r1)
	bnei	r3,-1,FAILURE
	load.b	r3,0x0d(r1)
	bnei	r3,-1,FAILURE
	load.b	r3,0x0e(r1)
	bnei	r3,-1,FAILURE
	load.b	r3,0x0f(r1)
	bnei	r3,-1,FAILURE
	load.b	r3,0x10(r1)			#
	bnei	r3,0x61,FAILURE
	load.b	r3,0x11(r1)			#
	bnei	r3,0x62,FAILURE
	load.b	r3,0x12(r1)			#
	bnei	r3,0x63,FAILURE
	load.b	r3,0x13(r1)			#
	bnei	r3,0x64,FAILURE
	load.b	r3,0x14(r1)			#
	bnei	r3,0x65,FAILURE
	load.b	r3,0x15(r1)			#
	bnei	r3,0x66,FAILURE
	load.b	r3,0x16(r1)			#
	bnei	r3,0x67,FAILURE
	load.b	r3,0x17(r1)			#
	bnei	r3,0x68,FAILURE
	load.b	r3,0x18(r1)
	bnei	r3,-1,FAILURE
	load.b	r3,0x19(r1)
	bnei	r3,-1,FAILURE
	load.b	r3,0x1a(r1)
	bnei	r3,-1,FAILURE
	load.b	r3,0x1b(r1)
	bnei	r3,-1,FAILURE
	load.b	r3,0x1c(r1)
	bnei	r3,-1,FAILURE
	load.b	r3,0x1d(r1)
	bnei	r3,-1,FAILURE
	load.b	r3,0x1e(r1)
	bnei	r3,-1,FAILURE
	load.b	r3,0x1f(r1)
	bnei	r3,-1,FAILURE
	load.b	r3,0x20(r1)
	bnei	r3,0,FAILURE
	load.b	r3,0x21(r1)			#
	bnei	r3,0xffffffffffffffb8,FAILURE
	load.b	r3,0x22(r1)
	bnei	r3,0,FAILURE
	load.b	r3,0x23(r1)
	bnei	r3,0,FAILURE
	load.b	r3,0x24(r1)			#
	bnei	r3,0xffffffffffffffb5,FAILURE
	load.b	r3,0x25(r1)			#
	bnei	r3,0xffffffffffffffb6,FAILURE
	load.b	r3,0x26(r1)			#
	bnei	r3,0xffffffffffffffb7,FAILURE
	load.b	r3,0x27(r1)			#
	bnei	r3,0xffffffffffffffb8,FAILURE
	load.b	r3,0x28(r1)
	bnei	r3,0,FAILURE
	load.b	r3,0x29(r1)
	bnei	r3,0,FAILURE
	load.b	r3,0x2a(r1)			#
	bnei	r3,0xffffffffffffffb7,FAILURE
	load.b	r3,0x2b(r1)			#
	bnei	r3,0xffffffffffffffb8,FAILURE
	load.b	r3,0x2c(r1)
	bnei	r3,0,FAILURE
	load.b	r3,0x2d(r1)
	bnei	r3,0,FAILURE
	load.b	r3,0x2e(r1)
	bnei	r3,0,FAILURE
	load.b	r3,0x2f(r1)
	bnei	r3,0,FAILURE
	load.b	r3,0x30(r1)			#
	bnei	r3,0xffffffffffffffb1,FAILURE
	load.b	r3,0x31(r1)			#
	bnei	r3,0xffffffffffffffb2,FAILURE
	load.b	r3,0x32(r1)			#
	bnei	r3,0xffffffffffffffb3,FAILURE
	load.b	r3,0x33(r1)			#
	bnei	r3,0xffffffffffffffb4,FAILURE
	load.b	r3,0x34(r1)			#
	bnei	r3,0xffffffffffffffb5,FAILURE
	load.b	r3,0x35(r1)			#
	bnei	r3,0xffffffffffffffb6,FAILURE
	load.b	r3,0x36(r1)			#
	bnei	r3,0xffffffffffffffb7,FAILURE
	load.b	r3,0x37(r1)			#
	bnei	r3,0xffffffffffffffb8,FAILURE
	load.b	r3,0x38(r1)
	bnei	r3,0,FAILURE
	load.b	r3,0x39(r1)
	bnei	r3,0,FAILURE
	load.b	r3,0x3a(r1)
	bnei	r3,0,FAILURE
	load.b	r3,0x3b(r1)
	bnei	r3,0,FAILURE
	load.b	r3,0x3c(r1)
	bnei	r3,0,FAILURE
	load.b	r3,0x3d(r1)
	bnei	r3,0,FAILURE
	load.b	r3,0x3e(r1)
	bnei	r3,0,FAILURE
	load.b	r3,0x3f(r1)
	bnei	r3,0,FAILURE


############################################################################
############################################################################
###
###  Test Basic Exception Processing
###
############################################################################
############################################################################

	movi		r1,TestMessage_4
	call		PrintString
	jump		TestAM_4
TestMessage_4:
	.string		"Test_4: Basic Exception Processing\n\0"
TestMessage_4a:
	.string		"        Testing LOADx - UNALIGNED LOAD/STORE exception\n\0"
TestMessage_4b:
	.string		"        Testing LOADx - NULL ADDRESS exception\n\0"
TestMessage_4c:
	.string		"        Testing STOREx - UNALIGNED LOAD/STORE exception\n\0"
TestMessage_4d:
	.string		"        Testing STOREx - NULL ADDRESS exception\n\0"
	.align		4
TestAM_4:


# ----- Test an ADDI instruction to see if the most basic exception processing is implemented -----

# Setup before the exception
	call		InitJumpTable
	movi		r1,Test66_OK_1
	stored		Jump_ArithmeticException,r1
	call		InitCSRs

# Perform the instruction
	movi		r1,0x7fffffffffffffff
Test66_Loc_1:
	addi		r1,r1,1

# Make sure all is good after the exception
	jump		FAILURE
Test66_OK_1:
	movi		r1,Test66_Loc_1			# r1 = expected csr_prevpc (Addr of the instruction)
	movi		r2,TRAP_CAUSE_ARITHMETIC	# r2 = expected csr_cause  (Arithmetic Exception code)
	loadw		r3,Test66_Loc_1			# r3 = expected csr_bad    (The offending instruction)
	movi		r4,0				# r4 = expected csr_addr
	call		CheckCSRs


	movi		r1,TestMessage_4a
	call		PrintString




# ----- Test LOAD.D - UNALIGNED_LOAD_STORE (kernel mode, interrupts enabled) -----
#
# Setup before the exception
	call		InitJumpTable
	movi		r1,Test4_OK_1
	stored		Jump_UnalignedLoadStore,r1
	call		InitCSRs

# Perform the instruction
Test4_Loc_1:
	loadd		r1,9(r0)

# Make sure all is good after the exception
	jump		FAILURE
Test4_OK_1:
	movi		r1,Test4_Loc_1				# r1 = expected csr_prevpc (Addr of the instruction)
	movi		r2,TRAP_CAUSE_UNALIGNED_LOAD_STORE	# r2 = expected csr_cause  (Unaligned LOAD/STORE code)
	loadw		r3,Test4_Loc_1				# r3 = expected csr_bad    (The offending instruction)
	movi		r4,9					# r4 = expected csr_addr   (The bad address)
	call		CheckCSRs



# ----- Test LOAD.W - UNALIGNED_LOAD_STORE (kernel mode, interrupts enabled) -----
#
# Setup before the exception
	call		InitJumpTable
	movi		r1,Test4_OK_2
	stored		Jump_UnalignedLoadStore,r1
	call		InitCSRs

# Perform the instruction
Test4_Loc_2:
	loadw		r1,9(r0)

# Make sure all is good after the exception
	jump		FAILURE
Test4_OK_2:
	movi		r1,Test4_Loc_2				# r1 = expected csr_prevpc (Addr of the instruction)
	movi		r2,TRAP_CAUSE_UNALIGNED_LOAD_STORE	# r2 = expected csr_cause  (Unaligned LOAD/STORE code)
	loadw		r3,Test4_Loc_2				# r3 = expected csr_bad    (The offending instruction)
	movi		r4,9					# r4 = expected csr_addr   (The bad address)
	call		CheckCSRs



# ----- Test LOAD.H - UNALIGNED_LOAD_STORE (kernel mode, interrupts enabled) -----
#
# Setup before the exception
	call		InitJumpTable
	movi		r1,Test4_OK_3
	stored		Jump_UnalignedLoadStore,r1
	call		InitCSRs

# Perform the instruction
Test4_Loc_3:
	loadh		r1,9(r0)

# Make sure all is good after the exception
	jump		FAILURE
Test4_OK_3:
	movi		r1,Test4_Loc_3				# r1 = expected csr_prevpc (Addr of the instruction)
	movi		r2,TRAP_CAUSE_UNALIGNED_LOAD_STORE	# r2 = expected csr_cause  (Unaligned LOAD/STORE code)
	loadw		r3,Test4_Loc_3				# r3 = expected csr_bad    (The offending instruction)
	movi		r4,9					# r4 = expected csr_addr   (The bad address)
	call		CheckCSRs


	movi		r1,TestMessage_4b
	call		PrintString




# ----- Test LOAD.D - NULL_ADDRESS (kernel mode, interrupts enabled, aligned) -----
#
# Setup before the exception
	call		InitJumpTable
	movi		r1,Test4_OK_5
	stored		Jump_NullAddress,r1
	call		InitCSRs

# Perform the instruction
Test4_Loc_5:
	loadd		r1,0(r0)

# Make sure all is good after the exception
	jump		FAILURE
Test4_OK_5:
	movi		r1,Test4_Loc_5				# r1 = expected csr_prevpc (Addr of the instruction)
	movi		r2,TRAP_CAUSE_NULL_ADDRESS		# r2 = expected csr_cause
	loadw		r3,Test4_Loc_5				# r3 = expected csr_bad    (The offending instruction)
	movi		r4,0					# r4 = expected csr_addr   (The bad address)
	call		CheckCSRs



# ----- Test LOAD.W - NULL_ADDRESS (kernel mode, interrupts enabled, aligned) -----
#
# Setup before the exception
	call		InitJumpTable
	movi		r1,Test4_OK_6
	stored		Jump_NullAddress,r1
	call		InitCSRs

# Perform the instruction
Test4_Loc_6:
	loadw		r1,4(r0)

# Make sure all is good after the exception
	jump		FAILURE
Test4_OK_6:
	movi		r1,Test4_Loc_6				# r1 = expected csr_prevpc (Addr of the instruction)
	movi		r2,TRAP_CAUSE_NULL_ADDRESS		# r2 = expected csr_cause
	loadw		r3,Test4_Loc_6				# r3 = expected csr_bad    (The offending instruction)
	movi		r4,0					# r4 = expected csr_addr   (The bad address)
	call		CheckCSRs



# ----- Test LOAD.H - NULL_ADDRESS (kernel mode, interrupts enabled, aligned) -----
#
# Setup before the exception
	call		InitJumpTable
	movi		r1,Test4_OK_7
	stored		Jump_NullAddress,r1
	call		InitCSRs

# Perform the instruction
Test4_Loc_7:
	loadh		r1,6(r0)

# Make sure all is good after the exception
	jump		FAILURE
Test4_OK_7:
	movi		r1,Test4_Loc_7				# r1 = expected csr_prevpc (Addr of the instruction)
	movi		r2,TRAP_CAUSE_NULL_ADDRESS		# r2 = expected csr_cause
	loadw		r3,Test4_Loc_7				# r3 = expected csr_bad    (The offending instruction)
	movi		r4,0					# r4 = expected csr_addr   (The bad address)
	call		CheckCSRs



# ----- Test LOAD.B - NULL_ADDRESS (kernel mode, interrupts enabled, aligned) -----
#
# Setup before the exception
	call		InitJumpTable
	movi		r1,Test4b_OK_7
	stored		Jump_NullAddress,r1
	call		InitCSRs

# Perform the instruction
Test4b_Loc_7:
	loadb		r1,7(r0)

# Make sure all is good after the exception
	jump		FAILURE
Test4b_OK_7:
	movi		r1,Test4b_Loc_7				# r1 = expected csr_prevpc (Addr of the instruction)
	movi		r2,TRAP_CAUSE_NULL_ADDRESS		# r2 = expected csr_cause
	loadw		r3,Test4b_Loc_7				# r3 = expected csr_bad    (The offending instruction)
	movi		r4,0					# r4 = expected csr_addr   (The bad address)
	call		CheckCSRs





# ----- Test LOAD.D - NULL_ADDRESS+UNALIGNED (kernel mode, interrupts enabled, unaligned) -----
#
# Setup before the exception
	call		InitJumpTable
	movi		r1,Test4_OK_8
	stored		Jump_NullAddress,r1
	call		InitCSRs

# Perform the instruction
Test4_Loc_8:
	loadd		r1,4(r0)

# Make sure all is good after the exception
	jump		FAILURE
Test4_OK_8:
	movi		r1,Test4_Loc_8				# r1 = expected csr_prevpc (Addr of the instruction)
	movi		r2,TRAP_CAUSE_NULL_ADDRESS		# r2 = expected csr_cause
	loadw		r3,Test4_Loc_8				# r3 = expected csr_bad    (The offending instruction)
	movi		r4,0					# r4 = expected csr_addr   (The bad address)
	call		CheckCSRs



# ----- Test LOAD.W - NULL_ADDRESS+UNALIGNED (kernel mode, interrupts enabled, unaligned) -----
#
# Setup before the exception
	call		InitJumpTable
	movi		r1,Test4_OK_9
	stored		Jump_NullAddress,r1
	call		InitCSRs

# Perform the instruction
Test4_Loc_9:
	loadw		r1,2(r0)

# Make sure all is good after the exception
	jump		FAILURE
Test4_OK_9:
	movi		r1,Test4_Loc_9				# r1 = expected csr_prevpc (Addr of the instruction)
	movi		r2,TRAP_CAUSE_NULL_ADDRESS		# r2 = expected csr_cause
	loadw		r3,Test4_Loc_9				# r3 = expected csr_bad    (The offending instruction)
	movi		r4,0					# r4 = expected csr_addr   (The bad address)
	call		CheckCSRs



# ----- Test LOAD.H - NULL_ADDRESS+UNALIGNED (kernel mode, interrupts enabled, unaligned) -----
#
# Setup before the exception
	call		InitJumpTable
	movi		r1,Test4_OK_10
	stored		Jump_NullAddress,r1
	call		InitCSRs

# Perform the instruction
Test4_Loc_10:
	loadh		r1,5(r0)

# Make sure all is good after the exception
	jump		FAILURE
Test4_OK_10:
	movi		r1,Test4_Loc_10				# r1 = expected csr_prevpc (Addr of the instruction)
	movi		r2,TRAP_CAUSE_NULL_ADDRESS		# r2 = expected csr_cause
	loadw		r3,Test4_Loc_10				# r3 = expected csr_bad    (The offending instruction)
	movi		r4,0					# r4 = expected csr_addr   (The bad address)
	call		CheckCSRs







	movi		r1,TestMessage_4c
	call		PrintString







# ----- Test STORE.D - UNALIGNED_LOAD_STORE (kernel mode, interrupts enabled) -----
#
# Setup before the exception
	call		InitJumpTable
	movi		r1,Test5_OK_1
	stored		Jump_UnalignedLoadStore,r1
	call		InitCSRs

# Perform the instruction
Test5_Loc_1:
	stored		9(r0),r1

# Make sure all is good after the exception
	jump		FAILURE
Test5_OK_1:
	movi		r1,Test5_Loc_1				# r1 = expected csr_prevpc (Addr of the instruction)
	movi		r2,TRAP_CAUSE_UNALIGNED_LOAD_STORE	# r2 = expected csr_cause  (Unaligned LOAD/STORE code)
	loadw		r3,Test5_Loc_1				# r3 = expected csr_bad    (The offending instruction)
	movi		r4,9					# r4 = expected csr_addr   (The bad address)
	call		CheckCSRs
Test5_Done_1:



# ----- Test STORE.W - UNALIGNED_LOAD_STORE (kernel mode, interrupts enabled) -----
#
# Setup before the exception
	call		InitJumpTable
	movi		r1,Test5_OK_2
	stored		Jump_UnalignedLoadStore,r1
	call		InitCSRs

# Perform the instruction
Test5_Loc_2:
	storew		9(r0),r1

# Make sure all is good after the exception
	jump		FAILURE
Test5_OK_2:
	movi		r1,Test5_Loc_2				# r1 = expected csr_prevpc (Addr of the instruction)
	movi		r2,TRAP_CAUSE_UNALIGNED_LOAD_STORE	# r2 = expected csr_cause  (Unaligned LOAD/STORE code)
	loadw		r3,Test5_Loc_2				# r3 = expected csr_bad    (The offending instruction)
	movi		r4,9					# r4 = expected csr_addr   (The bad address)
	call		CheckCSRs
Test5_Done_2:



# ----- Test STORE.H - UNALIGNED_LOAD_STORE (kernel mode, interrupts enabled) -----
#
# Setup before the exception
	call		InitJumpTable
	movi		r1,Test5_OK_3
	stored		Jump_UnalignedLoadStore,r1
	call		InitCSRs

# Perform the instruction
Test5_Loc_3:
	storeh		9(r0),r1

# Make sure all is good after the exception
	jump		FAILURE
Test5_OK_3:
	movi		r1,Test5_Loc_3				# r1 = expected csr_prevpc (Addr of the instruction)
	movi		r2,TRAP_CAUSE_UNALIGNED_LOAD_STORE	# r2 = expected csr_cause  (Unaligned LOAD/STORE code)
	loadw		r3,Test5_Loc_3				# r3 = expected csr_bad    (The offending instruction)
	movi		r4,9					# r4 = expected csr_addr   (The bad address)
	call		CheckCSRs
Test5_Done_3:


	movi		r1,TestMessage_4d
	call		PrintString



# ----- Test STORE.D - NULL_ADDRESS (kernel mode, interrupts enabled, aligned) -----
#
# Setup before the exception
	call		InitJumpTable
	movi		r1,Test5_OK_5
	stored		Jump_NullAddress,r1
	call		InitCSRs

# Perform the instruction
Test5_Loc_5:
	stored		0(r0),r1

# Make sure all is good after the exception
	jump		FAILURE
Test5_OK_5:
	movi		r1,Test5_Loc_5				# r1 = expected csr_prevpc (Addr of the instruction)
	movi		r2,TRAP_CAUSE_NULL_ADDRESS		# r2 = expected csr_cause
	loadw		r3,Test5_Loc_5				# r3 = expected csr_bad    (The offending instruction)
	movi		r4,0					# r4 = expected csr_addr   (The bad address)
	call		CheckCSRs
Test5_Done_5:



# ----- Test STORE.W - NULL_ADDRESS (kernel mode, interrupts enabled, aligned) -----
#
# Setup before the exception
	call		InitJumpTable
	movi		r1,Test5_OK_6
	stored		Jump_NullAddress,r1
	call		InitCSRs

# Perform the instruction
Test5_Loc_6:
	storew		4(r0),r1

# Make sure all is good after the exception
	jump		FAILURE
Test5_OK_6:
	movi		r1,Test5_Loc_6				# r1 = expected csr_prevpc (Addr of the instruction)
	movi		r2,TRAP_CAUSE_NULL_ADDRESS		# r2 = expected csr_cause
	loadw		r3,Test5_Loc_6				# r3 = expected csr_bad    (The offending instruction)
	movi		r4,0					# r4 = expected csr_addr   (The bad address)
	call		CheckCSRs
Test5_Done_6:



# ----- Test STORE.H - NULL_ADDRESS (kernel mode, interrupts enabled, aligned) -----
#
# Setup before the exception
	call		InitJumpTable
	movi		r1,Test5_OK_7
	stored		Jump_NullAddress,r1
	call		InitCSRs

# Perform the instruction
Test5_Loc_7:
	storeh		6(r0),r1

# Make sure all is good after the exception
	jump		FAILURE
Test5_OK_7:
	movi		r1,Test5_Loc_7				# r1 = expected csr_prevpc (Addr of the instruction)
	movi		r2,TRAP_CAUSE_NULL_ADDRESS		# r2 = expected csr_cause
	loadw		r3,Test5_Loc_7				# r3 = expected csr_bad    (The offending instruction)
	movi		r4,0					# r4 = expected csr_addr   (The bad address)
	call		CheckCSRs
Test5_Done_7:



# ----- Test STORE.B - NULL_ADDRESS (kernel mode, interrupts enabled, aligned) -----
#
# Setup before the exception
	call		InitJumpTable
	movi		r1,Test5b_OK_7
	stored		Jump_NullAddress,r1
	call		InitCSRs

# Perform the instruction
Test5b_Loc_7:
	storeb		7(r0),r1

# Make sure all is good after the exception
	jump		FAILURE
Test5b_OK_7:
	movi		r1,Test5b_Loc_7				# r1 = expected csr_prevpc (Addr of the instruction)
	movi		r2,TRAP_CAUSE_NULL_ADDRESS		# r2 = expected csr_cause
	loadw		r3,Test5b_Loc_7				# r3 = expected csr_bad    (The offending instruction)
	movi		r4,0					# r4 = expected csr_addr   (The bad address)
	call		CheckCSRs





# ----- Test STORE.D - NULL_ADDRESS+UNALIGNED (kernel mode, interrupts enabled, unaligned) -----
#
# Setup before the exception
	call		InitJumpTable
	movi		r1,Test5_OK_8
	stored		Jump_NullAddress,r1
	call		InitCSRs

# Perform the instruction
Test5_Loc_8:
	stored		4(r0),r1

# Make sure all is good after the exception
	jump		FAILURE
Test5_OK_8:
	movi		r1,Test5_Loc_8				# r1 = expected csr_prevpc (Addr of the instruction)
	movi		r2,TRAP_CAUSE_NULL_ADDRESS		# r2 = expected csr_cause
	loadw		r3,Test5_Loc_8				# r3 = expected csr_bad    (The offending instruction)
	movi		r4,0					# r4 = expected csr_addr   (The bad address)
	call		CheckCSRs
Test5_Done_8:



# ----- Test STORE.W - NULL_ADDRESS+UNALIGNED (kernel mode, interrupts enabled, unaligned) -----
#
# Setup before the exception
	call		InitJumpTable
	movi		r1,Test5_OK_9
	stored		Jump_NullAddress,r1
	call		InitCSRs

# Perform the instruction
Test5_Loc_9:
	storew		2(r0),r1

# Make sure all is good after the exception
	jump		FAILURE
Test5_OK_9:
	movi		r1,Test5_Loc_9				# r1 = expected csr_prevpc (Addr of the instruction)
	movi		r2,TRAP_CAUSE_NULL_ADDRESS		# r2 = expected csr_cause
	loadw		r3,Test5_Loc_9				# r3 = expected csr_bad    (The offending instruction)
	movi		r4,0					# r4 = expected csr_addr   (The bad address)
	call		CheckCSRs
Test5_Done_9:



# ----- Test STORE.H - NULL_ADDRESS+UNALIGNED (kernel mode, interrupts enabled, unaligned) -----
#
# Setup before the exception
	call		InitJumpTable
	movi		r1,Test5_OK_10
	stored		Jump_NullAddress,r1
	call		InitCSRs

# Perform the instruction
Test5_Loc_10:
	storeh		5(r0),r1

# Make sure all is good after the exception
	jump		FAILURE
Test5_OK_10:
	movi		r1,Test5_Loc_10				# r1 = expected csr_prevpc (Addr of the instruction)
	movi		r2,TRAP_CAUSE_NULL_ADDRESS		# r2 = expected csr_cause
	loadw		r3,Test5_Loc_10				# r3 = expected csr_bad    (The offending instruction)
	movi		r4,0					# r4 = expected csr_addr   (The bad address)
	call		CheckCSRs
Test5_Done_10:








# qwqwqw


############################################################################
############################################################################
###
###  Test Exceptions when interrupts enabled
###  (LOADx and STOREx, unaligned and null address)
###
############################################################################
############################################################################

	movi		r1,TestMessage_5
	call		PrintString
	jump		TestAM_5
TestMessage_5:
	.string		"Test_5: Exception with interrupts disabled (LOADx and STOREx, unaligned and null address)\n\0"
TestMessage_5a:
	.string		"        Testing LOADx - UNALIGNED LOAD/STORE exception\n\0"
TestMessage_5b:
	.string		"        Testing LOADx - NULL ADDRESS exception\n\0"
TestMessage_5c:
	.string		"        Testing STOREx - UNALIGNED LOAD/STORE exception\n\0"
TestMessage_5d:
	.string		"        Testing STOREx - NULL ADDRESS exception\n\0"
	.align		4
TestAM_5:



	movi		r1,TestMessage_5a
	call		PrintString

# ----- Test LOAD.D - UNALIGNED_LOAD_STORE (kernel mode, interrupts disabled) -----
#
# Setup before the exception
	call		InitJumpTable
	movi		r1,Test4a_OK_1
	stored		Jump_UnalignedLoadStore,r1
	call		InitCSRs_InterruptsDisabled

# Perform the instruction
Test4a_Loc_1:
	loadd		r1,9(r0)

# Make sure all is good after the exception
	jump		FAILURE
Test4a_OK_1:
	movi		r1,Test4a_Loc_1				# r1 = expected csr_prevpc (Addr of the instruction)
	movi		r2,TRAP_CAUSE_UNALIGNED_LOAD_STORE	# r2 = expected csr_cause  (Unaligned LOAD/STORE code)
	loadw		r3, Test4a_Loc_1			# r3 = expected csr_bad    (The offending instruction)
	movi		r4,9					# r4 = expected csr_addr   (The bad address)
	call		CheckCSRs_InterruptsDisabled	
Test4a_Done_1:



# ----- Test LOAD.W - UNALIGNED_LOAD_STORE (kernel mode, interrupts disabled) -----
#
# Setup before the exception
	call		InitJumpTable
	movi		r1,Test4a_OK_2
	stored		Jump_UnalignedLoadStore,r1
	call		InitCSRs_InterruptsDisabled

# Perform the instruction
Test4a_Loc_2:
	loadw		r1,9(r0)

# Make sure all is good after the exception
	jump		FAILURE
Test4a_OK_2:
	movi		r1, Test4a_Loc_2			# r1 = expected csr_prevpc (Addr of the instruction)
	movi		r2,TRAP_CAUSE_UNALIGNED_LOAD_STORE	# r2 = expected csr_cause  (Unaligned LOAD/STORE code)
	loadw		r3, Test4a_Loc_2			# r3 = expected csr_bad    (The offending instruction)
	movi		r4,9					# r4 = expected csr_addr   (The bad address)
	call		CheckCSRs_InterruptsDisabled
Test4a_Done_2:



# ----- Test LOAD.H - UNALIGNED_LOAD_STORE (kernel mode, interrupts disabled) -----
#
# Setup before the exception
	call		InitJumpTable
	movi		r1,Test4a_OK_3
	stored		Jump_UnalignedLoadStore,r1
	call		InitCSRs_InterruptsDisabled

# Perform the instruction
Test4a_Loc_3:
	loadh		r1,9(r0)

# Make sure all is good after the exception
	jump		FAILURE
Test4a_OK_3:
	movi		r1, Test4a_Loc_3			# r1 = expected csr_prevpc (Addr of the instruction)
	movi		r2,TRAP_CAUSE_UNALIGNED_LOAD_STORE	# r2 = expected csr_cause  (Unaligned LOAD/STORE code)
	loadw		r3, Test4a_Loc_3			# r3 = expected csr_bad    (The offending instruction)
	movi		r4,9					# r4 = expected csr_addr   (The bad address)
	call		CheckCSRs_InterruptsDisabled
Test4a_Done_3:



	movi		r1,TestMessage_5b
	call		PrintString




# ----- Test LOAD.D - NULL_ADDRESS ONLY (kernel mode, interrupts disabled, aligned) -----
#
# Setup before the exception
	call		InitJumpTable
	movi		r1,Test4a_OK_5
	stored		Jump_NullAddress,r1
	call		InitCSRs_InterruptsDisabled

# Perform the instruction
Test4a_Loc_5:
	loadd		r1,0(r0)

# Make sure all is good after the exception
	jump		FAILURE
Test4a_OK_5:
	movi		r1, Test4a_Loc_5		# r1 = expected csr_prevpc (Addr of the instruction)
	movi		r2,TRAP_CAUSE_NULL_ADDRESS	# r2 = expected csr_cause  (Exception code)
	loadw		r3, Test4a_Loc_5		# r3 = expected csr_bad    (The offending instruction)
	movi		r4,0				# r4 = expected csr_addr   (The bad address)
	call		CheckCSRs_InterruptsDisabled
Test4a_Done_5:



# ----- Test LOAD.W - NULL_ADDRESS (kernel mode, interrupts disabled, aligned) -----
#
# Setup before the exception
	call		InitJumpTable
	movi		r1,Test4a_OK_6
	stored		Jump_NullAddress,r1
	call		InitCSRs_InterruptsDisabled

# Perform the instruction
Test4a_Loc_6:
	loadw		r1,4(r0)

# Make sure all is good after the exception
	jump		FAILURE
Test4a_OK_6:
	movi		r1, Test4a_Loc_6		# r1 = expected csr_prevpc (Addr of the instruction)
	movi		r2,TRAP_CAUSE_NULL_ADDRESS	# r2 = expected csr_cause  (Exception code)
	loadw		r3, Test4a_Loc_6		# r3 = expected csr_bad    (The offending instruction)
	movi		r4,0				# r4 = expected csr_addr   (The bad address)
	call		CheckCSRs_InterruptsDisabled
Test4a_Done_6:



# ----- Test LOAD.H - NULL_ADDRESS (kernel mode, interrupts disabled, aligned) -----
#
# Setup before the exception
	call		InitJumpTable
	movi		r1,Test4a_OK_7
	stored		Jump_NullAddress,r1
	call		InitCSRs_InterruptsDisabled

# Perform the instruction
Test4a_Loc_7:
	loadh		r1,6(r0)

# Make sure all is good after the exception
	jump		FAILURE
Test4a_OK_7:
	movi		r1, Test4a_Loc_7		# r1 = expected csr_prevpc (Addr of the instruction)
	movi		r2,TRAP_CAUSE_NULL_ADDRESS	# r2 = expected csr_cause  (Exception code)
	loadw		r3, Test4a_Loc_7		# r3 = expected csr_bad    (The offending instruction)
	movi		r4,0				# r4 = expected csr_addr   (The bad address)
	call		CheckCSRs_InterruptsDisabled
Test4a_Done_7:





# ----- Test LOAD.D - NULL_ADDRESS+UNALIGNED (kernel mode, interrupts disabled, unaligned) -----
#
# Setup before the exception
	call		InitJumpTable
	movi		r1,Test4a_OK_8
	stored		Jump_NullAddress,r1
	call		InitCSRs_InterruptsDisabled
# Perform the instruction
Test4a_Loc_8:
	loadd		r1,4(r0)

# Make sure all is good after the exception
	jump		FAILURE
Test4a_OK_8:
	movi		r1, Test4a_Loc_8		# r1 = expected csr_prevpc (Addr of the instruction)
	movi		r2,TRAP_CAUSE_NULL_ADDRESS	# r2 = expected csr_cause  (Exception code)
	loadw		r3, Test4a_Loc_8		# r3 = expected csr_bad    (The offending instruction)
	movi		r4,0				# r4 = expected csr_addr   (The bad address)
	call		CheckCSRs_InterruptsDisabled
Test4a_Done_8:



# ----- Test LOAD.W - NULL_ADDRESS+UNALIGNED (kernel mode, interrupts disabled, unaligned) -----
#
# Setup before the exception
	call		InitJumpTable
	movi		r1,Test4a_OK_9
	stored		Jump_NullAddress,r1
	call		InitCSRs_InterruptsDisabled

# Perform the instruction
Test4a_Loc_9:
	loadw		r1,2(r0)

# Make sure all is good after the exception
	jump		FAILURE
Test4a_OK_9:
	movi		r1, Test4a_Loc_9		# r1 = expected csr_prevpc (Addr of the instruction)
	movi		r2,TRAP_CAUSE_NULL_ADDRESS	# r2 = expected csr_cause  (Exception code)
	loadw		r3, Test4a_Loc_9		# r3 = expected csr_bad    (The offending instruction)
	movi		r4,0				# r4 = expected csr_addr   (The bad address)
	call		CheckCSRs_InterruptsDisabled
Test4a_Done_9:



# ----- Test LOAD.H - NULL_ADDRESS+UNALIGNED (kernel mode, interrupts disabled, unaligned) -----
#
# Setup before the exception
	call		InitJumpTable
	movi		r1,Test4a_OK_10
	stored		Jump_NullAddress,r1
	call		InitCSRs_InterruptsDisabled

# Perform the instruction
Test4a_Loc_10:
	loadh		r1,5(r0)

# Make sure all is good after the exception
	jump		FAILURE
Test4a_OK_10:
	movi		r1, Test4a_Loc_10		# r1 = expected csr_prevpc (Addr of the instruction)
	movi		r2,TRAP_CAUSE_NULL_ADDRESS	# r2 = expected csr_cause  (Exception code)
	loadw		r3, Test4a_Loc_10		# r3 = expected csr_bad    (The offending instruction)
	movi		r4,0				# r4 = expected csr_addr   (The bad address)
	call		CheckCSRs_InterruptsDisabled
Test4a_Done_10:







	movi		r1,TestMessage_5c
	call		PrintString







# ----- Test STORE.D - UNALIGNED_LOAD_STORE (kernel mode, interrupts disabled) -----
#
# Setup before the exception
	call		InitJumpTable
	movi		r1,Test5a_OK_1
	stored		Jump_UnalignedLoadStore,r1
	call		InitCSRs_InterruptsDisabled

# Perform the instruction
Test5a_Loc_1:
	stored		9(r0),r1

# Make sure all is good after the exception
	jump		FAILURE
Test5a_OK_1:
	movi		r1, Test5a_Loc_1			# r1 = expected csr_prevpc (Addr of the instruction)
	movi		r2,TRAP_CAUSE_UNALIGNED_LOAD_STORE	# r2 = expected csr_cause  (Unaligned LOAD/STORE code)
	loadw		r3, Test5a_Loc_1			# r3 = expected csr_bad    (The offending instruction)
	movi		r4,9					# r4 = expected csr_addr   (The bad address)
	call		CheckCSRs_InterruptsDisabled
Test5a_Done_1:



# ----- Test STORE.W - UNALIGNED_LOAD_STORE (kernel mode, interrupts disabled) -----
#
# Setup before the exception
	call		InitJumpTable
	movi		r1,Test5a_OK_2
	stored		Jump_UnalignedLoadStore,r1
	call		InitCSRs_InterruptsDisabled

# Perform the instruction
Test5a_Loc_2:
	storew		9(r0),r1

# Make sure all is good after the exception
	jump		FAILURE
Test5a_OK_2:
	movi		r1, Test5a_Loc_2			# r1 = expected csr_prevpc (Addr of the instruction)
	movi		r2,TRAP_CAUSE_UNALIGNED_LOAD_STORE	# r2 = expected csr_cause  (Unaligned LOAD/STORE code)
	loadw		r3, Test5a_Loc_2			# r3 = expected csr_bad    (The offending instruction)
	movi		r4,9					# r4 = expected csr_addr   (The bad address)
	call		CheckCSRs_InterruptsDisabled
Test5a_Done_2:



# ----- Test STORE.H - UNALIGNED_LOAD_STORE (kernel mode, interrupts disabled) -----
#
# Setup before the exception
	call		InitJumpTable
	movi		r1,Test5a_OK_3
	stored		Jump_UnalignedLoadStore,r1
	call		InitCSRs_InterruptsDisabled

# Perform the instruction
Test5a_Loc_3:
	storeh		9(r0),r1

# Make sure all is good after the exception
	jump		FAILURE
Test5a_OK_3:
	movi		r1, Test5a_Loc_3			# r1 = expected csr_prevpc (Addr of the instruction)
	movi		r2,TRAP_CAUSE_UNALIGNED_LOAD_STORE	# r2 = expected csr_cause  (Unaligned LOAD/STORE code)
	loadw		r3, Test5a_Loc_3			# r3 = expected csr_bad    (The offending instruction)
	movi		r4,9					# r4 = expected csr_addr   (The bad address)
	call		CheckCSRs_InterruptsDisabled
Test5a_Done_3:


	movi		r1,TestMessage_5d
	call		PrintString




# ----- Test STORE.D - NULL_ADDRESS (kernel mode, interrupts disabled, aligned) -----
#
# Setup before the exception
	call		InitJumpTable
	movi		r1,Test5a_OK_5
	stored		Jump_NullAddress,r1
	call		InitCSRs_InterruptsDisabled

# Perform the instruction
Test5a_Loc_5:
	stored		0(r0),r1

# Make sure all is good after the exception
	jump		FAILURE
Test5a_OK_5:
	movi		r1, Test5a_Loc_5		# r1 = expected csr_prevpc (Addr of the instruction)
	movi		r2,TRAP_CAUSE_NULL_ADDRESS	# r2 = expected csr_cause  (Exception code)
	loadw		r3, Test5a_Loc_5		# r3 = expected csr_bad    (The offending instruction)
	movi		r4,0				# r4 = expected csr_addr   (The bad address)
	call		CheckCSRs_InterruptsDisabled
Test5a_Done_5:



# ----- Test STORE.W - NULL_ADDRESS (kernel mode, interrupts disabled, aligned) -----
#
# Setup before the exception
	call		InitJumpTable
	movi		r1,Test5a_OK_6
	stored		Jump_NullAddress,r1
	call		InitCSRs_InterruptsDisabled

# Perform the instruction
Test5a_Loc_6:
	storew		4(r0),r1

# Make sure all is good after the exception
	jump		FAILURE
Test5a_OK_6:
	movi		r1, Test5a_Loc_6		# r1 = expected csr_prevpc (Addr of the instruction)
	movi		r2,TRAP_CAUSE_NULL_ADDRESS	# r2 = expected csr_cause  (Exception code)
	loadw		r3, Test5a_Loc_6		# r3 = expected csr_bad    (The offending instruction)
	movi		r4,0				# r4 = expected csr_addr   (The bad address)
	call		CheckCSRs_InterruptsDisabled
Test5a_Done_6:



# ----- Test STORE.H - NULL_ADDRESS (kernel mode, interrupts disabled, aligned) -----
#
# Setup before the exception
	call		InitJumpTable
	movi		r1,Test5a_OK_7
	stored		Jump_NullAddress,r1
	call		InitCSRs_InterruptsDisabled

# Perform the instruction
Test5a_Loc_7:
	storeh		6(r0),r1

# Make sure all is good after the exception
	jump		FAILURE
Test5a_OK_7:
	movi		r1, Test5a_Loc_7		# r1 = expected csr_prevpc (Addr of the instruction)
	movi		r2,TRAP_CAUSE_NULL_ADDRESS	# r2 = expected csr_cause  (Exception code)
	loadw		r3, Test5a_Loc_7		# r3 = expected csr_bad    (The offending instruction)
	movi		r4,0				# r4 = expected csr_addr   (The bad address)
	call		CheckCSRs_InterruptsDisabled
Test5a_Done_7:





# ----- Test STORE.D - NULL_ADDRESS+UNALIGNED (kernel mode, interrupts disabled, unaligned) -----
#
# Setup before the exception
	call		InitJumpTable
	movi		r1,Test5a_OK_8
	stored		Jump_NullAddress,r1
	call		InitCSRs_InterruptsDisabled

# Perform the instruction
Test5a_Loc_8:
	stored		4(r0),r1

# Make sure all is good after the exception
	jump		FAILURE
Test5a_OK_8:
	movi		r1, Test5a_Loc_8		# r1 = expected csr_prevpc (Addr of the instruction)
	movi		r2,TRAP_CAUSE_NULL_ADDRESS	# r2 = expected csr_cause  (Exception code)
	loadw		r3, Test5a_Loc_8		# r3 = expected csr_bad    (The offending instruction)
	movi		r4,0				# r4 = expected csr_addr   (The bad address)
	call		CheckCSRs_InterruptsDisabled
Test5a_Done_8:



# ----- Test STORE.W - NULL_ADDRESS+UNALIGNED (kernel mode, interrupts disabled, unaligned) -----
#
# Setup before the exception
	call		InitJumpTable
	movi		r1,Test5a_OK_9
	stored		Jump_NullAddress,r1
	call		InitCSRs_InterruptsDisabled

# Perform the instruction
Test5a_Loc_9:
	storew		2(r0),r1

# Make sure all is good after the exception
	jump		FAILURE
Test5a_OK_9:
	movi		r1, Test5a_Loc_9		# r1 = expected csr_prevpc (Addr of the instruction)
	movi		r2,TRAP_CAUSE_NULL_ADDRESS	# r2 = expected csr_cause  (Exception code)
	loadw		r3, Test5a_Loc_9		# r3 = expected csr_bad    (The offending instruction)
	movi		r4,0				# r4 = expected csr_addr   (The bad address)
	call		CheckCSRs_InterruptsDisabled
Test5a_Done_9:



# ----- Test STORE.H - NULL_ADDRESS+UNALIGNED (kernel mode, interrupts disabled, unaligned) -----
#
# Setup before the exception
	call		InitJumpTable
	movi		r1,Test5a_OK_10
	stored		Jump_NullAddress,r1
	call		InitCSRs_InterruptsDisabled

# Perform the instruction
Test5a_Loc_10:
	storeh		5(r0),r1

# Make sure all is good after the exception
	jump		FAILURE
Test5a_OK_10:
	movi		r1, Test5a_Loc_10		# r1 = expected csr_prevpc (Addr of the instruction)
	movi		r2,TRAP_CAUSE_NULL_ADDRESS	# r2 = expected csr_cause  (Exception code)
	loadw		r3, Test5a_Loc_10		# r3 = expected csr_bad    (The offending instruction)
	movi		r4,0				# r4 = expected csr_addr   (The bad address)
	call		CheckCSRs_InterruptsDisabled
Test5a_Done_10:





############################################################################
############################################################################
###
###  Test B.xx, JAL, JALR (NULL ADDRESS exception, interrupts enabled)
###
############################################################################
############################################################################

	movi		r1,TestMessage_6
	call		PrintString
	jump		TestAM_6
TestMessage_6:
	.string		"Test_6: B.xx, JAL, JALR (NULL ADDRESS exception, interrupts enabled)\n\0"
TestMessage_6a:
	.string		"        B.xx, taken and not-taken (NULL ADDRESS exception, interrupts enabled)\n\0"
TestMessage_6b:
	.string		"        JALR (NULL ADDRESS exception, interrupts enabled)\n\0"
TestMessage_6c:
	.string		"        JAL (NULL ADDRESS exception, interrupts enabled)\n\0"
	.align		4
TestAM_6:




	movi		r1,TestMessage_6a
	call		PrintString


# ----- Test B.EQ (branch not taken) - NULL_ADDRESS+UNALIGNED (kernel mode, interrupts enabled, aligned) -----
#
# Setup before the exception
	call		InitJumpTable
	call		InitCSRs

# Modify the target instruction to branch to location 0.
	movi		r1, Test6_1_Loc
	call		MakeFormatCPointToAddress0001

# Perform the instruction
	movi		r1,1
	movi		r2,2
Test6_1_Loc:
	b.eq		r1,r2,0


# ----- Test B.EQ (branch taken) - NULL_ADDRESS+UNALIGNED (kernel mode, interrupts enabled, aligned) -----
#
# Setup before the exception
	call		InitJumpTable
	movi		r1,Test6_2_OK
	stored		Jump_NullAddress,r1
	call		InitCSRs

# Modify the target instruction to branch to location 0.
	movi		r1, Test6_2_Loc
	call		MakeFormatCPointToAddress0001

# Perform the instruction
Test6_2_Loc:
	b.eq		r1,r1,0
	jump		FAILURE

# Make sure all is good after the exception
	jump		FAILURE
Test6_2_OK:

	movi		r1,Test6_2_Loc				# r1 = expected csr_prevpc (Addr of the instruction)
	movi		r2,TRAP_CAUSE_NULL_ADDRESS		# r2 = expected csr_cause
	loadw		r3,Test6_2_Loc				# r3 = expected csr_bad    (The offending instruction)
	movi		r4,0					# r4 = expected csr_addr   (The bad address)
	call		CheckCSRs




# ----- Test B.NE (branch not taken) - NULL_ADDRESS+UNALIGNED (kernel mode, interrupts enabled, aligned) -----
#
# Setup before the exception
	call		InitJumpTable
	call		InitCSRs

# Modify the target instruction to branch to location 0.
	movi		r1, Test6_3_Loc
	call		MakeFormatCPointToAddress0001

# Perform the instruction
Test6_3_Loc:
	b.ne		r1,r1,0



# ----- Test B.NE (branch taken) - NULL_ADDRESS+UNALIGNED (kernel mode, interrupts enabled, aligned) -----
#
# Setup before the exception
	call		InitJumpTable
	movi		r1,Test6_4_OK
	stored		Jump_NullAddress,r1
	call		InitCSRs

# Modify the target instruction to branch to location 0.
	movi		r1, Test6_4_Loc
	call		MakeFormatCPointToAddress0001

# Perform the instruction
	movi		r1,1
	movi		r2,2
Test6_4_Loc:
	b.ne		r1,r2,0
	jump		FAILURE

# Make sure all is good after the exception
	jump		FAILURE
Test6_4_OK:
	movi		r1,Test6_4_Loc				# r1 = expected csr_prevpc (Addr of the instruction)
	movi		r2,TRAP_CAUSE_NULL_ADDRESS		# r2 = expected csr_cause
	loadw		r3,Test6_4_Loc				# r3 = expected csr_bad    (The offending instruction)
	movi		r4,0					# r4 = expected csr_addr   (The bad address)
	call		CheckCSRs



# ----- Test B.LT (branch not taken) - NULL_ADDRESS+UNALIGNED (kernel mode, interrupts enabled, aligned) -----
#
# Setup before the exception
	call		InitJumpTable
	call		InitCSRs

# Modify the target instruction to branch to location 0.
	movi		r1, Test6_5_Loc
	call		MakeFormatCPointToAddress0001

# Perform the instruction
Test6_5_Loc:
	b.lt		r1,r1,0



# ----- Test B.LT (branch taken) - NULL_ADDRESS+UNALIGNED (kernel mode, interrupts enabled, aligned) -----
#
# Setup before the exception
	call		InitJumpTable
	movi		r1,Test6_6_OK
	stored		Jump_NullAddress,r1
	call		InitCSRs

# Modify the target instruction to branch to location 0.
	movi		r1, Test6_6_Loc
	call		MakeFormatCPointToAddress0001

# Perform the instruction
	movi		r1,1
	movi		r2,2
Test6_6_Loc:
	b.lt		r1,r2,0
	jump		FAILURE

# Make sure all is good after the exception
	jump		FAILURE
Test6_6_OK:
	movi		r1,Test6_6_Loc				# r1 = expected csr_prevpc (Addr of the instruction)
	movi		r2,TRAP_CAUSE_NULL_ADDRESS		# r2 = expected csr_cause
	loadw		r3,Test6_6_Loc				# r3 = expected csr_bad    (The offending instruction)
	movi		r4,0					# r4 = expected csr_addr   (The bad address)
	call		CheckCSRs



# ----- Test B.LE (branch not taken) - NULL_ADDRESS+UNALIGNED (kernel mode, interrupts enabled, aligned) -----
#
# Setup before the exception
	call		InitJumpTable
	call		InitCSRs

# Modify the target instruction to branch to location 0.
	movi		r1, Test6_7_Loc
	call		MakeFormatCPointToAddress0001

# Perform the instruction
	movi		r1,1
	movi		r2,2
Test6_7_Loc:
	b.le		r2,r1,0



# ----- Test B.LE (branch taken) - NULL_ADDRESS+UNALIGNED (kernel mode, interrupts enabled, aligned) -----
#
# Setup before the exception
	call		InitJumpTable
	movi		r1,Test6_8_OK
	stored		Jump_NullAddress,r1
	call		InitCSRs

# Modify the target instruction to branch to location 0.
	movi		r1, Test6_8_Loc
	call		MakeFormatCPointToAddress0001

# Perform the instruction
Test6_8_Loc:
	b.le		r1,r1,0
	jump		FAILURE

# Make sure all is good after the exception
	jump		FAILURE
Test6_8_OK:
	movi		r1,Test6_8_Loc				# r1 = expected csr_prevpc (Addr of the instruction)
	movi		r2,TRAP_CAUSE_NULL_ADDRESS		# r2 = expected csr_cause
	loadw		r3,Test6_8_Loc				# r3 = expected csr_bad    (The offending instruction)
	movi		r4,0					# r4 = expected csr_addr   (The bad address)
	call		CheckCSRs




	movi		r1,TestMessage_6b	# JALR message
	call		PrintString


# ----- Test JALR - NULL_ADDRESS+UNALIGNED (kernel mode, interrupts enabled, aligned) -----
#
# Setup before the exception
	call		InitJumpTable
	movi		r1,Test6_9_OK
	stored		Jump_NullAddress,r1
	call		InitCSRs

# Perform the instruction
Test6_9_Loc:
	jalr		r1,1(r0)
	jump		FAILURE

# Make sure all is good after the exception
	jump		FAILURE
Test6_9_OK:
	movi		r1,Test6_9_Loc				# r1 = expected csr_prevpc (Addr of the instruction)
	movi		r2,TRAP_CAUSE_NULL_ADDRESS		# r2 = expected csr_cause
	loadw		r3,Test6_9_Loc				# r3 = expected csr_bad    (The offending instruction)
	movi		r4,0					# r4 = expected csr_addr   (The bad address)
	call		CheckCSRs


	movi		r1,TestMessage_6c	# JAL message
	call		PrintString


# ----- Test JAL - NULL_ADDRESS+UNALIGNED (kernel mode, interrupts enabled, aligned) -----
#
# Setup before the exception
	call		InitJumpTable
	movi		r1,Test6_10_OK
	stored		Jump_NullAddress,r1
	call		InitCSRs

# Modify the target instruction to branch to location 0.
	movi		r1, Test6_10_Loc
	call		MakeFormatDPointToAddress0001

# Perform the instruction
Test6_10_Loc:
	jal		r1,ADDRESS_ONE
	jump		FAILURE

# Make sure all is good after the exception
	jump		FAILURE
Test6_10_OK:
	movi		r1,Test6_10_Loc				# r1 = expected csr_prevpc (Addr of the instruction)
	movi		r2,TRAP_CAUSE_NULL_ADDRESS		# r2 = expected csr_cause
	loadw		r3,Test6_10_Loc				# r3 = expected csr_bad    (The offending instruction)
	movi		r4,0					# r4 = expected csr_addr   (The bad address)
	call		CheckCSRs



############################################################################
############################################################################
###
###  Test B.xx, JAL, JALR (NULL address exception, interrupts disabled)
###
############################################################################
############################################################################

	movi		r1,TestMessage_7
	call		PrintString
	jump		TestAM_7
TestMessage_7:
	.string		"Test_7: B.xx, JAL, JALR - targetAddress=0  (NULL ADDRESS exception, interrupts disabled)\n\0"
	.align		4
TestMessage_7a:
	.string		"        B.xx, taken and not-taken (NULL ADDRESS exception, interrupts disabled)\n\0"
TestMessage_7b:
	.string		"        JALR (NULL ADDRESS exception, interrupts disabled)\n\0"
TestMessage_7c:
	.string		"        JAL (NULL ADDRESS exception, interrupts disabled)\n\0"
	.align		4
TestAM_7:

	movi		r1,TestMessage_7a
	call		PrintString






# ----- Test B.EQ (branch not taken) - NULL_ADDRESS, aligned (kernel mode, interrupts disabled --> NO EXCEPTION) -----
#
# Setup before the exception
	call		InitJumpTable
	call		InitCSRs

# Modify the target instruction to branch to location 0.
	movi		r1, Test7_1_Loc
	call		MakeFormatCPointToAddress0001

# Perform the instruction
	movi		r1,1
	movi		r2,2
Test7_1_Loc:
	b.eq		r1,r2,0


# ----- Test B.EQ (branch taken) - NULL_ADDRESS, aligned (kernel mode, interrupts disabled --> EXCEPTION) -----
#
# Setup before the exception
	call		InitJumpTable
	movi		r1,Test7_2_OK
	stored		Jump_NullAddress,r1
	call		InitCSRs_InterruptsDisabled

# Modify the target instruction to branch to location 0.
	movi		r1, Test7_2_Loc
	call		MakeFormatCPointToAddress0001

# Perform the instruction
Test7_2_Loc:
	b.eq		r1,r1,0
	jump		FAILURE

# Make sure all is good after the exception
	jump		FAILURE
Test7_2_OK:
	movi		r1, Test7_2_Loc				# r1 = expected csr_prevpc (Addr of the instruction)
	movi		r2,TRAP_CAUSE_NULL_ADDRESS		# r2 = expected csr_cause
	loadw		r3, Test7_2_Loc				# r3 = expected csr_bad    (The offending instruction)
	movi		r4,0					# r4 = expected csr_addr   (The bad address)
	call		CheckCSRs_InterruptsDisabled



# ----- Test B.NE (branch not taken) - NULL_ADDRESS, aligned (kernel mode, interrupts disabled --> NO EXCEPTION) -----
#
# Setup before the exception
	call		InitJumpTable
	call		InitCSRs

# Modify the target instruction to branch to location 0.
	movi		r1, Test7_3_Loc
	call		MakeFormatCPointToAddress0001

# Perform the instruction
Test7_3_Loc:
	b.ne		r1,r1,0



# ----- Test B.NE (branch taken) - NULL_ADDRESS, aligned (kernel mode, interrupts disabled --> EXCEPTION) -----
#
# Setup before the exception
	call		InitJumpTable
	movi		r1,Test7_4_OK
	stored		Jump_NullAddress,r1
	call		InitCSRs_InterruptsDisabled

# Modify the target instruction to branch to location 0.
	movi		r1, Test7_4_Loc
	call		MakeFormatCPointToAddress0001

# Perform the instruction
	movi		r1,1
	movi		r2,2
Test7_4_Loc:
	b.ne		r1,r2,0
	jump		FAILURE

# Make sure all is good after the exception
	jump		FAILURE
Test7_4_OK:
	movi		r1, Test7_4_Loc				# r1 = expected csr_prevpc (Addr of the instruction)
	movi		r2,TRAP_CAUSE_NULL_ADDRESS		# r2 = expected csr_cause
	loadw		r3, Test7_4_Loc				# r3 = expected csr_bad    (The offending instruction)
	movi		r4,0					# r4 = expected csr_addr   (The bad address)
	call		CheckCSRs_InterruptsDisabled



# ----- Test B.LT (branch not taken) - NULL_ADDRESS, aligned (kernel mode, interrupts disabled --> NO EXCEPTION) -----
#
# Setup before the exception
	call		InitJumpTable
	call		InitCSRs

# Modify the target instruction to branch to location 0.
	movi		r1, Test7_5_Loc
	call		MakeFormatCPointToAddress0001

# Perform the instruction
Test7_5_Loc:
	b.lt		r1,r1,0



# ----- Test B.LT (branch taken) - NULL_ADDRESS, aligned (kernel mode, interrupts disabled --> EXCEPTION) -----
#
# Setup before the exception
	call		InitJumpTable
	movi		r1,Test7_6_OK
	stored		Jump_NullAddress,r1
	call		InitCSRs_InterruptsDisabled

# Modify the target instruction to branch to location 0.
	movi		r1, Test7_6_Loc
	call		MakeFormatCPointToAddress0001

# Perform the instruction
	movi		r1,1
	movi		r2,2
Test7_6_Loc:
	b.lt		r1,r2,0
	jump		FAILURE

# Make sure all is good after the exception
	jump		FAILURE
Test7_6_OK:
	movi		r1, Test7_6_Loc				# r1 = expected csr_prevpc (Addr of the instruction)
	movi		r2,TRAP_CAUSE_NULL_ADDRESS		# r2 = expected csr_cause
	loadw		r3, Test7_6_Loc				# r3 = expected csr_bad    (The offending instruction)
	movi		r4,0					# r4 = expected csr_addr   (The bad address)
	call		CheckCSRs_InterruptsDisabled



# ----- Test B.LE (branch not taken) - NULL_ADDRESS, aligned (kernel mode, interrupts disabled --> NO EXCEPTION) -----
#
# Setup before the exception
	call		InitJumpTable
	call		InitCSRs

# Modify the target instruction to branch to location 0.
	movi		r1, Test7_7_Loc
	call		MakeFormatCPointToAddress0001

# Perform the instruction
	movi		r1,1
	movi		r2,2
Test7_7_Loc:
	b.le		r2,r1,0



# ----- Test B.LE (branch taken) - NULL_ADDRESS, aligned (kernel mode, interrupts disabled --> EXCEPTION) -----
#
# Setup before the exception
	call		InitJumpTable
	movi		r1,Test7_8_OK
	stored		Jump_NullAddress,r1
	call		InitCSRs_InterruptsDisabled

# Modify the target instruction to branch to location 0.
	movi		r1, Test7_8_Loc
	call		MakeFormatCPointToAddress0001

# Perform the instruction
Test7_8_Loc:
	b.le		r1,r1,0
	jump		FAILURE

# Make sure all is good after the exception
	jump		FAILURE
Test7_8_OK:
	movi		r1, Test7_8_Loc				# r1 = expected csr_prevpc (Addr of the instruction)
	movi		r2,TRAP_CAUSE_NULL_ADDRESS		# r2 = expected csr_cause
	loadw		r3, Test7_8_Loc				# r3 = expected csr_bad    (The offending instruction)
	movi		r4,0					# r4 = expected csr_addr   (The bad address)
	call		CheckCSRs_InterruptsDisabled




	movi		r1,TestMessage_7b	# JALR message
	call		PrintString


# ----- Test JALR - NULL_ADDRESS, aligned (kernel mode, interrupts disabled --> EXCEPTION) -----
#
# Setup before the exception
	call		InitJumpTable
	movi		r1,Test7_9_OK
	stored		Jump_NullAddress,r1
	call		InitCSRs_InterruptsDisabled

# Perform the instruction
Test7_9_Loc:
	jalr		r1,0(r0)
	jump		FAILURE

# Make sure all is good after the exception
	jump		FAILURE
Test7_9_OK:
	movi		r1, Test7_9_Loc				# r1 = expected csr_prevpc (Addr of the instruction)
	movi		r2,TRAP_CAUSE_NULL_ADDRESS		# r2 = expected csr_cause
	loadw		r3, Test7_9_Loc				# r3 = expected csr_bad    (The offending instruction)
	movi		r4,0					# r4 = expected csr_addr   (The bad address)
	call		CheckCSRs_InterruptsDisabled


	movi		r1,TestMessage_7c	# JAL message
	call		PrintString


# ----- Test JAL - NULL_ADDRESS, aligned (kernel mode, interrupts disabled --> EXCEPTION) -----
#
# Setup before the exception
	call		InitJumpTable
	movi		r1,Test7_10_OK
	stored		Jump_NullAddress,r1
	call		InitCSRs_InterruptsDisabled

# Modify the target instruction to branch to location 0.
	movi		r1, Test7_10_Loc
	call		MakeFormatDPointToAddress0001

# Perform the instruction
Test7_10_Loc:
	jal		r1,ADDRESS_ZERO
	jump		FAILURE

# Make sure all is good after the exception
	jump		FAILURE
Test7_10_OK:
	movi		r1, Test7_10_Loc			# r1 = expected csr_prevpc (Addr of the instruction)
	movi		r2,TRAP_CAUSE_NULL_ADDRESS		# r2 = expected csr_cause
	loadw		r3, Test7_10_Loc			# r3 = expected csr_bad    (The offending instruction)
	movi		r4,0					# r4 = expected csr_addr   (The bad address)
	call		CheckCSRs_InterruptsDisabled



############################################################################
############################################################################
###
### Test NULL_ADDRESS EXCEPTIONS in User Mode
###
### LOADD/W/H/B, STORED/W/H/B, JALR -- Test with address 7.
### B.EQ, B.NE, B.LT, B.LE, and JAL -- No test needed
###
### NOTE: Using address 7 also may also cause Unaligned LOAD/STORE Exception, but
### the Null Address Exception has priority.
###
### Concerning B.EQ, B.NE, B.LT, B.LE, and JAL (when in User Mode)....
###   NULL_ADDRESS cannot occur. The 20-bit offset is relative to the PC. Since we are in User Mode, we
###   must be executing in a virtual address space and thus PC >= 0x8_0000_0000. There is no
###   way these instructions can reach address 0...7.
###
############################################################################
############################################################################

	movi		r1,TestMessage_8
	call		PrintString
	jump		TestAM_8
TestMessage_8:
	.string		"Test_8: Test NULL_ADDRESS EXCEPTIONS in User Mode     ***** NOT YET IMPLEMENTED *****\n\0"
	.align		4
TestAM_8:



############################################################################
############################################################################
###
###  Test CAS
###
############################################################################
############################################################################

	movi		r1,TestMessage_9
	call		PrintString
	jump		TestAM_9
TestMessage_9:
	.string		"Test_9: CAS     ***** TESTING NOT YET IMPLEMENTED *****\n\0"
	.align		4
TestAM_9:

	jump		SUCCESS

############################################################################
############################################################################
###
###  Test user mode
###
############################################################################
############################################################################

	movi		r1,TestMessage_10
	call		PrintString
	jump		TestAM_10
TestMessage_10:
	.string		"Test_10: user mode\n\0"
	.align		4
TestAM_10:

	call		InitPageTable
	call		goIntoUserMode
	movi		r1,UserMess
	call		PrintString
	call		goIntoKernelMode
	jump		Test_10_Done

UserMess:	.string		"-----  Now in user mode... run a test???  -----\n\0"
		.align		4
Test_10_Done:


############################################################################
############################################################################
###
###  Test something
###
############################################################################
############################################################################

	movi		r1,TestMessage_xxx
	call		PrintString
	jump		TestAM_xxx
TestMessage_xxx:
	.string		"Test_xxx: Something\n\0"
	.align		4
TestAM_xxx:




############################################################################
############################################################################
###
###  All tests have been completed.
###
############################################################################
############################################################################

	jump		SUCCESS






####################################################################################################
####################################################################################################
####################################################################################################
####################################################################################################
####################################################################################################
####################################################################################################
####################################################################################################
####################################################################################################
####################################################################################################
####################################################################################################
####################################################################################################
####################################################################################################


###########################################################
#
# Go Into USER MODE
#
# This function goes to USER_MODE, with INTERRUPTS_ENABLED.
#
# The page table was previously initialized to map the first 4 pages (64KiBytes)
# of the virtual address space into the first 4 pages of physical memory.
# Thus, it doesn't matter whether we are running in virtual or physical memory.
#
# NOTE: We assume all addressing will be PC-relative, so code can run either at
#       0_0000_0000 or 8_0000_0000.
#
# Regs used: r1, r2
# Stack:     Not used, leaf function
#
goIntoUserMode:
	
# Go into User Mode.
	movi		r1, goIntoUserMode_1
	movi		r2,0x0000_0008_0000_0000
	add		r1,r1,r2
	jr		r1
	jump		FAILURE
goIntoUserMode_1:

# Turn off kernel mode and enable interrupts
# Sets csr_status = FL_ROUND=00, FL_STAT=00000, INTERRUPTS=Enabled, Mode=User
	movi		r1,0x0000_0000_0000_0002
	csrwrite	csr_status,r1

# Initialize SP
	movi		sp,StackRegionX
	movi		r1,0x0000_0008_0000_0000
	or		sp,sp,r1

# The return address is in kernel space. Change it to virtual.
	movi		r2,0x0000_0008_0000_0000
	or		r14,r14,r2

	ret




###########################################################
#
# Go Into KERNEL MODE
#
# This function gets back in to KERNEL MODE, interrupts enabled.
#
# No checking is done.
#
# Regs used: r1
# Stack:     Will be reset to <empty stack>
#
goIntoKernelMode:
	controlu	r0,r0, ENABLE_KERNEL

	movi		r1, goIntoKernelMode_1
	movi		r2,0x0000_0007_ffff_ffff
	and		r1,r1,r2
	jr		r1
	jump		FAILURE
goIntoKernelMode_1:
	movi		sp,StackRegionX
	csrset		csr_status,0x0002		# Set INTERRUPTS ENABLED
	ret


###########################################################
#
# Set a page in memory to all zeros. r1=addr of page to clear.
#
# Regs used: r1 = Ptr to page
#            t = beyond
# Stack:     Not used, leaf function
#
ZeroPage:
	addi		r2,r1,16*1024
ZeroPageLoop:
	stored		0(r1),r0
	addi		r1,r1,8
	blt		r1,r2, ZeroPageLoop
	ret


###########################################################
#
# Initialize the page table tree and csr_pgtable.
#
# The data pages are not modified.
#
# Regs used: r1, r2, r3
# Stack:     Not used, leaf function
#
InitPageTable:
# Set csr_pgtable
	movi		r1,PageTable
	csrwrite	csr_pgtable,r1

# Initialize the root node and the two index nodes.
	mov		r3,lr			# save lr while we call ZeroPage
	movi		r1, PageTable
	call		ZeroPage
	movi		r1, IndexPage_0
	call		ZeroPage
	movi		r1, IndexPage_1
	call		ZeroPage
	mov		lr,r3

# Initialize the page table nodes.
	movi	r1,pt_0			# Store entry for index page 0 into root page
	stored	pt_addr_0,r1

	movi	r1,pt_1			# Store entry for index page 1 into root page
	stored	pt_addr_1,r1

# Store PTEs into index page 0

	movi	r1,index_0_0		# Store PTE for page 0
	stored	index_addr_0_0,r1

	movi	r1,index_0_8		# Store PTE for page 1
	stored	index_addr_0_8,r1

	movi	r1,index_0_10		# Store PTE for page 2
	stored	index_addr_0_10,r1

	movi	r1,index_0_18		# Store PTE for page 3
	stored	index_addr_0_18,r1

# Store PTEs into index page 1

	movi	r1,index_1_0		# Store PTE for virtual page 699048
	stored	index_addr_1_0,r1

	movi	r1,index_1_1
	stored	index_addr_1_1,r1

	movi	r1,index_1_2
	stored	index_addr_1_2,r1

	movi	r1,index_1_3
	stored	index_addr_1_3,r1

	movi	r1,index_1_4
	stored	index_addr_1_4,r1

	movi	r1,index_1_5
	stored	index_addr_1_5,r1

	movi	r1,index_1_6
	stored	index_addr_1_6,r1

	movi	r1,index_1_7
	stored	index_addr_1_7,r1

	movi	r1,index_1_8
	stored	index_addr_1_8,r1

	movi	r1,index_1_9
	stored	index_addr_1_9,r1

	movi	r1,index_1_a
	stored	index_addr_1_a,r1

	movi	r1,index_1_b
	stored	index_addr_1_b,r1

	movi	r1,index_1_c
	stored	index_addr_1_c,r1

	movi	r1,index_1_d
	stored	index_addr_1_d,r1

	movi	r1,index_1_e
	stored	index_addr_1_e,r1

	movi	r1,index_1_f
	stored	index_addr_1_f,r1

	ret
#
# Here is how this program uses physical memory...
#
# Page      Address
# ====   =============
#   0    0x0_0000_0000     ISA Code  -- Mapped to virtual page 0x8_0000_0000
#   1    0x0_0004_0000     ISA Code  -- Mapped to virtual page 0x8_0000_4000
#   2    0x0_0008_0000     ISA Code  -- Mapped to virtual page 0x8_0000_8000
#   3    0x0_000c_0000     ISA Code  -- Mapped to virtual page 0x8_0000_c000
#   4    0x0_0010_0000     Root Node of page table
#   5    0x0_0014_0000     Index page for virtual pages 0...1023
#   6    0x0_0018_0000     Index page for virtual pages 698368...699391
#   7    0x0_001c_0000        -- not used --
#   8    0x0_0020_0000     Virtual page 699048 at 0xa_aaaa0000
#   9    0x0_0024_0000        -- not used --
#  10    0x0_0028_0000     Virtual page 699049 at 0xa_aaaa_4000
#  11    0x0_002c_0000     Virtual page 699050 at 0xa_aaaa_8000
#  12    0x0_0030_0000     Virtual page 699051 at 0xa_aaaa_c000
#  ...   ...               ...
#  22    0x0_0058_0000     Virtual page 699061 at 0xa_aaad_4000
#  23    0x0_005c_0000     Virtual page 699062 at 0xa_aaad_8000
#  24    0x0_0060_0000     Virtual page 699063 at 0xa_aaad_c000
#
# Here is the page table we will create...
#
# Root page (in page 4 at 0x000010000):
#
#    Addr of PTE           PTE          Virt Page   VirtPageAddr     Phys Page      PhysPageAddr     C   D   W   X   V
#    ===========   ==================   =========  ==============  =============  ================  === === === === ===
#    0x000010000   ----------
#    0x000010000:  0x0000001400000001    0...1023                             5    0x000000014000                    V
#    0x000010aa8:  0x0000001800000001    698368...699391                      6    0x000000018000                    V
#
# Index page (in page 5 at 0x000014000):
#
#    Addr of PTE           PTE          Virt Page   VirtPageAddr     Phys Page      PhysPageAddr     C   D   W   X   V
#    ===========   ==================   =========  ==============  =============  ================  === === === === ===
#    0x000014000   ----------
#    0x000014000:  0x000000000000000f          0     0x800000000              0    0x000000000000        D   W   X   V *** PPN = 0 ***
#    0x000014008:  0x000000040000000f          1     0x800004000              1    0x000000004000        D   W   X   V
#    0x000014010:  0x000000080000000f          2     0x800008000              2    0x000000008000        D   W   X   V
#    0x000014018:  0x0000000c0000000f          3     0x80000c000              3    0x00000000c000        D   W   X   V
#
# Physical pages 7 and 9 intentionally skipped.
#
# Index page (in page 6 at 0x000018000):
#
#    Addr of PTE           PTE          Virt Page   VirtPageAddr     Phys Page      PhysPageAddr     C   D   W   X   V
#    ===========   ==================   =========  ==============  =============  ================  === === === === ===
#    0x000018000   ----------
#    0x000019540:  0x0000002000000001     699048     0xaaaaa0000              8    0x000000020000                    V
#    0x000019548:  0x0000002800000003     699049     0xaaaaa4000             10    0x000000028000                X   V
#    0x000019550:  0x0000002c00000005     699050     0xaaaaa8000             11    0x00000002c000            W       V
#    0x000019558:  0x0000003000000007     699051     0xaaaaac000             12    0x000000030000            W   X   V
#    0x000019560:  0x0000003400000009     699052     0xaaaab0000             13    0x000000034000        D           V
#    0x000019568:  0x000000380000000b     699053     0xaaaab4000             14    0x000000038000        D       X   V
#    0x000019570:  0x0000003c0000000d     699054     0xaaaab8000             15    0x00000003c000        D   W       V
#    0x000019578:  0x000000400000000f     699055     0xaaaabc000             16    0x000000040000        D   W   X   V
#    0x000019580:  0x0000004400000011     699056     0xaaaac0000             17    0x000000044000    C               V
#    0x000019588:  0x0000004800000013     699057     0xaaaac4000             18    0x000000048000    C           X   V
#    0x000019590:  0x0000004c00000015     699058     0xaaaac8000             19    0x00000004c000    C       W       V
#    0x000019598:  0x0000005000000017     699059     0xaaaacc000             20    0x000000050000    C       W   X   V
#    0x0000195a0:  0x0000005400000019     699060     0xaaaad0000             21    0x000000054000    C   D           V
#    0x0000195a8:  0x000000580000001b     699061     0xaaaad4000             22    0x000000058000    C   D       X   V
#    0x0000195b0:  0x0000005c0000001d     699062     0xaaaad8000             23    0x00000005c000    C   D   W       V
#    0x0000195b8:  0x000000600000001f     699063     0xaaaadc000             24    0x000000060000    C   D   W   X   V

#
# Page table root
#
PageTable:		.equ		0x0_0001_0000

pt_addr_0:		.equ		0x0_0001_0000
pt_0:			.equ		0x0000001400000001		# points to physical page 0x0_0001_4000

pt_addr_1:		.equ		0x0_0001_0aa8
pt_1:			.equ		0x0000001800000001		# points to physical page 0x0_0001_8000

#
# Index page 0
#
IndexPage_0:		.equ		0x0_0001_4000

index_addr_0_0:		.equ		0x0_0001_4000
index_0_0:		.equ		0x000000000000000f

index_addr_0_8:		.equ		0x0_0001_4008
index_0_8:		.equ		0x000000040000000f

index_addr_0_10:	.equ		0x0_0001_4010
index_0_10:		.equ		0x000000080000000f

index_addr_0_18:	.equ		0x0_0001_4018
index_0_18:		.equ		0x0000000c0000000f

#
# Index page 1
#
IndexPage_1:		.equ		0x0_0001_8000

index_addr_1_0:		.equ		0x0_0001_9540
index_1_0:		.equ		0x0000002000000001

index_addr_1_1:		.equ		0x0_0001_9548
index_1_1:		.equ		0x0000002800000003

index_addr_1_2:		.equ		0x0_0001_9550
index_1_2:		.equ		0x0000002c00000005

index_addr_1_3:		.equ		0x0_0001_9558
index_1_3:		.equ		0x0000003000000007

index_addr_1_4:		.equ		0x0_0001_9560
index_1_4:		.equ		0x0000003400000009

index_addr_1_5:		.equ		0x0_0001_9568
index_1_5:		.equ		0x000000380000000b

index_addr_1_6:		.equ		0x0_0001_9570
index_1_6:		.equ		0x0000003c0000000d

index_addr_1_7:		.equ		0x0_0001_9578
index_1_7:		.equ		0x000000400000000f

index_addr_1_8:		.equ		0x0_0001_9580
index_1_8:		.equ		0x0000004400000011

index_addr_1_9:		.equ		0x0_0001_9588
index_1_9:		.equ		0x0000004800000013

index_addr_1_a:		.equ		0x0_0001_9590
index_1_a:		.equ		0x0000004c00000015

index_addr_1_b:		.equ		0x0_0001_9598
index_1_b:		.equ		0x0000005000000017

index_addr_1_c:		.equ		0x0_0001_95a0
index_1_c:		.equ		0x0000005400000019

index_addr_1_d:		.equ		0x0_0001_95a8
index_1_d:		.equ		0x000000580000001b

index_addr_1_e:		.equ		0x0_0001_95b0
index_1_e:		.equ		0x0000005c0000001d

index_addr_1_f:		.equ		0x0_0001_95b8
index_1_f:		.equ		0x000000600000001f




############################################################################
############################################################################
############################################################################
############################################################################
###
###   SUPPORT FUNCTIONS
###
############################################################################
############################################################################
############################################################################
############################################################################


############################################################################
#
# PrintString
#
# Passed:
#    r1 = pointer to an array of bytes, terminated with \0.
# Uses:
#    none; uses stack
#
############################################################################

PrintString:
        addi      sp,sp,-32             # Function prologue
        store.d   0(sp),lr              #
        store.d   8(sp),r1              #
        store.d   16(sp),r2             #
        store.d   24(sp),r3             #
Ploop:                                  # LOOP
	load.b		r2,0(r1)		#   r2 = the next byte from the string
        bnez		r2,printLoop		#   IF r2 == 0
        load.d  	lr,0(sp)                #     Return Sequence           
        load.d  	r1,8(sp)                #     .
        load.d  	r2,16(sp)               #     .  
        load.d  	r3,24(sp)               #     .
        addi    	sp,sp,32                #     .
        ret                             #     .
printLoop:				#   LOOP
	controlu	r3,r0,SERIAL_STAT	#     Get serial status
	andi		r3,r3,0x02		#     Look at bit [1] only
	beqz		r3,printLoop		#   UNTIL OUTPUT READY = 1
	controlu	r0,r2,SERIAL_SEND	#   Send a byte from r2
	addi		r1,r1,1			#   Increment pointer
	jump		Ploop	        	# ENDLOOP

############################################################################
#
# PrintChar
#
# Passed:
#    r1 = character -128...+127
# Uses:
#    none; uses stack
#
############################################################################

PrintChar:
        addi      	sp,sp,-16           # Function prologue
        store.d   	0(sp),r1            #
        store.d   	8(sp),r2            #

PrintCharLoop:
	controlu	r2,r0,SERIAL_STAT     #   Get serial status
	andi		r2,r2,0x02	      #   Look at bit [1] only
	beqz		r2, PrintCharLoop     # UNTIL OUTPUT READY = 1
	controlu	r0,r1,SERIAL_SEND     # Print r1

        load.d    	r1,0(sp)            # Return Sequence           
        load.d    	r2,8(sp)            # .           
        addi      	sp,sp,16            # .
        ret                           # .

############################################################################
#
# PrintNL
#
# Uses:
#    none; uses stack
#
############################################################################

PrintNL:
        addi      sp,sp,-16           # Function prologue
        store.d   0(sp),lr            #
        store.d   8(sp),r1            #

	movi      r1,0x0a		# Print \n
	call      PrintChar		#

        load.d    lr,0(sp)            # Return Sequence           
        load.d    r1,8(sp)            # .           
        addi      sp,sp,16            # .
        ret                           # .

############################################################################
#
# PrintNibble
#
# Passed:
#    r1 = number in 0...15 (ignores all but LSB 4 bits)
# Uses:
#    none
#
############################################################################

PrintNibble:
        addi      sp,sp,-24           # Function prologue
        store.d   0(sp),lr            #
        store.d   8(sp),r1            #
        store.d   16(sp),r2           #

	andi      r1,r1,0x000F        # Look only at LSB 4 bits
        bgei      r1,10,PrintAlpha    # IF r1 <= 9
        addi      r1,r1,0x30          #   Change to "0"..."9"
        jump      PrintNibbleLoop
PrintAlpha:                           # ELSE
        addi      r1,r1,0x61-10       #   Change to "a"..."f"
PrintNibbleLoop:
	controlu	r2,r0,SERIAL_STAT     #   Get serial status
	andi		r2,r2,0x02	      #   Look at bit [1] only
	beqz		r2, PrintNibbleLoop   # UNTIL OUTPUT READY = 1
	controlu	r0,r1,SERIAL_SEND     # Print r1

        load.d    lr,0(sp)            # Return           
        load.d    r1,8(sp)            # .           
        load.d    r2,16(sp)           # .           
        addi      sp,sp,24            # .
        ret                           # .

############################################################################
#
# PrintIntNL
#
# Prints a value in hex, e.g., "abcd1234fedc8765" followed by "\n".
#
# Passed:
#    r1 = 64 bit value
#
# Uses:
#    none; uses stack
#
############################################################################

PrintIntNL:
        addi      sp,sp,-16           # Function prologue
        store.d   0(sp),lr            #
        store.d   8(sp),r1            #

	call	PrintInt		# Print integer
	call	PrintNL			# Print \n

        load.d    lr,0(sp)            # Return Sequence           
        load.d    r1,8(sp)            # .           
        addi      sp,sp,16            # .
        ret                           # .

############################################################################
#
# PrintInt
#
# Prints a value in hex, e.g., "abcd1234fedc8765"
#
# Passed:
#    r1 = 64 bit value
# Uses:
#    none; uses stack
#
############################################################################

PrintInt:
        addi      sp,sp,-24           # Function prologue
        store.d   0(sp),lr            #
        store.d   8(sp),r1            #
        store.d   16(sp),r2           #

	movi	r2,16		# LOOP 16 times
PrNibLoop:
	rotri	r1,r1,60	#   Look at next 4 bits (rotate left 4 bits)
	call	PrintNibble	#   Print as a hex char
	addi	r2,r2,-1	# ENDLOOP
	bgtz	r2,PrNibLoop	# .

        load.d    lr,0(sp)            # Return           
        load.d    r1,8(sp)            # .           
        load.d    r2,16(sp)           # .           
        addi      sp,sp,24            # .
        ret                           # .

############################################################################
#
# PrintS0
#
# Prints the value in reg "s0" in hex, e.g.,
#     "Test 000000000000001C"
#
# Uses:
#    none; uses stack
#
############################################################################

PrintS0:
        addi      sp,sp,-24           # Function prologue
        store.d   0(sp),lr            #
        store.d   8(sp),r1            #
        store.d   16(sp),r2           #

        movi      r1,printS0_a        # Print
        call      PrintString         #
        mov       r1,s0               # Print int
        call      PrintInt            #
        movi      r1,printS0_b        # Print
        call      PrintString         #

        load.d    lr,0(sp)            # Return           
        load.d    r1,8(sp)            # .           
        load.d    r2,16(sp)           # .           
        addi      sp,sp,24            # .
        ret                           # .
printS0_a:	.string		"Test \0"
printS0_b:	.string		"\n\0"
		.align		4



############################################################################
#
# PrintRegs
#
# Prints the values in the registers.
#
# Uses: All regs and the stack.
# The csr_status is not modified.
# Will not work in user mode since it initializes SP to a kernel address.
#
############################################################################

PrintRegs:
	stored		oldSP,sp		# Save SP and reset the stack
	movi		sp,StackRegionX

	addi		sp,sp,-120		# Save other regs on the stack
	store.d		  0(sp),r1
	store.d		  8(sp),r2
	store.d		 16(sp),r3
	store.d		 24(sp),r4
	store.d		 32(sp),r5
	store.d		 40(sp),r6
	store.d		 48(sp),r7
	store.d		 56(sp),r8
	store.d		 64(sp),r9
	store.d		 72(sp),r10
	store.d		 80(sp),r11
	store.d		 88(sp),r12
	store.d		 96(sp),r13
	store.d		104(sp),r14
#	store.d		112(sp),r15


FAIL_continue:

# Print r1
	movi		r1,m_r1
	call		PrintString
	load.d		r1,0(sp)
	call		PrintIntNL

# Print r2
	movi		r1,m_r2
	call		PrintString
	load.d		r1,8(sp)
	call		PrintIntNL

# Print r3
	movi		r1,m_r3
	call		PrintString
	load.d		r1,16(sp)
	call		PrintIntNL

# Print r4
	movi		r1,m_r4
	call		PrintString
	load.d		r1,24(sp)
	call		PrintIntNL

# Print r5
	movi		r1,m_r5
	call		PrintString
	load.d		r1,32(sp)
	call		PrintIntNL

# Print r6
	movi		r1,m_r6
	call		PrintString
	load.d		r1,40(sp)
	call		PrintIntNL

# Print r7
	movi		r1,m_r7
	call		PrintString
	load.d		r1,48(sp)
	call		PrintIntNL

# Print r8
	movi		r1,m_r8
	call		PrintString
	load.d		r1,56(sp)
	call		PrintIntNL

# Print r9
	movi		r1,m_r9
	call		PrintString
	load.d		r1,64(sp)
	call		PrintIntNL

# Print r10
	movi		r1,m_r10
	call		PrintString
	load.d		r1,72(sp)
	call		PrintIntNL

# Print r11
	movi		r1,m_r11
	call		PrintString
	load.d		r1,80(sp)
	call		PrintIntNL

# Print r12
	movi		r1,m_r12
	call		PrintString
	load.d		r1,88(sp)
	call		PrintIntNL

# Print r13
	movi		r1,m_r13
	call		PrintString
	load.d		r1,96(sp)
	call		PrintIntNL

# Print r14
	movi		r1,m_r14
	call		PrintString
	load.d		r1,104(sp)
	call		PrintIntNL

# Print r15
	movi		r1,m_r15
	call		PrintString
	loadd		r1,oldSP
	call		PrintIntNL

	load.d		r14,104(sp)		# restore LR and return
	ret

		.align		8
oldSP:		.doubleword	0
m_lr:		.string		"lr:         \0"
m_sp:		.string		"sp:         \0"
m_r1:		.string		"r1:         \0"
m_r2:		.string		"r2:         \0"
m_r3:		.string		"r3:         \0"
m_r4:		.string		"r4:         \0"
m_r5:		.string		"r5:         \0"
m_r6:		.string		"r6:         \0"
m_r7:		.string		"r7:         \0"
m_r8:		.string		"t: (?)      \0"
m_r9:		.string		"s0:         \0"
m_r10:		.string		"s1:         \0"
m_r11:		.string		"s2:         \0"
m_r12:		.string		"tp:         \0"
m_r13:		.string		"gp:         \0"
m_r14:		.string		"lr:         \0"
m_r15:		.string		"sp:         \0"
		.align		4



############################################################################
#
# PrintCSRs
#
# Prints the values in the CSR regs.
#
# Uses: All regs and the stack.
# Assumes: SP is valid. Interrupts will be disabled.
# May not work in user mode, since SP is used and addresses may not be relocatable.
#
############################################################################

PrintCSRs:

        addi      	sp,sp,-8            # Function prologue
        store.d   	0(sp),lr            #

# Switch to Kernel Mode; sp is now usable
	controlu	r2,r0,ENABLE_KERNEL
	stored		prevStat,r2			# Save old CSR_STATUS

# Look at bit [0] of old csr_status and print it
	andi		r1,r2,0x0001
	beqz		r1,WasUser
	movi		r1,stat_was_kernel
	call		PrintString
	jump		Stat_Print_X
WasUser:
	movi		r1,stat_was_user
	call		PrintString
Stat_Print_X:

	movi		r1,m_cycle
	call		PrintString
	csrread		r1,csr_cycle
	call		PrintIntNL

	movi		r1,m_inst
	call		PrintString
	csrread		r1,csr_instr
	call		PrintIntNL

	movi		r1,m_timer
	call		PrintString
	csrread		r1,csr_timer
	call		PrintIntNL

	movi		r1,m_status
	call		PrintString
	csrread		r1,csr_status
	call		PrintIntNL

	movi		r1,m_stat2
	call		PrintString
	csrread		r1,csr_stat2
	call		PrintIntNL

	movi		r1,m_prevpc
	call		PrintString
	csrread		r1,csr_prevpc
	call		PrintIntNL

	movi		r1,m_cause
	call		PrintString
	csrread		r1,csr_cause
	call		PrintIntNL

	movi		r1,m_bad
	call		PrintString
	csrread		r1,csr_bad
	call		PrintIntNL

	movi		r1,m_addr
	call		PrintString
	csrread		r1,csr_addr
	call		PrintIntNL

# Retrieve old csr_Status and restore it.
	loadd		r2,prevStat
	controlu	r0,r2,SET_STATUS	# Restore CSR_STATUS

        load.d    lr,0(sp)			# Return Sequence           
        addi      sp,sp,8			# .
	ret

stat_was_user:		.string		"\nPrevious CSR_STATUS: USER-MODE (PrintCSRs may fail because SP is unusable)\n\n\0"
stat_was_kernel:	.string		"\nPrevious CSR_STATUS: KERNEL-MODE\n\n\0"

m_cycle:		.string		"csr_cycle:  \0"
m_inst:			.string		"csr_inst:   \0"
m_timer:		.string		"csr_timer:  \0"
m_status:		.string		"csr_status: \0"
m_stat2:		.string		"csr_stat2:  \0"
m_prevpc:		.string		"csr_prevpc: \0"
m_cause:		.string		"csr_cause:  \0"
m_bad:			.string		"csr_bad:    \0"
m_addr:			.string		"csr_addr:   \0"

			.align		8
prevStat:		.doubleword	0


###########################################################
#
# GlobalTrapHandler
#
# This is the routine that is invoked when an exception occurs.
#
# Previously, we stored a jump to this routine into csr_trapvec.
#
# This routine will look at csr_cause and use
# it to determine which entry in the JumpTable above is relevant.
# Then this routine will get the address from the JumpTable and
# branch to to it.
#
# The benefit of doing it this way is that the individual tests
# can simply update the JumpTable entries to get control after the
# exception occurs.
#
# REGISTERS USED:   s1,s2,t
#
############################################################################

GlobalTrapHandler:
	csrread	s1,csr_cause			# Load the cause code
	movi	s2,0x2000			# IF not a SYSCALL...
	blt	s1,s2,gotSyscall		#

	movi	s2,JumpTableBeyond		#   IF this value is out-of-range...
	bge	s1,s2,FAILURE			#     Jump to FAILURE
	addi	s1,s1,-0x2000			#   Use the cause code to index into the table
	movi	t,JumpTable			#   .
	add	s1,s1,t				#   .
	loadd	s1,0(s1)			#   Get the address of the handler from table
	jr	s1				#   Jump to the handler

gotSyscall:					# ELSE it is a SYSCALL...
	mov	r1,s1				#   r1 = syscall code (*8)
	loadd	s1,Jump_SyscallHandler		#   Jump to the current syscall handler
	jr	s1				#   .

# Here is a table of addresses. Each slot contains the address of some code.
# The idea is that these addresses will be used by the global trap handler.
# When an exception occurs, the global trap handler will go to this table,
# find the corresponding address, and then JUMP to that address.
#
# We initialize (and re-initialize) the table by storing FAILURE in each entry,
# but we will some particular entry before a test which expects to get that exception.

	.align		8
JumpTable:

Jump_ArithmeticException:	.doubleword	FAILURE		# 8192   0x2000
Jump_UnalignedLoadStore:	.doubleword	FAILURE		# 8200   0x2008
Jump_NullAddress:		.doubleword	FAILURE		# 8208   0x2010
Jump_Illegal:			.doubleword	FAILURE		# 8216   0x2018	Instruction, privilege violation
Jump_PagePrivilege:		.doubleword	FAILURE		# 8224   0x2020	attempt to access kernel space
Jump_PageTable:			.doubleword	FAILURE		# 8232   0x2028	bad csr_pgtable
Jump_PageInvalid:		.doubleword	FAILURE		# 8240   0x2030	either index page or PTE
Jump_PageWrite:			.doubleword	FAILURE		# 8248   0x2038
Jump_PageFetch:			.doubleword	FAILURE		# 8256   0x2040
Jump_PageCopyOnWrite:		.doubleword	FAILURE		# 8264   0x2048
Jump_PageFirstDirty:		.doubleword	FAILURE		# 8272   0x2050
Jump_Debug:			.doubleword	FAILURE		# 8280   0x2058
Jump_Breakpoint:		.doubleword	FAILURE		# 8288   0x2060
Jump_Singlestep:		.doubleword	FAILURE		# 8296   0x2068
Jump_KernelException:		.doubleword	FAILURE		# 8304   0x2070
Jump_EmulatedInstruction:	.doubleword	FAILURE		# 8312   0x2078
Jump_HardwareFault:		.doubleword	FAILURE		# 8320   0x2080
Jump_BadArrayIndex:		.doubleword	FAILURE		# 8328   0x2088
Jump_TimerInterrupt:		.doubleword	FAILURE		# 8336   0x2090

Jump_SyscallHandler:		.doubleword	FAILURE

JumpTableBeyond:

###########################################################
#
# InitJumpTable
#
# This function resets the JumpTable so all entries point to FAILURE.
#
# Reg Usage: r1,r2
# Stack:     Not Used; this is a leaf function
#
############################################################################

InitJumpTable:
	movi		r2,FAILURE
	movi		r1,JumpTable
InitJT_Loop:
	stored		0(r1),r2
	addi		r1,r1,8
	bnei		r1,JumpTableBeyond,InitJT_Loop

# Set csr_trapvec so the table will be used.
	movi		r1, GlobalTrapHandler
	csrwrite	csr_trapvec,r1
	ret


###########################################################
#
# InitCSRs
#
# This function resets all CSRs to known values. This a useful thing
# to do before an exception, so we can verify that exactly the right
# CSRs are modified by the exception.
#
# Reg Usage: r1,r2
# Stack:     Not Used; this is a leaf function
#
############################################################################

InitCSRs:
	movi		r1,0x3333333333333333
	csrwrite	csr_timer,r1

	movi		r1,0x00000000000001AB	# FloatRound=01, FloatStat=10101,
	csrwrite	csr_status,r1		# SingleStep=0, InterruptsEnabled=1, KernelMode=1

	movi		r1,0x5555555555555555
	csrwrite	csr_stat2,r1
	movi		r1,0x6666666666666666
	csrwrite	csr_prevpc,r1
	movi		r1,0x7777777777777777
	csrwrite	csr_cause,r1
	movi		r1,0x8888888888888888
	csrwrite	csr_bad,r1
	movi		r1,0x9999999999999999
	csrwrite	csr_addr,r1
	movi		r1,0xaaaaaaaaaaaaaaaa
	csrwrite	csr_ptr,r1
	movi		r1,0xbbbbbbbbbbbbbbbb
	csrwrite	csr_temp,r1
#	movi		r1,0xcccccccccccccccc
#	csrwrite	csr_trapvec,r1
	movi		r1,0x1234_0000_0000_0000 | PageTable
	csrwrite	csr_pgtable,r1
	ret


###########################################################
#
# InitCSRs_InterruptsDisabled
#
# This function resets all CSRs to known values. This a useful thing
# to do before an exception, so we can verify that exactly the right
# CSRs are modified by the exception.
#
# Reg Usage: r1,r2
# Stack:     Not Used; this is a leaf function
#
############################################################################

InitCSRs_InterruptsDisabled:
	movi		r1,0x3333333333333333
	csrwrite	csr_timer,r1

	movi		r1,0x00000000000001A9	# FloatRound=01, FloatStat=10101,
	csrwrite	csr_status,r1		# SingleStep=0, InterruptsEnabled=0, KernelMode=1

	movi		r1,0x5555555555555555
	csrwrite	csr_stat2,r1
	movi		r1,0x6666666666666666
	csrwrite	csr_prevpc,r1
	movi		r1,0x7777777777777777
	csrwrite	csr_cause,r1
	movi		r1,0x8888888888888888
	csrwrite	csr_bad,r1
	movi		r1,0x9999999999999999
	csrwrite	csr_addr,r1
	movi		r1,0xaaaaaaaaaaaaaaaa
	csrwrite	csr_ptr,r1
	movi		r1,0xbbbbbbbbbbbbbbbb
	csrwrite	csr_temp,r1
#	movi		r1,0xcccccccccccccccc
#	csrwrite	csr_trapvec,r1
	movi		r1,0x1234_0000_0000_0000 | PageTable
	csrwrite	csr_pgtable,r1
	ret


###########################################################
#
# CheckCSRs
#
# This function looks at the CSRs after an exception has been
# triggered and makes sure they contain the correct values. It jumps
# to FAILURE if problems.
#
### This function assumes the exception occurred in KERNEL MODE.
#
# The following CSRs will have values that depend on the exception
# details. Therefore, the expected values are passed in as arguments.
#     r1 = csr_prevpc
#     r2 = csr_cause
#     r3 = csr_bad
#     r4 = csr_addr
#
# Regs modified: r5
# Stack:         Not Used; this is a leaf function
#
############################################################################

CheckCSRs:

# Don't check csr_version, csr_prod, csr_core, csr_instr, csr_cycle since they are read-only.

	csrread		r5,csr_timer
	movi		t, 0xFFFFFFFFFF000000		# It changes, so ignore LS bits
	and		r5,r5,t
	bnei		r5,0x3333333333000000,FAILURE

	csrread		r5,csr_status
	bnei		r5,0x00000000000001A9,FAILURE	# Unchanged, except IntEnabled=0

	csrread		r5,csr_stat2
	bnei		r5,0x00000000000001AB,FAILURE	# Previous value of csr_status

	csrread		r5,csr_prevpc
	bne		r5,r1,FAILURE

	csrread		r5,csr_cause
	bne		r5,r2,FAILURE

	csrread		r5,csr_bad
	bne		r5,r3,FAILURE

	csrread		r5,csr_addr
	bne		r5,r4,FAILURE

	csrread		r5,csr_ptr
	bnei		r5,0xaaaaaaaaaaaaaaaa,FAILURE

	csrread		r5,csr_temp
	bnei		r5,0xbbbbbbbbbbbbbbbb,FAILURE

	csrread		r5,csr_trapvec
	movi		t,GlobalTrapHandler
	bne		r5,t,FAILURE

	csrread		r5,csr_pgtable
	bnei		r5,0x1234_0000_0000_0000 | PageTable,FAILURE

	ret


###########################################################
#
# CheckCSRs_InterruptsDisabled
#
# This function looks at the CSRs after an exception has been
# triggered and makes sure they contain the correct values. It jumps
# to FAILURE if problems.
#
### This function assumes the exception occurred in KERNEL MODE.
#
# The following CSRs will have values that depend on the exception
# details. Therefore, the expected values are passed in as arguments.
#     r1 = csr_prevpc
#     r2 = csr_cause
#     r3 = csr_bad
#     r4 = csr_addr
#
# Regs modified: r5
# Stack:         Not Used; this is a leaf function
#
############################################################################

CheckCSRs_InterruptsDisabled:

# Don't check csr_version, csr_prod, csr_core, csr_instr, csr_cycle since they are read-only.

	csrread		r5,csr_timer
	movi		t, 0xFFFFFFFFFF000000		# It changes, so ignore LS bits
	and		r5,r5,t
	bnei		r5,0x3333333333000000,FAILURE

	csrread		r5,csr_status
	bnei		r5,0x00000000000001A9,FAILURE	# Unchanged, except IntEnabled=0

	csrread		r5,csr_stat2
	bnei		r5,0x00000000000001A9,FAILURE	# Previous value of csr_status

	csrread		r5,csr_prevpc
	bne		r5,r1,FAILURE

	csrread		r5, csr_cause
	bne		r5,r2,FAILURE

	csrread		r5,csr_bad
	bne		r5,r3,FAILURE

	csrread		r5,csr_addr
	bne		r5,r4,FAILURE

	csrread		r5,csr_ptr
	bnei		r5,0xaaaaaaaaaaaaaaaa,FAILURE

	csrread		r5,csr_temp
	bnei		r5,0xbbbbbbbbbbbbbbbb,FAILURE

	csrread		r5,csr_trapvec
	movi		t,GlobalTrapHandler
	bne		r5,t,FAILURE

	csrread		r5,csr_pgtable
	bnei		r5,0x1234_0000_0000_0000 | PageTable,FAILURE

	ret


###########################################################
#
# MakeFormatCPointToAddress0001
#
# This function is passed r1=pointer to a B.XX instruction. It modifies the immed-16 field
# so that the branch target will be address 0x0_0000_0001.
#
# r1 = address of the instruction.
#
# Stack:         Not Used; this is a leaf function
#
############################################################################

MakeFormatCPointToAddress0001:
	mov		r3,r1			# This is the address of the instruction
	neg		r3,r3			# Make it negative
	movi		r4,0x0000ffff		# Isolate the 16 bit field: r3 = ---- ---- ---- ---- VVVV VVVV VVVV VVVV
	and		r3,r3,r4		# .
	addi		r3,r3,1			# Add 1 to make it unaligned
	andi		r2,r3,0x0000000f	# r2 =  ---- ---- ---- ---- ---- ---- ---- VVVV
	srli		r3,r3,4			# .
	slli		r3,r3,12		# r3 =  ---- ---- VVVV VVVV VVVV ---- ---- ----
	or		r3,r3,r2		# Combine into format-c  ---- ---- VVVV VVVV VVVV ---- ---- VVVV
	loadw		r2,0(r1)		# Get the instruction instruction
	movi		r4,0xff000ff0		# Clear the 16 bit field
	and		r2,r2,r4		# .
	or		r3,r3,r2		# Put them together
	storew		0(r1),r3		# Replace the instruction
	ret


###########################################################
#
# MakeFormatDPointToAddress0001
#
# This function is passed r1=pointer to a JAL instruction. It modifies the immed-20 field
# so that the branch target will be address 0x0_0000_0001.
#
# r1 = address of the instruction.
#
# Stack:         Not Used; this is a leaf function
#
############################################################################

MakeFormatDPointToAddress0001:
	mov		r3,r1			# This is the address of the instruction
	neg		r3,r3			# Make it negative
	movi		r4,0x000fffff		# Isolate the 20 bit field: r3 = ---- ---- ---- VVVV VVVV VVVV VVVV VVVV
	and		r3,r3,r4		# .
	addi		r3,r3,1			# Add 1 to make it unaligned
	slli		r3,r3,4			# r3 =  ---- ---- VVVV VVVV VVVV VVVV VVVV ----
	loadw		r2,0(r1)		# Get the instruction instruction
	movi		r4,0xff00000f		# Clear the 20 bit field
	and		r2,r2,r4		# .
	or		r3,r3,r2		# Put them together
	storew		0(r1),r3		# Replace the instruction
	ret


EndOfCode:
	.endfunction
