Instruction Syntax
| Mnemonic | Format | Flags |
| lhax | 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 | 343 (Extended opcode) |
| Rc | 31 | Reserved (0) |
Operation
if rA = 0 then EA ← (rB) else EA ← (rA) + (rB) rD ← EXTS(MEM(EA, 2))
A halfword (16 bits) is loaded from memory, sign-extended to 32 bits, 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.
Note: This indexed form is essential for array access and dynamic addressing with signed 16-bit data. The sign extension preserves the sign of signed halfword values, making it ideal for processing signed integer arrays, sensor data, and audio samples. If rA=0, it is treated as the value 0, not the contents of register r0.
Affected Registers
None (load instruction does not affect condition registers).
For more information on memory addressing see Section 2.1.6, "Effective Address Calculation," in the PowerPC Microprocessor Family: The Programming Environments manual.
Examples
Matrix Operations with Signed Elements
# Access signed matrix elements using computed indices lis r3, signed_matrix@ha addi r3, r3, signed_matrix@l lwz r4, matrix_rows(r0) # Number of rows lwz r5, matrix_cols(r0) # Number of columns # Matrix element access: matrix[row][col] li r6, 2 # Row index li r7, 3 # Column index # Calculate element address: base + (row * cols + col) * 2 mullw r8, r6, r5 # row * cols add r9, r8, r7 # + col slwi r10, r9, 1 # * 2 (bytes per signed halfword) lhax r11, r3, r10 # Load signed matrix[row][col] # Process matrix element (already sign-extended) bl process_matrix_element # Process signed value in r11
Digital Signal Processing - Filter Coefficient Access
# Access filter coefficients with dynamic indexing
lis r3, filter_bank@ha
addi r3, r3, filter_bank@l
lis r4, coefficient_indices@ha
addi r4, r4, coefficient_indices@l
lwz r5, num_filters(r0) # Number of filters in bank
filter_processing_loop:
# Load coefficient index for current filter
lwz r6, 0(r4) # Load coefficient index
slwi r7, r6, 1 # Convert to byte offset
lhax r8, r3, r7 # Load signed filter coefficient
# Apply coefficient to signal processing
lwz r9, current_sample(r0) # Load current signal sample
mullw r10, r8, r9 # coefficient * sample
srawi r11, r10, 8 # Scale result (8-bit fractional)
# Store processed result
stw r11, processed_sample(r0)
addi r4, r4, 4 # Next coefficient index
subi r5, r5, 1 # Decrement filter counter
cmpwi r5, 0
bne filter_processing_loop # Continue processing
Game AI - Pathfinding Grid
# Navigate AI pathfinding grid with signed cost values
lis r3, pathfinding_grid@ha
addi r3, r3, pathfinding_grid@l
lwz r4, grid_width(r0) # Grid width
lwz r5, start_x(r0) # Starting X position
lwz r6, start_y(r0) # Starting Y position
lwz r7, target_x(r0) # Target X position
lwz r8, target_y(r0) # Target Y position
# A* pathfinding algorithm with signed movement costs
pathfinding_loop:
# Calculate current grid position
mullw r9, r6, r4 # current_y * grid_width
add r10, r9, r5 # + current_x
slwi r11, r10, 1 # Convert to byte offset
lhax r12, r3, r11 # Load movement cost (signed)
# Check for obstacles (negative costs indicate walls)
cmpwi r12, 0 # Check if passable
blt obstacle_found # Branch if obstacle
# Calculate movement in each direction
# North: y - 1
subi r13, r6, 1 # y - 1
cmpwi r13, 0 # Check bounds
blt check_south # Skip if out of bounds
mullw r14, r13, r4 # (y-1) * width
add r15, r14, r5 # + x
slwi r16, r15, 1 # Convert to byte offset
lhax r17, r3, r16 # Load north cell cost
cmpwi r17, 0 # Check if passable
bge calculate_north_cost # Calculate cost if passable
check_south:
# South: y + 1
addi r18, r6, 1 # y + 1
lwz r19, grid_height(r0) # Load grid height
cmpw r18, r19 # Check bounds
bge check_east # Skip if out of bounds
mullw r20, r18, r4 # (y+1) * width
add r21, r20, r5 # + x
slwi r22, r21, 1 # Convert to byte offset
lhax r23, r3, r22 # Load south cell cost
cmpwi r23, 0 # Check if passable
bge calculate_south_cost # Calculate cost if passable
check_east:
# East: x + 1
addi r24, r5, 1 # x + 1
cmpw r24, r4 # Check bounds (x < width)
bge check_west # Skip if out of bounds
mullw r25, r6, r4 # y * width
add r26, r25, r24 # + (x+1)
slwi r27, r26, 1 # Convert to byte offset
lhax r28, r3, r27 # Load east cell cost
cmpwi r28, 0 # Check if passable
bge calculate_east_cost # Calculate cost if passable
check_west:
# West: x - 1
subi r29, r5, 1 # x - 1
cmpwi r29, 0 # Check bounds
blt pathfinding_complete # Skip if out of bounds
mullw r30, r6, r4 # y * width
add r31, r30, r29 # + (x-1)
slwi r0, r31, 1 # Convert to byte offset
lhax r1, r3, r0 # Load west cell cost
cmpwi r1, 0 # Check if passable
bge calculate_west_cost # Calculate cost if passable
b pathfinding_complete
calculate_north_cost:
# Calculate heuristic cost to target
sub r2, r7, r5 # target_x - current_x
sub r3, r8, r13 # target_y - (current_y - 1)
abs r4, r2 # |delta_x|
abs r5, r3 # |delta_y|
add r6, r4, r5 # Manhattan distance
add r7, r17, r6 # movement_cost + heuristic
bl add_to_open_list # Add to pathfinding open list
b check_south
calculate_south_cost:
# Similar calculations for south direction
sub r8, r7, r5 # target_x - current_x
sub r9, r8, r18 # target_y - (current_y + 1)
abs r10, r8 # |delta_x|
abs r11, r9 # |delta_y|
add r12, r10, r11 # Manhattan distance
add r13, r23, r12 # movement_cost + heuristic
bl add_to_open_list # Add to pathfinding open list
b check_east
calculate_east_cost:
# Similar calculations for east direction
sub r14, r7, r24 # target_x - (current_x + 1)
sub r15, r8, r6 # target_y - current_y
abs r16, r14 # |delta_x|
abs r17, r15 # |delta_y|
add r18, r16, r17 # Manhattan distance
add r19, r28, r18 # movement_cost + heuristic
bl add_to_open_list # Add to pathfinding open list
b check_west
calculate_west_cost:
# Similar calculations for west direction
sub r20, r7, r29 # target_x - (current_x - 1)
sub r21, r8, r6 # target_y - current_y
abs r22, r20 # |delta_x|
abs r23, r21 # |delta_y|
add r24, r22, r23 # Manhattan distance
add r25, r1, r24 # movement_cost + heuristic
bl add_to_open_list # Add to pathfinding open list
b pathfinding_complete
obstacle_found:
bl handle_obstacle # Handle obstacle in pathfinding
pathfinding_complete:
bl get_next_open_node # Get next node from open list
# Continue pathfinding until target reached
Image Processing - Histogram Equalization
# Perform histogram equalization on signed image data
lis r3, signed_image@ha
addi r3, r3, signed_image@l
lis r4, histogram@ha
addi r4, r4, histogram@l
lwz r5, image_size(r0) # Total number of pixels
# First pass: build histogram
li r6, 0 # Pixel counter
histogram_build_loop:
slwi r7, r6, 1 # Convert pixel index to byte offset
lhax r8, r3, r7 # Load signed pixel value
# Normalize pixel value to histogram index (0-255)
# For signed 16-bit: map [-32768, 32767] to [0, 255]
addi r9, r8, 32768 # Shift to unsigned range [0, 65535]
srwi r10, r9, 8 # Scale to [0, 255]
# Increment histogram bin
slwi r11, r10, 2 # Convert to word offset
lwzx r12, r4, r11 # Load current histogram count
addi r13, r12, 1 # Increment count
stwx r13, r4, r11 # Store updated count
addi r6, r6, 1 # Next pixel
cmpw r6, r5 # Check if done with image
blt histogram_build_loop # Continue histogram building
# Second pass: calculate cumulative distribution function (CDF)
li r14, 0 # Cumulative sum
li r15, 0 # Histogram bin index
cdf_calculation_loop:
cmpwi r15, 256 # Check if done with all bins
bge equalization_pass
slwi r16, r15, 2 # Convert bin to word offset
lwzx r17, r4, r16 # Load histogram count
add r14, r14, r17 # Add to cumulative sum
# Store CDF value (normalized to 0-255 range)
mullw r18, r14, 255 # cumulative_sum * 255
divw r19, r18, r5 # / total_pixels
lis r20, cdf_table@ha
addi r20, r20, cdf_table@l
slwi r21, r15, 1 # Convert to halfword offset
sthx r19, r20, r21 # Store CDF value
addi r15, r15, 1 # Next histogram bin
b cdf_calculation_loop # Continue CDF calculation
equalization_pass:
# Third pass: apply histogram equalization
li r22, 0 # Pixel counter
equalization_loop:
slwi r23, r22, 1 # Convert pixel index to byte offset
lhax r24, r3, r23 # Load original signed pixel value
# Map pixel through equalization table
addi r25, r24, 32768 # Shift to unsigned range
srwi r26, r25, 8 # Scale to [0, 255] for table lookup
# Load equalized value from CDF table
lis r27, cdf_table@ha
addi r27, r27, cdf_table@l
slwi r28, r26, 1 # Convert to halfword offset
lhax r29, r27, r28 # Load equalized value
# Convert back to signed range [-32768, 32767]
slwi r30, r29, 8 # Scale back to 16-bit range
subi r31, r30, 32768 # Shift back to signed range
# Store equalized pixel
sthx r31, r3, r23 # Store equalized pixel value
addi r22, r22, 1 # Next pixel
cmpw r22, r5 # Check if done with image
blt equalization_loop # Continue equalization
Network Protocol - Packet Header Analysis
# Analyze network packet headers with signed field values
lis r3, packet_buffer@ha
addi r3, r3, packet_buffer@l
lis r4, field_offsets@ha
addi r4, r4, field_offsets@l
lwz r5, num_packets(r0) # Number of packets to analyze
packet_analysis_loop:
# Analyze custom protocol with signed header fields
# Field offsets vary based on protocol version
# Load protocol version to determine field layout
lwz r6, 0(r4) # Load version field offset
lhax r7, r3, r6 # Load protocol version (signed)
cmpwi r7, 0 # Check protocol version
blt legacy_protocol # Handle legacy versions (negative)
cmpwi r7, 10 # Check for newer versions
bge advanced_protocol # Handle advanced features
# Standard protocol processing
lwz r8, 4(r4) # Load sequence number offset
lhax r9, r3, r8 # Load signed sequence number
# Handle sequence number wraparound
lwz r10, expected_sequence(r0)
sub r11, r9, r10 # Calculate sequence delta
# Check for reasonable sequence progression
cmpwi r11, -100 # Check for reasonable negative delta
blt sequence_error # Handle sequence error
cmpwi r11, 100 # Check for reasonable positive delta
bgt sequence_error # Handle sequence error
# Load and validate checksum field
lwz r12, 8(r4) # Load checksum offset
lhax r13, r3, r12 # Load signed checksum
# Calculate expected checksum
bl calculate_checksum # Calculate checksum for packet
# Returns expected checksum in r14
cmpw r13, r14 # Compare checksums
bne checksum_error # Handle checksum mismatch
# Load priority field (can be negative for low priority)
lwz r15, 12(r4) # Load priority offset
lhax r16, r3, r15 # Load signed priority value
# Process based on priority
cmpwi r16, 0 # Check priority level
blt low_priority # Handle low priority packets
cmpwi r16, 100 # Check for high priority
bge high_priority # Handle high priority packets
# Normal priority processing
bl process_normal_packet
b next_packet
legacy_protocol:
# Handle legacy protocol versions (negative version numbers)
bl process_legacy_packet
b next_packet
advanced_protocol:
# Handle advanced protocol features
bl process_advanced_packet
b next_packet
sequence_error:
bl handle_sequence_error
b next_packet
checksum_error:
bl handle_checksum_error
b next_packet
low_priority:
bl queue_low_priority_packet
b next_packet
high_priority:
bl process_high_priority_packet
next_packet:
addi r3, r3, PACKET_SIZE # Next packet buffer
addi r4, r4, 16 # Next field offset set
subi r5, r5, 1 # Decrement packet counter
cmpwi r5, 0
bne packet_analysis_loop # Continue packet analysis