• AVR Freaks

Hot!WREG changed before function parameter is read

Author
Sarva
New Member
  • Total Posts : 5
  • Reward points : 0
  • Joined: 2019/09/16 03:11:15
  • Location: 0
  • Status: offline
2019/09/19 00:26:51 (permalink)
0

WREG changed before function parameter is read

I am using xc8 v2.05 for PIC18F46K22. I have inline assembly in a function:
 
void __section("bootcode") calc_CRC(uint8_t data_Byte)
{
    volatile uint8_t MTEMP = 0;
#asm
    MOVF calc_CRC@data_Byte, W ; Fetch Serial Data
...
#endasm
}
 
I believe the passed parameter is stored in WREG. But the register is used set MPEMP to 0 and value changed before the parameter is used. It works fine if I store the value beforehand...
 
void __section("bootcode") calc_CRC(uint8_t idata_Byte)
{
    volatile uint8_t data_Byte = idata_Byte;
    volatile uint8_t MTEMP = 0;
#asm
    MOVF calc_CRC@data_Byte, W ; Fetch Serial Data
...
#endasm
}
Should'nt  the compiler take care of this?
#1

17 Replies Related Threads

    mbrowning
    USNA79
    • Total Posts : 1537
    • Reward points : 0
    • Joined: 2005/03/16 14:32:56
    • Location: Melbourne, FL
    • Status: offline
    Re: WREG changed before function parameter is read 2019/09/19 09:22:15 (permalink)
    +1 (1)
    Parameters are not passed through WREG. You probably have a banking problem, and coincidence that BSR is set to the same bank as data_Byte at the start of the function.
    When you write inline assembly, the compiler does not take care of bank selection for you.
    Add the banksel directive.

    #asm
       banksel calc_CRC@data_Byte   ;
       MOVF calc_CRC@data_Byte, W ; Fetch Serial Data
    #endasm

    Correction - The first parameter is passed by register if it is byte-sized.
    post edited by mbrowning - 2019/09/19 11:25:40

    Go Navy! Beat Army!
    #2
    1and0
    Access is Denied
    • Total Posts : 9771
    • Reward points : 0
    • Joined: 2007/05/06 12:03:20
    • Location: Harry's Gray Matter
    • Status: offline
    Re: WREG changed before function parameter is read 2019/09/19 10:20:07 (permalink)
    +1 (1)
    When the first parameter is an 8-bit type, which is in this case, then it is passed into the function in WREG. However, the compiler does not "see" what is going on inside #asm/#endasm, so it's probably got optimized out for being "unused" by the optimizer.
     
    #3
    pcbbc
    Super Member
    • Total Posts : 1332
    • Reward points : 0
    • Joined: 2014/03/27 07:04:41
    • Location: 0
    • Status: offline
    Re: WREG changed before function parameter is read 2019/09/19 10:21:55 (permalink)
    +1 (1)
    mbrowningParameters are not passed through WREG.

    Really?
     
    I think you'll find they are passed in WREG when there's only a single byte parameter.
    The function prolog may immediately store W reg on the compiled stack, but that's a different matter.
     
    Confirmed with...
    #include <xc.h>
    #include <stdint.h>

    void test(uint8_t x)
    {
        PORTA = x;
    }

    void main() {
        test(0x01);
        test(0x02);
    }

    #4
    mbrowning
    USNA79
    • Total Posts : 1537
    • Reward points : 0
    • Joined: 2005/03/16 14:32:56
    • Location: Melbourne, FL
    • Status: offline
    Re: WREG changed before function parameter is read 2019/09/19 11:57:05 (permalink)
    +1 (1)
    1and0
    When the first parameter is an 8-bit type, which is in this case, then it is passed into the function in WREG. However, the compiler does not "see" what is going on inside #asm/#endasm, so it's probably got optimized out for being "unused" by the optimizer.

    Indeed it is as specified in section 4.86 of the User's Guide (C99 version).
     
    Banking could still be a potential problem. Looking back at a number of map files, most projects fit all the cstack inside COMRAM. I have one project however that had enough auto/parameter variables to spill out of the access portion of bank 0.

    Go Navy! Beat Army!
    #5
    ric
    Super Member
    • Total Posts : 23893
    • Reward points : 0
    • Joined: 2003/11/07 12:41:26
    • Location: Australia, Melbourne
    • Status: online
    Re: WREG changed before function parameter is read 2019/09/19 13:24:28 (permalink)
    +1 (1)
    Change
    void __section("bootcode") calc_CRC(uint8_t data_Byte)
    {
        volatile uint8_t MTEMP = 0;
    #asm
        MOVF calc_CRC@data_Byte, W ; Fetch Serial Data
    ...
    #endasm
    }

    to
    void __section("bootcode") calc_CRC(volatile uint8_t data_Byte)
    {
        volatile uint8_t MTEMP;
    #asm
    ;W already contains the input parameter. Clear MTEMP yourself.
    ...
    #endasm
    }


    I also post at: PicForum
    Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
    NEW USERS: Posting images, links and code - workaround for restrictions.
    To get a useful answer, always state which PIC you are using!
    #6
    Sarva
    New Member
    • Total Posts : 5
    • Reward points : 0
    • Joined: 2019/09/16 03:11:15
    • Location: 0
    • Status: offline
    Re: WREG changed before function parameter is read 2019/09/19 21:47:46 (permalink)
    0
    Thanks for all the replies.
    I tried this. It wont compile if MTEMP is not initialized. It gives the error: undefined symbol "calc_CRC@MTEMP"
    btw, I am using C90 because many Assembly directives are not supported in C99
    #7
    1and0
    Access is Denied
    • Total Posts : 9771
    • Reward points : 0
    • Joined: 2007/05/06 12:03:20
    • Location: Harry's Gray Matter
    • Status: offline
    Re: WREG changed before function parameter is read 2019/09/19 23:48:56 (permalink)
    +1 (1)
    Sarva
    I tried this. It wont compile if MTEMP is not initialized. It gives the error: undefined symbol "calc_CRC@MTEMP"
    btw, I am using C90 because many Assembly directives are not supported in C99

    Post your code.  XC8 C99 mode does not support #asm/#endasm; however, it does support __asm().
    #8
    Sarva
    New Member
    • Total Posts : 5
    • Reward points : 0
    • Joined: 2019/09/16 03:11:15
    • Location: 0
    • Status: offline
    Re: WREG changed before function parameter is read 2019/09/20 01:20:49 (permalink)
    0
    The same is the case for all variables declared in C and used in assembly.
    this is just one such routine...
     

    void __section("bootcode") calc_CRC(uint8_t idata_Byte)
    {
        volatile uint8_t data_Byte = idata_Byte;
        volatile uint8_t MTEMP;
    #asm
        BANKSEL(calc_CRC@MTEMP)
        CLRF calc_CRC@MTEMP
        MOVLW 8
        MOVWF calc_CRC@MTEMP+0
        MOVF calc_CRC@data_Byte, W ; Fetch Serial Data
        BANKSEL(_CRC16)
        XORWF _CRC16+1, F ; Xor Data with CRC.Lo
     
    CALC_2: BCF STATUS, 0 ;clear carry bit
       RRCF _CRC16+0, F ; 16bit Shift-Right
       RRCF _CRC16+1, F
       BNC CALC_4  ; Cy = 0
       ...
    CALC_4: DECFSZ calc_CRC@MTEMP+0, F ; Loop for 8 Bits Max = 102inst = 8*12+6
       BRA CALC_2
    #endasm
    }
     
    this gives error: (800) undefined symbol "calc_CRC@MTEMP"
    #9
    ric
    Super Member
    • Total Posts : 23893
    • Reward points : 0
    • Joined: 2003/11/07 12:41:26
    • Location: Australia, Melbourne
    • Status: online
    Re: WREG changed before function parameter is read 2019/09/20 04:05:20 (permalink)
    +1 (1)
    Do you have some spare locations in the global area?
    I've verified that the parameter in W survives to the XORWF instruction with this code.
    Edit: This was for PIC16. Hopefully for PIC18, "near" will put it into the Access bank.

    near uint8_t MTEMP;    //make sure "Address qualifiers" setting is "Require"

    void __section("bootcode") calc_CRC(volatile uint8_t idata_Byte)
    {   
    #asm
        BANKSEL (_CRC16)
        CLRF _MTEMP
        BSF  _MTEMP,3    ;manufacture "8" without corrupting W
        XORWF _CRC16+1, F ; Xor Data with CRC.Lo


    post edited by ric - 2019/09/20 04:06:30

    I also post at: PicForum
    Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
    NEW USERS: Posting images, links and code - workaround for restrictions.
    To get a useful answer, always state which PIC you are using!
    #10
    1and0
    Access is Denied
    • Total Posts : 9771
    • Reward points : 0
    • Joined: 2007/05/06 12:03:20
    • Location: Harry's Gray Matter
    • Status: offline
    Re: WREG changed before function parameter is read 2019/09/20 06:33:50 (permalink)
    0
    Sarva
    this gives error: (800) undefined symbol "calc_CRC@MTEMP"

    That looks like a compiler bug, please submit a support ticket to Microchip.
     
    As a workaround, try this
    uint8_t MTEMP;
    void __section("bootcode") calc_CRC(uint8_t data_Byte)
    {
    #asm
        BANKSEL(_CRC16)
        XORWF _CRC16+1, F ; Xor Data with CRC.Lo

     
        BANKSEL(_MTEMP)
        MOVLW 8
        MOVWF _MTEMP+0
     
    CALC_2: BCF STATUS, 0 ;clear carry bit
       RRCF _CRC16+0, F ; 16bit Shift-Right
       RRCF _CRC16+1, F
       BNC CALC_4  ; Cy = 0
       ; ...
    CALC_4: DECFSZ _MTEMP+0, F ; Loop for 8 Bits Max = 102inst = 8*12+6
       BRA CALC_2
    #endasm
    }

     
    If you want to use calc_CRC@data_Byte in the function, try this
    uint8_t MTEMP;

    void __section("bootcode") calc_CRC(uint8_t data_Byte)
    {
    #asm
        BANKSEL(_CRC16)
        XORWF _CRC16+1, F ; Xor Data with CRC.Lo

     
        BANKSEL(_MTEMP)
        MOVLW 8
        MOVWF _MTEMP+0
     
    CALC_2: BCF STATUS, 0 ;clear carry bit
        RRCF _CRC16+0, F ; 16bit Shift-Right
        RRCF _CRC16+1, F
        BNC CALC_4  ; Cy = 0
        ; ...
    CALC_4: DECFSZ _MTEMP+0, F ; Loop for 8 Bits Max = 102inst = 8*12+6
        BRA CALC_2


        return
    #endasm
        volatile uint8_t dummy = data_Byte;
    }
    post edited by 1and0 - 2019/09/20 06:37:53
    #11
    1and0
    Access is Denied
    • Total Posts : 9771
    • Reward points : 0
    • Joined: 2007/05/06 12:03:20
    • Location: Harry's Gray Matter
    • Status: offline
    Re: WREG changed before function parameter is read 2019/09/20 06:36:14 (permalink)
    0
    Stupid forum software messing up the code tags. :( 
    #12
    NorthGuy
    Super Member
    • Total Posts : 5688
    • Reward points : 0
    • Joined: 2014/02/23 14:23:23
    • Location: Northern Canada
    • Status: online
    Re: WREG changed before function parameter is read 2019/09/20 06:39:16 (permalink)
    +1 (1)
    I would suggest looking at the disassembly of the call. The compiler is smart. If it thinks the argument is not used, it may not pass the argument at all, especially if you use higher levels of optimization.
     
    #13
    ric
    Super Member
    • Total Posts : 23893
    • Reward points : 0
    • Joined: 2003/11/07 12:41:26
    • Location: Australia, Melbourne
    • Status: online
    Re: WREG changed before function parameter is read 2019/09/20 14:53:31 (permalink)
    +2 (2)
    NorthGuy
    I would suggest looking at the disassembly of the call. The compiler is smart. If it thinks the argument is not used, it may not pass the argument at all, especially if you use higher levels of optimization.

    Been there, done that.
    If you add a "volatile" qualifier to the parameter list (as my examples do), it will always pass it.

    I also post at: PicForum
    Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
    NEW USERS: Posting images, links and code - workaround for restrictions.
    To get a useful answer, always state which PIC you are using!
    #14
    Sarva
    New Member
    • Total Posts : 5
    • Reward points : 0
    • Joined: 2019/09/16 03:11:15
    • Location: 0
    • Status: offline
    Re: WREG changed before function parameter is read 2019/09/22 22:25:02 (permalink)
    0
    The value is passed in WREG and it is overwritten for MTEMP whether the parameter has volatile mentioned or not. I verified from the Assembly listing. The optimization level is set at 0!
    I am using a work around. I have raised a ticket for the compiler error and the loss of parameter. Will keep posted. 
    #15
    ric
    Super Member
    • Total Posts : 23893
    • Reward points : 0
    • Joined: 2003/11/07 12:41:26
    • Location: Australia, Melbourne
    • Status: online
    Re: WREG changed before function parameter is read 2019/09/22 22:28:01 (permalink)
    +1 (1)
    Sarva
    The value is passed in WREG and it is overwritten for MTEMP whether the parameter has volatile mentioned or not. I verified from the Assembly listing.

    That means you still have MTEMP defined as a local variable which has to be initialised.
    That is specifically what 1and0 and I have NOT been doing.
    Your ticket will come back with "Not a bug".
     
     
    post edited by ric - 2019/09/22 22:36:37

    I also post at: PicForum
    Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
    NEW USERS: Posting images, links and code - workaround for restrictions.
    To get a useful answer, always state which PIC you are using!
    #16
    Sarva
    New Member
    • Total Posts : 5
    • Reward points : 0
    • Joined: 2019/09/16 03:11:15
    • Location: 0
    • Status: offline
    Re: WREG changed before function parameter is read 2019/09/22 22:59:19 (permalink)
    0
    Not using a local variable is a work around right? It just happens that the current routine needs only 1 local variable! It will be a messy code with all global temporary variables.
    I thought compiler error was a bug. Let's see what they say
    #17
    pcbbc
    Super Member
    • Total Posts : 1332
    • Reward points : 0
    • Joined: 2014/03/27 07:04:41
    • Location: 0
    • Status: offline
    Re: WREG changed before function parameter is read 2019/09/22 23:25:36 (permalink)
    +2 (2)
    It was already “messy code” as soon as you typed #asm
    #18
    Jump to:
    © 2019 APG vNext Commercial Version 4.5