Author Topic: BRNE jump range, is this an ERROR in the Atmel AVR instruction datasheet ?  (Read 1796 times)

0 Members and 1 Guest are viewing this topic.

Offline MathWizardTopic starter

  • Super Contributor
  • ***
  • Posts: 1617
  • Country: ca
I'm decoding the opcodes from a little blink program on an ATTiny13A. And in the atmel-0856-avr-instruction-set-manual datasheet on page 54,  for the "BRNE k", Branch If Not Equal command, it lists the # of Words k, forwards or backwards, the PC can jump to if the  Z flag was 0. PC <-- PC +k +1

But they say k is from -64 to +6, so is that really supposed to be -64 to +63 ? And so a signed SXX XXXX number ? My code has
BRNE 124d
So I think that's k = -4 = 111 1100

I don't see it mentioned in the revisions, also they have the table of contents at the END, I've never seen that before.
« Last Edit: September 20, 2024, 06:16:08 am by MathWizard »
 

Online voltsandjolts

  • Supporter
  • ****
  • Posts: 2429
  • Country: gb
Re: BRNE jump range, is this an ERROR in the Atmel AVR instruction datasheet ?
« Reply #1 on: September 20, 2024, 06:51:57 am »
The answer is in the image you posted.
 
The following users thanked this post: pcprogrammer

Online magic

  • Super Contributor
  • ***
  • Posts: 7215
  • Country: pl
Re: BRNE jump range, is this an ERROR in the Atmel AVR instruction datasheet ?
« Reply #2 on: September 20, 2024, 07:13:26 am »
It's correct in my version :-//
Quote
Rev. 0856I–AVR–07/10

But LOL, they really managed to screw it up in later revisions. The answer is of course -64<=k<64, as with other conditional branch insns.
« Last Edit: September 20, 2024, 07:19:58 am by magic »
 

Offline westfw

  • Super Contributor
  • ***
  • Posts: 4311
  • Country: us
Re: BRNE jump range, is this an ERROR in the Atmel AVR instruction datasheet ?
« Reply #3 on: September 21, 2024, 12:23:45 am »
The newer manual (DS40002198A) doesn't have the error...)
 
The following users thanked this post: MathWizard

Offline MathWizardTopic starter

  • Super Contributor
  • ***
  • Posts: 1617
  • Country: ca
Re: BRNE jump range, is this an ERROR in the Atmel AVR instruction datasheet ?
« Reply #4 on: September 22, 2024, 09:57:53 am »
Yeah I should have put this in the other ATTiny thread I had. This stuff is addictive. I've been making a model of this MCU/program, in the OpenOffice spreadsheet, it doesn't really do binary or hex.  I've made clocked, full BJT ALU's in LTSpice before, so for real automation I might try some of this in LTS too. Before downloading some basic MCU sim program. Now I can't wait to make some 4 or 8bit MCU with all BJT's.

I'm using all NAND logic, so like open collector. With only using decimal 1,0 , 1-X=1 or 0 is an inverter, and the AND gate is X*Y=0 or 1. So I've made some register's, full 8-bit adders/ALU's, w/ inverted Carry flags, and 2's compliment were wanted, that matches the datasheet so far.  And the Status SREG, for all the ALU flags.

For now, I'm just making copies/new GP reg's and ALU for each instruction of interest, like the compare w/ carry instructions.

So I can see in this blink program, how it made the millis function counter, using some compare commands and subtractions, and BRNE, to count down 255*165*14 ~590,000, and 255*82*7 ~146,000. I'll have to make a small # of  cycles in the spreadsheet MCU, to see what it really does.


There's a bunch of POKE commands in the middle of the program, IDK much about the stack counter, or how all that will tie in to the "while" command, and the bitshift it does at the start, using compares, and more BRNE's. It starts witting numbers into the data SRAM too.


I expected the program to be shorter, I think I'm using the blink example in ArdIDE. Soon I'll have to try writing bare-metal Assembly for blink ON/OFF. The way they do it is probably fine, but IDK what all the rest of the middle code must be for yet.


Quote

#include <avr/io.h>
  #include <util/delay.h>

  int main(void)
  {
    DDRB = 1<<3; // port B3, ATtiny13a pin 2
    PORTB = 0x0;

    while (1)
    {
      PORTB = 1<<3; // port B3, ATtiny13a pin 2
      _delay_ms(500);
      PORTB = 0X0;
      _delay_ms(250);
   
« Last Edit: September 22, 2024, 10:20:22 am by MathWizard »
 

Offline westfw

  • Super Contributor
  • ***
  • Posts: 4311
  • Country: us
Re: BRNE jump range, is this an ERROR in the Atmel AVR instruction datasheet ?
« Reply #5 on: September 23, 2024, 02:10:33 am »
Quote
I expected the program to be shorter, I think I'm using the blink example in ArdIDE.
You can find a lot of analyses of Arduino code in various places, explaining some of the "unexpected bloat."
For simple programs (ie without Arduino), people are usually surprised by the interrupt vector table (~100 bytes) and C runtime initialization (~50 bytes)

My long-ago post:https://community.element14.com/products/arduino/w/documents/7889/analysis-of-an-empty-arduino-sketch
 

Offline 44kgk1lkf6u

  • Contributor
  • Posts: 47
  • Country: 00
Re: BRNE jump range, is this an ERROR in the Atmel AVR instruction datasheet ?
« Reply #6 on: September 23, 2024, 03:35:32 am »
How long a binary did you get?  I compiled with avr-gcc (Fedora 14.1.0-1.fc40) 14.1.0, with the options -std=gnu2x -Os -mmcu=attiny13 -DF_CPU=1'000'000.  The binary is 80 bytes long with no store instructions.

Code: [Select]
Disassembly of section .text:

00000000 <__vectors>:
   0: 09 c0        rjmp .+18      ; 0x14 <__ctors_end>
   2: 0e c0        rjmp .+28      ; 0x20 <__bad_interrupt>
   4: 0d c0        rjmp .+26      ; 0x20 <__bad_interrupt>
   6: 0c c0        rjmp .+24      ; 0x20 <__bad_interrupt>
   8: 0b c0        rjmp .+22      ; 0x20 <__bad_interrupt>
   a: 0a c0        rjmp .+20      ; 0x20 <__bad_interrupt>
   c: 09 c0        rjmp .+18      ; 0x20 <__bad_interrupt>
   e: 08 c0        rjmp .+16      ; 0x20 <__bad_interrupt>
  10: 07 c0        rjmp .+14      ; 0x20 <__bad_interrupt>
  12: 06 c0        rjmp .+12      ; 0x20 <__bad_interrupt>

00000014 <__ctors_end>:
  14: 11 24        eor r1, r1
  16: 1f be        out 0x3f, r1 ; 63
  18: cf e9        ldi r28, 0x9F ; 159
  1a: cd bf        out 0x3d, r28 ; 61
  1c: 02 d0        rcall .+4      ; 0x22 <main>
  1e: 16 c0        rjmp .+44      ; 0x4c <_exit>

00000020 <__bad_interrupt>:
  20: ef cf        rjmp .-34      ; 0x0 <__vectors>

00000022 <main>:
  22: 88 e0        ldi r24, 0x08 ; 8
  24: 87 bb        out 0x17, r24 ; 23
  26: 18 ba        out 0x18, r1 ; 24

00000028 <.L2>:
  28: 88 bb        out 0x18, r24 ; 24
  2a: 2f e9        ldi r18, 0x9F ; 159
  2c: 36 e8        ldi r19, 0x86 ; 134
  2e: 91 e0        ldi r25, 0x01 ; 1

00000030 <.L1^B1>:
  30: 21 50        subi r18, 0x01 ; 1
  32: 30 40        sbci r19, 0x00 ; 0
  34: 90 40        sbci r25, 0x00 ; 0
  36: e1 f7        brne .-8      ; 0x30 <.L1^B1>
  38: 00 c0        rjmp .+0      ; 0x3a <L0^A>

0000003a <L0^A>:
  3a: 00 00        nop
  3c: 18 ba        out 0x18, r1 ; 24
  3e: e3 e2        ldi r30, 0x23 ; 35
  40: f4 ef        ldi r31, 0xF4 ; 244

00000042 <.L1^B2>:
  42: 31 97        sbiw r30, 0x01 ; 1
  44: f1 f7        brne .-4      ; 0x42 <.L1^B2>
  46: 00 c0        rjmp .+0      ; 0x48 <L0^A>

00000048 <L0^A>:
  48: 00 00        nop
  4a: ee cf        rjmp .-36      ; 0x28 <.L2>

0000004c <_exit>:
  4c: f8 94        cli

0000004e <__stop_program>:
  4e: ff cf        rjmp .-2      ; 0x4e <__stop_program>
« Last Edit: September 23, 2024, 04:01:30 am by 44kgk1lkf6u »
 
The following users thanked this post: MathWizard

Offline westfw

  • Super Contributor
  • ***
  • Posts: 4311
  • Country: us
Re: BRNE jump range, is this an ERROR in the Atmel AVR instruction datasheet ?
« Reply #7 on: September 24, 2024, 04:47:10 am »
Quote
The binary is 80 bytes long
the code shown isn't "the Arduino blink example"; Arduino will likely add some additional overhead.

(Hmm.  "microcore" compiles the standard blink example to 90 bytes, which is better than I thought it would be!
Differences seems to be: initialize TCNT0, Turn on Interrupts, and delay() is implemented as a loop around _delay_ms(1))

(IIRC, there was another ATtiny13 "core" that was substantially less optimized than microcore.)

 

Offline MathWizardTopic starter

  • Super Contributor
  • ***
  • Posts: 1617
  • Country: ca
Re: BRNE jump range, is this an ERROR in the Atmel AVR instruction datasheet ?
« Reply #8 on: September 26, 2024, 08:18:00 am »
IDK for sure were I got this blink code, I might have copy/pasted it, from some ATTiny tutorial. But it's from 0-87, so 88 WORDS, 176 Bytes of program flash.

I just did up another spreadsheet to show what I think the prog does overall. But it doesn't lead to any of the middle stuff. This spreadsheet doesn't load the REG's and do all the ALU math, besides the program counter.

I don't know much about the STACK, so I thought for a while that maybe the DDRB 1<<3, and the "while" command  was doing some sort of PWM, overtop of the LED blink, to save power. This thing has bitwise operations, I expected a direct leftshift command. So I thought somehow all that was related to the RAM addresses that get used with the Store function and Xreg/XPointer, and the RCALL routine.

But no I don't see  anything like that. And DDRB is just for setting the port as input or output, so that's a bad way to try PWM. And they only ever write R1=0 into the start of RAM locations, so yeah I need to see some Stack and SP examples.


But does this look about right ? Yeah IDK what all the middle code is for yet, nothing seems to lead there, if I got this right. It looks messy in a table so here's a pic
« Last Edit: September 28, 2024, 12:53:44 am by MathWizard »
 

Offline westfw

  • Super Contributor
  • ***
  • Posts: 4311
  • Country: us
Re: BRNE jump range, is this an ERROR in the Atmel AVR instruction datasheet ?
« Reply #9 on: September 26, 2024, 10:43:58 am »
Quote
This thing has bitwise operations, I expected a direct leftshift command.
The bitshifts, since they have constants for both arguments, happen at compile time and won’t appear in the binary.

 

Offline MathWizardTopic starter

  • Super Contributor
  • ***
  • Posts: 1617
  • Country: ca
Re: BRNE jump range, is this an ERROR in the Atmel AVR instruction datasheet ?
« Reply #10 on: September 28, 2024, 12:22:16 am »
Oh ok, and I see the final assembly from 44kgk1lkf6u isn't the same, so that's down to the compiler doing it differently. In win10, I used ArduinoIDE, w/ an Uno as the ISP, to program the ATTiny13A, I'm not sure which avrdude got used.

And I see the RCALL isn't just a RJMP, there's a return address, from after the routine is done. But the only command I see like that is the RETI, in the section I'll mention below.

Here's the full assembly, and here's the 1st bit of IntelHex, :20 0000 00   09C0 16C0 15C0 15C0 13C0, those 2x RJMP 21 are correct.
0   RJMP 9
1   RJMP 22
2   RJMP 21
3   RJMP 21
4   RJMP 19
5   RJMP 18
6   RJMP 17
7   RJMP 16
8   RJMP 15
9   RJMP 14
10   EOR R1,R1
11   OUT 63,R1
12   LDI R28,159
13   OUT 61,R28
14   LDI R18,0
15   LDI R26,96
16   LDI R27,0
17   RJMP 1
18   ST X+,R1
19   CPI R26,100
20   CPC R27,R18
21   BRNE -4
22   RCALL 39
23   RJMP 62
24   RJMP-25
25   PUSH R1
26   PUSH R0
27   IN R0,63
28   PUSH R0
29   CLR R17
30   PUSH R24
31   PUSH R25
32   PUSH R26
33   PUSH R27
34   LDS R24,96
36   LDS R25,97
38   LDS R26,98
40   LDS R27,99
42   ADIW R24+1:R24,1
43   ADC R26,R1
44   ADC R27,R1
45   STS 96,R24
47   STS 97,R25
49   STS 98,R26
51   STS 99,R27
53   POP R27
54   POP R26
55   POP R25
56   POP R24
57   POP R0
58   OUT 63,R0
59   POP R0
60   POP R1
61   RETI
62   LDI R24,8
63   OUT 23,R24
64   OUT 24,R1
65   OUT 24,R24
66   SER R18
67   LDI R19,165
68   LDI R25,14
69   SUBI R18,1
70   SBCI R19,0
71   SBCI R25,0
72   BRNE -4
73   RJMP 0
74   NOP
75   OUT 24,R1
76   LDI R18,255
77   LDI R19,82
78   LDI R25,7
79   SUBI R18,1
80   SBCI R19,0
81   SBCI R25,0
82   BRNE 124
83   RJMP 0
84   NOP
85   RJMP -21
86   BCLR 7
87   RJMP -1


So the only thing that leads to Word 25, the 1st PUSH, is the RJMP 21, from the 0x03 interrupt location for the Timer/Counter OverFlow interrupt. But there was no setup at all for the T/C, so why bother if it's all off ?

Then all the PUSH onto stack, LDS from RAM, a bit more math, STS to RAM, POP from stack, then there's an actual RETI.

Isn't it correct, that R1 only ever equals, and then their ST X+, R1  , with X=0x60 to start, just stores, 0, to the 1st 4 places of RAM ? So aren't they just using ST X+, just to do an increment ? But they also seem to store R1=0 onto the stack, then moments later, POP the stored 0, back into R1, but R1 should never change anyways. So why bother ?? And R0 was never set to anything, but they PSUH it to 0x9F the top of the stack (at that time), so is it assumed it starts 0 ? They purposefully set R1=0.

Assuming RAM 0x60-0x63 does have 0 in them, so are they using this to clear R24-R27, after just storing their values onto the STACK ? Then do some math to those R24-R27, then reload the stored values back from the STACK ??

And whats the timer interrupt doing, and all that section ? It seemed to me, the BRNE's and RJMP's would be enough to reload all REG's to the programs initial conditions, and then do the 2 countdowns, and loop forever.

All this is making more sense as I go, but yeah some of it seems silly, like an RJMP 0, followed by a NOP. If it's just for some timing reason, why not use 2x NOP, or 2x RJMP 0, or does it trigger something useful behind the scenes ??

« Last Edit: September 28, 2024, 12:40:47 am by MathWizard »
 

Offline sleemanj

  • Super Contributor
  • ***
  • Posts: 3045
  • Country: nz
  • Professional tightwad.
    • The electronics hobby components I sell.
Re: BRNE jump range, is this an ERROR in the Atmel AVR instruction datasheet ?
« Reply #11 on: September 28, 2024, 03:45:06 am »
(IIRC, there was another ATtiny13 "core" that was substantially less optimized than microcore.)

There was "core13" but very ancient.

My ATTinyCore fork compiles standard blink for Tiny13A in 84 bytes.  I don't think you can get much shorter than that without losing Arduino abilities (actually, that is already technically sacrificing millis() and tone(), but blink isn't using it, so no problem).

Code: [Select]
:1000000009C00EC00DC00CC00BC00AC009C008C09A
:1000100007C006C011241FBECFE9CDBF02D018C053
:10002000EFCF86E886B9BB9A2AE439E0C39A89EE15
:1000300093E0019749F4C39889EE93E00197B1F3F7
:10004000F9013197F1F7FACFF9013197F1F7F1CFD3
:04005000F894FFCF52
:00000001FF

LED on PB3 (pin 2)
« Last Edit: September 28, 2024, 06:46:11 am by sleemanj »
~~~
EEVBlog Members - get yourself 10% discount off all my electronic components for sale just use the Buy Direct links and use Coupon Code "eevblog" during checkout.  Shipping from New Zealand, international orders welcome :-)
 

Offline westfw

  • Super Contributor
  • ***
  • Posts: 4311
  • Country: us
Re: BRNE jump range, is this an ERROR in the Atmel AVR instruction datasheet ?
« Reply #12 on: September 28, 2024, 06:38:15 am »
I don't know why you continue to do this the hard way, when several people have pointed out easier ways (and existing analyses.)
Also, recent versions of AVRDUDE (v8) have a nice "disassemble" feature that generates useful target labels for jmp/call instructions.

And I see the RCALL isn't just a RJMP, there's a return address, from after the routine is done. But the only command I see like that is the RETI, in the section I'll mention below.
Well, main() doesn't return, and delay_ms() is a macro (ok "built-in function"), so why would there be any return instructions?

Quote
there was no setup at all for the T/C, so why bother if it's all off ?
The C compiler has no knowlege of interrupt hardware, so there's no way for it to know that the ISR isn't called.
I believe more recent cores have the ability to omit the timer ISR.  NerdRalph's "picocore" keeps the ISR count in registers, so it takes less code and is faster.

Quote
an RJMP 0, followed by a NOP. If it's just for some timing reason, why not use 2x NOP, or 2x RJMP 0
Just for timing, I think.  _delay_ms() expands to __builtin_delay_cycles(), which will (hopefully) delay EXACTLY that many cycles.
RJMP 0 is a two-cycle nop, while NOP is single-cycle, so the combination delays 3 cycles in the minimum code size.

Here's the whole thing, annotated.
Code: [Select]
0   RJMP 9           ;; vectors
1   RJMP 22          ;; jump destinations pretty useless.
2   RJMP 21
3   RJMP 21
4   RJMP 19
5   RJMP 18
6   RJMP 17
7   RJMP 16
8   RJMP 15
9   RJMP 14

;;; Beginning of C runtime initialization
10   EOR R1,R1      ;; set up "known zero."
11   OUT 63,R1      ;;  clear status register
12   LDI R28,159    ;; set up stack
13   OUT 61,R28
14   LDI R18,0      ;; probly the clear bss code.
15   LDI R26,96
16   LDI R27,0
17   RJMP 1
18   ST X+,R1
19   CPI R26,100  ;; note X == r27:r26
20   CPC R27,R18
21   BRNE -4
22   RCALL 39      ;; "rcall main"
23   RJMP 62       ;; goto "exit"
24   RJMP-25       ;; bad interrupt, restart by jump to 0

25   PUSH R1       ;; timer ISR
26   PUSH R0       ;; save R0
27   IN R0,63       ;;  save SREG
28   PUSH R0
29   CLR R17       ;; no sure about this one!
30   PUSH R24     ;; save registers for "long temp" in ISR
31   PUSH R25
32   PUSH R26
33   PUSH R27
34   LDS R24,96   ;; temp = milliscount
36   LDS R25,97
38   LDS R26,98
40   LDS R27,99
42   ADIW R24+1:R24,1  ;; increment temp
43   ADC R26,R1
44   ADC R27,R1
45   STS 96,R24   ;; store new milliscount
47   STS 97,R25
49   STS 98,R26
51   STS 99,R27
53   POP R27     ;; restore registers
54   POP R26
55   POP R25
56   POP R24
57   POP R0        ;; restore SREG
58   OUT 63,R0
59   POP R0
60   POP R1
61   RETI         ;; end of ISR.
;; main() starts here
62   LDI R24,8    ;;  1<<3 to register.
63   OUT 23,R24   ;;  DDRB = 1<<3
64   OUT 24,R1    ;;  PORTB = 0
                  ;; while loop starts here
65   OUT 24,R24   ;; PORTB = 1<<3 (still in r24)
66   SER R18      ;; load constants for _delay_ms in r25:R19:r18
67   LDI R19,165
68   LDI R25,14
69   SUBI R18,1   ;; delayloop1: busy loop subtract for _delay_ms
70   SBCI R19,0
71   SBCI R25,0
72   BRNE -4      ;;  Keep looping.
73   RJMP 0       ;;   a couple extra cycles to make it exactly 500ms
74   NOP
75   OUT 24,R1    ;; PORTB = 0
76   LDI R18,255  ;; delayloop2: load constants for __delay_ms
                  ;; (interesting that this isn't diassembler as SER)
77   LDI R19,82
78   LDI R25,7
79   SUBI R18,1   ;; decrements
80   SBCI R19,0
81   SBCI R25,0
82   BRNE 124     ;; looping for 2nd delay
83   RJMP 0       ;; exactly 250ms
84   NOP
85   RJMP -21     ;; back to beginning of while loop.
86   BCLR 7       ;; cli (turn off interrupts)
87   RJMP -1      ;; infinite loop (this is "exit"), probably.
 
The following users thanked this post: MathWizard

Offline MathWizardTopic starter

  • Super Contributor
  • ***
  • Posts: 1617
  • Country: ca
Re: BRNE jump range, is this an ERROR in the Atmel AVR instruction datasheet ?
« Reply #13 on: September 29, 2024, 12:06:32 pm »
Ok thanks westfw, I have a MCU sim program called SimuIDE, it does AVR and PCI and more. I'm just learning the basics of it, but for instance it can simulate an ATmega328 voltmeter, and it shows all the IntelHex, aswell as an animated voltmeter, and a knob to turn. So I want to try the blink code in that.

So it is the Arduino way of doing things that's tripping me up. I'm still not sure if it's using the actual timer/counter. I see you said PUSH R1, becomes the timer interrupt service somehow. I'll have to look up about the arduino core, see where that even is. I have the EEPROM flash too, but never looked at it yet.

So in the sim, I want to just upload the part countdown code that I think should work on it's own, and find out.

Yeah I started to decode the IntelHex of the voltmeter stored in the AVR/examples in the SimuIDE program. It's on an ATMEGA328. That's taking way too long, it's some 2892 words long. It really seems to have a lot of gibberish for the 1st few lines. And the action starts around word 97.

So yeah I'm not finishing that by hand. But I still want to try this blink code stripped down, and then make my own 3-digit voltmeter on an ATTiny, to get a better feel for it all. I made my own VM w/ the ArduinoIDE once, now I can try it with just the assembly math.


And I need to get a newer datasheet for the assembly codes, there's more mistakes, I saw another place where #31 became just #3
« Last Edit: September 29, 2024, 12:08:05 pm by MathWizard »
 

Offline MathWizardTopic starter

  • Super Contributor
  • ***
  • Posts: 1617
  • Country: ca
Re: BRNE jump range, is this an ERROR in the Atmel AVR instruction datasheet ?
« Reply #14 on: September 30, 2024, 07:27:44 pm »
Hey I got it working in SimulIDE and on a real ATTiny13A. I worked out all the opcodes and the IntelHex in a speadsheet. Now for a DMM assembly program, I'll figure out which one of my programs will convert it. For now I just assume not use an IDE.

So I left in the RJMP and NOP's, but the flash for the Blink prog is 37*2=74 Bytes. Maybe I don't need to set the SPL at all either.

0   RJMP 9
1   RJMP 8
2   RJMP 7
3   RJMP 6
4   RJMP 5
5   RJMP 4
6   RJMP 3
7   RJMP 2
8   RJMP 1
9   RJMP 0
10   EOR R0,R0
11   LDI R16,8
12   LDI R17,159
13   OUT 63,R0
14   OUT 61,R17
15   OUT 23,R16
16   OUT 24,R16
17   SER R24
18   LDI R22,165
19   LDI R20,14
20   SUBI R24,1
21   SBCI R22,0
22   SBCI R20,0
23   BRNE -4
24   RJMP 0
25   NOP
26   OUT 24,R0
27   SER R24
28   LDI R22,42
29   LDI R20,5
30   SUBI R24,1
31   SBCI R22,0
32   SBCI R20,0
33   BRNE -4
34   RJMP 0
35   NOP
36   RJMP -21
:1000000009C008C007C006C005C004C003C002C0C4
:1000100001C000C0002408E01FE90FBE1DBF07BBE0
:1000200008BB8FEF65EA4EE0815060404040E1F749
:1000300000C0000008BA8FEF6AE245E081506040DE
:0A0040004040E1F700C00000EBCFE4
:00000001FF
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf