inline asm with constant?

Go To Last Post
6 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello...

I need to make really tight ISR. So I need to do that with inline asm.

But I hit in trouble as I don't know how to pass pointer as constant to ISR.

This is sample code:

volatile uint32_t Pulses;
volatile uint8_t abi;

ISR(PCINT1_vect, ISR_NAKED){
	asm volatile(
		"nop  \n\t"	//Prologue (TODO)
		"ldsr 24,Pulses	\n\t"
		//do something...
		"lds r24,abi					\n\t"
		//do something...
		"nop	\n\t"	//Epilogue (TODO)
		"reti	\n\t"
		:
		: [abi] "r" (&abi), [Pulses] "r" (&Pulses)
	);
}

and this compile as this:

000004b0 <__vector_4>:
 4b0:	27 e1       	ldi	r18, 0x17	; 23
 4b2:	31 e0       	ldi	r19, 0x01	; 1
 4b4:	88 e3       	ldi	r24, 0x38	; 56
 4b6:	91 e0       	ldi	r25, 0x01	; 1
 4b8:	00 00       	nop
 4ba:	80 91 17 01 	lds	r24, 0x0117	; 0x800117 <Pulses>
 4be:	80 91 38 01 	lds	r24, 0x0138	; 0x800138 <abi>
 4c2:	00 00       	nop
 4c4:	18 95       	reti

 

So how to avoid 1'st four lines? They are generated before my ISR prologue and use a lot of registers so prologue need a lot of push/pops. (this is only sample)

 

I need to load 'pulses' and do something and after that I need to do similar with 'abi'. I'd like to use only R24/R25 registers in complete ISR. As every PUSH/POP take a lot of time.

 

I assume that I need to somehow use clobbers (K,L,O) but didn't figured out how.

 

Thanks

 

 

 

 

 

This topic has a solution.
Last Edited: Tue. Nov 23, 2021 - 02:20 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

Why do this with inline Asm? Just put PCINT1_vect into a .S file and you have complete control over the code - just remember to follow the ABI

 

(and if your bit in the middle "// do something.." touches the flags you MUST preserve SREG!)

This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

eslavko wrote:

But I hit in trouble as I don't know how to pass pointer as constant to ISR.

But you already did that with your

        "lds r24,Pulses \n\t"

 

eslavko wrote:
So how to avoid 1'st four lines? They are generated before my ISR prologue

Because that's exactly what you asked for in your input constraints. You don't really need those constraints so just drop them out.

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

...fell stupid. Just need to drop clobbers...

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

if you need speed then perhaps place the pointer in R3:R2 so you can replace the LDS with a MOVW

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

OP probably does not need to load the addresses into registers.

LDS and STS are just as fast as LD and ST.

 

I second the suggestion to use a .S file.

Sometimes clarity favors using inline assembly.

This is not one of them.

 

When you do use inline assembly,

use clobbers sparingly, if at all.

Clobbers constrain avr-gcc's code optimization.

When one is tempted to use a clobber,

a frequently useful workaround is to use in/out

registers tied to an otherwise unused variable.

Moderation in all things. -- ancient proverb