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