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