psx_gpu: workaround overflow crash
[pcsx_rearmed.git] / plugins / gpu_neon / psx_gpu / psx_gpu_arm_neon.S
1 /*
2  * Copyright (C) 2011 Gilead Kutnick "Exophase" <exophase@gmail.com>
3  * Copyright (C) 2012 GraÅžvydas Ignotas "notaz" <notasas@gmail.com>
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License as
7  * published by the Free Software Foundation; either version 2 of
8  * the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License for more details.
14  */
15
16 #define MAX_SPANS                                         512
17 #define MAX_BLOCKS                                        64
18 #define MAX_BLOCKS_PER_ROW                                128
19
20 #define RENDER_STATE_MASK_EVALUATE                        0x20
21 #define RENDER_FLAGS_MODULATE_TEXELS                      0x1
22 #define RENDER_FLAGS_BLEND                                0x2
23
24 #include "psx_gpu_offsets.h"
25
26 #define psx_gpu_b_dx_offset (psx_gpu_b_block_span_offset + 4)
27
28 #define edge_data_left_x_offset                           0
29 #define edge_data_num_blocks_offset                       2
30 #define edge_data_right_mask_offset                       4
31 #define edge_data_y_offset                                6
32
33
34 #define psx_gpu                                           r0
35 #define v_a                                               r1
36 #define v_b                                               r2
37 #define v_c                                               r3
38
39 #define x0                                                r4
40 #define x1                                                r5
41 #define x2                                                r6
42 #define x0_x1                                             r5
43 #define x1_x2                                             r6
44 #define y0                                                r7
45 #define y1                                                r8
46 #define y2                                                r9
47 #define y0_y1                                             r7
48 #define y1_y2                                             r8
49 #define b0                                                r9
50 #define b1                                                r10
51 #define b2                                                r11
52 #define b0_b1                                             r10
53 #define b1_b2                                             r11
54
55
56 #define area_r_s                                          r5
57
58 #define g_bx0                                             r2
59 #define g_bx                                              r3
60 #define g_bx2                                             r4
61 #define g_bx3                                             r5
62 #define b_base                                            r6
63 #define g_by                                              r8
64
65 #define gs_bx                                             r7
66 #define gs_by                                             r10
67
68 #define ga_bx                                             g_bx
69 #define ga_by                                             g_by
70
71 #define gw_bx_h                                           g_bx
72 #define gw_by_h                                           g_by
73
74 #define gw_bx_l                                           r11
75 #define gw_by_l                                           gw_bx_l
76
77 #define store_a                                           r0
78 #define store_b                                           r1
79 #define store_inc                                         r5
80
81
82 #define v0                                                q0
83 #define uvrgb0                                            d0
84 #define x0_y0                                             d1
85
86 #define v1                                                q1
87 #define uvrgb1                                            d2
88 #define x1_y1                                             d3
89
90 #define v2                                                q2
91 #define uvrgb2                                            d4
92 #define x2_y2                                             d5
93
94 #define x0_ab                                             q3
95 #define uvrg_xxxx0                                        q3
96 #define uvrg0                                             d6
97 #define xxxx0                                             d7
98
99 #define x1_ab                                             q4
100 #define uvrg_xxxx1                                        q4
101 #define uvrg1                                             d8
102 #define xxxx1                                             d9
103
104 #define x2_ab                                             q5
105 #define uvrg_xxxx2                                        q5
106 #define uvrg2                                             d10
107 #define xxxx2                                             d11
108
109 #define y0_ab                                             q6
110 #define yyyy_uvrg0                                        q6
111 #define yyyy0                                             d12
112 #define uvrg0b                                            d13
113
114 #define y1_ab                                             q7
115 #define yyyy_uvrg1                                        q7
116 #define yyyy1                                             d14
117 #define uvrg1b                                            d15
118
119 #define y2_ab                                             q8
120 #define yyyy_uvrg2                                        q8
121 #define yyyy2                                             d16
122 #define uvrg2b                                            d17
123
124 #define d0_ab                                             q9
125 #define d0_a                                              d18
126 #define d0_b                                              d19
127
128 #define d1_ab                                             q10
129 #define d1_a                                              d20
130 #define d1_b                                              d21
131
132 #define d2_ab                                             q11
133 #define d2_a                                              d22
134 #define d2_b                                              d23
135
136 #define d3_ab                                             q12
137 #define d3_a                                              d24
138 #define d3_b                                              d25
139
140 #define ga_uvrg_x                                         q1
141 #define ga_uvrg_y                                         q4
142
143 #define dx                                                x0_x1
144 #define dy                                                y0_y1
145 #define db                                                b0_b1
146
147 #define uvrg_base                                         q11
148
149 #define gs_uvrg_x                                         q5
150 #define gs_uvrg_y                                         q6
151
152 #define g_uvrg_x                                          q1
153 #define ga_uv_x                                           d2
154 #define g_uv_x                                            d2
155 #define ga_rg_x                                           d3
156 #define g_rg_x                                            d3
157
158 #define g_uvrg_y                                          q4
159 #define ga_uv_y                                           d8
160 #define g_uv_y                                            d8
161 #define ga_rg_y                                           d9
162 #define g_rg_y                                            d9
163
164 #define gw_uv_x                                           q1
165 #define gw_rg_x                                           q2
166 #define gw_uv_y                                           q4
167 #define gw_rg_y                                           q3
168
169 #define w_mask                                            q9
170 #define w_mask_l                                          d18
171
172 #define r_shift                                           q10
173
174 #define uvrg_dx0                                          q0
175 #define uvrg_dx0l                                         d0
176 #define uvrg_dx0h                                         d1
177
178 #define uvrg_dx1                                          q1
179 #define uvrg_dx1l                                         d2
180 #define uvrg_dx1h                                         d3
181
182 #define uvrg_dx2                                          q2
183 #define uvrg_dx2l                                         d4
184 #define uvrg_dx2h                                         d5
185
186 #define uvrg_dx3                                          q3
187 #define uvrg_dx3l                                         d6
188 #define uvrg_dx3h                                         d7
189
190 #define uvrgb_phase                                       q13
191
192 .align 4
193
194 /* FIXME: users of this should be in psx_gpu instead */
195 #ifndef __PIC__
196 #define load_pointer(register, pointer)                                        \
197   movw register, :lower16:pointer;                                             \
198   movt register, :upper16:pointer;                                             \
199
200 #else
201 #define load_pointer(register, pointer)                                        \
202   ldr  register, =pointer                                                      \
203
204 #endif
205
206 #define function(name)                                                         \
207   .global name;                                                                \
208   name:                                                                        \
209
210 @ r0: psx_gpu
211 @ r1: v_a
212 @ r2: v_b
213 @ r3: v_c
214
215 function(compute_all_gradients)
216   // First compute the triangle area reciprocal and shift. The division will
217   // happen concurrently with much of the work which follows.
218   @ r12 = psx_gpu->triangle_area
219   ldr r12, [ psx_gpu, #psx_gpu_triangle_area_offset ]
220   stmdb sp!, { r4 - r11, lr }
221
222   @ load exponent of 62 into upper half of double
223   movw r4, #0
224   clz r14, r12                       @ r14 = shift
225
226   movt r4, #((62 + 1023) << 4)
227   mov r12, r12, lsl r14              @ r12 = triangle_area_normalized
228
229   @ load area normalized into lower half of double
230   mov r5, r12, lsr #10
231   vmov.f64 d30, r5, r4               @ d30 = (1 << 62) + ta_n
232
233   movt r4, #((1022 + 31) << 4)
234   mov r5, r12, lsl #20
235
236   add r4, r4, r12, lsr #11
237   vmov.f64 d31, r5, r4
238
239   vdiv.f64 d30, d30, d31             @ d30 = ((1 << 62) + ta_n) / ta_n
240
241   // ((x1 - x0) * (y2 - y1)) - ((x2 - x1) * (y1 - y0)) =
242   // ( d0       *  d1      ) - ( d2       *  d3      ) =
243   // ( m0                  ) - ( m1                  ) = gradient
244
245   // This is split to do 12 elements at a time over three sets: a, b, and c.
246   // Technically we only need to do 10 elements (uvrgb_x and uvrgb_y), so
247   // two of the slots are unused.
248
249   // Inputs are all 16-bit signed. The m0/m1 results are 32-bit signed, as
250   // is g.
251
252   // First type is:  uvrg bxxx xxxx 
253   // Second type is: yyyy ybyy uvrg 
254   // Since x_a and y_c are the same the same variable is used for both. 
255
256   vld1.u32 { v0 }, [ v_a, : 128 ]    @ v0 = { uvrg0, b0, x0, y0 }
257   ldrsh x0, [ v_a, #8 ]              @ load x0
258
259   vld1.u32 { v1 }, [ v_b, : 128 ]    @ v1 = { uvrg1, b1, x1, y1}
260   ldrh x1, [ v_b, #8 ]               @ load x1
261
262   vld1.u32 { v2 }, [ v_c, : 128 ]    @ v2 = { uvrg2, b2, x2, y2 }
263   ldrh x2, [ v_c, #8 ]               @ load x2
264
265   vmovl.u8 uvrg_xxxx0, uvrgb0        @ uvrg_xxxx0 = { uv0, rg0, b0-, -- }
266   ldrh y0, [ v_a, #10 ]              @ load y0
267
268   vmovl.u8 uvrg_xxxx1, uvrgb1        @ uvrg_xxxx1 = { uv1, rg1, b1-, -- }
269   ldrh y1, [ v_b, #10 ]              @ load y1
270
271   vmovl.u8 uvrg_xxxx2, uvrgb2        @ uvrg_xxxx2 = { uv2, rg2, b2-, -- }
272   ldrh y2, [ v_c, #10 ]              @ load y2
273
274   vmov.u8 uvrg0b, uvrg0              @ uvrg0b = { uv0, rg0 }
275   vdup.u16 xxxx0, x0_y0[0]           @ xxxx0 = { xx0, xx0 }
276
277   orr x1_x2, x1, x2, lsl #16         @ x1_x2 = { x1, x2 }
278   pkhbt x0_x1, x0, x1, lsl #16       @ x0_x1 = { x0, x1 }
279
280   vmov.u8 uvrg1b, uvrg1              @ uvrg1b = { uv1, rg1 }
281   vdup.u16 xxxx1, x1_y1[0]           @ xxxx1 = { xx1, xx1 }
282
283   vmov.u8 uvrg2b, uvrg2              @ uvrg2b = { uv2, rg2 }
284   vdup.u16 xxxx2, x2_y2[0]           @ xxxx2 = { xx2, xx2 }
285
286   ldrb b2, [ v_c, #4 ]               @ load b2
287   orr y0_y1, y0, y1, lsl #16         @ y0_y1 = { y0, y1 }
288
289   ldrb b1, [ v_b, #4 ]               @ load b1
290   orr y1_y2, y1, y2, lsl #16         @ y1_y2 = { y1, y2 }
291
292   vdup.u16 yyyy0, x0_y0[1]           @ yyyy0 = { yy0, yy0 }
293   vsub.s16 d0_ab, x1_ab, x0_ab
294
295   ldrb b0, [ v_a, #4 ]               @ load b0
296   orr b1_b2, b1, b2, lsl #16         @ b1_b2 = { b1, b2 }
297
298   vdup.u16 yyyy1, x1_y1[1]           @ yyyy1 = { yy1, yy1 }
299   vsub.s16 d2_ab, x2_ab, x1_ab
300
301   vdup.u16 yyyy2, x2_y2[1]           @ yyyy2 = { yy2, yy2 }
302   vsub.s16 d1_ab, y2_ab, y1_ab
303
304   orr b0_b1, b0, b1, lsl #16         @ b1_b2 = { b1, b2 }
305   ssub16 dx, x1_x2, x0_x1            @ dx = { x1 - x0, x2 - x1 }
306
307   ssub16 dy, y1_y2, y0_y1            @ dy = { y1 - y0, y2 - y1 }
308   ssub16 db, b1_b2, b0_b1            @ db = { b1 - b0, b2 - b1 }
309
310   vsub.s16 d3_ab, y1_ab, y0_ab
311   smusdx ga_by, dx, db               @ ga_by = ((x1 - x0) * (b2 - b1)) -
312                                      @         ((x2 - X1) * (b1 - b0)) 
313   vmull.s16 ga_uvrg_x, d0_a, d1_a
314   smusdx ga_bx, db, dy               @ ga_bx = ((b1 - b0) * (y2 - y1)) -
315                                      @         ((b2 - b1) * (y1 - y0))
316   vmlsl.s16 ga_uvrg_x, d2_a, d3_a
317   movs gs_bx, ga_bx, asr #31
318
319   vmull.s16 ga_uvrg_y, d0_b, d1_b
320   rsbmi ga_bx, ga_bx, #0
321
322   @ r12 = psx_gpu->uvrgb_phase
323   ldr r12, [ psx_gpu, #psx_gpu_uvrgb_phase_offset ]
324
325   vmlsl.s16 ga_uvrg_y, d2_b, d3_b
326   movs gs_by, ga_by, asr #31
327
328   vshr.u64 d0, d30, #22
329   add b_base, r12, b0, lsl #16
330
331   vdup.u32 uvrgb_phase, r12
332
333   rsbmi ga_by, ga_by, #0
334   vclt.s32 gs_uvrg_x, ga_uvrg_x, #0  @ gs_uvrg_x = ga_uvrg_x < 0
335
336   @ r12 = psx_gpu->triangle_winding_offset
337   ldrb r12, [ psx_gpu, #psx_gpu_triangle_winding_offset ]
338   vclt.s32 gs_uvrg_y, ga_uvrg_y, #0  @ gs_uvrg_y = ga_uvrg_y < 0
339
340   rsb r12, r12, #0                   @ r12 = -(triangle->winding)
341
342   vdup.u32 w_mask, r12               @ w_mask = { -w, -w, -w, -w }
343   sub r14, r14, #(62 - 12)           @ r14 = shift - (62 - FIXED_BITS)
344
345   vshll.u16 uvrg_base, uvrg0, #16    @ uvrg_base = uvrg0 << 16
346   vdup.u32 r_shift, r14              @ r_shift = { shift, shift, shift, shift }
347
348   vadd.u32 uvrg_base, uvrgb_phase
349   vabs.s32 ga_uvrg_x, ga_uvrg_x      @ ga_uvrg_x = abs(ga_uvrg_x)
350
351   vmov area_r_s, s0                  @ area_r_s = triangle_reciprocal
352   vabs.s32 ga_uvrg_y, ga_uvrg_y      @ ga_uvrg_y = abs(ga_uvrg_y)
353
354   vmull.u32 gw_rg_x, ga_rg_x, d0[0]
355   vmull.u32 gw_uv_x, ga_uv_x, d0[0]
356   vmull.u32 gw_rg_y, ga_rg_y, d0[0]
357   vmull.u32 gw_uv_y, ga_uv_y, d0[0]
358
359   vshl.u64 gw_rg_x, gw_rg_x, r_shift
360   vshl.u64 gw_uv_x, gw_uv_x, r_shift
361   vshl.u64 gw_rg_y, gw_rg_y, r_shift
362   vshl.u64 gw_uv_y, gw_uv_y, r_shift
363
364   veor.u32 gs_uvrg_x, gs_uvrg_x, w_mask
365   vmovn.u64 g_uv_x, gw_uv_x
366
367   veor.u32 gs_uvrg_y, gs_uvrg_y, w_mask
368   vmovn.u64 g_rg_x, gw_rg_x
369
370   veor.u32 g_uvrg_x, g_uvrg_x, gs_uvrg_x
371   vmovn.u64 g_uv_y, gw_uv_y
372
373   vsub.u32 g_uvrg_x, g_uvrg_x, gs_uvrg_x
374   vmovn.u64 g_rg_y, gw_rg_y
375
376   veor.u32 g_uvrg_y, g_uvrg_y, gs_uvrg_y
377   mov ga_bx, ga_bx, lsl #13
378
379   vsub.u32 g_uvrg_y, g_uvrg_y, gs_uvrg_y
380   mov ga_by, ga_by, lsl #13
381
382   vdup.u32 x0_y0, x0
383   umull gw_bx_l, gw_bx_h, ga_bx, area_r_s
384
385   vshl.u32 g_uvrg_x, g_uvrg_x, #4
386   vshl.u32 g_uvrg_y, g_uvrg_y, #4
387
388   umull gw_by_l, gw_by_h, ga_by, area_r_s
389   vmls.s32 uvrg_base, ga_uvrg_x, x0_y0[0]
390
391   eor gs_bx, gs_bx, r12
392   vadd.u32 uvrg_dx2, uvrg_dx1, uvrg_dx1
393
394   veor.u32 uvrg_dx0, uvrg_dx0, uvrg_dx0
395   eor gs_by, gs_by, r12
396
397   rsb r11, r14, #0                   @ r11 = negative shift for scalar lsr
398   add store_a, psx_gpu, #psx_gpu_uvrg_offset
399
400   sub r11, r11, #(32 - 13)
401
402   add store_b, store_a, #16
403   mov store_inc, #32
404
405   vadd.u32 uvrg_dx3, uvrg_dx2, uvrg_dx1
406   vst1.u32 { uvrg_base }, [ store_a, : 128 ], store_inc
407
408   vst1.u32 { uvrg_dx1 }, [ store_b, : 128 ], store_inc
409   mov g_bx, gw_bx_h, lsr r11
410
411   vst1.u32 { g_uvrg_y }, [ store_a, : 128 ], store_inc
412   mov g_by, gw_by_h, lsr r11
413
414   vst4.u32 { uvrg_dx0l, uvrg_dx1l, uvrg_dx2l, uvrg_dx3l },                     \
415    [ store_b, : 128 ], store_inc
416   eor g_bx, g_bx, gs_bx
417
418   vst4.u32 { uvrg_dx0h, uvrg_dx1h, uvrg_dx2h, uvrg_dx3h },                     \
419    [ store_b, : 128 ], store_inc
420   sub g_bx, g_bx, gs_bx
421
422   lsl g_bx, g_bx, #4  
423   eor g_by, g_by, gs_by
424
425   mls b_base, g_bx, x0, b_base
426   sub g_by, g_by, gs_by
427
428   lsl g_by, g_by, #4
429   mov g_bx0, #0
430
431   add g_bx2, g_bx, g_bx
432   add g_bx3, g_bx, g_bx2
433
434   stmia store_b, { g_bx0, g_bx, g_bx2, g_bx3, b_base, g_by }
435
436   ldmia sp!, { r4 - r11, pc }
437
438
439 #define psx_gpu                                  r0
440 #define v_a                                      r1
441 #define v_b                                      r2
442 #define v_c                                      r3
443
444 #define temp                                     r14
445
446 #define x_a                                      r4
447 #define x_b                                      r5
448 #define x_c                                      r6
449 #define y_a                                      r1
450 #define y_b                                      r2
451 #define y_c                                      r3
452
453 #define height_minor_a                           r7
454 #define height_minor_b                           r8
455 #define height_major                             r9
456 #define height                                   r9
457
458 #define reciprocal_table_ptr                     r10
459
460 #define edge_alt_low                             r4
461 #define edge_alt_high                            r5
462 #define edge_dx_dy_alt                           r6
463 #define edge_shift_alt                           r10
464
465 #define edge_dx_dy_alt_low                       r4
466 #define edge_dx_dy_alt_high                      r5
467
468 #define span_edge_data                           r4
469 #define span_uvrg_offset                         r5
470 #define span_b_offset                            r6
471
472 #define clip                                     r14
473
474 #define b                                        r11
475 #define b_dy                                     r12
476
477
478 #define alternate_x                              q0
479 #define alternate_dx_dy                          q1
480 #define alternate_x_32                           q2
481
482 #define alternate_x_low                          d0
483 #define alternate_x_high                         d1
484 #define alternate_dx_dy_low                      d2
485 #define alternate_dx_dy_high                     d3
486 #define alternate_x_32_low                       d4
487 #define alternate_x_32_high                      d5
488
489 #define left_x                                   q3
490 #define right_x                                  q4
491 #define left_dx_dy                               q5
492 #define right_dx_dy                              q6
493 #define left_edge                                q7
494 #define right_edge                               q8
495
496 #define left_x_low                               d6
497 #define left_x_high                              d7
498 #define right_x_low                              d8
499 #define right_x_high                             d9
500 #define left_dx_dy_low                           d10
501 #define left_dx_dy_high                          d11
502 #define right_dx_dy_low                          d12
503 #define right_dx_dy_high                         d13
504 #define left_edge_low                            d14
505 #define left_edge_high                           d15
506 #define right_edge_low                           d16
507 #define right_edge_high                          d17
508
509 #define y_mid_point                              d18
510 #define c_0x0004                                 d19
511
512 #define left_right_x_16                          q11
513 #define span_shifts_y                            q12
514 #define c_0x0001                                 q13
515
516 #define span_shifts                              d24
517 #define y_x4                                     d25
518 #define c_0xFFFE                                 d26
519 #define c_0x0007                                 d27
520
521 #define left_right_x_16_low                      d22
522 #define left_right_x_16_high                     d23
523
524 #define uvrg                                     q14
525 #define uvrg_dy                                  q15
526
527 #define alternate_x_16                           d4
528
529 #define v_clip                                   q3
530 #define v_clip_low                               d6
531
532 #define right_x_32                               q10
533 #define left_x_32                                q11
534 #define alternate_select                         d24
535
536 #define right_x_32_low                           d20
537 #define right_x_32_high                          d21
538 #define left_x_32_low                            d22
539 #define left_x_32_high                           d23
540
541 #define edges_xy                                 q0
542 #define edges_dx_dy                              d2
543 #define edge_shifts                              d3
544 #define edge_shifts_64                           q2
545
546 #define edges_xy_left                            d0
547 #define edges_xy_right                           d1
548
549 #define height_reciprocals                       d6
550 #define heights                                  d7
551
552 #define widths                                   d8
553 #define c_0x01                                   d9
554 #define x_starts                                 d10
555 #define x_ends                                   d11
556
557 #define heights_b                                d12
558 #define edges_dx_dy_64                           q10
559
560 #define edges_dx_dy_64_left                      d20
561 #define edges_dx_dy_64_right                     d21
562
563
564 #define setup_spans_prologue()                                                 \
565   stmdb sp!, { r4 - r11, lr };                                                 \
566                                                                                \
567   ldrsh x_a, [ v_a, #8 ];                                                      \
568   ldrsh x_b, [ v_b, #8 ];                                                      \
569   ldrsh x_c, [ v_c, #8 ];                                                      \
570   ldrsh y_a, [ v_a, #10 ];                                                     \
571   ldrsh y_b, [ v_b, #10 ];                                                     \
572   ldrsh y_c, [ v_c, #10 ];                                                     \
573                                                                                \
574   add temp, psx_gpu, #psx_gpu_uvrg_offset;                                     \
575   vld1.32 { uvrg }, [ temp ];                                                  \
576   add temp, psx_gpu, #psx_gpu_uvrg_dy_offset;                                  \
577   vld1.32 { uvrg_dy }, [ temp ];                                               \
578   load_pointer(reciprocal_table_ptr, reciprocal_table);                        \
579                                                                                \
580   vmov.u32 c_0x01, #0x01                                                       \
581
582 #define setup_spans_load_b()                                                   \
583   ldr b, [ psx_gpu, #psx_gpu_b_offset ];                                       \
584   ldr b_dy, [ psx_gpu, #psx_gpu_b_dy_offset ]                                  \
585
586 #define setup_spans_prologue_b()                                               \
587   add span_uvrg_offset, psx_gpu, #psx_gpu_span_uvrg_offset_offset;             \
588   add temp, psx_gpu, #psx_gpu_viewport_start_x_offset;                         \
589                                                                                \
590   add span_edge_data, psx_gpu, #psx_gpu_span_edge_data_offset;                 \
591   vmov.u16 c_0x0004, #0x0004;                                                  \
592                                                                                \
593   add span_b_offset, psx_gpu, #psx_gpu_span_b_offset_offset;                   \
594   vmov.u16 c_0x0001, #0x0001;                                                  \
595                                                                                \
596   vld1.u16 { left_edge_low[], left_edge_high[] }, [ temp ];                    \
597   add temp, psx_gpu, #psx_gpu_viewport_end_x_offset;                           \
598                                                                                \
599   vld1.u16 { right_edge_low[], right_edge_high[] }, [ temp ];                  \
600   vadd.u16 right_edge, right_edge, c_0x0001;                                   \
601                                                                                \
602   vmov.u16 c_0x0007, #0x0007;                                                  \
603   vmvn.u16 c_0xFFFE, #0x0001                                                   \
604
605
606 #define compute_edge_delta_x2()                                                \
607   ldr temp, [ reciprocal_table_ptr, height, lsl #2 ];                          \
608                                                                                \
609   vdup.u32 heights, height;                                                    \
610   vsub.u32 widths, x_ends, x_starts;                                           \
611                                                                                \
612   vdup.u32 edge_shifts, temp;                                                  \
613   vsub.u32 heights_b, heights, c_0x01;                                         \
614   vshr.u32 height_reciprocals, edge_shifts, #10;                               \
615                                                                                \
616   vmla.s32 heights_b, x_starts, heights;                                       \
617   vbic.u16 edge_shifts, #0xE0;                                                 \
618   vmul.s32 edges_dx_dy, widths, height_reciprocals;                            \
619   vmull.s32 edges_xy, heights_b, height_reciprocals                            \
620
621 #define width_alt                 r6
622 #define height_reciprocal_alt     r11
623 #define height_b_alt              r12
624
625 #define compute_edge_delta_x3(start_c, height_a, height_b)                     \
626   vmov.u32 heights, height_a, height_b;                                        \
627   ldr temp, [ reciprocal_table_ptr, height_a, lsl #2 ];                        \
628   vmov.u32 edge_shifts[0], temp;                                               \
629   ldr temp, [ reciprocal_table_ptr, height_b, lsl #2 ];                        \
630   vmov.u32 edge_shifts[1], temp;                                               \
631   ldr edge_shift_alt, [ reciprocal_table_ptr, height_minor_b, lsl #2 ];        \
632                                                                                \
633   vsub.u32 widths, x_ends, x_starts;                                           \
634   sub width_alt, x_c, start_c;                                                 \
635                                                                                \
636   vsub.u32 heights_b, heights, c_0x01;                                         \
637   sub height_b_alt, height_minor_b, #1;                                        \
638                                                                                \
639   vshr.u32 height_reciprocals, edge_shifts, #10;                               \
640   lsr height_reciprocal_alt, edge_shift_alt, #10;                              \
641                                                                                \
642   vmla.s32 heights_b, x_starts, heights;                                       \
643   mla height_b_alt, height_minor_b, start_c, height_b_alt;                     \
644                                                                                \
645   vbic.u16 edge_shifts, #0xE0;                                                 \
646   and edge_shift_alt, edge_shift_alt, #0x1F;                                   \
647                                                                                \
648   vmul.s32 edges_dx_dy, widths, height_reciprocals;                            \
649   mul edge_dx_dy_alt, width_alt, height_reciprocal_alt;                        \
650                                                                                \
651   vmull.s32 edges_xy, heights_b, height_reciprocals;                           \
652   smull edge_alt_low, edge_alt_high, height_b_alt, height_reciprocal_alt       \
653
654
655 #define setup_spans_adjust_y_up()                                              \
656   vsub.u32 y_x4, y_x4, c_0x0004                                                \
657
658 #define setup_spans_adjust_y_down()                                            \
659   vadd.u32 y_x4, y_x4, c_0x0004                                                \
660
661 #define setup_spans_adjust_interpolants_up()                                   \
662   vsub.u32 uvrg, uvrg, uvrg_dy;                                                \
663   sub b, b, b_dy                                                               \
664
665 #define setup_spans_adjust_interpolants_down()                                 \
666   vadd.u32 uvrg, uvrg, uvrg_dy;                                                \
667   add b, b, b_dy                                                               \
668
669
670 #define setup_spans_clip_interpolants_increment()                              \
671   mla b, b_dy, clip, b;                                                        \
672   vmla.s32 uvrg, uvrg_dy, v_clip                                               \
673
674 #define setup_spans_clip_interpolants_decrement()                              \
675   mls b, b_dy, clip, b;                                                        \
676   vmls.s32 uvrg, uvrg_dy, v_clip                                               \
677
678 #define setup_spans_clip_alternate_yes()                                       \
679   smlal edge_alt_low, edge_alt_high, edge_dx_dy_alt, clip                      \
680
681 #define setup_spans_clip_alternate_no()                                        \
682
683 #define setup_spans_clip(direction, alternate_active)                          \
684   vdup.u32 v_clip, clip;                                                       \
685   setup_spans_clip_alternate_##alternate_active();                             \
686   setup_spans_clip_interpolants_##direction();                                 \
687   vmlal.s32 edges_xy, edges_dx_dy, v_clip_low                                  \
688
689
690 #define setup_spans_adjust_edges_alternate_no(left_index, right_index)         \
691   vmovl.s32 edge_shifts_64, edge_shifts;                                       \
692   vmovl.s32 edges_dx_dy_64, edges_dx_dy;                                       \
693                                                                                \
694   vshl.s64 edges_xy, edges_xy, edge_shifts_64;                                 \
695   vshl.s64 edges_dx_dy_64, edges_dx_dy_64, edge_shifts_64;                     \
696                                                                                \
697   vmov left_x_low, edges_xy_##left_index;                                      \
698   vmov right_x_low, edges_xy_##right_index;                                    \
699                                                                                \
700   vmov left_dx_dy_low, edges_dx_dy_64_##left_index;                            \
701   vmov left_dx_dy_high, edges_dx_dy_64_##left_index;                           \
702   vmov right_dx_dy_low, edges_dx_dy_64_##right_index;                          \
703   vmov right_dx_dy_high, edges_dx_dy_64_##right_index;                         \
704                                                                                \
705   vadd.u64 left_x_high, left_x_low, left_dx_dy_low;                            \
706   vadd.u64 right_x_high, right_x_low, right_dx_dy_low;                         \
707                                                                                \
708   vadd.u64 left_dx_dy, left_dx_dy, left_dx_dy;                                 \
709   vadd.u64 right_dx_dy, right_dx_dy, right_dx_dy                               \
710
711
712 #define setup_spans_adjust_edges_alternate_yes(left_index, right_index)        \
713   setup_spans_adjust_edges_alternate_no(left_index, right_index);              \
714                                                                                \
715   vdup.u16 y_mid_point, y_b;                                                   \
716   rsb temp, edge_shift_alt, #32;                                               \
717                                                                                \
718   lsl edge_alt_high, edge_alt_high, edge_shift_alt;                            \
719   orr edge_alt_high, edge_alt_high, edge_alt_low, lsr temp;                    \
720   lsl edge_alt_low, edge_alt_low, edge_shift_alt;                              \
721   vmov alternate_x_low, edge_alt_low, edge_alt_high;                           \
722                                                                                \
723   asr edge_dx_dy_alt_high, edge_dx_dy_alt, temp;                               \
724   lsl edge_dx_dy_alt_low, edge_dx_dy_alt, edge_shift_alt;                      \
725   vmov alternate_dx_dy_low, edge_dx_dy_alt_low, edge_dx_dy_alt_high;           \
726   vmov alternate_dx_dy_high, alternate_dx_dy_low;                              \
727                                                                                \
728   vadd.u64 alternate_x_high, alternate_x_low, alternate_dx_dy_low;             \
729   vadd.u64 alternate_dx_dy, alternate_dx_dy, alternate_dx_dy                   \
730
731
732 #define setup_spans_y_select_up()                                              \
733   vclt.s16 alternate_select, y_x4, y_mid_point                                 \
734
735 #define setup_spans_y_select_down()                                            \
736   vcgt.s16 alternate_select, y_x4, y_mid_point                                 \
737
738
739 #define setup_spans_alternate_select_left()                                    \
740   vbit.u16 left_right_x_16_low, alternate_x_16, alternate_select               \
741
742 #define setup_spans_alternate_select_right()                                   \
743   vbit.u16 left_right_x_16_high, alternate_x_16, alternate_select              \
744
745
746 #define setup_spans_set_x4_alternate_yes(alternate, direction)                 \
747   vshrn.s64 alternate_x_32_low, alternate_x, #32;                              \
748   vshrn.s64 left_x_32_low, left_x, #32;                                        \
749   vshrn.s64 right_x_32_low, right_x, #32;                                      \
750                                                                                \
751   vadd.u64 alternate_x, alternate_x, alternate_dx_dy;                          \
752   vadd.u64 left_x, left_x, left_dx_dy;                                         \
753   vadd.u64 right_x, right_x, right_dx_dy;                                      \
754                                                                                \
755   vshrn.s64 alternate_x_32_high, alternate_x, #32;                             \
756   vshrn.s64 left_x_32_high, left_x, #32;                                       \
757   vshrn.s64 right_x_32_high, right_x, #32;                                     \
758                                                                                \
759   vadd.u64 alternate_x, alternate_x, alternate_dx_dy;                          \
760   vadd.u64 left_x, left_x, left_dx_dy;                                         \
761   vadd.u64 right_x, right_x, right_dx_dy;                                      \
762                                                                                \
763   vmovn.u32 alternate_x_16, alternate_x_32;                                    \
764   setup_spans_y_select_##direction();                                          \
765   vmovn.u32 left_right_x_16_low, left_x_32;                                    \
766                                                                                \
767   vmovn.u32 left_right_x_16_high, right_x_32;                                  \
768   setup_spans_alternate_select_##alternate();                                  \
769                                                                                \
770   vst1.u32 { uvrg }, [ span_uvrg_offset, :128 ]!;                              \
771   str b, [ span_b_offset ], #4;                                                \
772   setup_spans_adjust_interpolants_##direction();                               \
773                                                                                \
774   vmax.s16 left_right_x_16, left_right_x_16, left_edge;                        \
775                                                                                \
776   vst1.u32 { uvrg }, [ span_uvrg_offset, :128 ]!;                              \
777   str b, [ span_b_offset ], #4;                                                \
778   setup_spans_adjust_interpolants_##direction();                               \
779                                                                                \
780   vmin.s16 left_right_x_16, left_right_x_16, right_edge;                       \
781                                                                                \
782   vst1.u32 { uvrg }, [ span_uvrg_offset, :128 ]!;                              \
783   str b, [ span_b_offset ], #4;                                                \
784   setup_spans_adjust_interpolants_##direction();                               \
785                                                                                \
786   vsub.u16 left_right_x_16_high, left_right_x_16_high, left_right_x_16_low;    \
787   vadd.u16 left_right_x_16_high, left_right_x_16_high, c_0x0007;               \
788   vand.u16 span_shifts, left_right_x_16_high, c_0x0007;                        \
789                                                                                \
790   vst1.u32 { uvrg }, [ span_uvrg_offset, :128 ]!;                              \
791   str b, [ span_b_offset ], #4;                                                \
792   setup_spans_adjust_interpolants_##direction();                               \
793                                                                                \
794   vshr.u16 left_right_x_16_high, left_right_x_16_high, #3;                     \
795   vshl.u16 span_shifts, c_0xFFFE, span_shifts;                                 \
796                                                                                \
797   vst4.u16 { left_right_x_16, span_shifts_y }, [ span_edge_data ]!;            \
798                                                                                \
799   setup_spans_adjust_y_##direction()                                           \
800
801
802 #define setup_spans_set_x4_alternate_no(alternate, direction)                  \
803   vshrn.s64 left_x_32_low, left_x, #32;                                        \
804   vshrn.s64 right_x_32_low, right_x, #32;                                      \
805                                                                                \
806   vadd.u64 left_x, left_x, left_dx_dy;                                         \
807   vadd.u64 right_x, right_x, right_dx_dy;                                      \
808                                                                                \
809   vshrn.s64 left_x_32_high, left_x, #32;                                       \
810   vshrn.s64 right_x_32_high, right_x, #32;                                     \
811                                                                                \
812   vadd.u64 left_x, left_x, left_dx_dy;                                         \
813   vadd.u64 right_x, right_x, right_dx_dy;                                      \
814                                                                                \
815   vmovn.u32 left_right_x_16_low, left_x_32;                                    \
816   vmovn.u32 left_right_x_16_high, right_x_32;                                  \
817                                                                                \
818   vst1.u32 { uvrg }, [ span_uvrg_offset, :128 ]!;                              \
819   str b, [ span_b_offset ], #4;                                                \
820   setup_spans_adjust_interpolants_##direction();                               \
821                                                                                \
822   vmax.s16 left_right_x_16, left_right_x_16, left_edge;                        \
823                                                                                \
824   vst1.u32 { uvrg }, [ span_uvrg_offset, :128 ]!;                              \
825   str b, [ span_b_offset ], #4;                                                \
826   setup_spans_adjust_interpolants_##direction();                               \
827                                                                                \
828   vmin.s16 left_right_x_16, left_right_x_16, right_edge;                       \
829                                                                                \
830   vst1.u32 { uvrg }, [ span_uvrg_offset, :128 ]!;                              \
831   str b, [ span_b_offset ], #4;                                                \
832   setup_spans_adjust_interpolants_##direction();                               \
833                                                                                \
834   vsub.u16 left_right_x_16_high, left_right_x_16_high, left_right_x_16_low;    \
835   vadd.u16 left_right_x_16_high, left_right_x_16_high, c_0x0007;               \
836   vand.u16 span_shifts, left_right_x_16_high, c_0x0007;                        \
837                                                                                \
838   vst1.u32 { uvrg }, [ span_uvrg_offset, :128 ]!;                              \
839   str b, [ span_b_offset ], #4;                                                \
840   setup_spans_adjust_interpolants_##direction();                               \
841                                                                                \
842   vshl.u16 span_shifts, c_0xFFFE, span_shifts;                                 \
843   vshr.u16 left_right_x_16_high, left_right_x_16_high, #3;                     \
844                                                                                \
845   vst4.u16 { left_right_x_16, span_shifts_y }, [ span_edge_data ]!;            \
846                                                                                \
847   setup_spans_adjust_y_##direction()                                           \
848
849
850 #define edge_adjust_low           r11
851 #define edge_adjust_high          r12
852
853 #define setup_spans_alternate_adjust_yes()                                     \
854   smull edge_adjust_low, edge_adjust_high, edge_dx_dy_alt, height_minor_a;     \
855   subs edge_alt_low, edge_alt_low, edge_adjust_low;                            \
856   sbc edge_alt_high, edge_alt_high, edge_adjust_high                           \
857
858 #define setup_spans_alternate_adjust_no()                                      \
859
860
861 #define setup_spans_down(left_index, right_index, alternate, alternate_active) \
862   setup_spans_alternate_adjust_##alternate_active();                           \
863   setup_spans_load_b();                                                        \
864                                                                                \
865   ldrsh temp, [ psx_gpu, #psx_gpu_viewport_end_y_offset ];                     \
866   subs y_c, y_c, temp;                                                         \
867   subgt height, height, y_c;                                                   \
868   addgt height, height, #1;                                                    \
869                                                                                \
870   ldrsh temp, [ psx_gpu, #psx_gpu_viewport_start_y_offset ];                   \
871   subs clip, temp, y_a;                                                        \
872   ble 0f;                                                                      \
873                                                                                \
874   sub height, height, clip;                                                    \
875   add y_a, y_a, clip;                                                          \
876   setup_spans_clip(increment, alternate_active);                               \
877                                                                                \
878  0:                                                                            \
879   cmp height, #0;                                                              \
880   ble 1f;                                                                      \
881                                                                                \
882   orr temp, y_a, y_a, lsl #16;                                                 \
883   add temp, temp, #(1 << 16);                                                  \
884   add y_a, temp, #2;                                                           \
885   add y_a, y_a, #(2 << 16);                                                    \
886   vmov.u32 y_x4, temp, y_a;                                                    \
887                                                                                \
888   setup_spans_adjust_edges_alternate_##alternate_active(left_index,            \
889    right_index);                                                               \
890   setup_spans_prologue_b();                                                    \
891                                                                                \
892   strh height, [ psx_gpu, #psx_gpu_num_spans_offset ];                         \
893                                                                                \
894  2:                                                                            \
895   setup_spans_set_x4_alternate_##alternate_active(alternate, down);            \
896   subs height, height, #4;                                                     \
897   bhi 2b;                                                                      \
898                                                                                \
899  1:                                                                            \
900
901
902 #define setup_spans_alternate_pre_increment_yes()                              \
903   adds edge_alt_low, edge_alt_low, edge_dx_dy_alt;                             \
904   adc edge_alt_high, edge_alt_high, edge_dx_dy_alt, asr #31                    \
905
906 #define setup_spans_alternate_pre_increment_no()                               \
907
908
909 #define setup_spans_up_decrement_yes()                                         \
910   suble height, height, #1                                                     \
911
912 #define setup_spans_up_decrement_no()                                          \
913
914
915 #define setup_spans_up(left_index, right_index, alternate, alternate_active)   \
916   setup_spans_alternate_adjust_##alternate_active();                           \
917   setup_spans_load_b();                                                        \
918   sub y_a, y_a, #1;                                                            \
919                                                                                \
920   ldrh temp, [ psx_gpu, #psx_gpu_viewport_start_y_offset ];                    \
921   subs temp, temp, y_c;                                                        \
922   subgt height, height, temp;                                                  \
923   setup_spans_up_decrement_##alternate_active();                               \
924                                                                                \
925   ldrh temp, [ psx_gpu, #psx_gpu_viewport_end_y_offset ];                      \
926   subs clip, y_a, temp;                                                        \
927   ble 0f;                                                                      \
928                                                                                \
929   sub height, height, clip;                                                    \
930   sub y_a, y_a, clip;                                                          \
931   setup_spans_clip(decrement, alternate_active);                               \
932                                                                                \
933  0:                                                                            \
934   cmp height, #0;                                                              \
935   ble 1f;                                                                      \
936                                                                                \
937   orr temp, y_a, y_a, lsl #16;                                                 \
938   sub temp, temp, #(1 << 16);                                                  \
939   sub y_a, temp, #2;                                                           \
940   sub y_a, y_a, #(2 << 16);                                                    \
941   vmov.u32 y_x4, temp, y_a;                                                    \
942                                                                                \
943   vaddw.s32 edges_xy, edges_xy, edges_dx_dy;                                   \
944                                                                                \
945   setup_spans_alternate_pre_increment_##alternate_active();                    \
946   setup_spans_adjust_edges_alternate_##alternate_active(left_index,            \
947    right_index);                                                               \
948   setup_spans_adjust_interpolants_up();                                        \
949   setup_spans_prologue_b();                                                    \
950                                                                                \
951   strh height, [ psx_gpu, #psx_gpu_num_spans_offset ];                         \
952                                                                                \
953  2:                                                                            \
954   setup_spans_set_x4_alternate_##alternate_active(alternate, up);              \
955   subs height, height, #4;                                                     \
956   bhi 2b;                                                                      \
957                                                                                \
958  1:                                                                            \
959
960
961 #define setup_spans_epilogue()                                                 \
962   ldmia sp!, { r4 - r11, pc }                                                  \
963
964
965 #define setup_spans_up_up(minor, major)                                        \
966   setup_spans_prologue();                                                      \
967   sub height_minor_a, y_a, y_b;                                                \
968   sub height_minor_b, y_b, y_c;                                                \
969   sub height, y_a, y_c;                                                        \
970                                                                                \
971   vdup.u32 x_starts, x_a;                                                      \
972   vmov.u32 x_ends, x_c, x_b;                                                   \
973                                                                                \
974   compute_edge_delta_x3(x_b, height_major, height_minor_a);                    \
975   setup_spans_up(major, minor, minor, yes);                                    \
976   setup_spans_epilogue()                                                       \
977
978 function(setup_spans_up_left)
979   setup_spans_up_up(left, right)
980
981 function(setup_spans_up_right)
982   setup_spans_up_up(right, left)
983
984 .pool
985
986 #define setup_spans_down_down(minor, major)                                    \
987   setup_spans_prologue();                                                      \
988   sub height_minor_a, y_b, y_a;                                                \
989   sub height_minor_b, y_c, y_b;                                                \
990   sub height, y_c, y_a;                                                        \
991                                                                                \
992   vdup.u32 x_starts, x_a;                                                      \
993   vmov.u32 x_ends, x_c, x_b;                                                   \
994                                                                                \
995   compute_edge_delta_x3(x_b, height_major, height_minor_a);                    \
996   setup_spans_down(major, minor, minor, yes);                                  \
997   setup_spans_epilogue()                                                       \
998
999 function(setup_spans_down_left)
1000   setup_spans_down_down(left, right)
1001
1002 function(setup_spans_down_right)
1003   setup_spans_down_down(right, left)
1004
1005
1006 #define setup_spans_up_flat()                                                  \
1007   sub height, y_a, y_c;                                                        \
1008                                                                                \
1009   compute_edge_delta_x2();                                                     \
1010   setup_spans_up(left, right, none, no);                                       \
1011   setup_spans_epilogue()                                                       \
1012
1013 function(setup_spans_up_a)
1014   setup_spans_prologue()
1015
1016   vmov.u32 x_starts, x_a, x_b
1017   vdup.u32 x_ends, x_c
1018
1019   setup_spans_up_flat()
1020
1021 function(setup_spans_up_b)
1022   setup_spans_prologue()
1023
1024   vdup.u32 x_starts, x_a
1025   vmov.u32 x_ends, x_b, x_c
1026
1027   setup_spans_up_flat()
1028
1029 #define setup_spans_down_flat()                                                \
1030   sub height, y_c, y_a;                                                        \
1031                                                                                \
1032   compute_edge_delta_x2();                                                     \
1033   setup_spans_down(left, right, none, no);                                     \
1034   setup_spans_epilogue()                                                       \
1035
1036 function(setup_spans_down_a)
1037   setup_spans_prologue()
1038
1039   vmov.u32 x_starts, x_a, x_b
1040   vdup.u32 x_ends, x_c
1041
1042   setup_spans_down_flat()
1043
1044 function(setup_spans_down_b)
1045   setup_spans_prologue()
1046
1047   vdup.u32 x_starts, x_a
1048   vmov.u32 x_ends, x_b, x_c
1049
1050   setup_spans_down_flat()
1051
1052
1053 #define middle_y                                          r9
1054
1055 #define edges_xy_b                                        q11
1056 #define edges_dx_dy_b                                     d26
1057 #define edge_shifts_b                                     d27
1058 #define edges_dx_dy_and_shifts_b                          q13
1059 #define height_increment                                  d20
1060
1061 #define edges_dx_dy_and_shifts                            q1
1062
1063 #define edges_xy_b_left                                   d22
1064 #define edges_xy_b_right                                  d23
1065
1066 #define setup_spans_up_down_load_edge_set_b()                                  \
1067   vmov edges_xy, edges_xy_b;                                                   \
1068   vmov edges_dx_dy_and_shifts, edges_dx_dy_and_shifts_b                        \
1069
1070
1071 function(setup_spans_up_down)
1072   setup_spans_prologue()
1073
1074   // s32 middle_y = y_a;
1075   sub height_minor_a, y_a, y_b
1076   sub height_minor_b, y_c, y_a
1077   sub height_major, y_c, y_b
1078
1079   vmov.u32 x_starts, x_a, x_c
1080   vdup.u32 x_ends, x_b
1081
1082   compute_edge_delta_x3(x_a, height_minor_a, height_major)
1083
1084   mov temp, #0
1085   vmov.u32 height_increment, temp, height_minor_b
1086   vmlal.s32 edges_xy, edges_dx_dy, height_increment
1087
1088   vmov edges_xy_b_left, edge_alt_low, edge_alt_high
1089   vmov edges_xy_b_right, edges_xy_right
1090
1091   vmov edge_shifts_b, edge_shifts
1092   vmov.u32 edge_shifts_b[0], edge_shift_alt
1093
1094   vneg.s32 edges_dx_dy_b, edges_dx_dy
1095   vmov.u32 edges_dx_dy_b[0], edge_dx_dy_alt
1096
1097   mov middle_y, y_a
1098   
1099   setup_spans_load_b()
1100   sub y_a, y_a, #1
1101
1102   ldrh temp, [ psx_gpu, #psx_gpu_viewport_start_y_offset ]
1103   subs temp, temp, y_b
1104   subgt height_minor_a, height_minor_a, temp
1105
1106   ldrh temp, [ psx_gpu, #psx_gpu_viewport_end_y_offset ]
1107   subs clip, y_a, temp
1108   ble 0f
1109
1110   sub height_minor_a, height_minor_a, clip
1111   sub y_a, y_a, clip
1112   setup_spans_clip(decrement, no)
1113
1114  0:                                                                
1115   cmp height_minor_a, #0
1116   ble 3f
1117
1118   orr temp, y_a, y_a, lsl #16
1119   sub temp, temp, #(1 << 16)
1120   sub y_a, temp, #2
1121   sub y_a, y_a, #(2 << 16)
1122   vmov.u32 y_x4, temp, y_a
1123
1124   vaddw.s32 edges_xy, edges_xy, edges_dx_dy
1125
1126   strh height_minor_a, [ psx_gpu, #psx_gpu_num_spans_offset ]
1127
1128   setup_spans_adjust_edges_alternate_no(left, right); 
1129   setup_spans_adjust_interpolants_up()
1130   setup_spans_up_down_load_edge_set_b()
1131
1132   setup_spans_prologue_b()
1133
1134
1135  2: 
1136   setup_spans_set_x4_alternate_no(none, up)
1137   subs height_minor_a, height_minor_a, #4
1138   bhi 2b
1139
1140   add span_edge_data, span_edge_data, height_minor_a, lsl #3
1141   add span_uvrg_offset, span_uvrg_offset, height_minor_a, lsl #4
1142   add span_b_offset, span_b_offset, height_minor_a, lsl #2
1143
1144  4:
1145   add temp, psx_gpu, #psx_gpu_uvrg_offset
1146   vld1.32 { uvrg }, [ temp ]
1147   mov y_a, middle_y
1148   
1149   setup_spans_load_b()
1150
1151   ldrh temp, [ psx_gpu, #psx_gpu_viewport_end_y_offset ]
1152   subs y_c, y_c, temp
1153   subgt height_minor_b, height_minor_b, y_c
1154   addgt height_minor_b, height_minor_b, #1
1155
1156   ldrh temp, [ psx_gpu, #psx_gpu_viewport_start_y_offset ]
1157   subs clip, temp, y_a
1158   ble 0f
1159
1160   sub height_minor_b, height_minor_b, clip
1161   add y_a, y_a, clip
1162   setup_spans_clip(increment, no)
1163
1164  0:
1165   cmp height_minor_b, #0
1166   ble 1f
1167
1168   orr temp, y_a, y_a, lsl #16
1169   add temp, temp, #(1 << 16) 
1170   add y_a, temp, #2
1171   add y_a, y_a, #(2 << 16)
1172   vmov.u32 y_x4, temp, y_a
1173
1174   setup_spans_adjust_edges_alternate_no(left, right)
1175
1176   ldrh temp, [ psx_gpu, #psx_gpu_num_spans_offset ]
1177   add temp, temp, height_minor_b
1178
1179   cmp temp, #MAX_SPANS
1180   beq 5f
1181
1182   strh temp, [ psx_gpu, #psx_gpu_num_spans_offset ]
1183
1184  2:                                                     
1185   setup_spans_set_x4_alternate_no(none, down)
1186   subs height_minor_b, height_minor_b, #4
1187   bhi 2b
1188
1189  1:
1190   setup_spans_epilogue()
1191
1192  3:
1193   setup_spans_up_down_load_edge_set_b()
1194   setup_spans_prologue_b()
1195   bal 4b
1196
1197  5:
1198   // FIXME: overflow corner case
1199   sub temp, temp, height_minor_b
1200   bics height_minor_b, #3
1201   add temp, temp, height_minor_b
1202   strh temp, [ psx_gpu, #psx_gpu_num_spans_offset ]
1203   bne 2b
1204   bal 1b
1205
1206 .pool
1207
1208 #undef span_uvrg_offset
1209 #undef span_edge_data
1210 #undef span_b_offset
1211 #undef left_x
1212 #undef b
1213
1214 #define psx_gpu                                  r0
1215 #define num_spans                                r1
1216 #define span_uvrg_offset                         r2
1217 #define span_edge_data                           r3
1218 #define span_b_offset                            r4
1219 #define b_dx                                     r5
1220 #define span_num_blocks                          r6
1221 #define y                                        r7
1222 #define left_x                                   r8
1223 #define b                                        r9
1224 #define dither_offset_ptr                        r10
1225 #define block_ptr_a                              r11
1226 #define fb_ptr                                   r12
1227 #define num_blocks                               r14
1228
1229 #define uvrg_dx_ptr                              r2
1230 #define texture_mask_ptr                         r3
1231 #define dither_shift                             r8
1232 #define dither_row                               r10
1233
1234 #define c_32                                     r7
1235 #define b_dx4                                    r8
1236 #define b_dx8                                    r9
1237 #define block_ptr_b                              r10
1238
1239 #define block_span_ptr                           r10
1240 #define right_mask                               r8
1241
1242 #define color                                    r2
1243 #define color_r                                  r3
1244 #define color_g                                  r4
1245 #define color_b                                  r5
1246
1247 #undef uvrg
1248
1249 #define u_block                                  q0
1250 #define v_block                                  q1
1251 #define r_block                                  q2
1252 #define g_block                                  q3
1253 #define b_block                                  q4
1254
1255 #define uv_dx4                                   d10
1256 #define rg_dx4                                   d11
1257 #define uv_dx8                                   d12
1258 #define rg_dx8                                   d13
1259 #define b_whole_8                                d14
1260 #define fb_mask_ptrs                             d15
1261
1262 #define uvrg_dx4                                 q5
1263 #define uvrg_dx8                                 q6
1264 #define uv_dx8                                   d12
1265 #define rg_dx8                                   d13
1266
1267 #define u_whole                                  q8
1268 #define v_whole                                  q9
1269 #define r_whole                                  q10
1270 #define g_whole                                  q11
1271 #define b_whole                                  q12
1272
1273 #define u_whole_low                              d16
1274 #define u_whole_high                             d17
1275 #define v_whole_low                              d18
1276 #define v_whole_high                             d19
1277 #define r_whole_low                              d20
1278 #define r_whole_high                             d21
1279 #define g_whole_low                              d22
1280 #define g_whole_high                             d23
1281 #define b_whole_low                              d24
1282 #define b_whole_high                             d25
1283
1284 #define dx4                                      q13
1285 #define dx8                                      q13
1286
1287 #define u_whole_8                                d26
1288 #define v_whole_8                                d27
1289 #define u_whole_8b                               d24
1290 #define r_whole_8                                d24
1291 #define g_whole_8                                d25
1292
1293 #define uv_whole_8                               q13
1294 #define uv_whole_8b                              q14
1295
1296 #define dither_offsets                           q14
1297 #define texture_mask                             q15
1298 #define texture_mask_u                           d30
1299 #define texture_mask_v                           d31
1300
1301 #define dither_offsets_short                     d28
1302
1303 #define v_left_x                                 q8
1304 #define uvrg                                     q9
1305 #define block_span                               q10
1306
1307 #define uv                                       d18
1308 #define rg                                       d19
1309
1310 #define draw_mask                                q1
1311 #define draw_mask_edge                           q13
1312 #define test_mask                                q0
1313
1314 #define uvrg_dx                                  q3
1315
1316 #define colors                                   q2
1317
1318 #define setup_blocks_texture_swizzled()                                        \
1319   vand.u8 u_whole_8b, u_whole_8, texture_mask_u;                               \
1320   vsli.u8 u_whole_8, v_whole_8, #4;                                            \
1321   vsri.u8 v_whole_8, u_whole_8b, #4                                            \
1322
1323 #define setup_blocks_texture_unswizzled()                                      \
1324
1325
1326 #define setup_blocks_shaded_textured_builder(swizzling)                        \
1327 .align 3;                                                                      \
1328                                                                                \
1329 function(setup_blocks_shaded_textured_dithered_##swizzling##_indirect)         \
1330   ldrh num_spans, [ psx_gpu, #psx_gpu_num_spans_offset ];                      \
1331   add uvrg_dx_ptr, psx_gpu, #psx_gpu_uvrg_dx_offset;                           \
1332                                                                                \
1333   vld1.u32 { uvrg_dx }, [ uvrg_dx_ptr, :128 ];                                 \
1334   add texture_mask_ptr, psx_gpu, #psx_gpu_texture_mask_width_offset;           \
1335                                                                                \
1336   cmp num_spans, #0;                                                           \
1337   bxeq lr;                                                                     \
1338                                                                                \
1339   stmdb sp!, { r4 - r11, r14 };                                                \
1340   vshl.u32 uvrg_dx4, uvrg_dx, #2;                                              \
1341                                                                                \
1342   ldr b_dx, [ psx_gpu, #psx_gpu_b_dx_offset ];                                 \
1343   vshl.u32 uvrg_dx8, uvrg_dx, #3;                                              \
1344                                                                                \
1345   vld2.u8 { texture_mask_u[], texture_mask_v[] }, [ texture_mask_ptr, :16 ];   \
1346   add span_uvrg_offset, psx_gpu, #psx_gpu_span_uvrg_offset_offset;             \
1347                                                                                \
1348   ldrh num_blocks, [ psx_gpu, #psx_gpu_num_blocks_offset ];                    \
1349   add span_edge_data, psx_gpu, #psx_gpu_span_edge_data_offset;                 \
1350                                                                                \
1351   add span_b_offset, psx_gpu, #psx_gpu_span_b_offset_offset;                   \
1352   add block_ptr_a, psx_gpu, #psx_gpu_blocks_offset;                            \
1353                                                                                \
1354   add block_ptr_a, block_ptr_a, num_blocks, lsl #6;                            \
1355                                                                                \
1356  0:                                                                            \
1357   vmov.u8 fb_mask_ptrs, #0;                                                    \
1358                                                                                \
1359   ldrh span_num_blocks, [ span_edge_data, #edge_data_num_blocks_offset ];      \
1360   add dither_offset_ptr, psx_gpu, #psx_gpu_dither_table_offset;                \
1361                                                                                \
1362   ldrh y, [ span_edge_data, #edge_data_y_offset ];                             \
1363   ldr fb_ptr, [ psx_gpu, #psx_gpu_vram_out_ptr_offset ];                       \
1364                                                                                \
1365   cmp span_num_blocks, #0;                                                     \
1366   beq 1f;                                                                      \
1367                                                                                \
1368   ldrh left_x, [ span_edge_data, #edge_data_left_x_offset ];                   \
1369   add num_blocks, span_num_blocks, num_blocks;                                 \
1370                                                                                \
1371   cmp num_blocks, #MAX_BLOCKS;                                                 \
1372   bgt 2f;                                                                      \
1373                                                                                \
1374  3:                                                                            \
1375   ldr b, [ span_b_offset ];                                                    \
1376   add fb_ptr, fb_ptr, y, lsl #11;                                              \
1377                                                                                \
1378   vdup.u32 v_left_x, left_x;                                                   \
1379   and y, y, #0x3;                                                              \
1380                                                                                \
1381   ldr dither_row, [ dither_offset_ptr, y, lsl #2 ];                            \
1382   add fb_ptr, fb_ptr, left_x, lsl #1;                                          \
1383                                                                                \
1384   mla b, b_dx, left_x, b;                                                      \
1385   and dither_shift, left_x, #0x03;                                             \
1386                                                                                \
1387   vld1.u32 { uvrg }, [ span_uvrg_offset, :128 ];                               \
1388   vshr.u32 uvrg_dx, uvrg_dx4, #2;                                              \
1389                                                                                \
1390   mov dither_shift, dither_shift, lsl #3;                                      \
1391   vmla.u32 uvrg, uvrg_dx, v_left_x;                                            \
1392                                                                                \
1393   mov c_32, #32;                                                               \
1394   subs span_num_blocks, span_num_blocks, #1;                                   \
1395                                                                                \
1396   mov dither_row, dither_row, ror dither_shift;                                \
1397   mov b_dx4, b_dx, lsl #2;                                                     \
1398                                                                                \
1399   vdup.u32 dither_offsets_short, dither_row;                                   \
1400   add block_span_ptr, psx_gpu, #psx_gpu_u_block_span_offset;                   \
1401                                                                                \
1402   vdup.u32 b_block, b;                                                         \
1403   vshll.s8 dither_offsets, dither_offsets_short, #4;                           \
1404                                                                                \
1405   vdup.u32 u_block, uv[0];                                                     \
1406   mov b_dx8, b_dx, lsl #3;                                                     \
1407                                                                                \
1408   vdup.u32 v_block, uv[1];                                                     \
1409   vdup.u32 r_block, rg[0];                                                     \
1410   vdup.u32 g_block, rg[1];                                                     \
1411                                                                                \
1412   vld1.u32 { block_span }, [ block_span_ptr, :128 ]!;                          \
1413                                                                                \
1414   vadd.u32 u_block, u_block, block_span;                                       \
1415   vld1.u32 { block_span }, [ block_span_ptr, :128 ]!;                          \
1416                                                                                \
1417   vadd.u32 v_block, v_block, block_span;                                       \
1418   vld1.u32 { block_span }, [ block_span_ptr, :128 ]!;                          \
1419                                                                                \
1420   vadd.u32 r_block, r_block, block_span;                                       \
1421   vld1.u32 { block_span }, [ block_span_ptr, :128 ]!;                          \
1422                                                                                \
1423   vadd.u32 g_block, g_block, block_span;                                       \
1424   vld1.u32 { block_span }, [ block_span_ptr, :128 ];                           \
1425                                                                                \
1426   vadd.u32 b_block, b_block, block_span;                                       \
1427   add block_ptr_b, block_ptr_a, #16;                                           \
1428                                                                                \
1429   vshrn.u32 u_whole_low, u_block, #16;                                         \
1430   vshrn.u32 v_whole_low, v_block, #16;                                         \
1431   vshrn.u32 r_whole_low, r_block, #16;                                         \
1432   vshrn.u32 g_whole_low, g_block, #16;                                         \
1433                                                                                \
1434   vdup.u32 dx4, uv_dx4[0];                                                     \
1435   vshrn.u32 b_whole_low, b_block, #16;                                         \
1436                                                                                \
1437   vaddhn.u32 u_whole_high, u_block, dx4;                                       \
1438   vdup.u32 dx4, uv_dx4[1];                                                     \
1439                                                                                \
1440   vaddhn.u32 v_whole_high, v_block, dx4;                                       \
1441   vdup.u32 dx4, rg_dx4[0];                                                     \
1442                                                                                \
1443   vaddhn.u32 r_whole_high, r_block, dx4;                                       \
1444   vdup.u32 dx4, rg_dx4[1];                                                     \
1445                                                                                \
1446   vaddhn.u32 g_whole_high, g_block, dx4;                                       \
1447   vdup.u32 dx4, b_dx4;                                                         \
1448                                                                                \
1449   vaddhn.u32 b_whole_high, b_block, dx4;                                       \
1450   vdup.u32 dx8, uv_dx8[0];                                                     \
1451                                                                                \
1452   vadd.u32 u_block, u_block, dx8;                                              \
1453   vdup.u32 dx8, uv_dx8[1];                                                     \
1454                                                                                \
1455   vadd.u32 v_block, v_block, dx8;                                              \
1456   vdup.u32 dx8, rg_dx8[0];                                                     \
1457                                                                                \
1458   vadd.u32 r_block, r_block, dx8;                                              \
1459   vdup.u32 dx8, rg_dx8[1];                                                     \
1460                                                                                \
1461   vadd.u32 g_block, g_block, dx8;                                              \
1462   vdup.u32 dx8, b_dx8;                                                         \
1463                                                                                \
1464   vadd.u32 b_block, b_block, dx8;                                              \
1465   vmovn.u16 u_whole_8, u_whole;                                                \
1466                                                                                \
1467   vmovn.u16 v_whole_8, v_whole;                                                \
1468                                                                                \
1469   vmovn.u16 b_whole_8, b_whole;                                                \
1470   pld [ fb_ptr ];                                                              \
1471   vmov.u32 fb_mask_ptrs[1], fb_ptr;                                            \
1472                                                                                \
1473   vand.u8 uv_whole_8, uv_whole_8, texture_mask;                                \
1474   setup_blocks_texture_##swizzling();                                          \
1475                                                                                \
1476   vmovn.u16 r_whole_8, r_whole;                                                \
1477   beq 5f;                                                                      \
1478                                                                                \
1479  4:                                                                            \
1480   vmovn.u16 g_whole_8, g_whole;                                                \
1481   vshrn.u32 u_whole_low, u_block, #16;                                         \
1482                                                                                \
1483   vst2.u8 { u_whole_8, v_whole_8 }, [ block_ptr_a, :128 ], c_32;               \
1484   vshrn.u32 v_whole_low, v_block, #16;                                         \
1485                                                                                \
1486   vst1.u32 { r_whole_8, g_whole_8 }, [ block_ptr_b, :128 ], c_32;              \
1487   vshrn.u32 r_whole_low, r_block, #16;                                         \
1488                                                                                \
1489   vst1.u32 { b_whole_8, fb_mask_ptrs }, [ block_ptr_a, :128 ], c_32;           \
1490   vshrn.u32 g_whole_low, g_block, #16;                                         \
1491                                                                                \
1492   vdup.u32 dx4, uv_dx4[0];                                                     \
1493   vshrn.u32 b_whole_low, b_block, #16;                                         \
1494                                                                                \
1495   vaddhn.u32 u_whole_high, u_block, dx4;                                       \
1496   vdup.u32 dx4, uv_dx4[1];                                                     \
1497                                                                                \
1498   vaddhn.u32 v_whole_high, v_block, dx4;                                       \
1499   vdup.u32 dx4, rg_dx4[0];                                                     \
1500                                                                                \
1501   vaddhn.u32 r_whole_high, r_block, dx4;                                       \
1502   vdup.u32 dx4, rg_dx4[1];                                                     \
1503                                                                                \
1504   vaddhn.u32 g_whole_high, g_block, dx4;                                       \
1505   vdup.u32 dx4, b_dx4;                                                         \
1506                                                                                \
1507   vaddhn.u32 b_whole_high, b_block, dx4;                                       \
1508   vdup.u32 dx8, uv_dx8[0];                                                     \
1509                                                                                \
1510   vadd.u32 u_block, u_block, dx8;                                              \
1511   vdup.u32 dx8, uv_dx8[1];                                                     \
1512                                                                                \
1513   vadd.u32 v_block, v_block, dx8;                                              \
1514   vdup.u32 dx8, rg_dx8[0];                                                     \
1515                                                                                \
1516   vadd.u32 r_block, r_block, dx8;                                              \
1517   vdup.u32 dx8, rg_dx8[1];                                                     \
1518                                                                                \
1519   vadd.u32 g_block, g_block, dx8;                                              \
1520   vdup.u32 dx8, b_dx8;                                                         \
1521                                                                                \
1522   vadd.u32 b_block, b_block, dx8;                                              \
1523   vmovn.u16 u_whole_8, u_whole;                                                \
1524                                                                                \
1525   add fb_ptr, fb_ptr, #16;                                                     \
1526   vmovn.u16 v_whole_8, v_whole;                                                \
1527                                                                                \
1528   vst1.u32 { dither_offsets }, [ block_ptr_b, :128 ], c_32;                    \
1529   vmovn.u16 b_whole_8, b_whole;                                                \
1530                                                                                \
1531   pld [ fb_ptr ];                                                              \
1532                                                                                \
1533   vmov.u32 fb_mask_ptrs[1], fb_ptr;                                            \
1534   subs span_num_blocks, span_num_blocks, #1;                                   \
1535                                                                                \
1536   vand.u8 uv_whole_8, uv_whole_8, texture_mask;                                \
1537   setup_blocks_texture_##swizzling();                                          \
1538                                                                                \
1539   vmovn.u16 r_whole_8, r_whole;                                                \
1540   bne 4b;                                                                      \
1541                                                                                \
1542  5:                                                                            \
1543   vmovn.u16 g_whole_8, g_whole;                                                \
1544   ldrh right_mask, [ span_edge_data, #edge_data_right_mask_offset ];           \
1545                                                                                \
1546   vld1.u32 { test_mask }, [ psx_gpu, :128 ];                                   \
1547   vdup.u8 draw_mask, right_mask;                                               \
1548                                                                                \
1549   vmov.u32 fb_mask_ptrs[0], right_mask;                                        \
1550   vtst.u16 draw_mask, draw_mask, test_mask;                                    \
1551   vzip.u8 u_whole_8, v_whole_8;                                                \
1552                                                                                \
1553   vbic.u16 uv_whole_8, uv_whole_8, draw_mask;                                  \
1554   vst1.u32 { r_whole_8, g_whole_8 }, [ block_ptr_b, :128 ], c_32;              \
1555   vst1.u32 { uv_whole_8 }, [ block_ptr_a, :128 ], c_32;                        \
1556   vst1.u32 { dither_offsets }, [ block_ptr_b, :128 ], c_32;                    \
1557   vst1.u32 { b_whole_8, fb_mask_ptrs }, [ block_ptr_a, :128 ], c_32;           \
1558                                                                                \
1559  1:                                                                            \
1560   add span_uvrg_offset, span_uvrg_offset, #16;                                 \
1561   add span_b_offset, span_b_offset, #4;                                        \
1562                                                                                \
1563   add span_edge_data, span_edge_data, #8;                                      \
1564   subs num_spans, num_spans, #1;                                               \
1565                                                                                \
1566   strh num_blocks, [ psx_gpu, #psx_gpu_num_blocks_offset ];                    \
1567   bne 0b;                                                                      \
1568                                                                                \
1569   ldmia sp!, { r4 - r11, pc };                                                 \
1570                                                                                \
1571  2:                                                                            \
1572   /* TODO: Load from psx_gpu instead of saving/restoring these               */\
1573   vpush { texture_mask };                                                      \
1574   vpush { uvrg_dx4 };                                                          \
1575                                                                                \
1576   stmdb sp!, { r0 - r3, r12, r14 };                                            \
1577   bl flush_render_block_buffer;                                                \
1578   ldmia sp!, { r0 - r3, r12, r14 };                                            \
1579                                                                                \
1580   vpop { uvrg_dx4 };                                                           \
1581   vpop { texture_mask };                                                       \
1582                                                                                \
1583   vadd.u32 uvrg_dx8, uvrg_dx4, uvrg_dx4;                                       \
1584   vmov.u8 fb_mask_ptrs, #0;                                                    \
1585                                                                                \
1586   mov num_blocks, span_num_blocks;                                             \
1587   add block_ptr_a, psx_gpu, #psx_gpu_blocks_offset;                            \
1588   bal 3b                                                                       \
1589
1590
1591 setup_blocks_shaded_textured_builder(swizzled)
1592 setup_blocks_shaded_textured_builder(unswizzled)
1593
1594
1595 #define setup_blocks_unshaded_textured_builder(swizzling)                      \
1596 .align 3;                                                                      \
1597                                                                                \
1598 function(setup_blocks_unshaded_textured_dithered_##swizzling##_indirect)       \
1599   ldrh num_spans, [ psx_gpu, #psx_gpu_num_spans_offset ];                      \
1600   add uvrg_dx_ptr, psx_gpu, #psx_gpu_uvrg_dx_offset;                           \
1601                                                                                \
1602   vld1.u32 { uvrg_dx }, [ uvrg_dx_ptr, :128 ];                                 \
1603   add texture_mask_ptr, psx_gpu, #psx_gpu_texture_mask_width_offset;           \
1604                                                                                \
1605   cmp num_spans, #0;                                                           \
1606   bxeq lr;                                                                     \
1607                                                                                \
1608   stmdb sp!, { r4 - r11, r14 };                                                \
1609   vshl.u32 uvrg_dx4, uvrg_dx, #2;                                              \
1610                                                                                \
1611   vshl.u32 uvrg_dx8, uvrg_dx, #3;                                              \
1612                                                                                \
1613   vld2.u8 { texture_mask_u[], texture_mask_v[] }, [ texture_mask_ptr, :16 ];   \
1614   add span_uvrg_offset, psx_gpu, #psx_gpu_span_uvrg_offset_offset;             \
1615                                                                                \
1616   ldrh num_blocks, [ psx_gpu, #psx_gpu_num_blocks_offset ];                    \
1617   add span_edge_data, psx_gpu, #psx_gpu_span_edge_data_offset;                 \
1618                                                                                \
1619   add block_ptr_a, psx_gpu, #psx_gpu_blocks_offset;                            \
1620                                                                                \
1621   add block_ptr_a, block_ptr_a, num_blocks, lsl #6;                            \
1622                                                                                \
1623  0:                                                                            \
1624   vmov.u8 fb_mask_ptrs, #0;                                                    \
1625                                                                                \
1626   ldrh span_num_blocks, [ span_edge_data, #edge_data_num_blocks_offset ];      \
1627   add dither_offset_ptr, psx_gpu, #psx_gpu_dither_table_offset;                \
1628                                                                                \
1629   ldrh y, [ span_edge_data, #edge_data_y_offset ];                             \
1630   ldr fb_ptr, [ psx_gpu, #psx_gpu_vram_out_ptr_offset ];                       \
1631                                                                                \
1632   cmp span_num_blocks, #0;                                                     \
1633   beq 1f;                                                                      \
1634                                                                                \
1635   ldrh left_x, [ span_edge_data, #edge_data_left_x_offset ];                   \
1636   add num_blocks, span_num_blocks, num_blocks;                                 \
1637                                                                                \
1638   cmp num_blocks, #MAX_BLOCKS;                                                 \
1639   bgt 2f;                                                                      \
1640                                                                                \
1641  3:                                                                            \
1642   add fb_ptr, fb_ptr, y, lsl #11;                                              \
1643                                                                                \
1644   vdup.u32 v_left_x, left_x;                                                   \
1645   and y, y, #0x3;                                                              \
1646                                                                                \
1647   ldr dither_row, [ dither_offset_ptr, y, lsl #2 ];                            \
1648   add fb_ptr, fb_ptr, left_x, lsl #1;                                          \
1649                                                                                \
1650   and dither_shift, left_x, #0x03;                                             \
1651                                                                                \
1652   vld1.u32 { uvrg }, [ span_uvrg_offset, :128 ];                               \
1653   vshr.u32 uvrg_dx, uvrg_dx4, #2;                                              \
1654                                                                                \
1655   mov dither_shift, dither_shift, lsl #3;                                      \
1656   vmla.u32 uvrg, uvrg_dx, v_left_x;                                            \
1657                                                                                \
1658   mov c_32, #32;                                                               \
1659   subs span_num_blocks, span_num_blocks, #1;                                   \
1660                                                                                \
1661   mov dither_row, dither_row, ror dither_shift;                                \
1662                                                                                \
1663   vdup.u32 dither_offsets_short, dither_row;                                   \
1664   add block_span_ptr, psx_gpu, #psx_gpu_u_block_span_offset;                   \
1665                                                                                \
1666   vshll.s8 dither_offsets, dither_offsets_short, #4;                           \
1667                                                                                \
1668   vdup.u32 u_block, uv[0];                                                     \
1669                                                                                \
1670   vdup.u32 v_block, uv[1];                                                     \
1671   vld1.u32 { block_span }, [ block_span_ptr, :128 ]!;                          \
1672                                                                                \
1673   vadd.u32 u_block, u_block, block_span;                                       \
1674   vld1.u32 { block_span }, [ block_span_ptr, :128 ]!;                          \
1675                                                                                \
1676   vadd.u32 v_block, v_block, block_span;                                       \
1677   add block_ptr_b, block_ptr_a, #16;                                           \
1678                                                                                \
1679   vshrn.u32 u_whole_low, u_block, #16;                                         \
1680   vshrn.u32 v_whole_low, v_block, #16;                                         \
1681                                                                                \
1682   vdup.u32 dx4, uv_dx4[0];                                                     \
1683                                                                                \
1684   vaddhn.u32 u_whole_high, u_block, dx4;                                       \
1685   vdup.u32 dx4, uv_dx4[1];                                                     \
1686                                                                                \
1687   vaddhn.u32 v_whole_high, v_block, dx4;                                       \
1688   vdup.u32 dx8, uv_dx8[0];                                                     \
1689                                                                                \
1690   vadd.u32 u_block, u_block, dx8;                                              \
1691   vdup.u32 dx8, uv_dx8[1];                                                     \
1692                                                                                \
1693   vadd.u32 v_block, v_block, dx8;                                              \
1694   vmovn.u16 u_whole_8, u_whole;                                                \
1695                                                                                \
1696   vmovn.u16 v_whole_8, v_whole;                                                \
1697                                                                                \
1698   pld [ fb_ptr ];                                                              \
1699   vmov.u32 fb_mask_ptrs[1], fb_ptr;                                            \
1700                                                                                \
1701   vand.u8 uv_whole_8, uv_whole_8, texture_mask;                                \
1702   setup_blocks_texture_##swizzling();                                          \
1703                                                                                \
1704   beq 5f;                                                                      \
1705                                                                                \
1706  4:                                                                            \
1707   vshrn.u32 u_whole_low, u_block, #16;                                         \
1708                                                                                \
1709   vst2.u8 { u_whole_8, v_whole_8 }, [ block_ptr_a, :128 ], c_32;               \
1710   vshrn.u32 v_whole_low, v_block, #16;                                         \
1711                                                                                \
1712   add block_ptr_b, block_ptr_b, #32;                                           \
1713   vst1.u32 { b_whole_8, fb_mask_ptrs }, [ block_ptr_a, :128 ], c_32;           \
1714                                                                                \
1715   vdup.u32 dx4, uv_dx4[0];                                                     \
1716   vaddhn.u32 u_whole_high, u_block, dx4;                                       \
1717   vdup.u32 dx4, uv_dx4[1];                                                     \
1718                                                                                \
1719   vaddhn.u32 v_whole_high, v_block, dx4;                                       \
1720   vdup.u32 dx8, uv_dx8[0];                                                     \
1721                                                                                \
1722   vadd.u32 u_block, u_block, dx8;                                              \
1723   vdup.u32 dx8, uv_dx8[1];                                                     \
1724                                                                                \
1725   vadd.u32 v_block, v_block, dx8;                                              \
1726   vmovn.u16 u_whole_8, u_whole;                                                \
1727                                                                                \
1728   add fb_ptr, fb_ptr, #16;                                                     \
1729   vmovn.u16 v_whole_8, v_whole;                                                \
1730                                                                                \
1731   vst1.u32 { dither_offsets }, [ block_ptr_b, :128 ], c_32;                    \
1732   pld [ fb_ptr ];                                                              \
1733                                                                                \
1734   vmov.u32 fb_mask_ptrs[1], fb_ptr;                                            \
1735   subs span_num_blocks, span_num_blocks, #1;                                   \
1736                                                                                \
1737   vand.u8 uv_whole_8, uv_whole_8, texture_mask;                                \
1738   setup_blocks_texture_##swizzling();                                          \
1739                                                                                \
1740   bne 4b;                                                                      \
1741                                                                                \
1742  5:                                                                            \
1743   ldrh right_mask, [ span_edge_data, #edge_data_right_mask_offset ];           \
1744                                                                                \
1745   vld1.u32 { test_mask }, [ psx_gpu, :128 ];                                   \
1746   vdup.u8 draw_mask, right_mask;                                               \
1747                                                                                \
1748   vmov.u32 fb_mask_ptrs[0], right_mask;                                        \
1749   vtst.u16 draw_mask, draw_mask, test_mask;                                    \
1750   vzip.u8 u_whole_8, v_whole_8;                                                \
1751                                                                                \
1752   vbic.u16 uv_whole_8, uv_whole_8, draw_mask;                                  \
1753   add block_ptr_b, block_ptr_b, #32;                                           \
1754   vst1.u32 { uv_whole_8 }, [ block_ptr_a, :128 ], c_32;                        \
1755   vst1.u32 { dither_offsets }, [ block_ptr_b, :128 ], c_32;                    \
1756   vst1.u32 { b_whole_8, fb_mask_ptrs }, [ block_ptr_a, :128 ], c_32;           \
1757                                                                                \
1758  1:                                                                            \
1759   add span_uvrg_offset, span_uvrg_offset, #16;                                 \
1760   add span_edge_data, span_edge_data, #8;                                      \
1761   subs num_spans, num_spans, #1;                                               \
1762                                                                                \
1763   strh num_blocks, [ psx_gpu, #psx_gpu_num_blocks_offset ];                    \
1764   bne 0b;                                                                      \
1765                                                                                \
1766   ldmia sp!, { r4 - r11, pc };                                                 \
1767                                                                                \
1768  2:                                                                            \
1769   /* TODO: Load from psx_gpu instead of saving/restoring these               */\
1770   vpush { texture_mask };                                                      \
1771   vpush { uvrg_dx4 };                                                          \
1772                                                                                \
1773   stmdb sp!, { r0 - r3, r12, r14 };                                            \
1774   bl flush_render_block_buffer;                                                \
1775   ldmia sp!, { r0 - r3, r12, r14 };                                            \
1776                                                                                \
1777   vpop { uvrg_dx4 };                                                           \
1778   vpop { texture_mask };                                                       \
1779                                                                                \
1780   vadd.u32 uvrg_dx8, uvrg_dx4, uvrg_dx4;                                       \
1781   vmov.u8 fb_mask_ptrs, #0;                                                    \
1782                                                                                \
1783   mov num_blocks, span_num_blocks;                                             \
1784   add block_ptr_a, psx_gpu, #psx_gpu_blocks_offset;                            \
1785   bal 3b                                                                       \
1786
1787
1788 setup_blocks_unshaded_textured_builder(swizzled)
1789 setup_blocks_unshaded_textured_builder(unswizzled)
1790
1791
1792 .align 3
1793
1794 function(setup_blocks_unshaded_untextured_undithered_unswizzled_indirect)
1795   ldrh num_spans, [ psx_gpu, #psx_gpu_num_spans_offset ]
1796   veor.u32 draw_mask, draw_mask, draw_mask
1797
1798   cmp num_spans, #0
1799   bxeq lr
1800
1801   stmdb sp!, { r4 - r11, r14 }
1802   vld1.u32 { test_mask }, [ psx_gpu, :128 ]
1803
1804   ldr color, [ psx_gpu, #psx_gpu_triangle_color_offset ]
1805
1806   ubfx color_r, color, #3, #5
1807   ubfx color_g, color, #11, #5
1808   ubfx color_b, color, #19, #5
1809
1810   orr color, color_r, color_b, lsl #10
1811   orr color, color, color_g, lsl #5
1812
1813   vdup.u16 colors, color
1814
1815   ldrh num_blocks, [ psx_gpu, #psx_gpu_num_blocks_offset ]
1816   add span_edge_data, psx_gpu, #psx_gpu_span_edge_data_offset
1817
1818   add block_ptr_a, psx_gpu, #psx_gpu_blocks_offset
1819   add block_ptr_a, block_ptr_a, num_blocks, lsl #6
1820
1821  0:
1822   ldrh span_num_blocks, [ span_edge_data, #edge_data_num_blocks_offset ]
1823   ldrh y, [ span_edge_data, #edge_data_y_offset ]
1824
1825   ldr fb_ptr, [ psx_gpu, #psx_gpu_vram_out_ptr_offset ]
1826
1827   cmp span_num_blocks, #0
1828   beq 1f
1829
1830   ldrh left_x, [ span_edge_data, #edge_data_left_x_offset ]
1831   add num_blocks, span_num_blocks, num_blocks
1832
1833   cmp num_blocks, #MAX_BLOCKS
1834   bgt 2f
1835
1836  3:
1837   add fb_ptr, fb_ptr, y, lsl #11
1838   and y, y, #0x3
1839
1840   add fb_ptr, fb_ptr, left_x, lsl #1
1841   mov c_32, #32
1842
1843   subs span_num_blocks, span_num_blocks, #1
1844
1845   add block_ptr_b, block_ptr_a, #16
1846   pld [ fb_ptr ]
1847
1848   vmov.u32 fb_mask_ptrs[1], fb_ptr
1849   beq 5f
1850
1851  4:
1852   vst1.u32 { draw_mask }, [ block_ptr_a, :128 ], c_32
1853   vst1.u32 { colors }, [ block_ptr_b, :128 ], c_32
1854   vst1.u32 { b_whole_8, fb_mask_ptrs }, [ block_ptr_a, :128 ], c_32
1855
1856   add fb_ptr, fb_ptr, #16
1857   add block_ptr_b, block_ptr_b, #32
1858
1859   pld [ fb_ptr ]
1860
1861   vmov.u32 fb_mask_ptrs[1], fb_ptr
1862   subs span_num_blocks, span_num_blocks, #1
1863
1864   bne 4b
1865
1866  5:
1867   ldrh right_mask, [ span_edge_data, #edge_data_right_mask_offset ]
1868
1869   vdup.u8 draw_mask_edge, right_mask
1870   vtst.u16 draw_mask_edge, draw_mask_edge, test_mask
1871
1872   vst1.u32 { colors }, [ block_ptr_b, :128 ], c_32
1873   vst1.u32 { draw_mask_edge }, [ block_ptr_a, :128 ], c_32
1874   add block_ptr_b, block_ptr_b, #32
1875   vst1.u32 { b_whole_8, fb_mask_ptrs }, [ block_ptr_a, :128 ], c_32
1876
1877  1:
1878   add span_edge_data, span_edge_data, #8
1879   subs num_spans, num_spans, #1
1880
1881   strh num_blocks, [ psx_gpu, #psx_gpu_num_blocks_offset ]
1882   bne 0b
1883
1884   ldmia sp!, { r4 - r11, pc }
1885                                                                            
1886  2:
1887   vpush { colors }
1888
1889   stmdb sp!, { r0 - r3, r12, r14 }
1890   bl flush_render_block_buffer
1891   ldmia sp!, { r0 - r3, r12, r14 }
1892
1893   vpop { colors }
1894
1895   vld1.u32 { test_mask }, [ psx_gpu, :128 ]
1896   veor.u32 draw_mask, draw_mask, draw_mask
1897
1898   mov num_blocks, span_num_blocks
1899   add block_ptr_a, psx_gpu, #psx_gpu_blocks_offset
1900   bal 3b
1901
1902
1903 #define mask_msb_scalar                                   r14
1904
1905 #define msb_mask                                          q15
1906
1907 #define pixels_low                                        d16
1908
1909 #define msb_mask_low                                      d30
1910 #define msb_mask_high                                     d31
1911
1912
1913 .align 3
1914
1915 function(setup_blocks_unshaded_untextured_undithered_unswizzled_direct)
1916   ldrh num_spans, [ psx_gpu, #psx_gpu_num_spans_offset ]
1917
1918   cmp num_spans, #0
1919   bxeq lr
1920
1921   stmdb sp!, { r4 - r11, r14 }
1922
1923   ldr color, [ psx_gpu, #psx_gpu_triangle_color_offset ]
1924
1925   ubfx color_r, color, #3, #5
1926   ubfx color_g, color, #11, #5
1927
1928   ldrh mask_msb_scalar, [ psx_gpu, #psx_gpu_mask_msb_offset ]
1929   ubfx color_b, color, #19, #5
1930
1931   orr color, color_r, color_b, lsl #10
1932   orr color, color, color_g, lsl #5
1933   orr color, color, mask_msb_scalar
1934
1935   vdup.u16 colors, color
1936
1937   add span_edge_data, psx_gpu, #psx_gpu_span_edge_data_offset
1938   orr color, color, lsl #16
1939
1940
1941  0:
1942   ldrh span_num_blocks, [ span_edge_data, #edge_data_num_blocks_offset ]
1943   ldrh y, [ span_edge_data, #edge_data_y_offset ]
1944
1945   ldr fb_ptr, [ psx_gpu, #psx_gpu_vram_out_ptr_offset ]
1946
1947   cmp span_num_blocks, #0
1948   beq 1f
1949
1950   ldrh left_x, [ span_edge_data, #edge_data_left_x_offset ]
1951
1952   add fb_ptr, fb_ptr, y, lsl #11
1953   subs span_num_blocks, span_num_blocks, #1
1954
1955   add fb_ptr, fb_ptr, left_x, lsl #1
1956   beq 3f
1957
1958  2:
1959   vst1.u32 { colors }, [ fb_ptr ]!
1960   subs span_num_blocks, span_num_blocks, #1
1961
1962   bne 2b
1963
1964  3:
1965   ldrb right_mask, [ span_edge_data, #edge_data_right_mask_offset ]
1966
1967   cmp right_mask, #0x0
1968   beq 5f
1969
1970   tst right_mask, #0xF
1971   streq color, [ fb_ptr ], #4
1972   moveq right_mask, right_mask, lsr #4
1973   streq color, [ fb_ptr ], #4
1974
1975   tst right_mask, #0x3
1976   streq color, [ fb_ptr ], #4
1977   moveq right_mask, right_mask, lsr #2
1978
1979   tst right_mask, #0x1
1980   streqh color, [ fb_ptr ]
1981
1982  1:
1983   add span_edge_data, span_edge_data, #8
1984   subs num_spans, num_spans, #1
1985   bne 0b
1986
1987   ldmia sp!, { r4 - r11, pc }
1988                                                                            
1989  5:
1990   vst1.u32 { colors }, [ fb_ptr ]
1991   bal 1b
1992
1993
1994 #undef c_64
1995
1996 #define c_64                                              r7
1997 #define rg_dx_ptr                                         r2
1998
1999
2000 #undef r_block
2001 #undef g_block
2002 #undef b_block
2003 #undef r_whole
2004 #undef g_whole
2005 #undef b_whole
2006 #undef r_whole_low
2007 #undef r_whole_high
2008 #undef g_whole_low
2009 #undef g_whole_high
2010 #undef b_whole_low
2011 #undef b_whole_high
2012 #undef r_whole_8
2013 #undef g_whole_8
2014 #undef b_whole_8
2015 #undef dither_offsets
2016 #undef rg_dx4
2017 #undef rg_dx8
2018 #undef dx4
2019 #undef dx8
2020 #undef v_left_x
2021 #undef uvrg
2022 #undef block_span
2023 #undef rg
2024 #undef draw_mask
2025 #undef test_mask
2026
2027 #define r_block                                           q0
2028 #define g_block                                           q1
2029 #define b_block                                           q2
2030
2031 #define r_whole                                           q3
2032 #define g_whole                                           q4
2033 #define b_whole                                           q5
2034
2035 #define r_whole_low                                       d6
2036 #define r_whole_high                                      d7
2037 #define g_whole_low                                       d8
2038 #define g_whole_high                                      d9
2039 #define b_whole_low                                       d10
2040 #define b_whole_high                                      d11
2041
2042 #define gb_whole_8                                        q6
2043
2044 #define g_whole_8                                         d12
2045 #define b_whole_8                                         d13
2046
2047 #define r_whole_8                                         d14
2048
2049 #define pixels                                            q8
2050
2051 #define rg_dx4                                            d18
2052 #define rg_dx8                                            d19
2053
2054 #define dx4                                               q10
2055 #define dx8                                               q10
2056
2057 #define v_left_x                                          d6
2058 #define uvrg                                              q4
2059 #define block_span                                        q5
2060
2061 #define rg                                                d9
2062
2063 #define d64_1                                             d22
2064 #define d64_128                                           d23
2065
2066 #define d128_4                                            q12
2067 #define d128_0x7                                          q13
2068
2069 #define d64_4                                             d24
2070
2071 #define dither_offsets                                    q14
2072 #define draw_mask                                         q15
2073
2074 #define dither_offsets_low                                d28
2075
2076 #define rg_dx                                             d0
2077 #define test_mask                                         q10
2078
2079
2080 #define setup_blocks_shaded_untextured_dither_a_dithered()                     \
2081   vqadd.u8 r_whole_8, r_whole_8, dither_offsets_low;                           \
2082   vqadd.u8 gb_whole_8, gb_whole_8, dither_offsets;                             \
2083
2084 #define setup_blocks_shaded_untextured_dither_b_dithered()                     \
2085   vqsub.u8 r_whole_8, r_whole_8, d64_4;                                        \
2086   vqsub.u8 gb_whole_8, gb_whole_8, d128_4                                      \
2087
2088 #define setup_blocks_shaded_untextured_dither_a_undithered()                   \
2089
2090 #define setup_blocks_shaded_untextured_dither_b_undithered()                   \
2091
2092
2093 #define setup_blocks_shaded_untextured_indirect_builder(dithering)             \
2094 .align 3;                                                                      \
2095                                                                                \
2096 function(setup_blocks_shaded_untextured_##dithering##_unswizzled_indirect)     \
2097   ldrh num_spans, [ psx_gpu, #psx_gpu_num_spans_offset ];                      \
2098   add rg_dx_ptr, psx_gpu, #(psx_gpu_uvrg_dx_offset + 8);                       \
2099                                                                                \
2100   vld1.u32 { rg_dx }, [ rg_dx_ptr, :64 ];                                      \
2101                                                                                \
2102   cmp num_spans, #0;                                                           \
2103   bxeq lr;                                                                     \
2104                                                                                \
2105   stmdb sp!, { r4 - r11, r14 };                                                \
2106   vshl.u32 rg_dx4, rg_dx, #2;                                                  \
2107                                                                                \
2108   ldr b_dx, [ psx_gpu, #psx_gpu_b_dx_offset ];                                 \
2109   vshl.u32 rg_dx8, rg_dx, #3;                                                  \
2110                                                                                \
2111   add span_uvrg_offset, psx_gpu, #psx_gpu_span_uvrg_offset_offset;             \
2112                                                                                \
2113   ldrh num_blocks, [ psx_gpu, #psx_gpu_num_blocks_offset ];                    \
2114   add span_edge_data, psx_gpu, #psx_gpu_span_edge_data_offset;                 \
2115                                                                                \
2116   add span_b_offset, psx_gpu, #psx_gpu_span_b_offset_offset;                   \
2117   add block_ptr_a, psx_gpu, #psx_gpu_blocks_offset;                            \
2118                                                                                \
2119   add block_ptr_a, block_ptr_a, num_blocks, lsl #6;                            \
2120   vmov.u8 d64_1, #1;                                                           \
2121                                                                                \
2122   vmov.u8 d128_4, #4;                                                          \
2123   vmov.u8 d64_128, #128;                                                       \
2124                                                                                \
2125   vmov.u8 d128_0x7, #0x7;                                                      \
2126                                                                                \
2127  0:                                                                            \
2128   ldrh span_num_blocks, [ span_edge_data, #edge_data_num_blocks_offset ];      \
2129   add dither_offset_ptr, psx_gpu, #psx_gpu_dither_table_offset;                \
2130                                                                                \
2131   ldrh y, [ span_edge_data, #edge_data_y_offset ];                             \
2132   ldr fb_ptr, [ psx_gpu, #psx_gpu_vram_out_ptr_offset ];                       \
2133                                                                                \
2134   cmp span_num_blocks, #0;                                                     \
2135   beq 1f;                                                                      \
2136                                                                                \
2137   ldrh left_x, [ span_edge_data, #edge_data_left_x_offset ];                   \
2138   add num_blocks, span_num_blocks, num_blocks;                                 \
2139                                                                                \
2140   cmp num_blocks, #MAX_BLOCKS;                                                 \
2141   bgt 2f;                                                                      \
2142                                                                                \
2143  3:                                                                            \
2144   ldr b, [ span_b_offset ];                                                    \
2145   add fb_ptr, fb_ptr, y, lsl #11;                                              \
2146                                                                                \
2147   vdup.u32 v_left_x, left_x;                                                   \
2148   and y, y, #0x3;                                                              \
2149                                                                                \
2150   ldr dither_row, [ dither_offset_ptr, y, lsl #2 ];                            \
2151   add fb_ptr, fb_ptr, left_x, lsl #1;                                          \
2152                                                                                \
2153   mla b, b_dx, left_x, b;                                                      \
2154   and dither_shift, left_x, #0x03;                                             \
2155                                                                                \
2156   vld1.u32 { uvrg }, [ span_uvrg_offset, :128 ];                               \
2157   vshr.u32 rg_dx, rg_dx4, #2;                                                  \
2158                                                                                \
2159   mov dither_shift, dither_shift, lsl #3;                                      \
2160   vmla.u32 rg, rg_dx, v_left_x;                                                \
2161                                                                                \
2162   mov c_64, #64;                                                               \
2163   subs span_num_blocks, span_num_blocks, #1;                                   \
2164                                                                                \
2165   mov dither_row, dither_row, ror dither_shift;                                \
2166   mov b_dx4, b_dx, lsl #2;                                                     \
2167                                                                                \
2168   vdup.u32 dither_offsets, dither_row;                                         \
2169   add block_span_ptr, psx_gpu, #psx_gpu_r_block_span_offset;                   \
2170                                                                                \
2171   vdup.u32 b_block, b;                                                         \
2172   vadd.u8 dither_offsets, dither_offsets, d128_4;                              \
2173                                                                                \
2174   mov b_dx8, b_dx, lsl #3;                                                     \
2175   vdup.u32 r_block, rg[0];                                                     \
2176   vdup.u32 g_block, rg[1];                                                     \
2177                                                                                \
2178   vld1.u32 { block_span }, [ block_span_ptr, :128 ]!;                          \
2179                                                                                \
2180   vadd.u32 r_block, r_block, block_span;                                       \
2181   vld1.u32 { block_span }, [ block_span_ptr, :128 ]!;                          \
2182                                                                                \
2183   vadd.u32 g_block, g_block, block_span;                                       \
2184   vld1.u32 { block_span }, [ block_span_ptr, :128 ];                           \
2185                                                                                \
2186   vadd.u32 b_block, b_block, block_span;                                       \
2187   add block_ptr_b, block_ptr_a, #16;                                           \
2188                                                                                \
2189   vshrn.u32 r_whole_low, r_block, #16;                                         \
2190   vshrn.u32 g_whole_low, g_block, #16;                                         \
2191   vshrn.u32 b_whole_low, b_block, #16;                                         \
2192   vdup.u32 dx4, rg_dx4[0];                                                     \
2193                                                                                \
2194   vaddhn.u32 r_whole_high, r_block, dx4;                                       \
2195   vdup.u32 dx4, rg_dx4[1];                                                     \
2196                                                                                \
2197   vaddhn.u32 g_whole_high, g_block, dx4;                                       \
2198   vdup.u32 dx4, b_dx4;                                                         \
2199                                                                                \
2200   vaddhn.u32 b_whole_high, b_block, dx4;                                       \
2201   vdup.u32 dx8, rg_dx8[0];                                                     \
2202                                                                                \
2203   vadd.u32 r_block, r_block, dx8;                                              \
2204   vdup.u32 dx8, rg_dx8[1];                                                     \
2205                                                                                \
2206   vadd.u32 g_block, g_block, dx8;                                              \
2207   vdup.u32 dx8, b_dx8;                                                         \
2208                                                                                \
2209   vadd.u32 b_block, b_block, dx8;                                              \
2210                                                                                \
2211   vmovn.u16 r_whole_8, r_whole;                                                \
2212   vmovn.u16 g_whole_8, g_whole;                                                \
2213   vmovn.u16 b_whole_8, b_whole;                                                \
2214                                                                                \
2215   beq 5f;                                                                      \
2216   veor.u32 draw_mask, draw_mask, draw_mask;                                    \
2217                                                                                \
2218  4:                                                                            \
2219   setup_blocks_shaded_untextured_dither_a_##dithering();                       \
2220   vshrn.u32 r_whole_low, r_block, #16;                                         \
2221                                                                                \
2222   setup_blocks_shaded_untextured_dither_b_##dithering();                       \
2223   vshrn.u32 g_whole_low, g_block, #16;                                         \
2224                                                                                \
2225   vshrn.u32 b_whole_low, b_block, #16;                                         \
2226   str fb_ptr, [ block_ptr_a, #44 ];                                            \
2227                                                                                \
2228   vdup.u32 dx4, rg_dx4[0];                                                     \
2229   vshr.u8 r_whole_8, r_whole_8, #3;                                            \
2230   vbic.u8 gb_whole_8, gb_whole_8, d128_0x7;                                    \
2231                                                                                \
2232   vaddhn.u32 r_whole_high, r_block, dx4;                                       \
2233   vdup.u32 dx4, rg_dx4[1];                                                     \
2234                                                                                \
2235   vaddhn.u32 g_whole_high, g_block, dx4;                                       \
2236   vdup.u32 dx4, b_dx4;                                                        &n