CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

Writing equivalent of MPASM $+1 in inline assembly
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
vsmguy



Joined: 13 Jan 2007
Posts: 91

View user's profile Send private message Visit poster's website

Writing equivalent of MPASM $+1 in inline assembly
PostPosted: Sun Jul 11, 2010 1:32 pm     Reply with quote

I want to writing "something" that will be equivalent to:

Code:

         #asm
    goto $+1
    goto $+1
         #endasm


this should be 2 words.

This is to generate a delay of 4 ticks.

Conceptually, I could write the one below, but waste 2 words

Code:

         #asm
         NOP
         NOP
         NOP
         NOP
         #endasm


.. or 1

Code:

         #asm
         goto next1
         next1:
            nop
    nop
         #endasm


Any hints on getting the first construct working or any 2 word suggestion without extra variables?
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sun Jul 11, 2010 2:01 pm     Reply with quote

Use a macro. Example:
Code:

#include <16F877.H>
#fuses XT, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP
#use delay(clock=4000000)

#define delay4 \
           NOP \   
           NOP \
           NOP \
           NOP

//==========================================
void main()
{

#asm
movlw 0x55
delay4
movlw 0xAA
#endasm


while(1);
}
   
 
Ttelmah



Joined: 11 Mar 2010
Posts: 19496

View user's profile Send private message

PostPosted: Sun Jul 11, 2010 2:38 pm     Reply with quote

Surely the simplest way, is to let the compiler do it for you?.

delay_cycles(4);

This generates two jumps, to give 4 cycles, and two words used, exactly as required.
Code:

....................    delay_cycles(4);
00E3:  GOTO   0E4
00E4:  GOTO   0E5


Best Wishes
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sun Jul 11, 2010 2:42 pm     Reply with quote

I assumed he wanted to embed a delay in an #asm block. I could be wrong.
Ttelmah



Joined: 11 Mar 2010
Posts: 19496

View user's profile Send private message

PostPosted: Sun Jul 11, 2010 3:01 pm     Reply with quote

True.
Except of course, that even 'in an assembler block', there is no reason really, not to just have an endasm, the delay, and another asm. Could even be done as a macro.
That the delay gives exactly the code he wants, would seem to make this the ideal choice. Smile

Best Wishes
vsmguy



Joined: 13 Jan 2007
Posts: 91

View user's profile Send private message Visit poster's website

PostPosted: Sun Jul 11, 2010 5:59 pm     Reply with quote

WHOA! We had a delay_cycles function?

:-O

Damn... should have read the manual more carefully.

By the way - do you guys know that delays more than 153uS are inaccurate in CCS C?

Delays till 153uS are accurate, but after that 0.3% error creeps in.

I am not sure *why* CCS has used the kind of code they use in the delay subroutine that get generated above 153uS - there were *much* faster and 100% accurate ways!

Has some one analyzed the delay code in CCS C?

Otherwise, maybe I will share my findings and we can take that forward ( will there be people interested in such a kind of thing? )
vsmguy



Joined: 13 Jan 2007
Posts: 91

View user's profile Send private message Visit poster's website

PostPosted: Sun Jul 11, 2010 6:04 pm     Reply with quote

PCM programmer wrote:
I assumed he wanted to embed a delay in an #asm block. I could be wrong.


Your assumption is correct - however, I wanted a *smaller* version of 4 NOPs that would take just as much time.

Do you know how? ( delay_cycles is cool for now )
Ttelmah



Joined: 11 Mar 2010
Posts: 19496

View user's profile Send private message

PostPosted: Mon Jul 12, 2010 4:28 am     Reply with quote

The nearest I can think of, would be (as a standalone function):
Code:

#inline
void delay4(void) {
#asm
   GOTO inner1
inner1:
   GOTO inner2
inner2:
#endasm
}

Or just the lines between #asm, and #endasm, if in an existing assembler block.

Best Wishes
vsmguy



Joined: 13 Jan 2007
Posts: 91

View user's profile Send private message Visit poster's website

PostPosted: Mon Jul 12, 2010 11:48 am     Reply with quote

Ah - so no goto $+1 shortcut in the embedded asm in PIC C.

Not a problem though - we can always use labels :-)
vsmguy



Joined: 13 Jan 2007
Posts: 91

View user's profile Send private message Visit poster's website

PostPosted: Tue Jul 13, 2010 5:30 am     Reply with quote

Ttelmah wrote:
The nearest I can think of, would be (as a standalone function):
Code:

#inline
void delay4(void) {
#asm
   GOTO inner1
inner1:
   GOTO inner2
inner2:
#endasm
}

Or just the lines between #asm, and #endasm, if in an existing assembler block.

Best Wishes


I don't know what I am doing wrong, but when I use the suggested code in isolation, it gets assembled correctly :

Code:
#inline
void delay4(void) {
#asm
   GOTO inner1
inner1:
   GOTO inner2
inner2:
#endasm
}

is correctly assembled as 2 gotos:

Code:
.................... void delay4(void) { 
.................... #asm 
....................    GOTO inner1 
*
0172:  GOTO   173
.................... inner1: 
....................    GOTO inner2 
0173:  GOTO   174
.................... inner2: 
.................... #endasm 
.................... } 


However, when I put this in a larger function, the assembled code not only has 1 goto instead of the expected 2, but the code goes into an infinite loop/hangs!

Here is the piece of code I am talking about:

Code:
#inline
void delay_ticks()
{
   unsigned int8 CounterA = 74;
   unsigned int8 CounterB = 2;
   
#asm
loop:
   decfsz   CounterA,1
   goto   loop
   decfsz   CounterB,1
   goto   loop

   GOTO inner1
inner1:
   GOTO inner2
inner2:

#endasm

   //delay_cycles( 4 );
}


.. and here is how it gets assembled:

Code:
.................... #inline
.................... void delay_ticks()
.................... {
*
0174:  MOVLW  4A
0175:  MOVWF  21
0176:  MOVLW  02
0177:  MOVWF  22
....................    
....................    unsigned int8 CounterA = 74;
....................    unsigned int8 CounterB = 2;
....................    
.................... #asm
.................... loop:
....................    decfsz   CounterA,1
0178:  DECFSZ 21,F
....................    goto   loop
0179:  GOTO   178
....................    decfsz   CounterB,1
017A:  DECFSZ 22,F
....................    goto   loop
017B:  GOTO   178
.................... 
....................    GOTO inner1 
.................... inner1: 
....................    GOTO inner2 
017C:  GOTO   17D
.................... inner2: 
.................... #endasm
.................... 
....................    //delay_cycles( 4 );
.................... }

*
017D:  CLRF   10
....


What gives?

1. Why is the second goto missing in the later function?
2. Why does the loop hang - although, from reading the code, things do not look out of the ordinary?
Ttelmah



Joined: 11 Mar 2010
Posts: 19496

View user's profile Send private message

PostPosted: Tue Jul 13, 2010 6:56 am     Reply with quote

You need:
Code:

#inline
void delay_ticks() {
   unsigned int8 CounterA = 74;
   unsigned int8 CounterB = 2;
   
#asm
loop:
   decfsz   CounterA,1
   goto   loop
   decfsz   CounterB,1
   goto   loop
#endasm
#asm ASIS
   GOTO inner1
inner1:
   GOTO inner2
inner2:
#endasm
}

The problem is that the optimiser sees the second jump and says 'this is a waste of time'....

Best Wishes
vsmguy



Joined: 13 Jan 2007
Posts: 91

View user's profile Send private message Visit poster's website

PostPosted: Tue Jul 13, 2010 7:14 am     Reply with quote

Ttelmah wrote:

The problem is that the optimiser sees the second jump and says 'this is a waste of time'....


In that case why does this work correctly:

Code:
#inline
void delay4(void) {
#asm
   GOTO inner1
inner1:
   GOTO inner2
inner2:
#endasm
}


is correctly assembled as 2 gotos:


Code:
.................... void delay4(void) { 
.................... #asm 
....................    GOTO inner1 
*
0172:  GOTO   173
.................... inner1: 
....................    GOTO inner2 
0173:  GOTO   174
.................... inner2: 
.................... #endasm 
.................... } 
vsmguy



Joined: 13 Jan 2007
Posts: 91

View user's profile Send private message Visit poster's website

PostPosted: Thu Jul 15, 2010 6:23 pm     Reply with quote

Well?

:-)
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Thu Jul 15, 2010 8:29 pm     Reply with quote

Without detailed knowledge of the compiler's internals we can only guess why the optimization is not performed in all situations, but it is not a bug. Not the most optimal code either, but creating the perfect optimizer is extremely difficult and this is where the difference between good and better compilers becomes visible.

If you use the ASIS directive, the code should always be generated as you have coded. If not, that's a bug and you should report it to CCS.
equack



Joined: 21 Sep 2009
Posts: 21

View user's profile Send private message

PostPosted: Mon Sep 27, 2010 7:28 pm     Reply with quote

WHAT? The compiler optimizes my inline assembly code by default?
That's terrible. Inline assembly is for getting the PIC to do _exactly_ what you want. <sigh>
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group