IPB

Welcome Guest ( Log In | Register )

> Inline _asm Bug., The optimiser removes my code!
neomech
post Jun 25 2007, 09:08 PM
Post #1


Newbrie


Group: Members
Posts: 2
Joined: 20-September 06
From: UK
Member No.: 1,639



hi,
I been having problems with using inline asm, the some of my code being removed from the compiled output.

the following function:
CODE
void servoOn_broken1 (unsigned char servoIndex)
{
    _asm
    {
        MOVF  _servoIndex, W
        ADDWF _servoIndex, W
        ADDWF _pcl, F
        BSF _portb,0
        RETURN
        BSF _portb,1
        RETURN
        BSF _portb,2
        RETURN
        BSF _portb,3
    }
}

compiles (assembles?) as:
CODE
    ORG 0x00000036
0036        servoOn_br_00014
0036       ; { servoOn_broken1; function begin
0036  0866      MOVF servoOn_br_00014_arg_servoIndex, W
0037  0766      ADDWF servoOn_br_00014_arg_servoIndex, W
0038  0782      ADDWF gbl_pcl, F
0039  1406      BSF gbl_portb,0
003A  0008      RETURN
003B       ; } servoOn_broken1 function end

I suspect what is happening is that the optimiser is detecting that part of the code is "unreachable" and removing it.
However it is not unreachable as I'm modifying the Program Counter based on the parameter, thus implementing a fast (and also more importantly - constant speed) switch statement.

using Gotos results in similar output:
CODE
void servoOn_broken2 (unsigned char servoIndex)
{
    _asm
    {
        MOVF  _servoIndex, W
        ADDWF _servoIndex, W
        ADDWF _pcl, F
        BSF _portb,0
        GOTO end
        BSF _portb,1
        GOTO end
        BSF _portb,2
        GOTO end
        BSF _portb,3
    end:
    }
}

thus:
CODE
    ORG 0x00000031
0031        servoOn_br_00015
0031       ; { servoOn_broken2; function begin
0031  0866      MOVF servoOn_br_00015_arg_servoIndex, W
0032  0766      ADDWF servoOn_br_00015_arg_servoIndex, W
0033  0782      ADDWF gbl_pcl, F
0034  1406      BSF gbl_portb,0
0035  0008      RETURN
0036       ; } servoOn_broken2 function end

I have come up with a workaround for this:
CODE
#define ASM_RET data 8
void servoOn (unsigned char servoIndex)
{
    _asm
    {
        MOVF  _servoIndex, W
        ADDWF _servoIndex, W
        ADDWF _pcl, F
        BSF _portb,0
        ASM_RET
        BSF _portb,1
        ASM_RET
        BSF _portb,2
        ASM_RET
        BSF _portb,3
    }
}

This encodes the return statement as a data declaration, so it is left intact:
CODE
    ORG 0x0000003B
003B        servoOn_00000
003B       ; { servoOn; function begin
003B  0866      MOVF servoOn_00000_arg_servoIndex, W
003C  0766      ADDWF servoOn_00000_arg_servoIndex, W
003D  0782      ADDWF gbl_pcl, F
003E  1406      BSF gbl_portb,0
003F  0008      DW 0x0008
0040  1486      BSF gbl_portb,1
0041  0008      DW 0x0008
0042  1506      BSF gbl_portb,2
0043  0008      DW 0x0008
0044  1586      BSF gbl_portb,3
0045  0008      RETURN
0046       ; } servoOn function end


However, fixing the version with Gotos in is a little harder (as Jumps are absolute!) so very hard to compute, and the Goto version is needed as I wish to in-line the function.

btw I am using v6.70 and my target is a 16f88..

Any ideas for a workaround/fix?

Thanks,

Lee.
update SourceBoost release 6.97 is available.
Download Now
Go to the top of the page
 
+Quote Post
 
Start new topic
Replies
Dave
post Jun 27 2007, 11:05 AM
Post #2


Super Maniac
*****

Group: Administrators
Posts: 1,830
Joined: 28-September 04
From: UK
Member No.: 469



neomech,
QUOTE (neomech @ Jun 25 2007, 10:08 PM) *
However, fixing the version with Gotos in is a little harder (as Jumps are absolute!) so very hard to compute, and the Goto version is needed as I wish to in-line the function.

btw I am using v6.70 and my target is a 16f88..

Any ideas for a workaround/fix?
for getting the problem with optimisation, your code is dangerous because there is no way to place a function at a fixed address. You function could end up crossing a code page boundary which will then mean it wouldn't work as expected.

What others have done in this situation is to use #pragma DATA, as it places fixed data in ROM at fixed addresses. The only thing you will need to do in determine the opcode for the instructions and add this data to the #pragma DATA (not ideal I know).

CODE
#pragma DATA, 0xFF0, opcodedata, opcodedata, opcode data
....
void main()
{
    call 0xFF0
}


Hope that helps.

Regards
Dave
Go to the top of the page
 
+Quote Post
neomech
post Jun 27 2007, 12:16 PM
Post #3


Newbrie


Group: Members
Posts: 2
Joined: 20-September 06
From: UK
Member No.: 1,639



QUOTE (Dave @ Jun 27 2007, 12:05 PM) *
for getting the problem with optimisation, your code is dangerous because there is no way to place a function at a fixed address. You function could end up crossing a code page boundary which will then mean it wouldn't work as expected.

What others have done in this situation is to use #pragma DATA, as it places fixed data in ROM at fixed addresses. The only thing you will need to do in determine the opcode for the instructions and add this data to the #pragma DATA (not ideal I know).

CODE
#pragma DATA, 0xFF0, opcodedata, opcodedata, opcode data
....
void main()
{
    call 0xFF0
}


Hope that helps.

Regards
Dave


Thanks for the reply Dave,

I am aware of the code paging issues, but I dont have enough code to move into a second page... (yet!)
but having said that, the contents of an _asm block should be left intact shouldnt they? and not have instuctions removed? this is thing that is causing me problems, the removal of the code...,

would it be possible to have a flag on the linker so that it does not split functions across page boundries.... this I suppose would allow for PCL hackery like this.... :-)

Lee.
Go to the top of the page
 
+Quote Post
Dave
post Jun 27 2007, 03:05 PM
Post #4


Super Maniac
*****

Group: Administrators
Posts: 1,830
Joined: 28-September 04
From: UK
Member No.: 469



neomech,
QUOTE (neomech @ Jun 27 2007, 01:16 PM) *
I am aware of the code paging issues, but I dont have enough code to move into a second page... (yet!)
but having said that, the contents of an _asm block should be left intact shouldnt they? and not have instuctions removed? this is thing that is causing me problems, the removal of the code...,
Change _asm to asm and then no dead code is removed.

Regards
Dave
Go to the top of the page
 
+Quote Post

Posts in this topic
- neomech   Inline _asm Bug.   Jun 25 2007, 09:08 PM
- - Dave   neomech, QUOTE (neomech @ Jun 25 2007, 10...   Jun 27 2007, 11:05 AM
- - neomech   QUOTE (Dave @ Jun 27 2007, 12:05 PM) for ...   Jun 27 2007, 12:16 PM
- - Dave   neomech, QUOTE (neomech @ Jun 27 2007, 01...   Jun 27 2007, 03:05 PM


Reply to this topicStart new topic
1 User(s) are reading this topic (1 Guests and 0 Anonymous Users)
0 Members:

 



Lo-Fi Version Time is now: 3rd September 2010 - 02:47 PM