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: