What is ARM7TDMI
Keith Gangarahwe
@keith-gang
Introducing the ARM7TDMI Architecture
Delving into the fundamentals of systems development often brings us face-to-face with historical yet foundational architectures. Today, we turn our attention to the ARM7TDMI, a cornerstone processor that has powered countless devices. Drawing directly from the comprehensive ARM7TDMI Technical Reference Manual, and building upon our previous discussions regarding its interpreter, let’s explore the core principles that define this classic RISC design.
ARM7TDMI Assembly Example(Inline Assembly in Zig)
export fn _start() callconv(.naked) noreturn {
asm volatile (
// 1. SETUP
\\ ldr sp, =0x4000
// 2. Prepare Precious Data
\\ mov r0, #10
\\ mov r1, #50
\\ mov r2, #100
// 3. The PUSH: Save State
\\ stmdb sp!, {r0-r2} // Store Multiple Decrement Before (Standard Push), "!" updates SP to the new location
// 4. THE DESTRUCTION (Simulate Work)
\\ mov r0, #0 // Clobber registers
\\ mov r1, #0
\\ mov r2, #0
// 5. THE "POP" (Restore State)
// LDMIA = Load Multiple Increment After (Standard Pop)
\\ ldmia sp!, {r0-r2}
// 6. LOOP
\\ loop: b loop
);
while (true) {}
}1. Core Philosophy: Load/Store RISC
The ARM7TDMI is a RISC (Reduced Instruction Set Computer) processor. It follows a Load/Store architecture, meaning the CPU cannot process data directly in memory.
- To change data: You must load it from RAM into a register, modify it, and store it back.
- Pipeline: It uses a 3-stage pipeline (Fetch, Decode, Execute). As a result, the Program Counter (PC) always points 8 bytes ahead of the instruction currently executing.
2. The Register Layout (The “Workbench”)
Although the processor has 37 total registers, in standard User Mode you have access to 16 general-purpose 32-bit registers (r0–r15) and one Status Register.
- r0 – r12: General-purpose registers for holding variables and math results.
- r13 (SP): The Stack Pointer. By convention, this points to the top of the active stack in memory.
- r14 (LR): The Link Register. When you call a function (using
BL), the CPU automatically saves the return address here. - r15 (PC): The Program Counter. It holds the address of the instruction stream. Writing to this register causes a jump.
- CPSR: The Current Program Status Register. It holds the condition flags (Negative, Zero, Carry, oVerflow) and the current Mode bits (User, IRQ, Supervisor, etc.).
Banked Registers: When an exception occurs (like an interrupt), the hardware physically swaps out specific registers (like r13 and r14) for “shadow” copies (e.g., r13_irq) to preserve the main program’s state.
3. Data Processing: MOV, ADD, SUB
These instructions operate only on registers. They can optionally update the CPSR flags if the S suffix is used (e.g., MOVS, ADDS).
MOV Rd, <Op2>(Move): Copies a value into a destination register.- Example:
MOV r0, #10(Put 10 into r0).
- Example:
ADD Rd, Rn, <Op2>(Add): Adds two values.- Example:
ADD r0, r1, r2(r0 = r1 + r2).
- Example:
SUB Rd, Rn, <Op2>(Subtract): Subtracts the third operand from the second.- Example:
SUB r0, r1, #5(r0 = r1 - 5).
- Example:
Operand 2 (Barrel Shifter): The second operand (<Op2>) passes through a barrel shifter before entering the ALU. This allows you to shift and calculate in a single cycle, e.g., ADD r0, r1, r1, LSL #2 (r0 = r1 + r1*4).
4. Memory Access: LDR
Since ARM cannot do math on memory, LDR (Load Register) is used to fetch data.
LDR Rd, [Rn, <Offset>]: Loads a 32-bit word from the address calculated byRn + Offset.- Example:
LDR r0, [r1, #4](Go to the address in r1 plus 4 bytes, read the value, place it in r0). - Addressing Modes: It supports Pre-indexing (update address before load) and Post-indexing (load then update address).
5. Flow Control: BL
To handle function calls, ARM uses Branch with Link.
B Label: Simple jump (GOTO).BL Label(Call)::- Calculates the address of the next instruction.
- Saves that address into r14 (Link Register).
- Jumps to the target Label.
- To Return: You simply copy LR back into PC:
MOV pc, lr.
6. The Stack: STMDB, LDMIA
ARM is unique in that it moves multiple registers in a single instruction. This is used for stack operations.
STMDB(Store Multiple Decrement Before): The standard “Push”.- Logic: Decrease the pointer, then store data.
- Usage:
STMDB sp!, {r0-r3, lr}(Save working registers and the return address to the stack).
LDMIA(Load Multiple Increment After): The standard “Pop”.- Logic: Read data, then increase the pointer.
- Usage:
LDMIA sp!, {r0-r3, pc}(Restore working registers and pop the saved return address directly into the PC to return from the function).
These block transfers are highly optimized and are critical for efficient context switching and interrupt handling.
Our next post will dive into a short debugging session using GDB to see the register layout in action.