lwz
Load Word and Zero - 80 00 00 00
lwz

Instruction Syntax

Mnemonic Format Flags
lwz rD,d(rA) -

Instruction Encoding

1
0
0
0
0
0
D
D
D
D
D
A
A
A
A
A
d
d
d
d
d
d
d
d
d
d
d
d
d
d
d
d

Field Bits Description
Primary Opcode 0-5 100000 (0x20)
rD 6-10 Destination register
rA 11-15 Source register A
d 16-31 16-bit signed displacement

Operation

if rA = 0 then EA ← EXTS(d)
else EA ← (rA) + EXTS(d)
rD ← MEM(EA, 4)

LWZ loads a 32-bit word from memory into a register. It calculates the memory address by adding a signed offset to a base register.

  1. Calculates address = base register + offset (or just offset if base register is r0)
  2. Loads the 32-bit word from that memory address
  3. Stores the word in the destination register

Note: This is the most commonly used load instruction in PowerPC. The memory address must be aligned to 4 bytes. If you use r0 as the base register, it's treated as 0 (not the contents of r0).

Affected Registers

None - This instruction does not affect any condition register fields or XER register bits.

For more information on memory addressing see Section 2.1.6, "Effective Address Calculation," in the PowerPC Microprocessor Family: The Programming Environments manual.

Examples

Basic Word Loading

lwz r3, 0(r1)           # Load word from address in r1
lwz r4, 100(r2)         # Load word from address r2+100
lwz r5, -50(r3)         # Load word from address r3-50

Loading from Absolute Address

lwz r3, 0x1000(r0)      # Load word from absolute address 0x1000
# Note: r0 treated as value 0, not register contents

Structure Member Access

# Load structure members (C-style struct)
# struct Point { int x; int y; int z; };
lis r3, point_data@ha
addi r3, r3, point_data@l

lwz r4, 0(r3)           # Load x member (offset 0)
lwz r5, 4(r3)           # Load y member (offset 4)  
lwz r6, 8(r3)           # Load z member (offset 8)

Array Element Access

# Access elements in word array
lis r3, int_array@ha
addi r3, r3, int_array@l
li r4, 5                # Array index
slwi r5, r4, 2          # Multiply index by 4 (sizeof(int))
lwzx r6, r3, r5         # Load array[5] using indexed addressing
# Or using displacement:
lwz r7, 20(r3)          # Load array[5] directly (5*4=20)

Function Pointer Loading and Calling

# Load and call function through pointer
lis r3, function_table@ha
addi r3, r3, function_table@l
li r4, 2                # Function index
slwi r4, r4, 2          # Multiply by sizeof(pointer)
lwzx r5, r3, r4         # Load function pointer
mtctr r5                # Move to count register
bctrl                   # Call function

Global Variable Access

# Access global variables through GOT/TOC
lis r3, global_var@ha
lwz r4, global_var@l(r3) # Load global variable value

# Alternative for position-independent code
lis r3, _GLOBAL_OFFSET_TABLE_@ha
addi r3, r3, _GLOBAL_OFFSET_TABLE_@l
lwz r4, global_var@got(r3) # Load address from GOT
lwz r5, 0(r4)           # Load actual value

Stack Frame Access

# Access stack frame variables
# Function prologue
stwu r1, -64(r1)        # Create stack frame
stw r31, 60(r1)         # Save r31

# Access local variables (negative offsets from frame pointer)
lwz r3, 8(r1)           # Load local variable at offset 8
lwz r4, 12(r1)          # Load local variable at offset 12

# Access parameters (positive offsets from original stack pointer)
lwz r5, 68(r1)          # Load parameter (64 + 4)
lwz r6, 72(r1)          # Load next parameter

Object-Oriented Method Call

# Load virtual function table and call method
lis r3, object_ptr@ha
lwz r4, object_ptr@l(r3) # Load object pointer
lwz r5, 0(r4)           # Load vtable pointer (first member)
li r6, 2                # Method index
slwi r6, r6, 2          # Convert to byte offset
lwzx r7, r5, r6         # Load method pointer from vtable
mtctr r7                # Set up call
mr r3, r4               # Pass object as 'this' pointer
bctrl                   # Call virtual method

Configuration Register Access

# Load device configuration registers
lis r3, device_base@ha
addi r3, r3, device_base@l

lwz r4, DEVICE_ID(r3)   # Load device ID register
lwz r5, STATUS_REG(r3)  # Load status register
lwz r6, CONFIG_REG(r3)  # Load configuration register

# Check device status
andi. r7, r5, 0x0001    # Check ready bit
beq device_not_ready    # Branch if not ready
andi. r7, r5, 0x8000    # Check error bit
bne device_error        # Branch if error

Linked List Traversal

# Traverse singly-linked list
# struct Node { int data; struct Node* next; };
lis r3, list_head@ha
lwz r4, list_head@l(r3) # Load head pointer

traverse_list:
    cmpwi r4, 0         # Check for null pointer
    beq list_end        # Branch if end of list
    
    lwz r5, 0(r4)       # Load data member
    # Process data in r5
    bl process_data
    
    lwz r4, 4(r4)       # Load next pointer
    b traverse_list     # Continue traversal

list_end:

Hash Table Lookup

# Hash table lookup with chaining
lis r3, hash_table@ha
addi r3, r3, hash_table@l
li r4, 0x12345678       # Key to search for
li r5, 256              # Hash table size
rlwinm r6, r4, 0, 24, 31 # Simple hash: key % 256
slwi r6, r6, 2          # Convert to word offset
lwzx r7, r3, r6         # Load bucket head pointer

search_bucket:
    cmpwi r7, 0         # Check for null pointer
    beq key_not_found   # Branch if end of chain
    
    lwz r8, 0(r7)       # Load key from entry
    cmpw r8, r4         # Compare with search key
    beq key_found       # Branch if match
    
    lwz r7, 8(r7)       # Load next pointer (skip value at offset 4)
    b search_bucket     # Continue chain traversal

key_found:
    lwz r9, 4(r7)       # Load value from entry
    # r9 contains the found value
    b lookup_done

key_not_found:
    li r9, 0            # Return null/not found
    
lookup_done:

Graphics Vertex Loading

# Load 3D vertex data for graphics processing
# struct Vertex { float x, y, z; int color; };
lis r3, vertex_array@ha
addi r3, r3, vertex_array@l
li r4, 5                # Vertex index
li r5, 16               # sizeof(Vertex) = 4 floats
mullw r6, r4, r5        # Calculate byte offset
add r7, r3, r6          # Vertex address

lwz r8, 0(r7)           # Load x coordinate (as int bits)
lwz r9, 4(r7)           # Load y coordinate (as int bits)
lwz r10, 8(r7)          # Load z coordinate (as int bits)
lwz r11, 12(r7)         # Load color value

# Move to floating-point registers for processing
stw r8, temp_x(r1)      # Store to stack
stw r9, temp_y(r1)
stw r10, temp_z(r1)
lfs f1, temp_x(r1)      # Load into FP registers
lfs f2, temp_y(r1)
lfs f3, temp_z(r1)

File Header Parsing

# Parse binary file header
lis r3, file_buffer@ha
addi r3, r3, file_buffer@l

lwz r4, 0(r3)           # Load magic number/signature
lwz r5, 4(r3)           # Load version number
lwz r6, 8(r3)           # Load file size
lwz r7, 12(r3)          # Load header size
lwz r8, 16(r3)          # Load number of sections

# Validate header
lis r9, MAGIC_SIGNATURE@ha
ori r9, r9, MAGIC_SIGNATURE@l
cmpw r4, r9             # Check magic number
bne invalid_file        # Branch if invalid

cmpwi r5, SUPPORTED_VERSION # Check version
bne unsupported_version # Branch if unsupported

# Header validated, process sections
mr r10, r3              # Current position
add r10, r10, r7        # Skip to first section
mr r11, r8              # Section counter

process_sections:
    cmpwi r11, 0        # Check if more sections
    beq file_done       # Branch if done
    
    lwz r12, 0(r10)     # Load section type
    lwz r13, 4(r10)     # Load section size
    
    # Process section based on type
    bl process_section  # Pass r12=type, r13=size, r10=data
    
    add r10, r10, r13   # Move to next section
    subi r11, r11, 1    # Decrement section counter
    b process_sections

file_done:

Memory Pool Management

# Memory pool allocation tracking
# struct Block { size_t size; int free; struct Block* next; };
lis r3, memory_pool@ha
addi r3, r3, memory_pool@l
lwz r4, 0(r3)           # Load first block pointer
li r5, 1024             # Requested size

find_free_block:
    cmpwi r4, 0         # Check for null pointer
    beq no_free_blocks  # Branch if no more blocks
    
    lwz r6, 0(r4)       # Load block size
    lwz r7, 4(r4)       # Load free flag
    
    cmpwi r7, 1         # Check if block is free
    bne next_block      # Skip if not free
    
    cmpw r6, r5         # Compare size with requested
    bge block_found     # Branch if suitable size
    
next_block:
    lwz r4, 8(r4)       # Load next block pointer
    b find_free_block   # Continue search

block_found:
    li r7, 0            # Mark block as allocated
    stw r7, 4(r4)       # Update free flag
    addi r3, r4, 12     # Return pointer to data area
    b allocation_done

no_free_blocks:
    li r3, 0            # Return null pointer

allocation_done:

Related Instructions

lwzu, lwzx, lwzux, stw, lbz, lhz, lmw

Back to Index