Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- .macro BEGIN_FUNCTION
- .align 2 // Align the function code to a 4-byte (2^n) word boundary.
- .arm // Use ARM instructions instead of Thumb.
- .globl _$0 // Make the function globally accessible.
- .no_dead_strip _$0 // Stop the optimizer from ignoring this function!
- .private_extern _$0
- _$0: // Declare the function.
- .endmacro
- .macro END_FUNCTION
- bx lr // Jump back to the caller.
- .endmacro
- BEGIN_FUNCTION asm_rgb_to_hsv
- //args:
- // r0 - image data in format "rgbrgb"
- // r1 - output in format "hsvhsv"
- // r2 - image size in pixels
- // Function prolog that saves all important registers.
- push {r4, r5, r6, r7, lr} // Save registers r4-r6 if used and Frame Pointer (r7) and Link Register (r14).
- add r7, sp, #12 // Adjust FP to point to the saved FP (r7).
- push {r8, r10, r11, r14} // Save any general registers that should be preserved.
- // If NEON instructions aren't available, don't execute anything.
- #if defined __ARM_NEON__
- lsr r2, r2, #1 // divide size by 2 - we operate on two pixels at the same time
- vmov.f32 d0, #1.0 // load 1 into two registers
- vmov.f32 d1, #1.0e-15
- vmov.f32 d10, #0.0
- vmov.f32 d7, #0.0 // v = 0
- vmov.f32 d6, #0.0 // s = 0
- vmov.f32 d5, #0.0 // h = 0
- vmov.f32 d11, #2.0 // later add 2 to h
- vmov.f32 d20, #6.0
- .loop_rh:
- vld3.32 {d2, d3, d4}, [r0]!
- vmax.f32 d2, d2, d1 // dX > 1 => dX = 1
- vmin.f32 d2, d2, d0 // dX < 1e-15 => dX = 1e-15
- vmax.f32 d3, d3, d1
- vmin.f32 d3, d3, d0
- vmax.f32 d4, d4, d1
- vmin.f32 d4, d4, d1
- vmax.f32 d7, d2, d3 // v = max(r,g,b)
- vmax.f32 d7, d7, d4
- vmin.f32 d8, d2, d3 // m = min(r,g,b)
- vmin.f32 d8, d8, d4
- vsub.f32 d8, d7, d8 // gap = v - m
- vceq.f32 d9, d8, d10 // d10 = gap == 0
- vand.f32 d12, d11, d9 // if v = m => v += 2
- vadd.f32 d7, d7, d12
- vand.f32 d0, d0, d9 // set gap to 1 where sat = 0
- vorr.f32 d8, d8, d0
- vrecpe.f32 d13, d8 // gap_inv = 1.0 / gap
- // if r == v
- vceq.f32 d14, d2, d7
- vsub.f32 d15, d3, d4 // h = (g - b) / gap
- vmul.f32 d15, d13, d15
- // fill h
- vand.f32 d16, d11, d14
- vadd.f32 d7, d7, d16
- vbit.f32 d5, d15, d14
- // if g == v
- vceq.f32 d14, d3, d7
- vsub.f32 d15, d4, d2
- vmul.f32 d15, d15, d13
- vadd.f32 d15, d15, d11
- vand.f32 d16, d11, d14
- vadd.f32 d7, d7, d16
- vbit.f32 d5, d15, d14
- // if b == v
- vadd.f32 d17, d11, d11
- vceq.f32 d14, d4, d7
- vsub.f32 d16, d2, d3
- vmul.f32 d16, d16, d13
- vadd.f32 d15, d17, d16
- vand.f32 d16, d11, d14
- vadd.f32 d7, d7, d16
- vbit.f32 d5, d15, d14
- // fill s if gap > 0
- vsub.f32 d5, d5, d11
- vrecpe.f32 d16, d5
- vmul.f32 d15, d8, d16
- vorn d6, d9, d15
- // check if h < 0
- vclt.f32 d14, d5, d10
- vand.f32 d16, d14, d20
- vadd.f32 d5, d5, d16
- vst3.32 {d5, d6, d7}, [r1]!
- subs r2, r2, #1 // decrease loop counter
- bne .loop_rh
- #endif //defined __ARM_NEON__
- // Function epilog that restores all important registers.
- pop {r8, r10, r11, r14} // Restore any general registers that were saved.
- pop {r4, r5, r6, r7, pc} // Restore saved registers, the saved FP (r7), and return to the caller (saved LR as PC).
- END_FUNCTION
Add Comment
Please, Sign In to add comment