Jump to content

Wrong Bank With 32-bit Multiplication

Recommended Posts

Bug description:

Incorrect bank used in unsigned long multiplication under certain circumstances.


Steps to reproduce:

This has been seen when __mul_32u__0000F_arg_a is in bank 0, and __mul_32u__0000F_arg_b and __mul_32u__0000F_1_i are in bank 1.


In the compiled code, in the calling function, bank 1 is selected, __mul_32u__0000F_arg_b is set up, bank 0 is selected, __mul_32u__0000F_arg_a is set up, and __mul_32u__0000F is called while still in bank 0. __mul_32u__0000F assumes that it is already in bank 1 on calling, clears __mul_32u__0000F_1_i, then clears RP0 (although it is already cleared).


The problem only occurs if the first argument is a constant.


Example code:

#include <system.h>


//dummy global

char dummy[ 83 ];


unsigned char test( unsigned char multiplier )


unsigned long result;


//problem only appears when first arg is constant

result = 2000 * (unsigned long)multiplier;

return (unsigned char)result;



void main()


dummy[0] = 1;

test( 200 );

dummy[0] = 2;




Expected behaviour:

Bank 1 should be selected before clearing __mul_32u__0000F_1_i, or before entering __mul_32u__0000F.


Is the problem 100% reproduceable:



IDE version: 6.20

Compiler: BoostC

Compiler version: 6.21

Target device: PIC16F876

OS: Win2K

Link to post
Share on other sites
I tried the code you posted and didn't see any error. The variable 'result' gets the expected value of 400000 after the multiplication.


Yes, the result is fine (if I remember rightly), but the data in bank 0 gets corrupted because when __mul_32u__0000F_1_i is cleared, it is in the wrong bank (it should be in bank 1).


The assembly looks like this:


__mul_32u__0000F_arg_a EQU 0x0000007C ; bytes:4

__mul_32u__0000F_arg_b EQU 0x000000A0 ; bytes:4

__mul_32u__0000F_1_i EQU 0x000000A4 ; bytes:1



; { test ; function begin

MOVF test_00000_arg_multiplicand, W



;bank 1


MOVWF __mul_32u__0000F_arg_b

CLRF __mul_32u__0000F_arg_b+D'1'

CLRF __mul_32u__0000F_arg_b+D'2'

CLRF __mul_32u__0000F_arg_b+D'3'




;bank 0


MOVWF __mul_32u__0000F_arg_a

MOVLW 0x07

MOVWF __mul_32u__0000F_arg_a+D'1'

CLRF __mul_32u__0000F_arg_a+D'2'

CLRF __mul_32u__0000F_arg_a+D'3'


;still in bank 0


CALL __mul_32u__0000F




; { __mul_32u_32u ; function begin


; still in bank 0, and yet __mul_32u__0000F_1_i is in bank 1...whatever is in bank 0 at this location gets overwritten.


CLRF __mul_32u__0000F_1_i


CLRF CompTempVarRet0

CLRF CompTempVarRet0+D'1'

CLRF CompTempVarRet0+D'2'

CLRF CompTempVarRet0+D'3'

Link to post
Share on other sites
  • 3 weeks later...

Join the conversation

You are posting as a guest. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

  • Create New...