lwzx
Load Word and Zero Indexed - 7C 00 00 2E
lwzx

Instruction Syntax

Mnemonic Format Flags
lwzx rD,rA,rB -

Instruction Encoding

0
1
1
1
1
1
D
D
D
D
D
A
A
A
A
A
B
B
B
B
B
0
0
0
0
0
1
0
1
1
1
/

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:

Related Instructions

lwz, lwzu, lwzux, stwx, lbzx, lhzx

Back to Index