Instruction Syntax
| Mnemonic | Format | Flags |
| lwzx | rD,rA,rB | - |
Instruction Encoding
| Field | Bits | Description |
| Primary Opcode | 0-5 | 011111 (0x1F) |
| rD | 6-10 | Destination register |
| rA | 11-15 | Source register A |
| rB | 16-20 | Source register B |
| XO | 21-30 | 23 (Extended opcode) |
| Rc | 31 | Reserved (0) |
Operation
if rA = 0 then EA ← (rB) else EA ← (rA) + (rB) rD ← MEM(EA, 4)
A word (32 bits) is loaded from memory and placed in register rD. The effective address is computed by adding the contents of registers rA and rB, or just rB if rA is 0. This is the indexed form of the basic word load instruction.
Note: This indexed form is essential for array access and dynamic addressing. As specified in the Iowa State PowerPC Assembly Quick Reference, this instruction performs rD ← M[rA + rB]. The effective address should be word-aligned (divisible by 4) for optimal performance. If rA=0, it is treated as the value 0, not the contents of register 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
Array Element Access
# Access 32-bit array element by index lis r3, int_array@ha addi r3, r3, int_array@l li r4, 25 # Array index slwi r5, r4, 2 # Multiply by 4 (sizeof(int)) lwzx r6, r3, r5 # Load int_array[25] # Access with dynamic indexing lwz r7, dynamic_index(r0) # Load index from variable slwi r8, r7, 2 # Convert to byte offset lwzx r9, r3, r8 # Load int_array[dynamic_index]
Function Pointer Table
# Call function through pointer table using indexed access
lis r3, function_table@ha
addi r3, r3, function_table@l
lwz r4, function_id(r0) # Load function ID (0-based)
slwi r5, r4, 2 # Convert to pointer offset
lwzx r6, r3, r5 # Load function pointer
# Validate function pointer
cmpwi r6, 0
beq invalid_function # Branch if null pointer
# Set up function call
mtctr r6 # Move to count register
# Set up parameters in r3, r4, r5...
bctrl # Call function
invalid_function:
# Handle invalid function ID
bl error_handler
Hash Table Implementation
# Hash table lookup with collision handling
lis r3, hash_table@ha
addi r3, r3, hash_table@l
lwz r4, search_key(r0) # Key to search for
li r5, HASH_TABLE_SIZE # Table size (power of 2)
subi r6, r5, 1 # Create mask
# Calculate hash: key % table_size
and r7, r4, r6 # Simple hash using mask
slwi r8, r7, 2 # Convert to word offset
lwzx r9, r3, r8 # Load hash_table[hash_key]
# Check if slot is empty or matches
cmpwi r9, 0 # Empty slot
beq key_not_found
cmpw r9, r4 # Compare with search key
beq key_found # Direct hit
# Linear probing for collision resolution
li r10, 1 # Probe distance
probe_loop:
add r11, r7, r10 # Next probe position
and r11, r11, r6 # Wrap around using mask
slwi r12, r11, 2 # Convert to byte offset
lwzx r13, r3, r12 # Load hash_table[probe_pos]
cmpwi r13, 0 # Check if empty
beq key_not_found # Not found
cmpw r13, r4 # Compare with search key
beq key_found_probe # Found at probe position
addi r10, r10, 1 # Increase probe distance
cmpw r10, r5 # Check if wrapped entire table
blt probe_loop # Continue probing
# Table full or key not found
b key_not_found
key_found:
mr r14, r8 # Return original position
b search_done
key_found_probe:
mr r14, r12 # Return probe position
b search_done
key_not_found:
li r14, -1 # Return not found
search_done:
Object-Oriented Virtual Method Call
# Call virtual method using indexed vtable access
lis r3, object_ptr@ha
lwz r4, object_ptr@l(r3) # Load object pointer
lwz r5, 0(r4) # Load vtable pointer (first member)
lwz r6, method_index(r0) # Load method index
slwi r7, r6, 2 # Convert to pointer offset
lwzx r8, r5, r7 # Load method pointer from vtable
# Validate method pointer
cmpwi r8, 0
beq invalid_method # Branch if null
# Set up method call (C++ style)
mr r3, r4 # Pass object as 'this' pointer
# Additional parameters in r4, r5, r6...
mtctr r8 # Set up call
bctrl # Call virtual method
invalid_method:
# Handle invalid method
bl method_error_handler
Data Structure Traversal
# Traverse linked list using indexed access
lis r3, node_array@ha
addi r3, r3, node_array@l
lwz r4, head_index(r0) # Load head node index
# Node structure: [data, next_index, prev_index, flags]
# Each field is 4 bytes (32-bit)
traverse_list:
cmpwi r4, -1 # Check for end marker
beq list_end # Branch if end of list
# Calculate node address
li r5, 16 # sizeof(Node) = 4 * 4 bytes
mullw r6, r4, r5 # node_index * sizeof(Node)
# Load node data using indexed access
li r7, 0 # Offset for data field
lwzx r8, r3, r6 # Load node.data (r6 + 0)
# Load next index
li r7, 4 # Offset for next field
add r9, r6, r7 # Calculate address
lwzx r10, r3, r9 # Load node.next_index
# Load previous index
li r7, 8 # Offset for prev field
add r9, r6, r7 # Calculate address
lwzx r11, r3, r9 # Load node.prev_index
# Load flags
li r7, 12 # Offset for flags field
add r9, r6, r7 # Calculate address
lwzx r12, r3, r9 # Load node.flags
# Process node data
mr r3, r8 # Pass data to processor
bl process_node_data # Process the node
# Check flags for special handling
andi. r13, r12, 0x01 # Check delete flag
bne mark_for_deletion
andi. r13, r12, 0x02 # Check skip flag
bne skip_to_next
# Continue normal processing
bl additional_processing
skip_to_next:
# Move to next node
mr r4, r10 # Update current index
b traverse_list # Continue traversal
mark_for_deletion:
# Add to deletion list
bl add_to_delete_list
b skip_to_next
list_end:
Memory Pool Management
# Manage memory pool with indexed block access
lis r3, memory_pool@ha
addi r3, r3, memory_pool@l
lis r4, block_headers@ha
addi r4, r4, block_headers@l
lwz r5, requested_size(r0) # Size requested by caller
# Block header: [size, free_flag, next_free, prev_free]
# Each header is 16 bytes
find_free_block:
lwz r6, first_free_index(r0) # Load first free block index
search_loop:
cmpwi r6, -1 # Check for end of free list
beq no_free_blocks # No suitable block found
# Calculate header address
li r7, 16 # sizeof(BlockHeader)
mullw r8, r6, r7 # index * sizeof(BlockHeader)
# Load block size
li r9, 0 # Offset for size field
lwzx r10, r4, r8 # Load block.size
# Check if block is large enough
cmpw r10, r5 # Compare block size with requested
blt try_next_block # Too small, try next
# Load free flag to double-check
li r9, 4 # Offset for free_flag field
add r11, r8, r9 # Calculate address
lwzx r12, r4, r11 # Load block.free_flag
cmpwi r12, 1 # Verify block is free
bne try_next_block # Not free, try next
# Found suitable block
b allocate_block
try_next_block:
# Load next free block index
li r9, 8 # Offset for next_free field
add r11, r8, r9 # Calculate address
lwzx r6, r4, r11 # Load block.next_free
b search_loop # Continue search
allocate_block:
# Mark block as allocated
li r12, 0 # Not free
li r9, 4 # Offset for free_flag
add r11, r8, r9 # Calculate address
stwx r12, r4, r11 # Store free_flag = 0
# Calculate data address in memory pool
li r13, BLOCK_DATA_SIZE # Size of data area per block
mullw r14, r6, r13 # block_index * data_size
add r15, r3, r14 # memory_pool + offset
# Return pointer to allocated memory
mr r3, r15 # Return data pointer
b allocation_done
no_free_blocks:
li r3, 0 # Return null pointer
allocation_done:
Graphics Buffer Management
# Access 3D vertex data using indexed addressing lis r3, vertex_buffer@ha addi r3, r3, vertex_buffer@l lwz r4, vertex_index(r0) # Which vertex to access li r5, 32 # sizeof(Vertex) = 8 floats * 4 bytes # Vertex structure: [x, y, z, w, nx, ny, nz, color] # Each component is 4 bytes (32-bit float or int) # Calculate vertex address mullw r6, r4, r5 # vertex_index * sizeof(Vertex) # Load vertex position li r7, 0 # Offset for x lwzx r8, r3, r6 # Load x coordinate (as int bits) li r7, 4 # Offset for y add r9, r6, r7 # Calculate address lwzx r10, r3, r9 # Load y coordinate li r7, 8 # Offset for z add r9, r6, r7 # Calculate address lwzx r11, r3, r9 # Load z coordinate li r7, 12 # Offset for w add r9, r6, r7 # Calculate address lwzx r12, r3, r9 # Load w coordinate # Load vertex normal li r7, 16 # Offset for nx add r9, r6, r7 # Calculate address lwzx r13, r3, r9 # Load normal x li r7, 20 # Offset for ny add r9, r6, r7 # Calculate address lwzx r14, r3, r9 # Load normal y li r7, 24 # Offset for nz add r9, r6, r7 # Calculate address lwzx r15, r3, r9 # Load normal z # Load vertex color li r7, 28 # Offset for color add r9, r6, r7 # Calculate address lwzx r16, r3, r9 # Load color (RGBA packed) # Transform vertex using transformation matrix # (Matrix operations would use the loaded values...) # Store transformed vertex back to buffer # (Store operations would write back modified values...)
Database Index Operations
# B-tree index node traversal using indexed access
lis r3, btree_nodes@ha
addi r3, r3, btree_nodes@l
lwz r4, root_node_index(r0) # Start at root
lwz r5, search_key(r0) # Key to search for
li r6, 64 # sizeof(BTreeNode)
# BTreeNode structure:
# [num_keys, is_leaf, keys[15], children[16]]
# num_keys: 4 bytes, is_leaf: 4 bytes
# keys: 15 * 4 = 60 bytes, children: 16 * 4 = 64 bytes
# Total: 132 bytes (padded to 136 for alignment)
search_btree:
cmpwi r4, -1 # Check for null node
beq key_not_found # Reached null, key not found
# Calculate node address
li r7, 136 # sizeof(BTreeNode) with padding
mullw r8, r4, r7 # node_index * sizeof(BTreeNode)
# Load number of keys
li r9, 0 # Offset for num_keys
lwzx r10, r3, r8 # Load node.num_keys
# Load leaf flag
li r9, 4 # Offset for is_leaf
add r11, r8, r9 # Calculate address
lwzx r12, r3, r11 # Load node.is_leaf
# Search for key position in node
li r13, 0 # Key index
li r14, 8 # Offset to first key
key_search_loop:
cmpw r13, r10 # Check if searched all keys
bge key_greater_than_all
add r15, r8, r14 # Calculate key address
lwzx r16, r3, r15 # Load key[i]
cmpw r5, r16 # Compare search_key with current key
beq key_found_exact # Exact match
blt key_found_position # Search key is smaller
addi r13, r13, 1 # Next key
addi r14, r14, 4 # Next key offset
b key_search_loop
key_found_exact:
# Found exact key
mr r3, r4 # Return node index
mr r4, r13 # Return key index
b search_complete
key_found_position:
key_greater_than_all:
# Check if this is a leaf node
cmpwi r12, 1 # is_leaf == 1?
beq key_not_found # Not found in leaf
# Move to appropriate child
li r17, 68 # Offset to children array (8 + 60)
slwi r18, r13, 2 # child_index * 4
add r19, r17, r18 # Calculate child offset
add r20, r8, r19 # Calculate child address
lwzx r4, r3, r20 # Load child node index
b search_btree # Continue search in child
key_not_found:
li r3, -1 # Return not found
li r4, -1
search_complete: