Jump to content
Sign in to follow this  
djulien

Pclath Is Not Being Updated

Recommended Posts

Bug description:

The compiler correctly inserts a MOVLP before calling a function in another page, but sometimes it does *not* change it back after the function returns. This causes execution to jump to a random or invalid location, which of course causes various other problems.

 

Example code:

#include <system.h>

//example function located on another code page:
//this example is a lookup function, but the problem can occur with other types of functions also.
//a fixed address is used here to force the problem to occur, but it can also happen when the compiler chooses the address
void lookup(void) @ 0x800
{
//pclath<5:0> needs to be correct for this lookup function to work; it's already correct in this example
asm addwf _pcl, F
asm retlw 1<<0;
asm retlw 1<<1;
asm retlw 1<<2;
asm retlw 1<<3;
asm retlw 1<<4;
asm retlw 1<<5;
asm retlw 1<<6;
asm retlw 1<<7;
}

void main(void)
{
asm movlw 5; //load WREG with lookup value
lookup();
asm andlw 0xaa;  //example instruction to set up "if" condition below; can be anything here
if (status.Z) porta = 2;  //conditional statement that needs a jump
else porta = 3;	//another statement that needs a jump
trisa = 0;	//example instruction to continue execution; can be anything here
}

 

The code generated for main() is as follows:

MOVLW 0x05
MOVLP 0x08  ;//correct; compiler knows that function is on another code page
CALL lookup_00000
ANDLW 0xAA
//compiler should put a MOVLP 0 here, but it doesn't
BTFSS gbl_status,2
GOTO label1	;//this will jump to the wrong location!
MOVLW 0x02
MOVLB 0x00
MOVWF gbl_porta
GOTO label2	;//this will jump to the wrong location!
label1
MOVLW 0x03
MOVLB 0x00
MOVWF gbl_porta
label2
MOVLB 0x01
CLRF gbl_trisa
RETURN

 

The example above is a simple function, but the problem is occurring in a much larger program that I have, and it is very tedious to look through all the generated code for places where pclath might be wrong and try to correct it manually.

 

 

Expected behavior:

Compiler should insert a MOVLP before any GOTOs in the caller after returning from a function on another code page. (see comment in the code above where there is a missing MOVLP).

 

Is the problem 100% reproduceable:

yes for the example above, but it seems to depend on either the contents or location of the function

 

Compiler:

BoostC

 

Compiler version:

7.10

 

Target device:

PIC16F1827, etc.

 

OS:

Windows XP

 

Please let me know when this fix will be available.

 

thanks

 

don

Edited by djulien

Share this post


Link to post
Share on other sites

Don,

Bug description:

The compiler correctly inserts a MOVLP before calling a function in another page, but sometimes it does *not* change it back after the function returns. This causes execution to jump to a random or invalid location, which of course causes various other problems.

There does indeed appear to be a problem here.

More investigation is required.

I will let you know when there is more news.

 

Regards

Dave

Share this post


Link to post
Share on other sites

Don,

 

Linker is ignoring the retlw in a way that means the PCLATH value on function exit is ignored.

What partly helps is this:

volatile bool x = 0;
void lookup(void) @ 0x700
{
       if( x ) return;
       asm addwf _pcl, F
    asm retlw 1<<0;
    asm retlw 1<<1;
    asm retlw 1<<2;
    asm retlw 1<<3;
    asm retlw 1<<4;
    asm retlw 1<<5;
    asm retlw 1<<6;
    asm retlw 1<<7;
}

 

 

But there are other problems as well.

When PCLATH is used with calls and gotos only bits 4 to 6 are used. When it is used as a result of PCL register modification, bits 0 to 6 are used.

So the PCLATH loading to call your routine is not enough for the "addwf _pcl, F" to get you to the correct address on every occasion.

 

You need extra code to make sure all the extra PCLATH bits (ones not used by call and goto) are set:

 

volatile bool x = 0;
void lookup(void) @ 0x700
{
       if( x ) return;
       asm movlp 0x700
       asm addwf _pcl, F
    asm retlw 1<<0;
    asm retlw 1<<1;
    asm retlw 1<<2;
    asm retlw 1<<3;
    asm retlw 1<<4;
    asm retlw 1<<5;
    asm retlw 1<<6;
    asm retlw 1<<7;
}

 

I hope that helps for now.

I'm working on some proper code fixes to put these problem right, so it will work as you would expect.

It is quite funny how we have gone for many years with no one finding these problems, you must be pushing the envelope more that most users have done.

 

Regards

Dave

Share this post


Link to post
Share on other sites

Don

 

Another asssembly instruction that may help in your code is BRW (only available on PIC16F1xxx devices).

With this you don't need to load up PCLATH and it handles crossing page boundaries.

 

Regards

Dave

Share this post


Link to post
Share on other sites

Linker is ignoring the retlw in a way that means the PCLATH value on function exit is ignored.

What partly helps is this:

volatile bool x = 0;
void lookup(void) @ 0x700
{
	if( x ) return;

 

Well, okay.

 

Another work-around I found was to just put a "pclath = 0" statement after the call to the function (if it's in the first code page). That only takes 1 cycle instead of 2.

 

I guess I can use one of those work-arounds for now while debugging, but I'm trying to write some very tight code so I may need to shuffle the code around to avoid the extra overhead and the problem altogether.

 

But there are other problems as well.

When PCLATH is used with calls and gotos only bits 4 to 6 are used. When it is used as a result of PCL register modification, bits 0 to 6 are used.

So the PCLATH loading to call your routine is not enough for the "addwf _pcl, F" to get you to the correct address on every occasion.

 

You need extra code to make sure all the extra PCLATH bits (ones not used by call and goto) are set:

 

I agree. I usually either set pclath or use an address where the bottom bits are already 0. Sorry, I left that out of the sample code just to show the minimum needed to trigger the problem.

 

Actually, I've noticed that the compiler always uses a multiple of 8 in the movlp instructions. I assume that this is for compatibility with PICs that do not have movlp, but if it were to set the complete value then that would be another way to avoid the need for an extra instruction to set pclath manually (at least for PICs with a movlp instruction).

 

I hope that helps for now.

I'm working on some proper code fixes to put these problem right, so it will work as you would expect.

It is quite funny how we have gone for many years with no one finding these problems, you must be pushing the envelope more that most users have done.

 

If you are working in that section of code anyway, it would be nice to have a way to give the code generator some hints, like wanting a section of code to all fall on the same code page and move it if it doesn't, override bank selects, etc. (maybe some new #pragmas or keywords for that)

 

My code will probably fall outside your normal usage envelope. I have that happen sometimes. (I also ran into several bugs in MPASM, although I didn't take the time to isolate and write them up).

 

Another asssembly instruction that may help in your code is BRW (only available on PIC16F1xxx devices).

With this you don't need to load up PCLATH and it handles crossing page boundaries.

 

I'm wanting this particular code to work with some older 16F688s as well. If I give up that goal then I will definitely use the extended instructions.

 

thanks for your help.

 

don

Edited by djulien

Share this post


Link to post
Share on other sites

Linker is ignoring the retlw in a way that means the PCLATH value on function exit is ignored.

 

Dave,

 

I'm finding other cases where there is not a retlw within the called function, so I think the problem is more widespread than that.

 

don

Share this post


Link to post
Share on other sites

Don,

Linker is ignoring the retlw in a way that means the PCLATH value on function exit is ignored.

I'm finding other cases where there is not a retlw within the called function, so I think the problem is more widespread than that.

Please provide examples so we can make sure these other cases are fixed too.

 

Regards

Dave

Share this post


Link to post
Share on other sites

Your content will need to be approved by a moderator

Guest
You are commenting as a guest. If you have an account, please sign in.
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...
Sign in to follow this  

×