====== Addressing Modes ======
Addressing modes define how the processor accesses data and the target address of a jump. There are more than a dozen different addressing modes, such as: Direct Addressing, Indirect Addressing, Indirect with Displacement, Immediate Addressing, Register Addressing, Relative Addressing, Indirect I/O Addressing, and others. In this section, we first present the data addressing and later addressing used in flow control instructions.
=====Direct Single Register Addressing=====
Direct single register addressing informs the processor that the instruction's operand is stored in a chosen register. It is schematically shown in Fig {{ref>avr_addr_1}}. The register (Rd) is encoded in the instruction after the code of operation (OP - opcode). The example of such instruction can be register incrementation. The direct single register addressing mode can be used in conjunction with an immediate (constant) addressing to write the constant into the register.
inc R0
ldi R2, 0x05
{{ :en:multiasm:piot:ad01.png?600 |Direct Single Register Addressing}}
Direct Single Register Addressing
=====Direct Register Addressing, Two Registers=====
In this addressing mode, there are two register operands. They are contained in the source register (Rr) and destination register (Rd). The result is stored in the destination register (Rd). As it is shown in Fig {{ref>avr_addr_2}}, both registers are encoded in the instruction after the opcode (OP). The example of such a type of addressing can be used in an addition instruction.
add R2, R3
{{ :en:multiasm:piot:ad02.png?600 |Direct Register Addressing, Two Registers}}
Direct Register Addressing, Two Registers
=====I/O Direct Addressing=====
I/O direct addressing mode can be used to access the Special Function Register (SFR) from the internal peripheral address range. As presented in Fig {{ref>avr_addr_3}}, operand address A is contained in the instruction word. The A field is 6 bits long, so it limits the number of available addresses to 64 within the range from 0x00 to 0x3F. Rr/Rd specifies the destination or source register. The example of such addressing is the in instruction that reads data from a chosen SFR register.
in R2, SFR
{{ :en:multiasm:piot:ad03.png?600 |I/O Direct Addressing}}
I/O Direct Addressing
=====Data Direct Addressing=====
To address the byte in a 64-kilobyte address space, 16 bits are required. In Direct Data Addressing mode, the address is contained in the 16 LSbs of a two-word instruction, as shown in Fig {{ref>avr_addr_4}}. Rd/Rr specify the destination or source register. The example instruction for reading data directly from a 64 kB data space is LDS (a variable is the previously defined variable in data memory).
lds R2, variable
Please note that in models of AVR microcontrollers supporting memory larger than 64kB, the LDS instruction uses the RAMPD register to access memory addresses above 64 KB.
{{ :en:multiasm:piot:ad04.png?600 |Data Direct Addressing}}
Data Direct Addressing
=====Data Indirect Addressing=====
Indirect addressing uses the content of an index register as a pointer to memory. As shown in Fig {{ref>avr_addr_5}}, the operand address is the contents of the X, Y, or Z pointer. Please note that X is formed with concatenated registers R27 and R26, Y is built with R29 and R28, and Z with R31 and R30. In AVR devices without SRAM, Data Indirect Addressing is called Register Indirect Addressing.
An example of the instruction is load data from memory addressed with an X pointer.
LD R2, X
{{ :en:multiasm:piot:ad05.png?600 |Data Indirect Addressing}}
Data Indirect Addressing
=====Data Indirect Addressing with Pre-decrement=====
In the pre-decremented version of indirect addressing, the X,- Y-, or the Z-pointer is decremented before the operation. The operand address is the decremented contents of the X-, Y-, or Z-pointer. It is shown in Fig {{ref>avr_addr_6}}. The store instruction decrements X and writes the data from the R2 register to the modified address.
ST -X, R2
{{ :en:multiasm:piot:ad06.png?600 |Data Indirect Addressing with Pre-decrement}}
Data Indirect Addressing with Pre-decrement
=====Data Indirect Addressing with Post-increment=====
In addressing with post-increment, the X, Y, or Z pointer is incremented after the operation. The operand address is the content of the X, Y, or Z pointer before incrementing. It is shown in Fig {{ref>avr_addr_7}}. An example of the instruction can be as follows.
LD R2, X+
{{ :en:multiasm:piot:ad07.png?600 |Data Indirect Addressing with Post-increment}}
Data Indirect Addressing with Post-increment
=====Data Indirect with Displacement=====
The addressing with displacement calculated the sum of two values: the index register and the constant. As shown in Fig {{ref>avr_addr_8}}, the operand address is the result of the q displacement contained in the instruction word, added to the Y or Z pointer. Rd/Rr specify the destination or source register. An example of instruction with indirect addressing with displacement can be accessing the element of a previously defined data table.
LDD R2, Y+table
{{ :en:multiasm:piot:ad08.png?600 |Data Indirect with Displacement}}
Data Indirect with Displacement
=====Program Memory Constant Addressing=====
With this addressing mode, it is possible to read the byte from the program memory. As shown in Fig {{ref>avr_addr_9}}, the byte address in program memory is determined by the value stored in the Z pointer.
The upper 15 bits (Most Significant bits - MSbs) select the word address (each word contains 2 bytes).
The lowest bit (Less Significant bit - LSb) selects which byte of that word is used:
* 0 → low byte,
* 1 → high byte.
{{ :en:multiasm:piot:ad09.png?600 |Program Memory Constant Addressing}}
Program Memory Constant Addressing
Instruction which reads the program memory is **lpm**.
LPM R2, Z
When the **elpm** instruction is used, the RAMPZ register provides extra address bits so the processor can access larger program memories.
The **elpm** (Extended Load Program Memory) is an instruction used to read bytes from program memory when the memory is larger than 64 KB.
The normal **lpm** instruction can only access 64 KB because it uses the 16‑bit Z register.
The **elpm** adds extra address bits from the RAMPZ register, allowing access to extended program memory on larger AVR devices.
In short:
The **elpm** is equal to **lpm** with support for large program memory using RAMPZ.
=====Program Memory Addressing with Post-increment=====
Continue figures formatting here
Program memory can be addressed with post-increment mode. In this mode, the Z pointer is automatically incremented after reading.
As shown in Fing {{ref>avr_addr_10}}, the Z-pointer contents specify a constant byte address. The 15 MSbs select the word address. The LSb selects the low byte if cleared (LSb == 0) or the high byte if set (LSb == 1).
The example of instruction is **lpm Z+**. If **elmp Z+** is used, the RAMPZ Register is used to extend the address in the Z register.
LMP Z+
{{ :en:multiasm:piot:ad10.png?600 |Program Memory Addressing with Post-increment}}
Program Memory Addressing with Post-increment
=====Store Program Memory Post-increment=====
Some versions of AVR microcontrollers allow for writing to the program memory (Flash). They implement the **spm** (Store Program Memory) instruction. Normally, Flash is read‑only during program execution, but **spm** allows the microcontroller to modify or update its own program, for example, inside a bootloader.
As visible in Fig {{ref>avr_addr_11}}, for the **spm** instruction, the LSb must be 0, because **spm** works on whole words. The Z-pointer is incremented by 2 after the operation. The Z-pointer contents specify a constant byte address before incrementing. The 15 MSbs select the word address, and the LSb should be left cleared.
Marcin, tu mam wątpliwości co do nazwy tego rozdziału - to addressing mode? KT odpowiadam - według dokmentacji AVR tak
{{ :en:multiasm:piot:ad11.png?600 |Store Program Memory}}
Store Program Memory
=====Direct Program Memory Addressing=====
This addressing mode does not address data but rather modifies the program execution flow. It is used in jump and subroutine call instructions. These instructions use the constant immediate to specify the absolute target address to jump to. As shown in Fig {{ref>avr_addr_12}}, the constant is loaded to the program counter to change the place where the next instruction is fetched from.
CALL function
{{ :en:multiasm:piot:ad12.png?600 |Direct Program Memory Addressing}}
Direct Program Memory Addressing
"immediate" -> "following immediately the instruction word"? KT - opisałem to dokładniej, Janek zmodyfikuje rysunek bo jest trochę nielogiczny
=====Indirect Program Memory Addressing=====
The target address of the jump or call can be stored in the Z pointer register. After **ijmp** or **icall**, program execution continues at the address contained by the Z register (i.e., the PC is loaded with the contents of the Z register). It is shown in Fig {{ref>avr_addr_13}}.
ICALL
{{ :en:multiasm:piot:ad13.png?600 |Indirect Program Memory Addressing}}
Indirect Program Memory Addressing
=====Extended Indirect Program Memory Addressing=====
For versions of AVR microcontrollers with bigger program memory than 128 kB, additional bits used to extend the address are stored in the EIND register. Program execution continues at the address contained by the Z register and the EIND register (i.e., the PC is loaded with the contents of the EIND and Z register) as shown in fig {{ref>avr_addr_14}}.
{{ :en:multiasm:piot:ad14.png?600 |Extended Indirect Program Memory Addressing}}
Extended Indirect Program Memory Addressing
=====Relative Program Memory Addressing=====
If the target address is within the range of -2048 to 2047 from the current address, the shorter relative control transfer instructions can be used.
As shown in fig {{ref>avr_addr_15}}, program execution continues at the address PC + k + 1. The constant //k// does not represent the absolute address, so it must be calculated as a difference between the current address plus 1 and the target address. It is treated as a signed value, so the target address can be higher or lower than the current one.
RJMP target
{{ :en:multiasm:piot:ad15.png?600 |Relative Program Memory Addressing}}