Introduction
The AVR is the 8-bit microcontroller family that Atmel (now Microchip) introduced in 1996. It is the chip of the Arduino Uno and Nano
(ATmega328P), the Leonardo and the Arduboy (ATmega32U4), the Arduino Mega (ATmega2560) and of the small ATtiny parts. These pages describe the instruction set
and the disassembler the explorer uses for it (explorer/cpu/avr/, our own code). It reads the code in an
ELF file for an AVR (machine type 83) and in an Intel HEX file, the form in which an Arduino sketch is uploaded.
AVR is a Harvard machine: the program is in flash, a separate address space of 16-bit words, and the data (registers, I/O and RAM) is another. An instruction is one or two words long. Every address in a file format is a byte address, so a jump to word 0x0436 is written 0x086C in the tools; the registers page explains the two and the disassembler can show either.
Statuses
Every decoded instruction carries one of four statuses, drawn in its own colour and also written as text:
- documented: in the instruction set manual for the chosen core;
- unavailable: an instruction of another core (a
MULdecoded as AVR2,JMPon the reduced core). The encoding is decoded as it would read on the core that has it; - unpredictable: the manual says the result is undefined, as for
LD r26,X+(the register that receives the byte is part of the pointer that is incremented); - reserved: no AVR core has an instruction with this encoding. The disassembly shows
.word.
Flash often holds data (tables, bitmaps, strings) among the code. A disassembler cannot tell, so a game image such as the Arduboy’s shows its graphics as odd instructions; the viewer decodes the whole image.
The cores
The explorer offers thirteen choices, named after the architecture names that avr-gcc and llvm use. The cores page lists what each has.
| Choice | Core | Typical devices |
|---|---|---|
avr1 | AVR | AT90S1200, ATtiny11, ATtiny12, ATtiny15 (no RAM) |
avr2, avr25 | AVR, AVRe | AT90S2313, AT90S8515; ATtiny13, ATtiny85, ATtiny2313 |
avr3, avr31, avr35 | AVR, AVRe+ | ATmega603; ATmega103; ATtiny1634, AT90USB82 |
avr4 | AVRe+ | ATmega8, ATmega88 |
avr5, avr51 | AVRe+ | ATmega328P, ATmega32U4, ATmega16; ATmega128, ATmega1280 |
avr6 | AVRe+ | ATmega2560, ATmega2561 (3-byte return address) |
xmega | AVRxm | ATxmega16A4U, ATxmega128A1 (DES, LAC, LAS, LAT, XCH) |
xmega3 | AVRxt | ATtiny817, ATmega4809 |
avrtiny | AVRrc | ATtiny4, 5, 9, 10, 20, 40 (reduced core: 16 registers) |
In an ELF file the choice comes from e_flags; a HEX file does not say, so the options bar asks (the default is avr5, the Arduino case).
What the viewer lets you choose
- Core (above).
- Aliases:
lsl r24foradd r24,r24,rol,tst,clr,seiforbset 7,breqforbrbs 1and so on (the default, as llvm and avr-objdump write them), or the instruction as encoded. - Jump targets as byte addresses (default) or word addresses.
- I/O register names for the ATmega328P, ATmega32U4, ATmega2560 or ATtiny85:
in r24, SREGinstead ofin r24, 0x3f. Every device has its own table, so only these four are written out (I/O register names).
How this was checked
- llvm. For each of the thirteen cores all 65,536 sixteen-bit words, and the two-word forms (
LDS STS JMP CALL) with five second words each, were run throughllvm-mc --disassemble --triple=avrwith the matching-mcpuand compared with the decoder: 860,608 comparisons, no unexplained difference. Where llvm is more permissive than the manual the decoder says “unavailable”: llvm acceptsLDandSTon the core with no RAM,LDDon the reduced core, registers r0 to r15 on the reduced core, and the unassigned encoding1001 000d dddd 1000asLD Rd,Y(64 words). - An emulator. The avr8js core of the Arduboy emulator (emulators.org) ran every word the decoder calls documented for AVR5 from random states: the program counter after it, the registers and flags it changes, and (by changing one register or flag at a time) the registers and flags it reads, against what the decoder says. 255,064 executions and 2,524,108 read checks, no difference. The one finding is in avr8js: its
SBIWclears the half-carry flag, which the manual says it does not affect. - Real programs. Four Arduboy games (ATmega32U4 flash images) read through the HEX viewer, and four programs built with clang and linked with lld for the ATmega328P, ATmega2560, ATtiny85 and ATmega32U4, compared instruction by instruction with
llvm-objdumpin the ELF viewer.
There is no avr-gcc, avr-objdump or Arduino installation on the machine this was built on, so GNU binutils was not a second source. The cycle counts are the classic cores’ (AVR, AVRe, AVRe+) from the manual; XMEGA, tinyAVR 0/1/2 and the reduced core differ and are not tabulated.
Sources
- AVR Instruction Set Manual (DS40002198) – Microchip; the online edition Instruction Set Summary (read for the cycle counts of the cores and the instructions the reduced core lacks);
- LD – Load Indirect from Data Space to Register using X – Microchip (the undefined results of
LD r26,X+); - avr-libc device headers
iom328p.h,iom32u4.h,iomxx0_1.h(ATmega2560) andiotnx5.h(ATtiny85), read online for the I/O register names; - LLVM AVR target – the comparison tool.
Not described
- Cycle counts of the XMEGA, tinyAVR 0/1/2 and reduced cores; the extra cycles of self-programming (
SPM) and of external RAM. - The I/O registers of any device except the four named; interrupt vector names; fuse and lock bits; the peripherals.
- The behaviour of undefined results (
unpredictableinstructions) beyond saying they are undefined; the reduced core’sIJMPandICALL: llvm rejects them and the decoder follows llvm, but the manual’s instruction summary (as read) does not list them among the instructions the reduced core lacks, so they may exist there. - The 22-bit program counter’s wrap-around at the end of flash (a jump past the end of a smaller device is shown as the address it encodes).