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