why r1 should allways be zero in avr-gcc?

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

why r1 should allways be zero in avr-gcc?

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

Why not ? :-)
A "zeroreg" comes in handy in several situations:
Examples found in avrlibc1.4.2

Comparing a register against zero :  
cpc     siz_hi, __zero_reg__    ; size == 0 ?

Clearing a register : 
mov __tmp_reg__,__zero_reg__

Clearing a variable/location in RAM : 
st      Y,__zero_reg__

e.t.c 
e.t.c ...

/J

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

So, if i writing some multhtreaded application, I can register r1 exlude from thread context, becouse it allways will be zero?

Last Edited: Fri. Jan 13, 2006 - 02:18 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Found the following in macros.inc (in avrlibc...):

Quote:

#ifndef __zero_reg__
#define __zero_reg__ r1
#endif

and

r1 (__zero_reg__ - assumed to always contain 0)

Hmmm ... I remember reading that "Assumption is the mother of all f**kups!" ...

Quote:

So, if i writing some multhtreaded application, I can register r1 exlude from threads context, becouse allways it will be zero?

Wild guess : Yes !
BUT! I'm not familiar enough with AVR-GCC to trust my own judgement in this question :-)

/J

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

No. It is absolutely essential that r1 be included in any context-switching system.

The MUL instruction, for example, uses r1:r0 to hold its results. When MUL is used, the application code is responsible for clearing r1 again as soon as it finishes with the result. That's sufficient for functions that execute, perform a MUL, use the result, then clear r1 before moving on.

But interrupts are a different story -- it is possible that the AVR may service an interrupt immediately after a MUL and before the result has been interpreted. In such a case, when control passes back to this line of execution, r1 should have its old value maintained.

When an interrupt happens, one of the things you'll see in the default ISR prologue is that r1 will be saved and cleared. After the ISR is finished, r1 is restored before returning. That is done intentionally to account for cases such as MUL in the mainline, while still maintaining access to a "zero" register in the ISR context.

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

As a guess, that might be false economy if you are pre-emptive, leading to very curious failures. Snippets of ASM code or library routines, etc., could take advantage of the fact that R1 is "available", and use it, and restore it before "leaving". For example, any MUL-family instruction will overwrite R1. If not pre-emptive, you might be OK.

Lee

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

Quote:
The MUL instruction, for example, uses r1:r0 to hold its results

A bit funny that they've decided to use R1 as __zero_reg__ by default then ...

Quoting myself:

Quote:

BUT! I'm not familiar enough with AVR-GCC to trust my own judgement in this question

So, benner, if You're still reading this : Don't trust anyone with an ASM avatar in GCC related issues.

/J

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

Wow, great point @lfmorrison on the MUL instruction. I was going to remove all the `push/eor/pop r1`'s from my ISRs and never thought of this case!

 

I would be so nice to save all these cycles and stack space. Seems like a higher register that can only be explicitly changed would have been a better choice for zero_reg?

 

Any reasons why zero_reg must be in R1 (other than arbitrary choice by the compiler writers)?

 

Is there any easy way to tell GCC to use a different register?

 

Thanks!

 

-josh

 

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

Looks like zero_reg is on R17... but only on ATTINY platform?...

 

 

https://github.com/gcc-mirror/gc...

 

#if defined (__AVR_TINY__)
  #define __zero_reg__ r17
  #define __tmp_reg__ r16
 

#else
 
  #define __zero_reg__ r1
  #define __tmp_reg__ r0
#endif  

 

 

Anyone have any idea why this might be the case?

 

-josh

 

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

You're only 11 years late ;-)

 

I would be so nice to save all these cycles and stack space. Seems like a higher register that can only be explicitly changed would have been a better choice for zero_reg?

The choices were made long before AVR cores with MUL instructions were introduced.  The decision was made to keep the existing choices in favour of not breaking existing code.

 

Looks like zero_reg is on R17... but only on ATTINY platform?...

Not all ATtinies.  Some, however, have only registers r16 through r31.  For those, r17 is chosen as __zero_reg__.

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"Read a lot.  Write a lot."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

Last Edited: Thu. Oct 5, 2017 - 09:12 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

And there is no "easy way to tell GCC to use a different register". That would at least mean re-building the run-time libraries.

"He used to carry his guitar in a gunny sack, or sit beneath the tree by the railroad track. Oh the engineers would see him sitting in the shade, Strumming with the rhythm that the drivers made. People passing by, they would stop and say, "Oh, my, what that little country boy could play!" [Chuck Berry]

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

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

> why r1 should allways be zero in avr-gcc?

 

It's not always zero, but when you use it, you may assume it contains 0.

 

For example, after a MUL it usually doesn't contain 0.

 

> So, if i writing some multhtreaded application, I can register r1 exlude from thread context, becouse it allways will be zero?

 

No.  Same applies to R0 and T-Flag of SREG. You'll have to save / restore them so that after a thread context is restored, the values of these registers are the same -- whatever value they might have held before.

avrfreaks does not support Opera. Profile inactive.

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

> Anyone have any idea why this might be the case?

 

Because the ABI says so

 

https://gcc.gnu.org/wiki/avr-gcc...

avrfreaks does not support Opera. Profile inactive.

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

> Anyone have any idea why this might be the case?

 

On older AVRs, the first 16 registers are sort-of "second class registers."  In particular, you can't do immediate-mode arithmetic on them.  This makes the high registers (16-31) more valuable, with the top 8 being even more so (ADDIW works), and the top 6 or fewer being useful as index registers (X/Y/Z)  This makes the low registers less useful, and gcc isn't all that good at using them.  But they do register/register math just fine, and there are no immediate instructions that utilize the carry, so it's handy to have a known zero register for >8bit math:

 ;; 32bit increment
     addiw r28, 1
     adc r30, knownZero
     adc r31, knownZero

Furthermore, you DON'T want to use up one of your more-valuable high registers for known zero, since a low register works just as well for that.

 

On some of the newer ATtiny chips, Atmel apparently decided that the low 16 registers were so un-useful that they just got rid of them.  Since the compiler/abi had long-since come to rely on having the know-zero register, they had to move it to r17 instead of r1.

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

 

> Anyone have any idea why this might be the case?

 

If they had to do it all over again...

-- Custer might have taken a different route and avoided Little Big Horn

-- CodeVision might have used a bit [pun intended] different syntax than the historical dot notation for specifying register bits

-- GCC might have picked other than R1 for the zero register

-- I might have paid more attention to Mary Lou in braces and cat-eye glasses before she switched to contacts and became a voluptuous underwear model

 

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

theusch wrote:
Mary Lou in braces
I've always thought braces were sexy!
theusch wrote:
cat-eye glasses
I thought the same for Julie Newmar as catwoman.

Fortunately, I married Donna Jo who had braces and cat-eye glasses...wink

Edit: formatting

David (aka frog_jr)

Last Edited: Fri. Oct 6, 2017 - 01:49 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

theusch wrote:

-- GCC might have picked other than R1 for the zero register

 

There is strong support amongst gcc maintainers to remove features that avr-gcc is using.  Gives there exists someone on this planet (or beyond) who rewrites the gcc avr backend from scratch, you might get avr-gcc without zero and tmp register.

avrfreaks does not support Opera. Profile inactive.

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

SprinterSB wrote:
rewrites the gcc avr backend from scratch

;)  Indeed, that is the rub when just about anything has grown over the years.  Not just computer-language-processing toolchains.  Fairgounds.  Government and other extensive organizations.  Large corporate structure.  It is painful to start over in any of those, or similar.

 

 

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

SprinterSB wrote:
get avr-gcc without zero and temp register.
And then Microchip née Atmel, comes along and adds a feature that clobbers that register!

OK, make the zero and temp registers user defined!devil

 

Edit: misread statement, was assuming move to new registers, not eliminating them completely...

David (aka frog_jr)

Last Edited: Fri. Oct 6, 2017 - 03:46 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

>That would at least mean re-building the run-time libraries.

 

I'd consider re-building libraries easy - at least compared to mucking around in the compiler code. :)

 

It looks like the compiler primitives emit the symbol __zero_reg__ rather than referencing the register directly. 

 

So hopefully moving the zero_reg is as easy as updating the defines in `macros.inc` and a couple other places and recompiling everything?

 

Any chance the optimizer will then recognize R1 push/pop in the preamble as superfluous and omit it?

 

Maybe that ISR preamble is hard-coded somewhere also, but I can not find it. Anyone know?

Last Edited: Fri. Oct 6, 2017 - 03:58 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

theusch wrote:
 Government and other extensive organizations.  Large corporate structure.  It is painful to start over in any of those, or similar.

Not just large organisations.

 

I'm sure we've all looked back at stuff we've done - and not just programming or "work" - and thought, "if I started again from scratch, I would do that differently"

 

But do we ever scrap the lot and start again ... ?