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;

while(1);

}

 

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:

Yes.

 

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_00000

; { test ; function begin

MOVF test_00000_arg_multiplicand, W

BSF STATUS, RP0

 

;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'

MOVLW 0xD0

BCF STATUS, RP0

 

;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

----snip----

 

__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

BCF STATUS, RP0

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.

Guest
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.

Loading...
×
×
  • Create New...