PIC: pic-as loop with labelless relative branch bug - Page 1
Forum section: electronics / general

author: Dabbot
author_rank: Regular Contributor
timestamp: April 30, 2021, 07:53:25 am
content: Just letting you all know about this obscure bug I ran into.Basically, if you use FCALL, then set up a loop using DECFSZ followed by BRA $ - OFFSET, instead of BRA LABEL, the assembler will quietly precede DECFSZ with a MOVLP instruction and change the intended return point of the loop.This makes no sense whatsoever because PCLATH is corrected by the FCALL macro already, and the BRA / BRW instructions do not involve PCLATH at all.Attached is the assembly, and the resultant list file demonstrating the bug, specifically line 31 (37) in the list file. I've reproduced this on V2.31 and V2.32 so far.Edit: Reproduced the bug with V2.32 with list file attached.

author: jpanhalt
author_rank: Super Contributor
timestamp: April 30, 2021, 11:38:41 am
content: Interesting. Anxious to see others demonstrate it.Just FYI, I tried it in MPLAB 8.92 using LCALL, and it works entirely as expected. That is, if the destination is on the same page, PCLATH stays on that page (i.e., movlp 0 is in the disassembly). If the destination is moved to 0x0100, then movlp 1 is executed, PCLATH is set to 1, and is not reset. In either case, it returns to the proper place. NB: FCALL is not recognized in that version of MPASM.

author: Dabbot
author_rank: Regular Contributor
timestamp: April 30, 2021, 01:11:40 pm
content: Quote from: jpanhalt on April 30, 2021, 11:38:41 amThis is pic-as (xc8), not MPASM. Completely different beasts, so it's understandable that it works as expected on your end.The bug is not with FCALL itself, but further down where I'm using DECFSZ and BRA to form a loop. For some reason pic-as sees the need to insert a MOVLP instruction right before the DECFSZ, and thus causes the loop to malfunction because the return point has effectively shifted up one place, and pic-as has not accounted for that.If I comment out the FCALL, the extra MOVLP instruction disappears.If I leave the FCALL there and use a label instead of an offset to form the loop, the extra MOVLP instruction disappears.

author: jpanhalt
author_rank: Super Contributor
timestamp: April 30, 2021, 01:37:58 pm
content: I understood that the two assemblers were different. That's why I made it an FYI in case you had not tried the equivalent with the earlier version.I agree, it seems odd that an additional movlp gets added there, unless that was supposed to be an "enhancement." I would have added it before the return in the FCALL'd routine. Does it still add the movlp to the DECFSZ routine if you reset PCLATH before the return?

author: Dabbot
author_rank: Regular Contributor
timestamp: April 30, 2021, 01:50:46 pm
content: Quote from: jpanhalt on April 30, 2021, 01:37:58 pmFCALL handles the page selection automatically, so there's no need to do it manually unless some funny business is going on. It expands to:MOVLP TARGET_PAGECALL TARGETMOVLP CURRENT_PAGEQuote from: jpanhalt on April 30, 2021, 01:37:58 pmYep. I've tested manually placing an "MOVLP 0" in the function and after the FCALL macro. It does not change the behavior.

author: jpanhalt
author_rank: Super Contributor
timestamp: April 30, 2021, 01:58:24 pm
content: That does seem odd that it would place the movlp before the DECFSZ rather then right after the call.Sorry I can't help. I have avoided the new "full-featured" versions so far. Don't know how long I will be able to do that though.

author: Dabbot
author_rank: Regular Contributor
timestamp: April 30, 2021, 02:24:09 pm
content: Quote from: jpanhalt on April 30, 2021, 01:58:24 pmThe MOVLP right before the DECFSZ is in addition to the correctly placed MOVLP instructions surrounding the CALL instruction. It's completely out of place and seems to have something to do with the loop construction, because it will appear consistently before the DECFSZ no matter how many instructions are between the FCALL and the loop.Quote from: jpanhalt on April 30, 2021, 01:58:24 pmThat's fine. Thanks for checking.I can see why people are put off by Microchip's "new way forward", but give it a shot sooner rather than later is my recommendation. MYself and others here can help answer questions.

author: DrG
author_rank: Super Contributor
timestamp: April 30, 2021, 04:04:27 pm
content: I rejected trying to learn as, at least so far. I am trying to get a handle on why it is doing that. Quite frankly, I do not umm appreciate the new concept of a psect and that is when I said, no, I don't need to do this now. As long as I can still run mpasm in some coexisting older version of x ide, I will live.So,by more of a question than anything else, what does this mean from the manual and is there any chance that you (or them) are doing it without knowing it? IOW: you have not defined the range/size of that psect, have you?The fcall and ljmp instructions assume that the psect that contains them is smaller than a page. Do not use theseinstructions to transfer control to a label in the current psect if it is larger than a page.

author: Dabbot
author_rank: Regular Contributor
timestamp: April 30, 2021, 04:30:02 pm
content: Quote from: DrG on April 30, 2021, 04:04:27 pmThe assembler (pic-as) aligns psects as it sees fit and prevents them (size or placement) from crossing page boundaries, given correct configuration for the target chip. I only specify the placement when required. I.e., psects for the reset and interrupt vectors.The above from the manual is correct, but since the assembler will generally prevent psects from crossing page boundaries, it doesn't come into play. Normally, you do not use those macros in the same psect as they generate unnecessary instructions to handle page selection when it is not required.In the code I attached, I didn't bother placing the function in another psect because it doesn't matter for the purposes of replicating the bug.Edit: To clarify, as I was half asleep when I originally wrote my response.

author: jpanhalt
author_rank: Super Contributor
timestamp: April 30, 2021, 04:42:41 pm
content: Longshot guess:What if you replace those NOP's in the loop with something else that does almost nothing, like movf TEMP,f ? Does the bug still occur?

author: Dabbot
author_rank: Regular Contributor
timestamp: May 01, 2021, 12:31:20 am
content: Quote from: jpanhalt on April 30, 2021, 04:42:41 pmNo change.

author: jpanhalt
author_rank: Super Contributor
timestamp: May 01, 2021, 10:59:51 am
content: That glitch bothers me. In the years I have played with PICs, I have found a few inconsistencies, but never anything like that. Of course, you have a work around, just as with the inconsistencies.Is that return point always just 2 instructions off or is it always to the same DECFSZ instruction? That is, what happens if there are 4 NOP's after the call. Can you view the hardware stack in simulation like in MPASM? When does the wrong return PCL appear?

author: Dabbot
author_rank: Regular Contributor
timestamp: May 01, 2021, 12:00:51 pm
content: Quote from: jpanhalt on May 01, 2021, 10:59:51 amIt doesn't seem to matter how many instructions follow the FCALL. It will always stick a MOVLP in right before the DECFSZ instruction.I tried replacing DECFSZ with INCFSZ, BTFSS, BTFSC and it does the same thing: stick a sneaky MOVLP instruction before it.Quote from: jpanhalt on May 01, 2021, 10:59:51 amThere's no point going into the simulator, since the bug has already been identified as an assembler bug, not a hardware bug. I originally discovered and fixed the problem in a different body of code. What I attached is simply the bare minimum to showcase the bug, after I spent time narrowing it down. There's no need to simulate or load it onto a chip.