This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

CCS/MSP430F5529: Software Multiplier (Shift-and-Add Algorithm)

Part Number: MSP430F5529

Tool/software: Code Composer Studio

I have a piece of code that I am working on (that you guys have already helped me immensely with) that calculates the powers of 2 and places them into two separate arrays (one array for HW multiplication and one array for SW multiplication).  I have all of the array logic in place and functional as well as the HW multiplier function.  I have some vague documentation on how to implement the Shift-and-Add algorithm, but it doesn't actually include anything for basic integer-integer multiplication.  It also doesn't include any code examples at all.  If you guys have any input on how I can write a block to perform this operation, I would greatly appreciate it.  I will include my code here for anyone who wishes to look at it.

        .cdecls C,LIST,"msp430.h"       ;Include device header file

        .def    RESET                   ;Export program entry-point to
                                        ;make it known to linker.
        .def	hcalc_power
        .def	scalc_power
        .def	SW_Mult
        .def	HW_Mult

		.text                           ;Assemble into program memory.
		.retain                         ;Override ELF conditional linking
        		                        ;and retain current section.
		.retainrefs                     ;And retain any sections that have
        		                        ;references to current section.
		.data
b:		.int 	2						;Create variable and initialize it to 2
hval:	.int	1						;Create variable for product placement init 0
sval:	.int	1						;Create variable for product placement init 0
hwarr:	.int	2, 2, 2, 2, 2			;hw mult array
swarr:	.int	1, 1, 1, 1, 1			;sw mult array

RESET:  mov.w   #__STACK_END,SP         ;Initialize stack pointer
        mov.w   #WDTPW|WDTHOLD,&WDTCTL  ;Stop watchdog timer

;-------------------------------------------------------------------------------
; Main loop
;-------------------------------------------------------------------------------
main: 	mov.w	#hwarr, R7	;starting address of hwarr to R7
		mov.w	#swarr, R8	;starting address of swarr to R8
		clr.w	R9

hwnext:	mov.b	@R7+, R9	;get next hwarr element
		cmp		#2, R9		;is it a 2?
		jne		swnext		;if not, go to swnext
		call	#hcalc_power;calculate powers of 2
		mov.w	hval, 0(R7)	;put product into current array element
		inc.w	R7			;increment R7 or it won't fully move to next element
		jmp		hwnext

swnext:	mov.w	@R8+, R9	;get next swarr element
		cmp		#1, R9		;is it a 1?
		jne		lend		;if not, go to end
		call	#scalc_power;calculate powers of 2 again
		jmp		swnext

hcalc_power:
		mov.w	b, R5		;pass b to register for HW_Mult subroutine
		mov.w	hval, R6	;ditto for hval
		call	#HW_Mult
		ret

scalc_power:
		mov.w	b, R5		;pass b to register for HW_Mult subroutine
		mov.w	sval, R6	;ditto for hval
		call	#SW_Mult
		ret

HW_Mult:
		mov.w	R5, &MPY	;get R5
		mov.w	R6, &OP2	;get R6
		nop					;3 clock cycles
		nop
		nop
		mov		RESLO, &hval;multiply and put product in hval
		ret

SW_Mult:

		ret

lend:	nop

;-------------------------------------------------------------------------------
; Stack Pointer definition
;-------------------------------------------------------------------------------
        .global __STACK_END
        .sect   .stack

;-------------------------------------------------------------------------------
; Interrupt Vectors
;-------------------------------------------------------------------------------
         .sect   ".reset"               ; MSP430 RESET Vector
         .short  RESET
         .end

  • I have made SOME progress understanding how this should work, but it still doesn't function.

            .cdecls C,LIST,"msp430.h"       ;Include device header file
    
            .def    RESET                   ;Export program entry-point to
                                            ;make it known to linker.
            .def	hcalc_power
            .def	scalc_power
            .def	SW_Mult
            .def	HW_Mult
    
    		.text                           ;Assemble into program memory.
    		.retain                         ;Override ELF conditional linking
            		                        ;and retain current section.
    		.retainrefs                     ;And retain any sections that have
            		                        ;references to current section.
    		.data
    b:		.int 	2						;Create variable and initialize it to 2
    hval:	.int	1						;Create variable for product placement init 0
    sval:	.int	1						;Create variable for product placement init 0
    hwarr:	.int	2, 2, 2, 2, 2			;hw mult array
    swarr:	.int	1, 1, 1, 1, 1			;sw mult array
    
    RESET:  mov.w   #__STACK_END,SP         ;Initialize stack pointer
            mov.w   #WDTPW|WDTHOLD,&WDTCTL  ;Stop watchdog timer
    
    ;-------------------------------------------------------------------------------
    ; Main loop
    ;-------------------------------------------------------------------------------
    main: 	mov.w	#hwarr, R7		;starting address of hwarr to R7
    		mov.w	#swarr, R8		;starting address of swarr to R8
    		clr.w	R9
    		clr.w	R10
    		clr.w	R11
    		mov.w	b, R5			;pass b to R5 for calc_power
    
    hwnext:	mov.b	@R7+, R9		;get next hwarr element
    		cmp		#2, R9			;is it a 2?
    		jne		swnext			;if not, go to swnext
    		call	#hcalc_power	;calculate powers of 2 -- takes 36 cc
    		mov.w	hval, 0(R7)		;put product into current array element
    		inc.w	R7				;increment R7 or it won't fully move to next element
    		jmp		hwnext			;loop
    
    swnext:	mov.b	@R8+, R9		;get next swarr element
    		cmp		#1, R9			;is it a 1?
    		jne		lend			;if not, go to end
    		call	#scalc_power	;calculate powers of 2 again -- takes
    		mov.w	sval, 0(R8)		;put product into current array element
    		inc.w	R8				;increment R8 or it won't fully move to next element
    		jmp		swnext			;loop
    
    hcalc_power:
    		mov.w	hval, R6		;pass hval to R6 for HW_Mult
    		call	#HW_Mult
    		ret
    
    scalc_power:
    		mov.w	sval, R6			;pass R9 to R6 for SW_Mult
    		call	#SW_Mult
    		ret
    
    HW_Mult:
    		mov.w	R5, &MPY		;get R5
    		mov.w	R6, &OP2		;get R6
    		nop						;3 clock cycles
    		nop
    		nop
    		mov		RESLO, &hval	;multiply and put product in hval
    		ret
    
    SW_Mult:
    		bit.w	#1, R6
    		jz		skp
    		add.w	R9, R5
    skp:
    		rla.w	R9
    		rra.w	R6
    		add.w	#1, R6
    		cmp		#16, R6
    		jl		SW_Mult
    		add.b	#1, R15
    		cmp.b	#4, R15
    		mov.w	R5, 0(R8)
    		;jeq
    		ret
    
    lend:	nop
    
    ;-------------------------------------------------------------------------------
    ; Stack Pointer definition
    ;-------------------------------------------------------------------------------
            .global __STACK_END
            .sect   .stack
    
    ;-------------------------------------------------------------------------------
    ; Interrupt Vectors
    ;-------------------------------------------------------------------------------
             .sect   ".reset"               ; MSP430 RESET Vector
             .short  RESET
             .end
    

  • I think you can refer to the assemble code generated by compiler for software multiplication.

  • Of course it doesn't work. You are using R6 as both the loop counter and one of the arguments. But I think that you will also find that you are testing the bits in the wrong order.

    I recall reading a TI document on their fixed point routines that included cycle counts for both the hardware and software versions so you might want to look that up.

**Attention** This is a public forum