lha
Load Halfword Algebraic - A8 00 00 00
lha

Instruction Syntax

Mnemonic Format Flags
lha rD,d(rA) -

Instruction Encoding

1
0
1
0
1
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 101010 (0x2A)
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 ← EXTS(MEM(EA, 2))

A halfword (16 bits) is loaded from memory and sign-extended to 32 bits, then placed in register rD. The effective address is computed by adding the sign-extended displacement to the contents of register rA, or zero if rA is 0.

Note: Unlike lhz which zero-extends, this instruction sign-extends the loaded halfword, preserving the sign for signed 16-bit values. This is essential for processing signed integer data such as audio samples, sensor readings, and signed array indices. 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

Audio Processing - 16-bit Signed Samples

# Process signed 16-bit audio samples
lis r3, audio_buffer@ha
addi r3, r3, audio_buffer@l
lwz r4, num_samples(r0)     # Number of audio samples

audio_processing_loop:
    lha r5, 0(r3)           # Load signed 16-bit audio sample
    
    # Apply audio effects (sample is properly sign-extended)
    # Amplification: multiply by gain factor
    lwz r6, gain_factor(r0) # Load gain (fixed-point)
    mullw r7, r5, r6        # Apply gain
    srawi r8, r7, 8         # Scale back (assuming 8-bit fractional part)
    
    # Clipping to prevent overflow
    cmpwi r8, 32767         # Check upper bound
    ble check_lower_bound
    li r8, 32767            # Clip to maximum

check_lower_bound:
    cmpwi r8, -32768        # Check lower bound
    bge store_sample
    li r8, -32768           # Clip to minimum

store_sample:
    sth r8, 0(r3)           # Store processed sample
    addi r3, r3, 2          # Next sample (2 bytes)
    subi r4, r4, 1          # Decrement counter
    cmpwi r4, 0
    bne audio_processing_loop # Continue processing

Sensor Data Acquisition

# Read signed sensor values from ADC
lis r3, sensor_readings@ha
addi r3, r3, sensor_readings@l
lwz r4, num_sensors(r0)     # Number of sensors

sensor_loop:
    lha r5, 0(r3)           # Load signed sensor reading
    
    # Convert to engineering units
    # Value = (ADC_reading * scale_factor) + offset
    lwz r6, scale_factor(r0) # Load scale factor
    mullw r7, r5, r6        # Multiply by scale
    lwz r8, offset_value(r0) # Load offset
    add r9, r7, r8          # Add offset
    
    # Store calibrated value
    stw r9, calibrated_readings(r4) # Store in calibrated array
    
    addi r3, r3, 2          # Next sensor reading
    subi r4, r4, 1          # Decrement counter
    cmpwi r4, 0
    bne sensor_loop         # Continue processing

Graphics Coordinate Processing

# Process signed 2D coordinates
lis r3, vertex_data@ha
addi r3, r3, vertex_data@l
lwz r4, num_vertices(r0)    # Number of vertices

vertex_loop:
    lha r5, 0(r3)           # Load signed X coordinate
    lha r6, 2(r3)           # Load signed Y coordinate
    
    # Transform coordinates (translation)
    lwz r7, viewport_x(r0)  # Viewport X offset
    lwz r8, viewport_y(r0)  # Viewport Y offset
    add r9, r5, r7          # Translate X
    add r10, r6, r8         # Translate Y
    
    # Clip to viewport bounds
    lwz r11, viewport_width(r0)
    lwz r12, viewport_height(r0)
    
    # Check X bounds
    cmpwi r9, 0             # Check lower bound
    bge check_x_upper
    li r9, 0                # Clip to 0

check_x_upper:
    cmpw r9, r11            # Check upper bound
    blt check_y_bounds
    mr r9, r11              # Clip to viewport width

check_y_bounds:
    cmpwi r10, 0            # Check Y lower bound
    bge check_y_upper
    li r10, 0               # Clip to 0

check_y_upper:
    cmpw r10, r12           # Check Y upper bound
    blt store_vertex
    mr r10, r12             # Clip to viewport height

store_vertex:
    sth r9, 0(r3)           # Store transformed X
    sth r10, 2(r3)          # Store transformed Y
    
    addi r3, r3, 4          # Next vertex (4 bytes = 2 halfwords)
    subi r4, r4, 1          # Decrement counter
    cmpwi r4, 0
    bne vertex_loop         # Continue processing

Digital Signal Processing - FIR Filter

# Implement FIR filter with signed coefficients and data
lis r3, signal_input@ha
addi r3, r3, signal_input@l
lis r4, filter_coefficients@ha
addi r4, r4, filter_coefficients@l
lwz r5, filter_order(r0)   # Number of filter taps
lwz r6, signal_length(r0)  # Number of input samples

fir_filter_loop:
    li r7, 0                # Initialize accumulator
    mr r8, r5               # Filter tap counter
    mr r9, r3               # Input pointer for this sample
    mr r10, r4              # Coefficient pointer

tap_loop:
    cmpwi r8, 0             # Check if done with taps
    beq sample_complete
    
    lha r11, 0(r9)          # Load signed input sample
    lha r12, 0(r10)         # Load signed filter coefficient
    
    # Multiply and accumulate: acc += input * coefficient
    mullw r13, r11, r12     # Multiply sample by coefficient
    add r7, r7, r13         # Accumulate
    
    subi r9, r9, 2          # Previous input sample
    addi r10, r10, 2        # Next coefficient
    subi r8, r8, 1          # Decrement tap counter
    b tap_loop              # Continue filter taps

sample_complete:
    # Scale result (assuming coefficients have fractional scaling)
    srawi r14, r7, 8        # Scale down (8-bit fractional part)
    
    # Store filtered output
    sth r14, filtered_output(r0)
    
    addi r3, r3, 2          # Next input sample
    subi r6, r6, 1          # Decrement sample counter
    cmpwi r6, 0
    bne fir_filter_loop     # Continue filtering

Data Compression - Delta Encoding

# Perform delta encoding on signed 16-bit data
lis r3, raw_data@ha
addi r3, r3, raw_data@l
lis r4, delta_encoded@ha
addi r4, r4, delta_encoded@l
lwz r5, data_length(r0)    # Number of data points

# Store first value as-is (no delta)
lha r6, 0(r3)              # Load first value
sth r6, 0(r4)              # Store first value unchanged
mr r7, r6                  # Previous value for delta calculation

addi r3, r3, 2             # Next input sample
addi r4, r4, 2             # Next output position
subi r5, r5, 1             # One less sample to process

delta_encoding_loop:
    lha r8, 0(r3)          # Load current signed sample
    
    # Calculate delta: delta = current - previous
    sub r9, r8, r7         # Calculate delta
    
    # Check if delta fits in 16-bit signed range
    cmpwi r9, 32767        # Check upper bound
    ble check_delta_lower
    
    # Delta too large - store full value with escape code
    li r10, 0x8000         # Escape code for full value
    sth r10, 0(r4)         # Store escape code
    addi r4, r4, 2         # Next output position
    sth r8, 0(r4)          # Store full value
    b delta_stored

check_delta_lower:
    cmpwi r9, -32768       # Check lower bound
    bge store_delta
    
    # Delta too small - store full value with escape code
    li r10, 0x8000         # Escape code for full value
    sth r10, 0(r4)         # Store escape code
    addi r4, r4, 2         # Next output position
    sth r8, 0(r4)          # Store full value
    b delta_stored

store_delta:
    sth r9, 0(r4)          # Store delta value

delta_stored:
    mr r7, r8              # Update previous value
    addi r3, r3, 2         # Next input sample
    addi r4, r4, 2         # Next output position
    subi r5, r5, 1         # Decrement counter
    cmpwi r5, 0
    bne delta_encoding_loop # Continue encoding

Network Protocol - Signed Field Processing

# Process network packet with signed header fields
lis r3, packet_header@ha
addi r3, r3, packet_header@l

# Custom protocol with signed fields
lha r4, 0(r3)              # Load signed packet type
lha r5, 2(r3)              # Load signed sequence number
lha r6, 4(r3)              # Load signed acknowledgment offset
lha r7, 6(r3)              # Load signed window size

# Validate packet type
cmpwi r4, -100             # Check minimum valid type
blt invalid_packet
cmpwi r4, 100              # Check maximum valid type
bgt invalid_packet

# Process sequence number wraparound
lwz r8, expected_sequence(r0) # Load expected sequence
sub r9, r5, r8             # Calculate sequence difference

# Handle wraparound in signed arithmetic
cmpwi r9, 16384            # Half of 16-bit range
blt check_negative_wrap
subi r9, r9, 65536         # Adjust for positive wraparound

check_negative_wrap:
cmpwi r9, -16384           # Negative half of range
bgt sequence_ok
addi r9, r9, 65536         # Adjust for negative wraparound

sequence_ok:
cmpwi r9, 0                # Check if in order
bge packet_in_order
# Handle out-of-order packet
bl handle_out_of_order

packet_in_order:
# Process acknowledgment offset (signed relative to current position)
lwz r10, current_ack_base(r0)
add r11, r10, r6           # Calculate absolute acknowledgment

# Validate acknowledgment range
lwz r12, min_valid_ack(r0)
lwz r13, max_valid_ack(r0)
cmpw r11, r12              # Check minimum
blt invalid_ack
cmpw r11, r13              # Check maximum  
bgt invalid_ack

# Process window size (can be negative for flow control)
cmpwi r7, 0                # Check if window closed
bge window_open
# Handle closed window
bl handle_flow_control
b packet_complete

window_open:
# Update flow control window
stw r7, peer_window_size(r0)

packet_complete:
bl process_packet_payload
b packet_done

invalid_packet:
bl handle_invalid_packet

invalid_ack:
bl handle_invalid_ack

packet_done:

Mathematical Computation - Fixed-Point Arithmetic

# Perform fixed-point arithmetic with signed 16.16 format
lis r3, fixed_point_array@ha
addi r3, r3, fixed_point_array@l
lwz r4, array_size(r0)     # Number of elements

# Each element is 32-bit: high 16 bits = integer, low 16 bits = fraction
# We'll load the high part as signed for proper arithmetic

fixed_point_loop:
    lwz r5, 0(r3)          # Load full 32-bit fixed-point value
    
    # Extract integer and fractional parts
    lha r6, 0(r3)          # Load high 16 bits (integer part, signed)
    lhz r7, 2(r3)          # Load low 16 bits (fractional part, unsigned)
    
    # Perform mathematical operation: sqrt approximation using Newton's method
    # For demonstration: x_new = (x + n/x) / 2
    
    # Convert to approximate floating-point for calculation
    slwi r8, r6, 16        # Shift integer part to high bits
    or r9, r8, r7          # Combine integer and fractional parts
    
    # Simple square root approximation (for positive values)
    cmpwi r6, 0            # Check if positive
    ble skip_sqrt          # Skip negative values
    
    # Initial guess: x0 = n/2 (very rough)
    srawi r10, r9, 1       # x0 = n/2
    
    # Newton iteration: x1 = (x0 + n/x0) / 2
    divw r11, r9, r10      # n/x0
    add r12, r10, r11      # x0 + n/x0
    srawi r13, r12, 1      # (x0 + n/x0) / 2
    
    # Second iteration for better accuracy
    divw r14, r9, r13      # n/x1
    add r15, r13, r14      # x1 + n/x1
    srawi r16, r15, 1      # Final approximation
    
    # Store result back in fixed-point format
    stw r16, 0(r3)         # Store computed square root
    b continue_processing

skip_sqrt:
    # For negative numbers, store absolute value
    neg r17, r9            # Absolute value
    stw r17, 0(r3)         # Store absolute value

continue_processing:
    addi r3, r3, 4         # Next fixed-point value
    subi r4, r4, 1         # Decrement counter
    cmpwi r4, 0
    bne fixed_point_loop   # Continue processing

Game Engine - Sprite Animation

# Process sprite animation with signed offset values
lis r3, sprite_data@ha
addi r3, r3, sprite_data@l
lwz r4, num_sprites(r0)    # Number of sprites

sprite_animation_loop:
    # Load sprite position and animation data
    lwz r5, 0(r3)          # Base X position
    lwz r6, 4(r3)          # Base Y position
    lha r7, 8(r3)          # Signed X animation offset
    lha r8, 10(r3)         # Signed Y animation offset
    lha r9, 12(r3)         # Animation frame (can be negative for reverse)
    lha r10, 14(r3)        # Animation speed (signed for direction)
    
    # Update animation frame
    add r11, r9, r10       # frame += speed
    
    # Check animation bounds
    cmpwi r11, 0           # Check if frame went negative
    bge check_upper_bound
    li r11, 0              # Clamp to 0

check_upper_bound:
    lwz r12, max_animation_frame(r0)
    cmpw r11, r12          # Check if exceeded maximum
    ble frame_ok
    mr r11, r12            # Clamp to maximum

frame_ok:
    # Calculate current sprite position with animation offset
    add r13, r5, r7        # current_x = base_x + offset_x
    add r14, r6, r8        # current_y = base_y + offset_y
    
    # Apply frame-based animation displacement
    mullw r15, r11, r10    # frame * speed
    srawi r16, r15, 4      # Scale down animation displacement
    add r17, r13, r16      # Apply horizontal animation
    
    # Check screen bounds
    cmpwi r17, 0           # Check left bound
    bge check_right_bound
    li r17, 0              # Clamp to left edge

check_right_bound:
    lwz r18, screen_width(r0)
    cmpw r17, r18          # Check right bound
    blt check_vertical
    mr r17, r18            # Clamp to right edge

check_vertical:
    cmpwi r14, 0           # Check top bound
    bge check_bottom_bound
    li r14, 0              # Clamp to top edge

check_bottom_bound:
    lwz r19, screen_height(r0)
    cmpw r14, r19          # Check bottom bound
    blt update_sprite
    mr r14, r19            # Clamp to bottom edge

update_sprite:
    # Store updated sprite data
    stw r17, 0(r3)         # Store new X position
    stw r14, 4(r3)         # Store new Y position
    sth r11, 12(r3)        # Store updated animation frame
    
    # Render sprite at new position
    bl render_sprite       # Render sprite
    
    addi r3, r3, 16        # Next sprite (16 bytes per sprite)
    subi r4, r4, 1         # Decrement counter
    cmpwi r4, 0
    bne sprite_animation_loop # Continue animation

Related Instructions

lhz, lhau, lhax, lhaux, sth, lbz

Back to Index