Addressing Modes - wgrzegorz/c5xtools GitHub Wiki
Addressing Modes
Normative source: SPRU056D, chapter 5 (Addressing Modes). Opcode field widths
are additionally checked against the toolchain's include/c5x_isa.h.
The TMS320C5x reaches an operand in data memory in one of six ways. The first two (direct and indirect) are the general data-memory modes and share one bit in the instruction word (bit 7) that selects between them. The other four are specialized.
| Mode | Operand comes from | Selected by |
|---|---|---|
| Direct | 7-bit field in the instruction, paged by DP | bit 7 = 0 |
| Indirect | one of AR0 to AR7, via the ARAU | bit 7 = 1 |
| Immediate | a constant inside the instruction word(s) | the instruction itself (#k) |
| Dedicated-register | the BMAR or the DBMR | the instruction itself |
| Memory-mapped | page-0 address with the 9 high bits forced to 0 | the instruction itself |
| Circular | an AR constrained to a buffer by CBSR/CBER/CBCR | CBCR enable bit |
1. Direct addressing
The instruction carries the low 7 bits of the data-memory address (the dma).
Those 7 bits select one of 128 words inside a page; the 9-bit data-memory page
pointer DP (in status register ST0) selects one of 512 pages. Concatenating
them forms the full 16-bit address, which is driven onto the internal data
address bus (DAB).
Instruction-word layout:
Load the DP with LDP (or with LST #0). Example:
LDP #019Dh ; DP = 19Dh (page 413)
ADD 010h, 5 ; add Data(DP:010h) << 5 to the accumulator
Note (from SPRU056D): the DP is not initialized by reset and is undefined after power-up. Development tools use default values, so a program that does not set the DP in software may behave differently on real silicon than under a tool. Always initialize the DP.
2. Indirect addressing
Eight 16-bit auxiliary registers AR0 to AR7 hold addresses; any of the 64K-word data space can be reached through them. The 3-bit auxiliary register pointer ARP (in ST0) selects the current AR. After the access, the auxiliary register arithmetic unit (ARAU) can modify the current AR, and the ARP can be pointed at a different AR, all in the same cycle. The index register INDX supplies the step for indexed and bit-reversed updates.
Instruction-word low byte (SPRU056D Table 5-1): the Indirect addressing row of the figure at the top of this page shows the layout; the fields are:
| Field | Bit(s) | Meaning |
|---|---|---|
| I | 7 | Addressing mode. 1 = indirect, 0 = direct. |
| IDV | 6 | Use INDX for the update (1) rather than a step of 1 (0). |
| INC | 5 | Increment the current AR after the access. |
| DEC | 4 | Decrement the current AR after the access. |
| N | 3 | Load a new ARP (1) or leave it unchanged (0). |
| NAR | 2-0 | The next AR number, loaded into ARP when N = 1. |
The assembler hides those bits behind operand syntax. The seven update forms:
| Operand | Update to the current AR after the access |
|---|---|
* |
none |
*+ |
increment by 1 |
*- |
decrement by 1 |
*0+ |
add INDX |
*0- |
subtract INDX |
*BR0+ |
add INDX with reverse carry (bit-reversed) |
*BR0- |
subtract INDX with reverse carry (bit-reversed) |
Any of these may be followed by a next-AR number to repoint the ARP in the same
instruction, for example *+,AR3 (use the current AR, increment it by 1, then
set ARP = 3). Bit-reversed forms support FFT data reordering: set INDX to half
the array size and the ARAU propagates carries in reverse.
LAR AR3, #0300h ; AR3 -> 0300h
MAR *, AR3 ; make AR3 the current AR (ARP = 3)
LACC *+ ; ACC = Data(0300h), then AR3 = 0301h
LACC *0+ ; ACC = Data(0301h), then AR3 = AR3 + INDX
3. Immediate addressing
The operand is a constant contained in the instruction itself, written with a
leading #. Short-immediate instructions are one word and carry an 8-, 9- or
13-bit constant; long-immediate instructions are two words and carry a full
16-bit constant in the second word.
Instructions that accept an immediate operand (SPRU056D Table 5-5):
| Constant width | Instructions |
|---|---|
| 8-bit (short) | ADD, ADRK, LACL, LAR, RPT, SBRK, SUB |
| 9-bit (short) | LDP |
| 13-bit (short) | MPY |
| 16-bit (long) | ADD, AND, APL, CPL, LACC, LAR, MPY, OPL, OR, RPT, RPTZ, SPLK, SUB, XOR, XPL |
Example:
ADD #0FFh ; one-word, 8-bit immediate
ADD #01234h ; two-word, 16-bit immediate
4. Dedicated-register addressing
Works like long-immediate addressing, except the address is taken from a special memory-mapped CPU register instead of the instruction word, so it can change at run time:
| Register | Name | Used by |
|---|---|---|
| BMAR | block move address register | BLDD, BLDP, BLPD (block moves) and MADD, MADS (multiply-accumulate from program memory) |
| DBMR | dynamic bit manipulation register | APL, CPL, OPL, XPL when no immediate mask is given |
BLDD BMAR, DAT100 ; source address comes from BMAR
OPL DAT10 ; OR Data(DAT10) with the DBMR mask
5. Memory-mapped register addressing
Like direct addressing, but the 9 high bits of the address are forced to 0 instead of coming from the DP. This reaches the memory-mapped registers (and scratch-pad RAM block B2, and page 0) without first changing the DP or an AR. Four instructions use this mode and leave the DP untouched:
| Instruction | Operation |
|---|---|
| LAMM | load the accumulator from a memory-mapped register |
| SAMM | store the accumulator to a memory-mapped register |
| LMMR | load a memory-mapped register |
| SMMR | store a memory-mapped register |
6. Circular addressing
A circular buffer implements a sliding window (used by convolution, correlation and FIR filters). The 'C5x supports two concurrent circular buffers driven by auxiliary registers and controlled by five memory-mapped registers:
| Register | Role |
|---|---|
| CBSR1 | buffer 1 start address |
| CBER1 | buffer 1 end address |
| CBSR2 | buffer 2 start address |
| CBER2 | buffer 2 end address |
| CBCR | 8-bit control register (enable bits and the AR selection) |
To set up a buffer: load its start and end addresses into the CBSR/CBER pair, load an AR with a value inside that range, and set the matching enable bit in the CBCR. Do not enable the same AR for both buffers. On every AR modification the ARAU applies:
if (ARn == CBER) and (any AR modification):
ARn = CBSR ; wrap to the start
else:
ARn = ARn + step ; normal update (step may be negative)
SPLK #0200h, CBSR1 ; buffer 1: 0200h .. 0203h
SPLK #0203h, CBER1
SPLK #0Eh, CBCR ; enable AR6 on buffer 1
LAR AR6, #0203h
LACC *+ ; AR6 was at CBER, so it wraps: AR6 = 0200h
How c5xtools encodes these
c5xasm parses the operand forms above and emits the exact fields shown here:
bit 7 selects direct vs indirect, the IDV/INC/DEC/N/NAR bits encode the *
update and any next-AR, and short vs long immediate selection follows the
instruction and the constant's width (with the reference assembler's
short-to-long auto-promotion). c5xdis decodes the same fields back into these
operand forms, which is why a disassembly re-assembles byte-for-byte. The
operand-form matrix is exercised by the toolchain's conformance test against the
TI golden objects.
License
MIT - (c) 2026 Grzegorz Worona [email protected]. See LICENSE.