Exceptions in SREG_x rules

32 posts / 0 new
Last post
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Brutte wrote:
"neg" "adc" "neg" (for int16_t) does not need an upper register.
Thanks for pointing that out. It's just another micro-optimization to avr-gcc now:
http://gcc.gnu.org/viewcvs/trunk/gcc/config/avr/avr.md?r1=184447&r2=184446&pathrev=184447

avrfreaks does not support Opera. Profile inactive.

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

SprinterSB wrote:
It's just another micro-optimization to avr-gcc now:

You mean it was added into GCC?
Great!
Unfortunately I do not understand these patches.. Cannot find "adc" op-code there.

You mean:

Quote:
neg B
neg A
sbc B,zero
?
Looks ok.
I am not sure about that but does GCC mind the SREG_S flag is not set correctly (when you neg 0x8000 )? SREG_Z propagates fine, it is set iff int==0.

No RSTDISBL, no fun!

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

Brutte wrote:

Unfortunately I do not understand these patches.. Cannot find "adc" op-code there.

Brutte I don't understand the "inner works of avr-gcc" nor am i an assembler expert.

But for a quick "patch" tour ....

The lines starting with - are removed from the source, the lines starting with + are added.

Maybe that gives a bit of a hint , to what SB has done (with the source) :-) .

/Bingo

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

More to the point is that if you follow on from Sprinter's link you get to see the whole avr.md:

http://gcc.gnu.org/viewcvs/trunk/gcc/config/avr/avr.md?view=markup

It appears to be a work of genius in something resembling Forth a bit. The .md = machine description and it's presumably how the actual AVR architecture is known by GCC's code generator. Ultimately it looks like the _insn (instructions) it defines lead to the insertion of small snippets of AVr source code in the .s file.

 

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

Bingo600 wrote:
The lines starting with - are removed from the source, the lines starting with + are added.

Thanks, there is an option to "colour" what was added and what was removed but there is no "adc" in what was added! So I guess SB must have made some further tweaks with -int and changed "neg adc neg" into "neg neg sbc" (which is ok).
I suspect GCC is not very clever and ignores SREG's arguments and returned values and thus SREG_S and SREG_Z is of no use with GCC anyway.

Quote:
(set_attr "cc" "set_czn")

??

No RSTDISBL, no fun!

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

Brutte wrote:

Quote:
(set_attr "cc" "set_czn")

??

I really have no idea , but a guess would be that gcc needs to know what flags are affected/set by the things just executed.

set C + Z + N flag or ??

/Bingo

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

Brutte wrote:
Unfortunately I do not understand these patches...
There is also colored diff which is more readable. It's not a patch actually but a diff between two SVN versions of GCC.
Quote:
Cannot find "adc" op-code there. You mean?
Quote:
neg B
neg A
sbc B, zero
Yes, I used that sequence because it sets Z flag in a usable way: SBC propagates Z from NEG wheras ADC would clobber condition code.
Quote:
I am not sure about that but does GCC mind the SREG_S flag is not set correctly (when you neg 0x8000)? SREG_Z propagates fine, it is set iff int==0.
avr-gcc's representation of AVR machine status is somewhat limitet and is not modelled 1:1. Condition code is not modelled explicitely but only implicitly by insn attribute "cc" that can have several states:
  • none: not affected by insn, for example LDI, SWAP
  • clobber: insn left cc in a mess (worst case), for example CALL
  • compare: after a comparison (best case)
  • set_zn: Z and N are set in a usable way, i.e. represent the output operand of the last insn
  • set_czn: same as set_zn, but some other flags clobbered. Currently same effect like set_zn.
  • set_n: N is set in a usable way. Currently not taken advantage of, same effect like clobber
clawson wrote:
The .md = machine description and it's presumably how the actual AVR architecture is known by GCC's code generator. Ultimately it looks like the _insn (instructions) it defines lead to the insertion of small snippets of AVR source code in the .s file.
Insns (pronounced "insns" in order not to confuse them with instructions) are pieces of one of GCC's intermediate representations (IRs): RTL (Register Transfer Language) with lisp-like syntax.

The insn's assembler template is very much like assembler template you know from inline assembler.

And the constraints for the operands are very much like the operand constraints you know from inline assembler, except that GCC allows multiple alternatives (actually, inline asm allows multiple alternatives, too, but they are not very helpful because inline asm does not allow multiple asm templates).

The insn pattern describes the insn's action on algebraic level, for neghi2 ($0 = -$1) from above it is

(set (match_operand:HI 0 "register_operand")
     (neg:HI (match_operand:HI 1 "register_operand")))

HI stands for "Half Integer" which is a 16 bit scalar integer.

This means "take a HI register $1 as input, negate it, and set HI register $0 to the result of the operation".

Brutte wrote:
I suspect GCC is not very clever and ignores SREG's arguments
Consider
void bar (int);

void neg (int x)
{
    x = -x;
    
    if (x)
        bar(x);
}

compiled -Os -dp -S and you get (older version without the change from above, i.e. insn neghi2 from the left side of the diff)

neg:
	com r25	 ;  6	neghi2/1	[length = 3]
	neg r24
	sbci r25,lo8(-1)
	breq .L3	 ;  8	branch	[length = 1]
	rjmp bar	 ;  11	call_insn/4	[length = 1]
.L3:
	ret	 ;  22	return	[length = 1]

Left is the filled-in insn template and in asm comments the insn name, constraint alternative used and length in words.

avrfreaks does not support Opera. Profile inactive.

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

Quote:
avr-gcc's representation of AVR machine status is somewhat limitet and is not modelled 1:1

But still impressive.
Quote:
Consider

Ok, so I guess SREG_S is not a problem in above example as GCC does not understand SREG_V or SREG_S? Is there a chance that "com com adc adc" which sets SREG_S correctly could have any value over "neg neg sbc" in GCC?

No RSTDISBL, no fun!

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

Brutte wrote:
I guess SREG_S is not a problem in above example as GCC does not understand SREG_V or SREG_S?
It's not a problem. As said, avr-gcc does not model each bit of SREG. Instead, the compiler tracks how usable the contents of SREG are. That information is only used when a branch is emit. If the information is not there, avr-gcc emits a comparison. Otherwise, the comparision can be omitted.

Other iformation that's used is if the value to be compared dies or not. For example, in

char c;

void func_1 (long x)
{
    if (x < 1234567)
        c = 0;
}

void func_14 (int x)
{
    if (x == -14)
        c = 0;
}

x is unused after the comparison. Thus:

func_1:
	cpi r22,-121
	sbci r23,-42
	sbci r24,18
	cpc r25,__zero_reg__
	brge .L1
	sts c,__zero_reg__
.L1:
	ret

func_14:
	adiw r24,14
	brne .L3
	sts c,__zero_reg__
.L3:
	ret

avrfreaks does not support Opera. Profile inactive.

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

Quote:
It's not a problem.

Thanks for the detailed explanation. I can see GCC is quite advanced in the SREG subject.

brge .L1 

I suppose this "brbx SREG_S,.." happens only after "compare: after a comparison (best case)" so it looks like even with "com com adc adc" (which does not propagate SREG_Z at all) that SREG_S is useless as there is no option in GCC: "SREG_S and SREG_N is ok, but the rest of the flags - not really as SREG_C inticates zero and SREG_Z tests for zero only on highest byte"..

No RSTDISBL, no fun!

Pages