Hands on Risc-V (RV32IMAC) assembler : Part 3

Arithmetic calculations

The code below shows addition, subtraction, multiplication and division. Immediate addition and subtraction are the same instruction ; you add a negative sign to the immediate value to perform subtraction. Immediate values are 12 bit signed so the range of values is -2048 to +2047.

Multiplying two 32 bit numbers requires two steps: the mul instruction produces the 32 bit low order word result. The mulh(u) insruction produces the 32 bit high order word result. The u suffix is used for unsigned multiplication.

32 bit division uses the div instruction while the rem instruction can be used to determine the remaind er of a division.

I have noticed some problems debugging this chip. Normally when you debug assembly language, the debugger shows you the line of code that will be executed next i.e. it hasn’t happened yet. I have noticed that this is not the case with this debugger and mcu. I suspect it is due to the instruction pipeline in the CPU behaving in way that is not expected by jlink and/or gdb. I have taken to (temporarily) adding nop instructions at various places to stop the CPU from getting ahead me.

/* Initialization routine which sets the stack pointer, 
 sets initial global values and clears those that are not
 specifically initialized.  Assumes that the linker script aligned 
 data sections along a word (4 byte) boundary.
*/
	.global Reset_Handler	
	
	.section start
Reset_Handler:
	lui sp,0x20005 # set stack pointer to top of RAM
	
	lui t2,%hi(a)		/* load 20 high bits of address of a into t2 */
	addi t2,t2,%lo(a)   /* add lower 12 bits of address of a to t2 */
	lw t0,0(t2) 		/* load the value pointed to by (0+t2) into t0 */
	
	lui t2,%hi(b)		/* load 20 high bits of address of b into t2 */
	addi t2,t2,%lo(b)	/* add lower 12 bits of address of b to t2 */
	lw t1,0(t2)			/* load the value pointed to by (0+t2) into t0 */	
	
	add t4,t0,t1        /* register to register addition */
	sub t5,t1,t0		/* register to register subtraction */
	
	add t4,t0,1			/* add immediate */
	add t5,t0,-1		/* subtract immediate */
	
	add t4,t0,2047		/* maximum immediate addition (12 bits signed) */
	add t5,t0,-2048		/* maximum immediate subtraction (12 bits signed) */
	
	lui t2,%hi(a)		/* load 20 high bits of address of a into t2 */
	addi t2,t2,%lo(a)   /* add lower 12 bits of address of a to t2 */
	lw t0,0(t2) 		/* load the value pointed to by (0+t2) into t0 */
	
	lui t2,%hi(b)		/* load 20 high bits of address of b into t2 */
	addi t2,t2,%lo(b)	/* add lower 12 bits of address of b to t2 */
	lw t1,0(t2)			/* load the value pointed to by (0+t2) into t0 */	
	
	mul t4,t0,t1		/* low order multiplication word */
	mulhu t5,t0,t1		/* high order multiplication word */
	
	lui t2,%hi(mul64)		/* load 20 high bits of address of mul64 into t2 */
	addi t2,t2,%lo(mul64)	/* add lower 12 bits of address of mul64 to t2 */
	sw t4,0(t2)				/* store the value in t4 to address pointed to by (0+t2) */
	sw t5,4(t2)				/* store the value in t5 to address pointed to by (4+t2) */
	
	lui t2,%hi(e)		/* load 20 high bits of address of e into t2 */
	addi t2,t2,%lo(e)   /* add lower 12 bits of address of e to t2 */
	lw t0,0(t2) 		/* load the value pointed to by (0+t2) into t0 */
	
	lui t2,%hi(f)		/* load 20 high bits of address of f into t2 */
	addi t2,t2,%lo(f)	/* add lower 12 bits of address of f to t2 */
	lw t1,0(t2)			/* load the value pointed to by (0+t2) into t0 */	
	
	divu t4,t0,t1		/* 32 bit division result	*/
	rem t5,t0,t1		/* 32 bit division remainder */
	
	lui t2,%hi(divresult)		/* load 20 high bits of address of mul64 into t2 */
	addi t2,t2,%lo(divresult)	/* add lower 12 bits of address of mul64 to t2 */
	sw t4,0(t2)				/* store the value in t4 to address pointed to by (0+t2) */
	sw t5,4(t2)				/* store the value in t5 to address pointed to by (4+t2) */
	
	nop /* 1 */
	nop /* 2 */
	nop /* 3 */
	nop /* 4 */
	nop /* 5 */
	nop /* 6 */
	nop /* 7 */
	nop /* 8 */
	nop /* 9 */
	
exit_spin: 
	j exit_spin
		
a:	.word 0x12345678
b:	.word 0x23456789
e:	.word 19
f:	.word 6



		.data
mul64:	.word 0,0
divresult:	.word 0
rem32:	.word 0



Leave a comment