Revision control
++ // Copyright (C) 2013 Imagination Technologies Limited, www.imgtec.com
++ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
++ // Qt-Security score:critical reason:data-parser
++
++ #include "../../gui/painting/qt_mips_asm_dsp_p.h"
++
++ .macro EXTRACT_HALVES_x2 src1, src2, hi_1, hi_2
++ #if defined(__MIPSEL) && __MIPSEL
++ srl \hi_1, \src1, 16
++ ext \src1, \src1, 0, 16
++ srl \hi_2, \src2, 16
++ ext \src2, \src2, 0, 16
++ #else
++ ext \hi_1, \src1, 0, 16
++ srl \src1, \src1, 16
++ ext \hi_2, \src2, 0, 16
++ srl \src2, \src2, 16
++ #endif
++ .endm
++
++
++ LEAF_MIPS_DSP(qt_ucstrncmp_mips_dsp_asm)
++ /*
++ * Arguments:
++ * a0 - string_a (uint16_t*)
++ * a1 - string_b (uint16_t*)
++ * a2 - length (uint32_t)
++ *
++ * Register usage:
++ * t0 - batches
++ */
++
++ move v0, zero /* result = 0 */
++ andi t0, a0, 0x3 /* t1 = string_a % 4 */
++ andi t1, a1, 0x3 /* t0 = string_b % 4 */
++ or t2, t0, t1 /* t2 = t0 | t1 */
++
++ beqz t2, 5f /* both aligned */
++ and t2, t0 ,t1
++ beqz t2, 6f /* one aligned */
++ nop
++
++ /*
++ * Both strings are unaligned: read 1 halfword from each,
++ * then fall-off to continue with the both-aligned case.
++ */
++ lhu t0, 0 (a0)
++ lhu t1, 0 (a1)
++ addiu a2, a2, -1 /* len-- */
++ sub v0, t0, t1 /* v0 = t0-t1 */
++ addiu a0, a0, 2 /* string_a++ */
++ bnez v0, 0f /* if (t0-t1): return */
++ addiu a1, a1, 2 /* string_b++ */
++ beqz a2, 0f /* if !len: return */
++ /* next instruction (srl) fills delay branch slot */
++
++ 5: /* Both string pointers are aligned */
++ srl t0, a2, 3 /* batches = length / 8 */
++ beqz t0, 9f /* if !batches: tail */
++ andi a2, a2, 0x7 /* length = length % 8 */
++
++ SAVE_REGS_ON_STACK 0, s0, s1, s2, s3
++
++ 1: lw t1, 0 (a0) /* [a0 a1] */
++ lw t3, 4 (a0) /* [a2 a3] */
++ lw t5, 8 (a0) /* [a4 a5] */
++ lw t7, 12 (a0) /* [a6 a7] */
++
++ lw t2, 0 (a1) /* [b0 b1] */
++ lw t4, 4 (a1) /* [b2 b3] */
++ lw t6, 8 (a1) /* [b4 b5] */
++ lw t8, 12 (a1) /* [b6 b7] */
++
++ /*
++ * Subtract elements one by one, if the result is zero
++ * both halves of the registers (shorts) are equal.
++ */
++ subq.ph s0, t1, t2 /* [a0-b0 a1-b1] */
++ subq.ph s1, t3, t4 /* [a2-b2 a3-b3] */
++
++ bnez s0, 1f
++ subq.ph s2, t5, t6 /* [a4-b4 a5-b5] */
++ bnez s1, 2f
++ subq.ph s3, t7, t8 /* [a6-b6 a7-b7] */
++ bnez s2, 3f
++ addiu t0, t0, -1 /* batches-- */
++ bnez s3, 4f
++ addiu a0, a0, 8*2 /* string_a += 8 */
++
++ bnez t0, 1b /* if batches: loop */
++ addiu a1, a1, 8*2 /* string_b += 8 */
++
++ RESTORE_REGS_FROM_STACK 0, s0, s1, s2, s3
++
++ bnez a2, 9f /* if length: tail */
++ nop
++ jr ra
++ nop
++
++
++ 1: /* Check t1 [a0 a1] vs. t2 [b0 b1] */
++ EXTRACT_HALVES_x2 t1, t2, t3, t4 /* a0, b0, a1, b1 */
++ sub v0, t1, t2
++ RESTORE_REGS_FROM_STACK 0, s0, s1, s2, s3
++ bnez v0, 0f /* if (a0-b0): return */
++ nop
++ jr ra
++ sub v0, t3, t4 /* return a1-b1 */
++
++ 2: /* Check t3 [a2 a3] vs. t4 [b2 b3] */
++ EXTRACT_HALVES_x2 t3, t4, t1, t2 /* a2, b2, a3, b3 */
++ sub v0, t3, t4
++ RESTORE_REGS_FROM_STACK 0, s0, s1, s2, s3
++ bnez v0, 0f /* if (a2-b2): return */
++ nop
++ jr ra
++ sub v0, t1, t2 /* return a3-b3 */
++
++ 3: /* Check t5 [a4 a5] vs. t6 [b4 b5] */
++ EXTRACT_HALVES_x2 t5, t6, t1, t2 /* a4, b4, a5, b5 */
++ sub v0, t5, t6
++ RESTORE_REGS_FROM_STACK 0, s0, s1, s2, s3
++ bnez v0, 0f /* if (a4-b4): return */
++ nop
++ jr ra
++ sub v0, t1, t2 /* return a5-b5 */
++
++ 4: /* Check t7 [a6 a7] vs. t8 [b6 b7] */
++ EXTRACT_HALVES_x2 t7, t8, t1, t2 /* a6, b6, a7, b7 */
++ sub v0, t7, t8
++ RESTORE_REGS_FROM_STACK 0, s0, s1, s2, s3
++ bnez v0, 0f /* if (a6-b6): return */
++ nop
++ jr ra
++ sub v0, t1, t2
++
++
++ /* Process remaining tail items. */
++ 9: lhu t1, 0 (a0) /* a */
++ lhu t2, 0 (a1) /* b */
++ addiu a2, a2, -1 /* length-- */
++ sub v0, t1, t2 /* result = (a - b) */
++
++ bnez v0, 0f /* if (a - b): return */
++ addiu a0, a0, 2 /* string_a++ */
++
++ bnez a2, 9b /* if length: loop */
++ addiu a1, a1, 2 /* string_b++ */
++
++ 0: jr ra
++ nop
++
++
++ /* One of the inputs is unaligned, do unrolled half-word loads */
++ 6: srl t0, a2, 3 /* batches = length / 8 */
++ andi a2, a2, 0x7 /* length = length % 8 */
++
++ 1: lhu t1, 0 (a0)
++ lhu t2, 0 (a1)
++ lhu t3, 2 (a0)
++ lhu t4, 2 (a1)
++ lhu t5, 4 (a0)
++ lhu t6, 4 (a1)
++ lhu t7, 6 (a0)
++ lhu t8, 6 (a1)
++
++ sub v0, t1, t2
++ sub t1, t3, t4
++
++ bnez v0, 0f
++ sub t2, t5, t6
++ bnez t1, 2f
++ sub t3, t7, t8
++ bnez t2, 3f
++ lhu t1, 8 (a0)
++ bnez t3, 4f
++ lhu t2, 8 (a1)
++
++ lhu t3, 10 (a0)
++ lhu t4, 10 (a1)
++ lhu t5, 12 (a0)
++ lhu t6, 12 (a1)
++ lhu t7, 14 (a0)
++ lhu t8, 14 (a1)
++
++ sub v0, t1, t2
++ sub t1, t3, t4
++
++ bnez v0, 0f
++ sub t2, t5, t6
++ bnez t1, 2f
++ sub t3, t7, t8
++ bnez t2, 3f
++ addiu t0, t0, -1 /* batches-- */
++ bnez t3, 4f
++ addiu a0, a0, 8*2 /* string_a += 8 */
++
++ bnez t0, 1b
++ addiu a1, a1, 8*2 /* string_b += 8 */
++
++ bnez a2, 9b /* if length: tail */
++ nop
++
++ 0: jr ra
++ nop
++ 2: jr ra
++ move v0, t1
++ 3: jr ra
++ move v0, t2
++ 4: jr ra
++ move v0, t3
++
++ END(qt_ucstrncmp_mips_dsp_asm)
++
++
++ #if defined(__mips_dspr2)
++ LEAF_MIPS_DSPR2(qt_fromlatin1_mips_asm_unroll8)
++ #else
++ LEAF_MIPS_DSP(qt_fromlatin1_mips_asm_unroll8)
++ #endif
++
++ andi t0, a1, 0x3
++ beqz t0, 9f /* check that src is aligned */
++ nop
++
++ 1: lbu t1, 0 (a1)
++ addiu a1, a1, 1
++ addiu a2, a2, -1
++ sh t1, 0 (a0)
++ beqz a2, 0f
++ andi t0, a1, 0x3
++ bnez t0, 1b
++ addiu a0, a0, 2
++
++ 9: /* source pointer is aligned: do batches of 8 elements */
++ andi t0, a0, 3 /* check if dst is aligned */
++ bnez t0, 6f
++ srl t0, a2, 3 /* batches = len / 8 */
++ andi a2, a2, 0x7 /* tail = len % 8 */
++
++ beqz t0, 8f /* if !batches: tail */
++ nop
++
++ 1: lw t1, 0 (a1)
++ lw t2, 4 (a1)
++
++ addiu a1, a1, 8*1
++ addiu t0, t0, -1
++
++ preceu.ph.qbl t3, t1
++ preceu.ph.qbr t1, t1
++ preceu.ph.qbl t4, t2
++ preceu.ph.qbr t2, t2
++
++ #if defined(__MIPSEL) && __MIPSEL
++ sw t1, 0 (a0)
++ sw t3, 4 (a0)
++ sw t2, 8 (a0)
++ sw t4, 12 (a0)
++ #else
++ sw t3, 0 (a0)
++ sw t1, 4 (a0)
++ sw t4, 8 (a0)
++ sw t2, 12 (a0)
++ #endif
++
++ bnez t0, 1b
++ addiu a0, a0, 8*2
++
++ 8: /* process tail items */
++ beqz a2, 0f
++ nop
++
++ 1: lbu t1, 0 (a1)
++ addiu a2, a2, -1
++ sh t1, 0 (a0)
++ addiu a1, a1, 1
++ bnez a2, 1b
++ addiu a0, a0, 2
++
++ 0: jr ra
++ nop
++
++ 6: beqz t0, 8b
++ andi a2, a2, 7
++ 7: lw t1, 0(a1)
++ lw t2, 4(a1)
++ addiu t0, t0, -1
++ addiu a1, a1, 8
++ andi t3, t1, 0xff
++ #if defined(__mips_dspr2)
++ prepend t1, t2, 8
++ #else
++ sll t4, t4, 24
++ srl t1, t1, 8
++ or t1, t1, t4
++ #endif
++ srl t2, t2, 8
++ preceu.ph.qbr t4, t1
++ preceu.ph.qbl t1, t1
++ preceu.ph.qbr t5, t2
++ srl t2, t2, 16
++ sh t3, 0(a0)
++ sw t4, 2(a0)
++ sw t1, 6(a0)
++ sw t5, 10(a0)
++ sh t2, 14(a0)
++ bnez t0, 7b
++ addiu a0, a0, 16
++ bnez a2, 1b
++ nop
++
++ jr ra
++ nop
++
++ END(qt_fromlatin1_mips_asm_unroll8)
++
++
++ LEAF_MIPS_DSP(qt_fromlatin1_mips_asm_unroll4)
++ /*
++ * Arguments:
++ * a0 - dst (uint16_t*)
++ * a1 - src (const char*)
++ * a2 - len (unsigned int)
++ */
++
++ /*
++ * QString::fromLatin1_helper() already handles the len==0
++ * case: assume that len is never zero.
++ */
++ srl t0, a2, 2
++ beqz t0, 9f
++ andi a2, a2, 0x3
++
++ 1: lbu t1, 0(a1)
++ lbu t2, 1(a1)
++ lbu t3, 2(a1)
++ lbu t4, 3(a1)
++ sh t1, 0(a0)
++ sh t2, 2(a0)
++ sh t3, 4(a0)
++ sh t4, 6(a0)
++ addiu t0, t0, -1
++ addiu a1, a1, 4
++ bnez t0, 1b
++ addiu a0, a0, 8
++
++ 8: beqz a2, 0f
++ nop
++
++ 9: lbu t1, 0(a1)
++ addiu a2, a2, -1
++ addiu a1, a1, 1
++ sh t1, 0(a0)
++ bnez a2, 9b
++ addiu a0, a0, 2
++
++ 0: jr ra
++ nop
++
++ END(qt_fromlatin1_mips_asm_unroll4)
++
++
++ LEAF_MIPS_DSP(qt_toLatin1_mips_dsp_asm)
++ /*
++ * a0 - dst
++ * a1 - src
++ * a2 - length
++ */
++
++ addiu t9, zero, 0x3f
++ srl t8, a2, 2
++ beqz t8, 2f
++ andi a2, a2, 3
++ 1:
++ lhu t0, 0(a1)
++ lhu t1, 2(a1)
++ lhu t2, 4(a1)
++ lhu t3, 6(a1)
++ srl t4, t0, 8
++ srl t5, t1, 8
++ srl t6, t2, 8
++ srl t7, t3, 8
++ movn t0, t9, t4
++ movn t1, t9, t5
++ movn t2, t9, t6
++ movn t3, t9, t7
++ addiu a1, a1, 8
++ addiu t8, t8, -1
++ sb t0, 0(a0)
++ sb t1, 1(a0)
++ sb t2, 2(a0)
++ sb t3, 3(a0)
++ bgtz t8, 1b
++ addiu a0, a0, 4
++ 2: beqz a2, 4f
++ nop
++ 3:
++ lhu t0, 0(a1)
++ addiu a1, a1, 2
++ addiu a2, a2, -1
++ srl t1, t0, 8
++ movn t0, t9, t1
++ sb t0, 0(a0)
++ bgtz a2, 3b
++ addiu a0, a0, 1
++ 4:
++ jr ra
++ nop
++
++ END(qt_toLatin1_mips_dsp_asm)
++