1 /**************************************************************************** 2 ** 3 ** Copyright (C) 2013 Imagination Technologies Limited, www.imgtec.com 4 ** Contact: https://www.qt.io/licensing/ 5 ** 6 ** This file is part of the QtGui module of the Qt Toolkit. 7 ** 8 ** $QT_BEGIN_LICENSE:LGPL$ 9 ** Commercial License Usage 10 ** Licensees holding valid commercial Qt licenses may use this file in 11 ** accordance with the commercial license agreement provided with the 12 ** Software or, alternatively, in accordance with the terms contained in 13 ** a written agreement between you and The Qt Company. For licensing terms 14 ** and conditions see https://www.qt.io/terms-conditions. For further 15 ** information use the contact form at https://www.qt.io/contact-us. 16 ** 17 ** GNU Lesser General Public License Usage 18 ** Alternatively, this file may be used under the terms of the GNU Lesser 19 ** General Public License version 3 as published by the Free Software 20 ** Foundation and appearing in the file LICENSE.LGPL3 included in the 21 ** packaging of this file. Please review the following information to 22 ** ensure the GNU Lesser General Public License version 3 requirements 23 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. 24 ** 25 ** GNU General Public License Usage 26 ** Alternatively, this file may be used under the terms of the GNU 27 ** General Public License version 2.0 or (at your option) the GNU General 28 ** Public license version 3 or any later version approved by the KDE Free 29 ** Qt Foundation. The licenses are as published by the Free Software 30 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 31 ** included in the packaging of this file. Please review the following 32 ** information to ensure the GNU General Public License requirements will 33 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and 34 ** https://www.gnu.org/licenses/gpl-3.0.html. 35 ** 36 ** $QT_END_LICENSE$ 37 ** 38 ****************************************************************************/ 39 40 #ifndef QT_MIPS_ASM_DSP_H 41 #define QT_MIPS_ASM_DSP_H 42 43 // 44 // W A R N I N G 45 // ------------- 46 // 47 // This file is not part of the Qt API. It exists purely as an 48 // implementation detail. This header file may change from version to 49 // version without notice, or even be removed. 50 // 51 // We mean it. 52 // 53 54 #if 0 55 #pragma qt_sync_stop_processing 56 #endif 57 58 #ifndef Q_CLANG_QDOC 59 #define zero $0 60 #define AT $1 61 #define v0 $2 62 #define v1 $3 63 #define a0 $4 64 #define a1 $5 65 #define a2 $6 66 #define a3 $7 67 #define t0 $8 68 #define t1 $9 69 #define t2 $10 70 #define t3 $11 71 #define t4 $12 72 #define t5 $13 73 #define t6 $14 74 #define t7 $15 75 #define s0 $16 76 #define s1 $17 77 #define s2 $18 78 #define s3 $19 79 #define s4 $20 80 #define s5 $21 81 #define s6 $22 82 #define s7 $23 83 #define t8 $24 84 #define t9 $25 85 #define k0 $26 86 #define k1 $27 87 #define gp $28 88 #define sp $29 89 #define fp $30 90 #define s8 $30 91 #define ra $31 92 #endif 93 94 /* 95 * LEAF_MIPS32R2 - declare leaf_mips32r2 routine 96 */ 97 #define LEAF_MIPS32R2(symbol) \ 98 .globl symbol; \ 99 .align 2; \ 100 .type symbol,@function; \ 101 .ent symbol,0; \ 102 symbol: .frame sp, 0, ra; \ 103 .set arch=mips32r2; \ 104 .set noreorder; 105 106 /* 107 * LEAF_MIPS_DSP - declare leaf_mips_dsp routine 108 */ 109 #define LEAF_MIPS_DSP(symbol) \ 110 LEAF_MIPS32R2(symbol) \ 111 .set dsp; 112 113 /* 114 * LEAF_MIPS_DSPR2 - declare leaf_mips_dspr2 routine 115 */ 116 #define LEAF_MIPS_DSPR2(symbol) \ 117 LEAF_MIPS32R2(symbol) \ 118 .set dspr2; 119 120 /* 121 * END - mark end of function 122 */ 123 #define END(function) \ 124 .set reorder; \ 125 .end function; \ 126 .size function,.-function 127 128 /* 129 * BYTE_MUL operation on two pixels (in_1 and in_2) with two 130 * multiplicator bytes, repl_a1 and repl_a2, which should be 131 * prepered with: 132 * replv.ph repl_a1, a1 133 * replv.ph repl_a2, a2 134 * to became such as: 135 * repl_a1 = | 00 | a1 | 00 | a1 | 136 * repl_a2 = | 00 | a2 | 00 | a2 | 137 * 138 * rounding_factor must have following value: 139 * li rounding_factor, 0x00800080 140 * 141 * scratch(n) - temporary registers 142 * 143 * in_const: 1 -> (default) causes that in_1, in_2 144 * registers will remain unchanged after usage 145 * 0 -> (or anything different then 1) causes 146 * that registers repl_a1, repl_a2 remain 147 * unchanged after usage 148 */ 149 .macro BYTE_MUL_x2 in_1, in_2, out_1, out_2 \ 150 repl_a1, repl_a2, rounding_factor, \ 151 scratch1, scratch2, scratch3, scratch4, \ 152 in_const = 1 153 muleu_s.ph.qbl \scratch1, \in_1, \repl_a1 154 muleu_s.ph.qbr \scratch2, \in_1, \repl_a1 155 muleu_s.ph.qbl \scratch3, \in_2, \repl_a2 156 muleu_s.ph.qbr \scratch4, \in_2, \repl_a2 157 158 .if \in_const == 1 159 preceu.ph.qbla \repl_a1, \scratch1 160 preceu.ph.qbla \repl_a2, \scratch2 161 preceu.ph.qbla \out_1, \scratch3 162 preceu.ph.qbla \out_2, \scratch4 163 164 addu \scratch1, \repl_a1, \scratch1 165 addu \scratch2, \repl_a2, \scratch2 166 .else 167 preceu.ph.qbla \in_1, \scratch1 168 preceu.ph.qbla \in_2, \scratch2 169 preceu.ph.qbla \out_1, \scratch3 170 preceu.ph.qbla \out_2, \scratch4 171 172 addu \scratch1, \in_1, \scratch1 173 addu \scratch2, \in_2, \scratch2 174 .endif 175 176 addu \out_1, \out_1, \scratch3 177 addu \out_2, \out_2, \scratch4 178 179 addu \scratch1, \scratch1, \rounding_factor 180 addu \scratch2, \scratch2, \rounding_factor 181 addu \scratch3, \out_1, \rounding_factor 182 addu \scratch4, \out_2, \rounding_factor 183 184 precrq.qb.ph \out_1, \scratch1, \scratch2 185 precrq.qb.ph \out_2, \scratch3, \scratch4 186 187 .endm 188 189 /* 190 * BYTE_MUL operation on one pixel (in_1) with 191 * multiplicator byte, repl_a1, which should be 192 * prepered with: 193 * replv.ph repl_a1, a1 194 * to became such as: 195 * repl_a1 = | 00 | a1 | 00 | a1 | 196 * 197 * rounding_factor must have following value: 198 * li rounding_factor, 0x00800080 199 * 200 * scratch(n) - temporary registers 201 */ 202 .macro BYTE_MUL in_1, out_1, \ 203 repl_a1, rounding_factor, \ 204 scratch1, scratch2, scratch3, scratch4 205 muleu_s.ph.qbl \scratch1, \in_1, \repl_a1 206 muleu_s.ph.qbr \scratch2, \in_1, \repl_a1 207 208 preceu.ph.qbla \scratch3, \scratch1 209 preceu.ph.qbla \scratch4, \scratch2 210 211 addu \scratch1, \scratch1, \scratch3 212 addu \scratch1, \scratch1, \rounding_factor 213 214 addu \scratch2, \scratch2, \scratch4 215 addu \scratch2, \scratch2, \rounding_factor 216 217 precrq.qb.ph \out_1, \scratch1, \scratch2 218 219 .endm 220 221 /* 222 * macro for INTERPOLATE_PIXEL_255 operation 223 * in_1 - First value to multiply 224 * mul_1 - Multiplicator byte for first value 225 * in_2 - Second value to multiply 226 * mul_2 - Multiplicator byte for second value 227 * rounding_factor and andi_factor should be prepared 228 * as: 229 * li rounding_factor, 0x00800080 230 * li andi_factor, 0xff00ff00 231 * scratch(n) - temporary registers 232 */ 233 .macro INTERPOLATE_PIXEL_255 in_1, mul_1, \ 234 in_2, mul_2, \ 235 out_1, \ 236 rounding_factor, andi_factor \ 237 scratch1, scratch2, scratch3, scratch4 238 # x part 239 preceu.ph.qbra \scratch1, \in_1 240 preceu.ph.qbra \scratch2, \in_2 241 mul \scratch1, \scratch1, \mul_1 242 mul \scratch2, \scratch2, \mul_2 243 # x>>8 part 244 preceu.ph.qbla \scratch3, \in_1 245 preceu.ph.qbla \scratch4, \in_2 246 mul \scratch3, \scratch3, \mul_1 247 mul \scratch4, \scratch4, \mul_2 248 # x part 249 addu \scratch1, \scratch1, \scratch2 250 preceu.ph.qbla \scratch2, \scratch1 251 addu \scratch1, \scratch1, \scratch2 252 addu \scratch1, \scratch1, \rounding_factor 253 preceu.ph.qbla \scratch1, \scratch1 254 # x>>8 part 255 addu \scratch3, \scratch3, \scratch4 256 preceu.ph.qbla \scratch4, \scratch3 257 addu \scratch3, \scratch3, \scratch4 258 addu \scratch3, \scratch3, \rounding_factor 259 and \scratch3, \scratch3, \andi_factor 260 261 or \out_1, \scratch1, \scratch3 262 .endm 263 264 /* 265 * Checks if stack offset is big enough for storing/restoring regs_num 266 * number of register to/from stack. Stack offset must be greater than 267 * or equal to the number of bytes needed for storing registers (regs_num*4). 268 * Since MIPS ABI allows usage of first 16 bytes of stack frame (this is 269 * preserved for input arguments of the functions, already stored in a0-a3), 270 * stack size can be further optimized by utilizing this space. 271 */ 272 .macro CHECK_STACK_OFFSET regs_num, stack_offset 273 .if \stack_offset < \regs_num * 4 - 16 274 .error "Stack offset too small." 275 .endif 276 .endm 277 278 /* 279 * Saves set of registers on stack. Maximum number of registers that 280 * can be saved on stack is limitted to 14 (a0-a3, v0-v1 and s0-s7). 281 * Stack offset is number of bytes that are added to stack pointer (sp) 282 * before registers are pushed in order to provide enough space on stack 283 * (offset must be multiple of 4, and must be big enough, as described by 284 * CHECK_STACK_OFFSET macro). This macro is intended to be used in 285 * combination with RESTORE_REGS_FROM_STACK macro. Example: 286 * SAVE_REGS_ON_STACK 4, v0, v1, s0, s1 287 * RESTORE_REGS_FROM_STACK 4, v0, v1, s0, s1 288 */ 289 .macro SAVE_REGS_ON_STACK stack_offset = 0, r1, \ 290 r2 = 0, r3 = 0, r4 = 0, \ 291 r5 = 0, r6 = 0, r7 = 0, \ 292 r8 = 0, r9 = 0, r10 = 0, \ 293 r11 = 0, r12 = 0, r13 = 0, \ 294 r14 = 0 295 .if (\stack_offset < 0) || (\stack_offset - (\stack_offset / 4) * 4) 296 .error "Stack offset must be positive and multiple of 4." 297 .endif 298 .if \stack_offset != 0 299 addiu sp, sp, -\stack_offset 300 .endif 301 sw \r1, 0(sp) 302 .if \r2 != 0 303 sw \r2, 4(sp) 304 .endif 305 .if \r3 != 0 306 sw \r3, 8(sp) 307 .endif 308 .if \r4 != 0 309 sw \r4, 12(sp) 310 .endif 311 .if \r5 != 0 312 CHECK_STACK_OFFSET 5, \stack_offset 313 sw \r5, 16(sp) 314 .endif 315 .if \r6 != 0 316 CHECK_STACK_OFFSET 6, \stack_offset 317 sw \r6, 20(sp) 318 .endif 319 .if \r7 != 0 320 CHECK_STACK_OFFSET 7, \stack_offset 321 sw \r7, 24(sp) 322 .endif 323 .if \r8 != 0 324 CHECK_STACK_OFFSET 8, \stack_offset 325 sw \r8, 28(sp) 326 .endif 327 .if \r9 != 0 328 CHECK_STACK_OFFSET 9, \stack_offset 329 sw \r9, 32(sp) 330 .endif 331 .if \r10 != 0 332 CHECK_STACK_OFFSET 10, \stack_offset 333 sw \r10, 36(sp) 334 .endif 335 .if \r11 != 0 336 CHECK_STACK_OFFSET 11, \stack_offset 337 sw \r11, 40(sp) 338 .endif 339 .if \r12 != 0 340 CHECK_STACK_OFFSET 12, \stack_offset 341 sw \r12, 44(sp) 342 .endif 343 .if \r13 != 0 344 CHECK_STACK_OFFSET 13, \stack_offset 345 sw \r13, 48(sp) 346 .endif 347 .if \r14 != 0 348 CHECK_STACK_OFFSET 14, \stack_offset 349 sw \r14, 52(sp) 350 .endif 351 .endm 352 353 /* 354 * Restores set of registers from stack. Maximum number of registers that 355 * can be restored from stack is limitted to 14 (a0-a3, v0-v1 and s0-s7). 356 * Stack offset is number of bytes that are added to stack pointer (sp) 357 * after registers are restored (offset must be multiple of 4, and must 358 * be big enough, as described by CHECK_STACK_OFFSET macro). This macro is 359 * intended to be used in combination with RESTORE_REGS_FROM_STACK macro. 360 * Example: 361 * SAVE_REGS_ON_STACK 4, v0, v1, s0, s1 362 * RESTORE_REGS_FROM_STACK 4, v0, v1, s0, s1 363 */ 364 .macro RESTORE_REGS_FROM_STACK stack_offset = 0, r1, \ 365 r2 = 0, r3 = 0, r4 = 0, \ 366 r5 = 0, r6 = 0, r7 = 0, \ 367 r8 = 0, r9 = 0, r10 = 0, \ 368 r11 = 0, r12 = 0, r13 = 0, \ 369 r14 = 0 370 .if (\stack_offset < 0) || (\stack_offset - (\stack_offset/4)*4) 371 .error "Stack offset must be pozitive and multiple of 4." 372 .endif 373 lw \r1, 0(sp) 374 .if \r2 != 0 375 lw \r2, 4(sp) 376 .endif 377 .if \r3 != 0 378 lw \r3, 8(sp) 379 .endif 380 .if \r4 != 0 381 lw \r4, 12(sp) 382 .endif 383 .if \r5 != 0 384 CHECK_STACK_OFFSET 5, \stack_offset 385 lw \r5, 16(sp) 386 .endif 387 .if \r6 != 0 388 CHECK_STACK_OFFSET 6, \stack_offset 389 lw \r6, 20(sp) 390 .endif 391 .if \r7 != 0 392 CHECK_STACK_OFFSET 7, \stack_offset 393 lw \r7, 24(sp) 394 .endif 395 .if \r8 != 0 396 CHECK_STACK_OFFSET 8, \stack_offset 397 lw \r8, 28(sp) 398 .endif 399 .if \r9 != 0 400 CHECK_STACK_OFFSET 9, \stack_offset 401 lw \r9, 32(sp) 402 .endif 403 .if \r10 != 0 404 CHECK_STACK_OFFSET 10, \stack_offset 405 lw \r10, 36(sp) 406 .endif 407 .if \r11 != 0 408 CHECK_STACK_OFFSET 11, \stack_offset 409 lw \r11, 40(sp) 410 .endif 411 .if \r12 != 0 412 CHECK_STACK_OFFSET 12, \stack_offset 413 lw \r12, 44(sp) 414 .endif 415 .if \r13 != 0 416 CHECK_STACK_OFFSET 13, \stack_offset 417 lw \r13, 48(sp) 418 .endif 419 .if \r14 != 0 420 CHECK_STACK_OFFSET 14, \stack_offset 421 lw \r14, 52(sp) 422 .endif 423 .if \stack_offset != 0 424 addiu sp, sp, \stack_offset 425 .endif 426 .endm 427 428 #endif // QT_MIPS_ASM_DSP_H 429