psx_gpu: texture cache fix, updates
[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 #define function(name)                                                         \
245   .global name;                                                                \
246   name:                                                                        \
247
248 @ r0: psx_gpu
249 @ r1: v_a
250 @ r2: v_b
251 @ r3: v_c
252
253 function(compute_all_gradients)
254   // First compute the triangle area reciprocal and shift. The division will
255   // happen concurrently with much of the work which follows.
256   @ r12 = psx_gpu->triangle_area
257   ldr r12, [ psx_gpu, #psx_gpu_triangle_area_offset ]
258   stmdb sp!, { r4 - r11, lr }
259
260   @ load exponent of 62 into upper half of double
261   movw r4, #0
262   clz r14, r12                       @ r14 = shift
263
264   movt r4, #((62 + 1023) << 4)
265   mov r12, r12, lsl r14              @ r12 = triangle_area_normalized
266
267   @ load area normalized into lower half of double
268   mov r5, r12, lsr #10
269   vmov.f64 d30, r5, r4               @ d30 = (1 << 62) + ta_n
270
271   movt r4, #((1022 + 31) << 4)
272   mov r5, r12, lsl #20
273
274   add r4, r4, r12, lsr #11
275   vmov.f64 d31, r5, r4
276
277   vdiv.f64 d30, d30, d31             @ d30 = ((1 << 62) + ta_n) / ta_n
278
279   // ((x1 - x0) * (y2 - y1)) - ((x2 - x1) * (y1 - y0)) =
280   // ( d0       *  d1      ) - ( d2       *  d3      ) =
281   // ( m0                  ) - ( m1                  ) = gradient
282
283   // This is split to do 12 elements at a time over three sets: a, b, and c.
284   // Technically we only need to do 10 elements (uvrgb_x and uvrgb_y), so
285   // two of the slots are unused.
286
287   // Inputs are all 16-bit signed. The m0/m1 results are 32-bit signed, as
288   // is g.
289
290   // First type is:  uvrg bxxx xxxx 
291   // Second type is: yyyy ybyy uvrg 
292   // Since x_a and y_c are the same the same variable is used for both. 
293
294   vld1.u32 { v0 }, [ v_a, : 128 ]    @ v0 = { uvrg0, b0, x0, y0 }
295   ldrsh x0, [ v_a, #8 ]              @ load x0
296
297   vld1.u32 { v1 }, [ v_b, : 128 ]    @ v1 = { uvrg1, b1, x1, y1}
298   ldrh x1, [ v_b, #8 ]               @ load x1
299
300   vld1.u32 { v2 }, [ v_c, : 128 ]    @ v2 = { uvrg2, b2, x2, y2 }
301   ldrh x2, [ v_c, #8 ]               @ load x2
302
303   vmovl.u8 uvrg_xxxx0, uvrgb0        @ uvrg_xxxx0 = { uv0, rg0, b0-, -- }
304   ldrh y0, [ v_a, #10 ]              @ load y0
305
306   vmovl.u8 uvrg_xxxx1, uvrgb1        @ uvrg_xxxx1 = { uv1, rg1, b1-, -- }
307   ldrh y1, [ v_b, #10 ]              @ load y1
308
309   vmovl.u8 uvrg_xxxx2, uvrgb2        @ uvrg_xxxx2 = { uv2, rg2, b2-, -- }
310   ldrh y2, [ v_c, #10 ]              @ load y2
311
312   vmov.u8 uvrg0b, uvrg0              @ uvrg0b = { uv0, rg0 }
313   vdup.u16 xxxx0, x0_y0[0]           @ xxxx0 = { xx0, xx0 }
314
315   orr x1_x2, x1, x2, lsl #16         @ x1_x2 = { x1, x2 }
316   pkhbt x0_x1, x0, x1, lsl #16       @ x0_x1 = { x0, x1 }
317
318   vmov.u8 uvrg1b, uvrg1              @ uvrg1b = { uv1, rg1 }
319   vdup.u16 xxxx1, x1_y1[0]           @ xxxx1 = { xx1, xx1 }
320
321   vmov.u8 uvrg2b, uvrg2              @ uvrg2b = { uv2, rg2 }
322   vdup.u16 xxxx2, x2_y2[0]           @ xxxx2 = { xx2, xx2 }
323
324   ldrb b2, [ v_c, #4 ]               @ load b2
325   orr y0_y1, y0, y1, lsl #16         @ y0_y1 = { y0, y1 }
326
327   ldrb b1, [ v_b, #4 ]               @ load b1
328   orr y1_y2, y1, y2, lsl #16         @ y1_y2 = { y1, y2 }
329
330   vdup.u16 yyyy0, x0_y0[1]           @ yyyy0 = { yy0, yy0 }
331   vsub.s16 d0_ab, x1_ab, x0_ab
332
333   ldrb b0, [ v_a, #4 ]               @ load b0
334   orr b1_b2, b1, b2, lsl #16         @ b1_b2 = { b1, b2 }
335
336   vdup.u16 yyyy1, x1_y1[1]           @ yyyy1 = { yy1, yy1 }
337   vsub.s16 d2_ab, x2_ab, x1_ab
338
339   vdup.u16 yyyy2, x2_y2[1]           @ yyyy2 = { yy2, yy2 }
340   vsub.s16 d1_ab, y2_ab, y1_ab
341
342   orr b0_b1, b0, b1, lsl #16         @ b1_b2 = { b1, b2 }
343   ssub16 dx, x1_x2, x0_x1            @ dx = { x1 - x0, x2 - x1 }
344
345   ssub16 dy, y1_y2, y0_y1            @ dy = { y1 - y0, y2 - y1 }
346   ssub16 db, b1_b2, b0_b1            @ db = { b1 - b0, b2 - b1 }
347
348   vsub.s16 d3_ab, y1_ab, y0_ab
349   smusdx ga_by, dx, db               @ ga_by = ((x1 - x0) * (b2 - b1)) -
350                                      @         ((x2 - X1) * (b1 - b0)) 
351   vmull.s16 ga_uvrg_x, d0_a, d1_a
352   smusdx ga_bx, db, dy               @ ga_bx = ((b1 - b0) * (y2 - y1)) -
353                                      @         ((b2 - b1) * (y1 - y0))
354   vmlsl.s16 ga_uvrg_x, d2_a, d3_a
355   movs gs_bx, ga_bx, asr #31
356
357   vmull.s16 ga_uvrg_y, d0_b, d1_b
358   rsbmi ga_bx, ga_bx, #0
359
360   vmlsl.s16 ga_uvrg_y, d2_b, d3_b
361   movs gs_by, ga_by, asr #31
362
363   vshr.u64 d0, d30, #22
364   mov b_base, b0, lsl #16
365
366   rsbmi ga_by, ga_by, #0
367   vclt.s32 gs_uvrg_x, ga_uvrg_x, #0  @ gs_uvrg_x = ga_uvrg_x < 0
368
369   @ r12 = psx_gpu->triangle_winding_offset
370   ldrb r12, [ psx_gpu, #psx_gpu_triangle_winding_offset ]
371   vclt.s32 gs_uvrg_y, ga_uvrg_y, #0  @ gs_uvrg_y = ga_uvrg_y < 0
372
373   add b_base, b_base, #0x8000
374   rsb r12, r12, #0                   @ r12 = -(triangle->winding)
375
376   vdup.u32 w_mask, r12               @ w_mask = { -w, -w, -w, -w }
377   sub r14, r14, #(62 - 12)           @ r14 = shift - (62 - FIXED_BITS)
378
379   vshll.u16 uvrg_base, uvrg0, #16    @ uvrg_base = uvrg0 << 16
380   vdup.u32 r_shift, r14              @ r_shift = { shift, shift, shift, shift }
381
382   vorr.u32 uvrg_base, #0x8000
383   vabs.s32 ga_uvrg_x, ga_uvrg_x      @ ga_uvrg_x = abs(ga_uvrg_x)
384
385   vmov area_r_s, s0                  @ area_r_s = triangle_reciprocal
386   vabs.s32 ga_uvrg_y, ga_uvrg_y      @ ga_uvrg_y = abs(ga_uvrg_y)
387
388   vmull.u32 gw_rg_x, ga_rg_x, d0[0]
389   vmull.u32 gw_uv_x, ga_uv_x, d0[0]
390   vmull.u32 gw_rg_y, ga_rg_y, d0[0]
391   vmull.u32 gw_uv_y, ga_uv_y, d0[0]
392
393   vshl.u64 gw_rg_x, gw_rg_x, r_shift
394   vshl.u64 gw_uv_x, gw_uv_x, r_shift
395   vshl.u64 gw_rg_y, gw_rg_y, r_shift
396   vshl.u64 gw_uv_y, gw_uv_y, r_shift
397
398   veor.u32 gs_uvrg_x, gs_uvrg_x, w_mask
399   vmovn.u64 g_uv_x, gw_uv_x
400
401   veor.u32 gs_uvrg_y, gs_uvrg_y, w_mask
402   vmovn.u64 g_rg_x, gw_rg_x
403
404   veor.u32 g_uvrg_x, g_uvrg_x, gs_uvrg_x
405   vmovn.u64 g_uv_y, gw_uv_y
406
407   vsub.u32 g_uvrg_x, g_uvrg_x, gs_uvrg_x
408   vmovn.u64 g_rg_y, gw_rg_y
409
410   veor.u32 g_uvrg_y, g_uvrg_y, gs_uvrg_y
411   mov ga_bx, ga_bx, lsl #13
412
413   vsub.u32 g_uvrg_y, g_uvrg_y, gs_uvrg_y
414   mov ga_by, ga_by, lsl #13
415
416   vdup.u32 x0_y0, x0
417   umull gw_bx_l, gw_bx_h, ga_bx, area_r_s
418
419   vshl.u32 g_uvrg_x, g_uvrg_x, #4
420   vshl.u32 g_uvrg_y, g_uvrg_y, #4
421
422   umull gw_by_l, gw_by_h, ga_by, area_r_s
423   vmls.s32 uvrg_base, ga_uvrg_x, x0_y0[0]
424
425   eor gs_bx, gs_bx, r12
426   vadd.u32 uvrg_dx2, uvrg_dx1, uvrg_dx1
427
428   veor.u32 uvrg_dx0, uvrg_dx0, uvrg_dx0
429   eor gs_by, gs_by, r12
430
431   rsb r11, r14, #0                   @ r11 = negative shift for scalar lsr
432   add store_a, psx_gpu, #psx_gpu_uvrg_offset
433
434   sub r11, r11, #(32 - 13)
435
436   add store_b, store_a, #16
437   mov store_inc, #32
438
439   vadd.u32 uvrg_dx3, uvrg_dx2, uvrg_dx1
440   vst1.u32 { uvrg_base }, [ store_a, : 128 ], store_inc
441
442   vst1.u32 { uvrg_dx1 }, [ store_b, : 128 ], store_inc
443   mov g_bx, gw_bx_h, lsr r11
444
445   vst1.u32 { g_uvrg_y }, [ store_a, : 128 ], store_inc
446   mov g_by, gw_by_h, lsr r11
447
448   vst4.u32 { uvrg_dx0l, uvrg_dx1l, uvrg_dx2l, uvrg_dx3l },                     \
449    [ store_b, : 128 ], store_inc
450   eor g_bx, g_bx, gs_bx
451
452   vst4.u32 { uvrg_dx0h, uvrg_dx1h, uvrg_dx2h, uvrg_dx3h },                     \
453    [ store_b, : 128 ], store_inc
454   sub g_bx, g_bx, gs_bx
455
456   lsl g_bx, g_bx, #4  
457   eor g_by, g_by, gs_by
458
459   mls b_base, g_bx, x0, b_base
460   sub g_by, g_by, gs_by
461
462   lsl g_by, g_by, #4
463   mov g_bx0, #0
464
465   add g_bx2, g_bx, g_bx
466   add g_bx3, g_bx, g_bx2
467
468   stmia store_b, { g_bx0, g_bx, g_bx2, g_bx3, b_base, g_by }
469
470   ldmia sp!, { r4 - r11, pc }
471
472
473 #define psx_gpu                                  r0
474 #define v_a                                      r1
475 #define v_b                                      r2
476 #define v_c                                      r3
477
478 #define temp                                     r14
479
480 #define x_a                                      r4
481 #define x_b                                      r5
482 #define x_c                                      r6
483 #define y_a                                      r1
484 #define y_b                                      r2
485 #define y_c                                      r3
486
487 #define height_minor_a                           r7
488 #define height_minor_b                           r8
489 #define height_major                             r9
490 #define height                                   r9
491
492 #define reciprocal_table_ptr                     r10
493
494 #define edge_alt_low                             r4
495 #define edge_alt_high                            r5
496 #define edge_dx_dy_alt                           r6
497 #define edge_shift_alt                           r10
498
499 #define edge_dx_dy_alt_low                       r4
500 #define edge_dx_dy_alt_high                      r5
501
502 #define span_edge_data                           r4
503 #define span_uvrg_offset                         r5
504 #define span_b_offset                            r6
505
506 #define clip                                     r14
507
508 #define b                                        r11
509 #define b_dy                                     r12
510
511
512 #define alternate_x                              q0
513 #define alternate_dx_dy                          q1
514 #define alternate_x_32                           q2
515
516 #define alternate_x_low                          d0
517 #define alternate_x_high                         d1
518 #define alternate_dx_dy_low                      d2
519 #define alternate_dx_dy_high                     d3
520 #define alternate_x_32_low                       d4
521 #define alternate_x_32_high                      d5
522
523 #define left_x                                   q3
524 #define right_x                                  q4
525 #define left_dx_dy                               q5
526 #define right_dx_dy                              q6
527 #define left_edge                                q7
528 #define right_edge                               q8
529
530 #define left_x_low                               d6
531 #define left_x_high                              d7
532 #define right_x_low                              d8
533 #define right_x_high                             d9
534 #define left_dx_dy_low                           d10
535 #define left_dx_dy_high                          d11
536 #define right_dx_dy_low                          d12
537 #define right_dx_dy_high                         d13
538 #define left_edge_low                            d14
539 #define left_edge_high                           d15
540 #define right_edge_low                           d16
541 #define right_edge_high                          d17
542
543 #define y_mid_point                              d18
544 #define c_0x0004                                 d19
545
546 #define left_right_x_16                          q11
547 #define span_shifts_y                            q12
548 #define c_0x0001                                 q13
549
550 #define span_shifts                              d24
551 #define y_x4                                     d25
552 #define c_0xFFFE                                 d26
553 #define c_0x0007                                 d27
554
555 #define left_right_x_16_low                      d22
556 #define left_right_x_16_high                     d23
557
558 #define uvrg                                     q14
559 #define uvrg_dy                                  q15
560
561 #define alternate_x_16                           d4
562
563 #define v_clip                                   q3
564 #define v_clip_low                               d6
565
566 #define right_x_32                               q10
567 #define left_x_32                                q11
568 #define alternate_select                         d24
569
570 #define right_x_32_low                           d20
571 #define right_x_32_high                          d21
572 #define left_x_32_low                            d22
573 #define left_x_32_high                           d23
574
575 #define edges_xy                                 q0
576 #define edges_dx_dy                              d2
577 #define edge_shifts                              d3
578 #define edge_shifts_64                           q2
579
580 #define edges_xy_left                            d0
581 #define edges_xy_right                           d1
582
583 #define height_reciprocals                       d6
584 #define heights                                  d7
585
586 #define widths                                   d8
587 #define c_0x01                                   d9
588 #define x_starts                                 d10
589 #define x_ends                                   d11
590
591 #define heights_b                                d12
592 #define edges_dx_dy_64                           q10
593
594 #define edges_dx_dy_64_left                      d20
595 #define edges_dx_dy_64_right                     d21
596
597
598 #define setup_spans_prologue()                                                 \
599   stmdb sp!, { r4 - r11, lr };                                                 \
600                                                                                \
601   ldrsh x_a, [ v_a, #8 ];                                                      \
602   ldrsh x_b, [ v_b, #8 ];                                                      \
603   ldrsh x_c, [ v_c, #8 ];                                                      \
604   ldrsh y_a, [ v_a, #10 ];                                                     \
605   ldrsh y_b, [ v_b, #10 ];                                                     \
606   ldrsh y_c, [ v_c, #10 ];                                                     \
607                                                                                \
608   add temp, psx_gpu, #psx_gpu_uvrg_offset;                                     \
609   vld1.32 { uvrg }, [ temp ];                                                  \
610   add temp, psx_gpu, #psx_gpu_uvrg_dy_offset;                                  \
611   vld1.32 { uvrg_dy }, [ temp ];                                               \
612   movw reciprocal_table_ptr, :lower16:reciprocal_table;                        \
613   movt reciprocal_table_ptr, :upper16:reciprocal_table;                        \
614                                                                                \
615   vmov.u32 c_0x01, #0x01                                                       \
616
617 #define setup_spans_load_b()                                                   \
618   ldr b, [ psx_gpu, #psx_gpu_b_offset ];                                       \
619   ldr b_dy, [ psx_gpu, #psx_gpu_b_dy_offset ]                                  \
620
621 #define setup_spans_prologue_b()                                               \
622   add span_uvrg_offset, psx_gpu, #psx_gpu_span_uvrg_offset_offset;             \
623   add temp, psx_gpu, #psx_gpu_viewport_start_x_offset;                         \
624                                                                                \
625   add span_edge_data, psx_gpu, #psx_gpu_span_edge_data_offset;                 \
626   vmov.u16 c_0x0004, #0x0004;                                                  \
627                                                                                \
628   add span_b_offset, psx_gpu, #psx_gpu_span_b_offset_offset;                   \
629   vmov.u16 c_0x0001, #0x0001;                                                  \
630                                                                                \
631   vld1.u16 { left_edge_low[], left_edge_high[] }, [ temp ];                    \
632   add temp, psx_gpu, #psx_gpu_viewport_end_x_offset;                           \
633                                                                                \
634   vld1.u16 { right_edge_low[], right_edge_high[] }, [ temp ];                  \
635   vadd.u16 right_edge, right_edge, c_0x0001;                                   \
636                                                                                \
637   vmov.u16 c_0x0007, #0x0007;                                                  \
638   vmvn.u16 c_0xFFFE, #0x0001                                                   \
639
640
641 #define compute_edge_delta_x2()                                                \
642   ldr temp, [ reciprocal_table_ptr, height, lsl #2 ];                          \
643                                                                                \
644   vdup.u32 heights, height;                                                    \
645   vsub.u32 widths, x_ends, x_starts;                                           \
646                                                                                \
647   vdup.u32 edge_shifts, temp;                                                  \
648   vsub.u32 heights_b, heights, c_0x01;                                         \
649   vshr.u32 height_reciprocals, edge_shifts, #12;                               \
650                                                                                \
651   vmla.s32 heights_b, x_starts, heights;                                       \
652   vbic.u16 edge_shifts, #0xE0;                                                 \
653   vmul.s32 edges_dx_dy, widths, height_reciprocals;                            \
654   vmull.s32 edges_xy, heights_b, height_reciprocals                            \
655
656 #define width_alt                 r6
657 #define height_reciprocal_alt     r11
658 #define height_b_alt              r12
659
660 #define compute_edge_delta_x3(start_c, height_a, height_b)                     \
661   vmov.u32 heights, height_a, height_b;                                        \
662   ldr temp, [ reciprocal_table_ptr, height_a, lsl #2 ];                        \
663   vmov.u32 edge_shifts[0], temp;                                               \
664   ldr temp, [ reciprocal_table_ptr, height_b, lsl #2 ];                        \
665   vmov.u32 edge_shifts[1], temp;                                               \
666   ldr edge_shift_alt, [ reciprocal_table_ptr, height_minor_b, lsl #2 ];        \
667                                                                                \
668   vsub.u32 widths, x_ends, x_starts;                                           \
669   sub width_alt, x_c, start_c;                                                 \
670                                                                                \
671   vsub.u32 heights_b, heights, c_0x01;                                         \
672   sub height_b_alt, height_minor_b, #1;                                        \
673                                                                                \
674   vshr.u32 height_reciprocals, edge_shifts, #12;                               \
675   lsr height_reciprocal_alt, edge_shift_alt, #12;                              \
676                                                                                \
677   vmla.s32 heights_b, x_starts, heights;                                       \
678   mla height_b_alt, height_minor_b, start_c, height_b_alt;                     \
679                                                                                \
680   vbic.u16 edge_shifts, #0xE0;                                                 \
681   and edge_shift_alt, edge_shift_alt, #0x1F;                                   \
682                                                                                \
683   vmul.s32 edges_dx_dy, widths, height_reciprocals;                            \
684   mul edge_dx_dy_alt, width_alt, height_reciprocal_alt;                        \
685                                                                                \
686   vmull.s32 edges_xy, heights_b, height_reciprocals;                           \
687   smull edge_alt_low, edge_alt_high, height_b_alt, height_reciprocal_alt       \
688
689
690 #define setup_spans_adjust_y_up()                                              \
691   vsub.u32 y_x4, y_x4, c_0x0004                                                \
692
693 #define setup_spans_adjust_y_down()                                            \
694   vadd.u32 y_x4, y_x4, c_0x0004                                                \
695
696 #define setup_spans_adjust_interpolants_up()                                   \
697   vsub.u32 uvrg, uvrg, uvrg_dy;                                                \
698   sub b, b, b_dy                                                               \
699
700 #define setup_spans_adjust_interpolants_down()                                 \
701   vadd.u32 uvrg, uvrg, uvrg_dy;                                                \
702   add b, b, b_dy                                                               \
703
704
705 #define setup_spans_clip_interpolants_increment()                              \
706   mla b, b_dy, clip, b;                                                        \
707   vmla.s32 uvrg, uvrg_dy, v_clip                                               \
708
709 #define setup_spans_clip_interpolants_decrement()                              \
710   mls b, b_dy, clip, b;                                                        \
711   vmls.s32 uvrg, uvrg_dy, v_clip                                               \
712
713 #define setup_spans_clip_alternate_yes()                                       \
714   smlal edge_alt_low, edge_alt_high, edge_dx_dy_alt, clip                      \
715
716 #define setup_spans_clip_alternate_no()                                        \
717
718 #define setup_spans_clip(direction, alternate_active)                          \
719   vdup.u32 v_clip, clip;                                                       \
720   setup_spans_clip_alternate_##alternate_active();                             \
721   setup_spans_clip_interpolants_##direction();                                 \
722   vmlal.s32 edges_xy, edges_dx_dy, v_clip_low                                  \
723
724
725 #define setup_spans_adjust_edges_alternate_no(left_index, right_index)         \
726   vmovl.s32 edge_shifts_64, edge_shifts;                                       \
727   vmovl.s32 edges_dx_dy_64, edges_dx_dy;                                       \
728                                                                                \
729   vshl.s64 edges_xy, edges_xy, edge_shifts_64;                                 \
730   vshl.s64 edges_dx_dy_64, edges_dx_dy_64, edge_shifts_64;                     \
731                                                                                \
732   vmov left_x_low, edges_xy_##left_index;                                      \
733   vmov right_x_low, edges_xy_##right_index;                                    \
734                                                                                \
735   vmov left_dx_dy_low, edges_dx_dy_64_##left_index;                            \
736   vmov left_dx_dy_high, edges_dx_dy_64_##left_index;                           \
737   vmov right_dx_dy_low, edges_dx_dy_64_##right_index;                          \
738   vmov right_dx_dy_high, edges_dx_dy_64_##right_index;                         \
739                                                                                \
740   vadd.u64 left_x_high, left_x_low, left_dx_dy_low;                            \
741   vadd.u64 right_x_high, right_x_low, right_dx_dy_low;                         \
742                                                                                \
743   vadd.u64 left_dx_dy, left_dx_dy, left_dx_dy;                                 \
744   vadd.u64 right_dx_dy, right_dx_dy, right_dx_dy                               \
745
746
747 #define setup_spans_adjust_edges_alternate_yes(left_index, right_index)        \
748   setup_spans_adjust_edges_alternate_no(left_index, right_index);              \
749                                                                                \
750   vdup.u16 y_mid_point, y_b;                                                   \
751   rsb temp, edge_shift_alt, #32;                                               \
752                                                                                \
753   lsl edge_alt_high, edge_alt_high, edge_shift_alt;                            \
754   orr edge_alt_high, edge_alt_high, edge_alt_low, lsr temp;                    \
755   lsl edge_alt_low, edge_alt_low, edge_shift_alt;                              \
756   vmov alternate_x_low, edge_alt_low, edge_alt_high;                           \
757                                                                                \
758   asr edge_dx_dy_alt_high, edge_dx_dy_alt, temp;                               \
759   lsl edge_dx_dy_alt_low, edge_dx_dy_alt, edge_shift_alt;                      \
760   vmov alternate_dx_dy_low, edge_dx_dy_alt_low, edge_dx_dy_alt_high;           \
761   vmov alternate_dx_dy_high, alternate_dx_dy_low;                              \
762                                                                                \
763   vadd.u64 alternate_x_high, alternate_x_low, alternate_dx_dy_low;             \
764   vadd.u64 alternate_dx_dy, alternate_dx_dy, alternate_dx_dy                   \
765
766
767 #define setup_spans_y_select_up()                                              \
768   vclt.s16 alternate_select, y_x4, y_mid_point                                 \
769
770 #define setup_spans_y_select_down()                                            \
771   vcgt.s16 alternate_select, y_x4, y_mid_point                                 \
772
773
774 #define setup_spans_alternate_select_left()                                    \
775   vbit.u16 left_right_x_16_low, alternate_x_16, alternate_select               \
776
777 #define setup_spans_alternate_select_right()                                   \
778   vbit.u16 left_right_x_16_high, alternate_x_16, alternate_select              \
779
780
781 #define setup_spans_set_x4_alternate_yes(alternate, direction)                 \
782   vshrn.s64 alternate_x_32_low, alternate_x, #32;                              \
783   vshrn.s64 left_x_32_low, left_x, #32;                                        \
784   vshrn.s64 right_x_32_low, right_x, #32;                                      \
785                                                                                \
786   vadd.u64 alternate_x, alternate_x, alternate_dx_dy;                          \
787   vadd.u64 left_x, left_x, left_dx_dy;                                         \
788   vadd.u64 right_x, right_x, right_dx_dy;                                      \
789                                                                                \
790   vshrn.s64 alternate_x_32_high, alternate_x, #32;                             \
791   vshrn.s64 left_x_32_high, left_x, #32;                                       \
792   vshrn.s64 right_x_32_high, right_x, #32;                                     \
793                                                                                \
794   vadd.u64 alternate_x, alternate_x, alternate_dx_dy;                          \
795   vadd.u64 left_x, left_x, left_dx_dy;                                         \
796   vadd.u64 right_x, right_x, right_dx_dy;                                      \
797                                                                                \
798   vmovn.u32 alternate_x_16, alternate_x_32;                                    \
799   setup_spans_y_select_##direction();                                          \
800   vmovn.u32 left_right_x_16_low, left_x_32;                                    \
801                                                                                \
802   vmovn.u32 left_right_x_16_high, right_x_32;                                  \
803   setup_spans_alternate_select_##alternate();                                  \
804                                                                                \
805   vst1.u32 { uvrg }, [ span_uvrg_offset, :128 ]!;                              \
806   str b, [ span_b_offset ], #4;                                                \
807   setup_spans_adjust_interpolants_##direction();                               \
808                                                                                \
809   vmax.s16 left_right_x_16, left_right_x_16, left_edge;                        \
810                                                                                \
811   vst1.u32 { uvrg }, [ span_uvrg_offset, :128 ]!;                              \
812   str b, [ span_b_offset ], #4;                                                \
813   setup_spans_adjust_interpolants_##direction();                               \
814                                                                                \
815   vmin.s16 left_right_x_16, left_right_x_16, right_edge;                       \
816                                                                                \
817   vst1.u32 { uvrg }, [ span_uvrg_offset, :128 ]!;                              \
818   str b, [ span_b_offset ], #4;                                                \
819   setup_spans_adjust_interpolants_##direction();                               \
820                                                                                \
821   vsub.u16 left_right_x_16_high, left_right_x_16_high, left_right_x_16_low;    \
822   vadd.u16 left_right_x_16_high, left_right_x_16_high, c_0x0007;               \
823   vand.u16 span_shifts, left_right_x_16_high, c_0x0007;                        \
824                                                                                \
825   vst1.u32 { uvrg }, [ span_uvrg_offset, :128 ]!;                              \
826   str b, [ span_b_offset ], #4;                                                \
827   setup_spans_adjust_interpolants_##direction();                               \
828                                                                                \
829   vshr.u16 left_right_x_16_high, left_right_x_16_high, #3;                     \
830   vshl.u16 span_shifts, c_0xFFFE, span_shifts;                                 \
831                                                                                \
832   vst4.u16 { left_right_x_16, span_shifts_y }, [ span_edge_data ]!;            \
833                                                                                \
834   setup_spans_adjust_y_##direction()                                           \
835
836
837 #define setup_spans_set_x4_alternate_no(alternate, direction)                  \
838   vshrn.s64 left_x_32_low, left_x, #32;                                        \
839   vshrn.s64 right_x_32_low, right_x, #32;                                      \
840                                                                                \
841   vadd.u64 left_x, left_x, left_dx_dy;                                         \
842   vadd.u64 right_x, right_x, right_dx_dy;                                      \
843                                                                                \
844   vshrn.s64 left_x_32_high, left_x, #32;                                       \
845   vshrn.s64 right_x_32_high, right_x, #32;                                     \
846                                                                                \
847   vadd.u64 left_x, left_x, left_dx_dy;                                         \
848   vadd.u64 right_x, right_x, right_dx_dy;                                      \
849                                                                                \
850   vmovn.u32 left_right_x_16_low, left_x_32;                                    \
851   vmovn.u32 left_right_x_16_high, right_x_32;                                  \
852                                                                                \
853   vst1.u32 { uvrg }, [ span_uvrg_offset, :128 ]!;                              \
854   str b, [ span_b_offset ], #4;                                                \
855   setup_spans_adjust_interpolants_##direction();                               \
856                                                                                \
857   vmax.s16 left_right_x_16, left_right_x_16, left_edge;                        \
858                                                                                \
859   vst1.u32 { uvrg }, [ span_uvrg_offset, :128 ]!;                              \
860   str b, [ span_b_offset ], #4;                                                \
861   setup_spans_adjust_interpolants_##direction();                               \
862                                                                                \
863   vmin.s16 left_right_x_16, left_right_x_16, right_edge;                       \
864                                                                                \
865   vst1.u32 { uvrg }, [ span_uvrg_offset, :128 ]!;                              \
866   str b, [ span_b_offset ], #4;                                                \
867   setup_spans_adjust_interpolants_##direction();                               \
868                                                                                \
869   vsub.u16 left_right_x_16_high, left_right_x_16_high, left_right_x_16_low;    \
870   vadd.u16 left_right_x_16_high, left_right_x_16_high, c_0x0007;               \
871   vand.u16 span_shifts, left_right_x_16_high, c_0x0007;                        \
872                                                                                \
873   vst1.u32 { uvrg }, [ span_uvrg_offset, :128 ]!;                              \
874   str b, [ span_b_offset ], #4;                                                \
875   setup_spans_adjust_interpolants_##direction();                               \
876                                                                                \
877   vshl.u16 span_shifts, c_0xFFFE, span_shifts;                                 \
878   vshr.u16 left_right_x_16_high, left_right_x_16_high, #3;                     \
879                                                                                \
880   vst4.u16 { left_right_x_16, span_shifts_y }, [ span_edge_data ]!;            \
881                                                                                \
882   setup_spans_adjust_y_##direction()                                           \
883
884
885 #define edge_adjust_low           r11
886 #define edge_adjust_high          r12
887
888 #define setup_spans_alternate_adjust_yes()                                     \
889   smull edge_adjust_low, edge_adjust_high, edge_dx_dy_alt, height_minor_a;     \
890   subs edge_alt_low, edge_alt_low, edge_adjust_low;                            \
891   sbc edge_alt_high, edge_alt_high, edge_adjust_high                           \
892
893 #define setup_spans_alternate_adjust_no()                                      \
894
895
896 #define setup_spans_down(left_index, right_index, alternate, alternate_active) \
897   setup_spans_alternate_adjust_##alternate_active();                           \
898   setup_spans_load_b();                                                        \
899                                                                                \
900   ldrsh temp, [ psx_gpu, #psx_gpu_viewport_end_y_offset ];                     \
901   subs y_c, y_c, temp;                                                         \
902   subgt height, height, y_c;                                                   \
903   addgt height, height, #1;                                                    \
904                                                                                \
905   ldrsh temp, [ psx_gpu, #psx_gpu_viewport_start_y_offset ];                   \
906   subs clip, temp, y_a;                                                        \
907   ble 0f;                                                                      \
908                                                                                \
909   sub height, height, clip;                                                    \
910   add y_a, y_a, clip;                                                          \
911   setup_spans_clip(increment, alternate_active);                               \
912                                                                                \
913  0:                                                                            \
914   cmp height, #0;                                                              \
915   ble 1f;                                                                      \
916                                                                                \
917   orr temp, y_a, y_a, lsl #16;                                                 \
918   add temp, temp, #(1 << 16);                                                  \
919   add y_a, temp, #2;                                                           \
920   add y_a, y_a, #(2 << 16);                                                    \
921   vmov.u32 y_x4, temp, y_a;                                                    \
922                                                                                \
923   setup_spans_adjust_edges_alternate_##alternate_active(left_index,            \
924    right_index);                                                               \
925   setup_spans_prologue_b();                                                    \
926                                                                                \
927   strh height, [ psx_gpu, #psx_gpu_num_spans_offset ];                         \
928                                                                                \
929  2:                                                                            \
930   setup_spans_set_x4_alternate_##alternate_active(alternate, down);            \
931   subs height, height, #4;                                                     \
932   bhi 2b;                                                                      \
933                                                                                \
934  1:                                                                            \
935
936
937 #define setup_spans_alternate_pre_increment_yes()                              \
938   adds edge_alt_low, edge_alt_low, edge_dx_dy_alt;                             \
939   adc edge_alt_high, edge_alt_high, edge_dx_dy_alt, asr #31                    \
940
941 #define setup_spans_alternate_pre_increment_no()                               \
942
943
944 #define setup_spans_up_decrement_yes()                                         \
945   suble height, height, #1                                                     \
946
947 #define setup_spans_up_decrement_no()                                          \
948
949
950 #define setup_spans_up(left_index, right_index, alternate, alternate_active)   \
951   setup_spans_alternate_adjust_##alternate_active();                           \
952   setup_spans_load_b();                                                        \
953   sub y_a, y_a, #1;                                                            \
954                                                                                \
955   ldrh temp, [ psx_gpu, #psx_gpu_viewport_start_y_offset ];                    \
956   subs temp, temp, y_c;                                                        \
957   subgt height, height, temp;                                                  \
958   setup_spans_up_decrement_##alternate_active();                               \
959                                                                                \
960   ldrh temp, [ psx_gpu, #psx_gpu_viewport_end_y_offset ];                      \
961   subs clip, y_a, temp;                                                        \
962   ble 0f;                                                                      \
963                                                                                \
964   sub height, height, clip;                                                    \
965   sub y_a, y_a, clip;                                                          \
966   setup_spans_clip(decrement, alternate_active);                               \
967                                                                                \
968  0:                                                                            \
969   cmp height, #0;                                                              \
970   ble 1f;                                                                      \
971                                                                                \
972   orr temp, y_a, y_a, lsl #16;                                                 \
973   sub temp, temp, #(1 << 16);                                                  \
974   sub y_a, temp, #2;                                                           \
975   sub y_a, y_a, #(2 << 16);                                                    \
976   vmov.u32 y_x4, temp, y_a;                                                    \
977                                                                                \
978   vaddw.s32 edges_xy, edges_xy, edges_dx_dy;                                   \
979                                                                                \
980   setup_spans_alternate_pre_increment_##alternate_active();                    \
981   setup_spans_adjust_edges_alternate_##alternate_active(left_index,            \
982    right_index);                                                               \
983   setup_spans_adjust_interpolants_up();                                        \
984   setup_spans_prologue_b();                                                    \
985                                                                                \
986   strh height, [ psx_gpu, #psx_gpu_num_spans_offset ];                         \
987                                                                                \
988  2:                                                                            \
989   setup_spans_set_x4_alternate_##alternate_active(alternate, up);              \
990   subs height, height, #4;                                                     \
991   bhi 2b;                                                                      \
992                                                                                \
993  1:                                                                            \
994
995
996 #define setup_spans_epilogue()                                                 \
997   ldmia sp!, { r4 - r11, pc }                                                  \
998
999
1000 #define setup_spans_up_up(minor, major)                                        \
1001   setup_spans_prologue();                                                      \
1002   sub height_minor_a, y_a, y_b;                                                \
1003   sub height_minor_b, y_b, y_c;                                                \
1004   sub height, y_a, y_c;                                                        \
1005                                                                                \
1006   vdup.u32 x_starts, x_a;                                                      \
1007   vmov.u32 x_ends, x_c, x_b;                                                   \
1008                                                                                \
1009   compute_edge_delta_x3(x_b, height_major, height_minor_a);                    \
1010   setup_spans_up(major, minor, minor, yes);                                    \
1011   setup_spans_epilogue()                                                       \
1012
1013 function(setup_spans_up_left)
1014   setup_spans_up_up(left, right)
1015
1016 function(setup_spans_up_right)
1017   setup_spans_up_up(right, left)
1018
1019
1020 #define setup_spans_down_down(minor, major)                                    \
1021   setup_spans_prologue();                                                      \
1022   sub height_minor_a, y_b, y_a;                                                \
1023   sub height_minor_b, y_c, y_b;                                                \
1024   sub height, y_c, y_a;                                                        \
1025                                                                                \
1026   vdup.u32 x_starts, x_a;                                                      \
1027   vmov.u32 x_ends, x_c, x_b;                                                   \
1028                                                                                \
1029   compute_edge_delta_x3(x_b, height_major, height_minor_a);                    \
1030   setup_spans_down(major, minor, minor, yes);                                  \
1031   setup_spans_epilogue()                                                       \
1032
1033 function(setup_spans_down_left)
1034   setup_spans_down_down(left, right)
1035
1036 function(setup_spans_down_right)
1037   setup_spans_down_down(right, left)
1038
1039
1040 #define setup_spans_up_flat()                                                  \
1041   sub height, y_a, y_c;                                                        \
1042                                                                                \
1043   compute_edge_delta_x2();                                                     \
1044   setup_spans_up(left, right, none, no);                                       \
1045   setup_spans_epilogue()                                                       \
1046
1047 function(setup_spans_up_a)
1048   setup_spans_prologue()
1049
1050   vmov.u32 x_starts, x_a, x_b
1051   vdup.u32 x_ends, x_c
1052
1053   setup_spans_up_flat()
1054
1055 function(setup_spans_up_b)
1056   setup_spans_prologue()
1057
1058   vdup.u32 x_starts, x_a
1059   vmov.u32 x_ends, x_b, x_c
1060
1061   setup_spans_up_flat()
1062
1063 #define setup_spans_down_flat()                                                \
1064   sub height, y_c, y_a;                                                        \
1065                                                                                \
1066   compute_edge_delta_x2();                                                     \
1067   setup_spans_down(left, right, none, no);                                     \
1068   setup_spans_epilogue()                                                       \
1069
1070 function(setup_spans_down_a)
1071   setup_spans_prologue()
1072
1073   vmov.u32 x_starts, x_a, x_b
1074   vdup.u32 x_ends, x_c
1075
1076   setup_spans_down_flat()
1077
1078 function(setup_spans_down_b)
1079   setup_spans_prologue()
1080
1081   vdup.u32 x_starts, x_a
1082   vmov.u32 x_ends, x_b, x_c
1083
1084   setup_spans_down_flat()
1085
1086
1087 #define middle_y                                          r9
1088
1089 #define edges_xy_b                                        q11
1090 #define edges_dx_dy_b                                     d26
1091 #define edge_shifts_b                                     d27
1092 #define edges_dx_dy_and_shifts_b                          q13
1093 #define height_increment                                  d20
1094
1095 #define edges_dx_dy_and_shifts                            q1
1096
1097 #define edges_xy_b_left                                   d22
1098 #define edges_xy_b_right                                  d23
1099
1100 #define setup_spans_up_down_load_edge_set_b()                                  \
1101   vmov edges_xy, edges_xy_b;                                                   \
1102   vmov edges_dx_dy_and_shifts, edges_dx_dy_and_shifts_b                        \
1103
1104
1105 function(setup_spans_up_down)
1106   setup_spans_prologue()
1107
1108   // s32 middle_y = y_a;
1109   sub height_minor_a, y_a, y_b
1110   sub height_minor_b, y_c, y_a
1111   sub height_major, y_c, y_b
1112
1113   vmov.u32 x_starts, x_a, x_c
1114   vdup.u32 x_ends, x_b
1115
1116   compute_edge_delta_x3(x_a, height_minor_a, height_major)
1117
1118   mov temp, #0
1119   vmov.u32 height_increment, temp, height_minor_b
1120   vmlal.s32 edges_xy, edges_dx_dy, height_increment
1121
1122   vmov edges_xy_b_left, edge_alt_low, edge_alt_high
1123   vmov edges_xy_b_right, edges_xy_right
1124
1125   vmov edge_shifts_b, edge_shifts
1126   vmov.u32 edge_shifts_b[0], edge_shift_alt
1127
1128   vneg.s32 edges_dx_dy_b, edges_dx_dy
1129   vmov.u32 edges_dx_dy_b[0], edge_dx_dy_alt
1130
1131   mov middle_y, y_a
1132   
1133   setup_spans_load_b()
1134   sub y_a, y_a, #1
1135
1136   ldrh temp, [ psx_gpu, #psx_gpu_viewport_start_y_offset ]
1137   subs temp, temp, y_b
1138   subgt height_minor_a, height_minor_a, temp
1139
1140   ldrh temp, [ psx_gpu, #psx_gpu_viewport_end_y_offset ]
1141   subs clip, y_a, temp
1142   ble 0f
1143
1144   sub height_minor_a, height_minor_a, clip
1145   sub y_a, y_a, clip
1146   setup_spans_clip(decrement, no)
1147
1148  0:                                                                
1149   cmp height_minor_a, #0
1150   ble 3f
1151
1152   orr temp, y_a, y_a, lsl #16
1153   sub temp, temp, #(1 << 16)
1154   sub y_a, temp, #2
1155   sub y_a, y_a, #(2 << 16)
1156   vmov.u32 y_x4, temp, y_a
1157
1158   vaddw.s32 edges_xy, edges_xy, edges_dx_dy
1159
1160   strh height_minor_a, [ psx_gpu, #psx_gpu_num_spans_offset ]
1161
1162   setup_spans_adjust_edges_alternate_no(left, right); 
1163   setup_spans_adjust_interpolants_up()
1164   setup_spans_up_down_load_edge_set_b()
1165
1166   setup_spans_prologue_b()
1167
1168
1169  2: 
1170   setup_spans_set_x4_alternate_no(none, up)
1171   subs height_minor_a, height_minor_a, #4
1172   bhi 2b
1173
1174   add span_edge_data, span_edge_data, height_minor_a, lsl #3
1175   add span_uvrg_offset, span_uvrg_offset, height_minor_a, lsl #4
1176   add span_b_offset, span_b_offset, height_minor_a, lsl #2
1177
1178  4:
1179   add temp, psx_gpu, #psx_gpu_uvrg_offset
1180   vld1.32 { uvrg }, [ temp ]
1181   mov y_a, middle_y
1182   
1183   setup_spans_load_b()
1184
1185   ldrh temp, [ psx_gpu, #psx_gpu_viewport_end_y_offset ]
1186   subs y_c, y_c, temp
1187   subgt height_minor_b, height_minor_b, y_c
1188   addgt height_minor_b, height_minor_b, #1
1189
1190   ldrh temp, [ psx_gpu, #psx_gpu_viewport_start_y_offset ]
1191   subs clip, temp, y_a
1192   ble 0f
1193
1194   sub height_minor_b, height_minor_b, clip
1195   add y_a, y_a, clip
1196   setup_spans_clip(increment, no)
1197
1198  0:
1199   cmp height_minor_b, #0
1200   ble 1f
1201
1202   orr temp, y_a, y_a, lsl #16
1203   add temp, temp, #(1 << 16) 
1204   add y_a, temp, #2
1205   add y_a, y_a, #(2 << 16)
1206   vmov.u32 y_x4, temp, y_a
1207
1208   setup_spans_adjust_edges_alternate_no(left, right)
1209
1210   ldrh temp, [ psx_gpu, #psx_gpu_num_spans_offset ]
1211   add temp, temp, height_minor_b
1212   strh temp, [ psx_gpu, #psx_gpu_num_spans_offset ]
1213
1214  2:                                                     
1215   setup_spans_set_x4_alternate_no(none, down)
1216   subs height_minor_b, height_minor_b, #4
1217   bhi 2b
1218
1219  1:
1220   setup_spans_epilogue()
1221
1222  3:
1223   setup_spans_up_down_load_edge_set_b()
1224   setup_spans_prologue_b()
1225   bal 4b
1226
1227
1228 #undef span_uvrg_offset
1229 #undef span_edge_data
1230 #undef span_b_offset
1231 #undef left_x
1232 #undef b
1233
1234 #define psx_gpu                                  r0
1235 #define num_spans                                r1
1236 #define span_uvrg_offset                         r2
1237 #define span_edge_data                           r3
1238 #define span_b_offset                            r4
1239 #define b_dx                                     r5
1240 #define span_num_blocks                          r6
1241 #define y                                        r7
1242 #define left_x                                   r8
1243 #define b                                        r9
1244 #define dither_offset_ptr                        r10
1245 #define block_ptr_a                              r11
1246 #define fb_ptr                                   r12
1247 #define num_blocks                               r14
1248
1249 #define uvrg_dx_ptr                              r2
1250 #define texture_mask_ptr                         r3
1251 #define dither_shift                             r8
1252 #define dither_row                               r10
1253
1254 #define c_32                                     r7
1255 #define b_dx4                                    r8
1256 #define b_dx8                                    r9
1257 #define block_ptr_b                              r10
1258
1259 #define block_span_ptr                           r10
1260 #define right_mask                               r8
1261
1262 #define color                                    r2
1263 #define color_r                                  r3
1264 #define color_g                                  r4
1265 #define color_b                                  r5
1266
1267 #undef uvrg
1268
1269 #define u_block                                  q0
1270 #define v_block                                  q1
1271 #define r_block                                  q2
1272 #define g_block                                  q3
1273 #define b_block                                  q4
1274
1275 #define uv_dx4                                   d10
1276 #define rg_dx4                                   d11
1277 #define uv_dx8                                   d12
1278 #define rg_dx8                                   d13
1279 #define b_whole_8                                d14
1280 #define fb_mask_ptrs                             d15
1281
1282 #define uvrg_dx4                                 q5
1283 #define uvrg_dx8                                 q6
1284 #define uv_dx8                                   d12
1285 #define rg_dx8                                   d13
1286
1287 #define u_whole                                  q8
1288 #define v_whole                                  q9
1289 #define r_whole                                  q10
1290 #define g_whole                                  q11
1291 #define b_whole                                  q12
1292
1293 #define u_whole_low                              d16
1294 #define u_whole_high                             d17
1295 #define v_whole_low                              d18
1296 #define v_whole_high                             d19
1297 #define r_whole_low                              d20
1298 #define r_whole_high                             d21
1299 #define g_whole_low                              d22
1300 #define g_whole_high                             d23
1301 #define b_whole_low                              d24
1302 #define b_whole_high                             d25
1303
1304 #define dx4                                      q13
1305 #define dx8                                      q13
1306
1307 #define u_whole_8                                d26
1308 #define v_whole_8                                d27
1309 #define u_whole_8b                               d24
1310 #define r_whole_8                                d24
1311 #define g_whole_8                                d25
1312
1313 #define uv_whole_8                               q13
1314 #define uv_whole_8b                              q14
1315
1316 #define dither_offsets                           q14
1317 #define texture_mask                             q15
1318 #define texture_mask_u                           d30
1319 #define texture_mask_v                           d31
1320
1321 #define dither_offsets_short                     d28
1322
1323 #define v_left_x                                 q8
1324 #define uvrg                                     q9
1325 #define block_span                               q10
1326
1327 #define uv                                       d18
1328 #define rg                                       d19
1329
1330 #define draw_mask                                q1
1331 #define draw_mask_edge                           q13
1332 #define test_mask                                q0
1333
1334 #define uvrg_dx                                  q3
1335
1336 #define colors                                   q2
1337
1338 #define setup_blocks_texture_swizzled()                                        \
1339   vand.u8 u_whole_8b, u_whole_8, texture_mask_u;                               \
1340   vsli.u8 u_whole_8, v_whole_8, #4;                                            \
1341   vsri.u8 v_whole_8, u_whole_8b, #4                                            \
1342
1343 #define setup_blocks_texture_unswizzled()                                      \
1344
1345
1346 #define setup_blocks_shaded_textured_builder(swizzling)                        \
1347 .align 3;                                                                      \
1348                                                                                \
1349 function(setup_blocks_shaded_textured_dithered_##swizzling##_indirect)         \
1350   ldrh num_spans, [ psx_gpu, #psx_gpu_num_spans_offset ];                      \
1351   add uvrg_dx_ptr, psx_gpu, #psx_gpu_uvrg_dx_offset;                           \
1352                                                                                \
1353   vld1.u32 { uvrg_dx }, [ uvrg_dx_ptr, :128 ];                                 \
1354   add texture_mask_ptr, psx_gpu, #psx_gpu_texture_mask_width_offset;           \
1355                                                                                \
1356   cmp num_spans, #0;                                                           \
1357   bxeq lr;                                                                     \
1358                                                                                \
1359   stmdb sp!, { r4 - r11, r14 };                                                \
1360   vshl.u32 uvrg_dx4, uvrg_dx, #2;                                              \
1361                                                                                \
1362   ldr b_dx, [ psx_gpu, #psx_gpu_b_dx_offset ];                                 \
1363   vshl.u32 uvrg_dx8, uvrg_dx, #3;                                              \
1364                                                                                \
1365   vld2.u8 { texture_mask_u[], texture_mask_v[] }, [ texture_mask_ptr, :16 ];   \
1366   add span_uvrg_offset, psx_gpu, #psx_gpu_span_uvrg_offset_offset;             \
1367                                                                                \
1368   ldrh num_blocks, [ psx_gpu, #psx_gpu_num_blocks_offset ];                    \
1369   add span_edge_data, psx_gpu, #psx_gpu_span_edge_data_offset;                 \
1370                                                                                \
1371   add span_b_offset, psx_gpu, #psx_gpu_span_b_offset_offset;                   \
1372   add block_ptr_a, psx_gpu, #psx_gpu_blocks_offset;                            \
1373                                                                                \
1374   add block_ptr_a, block_ptr_a, num_blocks, lsl #6;                            \
1375                                                                                \
1376  0:                                                                            \
1377   vmov.u8 fb_mask_ptrs, #0;                                                    \
1378                                                                                \
1379   ldrh span_num_blocks, [ span_edge_data, #edge_data_num_blocks_offset ];      \
1380   add dither_offset_ptr, psx_gpu, #psx_gpu_dither_table_offset;                \
1381                                                                                \
1382   ldrh y, [ span_edge_data, #edge_data_y_offset ];                             \
1383   ldr fb_ptr, [ psx_gpu, #psx_gpu_vram_ptr_offset ];                           \
1384                                                                                \
1385   cmp span_num_blocks, #0;                                                     \
1386   beq 1f;                                                                      \
1387                                                                                \
1388   ldrh left_x, [ span_edge_data, #edge_data_left_x_offset ];                   \
1389   add num_blocks, span_num_blocks, num_blocks;                                 \
1390                                                                                \
1391   cmp num_blocks, #MAX_BLOCKS;                                                 \
1392   bgt 2f;                                                                      \
1393                                                                                \
1394  3:                                                                            \
1395   ldr b, [ span_b_offset ];                                                    \
1396   add fb_ptr, fb_ptr, y, lsl #11;                                              \
1397                                                                                \
1398   vdup.u32 v_left_x, left_x;                                                   \
1399   and y, y, #0x3;                                                              \
1400                                                                                \
1401   ldr dither_row, [ dither_offset_ptr, y, lsl #2 ];                            \
1402   add fb_ptr, fb_ptr, left_x, lsl #1;                                          \
1403                                                                                \
1404   mla b, b_dx, left_x, b;                                                      \
1405   and dither_shift, left_x, #0x03;                                             \
1406                                                                                \
1407   vld1.u32 { uvrg }, [ span_uvrg_offset, :128 ];                               \
1408   vshr.u32 uvrg_dx, uvrg_dx4, #2;                                              \
1409                                                                                \
1410   mov dither_shift, dither_shift, lsl #3;                                      \
1411   vmla.u32 uvrg, uvrg_dx, v_left_x;                                            \
1412                                                                                \
1413   mov c_32, #32;                                                               \
1414   subs span_num_blocks, span_num_blocks, #1;                                   \
1415                                                                                \
1416   mov dither_row, dither_row, ror dither_shift;                                \
1417   mov b_dx4, b_dx, lsl #2;                                                     \
1418                                                                                \
1419   vdup.u32 dither_offsets_short, dither_row;                                   \
1420   add block_span_ptr, psx_gpu, #psx_gpu_u_block_span_offset;                   \
1421                                                                                \
1422   vdup.u32 b_block, b;                                                         \
1423   vshll.s8 dither_offsets, dither_offsets_short, #4;                           \
1424                                                                                \
1425   vdup.u32 u_block, uv[0];                                                     \
1426   mov b_dx8, b_dx, lsl #3;                                                     \
1427                                                                                \
1428   vdup.u32 v_block, uv[1];                                                     \
1429   vdup.u32 r_block, rg[0];                                                     \
1430   vdup.u32 g_block, rg[1];                                                     \
1431                                                                                \
1432   vld1.u32 { block_span }, [ block_span_ptr, :128 ]!;                          \
1433                                                                                \
1434   vadd.u32 u_block, u_block, block_span;                                       \
1435   vld1.u32 { block_span }, [ block_span_ptr, :128 ]!;                          \
1436                                                                                \
1437   vadd.u32 v_block, v_block, block_span;                                       \
1438   vld1.u32 { block_span }, [ block_span_ptr, :128 ]!;                          \
1439                                                                                \
1440   vadd.u32 r_block, r_block, block_span;                                       \
1441   vld1.u32 { block_span }, [ block_span_ptr, :128 ]!;                          \
1442                                                                                \
1443   vadd.u32 g_block, g_block, block_span;                                       \
1444   vld1.u32 { block_span }, [ block_span_ptr, :128 ];                           \
1445                                                                                \
1446   vadd.u32 b_block, b_block, block_span;                                       \
1447   add block_ptr_b, block_ptr_a, #16;                                           \
1448                                                                                \
1449   vshrn.u32 u_whole_low, u_block, #16;                                         \
1450   vshrn.u32 v_whole_low, v_block, #16;                                         \
1451   vshrn.u32 r_whole_low, r_block, #16;                                         \
1452   vshrn.u32 g_whole_low, g_block, #16;                                         \
1453                                                                                \
1454   vdup.u32 dx4, uv_dx4[0];                                                     \
1455   vshrn.u32 b_whole_low, b_block, #16;                                         \
1456                                                                                \
1457   vaddhn.u32 u_whole_high, u_block, dx4;                                       \
1458   vdup.u32 dx4, uv_dx4[1];                                                     \
1459                                                                                \
1460   vaddhn.u32 v_whole_high, v_block, dx4;                                       \
1461   vdup.u32 dx4, rg_dx4[0];                                                     \
1462                                                                                \
1463   vaddhn.u32 r_whole_high, r_block, dx4;                                       \
1464   vdup.u32 dx4, rg_dx4[1];                                                     \
1465                                                                                \
1466   vaddhn.u32 g_whole_high, g_block, dx4;                                       \
1467   vdup.u32 dx4, b_dx4;                                                         \
1468                                                                                \
1469   vaddhn.u32 b_whole_high, b_block, dx4;                                       \
1470   vdup.u32 dx8, uv_dx8[0];                                                     \
1471                                                                                \
1472   vadd.u32 u_block, u_block, dx8;                                              \
1473   vdup.u32 dx8, uv_dx8[1];                                                     \
1474                                                                                \
1475   vadd.u32 v_block, v_block, dx8;                                              \
1476   vdup.u32 dx8, rg_dx8[0];                                                     \
1477                                                                                \
1478   vadd.u32 r_block, r_block, dx8;                                              \
1479   vdup.u32 dx8, rg_dx8[1];                                                     \
1480                                                                                \
1481   vadd.u32 g_block, g_block, dx8;                                              \
1482   vdup.u32 dx8, b_dx8;                                                         \
1483                                                                                \
1484   vadd.u32 b_block, b_block, dx8;                                              \
1485   vmovn.u16 u_whole_8, u_whole;                                                \
1486                                                                                \
1487   vmovn.u16 v_whole_8, v_whole;                                                \
1488                                                                                \
1489   vmovn.u16 b_whole_8, b_whole;                                                \
1490   pld [ fb_ptr ];                                                              \
1491   vmov.u32 fb_mask_ptrs[1], fb_ptr;                                            \
1492                                                                                \
1493   vand.u8 uv_whole_8, uv_whole_8, texture_mask;                                \
1494   setup_blocks_texture_##swizzling();                                          \
1495                                                                                \
1496   vmovn.u16 r_whole_8, r_whole;                                                \
1497   beq 5f;                                                                      \
1498                                                                                \
1499  4:                                                                            \
1500   vmovn.u16 g_whole_8, g_whole;                                                \
1501   vshrn.u32 u_whole_low, u_block, #16;                                         \
1502                                                                                \
1503   vst2.u8 { u_whole_8, v_whole_8 }, [ block_ptr_a, :128 ], c_32;               \
1504   vshrn.u32 v_whole_low, v_block, #16;                                         \
1505                                                                                \
1506   vst1.u32 { r_whole_8, g_whole_8 }, [ block_ptr_b, :128 ], c_32;              \
1507   vshrn.u32 r_whole_low, r_block, #16;                                         \
1508                                                                                \
1509   vst1.u32 { b_whole_8, fb_mask_ptrs }, [ block_ptr_a, :128 ], c_32;           \
1510   vshrn.u32 g_whole_low, g_block, #16;                                         \
1511                                                                                \
1512   vdup.u32 dx4, uv_dx4[0];                                                     \
1513   vshrn.u32 b_whole_low, b_block, #16;                                         \
1514                                                                                \
1515   vaddhn.u32 u_whole_high, u_block, dx4;                                       \
1516   vdup.u32 dx4, uv_dx4[1];                                                     \
1517                                                                                \
1518   vaddhn.u32 v_whole_high, v_block, dx4;                                       \
1519   vdup.u32 dx4, rg_dx4[0];                                                     \
1520                                                                                \
1521   vaddhn.u32 r_whole_high, r_block, dx4;                                       \
1522   vdup.u32 dx4, rg_dx4[1];                                                     \
1523                                                                                \
1524   vaddhn.u32 g_whole_high, g_block, dx4;                                       \
1525   vdup.u32 dx4, b_dx4;                                                         \
1526                                                                                \
1527   vaddhn.u32 b_whole_high, b_block, dx4;                                       \
1528   vdup.u32 dx8, uv_dx8[0];                                                     \
1529                                                                                \
1530   vadd.u32 u_block, u_block, dx8;                                              \
1531   vdup.u32 dx8, uv_dx8[1];                                                     \
1532                                                                                \
1533   vadd.u32 v_block, v_block, dx8;                                              \
1534   vdup.u32 dx8, rg_dx8[0];                                                     \
1535                                                                                \
1536   vadd.u32 r_block, r_block, dx8;                                              \
1537   vdup.u32 dx8, rg_dx8[1];                                                     \
1538                                                                                \
1539   vadd.u32 g_block, g_block, dx8;                                              \
1540   vdup.u32 dx8, b_dx8;                                                         \
1541                                                                                \
1542   vadd.u32 b_block, b_block, dx8;                                              \
1543   vmovn.u16 u_whole_8, u_whole;                                                \
1544                                                                                \
1545   add fb_ptr, fb_ptr, #16;                                                     \
1546   vmovn.u16 v_whole_8, v_whole;                                                \
1547                                                                                \
1548   vst1.u32 { dither_offsets }, [ block_ptr_b, :128 ], c_32;                    \
1549   vmovn.u16 b_whole_8, b_whole;                                                \
1550                                                                                \
1551   pld [ fb_ptr ];                                                              \
1552                                                                                \
1553   vmov.u32 fb_mask_ptrs[1], fb_ptr;                                            \
1554   subs span_num_blocks, span_num_blocks, #1;                                   \
1555                                                                                \
1556   vand.u8 uv_whole_8, uv_whole_8, texture_mask;                                \
1557   setup_blocks_texture_##swizzling();                                          \
1558                                                                                \
1559   vmovn.u16 r_whole_8, r_whole;                                                \
1560   bne 4b;                                                                      \
1561                                                                                \
1562  5:                                                                            \
1563   vmovn.u16 g_whole_8, g_whole;                                                \
1564   ldrh right_mask, [ span_edge_data, #edge_data_right_mask_offset ];           \
1565                                                                                \
1566   vld1.u32 { test_mask }, [ psx_gpu, :128 ];                                   \
1567   vdup.u8 draw_mask, right_mask;                                               \
1568                                                                                \
1569   vmov.u32 fb_mask_ptrs[0], right_mask;                                        \
1570   vtst.u16 draw_mask, draw_mask, test_mask;                                    \
1571   vzip.u8 u_whole_8, v_whole_8;                                                \
1572                                                                                \
1573   vbic.u16 uv_whole_8, uv_whole_8, draw_mask;                                  \
1574   vst1.u32 { r_whole_8, g_whole_8 }, [ block_ptr_b, :128 ], c_32;              \
1575   vst1.u32 { uv_whole_8 }, [ block_ptr_a, :128 ], c_32;                        \
1576   vst1.u32 { dither_offsets }, [ block_ptr_b, :128 ], c_32;                    \
1577   vst1.u32 { b_whole_8, fb_mask_ptrs }, [ block_ptr_a, :128 ], c_32;           \
1578                                                                                \
1579  1:                                                                            \
1580   add span_uvrg_offset, span_uvrg_offset, #16;                                 \
1581   add span_b_offset, span_b_offset, #4;                                        \
1582                                                                                \
1583   add span_edge_data, span_edge_data, #8;                                      \
1584   subs num_spans, num_spans, #1;                                               \
1585                                                                                \
1586   strh num_blocks, [ psx_gpu, #psx_gpu_num_blocks_offset ];                    \
1587   bne 0b;                                                                      \
1588                                                                                \
1589   ldmia sp!, { r4 - r11, pc };                                                 \
1590                                                                                \
1591  2:                                                                            \
1592   /* TODO: Load from psx_gpu instead of saving/restoring these               */\
1593   vpush { texture_mask };                                                      \
1594   vpush { uvrg_dx4 };                                                          \
1595                                                                                \
1596   stmdb sp!, { r0 - r3, r12, r14 };                                            \
1597   bl flush_render_block_buffer;                                                \
1598   ldmia sp!, { r0 - r3, r12, r14 };                                            \
1599                                                                                \
1600   vpop { uvrg_dx4 };                                                           \
1601   vpop { texture_mask };                                                       \
1602                                                                                \
1603   vadd.u32 uvrg_dx8, uvrg_dx4, uvrg_dx4;                                       \
1604   vmov.u8 fb_mask_ptrs, #0;                                                    \
1605                                                                                \
1606   mov num_blocks, span_num_blocks;                                             \
1607   add block_ptr_a, psx_gpu, #psx_gpu_blocks_offset;                            \
1608   bal 3b                                                                       \
1609
1610
1611 setup_blocks_shaded_textured_builder(swizzled)
1612 setup_blocks_shaded_textured_builder(unswizzled)
1613
1614
1615 #define setup_blocks_unshaded_textured_builder(swizzling)                      \
1616 .align 3;                                                                      \
1617                                                                                \
1618 function(setup_blocks_unshaded_textured_dithered_##swizzling##_indirect)       \
1619   ldrh num_spans, [ psx_gpu, #psx_gpu_num_spans_offset ];                      \
1620   add uvrg_dx_ptr, psx_gpu, #psx_gpu_uvrg_dx_offset;                           \
1621                                                                                \
1622   vld1.u32 { uvrg_dx }, [ uvrg_dx_ptr, :128 ];                                 \
1623   add texture_mask_ptr, psx_gpu, #psx_gpu_texture_mask_width_offset;           \
1624                                                                                \
1625   cmp num_spans, #0;                                                           \
1626   bxeq lr;                                                                     \
1627                                                                                \
1628   stmdb sp!, { r4 - r11, r14 };                                                \
1629   vshl.u32 uvrg_dx4, uvrg_dx, #2;                                              \
1630                                                                                \
1631   vshl.u32 uvrg_dx8, uvrg_dx, #3;                                              \
1632                                                                                \
1633   vld2.u8 { texture_mask_u[], texture_mask_v[] }, [ texture_mask_ptr, :16 ];   \
1634   add span_uvrg_offset, psx_gpu, #psx_gpu_span_uvrg_offset_offset;             \
1635                                                                                \
1636   ldrh num_blocks, [ psx_gpu, #psx_gpu_num_blocks_offset ];                    \
1637   add span_edge_data, psx_gpu, #psx_gpu_span_edge_data_offset;                 \
1638                                                                                \
1639   add block_ptr_a, psx_gpu, #psx_gpu_blocks_offset;                            \
1640                                                                                \
1641   add block_ptr_a, block_ptr_a, num_blocks, lsl #6;                            \
1642                                                                                \
1643  0:                                                                            \
1644   vmov.u8 fb_mask_ptrs, #0;                                                    \
1645                                                                                \
1646   ldrh span_num_blocks, [ span_edge_data, #edge_data_num_blocks_offset ];      \
1647   add dither_offset_ptr, psx_gpu, #psx_gpu_dither_table_offset;                \
1648                                                                                \
1649   ldrh y, [ span_edge_data, #edge_data_y_offset ];                             \
1650   ldr fb_ptr, [ psx_gpu, #psx_gpu_vram_ptr_offset ];                           \
1651                                                                                \
1652   cmp span_num_blocks, #0;                                                     \
1653   beq 1f;                                                                      \
1654                                                                                \
1655   ldrh left_x, [ span_edge_data, #edge_data_left_x_offset ];                   \
1656   add num_blocks, span_num_blocks, num_blocks;                                 \
1657                                                                                \
1658   cmp num_blocks, #MAX_BLOCKS;                                                 \
1659   bgt 2f;                                                                      \
1660                                                                                \
1661  3:                                                                            \
1662   add fb_ptr, fb_ptr, y, lsl #11;                                              \
1663                                                                                \
1664   vdup.u32 v_left_x, left_x;                                                   \
1665   and y, y, #0x3;                                                              \
1666                                                                                \
1667   ldr dither_row, [ dither_offset_ptr, y, lsl #2 ];                            \
1668   add fb_ptr, fb_ptr, left_x, lsl #1;                                          \
1669                                                                                \
1670   and dither_shift, left_x, #0x03;                                             \
1671                                                                                \
1672   vld1.u32 { uvrg }, [ span_uvrg_offset, :128 ];                               \
1673   vshr.u32 uvrg_dx, uvrg_dx4, #2;                                              \
1674                                                                                \
1675   mov dither_shift, dither_shift, lsl #3;                                      \
1676   vmla.u32 uvrg, uvrg_dx, v_left_x;                                            \
1677                                                                                \
1678   mov c_32, #32;                                                               \
1679   subs span_num_blocks, span_num_blocks, #1;                                   \
1680                                                                                \
1681   mov dither_row, dither_row, ror dither_shift;                                \
1682                                                                                \
1683   vdup.u32 dither_offsets_short, dither_row;                                   \
1684   add block_span_ptr, psx_gpu, #psx_gpu_u_block_span_offset;                   \
1685                                                                                \
1686   vshll.s8 dither_offsets, dither_offsets_short, #4;                           \
1687                                                                                \
1688   vdup.u32 u_block, uv[0];                                                     \
1689                                                                                \
1690   vdup.u32 v_block, uv[1];                                                     \
1691   vld1.u32 { block_span }, [ block_span_ptr, :128 ]!;                          \
1692                                                                                \
1693   vadd.u32 u_block, u_block, block_span;                                       \
1694   vld1.u32 { block_span }, [ block_span_ptr, :128 ]!;                          \
1695                                                                                \
1696   vadd.u32 v_block, v_block, block_span;                                       \
1697   add block_ptr_b, block_ptr_a, #16;                                           \
1698                                                                                \
1699   vshrn.u32 u_whole_low, u_block, #16;                                         \
1700   vshrn.u32 v_whole_low, v_block, #16;                                         \
1701                                                                                \
1702   vdup.u32 dx4, uv_dx4[0];                                                     \
1703                                                                                \
1704   vaddhn.u32 u_whole_high, u_block, dx4;                                       \
1705   vdup.u32 dx4, uv_dx4[1];                                                     \
1706                                                                                \
1707   vaddhn.u32 v_whole_high, v_block, dx4;                                       \
1708   vdup.u32 dx8, uv_dx8[0];                                                     \
1709                                                                                \
1710   vadd.u32 u_block, u_block, dx8;                                              \
1711   vdup.u32 dx8, uv_dx8[1];                                                     \
1712                                                                                \
1713   vadd.u32 v_block, v_block, dx8;                                              \
1714   vmovn.u16 u_whole_8, u_whole;                                                \
1715                                                                                \
1716   vmovn.u16 v_whole_8, v_whole;                                                \
1717                                                                                \
1718   pld [ fb_ptr ];                                                              \
1719   vmov.u32 fb_mask_ptrs[1], fb_ptr;                                            \
1720                                                                                \
1721   vand.u8 uv_whole_8, uv_whole_8, texture_mask;                                \
1722   setup_blocks_texture_##swizzling();                                          \
1723                                                                                \
1724   beq 5f;                                                                      \
1725                                                                                \
1726  4:                                                                            \
1727   vshrn.u32 u_whole_low, u_block, #16;                                         \
1728                                                                                \
1729   vst2.u8 { u_whole_8, v_whole_8 }, [ block_ptr_a, :128 ], c_32;               \
1730   vshrn.u32 v_whole_low, v_block, #16;                                         \
1731                                                                                \
1732   add block_ptr_b, block_ptr_b, #32;                                           \
1733   vst1.u32 { b_whole_8, fb_mask_ptrs }, [ block_ptr_a, :128 ], c_32;           \
1734                                                                                \
1735   vdup.u32 dx4, uv_dx4[0];                                                     \
1736   vaddhn.u32 u_whole_high, u_block, dx4;                                       \
1737   vdup.u32 dx4, uv_dx4[1];                                                     \
1738                                                                                \
1739   vaddhn.u32 v_whole_high, v_block, dx4;                                       \
1740   vdup.u32 dx8, uv_dx8[0];                                                     \
1741                                                                                \
1742   vadd.u32 u_block, u_block, dx8;                                              \
1743   vdup.u32 dx8, uv_dx8[1];                                                     \
1744                                                                                \
1745   vadd.u32 v_block, v_block, dx8;                                              \
1746   vmovn.u16 u_whole_8, u_whole;                                                \
1747                                                                                \
1748   add fb_ptr, fb_ptr, #16;                                                     \
1749   vmovn.u16 v_whole_8, v_whole;                                                \
1750                                                                                \
1751   vst1.u32 { dither_offsets }, [ block_ptr_b, :128 ], c_32;                    \
1752   pld [ fb_ptr ];                                                              \
1753                                                                                \
1754   vmov.u32 fb_mask_ptrs[1], fb_ptr;                                            \
1755   subs span_num_blocks, span_num_blocks, #1;                                   \
1756                                                                                \
1757   vand.u8 uv_whole_8, uv_whole_8, texture_mask;                                \
1758   setup_blocks_texture_##swizzling();                                          \
1759                                                                                \
1760   bne 4b;                                                                      \
1761                                                                                \
1762  5:                                                                            \
1763   ldrh right_mask, [ span_edge_data, #edge_data_right_mask_offset ];           \
1764                                                                                \
1765   vld1.u32 { test_mask }, [ psx_gpu, :128 ];                                   \
1766   vdup.u8 draw_mask, right_mask;                                               \
1767                                                                                \
1768   vmov.u32 fb_mask_ptrs[0], right_mask;                                        \
1769   vtst.u16 draw_mask, draw_mask, test_mask;                                    \
1770   vzip.u8 u_whole_8, v_whole_8;                                                \
1771                                                                                \
1772   vbic.u16 uv_whole_8, uv_whole_8, draw_mask;                                  \
1773   add block_ptr_b, block_ptr_b, #32;                                           \
1774   vst1.u32 { uv_whole_8 }, [ block_ptr_a, :128 ], c_32;                        \
1775   vst1.u32 { dither_offsets }, [ block_ptr_b, :128 ], c_32;                    \
1776   vst1.u32 { b_whole_8, fb_mask_ptrs }, [ block_ptr_a, :128 ], c_32;           \
1777                                                                                \
1778  1:                                                                            \
1779   add span_uvrg_offset, span_uvrg_offset, #16;                                 \
1780   add span_edge_data, span_edge_data, #8;                                      \
1781   subs num_spans, num_spans, #1;                                               \
1782                                                                                \
1783   strh num_blocks, [ psx_gpu, #psx_gpu_num_blocks_offset ];                    \
1784   bne 0b;                                                                      \
1785                                                                                \
1786   ldmia sp!, { r4 - r11, pc };                                                 \
1787                                                                                \
1788  2:                                                                            \
1789   /* TODO: Load from psx_gpu instead of saving/restoring these               */\
1790   vpush { texture_mask };                                                      \
1791   vpush { uvrg_dx4 };                                                          \
1792                                                                                \
1793   stmdb sp!, { r0 - r3, r12, r14 };                                            \
1794   bl flush_render_block_buffer;                                                \
1795   ldmia sp!, { r0 - r3, r12, r14 };                                            \
1796                                                                                \
1797   vpop { uvrg_dx4 };                                                           \
1798   vpop { texture_mask };                                                       \
1799                                                                                \
1800   vadd.u32 uvrg_dx8, uvrg_dx4, uvrg_dx4;                                       \
1801   vmov.u8 fb_mask_ptrs, #0;                                                    \
1802                                                                                \
1803   mov num_blocks, span_num_blocks;                                             \
1804   add block_ptr_a, psx_gpu, #psx_gpu_blocks_offset;                            \
1805   bal 3b                                                                       \
1806
1807
1808 setup_blocks_unshaded_textured_builder(swizzled)
1809 setup_blocks_unshaded_textured_builder(unswizzled)
1810
1811
1812 .align 3
1813
1814 function(setup_blocks_unshaded_untextured_undithered_unswizzled_indirect)
1815   ldrh num_spans, [ psx_gpu, #psx_gpu_num_spans_offset ]
1816   veor.u32 draw_mask, draw_mask, draw_mask
1817
1818   cmp num_spans, #0
1819   bxeq lr
1820
1821   stmdb sp!, { r4 - r11, r14 }
1822   vld1.u32 { test_mask }, [ psx_gpu, :128 ]
1823
1824   ldr color, [ psx_gpu, #psx_gpu_triangle_color_offset ]
1825
1826   ubfx color_r, color, #3, #5
1827   ubfx color_g, color, #11, #5
1828   ubfx color_b, color, #19, #5
1829
1830   orr color, color_r, color_b, lsl #10
1831   orr color, color, color_g, lsl #5
1832
1833   vdup.u16 colors, color
1834
1835   ldrh num_blocks, [ psx_gpu, #psx_gpu_num_blocks_offset ]
1836   add span_edge_data, psx_gpu, #psx_gpu_span_edge_data_offset
1837
1838   add block_ptr_a, psx_gpu, #psx_gpu_blocks_offset
1839   add block_ptr_a, block_ptr_a, num_blocks, lsl #6
1840
1841  0:
1842   ldrh span_num_blocks, [ span_edge_data, #edge_data_num_blocks_offset ]
1843   ldrh y, [ span_edge_data, #edge_data_y_offset ]
1844
1845   ldr fb_ptr, [ psx_gpu, #psx_gpu_vram_ptr_offset ]
1846
1847   cmp span_num_blocks, #0
1848   beq 1f
1849
1850   ldrh left_x, [ span_edge_data, #edge_data_left_x_offset ]
1851   add num_blocks, span_num_blocks, num_blocks
1852
1853   cmp num_blocks, #MAX_BLOCKS
1854   bgt 2f
1855
1856  3:
1857   add fb_ptr, fb_ptr, y, lsl #11
1858   and y, y, #0x3
1859
1860   add fb_ptr, fb_ptr, left_x, lsl #1
1861   mov c_32, #32
1862
1863   subs span_num_blocks, span_num_blocks, #1
1864
1865   add block_ptr_b, block_ptr_a, #16
1866   pld [ fb_ptr ]
1867
1868   vmov.u32 fb_mask_ptrs[1], fb_ptr
1869   beq 5f
1870
1871  4:
1872   vst1.u32 { draw_mask }, [ block_ptr_a, :128 ], c_32
1873   vst1.u32 { colors }, [ block_ptr_b, :128 ], c_32
1874   vst1.u32 { b_whole_8, fb_mask_ptrs }, [ block_ptr_a, :128 ], c_32
1875
1876   add fb_ptr, fb_ptr, #16
1877   add block_ptr_b, block_ptr_b, #32
1878
1879   pld [ fb_ptr ]
1880
1881   vmov.u32 fb_mask_ptrs[1], fb_ptr
1882   subs span_num_blocks, span_num_blocks, #1
1883
1884   bne 4b
1885
1886  5:
1887   ldrh right_mask, [ span_edge_data, #edge_data_right_mask_offset ]
1888
1889   vdup.u8 draw_mask_edge, right_mask
1890   vtst.u16 draw_mask_edge, draw_mask_edge, test_mask
1891
1892   vst1.u32 { colors }, [ block_ptr_b, :128 ], c_32
1893   vst1.u32 { draw_mask_edge }, [ block_ptr_a, :128 ], c_32
1894   add block_ptr_b, block_ptr_b, #32
1895   vst1.u32 { b_whole_8, fb_mask_ptrs }, [ block_ptr_a, :128 ], c_32
1896
1897  1:
1898   add span_edge_data, span_edge_data, #8
1899   subs num_spans, num_spans, #1
1900
1901   strh num_blocks, [ psx_gpu, #psx_gpu_num_blocks_offset ]
1902   bne 0b
1903
1904   ldmia sp!, { r4 - r11, pc }
1905                                                                            
1906  2:
1907   vpush { colors }
1908
1909   stmdb sp!, { r0 - r3, r12, r14 }
1910   bl flush_render_block_buffer
1911   ldmia sp!, { r0 - r3, r12, r14 }
1912
1913   vpop { colors }
1914
1915   vld1.u32 { test_mask }, [ psx_gpu, :128 ]
1916   veor.u32 draw_mask, draw_mask, draw_mask
1917
1918   mov num_blocks, span_num_blocks
1919   add block_ptr_a, psx_gpu, #psx_gpu_blocks_offset
1920   bal 3b
1921
1922
1923 #define mask_msb_scalar                                   r14
1924
1925 #define msb_mask                                          q15
1926
1927 #define pixels_low                                        d16
1928
1929 #define msb_mask_low                                      d30
1930 #define msb_mask_high                                     d31
1931
1932
1933 .align 3
1934
1935 function(setup_blocks_unshaded_untextured_undithered_unswizzled_direct)
1936   ldrh num_spans, [ psx_gpu, #psx_gpu_num_spans_offset ]
1937
1938   cmp num_spans, #0
1939   bxeq lr
1940
1941   stmdb sp!, { r4 - r11, r14 }
1942
1943   ldr color, [ psx_gpu, #psx_gpu_triangle_color_offset ]
1944
1945   ubfx color_r, color, #3, #5
1946   ubfx color_g, color, #11, #5
1947
1948   ldrh mask_msb_scalar, [ psx_gpu, #psx_gpu_mask_msb_offset ]
1949   ubfx color_b, color, #19, #5
1950
1951   orr color, color_r, color_b, lsl #10
1952   orr color, color, color_g, lsl #5
1953   orr color, color, mask_msb_scalar
1954
1955   vdup.u16 colors, color
1956
1957   add span_edge_data, psx_gpu, #psx_gpu_span_edge_data_offset
1958   orr color, color, lsl #16
1959
1960
1961  0:
1962   ldrh span_num_blocks, [ span_edge_data, #edge_data_num_blocks_offset ]
1963   ldrh y, [ span_edge_data, #edge_data_y_offset ]
1964
1965   ldr fb_ptr, [ psx_gpu, #psx_gpu_vram_ptr_offset ]
1966
1967   cmp span_num_blocks, #0
1968   beq 1f
1969
1970   ldrh left_x, [ span_edge_data, #edge_data_left_x_offset ]
1971
1972   add fb_ptr, fb_ptr, y, lsl #11
1973   subs span_num_blocks, span_num_blocks, #1
1974
1975   add fb_ptr, fb_ptr, left_x, lsl #1
1976   beq 3f
1977
1978  2:
1979   vst1.u32 { colors }, [ fb_ptr ]!
1980   subs span_num_blocks, span_num_blocks, #1
1981
1982   bne 2b
1983
1984  3:
1985   ldrb right_mask, [ span_edge_data, #edge_data_right_mask_offset ]
1986
1987   cmp right_mask, #0x0
1988   beq 5f
1989
1990   tst right_mask, #0xF
1991   streq color, [ fb_ptr ], #4
1992   moveq right_mask, right_mask, lsr #4
1993   streq color, [ fb_ptr ], #4
1994
1995   tst right_mask, #0x3
1996   streq color, [ fb_ptr ], #4
1997   moveq right_mask, right_mask, lsr #2
1998
1999   tst right_mask, #0x1
2000   streqh color, [ fb_ptr ]
2001
2002  1:
2003   add span_edge_data, span_edge_data, #8
2004   subs num_spans, num_spans, #1
2005
2006   strh num_blocks, [ psx_gpu, #psx_gpu_num_blocks_offset ]
2007   bne 0b
2008
2009   ldmia sp!, { r4 - r11, pc }
2010                                                                            
2011  5:
2012   vst1.u32 { colors }, [ fb_ptr ]
2013   bal 1b
2014
2015
2016 #undef c_64
2017
2018 #define c_64                                              r7
2019 #define rg_dx_ptr                                         r2
2020
2021
2022 #undef r_block
2023 #undef g_block
2024 #undef b_block
2025 #undef r_whole
2026 #undef g_whole
2027 #undef b_whole
2028 #undef r_whole_low
2029 #undef r_whole_high
2030 #undef g_whole_low
2031 #undef g_whole_high
2032 #undef b_whole_low
2033 #undef b_whole_high
2034 #undef r_whole_8
2035 #undef g_whole_8
2036 #undef b_whole_8
2037 #undef dither_offsets
2038 #undef rg_dx4
2039 #undef rg_dx8
2040 #undef dx4
2041 #undef dx8
2042 #undef v_left_x
2043 #undef uvrg
2044 #undef block_span
2045 #undef rg
2046 #undef draw_mask
2047 #undef test_mask
2048
2049 #define r_block                                           q0
2050 #define g_block                                           q1
2051 #define b_block                                           q2
2052
2053 #define r_whole                                           q3
2054 #define g_whole                                           q4
2055 #define b_whole                                           q5
2056
2057 #define r_whole_low                                       d6
2058 #define r_whole_high                                      d7
2059 #define g_whole_low                                       d8
2060 #define g_whole_high                                      d9
2061 #define b_whole_low                                       d10
2062 #define b_whole_high                                      d11
2063
2064 #define gb_whole_8                                        q6
2065
2066 #define g_whole_8                                         d12
2067 #define b_whole_8                                         d13
2068
2069 #define r_whole_8                                         d14
2070
2071 #define pixels                                            q8
2072
2073 #define rg_dx4                                            d18
2074 #define rg_dx8                                            d19
2075
2076 #define dx4                                               q10
2077 #define dx8                                               q10
2078
2079 #define v_left_x                                          d6
2080 #define uvrg                                              q4
2081 #define block_span                                        q5
2082
2083 #define rg                                                d9
2084
2085 #define d64_1                                             d22
2086 #define d64_128                                           d23
2087
2088 #define d128_4                                            q12
2089 #define d128_0x7                                          q13
2090
2091 #define d64_4                                             d24
2092
2093 #define dither_offsets                                    q14
2094 #define draw_mask                                         q15
2095
2096 #define dither_offsets_low                                d28
2097
2098 #define rg_dx                                             d0
2099 #define test_mask                                         q10
2100
2101
2102 #define setup_blocks_shaded_untextured_dither_a_dithered()                     \
2103   vqadd.u8 r_whole_8, r_whole_8, dither_offsets_low;                           \
2104   vqadd.u8 gb_whole_8, gb_whole_8, dither_offsets;                             \
2105
2106 #define setup_blocks_shaded_untextured_dither_b_dithered()                     \
2107   vqsub.u8 r_whole_8, r_whole_8, d64_4;                                        \
2108   vqsub.u8 gb_whole_8, gb_whole_8, d128_4                                      \
2109
2110 #define setup_blocks_shaded_untextured_dither_a_undithered()                   \
2111
2112 #define setup_blocks_shaded_untextured_dither_b_undithered()                   \
2113
2114
2115 #define setup_blocks_shaded_untextured_indirect_builder(dithering)             \
2116 .align 3;                                                                      \
2117                                                                                \
2118 function(setup_blocks_shaded_untextured_##dithering##_unswizzled_indirect)     \
2119   ldrh num_spans, [ psx_gpu, #psx_gpu_num_spans_offset ];                      \
2120   add rg_dx_ptr, psx_gpu, #(psx_gpu_uvrg_dx_offset + 8);                       \
2121                                                                                \
2122   vld1.u32 { rg_dx }, [ rg_dx_ptr, :64 ];                                      \
2123                                                                                \
2124   cmp num_spans, #0;                                                           \
2125   bxeq lr;                                                                     \
2126                                                                                \
2127   stmdb sp!, { r4 - r11, r14 };                                                \
2128   vshl.u32 rg_dx4, rg_dx, #2;                                                  \
2129                                                                                \
2130   ldr b_dx, [ psx_gpu, #psx_gpu_b_dx_offset ];                                 \
2131   vshl.u32 rg_dx8, rg_dx, #3;                                                  \
2132                                                                                \
2133   add span_uvrg_offset, psx_gpu, #psx_gpu_span_uvrg_offset_offset;             \
2134                                                                                \
2135   ldrh num_blocks, [ psx_gpu, #psx_gpu_num_blocks_offset ];                    \
2136   add span_edge_data, psx_gpu, #psx_gpu_span_edge_data_offset;                 \
2137                                                                                \
2138   add span_b_offset, psx_gpu, #psx_gpu_span_b_offset_offset;                   \
2139   add block_ptr_a, psx_gpu, #psx_gpu_blocks_offset;                            \
2140                                                                                \
2141   add block_ptr_a, block_ptr_a, num_blocks, lsl #6;                            \
2142   vmov.u8 d64_1, #1;                                                           \
2143                                                                                \
2144   vmov.u8 d128_4, #4;                                                          \
2145   vmov.u8 d64_128, #128;                                                       \
2146                                                                                \
2147   vmov.u8 d128_0x7, #0x7;                                                      \
2148                                                                                \
2149  0:                                                                            \
2150   ldrh span_num_blocks, [ span_edge_data, #edge_data_num_blocks_offset ];      \
2151   add dither_offset_ptr, psx_gpu, #psx_gpu_dither_table_offset;                \
2152                                                                                \
2153   ldrh y, [ span_edge_data, #edge_data_y_offset ];                             \
2154   ldr fb_ptr, [ psx_gpu, #psx_gpu_vram_ptr_offset ];                           \
2155                                                                                \
2156   cmp span_num_blocks, #0;                                                     \
2157   beq 1f;                                                                      \
2158                                                                                \
2159   ldrh left_x, [ span_edge_data, #edge_data_left_x_offset ];                   \
2160   add num_blocks, span_num_blocks, num_blocks;                                 \
2161                                                                                \
2162   cmp num_blocks, #MAX_BLOCKS;                                                 \
2163   bgt 2f;                                                                      \
2164                                                                                \
2165  3:                                                                            \
2166   ldr b, [ span_b_offset ];                                                    \
2167   add fb_ptr, fb_ptr, y, lsl #11;                                              \
2168                                                                                \
2169   vdup.u32 v_left_x, left_x;                                                   \
2170   and y, y, #0x3;                                                              \
2171                                                                                \
2172   ldr dither_row, [ dither_offset_ptr, y, lsl #2 ];                            \
2173   add fb_ptr, fb_ptr, left_x, lsl #1;                                          \
2174                                                                                \
2175   mla b, b_dx, left_x, b;                                                      \
2176   and dither_shift, left_x, #0x03;                                             \
2177                                                                                \
2178   vld1.u32 { uvrg }, [ span_uvrg_offset, :128 ];                               \
2179   vshr.u32 rg_dx, rg_dx4, #2;                                                  \
2180                                                                                \
2181   mov dither_shift, dither_shift, lsl #3;                                      \
2182   vmla.u32 rg, rg_dx, v_left_x;                                                \
2183                                                                                \
2184   mov c_64, #64;                                                               \
2185   subs span_num_blocks, span_num_blocks, #1;                                   \
2186                                                                                \
2187   mov dither_row, dither_row, ror dither_shift;                                \
2188   mov b_dx4, b_dx, lsl #2;                                                     \
2189                                                                                \
2190   vdup.u32 dither_offsets, dither_row;                                         \
2191   add block_span_ptr, psx_gpu, #psx_gpu_r_block_span_offset;                   \
2192                                                                                \
2193   vdup.u32 b_block, b;                                                         \
2194   vadd.u8 dither_offsets, dither_offsets, d128_4;                              \
2195                                                                                \
2196   mov b_dx8, b_dx, lsl #3;                                                     \
2197   vdup.u32 r_block, rg[0];                                                     \
2198   vdup.u32 g_block, rg[1];                                                     \
2199                                                                                \
2200   vld1.u32 { block_span }, [ block_span_ptr, :128 ]!;                          \
2201                                                                                \
2202   vadd.u32 r_block, r_block, block_span;                                       \
2203   vld1.u32 { block_span }, [ block_span_ptr, :128 ]!;                          \
2204                                                                                \
2205   vadd.u32 g_block, g_block, block_span;                                       \
2206   vld1.u32 { block_span }, [ block_span_ptr, :128 ];                           \
2207                                                                                \
2208   vadd.u32 b_block, b_block, block_span;                                       \
2209   add block_ptr_b, block_ptr_a, #16;                                           \
2210                                                                                \
2211   vshrn.u32 r_whole_low, r_block, #16;                                         \
2212   vshrn.u32 g_whole_low, g_block, #16;                                         \
2213   vshrn.u32 b_whole_low, b_block, #16;                                         \
2214   vdup.u32 dx4, rg_dx4[0];                                                     \
2215                                                                                \
2216   vaddhn.u32 r_whole_high, r_block, dx4;                                       \
2217   vdup.u32 dx4, rg_dx4[1];                                                     \
2218                                                                                \
2219   vaddhn.u32 g_whole_high, g_block, dx4;                                       \
2220   vdup.u32 dx4, b_dx4;                                                         \
2221                                                                                \
2222   vaddhn.u32 b_whole_high, b_block, dx4;                                       \
2223   vdup.u32 dx8, rg_dx8[0];                                                     \
2224                                                                                \
2225   vadd.u32 r_block, r_block, dx8;                                              \
2226   vdup.u32 dx8, rg_dx8[1];                                                     \
2227                                                                                \
2228   vadd.u32 g_block, g_block, dx8;                                              \
2229   vdup.u32 dx8, b_dx8;                                                         \
2230                                                                                \
2231   vadd.u32 b_block, b_block, dx8;                                              \
2232                                                                                \
2233   vmovn.u16 r_whole_8, r_whole;                                                \
2234   vmovn.u16 g_whole_8, g_whole;                                                \
2235   vmovn.u16 b_whole_8, b_whole;                                                \
2236                                                                                \
2237   beq 5f;                                                                      \
2238   veor.u32 draw_mask, draw_mask, draw_mask;                                    \
2239                                                                                \
2240  4:                                                                            \
2241   setup_blocks_shaded_untextured_dither_a_##dithering();                       \
2242   vshrn.u32 r_whole_low, r_block, #16;                                         \
2243                                                                                \
2244   setup_blocks_shaded_untextured_dither_b_##dithering();                       \
2245   vshrn.u32 g_whole_low, g_block, #16;                                         \
2246                                                                                \
2247   vshrn.u32 b_whole_low, b_block, #16;                                         \
2248   str fb_ptr, [ block_ptr_a, #44 ];                                            \
2249                                                                                \
2250   vdup.u32 dx4, rg_dx4[0];                                                     \
2251   vshr.u8 r_whole_8, r_whole_8, #3;                                            \
2252   vbic.u8 gb_whole_8, gb_whole_8, d128_0x7;                                    \
2253                                                                                \
2254   vaddhn.u32 r_whole_high, r_block, dx4;                                       \
2255   vdup.u32 dx4, rg_dx4[1];                                                     \
2256                                                                                \
2257   vaddhn.u32 g_whole_high, g_block, dx4;                                       \
2258   vdup.u32 dx4, b_dx4;                                                         \
2259                                                                                \
2260   vaddhn.u32 b_whole_high, b_block, dx4;                                       \
2261   vdup.u32 dx8, rg_dx8[0];                                                     \
2262                                                                                \
2263   vmull.u8 pixels, r_whole_8, d64_1;                                           \
2264   vmlal.u8 pixels, g_whole_8, d64_4;                                           \
2265   vmlal.u8 pixels, b_whole_8, d64_128;                                         \
2266                                                                                \
2267   vadd.u32 r_block, r_block, dx8;                                              \
2268   vdup.u32 dx8, rg_dx8[1];                                                     \
2269                                                                                \
2270   vadd.u32 g_block, g_block, dx8;                                              \
2271   vdup.u32 dx8, b_dx8;                                                         \
2272                                                                                \
2273   vadd.u32 b_block, b_block, dx8;                                              \
2274   add fb_ptr, fb_ptr, #16;                                                     \
2275                                                                                \
2276   vmovn.u16 r_whole_8, r_whole;                                                \
2277   vmovn.u16 g_whole_8, g_whole;                                                \
2278   vmovn.u16 b_whole_8, b_whole;                                                \
2279                                                                                \
2280   vst1.u32 { draw_mask }, [ block_ptr_a, :128 ], c_64;                         \
2281   vst1.u32 { pixels }, [ block_ptr_b, :128 ], c_64;                            \
2282                                                                                \
2283   pld [ fb_ptr ];                                                              \
2284                                                                                \
2285   subs span_num_blocks, span_num_blocks, #1;                                   \
2286   bne 4b;                                                                      \
2287                                                                                \
2288  5:                                                                            \
2289   str fb_ptr, [ block_ptr_a, #44 ];                                            \
2290   setup_blocks_shaded_untextured_dither_a_##dithering();                       \
2291                                                                                \
2292   ldrh right_mask, [ span_edge_data, #edge_data_right_mask_offset ];           \
2293   setup_blocks_shaded_untextured_dither_b_##dithering();                       \
2294                                                                                \
2295   vshr.u8 r_whole_8, r_whole_8, #3;                                            \
2296   vdup.u8 draw_mask, right_mask;                                               \
2297                                                                                \
2298   vbic.u8 gb_whole_8, gb_whole_8, d128_0x7;                                    \
2299   vld1.u32 { test_mask }, [ psx_gpu, :128 ];                                   \
2300                                                                                \
2301   vtst.u16 draw_mask, draw_mask, test_mask;                                    \
2302                                                                                \
2303   vmull.u8 pixels, r_whole_8, d64_1;                                           \
2304   vmlal.u8 pixels, g_whole_8, d64_4;                                           \
2305   vmlal.u8 pixels, b_whole_8, d64_128;                                         \
2306                                                                                \
2307   vst1.u32 { draw_mask }, [ block_ptr_a, :128 ], c_64;                         \
2308   vst1.u32 { pixels }, [ block_ptr_b, :128 ], c_64;                            \
2309                                                                                \
2310  1:                                                                            \
2311   add span_uvrg_offset, span_uvrg_offset, #16;                                 \
2312   add span_b_offset, span_b_offset, #4;                                        \
2313                                                                                \
2314   add span_edge_data, span_edge_data, #8;                                      \
2315   subs num_spans, num_spans, #1;                                               \
2316                                                                                \
2317   strh num_blocks, [ psx_gpu, #psx_gpu_num_blocks_offset ];                    \
2318   bne 0b;                                                                      \
2319                                                                                \
2320   ldmia sp!, { r4 - r11, pc };                                                 \
2321                                                                                \
2322  2:                                                                            \
2323   /* TODO: Load from psx_gpu instead of saving/restoring these               */\
2324   vpush { rg_dx4 };                                                            \
2325                                                                                \
2326   stmdb sp!, { r0 - r3, r12, r14 };                                            \
2327   bl flush_render_block_buffer;                                                \
2328   ldmia sp!, { r0 - r3, r12, r14 };                                            \
2329                                                                                \
2330   vpop { rg_dx4 };                                                             \
2331                                                                                \
2332   vmov.u8 d64_1, #1;                                                           \
2333   vmov.u8 d128_4, #4;                                                          \
2334   vmov.u8 d64_128, #128;                                                       \
2335   vmov.u8 d128_0x7, #0x7;                                                      \
2336                                                                                \
2337   vadd.u32 rg_dx8, rg_dx4, rg_dx4;                                             \
2338                                                                                \
2339   mov num_blocks, span_num_blocks;                                             \
2340   add block_ptr_a, psx_gpu, #psx_gpu_blocks_offset;                            \
2341   bal 3b                                                                       \
2342
2343
2344 setup_blocks_shaded_untextured_indirect_builder(undithered)
2345 setup_blocks_shaded_untextured_indirect_builder(dithered)
2346
2347
2348 #undef draw_mask
2349
2350 #define mask_msb_ptr                                      r14
2351
2352 #define draw_mask                                         q0
2353 #define pixels_low                                        d16
2354 #define pixels_high                                       d17
2355
2356
2357
2358 #define setup_blocks_shaded_untextured_direct_builder(dithering)               \
2359 .align 3;                                                                      \
2360                                                                                \
2361 function(setup_blocks_shaded_untextured_##dithering##_unswizzled_direct)       \
2362   ldrh num_spans, [ psx_gpu, #psx_gpu_num_spans_offset ];                      \
2363   add rg_dx_ptr, psx_gpu, #(psx_gpu_uvrg_dx_offset + 8);                       \
2364                                                                                \
2365   vld1.u32 { rg_dx }, [ rg_dx_ptr, :64 ];                                      \
2366                                                                                \
2367   cmp num_spans, #0;                                                           \
2368   bxeq lr;                                                                     \
2369                                                                                \
2370   stmdb sp!, { r4 - r11, r14 };                                                \
2371   vshl.u32 rg_dx4, rg_dx, #2;                                                  \
2372                                                                                \
2373   ldr b_dx, [ psx_gpu, #psx_gpu_b_dx_offset ];                                 \
2374   vshl.u32 rg_dx8, rg_dx, #3;                                                  \
2375                                                                                \
2376   add span_uvrg_offset, psx_gpu, #psx_gpu_span_uvrg_offset_offset;             \
2377   add span_edge_data, psx_gpu, #psx_gpu_span_edge_data_offset;                 \
2378                                                                                \
2379   add span_b_offset, psx_gpu, #psx_gpu_span_b_offset_offset;                   \
2380   vmov.u8 d64_1, #1;                                                           \
2381                                                                                \
2382   vmov.u8 d128_4, #4;                                                          \
2383   vmov.u8 d64_128, #128;                                                       \
2384                                                                                \
2385   vmov.u8 d128_0x7, #0x7;                                                      \
2386   add mask_msb_ptr, psx_gpu, #psx_gpu_mask_msb_offset;                         \
2387   vld1.u16 { msb_mask_low[], msb_mask_high[] }, [ mask_msb_ptr, :16 ];         \
2388                                                                                \
2389  0:                                                                            \
2390   ldrh span_num_blocks, [ span_edge_data, #edge_data_num_blocks_offset ];      \
2391   add dither_offset_ptr, psx_gpu, #psx_gpu_dither_table_offset;                \
2392                                                                                \
2393   ldrh y, [ span_edge_data, #edge_data_y_offset ];                             \
2394   ldr fb_ptr, [ psx_gpu, #psx_gpu_vram_ptr_offset ];                           \
2395                                                                                \
2396   cmp span_num_blocks, #0;                                                     \
2397   beq 1f;                                                                      \
2398                                                                                \
2399   ldrh left_x, [ span_edge_data, #edge_data_left_x_offset ];                   \
2400   add fb_ptr, fb_ptr, y, lsl #11;                                              \
2401                                                                                \
2402   ldr b, [ span_b_offset ];                                                    \
2403   vdup.u32 v_left_x, left_x;                                                   \
2404   and y, y, #0x3;                                                              \
2405                                                                                \
2406   ldr dither_row, [ dither_offset_ptr, y, lsl #2 ];                            \
2407   add fb_ptr, fb_ptr, left_x, lsl #1;                                          \
2408                                                                                \
2409   mla b, b_dx, left_x, b;                                                      \
2410   and dither_shift, left_x, #0x03;                                             \
2411                                                                                \
2412   vld1.u32 { uvrg }, [ span_uvrg_offset, :128 ];                               \
2413   vshr.u32 rg_dx, rg_dx4, #2;                                                  \
2414                                                                                \
2415   mov dither_shift, dither_shift, lsl #3;                                      \
2416   vmla.u32 rg, rg_dx, v_left_x;                                                \
2417                                                                                \
2418   subs span_num_blocks, span_num_blocks, #1;                                   \
2419                                                                                \
2420   mov dither_row, dither_row, ror dither_shift;                                \
2421   mov b_dx4, b_dx, lsl #2;                                                     \
2422                                                                                \
2423   vdup.u32 dither_offsets, dither_row;                                         \
2424   add block_span_ptr, psx_gpu, #psx_gpu_r_block_span_offset;                   \
2425                                                                                \
2426   vdup.u32 b_block, b;                                                         \
2427   vadd.u8 dither_offsets, dither_offsets, d128_4;                              \
2428                                                                                \
2429   mov b_dx8, b_dx, lsl #3;                                                     \
2430   vdup.u32 r_block, rg[0];                                                     \
2431   vdup.u32 g_block, rg[1];                                                     \
2432                                                                                \
2433   vld1.u32 { block_span }, [ block_span_ptr, :128 ]!;                          \
2434                                                                                \
2435   vadd.u32 r_block, r_block, block_span;                                       \
2436   vld1.u32 { block_span }, [ block_span_ptr, :128 ]!;                          \
2437                                                                                \
2438   vadd.u32 g_block, g_block, block_span;                                       \
2439   vld1.u32 { block_span }, [ block_span_ptr, :128 ];                           \
2440                                                                                \
2441   vadd.u32 b_block, b_block, block_span;                                       \
2442   add block_ptr_b, block_ptr_a, #16;                                           \
2443                                                                                \
2444   vshrn.u32 r_whole_low, r_block, #16;                                         \
2445   vshrn.u32 g_whole_low, g_block, #16;                                         \
2446   vshrn.u32 b_whole_low, b_block, #16;                                         \
2447   vdup.u32 dx4, rg_dx4[0];                                                     \
2448                                                                                \
2449   vaddhn.u32 r_whole_high, r_block, dx4;                                       \
2450   vdup.u32 dx4, rg_dx4[1];                                                     \
2451                                                                                \
2452   vaddhn.u32 g_whole_high, g_block, dx4;                                       \
2453   vdup.u32 dx4, b_dx4;                                                         \
2454                                                                                \
2455   vaddhn.u32 b_whole_high, b_block, dx4;                                       \
2456   vdup.u32 dx8, rg_dx8[0];                                                     \
2457                                                                                \
2458   vadd.u32 r_block, r_block, dx8;                                              \
2459   vdup.u32 dx8, rg_dx8[1];                                                     \
2460                                                                                \
2461   vadd.u32 g_block, g_block, dx8;                                              \
2462   vdup.u32 dx8, b_dx8;                                                         \
2463                                                                                \
2464   vadd.u32 b_block, b_block, dx8;                                              \
2465                                                                                \
2466   vmovn.u16 r_whole_8, r_whole;                                                \
2467   vmovn.u16 g_whole_8, g_whole;                                                \
2468   vmovn.u16 b_whole_8, b_whole;                                                \
2469                                                                                \
2470   beq 3f;                                                                      \
2471                                                                                \
2472  2:                                                                            \
2473   setup_blocks_shaded_untextured_dither_a_##dithering();                       \
2474   vshrn.u32 r_whole_low, r_block, #16;                                         \
2475                                                                                \
2476   setup_blocks_shaded_untextured_dither_b_##dithering();                       \
2477   vshrn.u32 g_whole_low, g_block, #16;                                         \
2478                                                                                \
2479   vshrn.u32 b_whole_low, b_block, #16;                                         \
2480                                                                                \
2481   vdup.u32 dx4, rg_dx4[0];                                                     \
2482   vshr.u8 r_whole_8, r_whole_8, #3;                                            \
2483   vbic.u8 gb_whole_8, gb_whole_8, d128_0x7;                                    \
2484                                                                                \
2485   vaddhn.u32 r_whole_high, r_block, dx4;                                       \
2486   vdup.u32 dx4, rg_dx4[1];                                                     \
2487                                                                                \
2488   vmov pixels, msb_mask;                                                       \
2489   vaddhn.u32 g_whole_high, g_block, dx4;                                       \
2490   vdup.u32 dx4, b_dx4;                                                         \
2491                                                                                \
2492   vaddhn.u32 b_whole_high, b_block, dx4;                                       \
2493   vdup.u32 dx8, rg_dx8[0];                                                     \
2494                                                                                \
2495   vmlal.u8 pixels, r_whole_8, d64_1;                                           \
2496   vmlal.u8 pixels, g_whole_8, d64_4;                                           \
2497   vmlal.u8 pixels, b_whole_8, d64_128;                                         \
2498                                                                                \
2499   vadd.u32 r_block, r_block, dx8;                                              \
2500   vdup.u32 dx8, rg_dx8[1];                                                     \
2501                                                                                \
2502   vadd.u32 g_block, g_block, dx8;                                              \
2503   vdup.u32 dx8, b_dx8;                                                         \
2504                                                                                \
2505   vadd.u32 b_block, b_block, dx8;                                              \
2506                                                                                \
2507   vmovn.u16 r_whole_8, r_whole;                                                \
2508   vmovn.u16 g_whole_8, g_whole;                                                \
2509   vmovn.u16 b_whole_8, b_whole;                                                \
2510                                                                                \
2511   vst1.u32 { pixels }, [ fb_ptr ]!;                                            \
2512   subs span_num_blocks, span_num_blocks, #1;                                   \
2513   bne 2b;                                                                      \
2514                                                                                \
2515  3:                                                                            \
2516   setup_blocks_shaded_untextured_dither_a_##dithering();                       \
2517                                                                                \
2518   ldrh right_mask, [ span_edge_data, #edge_data_right_mask_offset ];           \
2519   setup_blocks_shaded_untextured_dither_b_##dithering();                       \
2520                                                                                \
2521   vshr.u8 r_whole_8, r_whole_8, #3;                                            \
2522   rbit right_mask, right_mask;                                                 \
2523   vmov pixels, msb_mask;                                                       \
2524   vbic.u8 gb_whole_8, gb_whole_8, d128_0x7;                                    \
2525   clz right_mask, right_mask;                                                  \
2526                                                                                \
2527   vmlal.u8 pixels, r_whole_8, d64_1;                                           \
2528   vmlal.u8 pixels, g_whole_8, d64_4;                                           \
2529   vmlal.u8 pixels, b_whole_8, d64_128;                                         \
2530                                                                                \
2531   ldr pc, [ pc, right_mask, lsl #2 ];                                          \
2532   nop;                                                                         \
2533   nop;                                                                         \
2534   .word 4f;                                                                    \
2535   .word 5f;                                                                    \
2536   .word 6f;                                                                    \
2537   .word 7f;                                                                    \
2538   .word 8f;                                                                    \
2539   .word 9f;                                                                    \
2540   .word 10f;                                                                   \
2541   .word 11f;                                                                   \
2542                                                                                \
2543  4:                                                                            \
2544   vst1.u16 { pixels_low[0] }, [ fb_ptr ];                                      \
2545   bal 1f;                                                                      \
2546                                                                                \
2547  5:                                                                            \
2548   vst1.u32 { pixels_low[0] }, [ fb_ptr ];                                      \
2549   bal 1f;                                                                      \
2550                                                                                \
2551  6:                                                                            \
2552   vst1.u32 { pixels_low[0] }, [ fb_ptr ]!;                                     \
2553   vst1.u16 { pixels_low[2] }, [ fb_ptr ];                                      \
2554   bal 1f;                                                                      \
2555                                                                                \
2556  7:                                                                            \
2557   vst1.u32 { pixels_low }, [ fb_ptr ];                                         \
2558   bal 1f;                                                                      \
2559                                                                                \
2560  8:                                                                            \
2561   vst1.u32 { pixels_low }, [ fb_ptr ]!;                                        \
2562   vst1.u16 { pixels_high[0] }, [ fb_ptr ];                                     \
2563   bal 1f;                                                                      \
2564                                                                                \
2565  9:                                                                            \
2566   vst1.u32 { pixels_low }, [ fb_ptr ]!;                                        \
2567   vst1.u32 { pixels_high[0] }, [ fb_ptr ]!;                                    \
2568   bal 1f;                                                                      \
2569                                                                                \
2570  10:                                                                           \
2571   vst1.u32 { pixels_low }, [ fb_ptr ]!;                                        \
2572   vst1.u32 { pixels_high[0] }, [ fb_ptr ]!;                                    \
2573   vst1.u16 { pixels_high[2] }, [ fb_ptr ];                                     \
2574   bal 1f;                                                                      \
2575                                                                                \
2576  11:                                                                           \
2577   vst1.u32 { pixels }, [ fb_ptr ];                                             \
2578   bal 1f;                                                                      \
2579                                                                                \
2580  1:                                                                            \
2581   add span_uvrg_offset, span_uvrg_offset, #16;                                 \
2582   add span_b_offset, span_b_offset, #4;                                        \
2583                                                                                \
2584   add span_edge_data, span_edge_data, #8;                                      \
2585   subs num_spans, num_spans, #1;                                               \
2586                                                                                \
2587   bne 0b;                                                                      \
2588                                                                                \
2589   ldmia sp!, { r4 - r11, pc }                                                  \
2590
2591 setup_blocks_shaded_untextured_direct_builder(undithered)
2592 setup_blocks_shaded_untextured_direct_builder(dithered)
2593
2594
2595 #undef psx_gpu
2596 #undef num_blocks
2597 #undef triangle
2598 #undef c_64
2599
2600 #define psx_gpu                                  r0
2601 #define block_ptr                                r1
2602 #define num_blocks                               r2
2603 #define uv_01                                    r3
2604 #define uv_23                                    r4
2605 #define uv_45                                    r5
2606 #define uv_67                                    r6
2607 #define uv_0                                     r7
2608 #define uv_1                                     r3
2609 #define uv_2                                     r8
2610 #define uv_3                                     r4
2611 #define uv_4                                     r9
2612 #define uv_5                                     r5
2613 #define uv_6                                     r10
2614 #define uv_7                                     r6
2615 #define texture_ptr                              r11
2616
2617 #define pixel_0                                  r7
2618 #define pixel_1                                  r3
2619 #define pixel_2                                  r8
2620 #define pixel_3                                  r4
2621 #define pixel_4                                  r9
2622 #define pixel_5                                  r5
2623 #define pixel_6                                  r10
2624 #define pixel_7                                  r6
2625
2626 #define pixels_a                                 r7
2627 #define pixels_b                                 r9
2628 #define pixels_c                                 r8
2629 #define pixels_d                                 r10
2630
2631 #define c_64                                     r0
2632
2633 #define clut_ptr                                 r12
2634 #define current_texture_mask                     r5
2635 #define dirty_textures_mask                      r6
2636
2637 #define texels                                   d0
2638
2639 #define clut_low_a                               d2
2640 #define clut_low_b                               d3
2641 #define clut_high_a                              d4
2642 #define clut_high_b                              d5
2643
2644 #define clut_a                                   q1
2645 #define clut_b                                   q2
2646
2647 #define texels_low                               d6
2648 #define texels_high                              d7
2649
2650 .align 3
2651
2652 function(texture_blocks_untextured)
2653   bx lr
2654
2655
2656 .align 3
2657
2658 function(texture_blocks_4bpp)
2659   stmdb sp!, { r3 - r11, r14 }
2660   add block_ptr, psx_gpu, #psx_gpu_blocks_offset
2661
2662   ldr texture_ptr, [ psx_gpu, #psx_gpu_texture_page_ptr_offset ]
2663   ldrh num_blocks, [ psx_gpu, #psx_gpu_num_blocks_offset ]
2664
2665   ldr clut_ptr, [ psx_gpu, #psx_gpu_clut_ptr_offset ]
2666   vld1.u32 { clut_a, clut_b }, [ clut_ptr, :128 ]
2667
2668   ldr current_texture_mask, [ psx_gpu, #psx_gpu_current_texture_mask_offset ]
2669   vuzp.u8 clut_a, clut_b
2670
2671   ldr dirty_textures_mask, [ psx_gpu, #psx_gpu_dirty_textures_4bpp_mask_offset ]
2672   tst dirty_textures_mask, current_texture_mask
2673
2674   bne 1f
2675   mov c_64, #64
2676
2677 0:
2678   ldm block_ptr, { uv_01, uv_23, uv_45, uv_67 }
2679
2680   uxtah uv_0, texture_ptr, uv_01
2681   uxtah uv_1, texture_ptr, uv_01, ror #16
2682
2683   uxtah uv_2, texture_ptr, uv_23
2684   uxtah uv_3, texture_ptr, uv_23, ror #16
2685
2686   uxtah uv_4, texture_ptr, uv_45
2687   ldrb pixel_0, [ uv_0 ]
2688
2689   uxtah uv_5, texture_ptr, uv_45, ror #16
2690   ldrb pixel_1, [ uv_1 ]
2691
2692   uxtah uv_6, texture_ptr, uv_67
2693   ldrb pixel_2, [ uv_2 ]
2694
2695   uxtah uv_7, texture_ptr, uv_67, ror #16
2696   ldrb pixel_3, [ uv_3 ]
2697
2698   ldrb pixel_4, [ uv_4 ]
2699   subs num_blocks, num_blocks, #1
2700
2701   ldrb pixel_5, [ uv_5 ]
2702   orr pixels_a, pixel_0, pixel_1, lsl #8
2703
2704   ldrb pixel_6, [ uv_6 ]
2705   orr pixels_b, pixel_4, pixel_5, lsl #8
2706
2707   ldrb pixel_7, [ uv_7 ]
2708   orr pixels_a, pixels_a, pixel_2, lsl #16
2709
2710   orr pixels_b, pixels_b, pixel_6, lsl #16
2711   orr pixels_a, pixels_a, pixel_3, lsl #24
2712
2713   orr pixels_b, pixels_b, pixel_7, lsl #24
2714   vmov.u32 texels, pixels_a, pixels_b
2715
2716   vtbl.8 texels_low, { clut_low_a, clut_low_b }, texels
2717   vtbl.8 texels_high, { clut_high_a, clut_high_b }, texels
2718
2719   vst2.u8 { texels_low, texels_high }, [ block_ptr, :128 ], c_64
2720   bne 0b
2721
2722   ldmia sp!, { r3 - r11, pc }
2723
2724 1:
2725   stmdb sp!, { r1 - r2 }  
2726   bl update_texture_4bpp_cache
2727
2728   mov c_64, #64
2729   ldmia sp!, { r1 - r2 }
2730   bal 0b
2731
2732
2733 .align 3
2734
2735 function(texture_blocks_8bpp)
2736   stmdb sp!, { r3 - r11, r14 }
2737   add block_ptr, psx_gpu, #psx_gpu_blocks_offset
2738
2739   ldr texture_ptr, [ psx_gpu, #psx_gpu_texture_page_ptr_offset ]
2740   ldrh num_blocks, [ psx_gpu, #psx_gpu_num_blocks_offset ]
2741
2742   ldr clut_ptr, [ psx_gpu, #psx_gpu_clut_ptr_offset ]
2743   ldr current_texture_mask, [ psx_gpu, #psx_gpu_current_texture_mask_offset ]
2744
2745   ldr dirty_textures_mask, [ psx_gpu, #psx_gpu_dirty_textures_8bpp_mask_offset ]
2746   tst dirty_textures_mask, current_texture_mask
2747
2748   bne 1f
2749   nop
2750
2751 0:
2752   ldm block_ptr, { uv_01, uv_23, uv_45, uv_67 }
2753
2754   uxtah uv_0, texture_ptr, uv_01
2755   uxtah uv_1, texture_ptr, uv_01, ror #16
2756
2757   uxtah uv_2, texture_ptr, uv_23
2758   uxtah uv_3, texture_ptr, uv_23, ror #16
2759
2760   uxtah uv_4, texture_ptr, uv_45
2761   ldrb pixel_0, [ uv_0 ]
2762
2763   uxtah uv_5, texture_ptr, uv_45, ror #16
2764   ldrb pixel_1, [ uv_1 ]
2765
2766   uxtah uv_6, texture_ptr, uv_67
2767   ldrb pixel_2, [ uv_2 ]
2768
2769   uxtah uv_7, texture_ptr, uv_67, ror #16
2770   ldrb pixel_3, [ uv_3 ]
2771
2772   ldrb pixel_4, [ uv_4 ]
2773   add pixel_0, pixel_0, pixel_0
2774
2775   ldrb pixel_5, [ uv_5 ]
2776   add pixel_1, pixel_1, pixel_1
2777
2778   ldrb pixel_6, [ uv_6 ]
2779   add pixel_2, pixel_2, pixel_2
2780
2781   ldrb pixel_7, [ uv_7 ]
2782   add pixel_3, pixel_3, pixel_3
2783
2784   ldrh pixel_0, [ clut_ptr, pixel_0 ]
2785   add pixel_4, pixel_4, pixel_4
2786
2787   ldrh pixel_1, [ clut_ptr, pixel_1 ]
2788   add pixel_5, pixel_5, pixel_5
2789
2790   ldrh pixel_2, [ clut_ptr, pixel_2 ]
2791   add pixel_6, pixel_6, pixel_6
2792
2793   ldrh pixel_3, [ clut_ptr, pixel_3 ]
2794   add pixel_7, pixel_7, pixel_7
2795
2796   ldrh pixel_4, [ clut_ptr, pixel_4 ]
2797   orr pixels_a, pixel_0, pixel_1, lsl #16
2798
2799   ldrh pixel_5, [ clut_ptr, pixel_5 ]
2800   orr pixels_c, pixel_2, pixel_3, lsl #16
2801
2802   ldrh pixel_6, [ clut_ptr, pixel_6 ]
2803   subs num_blocks, num_blocks, #1
2804
2805   ldrh pixel_7, [ clut_ptr, pixel_7 ]
2806   orr pixels_b, pixel_4, pixel_5, lsl #16
2807
2808   orr pixels_d, pixel_6, pixel_7, lsl #16
2809   stm block_ptr, { pixels_a, pixels_c, pixels_b, pixels_d } 
2810
2811   add block_ptr, block_ptr, #64
2812   bne 0b
2813
2814   ldmia sp!, { r3 - r11, pc }
2815
2816 1:
2817   stmdb sp!, { r1 - r2, r12 }
2818
2819   bl update_texture_8bpp_cache
2820
2821   ldmia sp!, { r1 - r2, r12 }
2822   bal 0b
2823
2824
2825 #undef uv_0
2826 #undef uv_1
2827 #undef uv_2
2828 #undef uv_3
2829 #undef uv_4
2830 #undef uv_5
2831 #undef uv_6
2832 #undef uv_7
2833
2834 #undef pixel_0
2835 #undef pixel_1
2836 #undef pixel_2
2837 #undef pixel_3
2838 #undef pixel_4
2839 #undef pixel_5
2840 #undef pixel_6
2841 #undef pixel_7
2842
2843 #undef texture_ptr
2844
2845 #undef pixels_a
2846 #undef pixels_b
2847 #undef pixels_c
2848 #undef pixels_d
2849
2850 #define psx_gpu                                  r0
2851 #define block_ptr                                r1
2852 #define num_blocks                               r2
2853
2854 #define uv_0                                     r3
2855 #define uv_1                                     r4
2856 #define u_0                                      r3
2857 #define u_1                                      r4
2858 #define v_0                                      r5
2859 #define v_1                                      r6
2860
2861 #define uv_2                                     r5
2862 #define uv_3                                     r6
2863 #define u_2                                      r5
2864 #define u_3                                      r6
2865 #define v_2                                      r7
2866 #define v_3                                      r8
2867
2868 #define uv_4                                     r7
2869 #define uv_5                                     r8
2870 #define u_4                                      r7
2871 #define u_5                                      r8
2872 #define v_4                                      r9
2873 #define v_5                                      r10
2874
2875 #define uv_6                                     r9
2876 #define uv_7                                     r10
2877 #define u_6                                      r9
2878 #define u_7                                      r10
2879 #define v_6                                      r11
2880 #define v_7                                      r0
2881
2882 #define pixel_0                                  r3
2883 #define pixel_1                                  r4
2884 #define pixel_2                                  r5
2885 #define pixel_3                                  r6
2886 #define pixel_4                                  r7
2887 #define pixel_5                                  r8
2888 #define pixel_6                                  r9
2889 #define pixel_7                                  r10
2890
2891 #define pixels_a                                 r3
2892 #define pixels_b                                 r5
2893 #define pixels_c                                 r7
2894 #define pixels_d                                 r9
2895
2896 #define texture_ptr                              r12
2897
2898
2899 .align 3
2900
2901 function(texture_blocks_16bpp)
2902   stmdb sp!, { r3 - r11, r14 }
2903   add block_ptr, psx_gpu, #psx_gpu_blocks_offset
2904
2905   ldrh num_blocks, [ psx_gpu, #psx_gpu_num_blocks_offset ]
2906   ldr texture_ptr, [ psx_gpu, #psx_gpu_texture_page_ptr_offset ]
2907
2908 0:
2909   ldrh uv_0, [ block_ptr ]
2910   subs num_blocks, num_blocks, #1
2911
2912   ldrh uv_1, [ block_ptr, #2 ]
2913
2914   and v_0, uv_0, #0xFF00
2915   and v_1, uv_1, #0xFF00
2916
2917   and u_0, uv_0, #0xFF
2918   and u_1, uv_1, #0xFF
2919
2920   add uv_0, u_0, v_0, lsl #2
2921   ldrh uv_2, [ block_ptr, #4 ]
2922
2923   add uv_1, u_1, v_1, lsl #2
2924   ldrh uv_3, [ block_ptr, #6 ]
2925
2926   add uv_0, uv_0, uv_0
2927   add uv_1, uv_1, uv_1
2928
2929   and v_2, uv_2, #0xFF00
2930   and v_3, uv_3, #0xFF00
2931
2932   and u_2, uv_2, #0xFF
2933   and u_3, uv_3, #0xFF
2934
2935   add uv_2, u_2, v_2, lsl #2
2936   ldrh uv_4, [ block_ptr, #8 ]
2937
2938   add uv_3, u_3, v_3, lsl #2
2939   ldrh uv_5, [ block_ptr, #10 ]
2940
2941   add uv_2, uv_2, uv_2
2942   add uv_3, uv_3, uv_3
2943
2944   and v_4, uv_4, #0xFF00
2945   and v_5, uv_5, #0xFF00
2946
2947   and u_4, uv_4, #0xFF
2948   and u_5, uv_5, #0xFF
2949
2950   add uv_4, u_4, v_4, lsl #2
2951   ldrh uv_6, [ block_ptr, #12 ]
2952
2953   add uv_5, u_5, v_5, lsl #2
2954   ldrh uv_7, [ block_ptr, #14 ]
2955
2956   add uv_4, uv_4, uv_4
2957   ldrh pixel_0, [ texture_ptr, uv_0 ]
2958
2959   add uv_5, uv_5, uv_5
2960   ldrh pixel_1, [ texture_ptr, uv_1 ]
2961
2962   and v_6, uv_6, #0xFF00
2963   ldrh pixel_2, [ texture_ptr, uv_2 ]
2964
2965   and v_7, uv_7, #0xFF00
2966   ldrh pixel_3, [ texture_ptr, uv_3 ]
2967
2968   and u_6, uv_6, #0xFF
2969   ldrh pixel_4, [ texture_ptr, uv_4 ]
2970
2971   and u_7, uv_7, #0xFF
2972   ldrh pixel_5, [ texture_ptr, uv_5 ]
2973
2974   add uv_6, u_6, v_6, lsl #2
2975   add uv_7, u_7, v_7, lsl #2
2976
2977   add uv_6, uv_6, uv_6
2978   add uv_7, uv_7, uv_7
2979
2980   orr pixels_a, pixel_0, pixel_1, lsl #16
2981   orr pixels_b, pixel_2, pixel_3, lsl #16
2982
2983   ldrh pixel_6, [ texture_ptr, uv_6 ]
2984   orr pixels_c, pixel_4, pixel_5, lsl #16
2985
2986   ldrh pixel_7, [ texture_ptr, uv_7 ]
2987   orr pixels_d, pixel_6, pixel_7, lsl #16
2988
2989   stm block_ptr, { pixels_a, pixels_b, pixels_c, pixels_d }
2990   add block_ptr, block_ptr, #64
2991
2992   bne 0b
2993
2994   ldmia sp!, { r3 - r11, pc }
2995
2996
2997 #undef num_blocks
2998
2999 #undef test_mask
3000 #undef texels
3001 #undef pixels_b
3002 #undef pixels
3003 #undef d64_1
3004 #undef d64_4
3005 #undef d64_128
3006 #undef draw_mask
3007 #undef msb_mask
3008 #undef msb_mask_low
3009 #undef msb_mask_high
3010 #undef fb_pixels
3011
3012 #undef c_32
3013 #undef fb_ptr
3014 #undef mask_msb_ptr
3015
3016 #define psx_gpu                                  r0
3017 #define num_blocks                               r1
3018 #define color_ptr                                r2
3019 #define colors_scalar                            r2
3020 #define colors_scalar_compare                    r3
3021 #define mask_msb_ptr                             r2
3022
3023 #define block_ptr_load_a                         r0
3024 #define block_ptr_store                          r3
3025 #define block_ptr_load_b                         r12
3026 #define c_32                                     r2
3027
3028 #define c_48                                     r4
3029 #define fb_ptr                                   r14
3030 #define draw_mask_bits_scalar                    r5
3031
3032 #define d128_0x07                                q0
3033 #define d128_0x1F                                q1
3034 #define d128_0x8000                              q2
3035 #define test_mask                                q3
3036 #define texels                                   q4
3037 #define colors_rg                                q5
3038 #define colors_b_dm_bits                         q6
3039 #define texels_rg                                q7
3040 #define pixels_r                                 q8
3041 #define pixels_g                                 q9
3042 #define pixels_b                                 q10
3043 #define pixels                                   q11
3044 #define zero_mask                                q4
3045 #define draw_mask                                q12
3046 #define msb_mask                                 q13
3047
3048 #define fb_pixels                                q8
3049
3050 #define pixels_gb_low                            q9
3051
3052 #define colors_r                                 d10
3053 #define colors_g                                 d11
3054 #define colors_b                                 d12
3055 #define draw_mask_bits                           d13
3056 #define texels_r                                 d14
3057 #define texels_g                                 d15
3058 #define pixels_r_low                             d16
3059 #define pixels_g_low                             d18
3060 #define pixels_b_low                             d19
3061 #define msb_mask_low                             d26
3062 #define msb_mask_high                            d27
3063
3064 #define d64_1                                    d28
3065 #define d64_4                                    d29
3066 #define d64_128                                  d30
3067 #define texels_b                                 d31
3068
3069 #define shade_blocks_textured_modulated_prologue_indirect()                    \
3070   mov c_48, #48;                                                               \
3071   add block_ptr_store, psx_gpu, #psx_gpu_blocks_offset                         \
3072
3073 #define shade_blocks_textured_modulated_prologue_direct()                      \
3074   add mask_msb_ptr, psx_gpu, #psx_gpu_mask_msb_offset;                         \
3075   vld1.u16 { msb_mask_low[], msb_mask_high[] }, [ mask_msb_ptr, :16 ]          \
3076
3077
3078 #define shade_blocks_textured_modulated_prologue_shaded(dithering, target)     \
3079   
3080 #define shade_blocks_textured_false_modulation_check_undithered(target)        \
3081   ldr colors_scalar, [ psx_gpu, #psx_gpu_triangle_color_offset ];              \
3082   movw colors_scalar_compare, #0x8080;                                         \
3083                                                                                \
3084   movt colors_scalar_compare, #0x80;                                           \
3085   cmp colors_scalar, colors_scalar_compare;                                    \
3086   beq shade_blocks_textured_unmodulated_##target                               \
3087
3088 #define shade_blocks_textured_false_modulation_check_dithered(target)          \
3089
3090 #define shade_blocks_textured_modulated_prologue_unshaded(dithering, target)   \
3091   shade_blocks_textured_false_modulation_check_##dithering(target);            \
3092   add color_ptr, psx_gpu, #psx_gpu_triangle_color_offset;                      \
3093   vld1.u32 { colors_r[] }, [ color_ptr, :32 ];                                 \
3094   vdup.u8 colors_g, colors_r[1];                                               \
3095   vdup.u8 colors_b, colors_r[2];                                               \
3096   vdup.u8 colors_r, colors_r[0]                                                \
3097
3098
3099 #define shade_blocks_textured_modulated_load_dithered(target)                  \
3100   vld1.u32 { target }, [ block_ptr_load_b, :128 ]                              \
3101
3102 #define shade_blocks_textured_modulated_load_last_dithered(target)             \
3103   vld1.u32 { target }, [ block_ptr_load_b, :128 ], c_32                        \
3104
3105 #define shade_blocks_textured_modulated_load_undithered(target)                \
3106
3107 #define shade_blocks_textured_modulated_load_last_undithered(target)           \
3108   add block_ptr_load_b, block_ptr_load_b, #32                                  \
3109
3110 #define shade_blocks_textured_modulate_dithered(channel)                       \
3111   vmlal.u8 pixels_##channel, texels_##channel, colors_##channel                \
3112
3113 #define shade_blocks_textured_modulate_undithered(channel)                     \
3114   vmull.u8 pixels_##channel, texels_##channel, colors_##channel                \
3115
3116
3117 #define shade_blocks_textured_modulated_store_draw_mask_indirect(offset)       \
3118   vst1.u32 { draw_mask }, [ block_ptr_store, :128 ]!                           \
3119
3120 #define shade_blocks_textured_modulated_store_draw_mask_direct(offset)         \
3121   ldr fb_ptr, [ block_ptr_load_b, #(offset - 64) ];                            \
3122   vld1.u32 { fb_pixels }, [ fb_ptr ];                                          \
3123   vbit.u16 pixels, fb_pixels, draw_mask                                        \
3124
3125 #define shade_blocks_textured_modulated_store_pixels_indirect()                \
3126   vst1.u32 { pixels }, [ block_ptr_store, :128 ], c_48                         \
3127
3128 #define shade_blocks_textured_modulated_store_pixels_direct()                  \
3129   vst1.u32 { pixels }, [ fb_ptr ]                                              \
3130
3131
3132 #define shade_blocks_textured_modulated_load_rg_shaded()                       \
3133   vld1.u32 { colors_r, colors_g }, [ block_ptr_load_b, :128 ], c_32            \
3134
3135 #define shade_blocks_textured_modulated_load_rg_unshaded()                     \
3136   add block_ptr_load_b, block_ptr_load_b, #32                                  \
3137
3138 #define shade_blocks_textured_modulated_load_bdm_shaded()                      \
3139   vld1.u32 { colors_b, draw_mask_bits }, [ block_ptr_load_a, :128 ], c_32      \
3140
3141 #define shade_blocks_textured_modulated_load_bdm_unshaded()                    \
3142   ldr draw_mask_bits_scalar, [ block_ptr_load_a, #8 ];                         \
3143   add block_ptr_load_a, block_ptr_load_a, #32                                  \
3144
3145 #define shade_blocks_textured_modulated_expand_draw_mask_shaded()              \
3146   vdup.u16 draw_mask, draw_mask_bits[0]                                        \
3147
3148 #define shade_blocks_textured_modulated_expand_draw_mask_unshaded()            \
3149   vdup.u16 draw_mask, draw_mask_bits_scalar                                    \
3150
3151
3152 #define shade_blocks_textured_modulated_apply_msb_mask_indirect()              \
3153
3154 #define shade_blocks_textured_modulated_apply_msb_mask_direct()                \
3155   vorr.u16 pixels, pixels, msb_mask                                            \
3156
3157
3158 #define shade_blocks_textured_modulated_builder(shading, dithering, target)    \
3159 .align 3;                                                                      \
3160                                                                                \
3161 function(shade_blocks_##shading##_textured_modulated_##dithering##_##target)   \
3162   shade_blocks_textured_modulated_prologue_##shading(dithering, target);       \
3163   stmdb sp!, { r4 - r5, lr };                                                  \
3164   ldrh num_blocks, [ psx_gpu, #psx_gpu_num_blocks_offset ];                    \
3165                                                                                \
3166   vld1.u32 { test_mask }, [ psx_gpu, :128 ];                                   \
3167                                                                                \
3168   shade_blocks_textured_modulated_prologue_##target();                         \
3169                                                                                \
3170   add block_ptr_load_a, psx_gpu, #psx_gpu_blocks_offset;                       \
3171   mov c_32, #32;                                                               \
3172                                                                                \
3173   add block_ptr_load_b, block_ptr_load_a, #16;                                 \
3174   vmov.u8 d64_1, #1;                                                           \
3175   vmov.u8 d64_4, #4;                                                           \
3176   vmov.u8 d64_128, #128;                                                       \
3177                                                                                \
3178   vld1.u32 { texels }, [ block_ptr_load_a, :128 ], c_32;                       \
3179   vmov.u8 d128_0x07, #0x07;                                                    \
3180                                                                                \
3181   shade_blocks_textured_modulated_load_rg_##shading();                         \
3182   vmov.u8 d128_0x1F, #0x1F;                                                    \
3183                                                                                \
3184   shade_blocks_textured_modulated_load_bdm_##shading();                        \
3185   vmov.u16 d128_0x8000, #0x8000;                                               \
3186                                                                                \
3187   vmovn.u16 texels_r, texels;                                                  \
3188   vshrn.u16 texels_g, texels, #5;                                              \
3189                                                                                \
3190   vshrn.u16 texels_b, texels, #7;                                              \
3191   shade_blocks_textured_modulated_expand_draw_mask_##shading();                \
3192                                                                                \
3193   shade_blocks_textured_modulated_load_##dithering(pixels_r);                  \
3194   vtst.u16 draw_mask, draw_mask, test_mask;                                    \
3195                                                                                \
3196   shade_blocks_textured_modulated_load_##dithering(pixels_g);                  \
3197   vand.u8 texels_rg, texels_rg, d128_0x1F;                                     \
3198                                                                                \
3199   shade_blocks_textured_modulated_load_last_##dithering(pixels_b);             \
3200   vshr.u8 texels_b, texels_b, #3;                                              \
3201                                                                                \
3202   shade_blocks_textured_modulate_##dithering(r);                               \
3203   shade_blocks_textured_modulate_##dithering(g);                               \
3204   shade_blocks_textured_modulate_##dithering(b);                               \
3205                                                                                \
3206   vand.u16 pixels, texels, d128_0x8000;                                        \
3207   vceq.u16 zero_mask, texels, #0;                                              \
3208                                                                                \
3209   vqshrun.s16 pixels_r_low, pixels_r, #4;                                      \
3210   vqshrun.s16 pixels_g_low, pixels_g, #4;                                      \
3211   vqshrun.s16 pixels_b_low, pixels_b, #4;                                      \
3212                                                                                \
3213   shade_blocks_textured_modulated_apply_msb_mask_##target();                   \
3214   vorr.u16 draw_mask, draw_mask, zero_mask;                                    \
3215   vshr.u8 pixels_r_low, pixels_r_low, #3;                                      \
3216   vbic.u8 pixels_gb_low, pixels_gb_low, d128_0x07;                             \
3217                                                                                \
3218   subs num_blocks, num_blocks, #1;                                             \
3219   beq 1f;                                                                      \
3220                                                                                \
3221  .align 3;                                                                     \
3222                                                                                \
3223  0:                                                                            \
3224   vld1.u32 { texels }, [ block_ptr_load_a, :128 ], c_32;                       \
3225   shade_blocks_textured_modulated_load_rg_##shading();                         \
3226   vshrn.u16 texels_g, texels, #5;                                              \
3227                                                                                \
3228   shade_blocks_textured_modulated_load_bdm_##shading();                        \
3229   vshrn.u16 texels_b, texels, #7;                                              \
3230                                                                                \
3231   vmovn.u16 texels_r, texels;                                                  \
3232   vmlal.u8 pixels, pixels_r_low, d64_1;                                        \
3233                                                                                \
3234   vmlal.u8 pixels, pixels_g_low, d64_4;                                        \
3235   vmlal.u8 pixels, pixels_b_low, d64_128;                                      \
3236   shade_blocks_textured_modulated_store_draw_mask_##target(-4);                \
3237                                                                                \
3238   shade_blocks_textured_modulated_load_##dithering(pixels_r);                  \
3239   shade_blocks_textured_modulated_expand_draw_mask_##shading();                \
3240                                                                                \
3241   shade_blocks_textured_modulated_load_##dithering(pixels_g);                  \
3242   vand.u8 texels_rg, texels_rg, d128_0x1F;                                     \
3243                                                                                \
3244   shade_blocks_textured_modulated_load_last_##dithering(pixels_b);             \
3245   vtst.u16 draw_mask, draw_mask, test_mask;                                    \
3246                                                                                \
3247   shade_blocks_textured_modulated_store_pixels_##target();                     \
3248   vshr.u8 texels_b, texels_b, #3;                                              \
3249                                                                                \
3250   shade_blocks_textured_modulate_##dithering(r);                               \
3251   shade_blocks_textured_modulate_##dithering(g);                               \
3252   shade_blocks_textured_modulate_##dithering(b);                               \
3253                                                                                \
3254   vand.u16 pixels, texels, d128_0x8000;                                        \
3255   vceq.u16 zero_mask, texels, #0;                                              \
3256                                                                                \
3257   subs num_blocks, num_blocks, #1;                                             \
3258                                                                                \
3259   vqshrun.s16 pixels_r_low, pixels_r, #4;                                      \
3260   vqshrun.s16 pixels_g_low, pixels_g, #4;                                      \
3261   vqshrun.s16 pixels_b_low, pixels_b, #4;                                      \
3262                                                                                \
3263   shade_blocks_textured_modulated_apply_msb_mask_##target();                   \
3264   vorr.u16 draw_mask, draw_mask, zero_mask;                                    \
3265   vshr.u8 pixels_r_low, pixels_r_low, #3;                                      \
3266   vbic.u8 pixels_gb_low, pixels_gb_low, d128_0x07;                             \
3267                                                                                \
3268   bne 0b;                                                                      \
3269                                                                                \
3270  1:                                                                            \
3271   vmlal.u8 pixels, pixels_r_low, d64_1;                                        \
3272   vmlal.u8 pixels, pixels_g_low, d64_4;                                        \
3273   vmlal.u8 pixels, pixels_b_low, d64_128;                                      \
3274                                                                                \
3275   shade_blocks_textured_modulated_store_draw_mask_##target(28);                \
3276   shade_blocks_textured_modulated_store_pixels_##target();                     \
3277                                                                                \
3278   ldmia sp!, { r4 - r5, pc }                                                   \
3279
3280
3281 shade_blocks_textured_modulated_builder(shaded, dithered, direct);
3282 shade_blocks_textured_modulated_builder(shaded, undithered, direct);
3283 shade_blocks_textured_modulated_builder(unshaded, dithered, direct);
3284 shade_blocks_textured_modulated_builder(unshaded, undithered, direct);
3285
3286 shade_blocks_textured_modulated_builder(shaded, dithered, indirect);
3287 shade_blocks_textured_modulated_builder(shaded, undithered, indirect);
3288 shade_blocks_textured_modulated_builder(unshaded, dithered, indirect);
3289 shade_blocks_textured_modulated_builder(unshaded, undithered, indirect);
3290
3291
3292 #undef c_64
3293 #undef fb_ptr
3294 #undef color_ptr
3295
3296 #undef color_r
3297 #undef color_g
3298 #undef color_b
3299
3300 #undef test_mask
3301 #undef pixels
3302 #undef draw_mask
3303 #undef zero_mask
3304 #undef fb_pixels
3305 #undef msb_mask
3306 #undef msb_mask_low
3307 #undef msb_mask_high
3308
3309 #define psx_gpu                                  r0
3310 #define num_blocks                               r1
3311 #define mask_msb_ptr                             r2
3312 #define color_ptr                                r3
3313
3314 #define block_ptr_load                           r0
3315 #define draw_mask_store_ptr                      r3
3316 #define draw_mask_bits_ptr                       r12
3317 #define draw_mask_ptr                            r12
3318 #define pixel_store_ptr                          r14
3319
3320 #define fb_ptr_cmp                               r4
3321
3322 #define fb_ptr                                   r3
3323 #define fb_ptr_next                              r14
3324
3325 #define c_64                                     r2
3326
3327 #define test_mask                                q0
3328 #define pixels                                   q1
3329 #define draw_mask                                q2
3330 #define zero_mask                                q3
3331 #define draw_mask_combined                       q4
3332 #define fb_pixels                                q5
3333 #define fb_pixels_next                           q6
3334 #define msb_mask                                 q7
3335
3336 #define draw_mask_low                            d4
3337 #define draw_mask_high                           d5
3338 #define msb_mask_low                             d14
3339 #define msb_mask_high                            d15
3340
3341 .align 3
3342 function(shade_blocks_textured_unmodulated_indirect)
3343   str r14, [ sp, #-4 ]
3344   add draw_mask_bits_ptr, psx_gpu, #(psx_gpu_blocks_offset + 40)
3345
3346   ldrh num_blocks, [ psx_gpu, #psx_gpu_num_blocks_offset ]
3347   add pixel_store_ptr, psx_gpu, #(psx_gpu_blocks_offset + 16)
3348
3349   vld1.u32 { test_mask }, [ psx_gpu, :128 ]
3350   add draw_mask_store_ptr, psx_gpu, #psx_gpu_blocks_offset
3351
3352   mov c_64, #64
3353   add block_ptr_load, psx_gpu, #psx_gpu_blocks_offset
3354
3355   vld1.u32 { pixels }, [ block_ptr_load, :128 ], c_64
3356   vld1.u16 { draw_mask_low[], draw_mask_high[] },                              \
3357    [ draw_mask_bits_ptr, :16 ], c_64
3358   vceq.u16 zero_mask, pixels, #0
3359
3360   vtst.u16 draw_mask, draw_mask, test_mask
3361   vst1.u32 { pixels }, [ pixel_store_ptr, :128 ], c_64
3362
3363   subs num_blocks, num_blocks, #1
3364   beq 1f
3365
3366  0:
3367   vld1.u32 { pixels }, [ block_ptr_load, :128 ], c_64
3368   vorr.u16 draw_mask_combined, draw_mask, zero_mask
3369
3370   vld1.u16 { draw_mask_low[], draw_mask_high[] },                              \
3371    [ draw_mask_bits_ptr, :16 ], c_64
3372   vceq.u16 zero_mask, pixels, #0
3373
3374   vtst.u16 draw_mask, draw_mask, test_mask
3375   vst1.u32 { pixels }, [ pixel_store_ptr, :128 ], c_64
3376
3377   vst1.u32 { draw_mask_combined }, [ draw_mask_store_ptr, :128 ], c_64
3378   subs num_blocks, num_blocks, #1
3379
3380   bne 0b
3381
3382  1:
3383   vorr.u16 draw_mask_combined, draw_mask, zero_mask
3384   vst1.u32 { draw_mask_combined }, [ draw_mask_store_ptr, :128 ], c_64
3385
3386   ldr pc, [ sp, #-4 ]
3387
3388
3389 .align 3
3390
3391 function(shade_blocks_textured_unmodulated_direct)
3392   stmdb sp!, { r4, r14 }
3393   add draw_mask_bits_ptr, psx_gpu, #(psx_gpu_blocks_offset + 40)
3394
3395   ldrh num_blocks, [ psx_gpu, #psx_gpu_num_blocks_offset ]
3396   add mask_msb_ptr, psx_gpu, #psx_gpu_mask_msb_offset
3397
3398   vld1.u16 { msb_mask_low[], msb_mask_high[] }, [ mask_msb_ptr, :16 ]
3399   mov c_64, #64
3400
3401   vld1.u32 { test_mask }, [ psx_gpu, :128 ]
3402   add block_ptr_load, psx_gpu, #psx_gpu_blocks_offset
3403
3404   vld1.u16 { draw_mask_low[], draw_mask_high[] },                              \
3405    [ draw_mask_bits_ptr, :16 ], c_64
3406   ldr fb_ptr_next, [ block_ptr_load, #44 ]
3407
3408   vld1.u32 { pixels }, [ block_ptr_load, :128 ], c_64
3409   vld1.u16 { fb_pixels_next }, [ fb_ptr_next ]
3410   vceq.u16 zero_mask, pixels, #0
3411   vtst.u16 draw_mask, draw_mask, test_mask
3412
3413   subs num_blocks, num_blocks, #1
3414   beq 1f
3415
3416  0:
3417   mov fb_ptr, fb_ptr_next
3418   ldr fb_ptr_next, [ block_ptr_load, #44 ]
3419
3420   vorr.u16 pixels, pixels, msb_mask
3421
3422   vorr.u16 draw_mask_combined, draw_mask, zero_mask
3423   vmov fb_pixels, fb_pixels_next
3424
3425   vld1.u16 { draw_mask_low[], draw_mask_high[] },                              \
3426    [ draw_mask_bits_ptr, :16 ], c_64
3427   vbif.u16 fb_pixels, pixels, draw_mask_combined
3428
3429   vld1.u32 { pixels }, [ block_ptr_load, :128 ], c_64
3430
3431   sub fb_ptr_cmp, fb_ptr_next, fb_ptr
3432   add fb_ptr_cmp, fb_ptr_cmp, #14
3433   cmp fb_ptr_cmp, #28
3434   bls 4f
3435
3436   vld1.u16 { fb_pixels_next }, [ fb_ptr_next ]
3437   vceq.u16 zero_mask, pixels, #0
3438
3439   vst1.u16 { fb_pixels }, [ fb_ptr ]
3440   vtst.u16 draw_mask, draw_mask, test_mask
3441
3442  3:
3443   subs num_blocks, num_blocks, #1
3444   bne 0b
3445
3446  1:
3447   vorr.u16 draw_mask_combined, draw_mask, zero_mask
3448   vbif.u16 fb_pixels_next, pixels, draw_mask_combined
3449
3450   vst1.u16 { fb_pixels_next }, [ fb_ptr_next ]
3451
3452   ldmia sp!, { r4, pc }
3453
3454  4:
3455   vst1.u16 { fb_pixels }, [ fb_ptr ]
3456   vceq.u16 zero_mask, pixels, #0
3457
3458   vld1.u16 { fb_pixels_next }, [ fb_ptr_next ]
3459   vtst.u16 draw_mask, draw_mask, test_mask
3460
3461   bal 3b
3462
3463
3464 function(shade_blocks_unshaded_untextured_indirect)
3465   bx lr
3466
3467 .align 3
3468
3469 function(shade_blocks_unshaded_untextured_direct)
3470   stmdb sp!, { r4, r14 }
3471   add draw_mask_ptr, psx_gpu, #psx_gpu_blocks_offset
3472
3473   ldrh num_blocks, [ psx_gpu, #psx_gpu_num_blocks_offset ]
3474   add mask_msb_ptr, psx_gpu, #psx_gpu_mask_msb_offset
3475
3476   vld1.u16 { msb_mask_low[], msb_mask_high[] }, [ mask_msb_ptr, :16 ]
3477   add color_ptr, psx_gpu, #(psx_gpu_blocks_offset + 16)
3478
3479   add block_ptr_load, psx_gpu, #(psx_gpu_blocks_offset + 44)
3480   vld1.u16 { pixels }, [ color_ptr, :128 ]
3481
3482   mov c_64, #64
3483   vld1.u16 { draw_mask }, [ draw_mask_ptr, :128 ], c_64
3484
3485   vorr.u16 pixels, pixels, msb_mask
3486   subs num_blocks, num_blocks, #1
3487
3488   ldr fb_ptr_next, [ block_ptr_load ], #64
3489
3490   vld1.u16 { fb_pixels_next }, [ fb_ptr_next ]
3491   beq 1f
3492
3493  0:
3494   vmov fb_pixels, fb_pixels_next
3495   mov fb_ptr, fb_ptr_next
3496   ldr fb_ptr_next, [ block_ptr_load ], #64
3497
3498   vbif.u16 fb_pixels, pixels, draw_mask
3499   vld1.u16 { draw_mask }, [ draw_mask_ptr, :128 ], c_64
3500
3501   sub fb_ptr_cmp, fb_ptr_next, fb_ptr
3502   add fb_ptr_cmp, fb_ptr_cmp, #14
3503   cmp fb_ptr_cmp, #28
3504   bls 4f
3505
3506   vld1.u16 { fb_pixels_next }, [ fb_ptr_next ]
3507   vst1.u16 { fb_pixels }, [ fb_ptr ]
3508
3509  3:
3510   subs num_blocks, num_blocks, #1
3511   bne 0b
3512
3513  1:
3514   vbif.u16 fb_pixels_next, pixels, draw_mask
3515   vst1.u16 { fb_pixels_next }, [ fb_ptr_next ]
3516
3517   ldmia sp!, { r4, pc }
3518
3519  4:
3520   vst1.u16 { fb_pixels }, [ fb_ptr ]
3521   vld1.u16 { fb_pixels_next }, [ fb_ptr_next ]
3522   bal 3b
3523
3524
3525 #undef draw_mask_ptr
3526 #undef c_64
3527 #undef fb_ptr
3528 #undef fb_ptr_next
3529 #undef fb_ptr_cmp
3530
3531 #define psx_gpu                                  r0
3532 #define num_blocks                               r1
3533 #define msb_mask_ptr                             r2
3534 #define pixel_ptr                                r3
3535 #define draw_mask_ptr                            r0
3536 #define c_64                                     r2
3537 #define fb_ptr                                   r12
3538 #define fb_ptr_next                              r14
3539 #define fb_ptr_cmp                               r4
3540
3541 #undef msb_mask
3542 #undef draw_mask
3543 #undef pixels
3544 #undef fb_pixels
3545 #undef d128_0x8000
3546 #undef msb_mask_low
3547 #undef msb_mask_high
3548 #undef draw_mask_next
3549 #undef pixels_g
3550 #undef blend_pixels
3551 #undef fb_pixels_next
3552
3553 #define msb_mask                                 q0
3554 #define draw_mask                                q1
3555 #define pixels                                   q2
3556 #define fb_pixels                                q3
3557 #define blend_pixels                             q4
3558 #define pixels_no_msb                            q5
3559 #define blend_mask                               q6
3560 #define fb_pixels_no_msb                         q7
3561 #define d128_0x8000                              q8
3562 #define d128_0x0421                              q9
3563 #define fb_pixels_next                           q10
3564 #define blend_pixels_next                        q11
3565 #define pixels_next                              q12
3566 #define draw_mask_next                           q13
3567 #define write_mask                               q14
3568
3569 #define pixels_rb                                q5
3570 #define pixels_mg                                q7
3571 #define pixels_g                                 q7
3572 #define d128_0x7C1F                              q8
3573 #define d128_0x03E0                              q9
3574 #define fb_pixels_rb                             q10
3575 #define fb_pixels_g                              q11
3576 #define fb_pixels_masked                         q11
3577 #define d128_0x83E0                              q15
3578 #define pixels_fourth                            q7
3579 #define d128_0x1C07                              q12
3580 #define d128_0x00E0                              q13
3581 #define d128_0x80E0                              q13
3582
3583 #define msb_mask_low                             d0
3584 #define msb_mask_high                            d1
3585
3586 #define blend_blocks_average_set_blend_mask_textured(source)                   \
3587   vclt.s16 blend_mask, source, #0                                              \
3588
3589 #define blend_blocks_average_set_stp_bit_textured()                            \
3590   vorr.u16 blend_pixels, #0x8000                                               \
3591
3592 #define blend_blocks_average_combine_textured(source)                          \
3593   vbif.u16 blend_pixels, source, blend_mask                                    \
3594   
3595 #define blend_blocks_average_set_blend_mask_untextured(source)                 \
3596
3597 #define blend_blocks_average_set_stp_bit_untextured()                          \
3598
3599 #define blend_blocks_average_combine_untextured(source)                        \
3600
3601 #define blend_blocks_average_mask_set_on()                                     \
3602   vclt.s16 write_mask, fb_pixels_next, #0                                      \
3603
3604 #define blend_blocks_average_mask_copy_on()                                    \
3605   vorr.u16 draw_mask, draw_mask_next, write_mask                               \
3606
3607 #define blend_blocks_average_mask_copy_b_on()                                  \
3608   vorr.u16 draw_mask_next, draw_mask_next, write_mask                          \
3609
3610 #define blend_blocks_average_mask_set_off()                                    \
3611
3612 #define blend_blocks_average_mask_copy_off()                                   \
3613   vmov draw_mask, draw_mask_next                                               \
3614
3615 #define blend_blocks_average_mask_copy_b_off()                                 \
3616
3617 #define blend_blocks_average_builder(texturing, mask_evaluate)                 \
3618 .align 3;                                                                      \
3619                                                                                \
3620 function(blend_blocks_##texturing##_average_##mask_evaluate)                   \
3621   stmdb sp!, { r4, r14 };                                                      \
3622   add mask_msb_ptr, psx_gpu, #psx_gpu_mask_msb_offset;                         \
3623   ldrh num_blocks, [ psx_gpu, #psx_gpu_num_blocks_offset ];                    \
3624                                                                                \
3625   add pixel_ptr, psx_gpu, #(psx_gpu_blocks_offset + 16);                       \
3626   vld1.u16 { msb_mask_low[], msb_mask_high[] }, [ mask_msb_ptr, :16 ];         \
3627                                                                                \
3628   add draw_mask_ptr, psx_gpu, #psx_gpu_blocks_offset;                          \
3629   mov c_64, #64;                                                               \
3630                                                                                \
3631   vmov.u16 d128_0x8000, #0x8000;                                               \
3632   vld1.u32 { draw_mask_next }, [ draw_mask_ptr, :128 ], c_64;                  \
3633   ldr fb_ptr_next, [ pixel_ptr, #28 ];                                         \
3634                                                                                \
3635   vmov.u16 d128_0x0421, #0x0400;                                               \
3636   vld1.u32 { pixels_next }, [ pixel_ptr, :128 ], c_64;                         \
3637                                                                                \
3638   vorr.u16 d128_0x0421, #0x0021;                                               \
3639   vld1.u16 { fb_pixels_next }, [ fb_ptr_next ];                                \
3640                                                                                \
3641   veor.u16 blend_pixels_next, pixels_next, fb_pixels_next;                     \
3642   vbic.u16 pixels_no_msb, pixels_next, d128_0x8000;                            \
3643   vand.u16 blend_pixels_next, blend_pixels_next, d128_0x0421;                  \
3644   vsub.u16 blend_pixels_next, pixels_no_msb, blend_pixels_next;                \
3645   blend_blocks_average_mask_set_##mask_evaluate();                             \
3646   vbic.u16 fb_pixels_no_msb, fb_pixels_next, d128_0x8000;                      \
3647                                                                                \
3648   subs num_blocks, num_blocks, #1;                                             \
3649   beq 1f;                                                                      \
3650                                                                                \
3651  0:                                                                            \
3652   mov fb_ptr, fb_ptr_next;                                                     \
3653   ldr fb_ptr_next, [ pixel_ptr, #28 ];                                         \
3654                                                                                \
3655   vmov pixels, pixels_next;                                                    \
3656   vld1.u32 { pixels_next }, [ pixel_ptr, :128 ], c_64;                         \
3657                                                                                \
3658   vhadd.u16 blend_pixels, fb_pixels_no_msb, blend_pixels_next;                 \
3659                                                                                \
3660   blend_blocks_average_mask_copy_##mask_evaluate();                            \
3661   vld1.u32 { draw_mask_next }, [ draw_mask_ptr, :128 ], c_64;                  \
3662                                                                                \
3663   blend_blocks_average_set_blend_mask_##texturing(pixels);                     \
3664   blend_blocks_average_set_stp_bit_##texturing();                              \
3665   vmov fb_pixels, fb_pixels_next;                                              \
3666   blend_blocks_average_combine_##texturing(pixels);                            \
3667                                                                                \
3668   sub fb_ptr_cmp, fb_ptr_next, fb_ptr;                                         \
3669   add fb_ptr_cmp, fb_ptr_cmp, #14;                                             \
3670   cmp fb_ptr_cmp, #28;                                                         \
3671   bls 2f;                                                                      \
3672                                                                                \
3673   vld1.u16 { fb_pixels_next }, [ fb_ptr_next ];                                \
3674   veor.u16 blend_pixels_next, pixels_next, fb_pixels_next;                     \
3675                                                                                \
3676   vorr.u16 blend_pixels, blend_pixels, msb_mask;                               \
3677   vbic.u16 pixels_no_msb, pixels_next, d128_0x8000;                            \
3678                                                                                \
3679   vand.u16 blend_pixels_next, blend_pixels_next, d128_0x0421;                  \
3680   vbif.u16 fb_pixels, blend_pixels, draw_mask;                                 \
3681                                                                                \
3682   vbic.u16 fb_pixels_no_msb, fb_pixels_next, d128_0x8000;                      \
3683   vsub.u16 blend_pixels_next, pixels_no_msb, blend_pixels_next;                \
3684   blend_blocks_average_mask_set_##mask_evaluate();                             \
3685   vst1.u16 { fb_pixels }, [ fb_ptr ];                                          \
3686                                                                                \
3687  3:                                                                            \
3688   subs num_blocks, num_blocks, #1;                                             \
3689   bne 0b;                                                                      \
3690                                                                                \
3691  1:                                                                            \
3692   blend_blocks_average_mask_copy_b_##mask_evaluate();                          \
3693   vhadd.u16 blend_pixels, fb_pixels_no_msb, blend_pixels_next;                 \
3694                                                                                \
3695   blend_blocks_average_set_blend_mask_##texturing(pixels_next);                \
3696   blend_blocks_average_set_stp_bit_##texturing();                              \
3697   blend_blocks_average_combine_##texturing(pixels_next);                       \
3698                                                                                \
3699   vorr.u16 blend_pixels, blend_pixels, msb_mask;                               \
3700   vbif.u16 fb_pixels_next, blend_pixels, draw_mask_next;                       \
3701   vst1.u16 { fb_pixels_next }, [ fb_ptr_next ];                                \
3702                                                                                \
3703   ldmia sp!, { r4, pc };                                                       \
3704                                                                                \
3705  2:                                                                            \
3706   vorr.u16 blend_pixels, blend_pixels, msb_mask;                               \
3707   vbif.u16 fb_pixels, blend_pixels, draw_mask;                                 \
3708   vst1.u16 { fb_pixels }, [ fb_ptr ];                                          \
3709                                                                                \
3710   vld1.u16 { fb_pixels_next }, [ fb_ptr_next ];                                \
3711   veor.u16 blend_pixels_next, pixels_next, fb_pixels_next;                     \
3712   vbic.u16 pixels_no_msb, pixels_next, d128_0x8000;                            \
3713   vand.u16 blend_pixels_next, blend_pixels_next, d128_0x0421;                  \
3714   vsub.u16 blend_pixels_next, pixels_no_msb, blend_pixels_next;                \
3715   vbic.u16 fb_pixels_no_msb, fb_pixels_next, d128_0x8000;                      \
3716                                                                                \
3717   bal 3b                                                                       \
3718
3719 blend_blocks_average_builder(textured, off)
3720 blend_blocks_average_builder(untextured, off)
3721 blend_blocks_average_builder(textured, on)
3722 blend_blocks_average_builder(untextured, on)
3723
3724
3725 #define blend_blocks_add_mask_set_on()                                         \
3726   vclt.s16 write_mask, fb_pixels, #0                                           \
3727
3728 #define blend_blocks_add_mask_copy_on()                                        \
3729   vorr.u16 draw_mask, draw_mask, write_mask                                    \
3730
3731 #define blend_blocks_add_mask_set_off()                                        \
3732
3733 #define blend_blocks_add_mask_copy_off()                                       \
3734
3735
3736 #define blend_blocks_add_textured_builder(mask_evaluate)                       \
3737 .align 3;                                                                      \
3738                                                                                \
3739 function(blend_blocks_textured_add_##mask_evaluate)                            \
3740   stmdb sp!, { r4, r14 };                                                      \
3741   add mask_msb_ptr, psx_gpu, #psx_gpu_mask_msb_offset;                         \
3742   ldrh num_blocks, [ psx_gpu, #psx_gpu_num_blocks_offset ];                    \
3743                                                                                \
3744   add pixel_ptr, psx_gpu, #(psx_gpu_blocks_offset + 16);                       \
3745   vld1.u16 { msb_mask_low[], msb_mask_high[] }, [ mask_msb_ptr, :16 ];         \
3746                                                                                \
3747   add draw_mask_ptr, psx_gpu, #psx_gpu_blocks_offset;                          \
3748   mov c_64, #64;                                                               \
3749                                                                                \
3750   vmov.u16 d128_0x7C1F, #0x7C00;                                               \
3751   vmov.u16 d128_0x03E0, #0x0300;                                               \
3752   vmov.u16 d128_0x83E0, #0x8000;                                               \
3753   vorr.u16 d128_0x03E0, #0x00E0;                                               \
3754   vorr.u16 d128_0x7C1F, #0x001F;                                               \
3755   vorr.u16 d128_0x83E0, d128_0x83E0, d128_0x03E0;                              \
3756                                                                                \
3757   vld1.u32 { draw_mask }, [ draw_mask_ptr, :128 ], c_64;                       \
3758   ldr fb_ptr_next, [ pixel_ptr, #28 ];                                         \
3759   vld1.u32 { pixels }, [ pixel_ptr, :128 ], c_64;                              \
3760   vclt.s16 blend_mask, pixels, #0;                                             \
3761   vld1.u16 { fb_pixels }, [ fb_ptr_next ];                                     \
3762   blend_blocks_add_mask_set_##mask_evaluate();                                 \
3763   vand.u16 pixels_rb, pixels, d128_0x7C1F;                                     \
3764                                                                                \
3765   blend_blocks_add_mask_copy_##mask_evaluate();                                \
3766   vorr.u16 pixels, pixels, msb_mask;                                           \
3767   vand.u16 fb_pixels_masked, fb_pixels, blend_mask;                            \
3768   vand.u16 pixels_mg, pixels, d128_0x83E0;                                     \
3769   vand.u16 fb_pixels_rb, fb_pixels_masked, d128_0x7C1F;                        \
3770   vand.u16 fb_pixels_g, fb_pixels_masked, d128_0x03E0;                         \
3771   vadd.u16 fb_pixels_rb, fb_pixels_rb, pixels_rb;                              \
3772   vadd.u16 fb_pixels_g, fb_pixels_g, pixels_mg;                                \
3773   vmin.u8 fb_pixels_rb, fb_pixels_rb, d128_0x7C1F;                             \
3774   vmin.u16 fb_pixels_g, fb_pixels_g, d128_0x83E0;                              \
3775                                                                                \
3776   subs num_blocks, num_blocks, #1;                                             \
3777   beq 1f;                                                                      \
3778                                                                                \
3779  0:                                                                            \
3780   mov fb_ptr, fb_ptr_next;                                                     \
3781                                                                                \
3782   ldr fb_ptr_next, [ pixel_ptr, #28 ];                                         \
3783                                                                                \
3784   vld1.u32 { pixels }, [ pixel_ptr, :128 ], c_64;                              \
3785   vclt.s16 blend_mask, pixels, #0;                                             \
3786                                                                                \
3787   vorr.u16 pixels, pixels, msb_mask;                                           \
3788   vorr.u16 blend_pixels, fb_pixels_rb, fb_pixels_g;                            \
3789   vand.u16 pixels_mg, pixels, d128_0x83E0;                                     \
3790                                                                                \
3791   vbit.u16 blend_pixels, fb_pixels, draw_mask;                                 \
3792   vld1.u32 { draw_mask }, [ draw_mask_ptr, :128 ], c_64;                       \
3793                                                                                \
3794   sub fb_ptr_cmp, fb_ptr_next, fb_ptr;                                         \
3795   add fb_ptr_cmp, fb_ptr_cmp, #14;                                             \
3796   cmp fb_ptr_cmp, #28;                                                         \
3797   bls 2f;                                                                      \
3798                                                                                \
3799   vld1.u16 { fb_pixels }, [ fb_ptr_next ];                                     \
3800   blend_blocks_add_mask_set_##mask_evaluate();                                 \
3801   vand.u16 fb_pixels_masked, fb_pixels, blend_mask;                            \
3802   blend_blocks_add_mask_copy_##mask_evaluate();                                \
3803   vand.u16 pixels_rb, pixels, d128_0x7C1F;                                     \
3804   vand.u16 fb_pixels_rb, fb_pixels_masked, d128_0x7C1F;                        \
3805   vst1.u16 { blend_pixels }, [ fb_ptr ];                                       \
3806                                                                                \
3807  3:                                                                            \
3808   vand.u16 fb_pixels_g, fb_pixels_masked, d128_0x03E0;                         \
3809   vadd.u16 fb_pixels_rb, fb_pixels_rb, pixels_rb;                              \
3810   vadd.u16 fb_pixels_g, fb_pixels_g, pixels_mg;                                \
3811   vmin.u8 fb_pixels_rb, fb_pixels_rb, d128_0x7C1F;                             \
3812   vmin.u16 fb_pixels_g, fb_pixels_g, d128_0x83E0;                              \
3813                                                                                \
3814   subs num_blocks, num_blocks, #1;                                             \
3815   bne 0b;                                                                      \
3816                                                                                \
3817  1:                                                                            \
3818   vorr.u16 blend_pixels, fb_pixels_rb, fb_pixels_g;                            \
3819   vbit.u16 blend_pixels, fb_pixels, draw_mask;                                 \
3820   vst1.u16 { blend_pixels }, [ fb_ptr_next ];                                  \
3821                                                                                \
3822   ldmia sp!, { r4, pc };                                                       \
3823                                                                                \
3824  2:                                                                            \
3825   vst1.u16 { blend_pixels }, [ fb_ptr ];                                       \
3826   vand.u16 pixels_rb, pixels, d128_0x7C1F;                                     \
3827                                                                                \
3828   vld1.u16 { fb_pixels }, [ fb_ptr_next ];                                     \
3829   blend_blocks_add_mask_set_##mask_evaluate();                                 \
3830   vand.u16 fb_pixels_masked, fb_pixels, blend_mask;                            \
3831   blend_blocks_add_mask_copy_##mask_evaluate();                                \
3832   vand.u16 fb_pixels_rb, fb_pixels_masked, d128_0x7C1F;                        \
3833   bal 3b                                                                       \
3834
3835
3836 #define blend_blocks_add_untextured_builder(mask_evaluate)                     \
3837 .align 3;                                                                      \
3838                                                                                \
3839 function(blend_blocks_untextured_add_##mask_evaluate)                          \
3840   stmdb sp!, { r4, r14 };                                                      \
3841   add mask_msb_ptr, psx_gpu, #psx_gpu_mask_msb_offset;                         \
3842   ldrh num_blocks, [ psx_gpu, #psx_gpu_num_blocks_offset ];                    \
3843                                                                                \
3844   add pixel_ptr, psx_gpu, #(psx_gpu_blocks_offset + 16);                       \
3845   vld1.u16 { msb_mask_low[], msb_mask_high[] }, [ mask_msb_ptr, :16 ];         \
3846                                                                                \
3847   add draw_mask_ptr, psx_gpu, #psx_gpu_blocks_offset;                          \
3848   mov c_64, #64;                                                               \
3849                                                                                \
3850   vmov.u16 d128_0x7C1F, #0x7C00;                                               \
3851   vmov.u16 d128_0x03E0, #0x0300;                                               \
3852   vorr.u16 d128_0x7C1F, #0x001F;                                               \
3853   vorr.u16 d128_0x03E0, #0x00E0;                                               \
3854                                                                                \
3855   vld1.u32 { draw_mask }, [ draw_mask_ptr, :128 ], c_64;                       \
3856   ldr fb_ptr_next, [ pixel_ptr, #28 ];                                         \
3857   vld1.u32 { pixels }, [ pixel_ptr, :128 ], c_64;                              \
3858   vld1.u16 { fb_pixels }, [ fb_ptr_next ];                                     \
3859   blend_blocks_add_mask_set_##mask_evaluate();                                 \
3860   vand.u16 pixels_rb, pixels, d128_0x7C1F;                                     \
3861                                                                                \
3862   blend_blocks_add_mask_copy_##mask_evaluate();                                \
3863   vand.u16 pixels_g, pixels, d128_0x03E0;                                      \
3864   vand.u16 fb_pixels_rb, fb_pixels, d128_0x7C1F;                               \
3865   vand.u16 fb_pixels_g, fb_pixels, d128_0x03E0;                                \
3866   vadd.u16 fb_pixels_rb, fb_pixels_rb, pixels_rb;                              \
3867   vadd.u16 fb_pixels_g, fb_pixels_g, pixels_g;                                 \
3868   vmin.u8 fb_pixels_rb, fb_pixels_rb, d128_0x7C1F;                             \
3869   vmin.u16 fb_pixels_g, fb_pixels_g, d128_0x03E0;                              \
3870                                                                                \
3871   subs num_blocks, num_blocks, #1;                                             \
3872   beq 1f;                                                                      \
3873                                                                                \
3874  0:                                                                            \
3875   mov fb_ptr, fb_ptr_next;                                                     \
3876                                                                                \
3877   ldr fb_ptr_next, [ pixel_ptr, #28 ];                                         \
3878                                                                                \
3879   vld1.u32 { pixels }, [ pixel_ptr, :128 ], c_64;                              \
3880                                                                                \
3881   vorr.u16 blend_pixels, fb_pixels_rb, fb_pixels_g;                            \
3882   vorr.u16 blend_pixels, blend_pixels, msb_mask;                               \
3883   vand.u16 pixels_g, pixels, d128_0x03E0;                                      \
3884                                                                                \
3885   vbit.u16 blend_pixels, fb_pixels, draw_mask;                                 \
3886   vld1.u32 { draw_mask }, [ draw_mask_ptr, :128 ], c_64;                       \
3887                                                                                \
3888   sub fb_ptr_cmp, fb_ptr_next, fb_ptr;                                         \
3889   add fb_ptr_cmp, fb_ptr_cmp, #14;                                             \
3890   cmp fb_ptr_cmp, #28;                                                         \
3891   bls 2f;                                                                      \
3892                                                                                \
3893   vld1.u16 { fb_pixels }, [ fb_ptr_next ];                                     \
3894   blend_blocks_add_mask_set_##mask_evaluate();                                 \
3895   blend_blocks_add_mask_copy_##mask_evaluate();                                \
3896   vand.u16 pixels_rb, pixels, d128_0x7C1F;                                     \
3897   vand.u16 fb_pixels_rb, fb_pixels, d128_0x7C1F;                               \
3898   vst1.u16 { blend_pixels }, [ fb_ptr ];                                       \
3899                                                                                \
3900  3:                                                                            \
3901   vand.u16 fb_pixels_g, fb_pixels, d128_0x03E0;                                \
3902   vadd.u16 fb_pixels_rb, fb_pixels_rb, pixels_rb;                              \
3903   vadd.u16 fb_pixels_g, fb_pixels_g, pixels_g;                                 \
3904   vmin.u8 fb_pixels_rb, fb_pixels_rb, d128_0x7C1F;                             \
3905   vmin.u16 fb_pixels_g, fb_pixels_g, d128_0x03E0;                              \
3906                                                                                \
3907   subs num_blocks, num_blocks, #1;                                             \
3908   bne 0b;                                                                      \
3909                                                                                \
3910  1:                                                                            \
3911   vorr.u16 blend_pixels, fb_pixels_rb, fb_pixels_g;                            \
3912   vorr.u16 blend_pixels, blend_pixels, msb_mask;                               \
3913   vbit.u16 blend_pixels, fb_pixels, draw_mask;                                 \
3914   vst1.u16 { blend_pixels }, [ fb_ptr_next ];                                  \
3915                                                                                \
3916   ldmia sp!, { r4, pc };                                                       \
3917                                                                                \
3918  2:                                                                            \
3919   vst1.u16 { blend_pixels }, [ fb_ptr ];                                       \
3920   vand.u16 pixels_rb, pixels, d128_0x7C1F;                                     \
3921                                                                                \
3922   vld1.u16 { fb_pixels }, [ fb_ptr_next ];                                     \
3923   blend_blocks_add_mask_set_##mask_evaluate();                                 \
3924   blend_blocks_add_mask_copy_##mask_evaluate();                                \
3925   vand.u16 fb_pixels_rb, fb_pixels, d128_0x7C1F;                               \
3926   bal 3b                                                                       \
3927
3928
3929 blend_blocks_add_textured_builder(off)
3930 blend_blocks_add_textured_builder(on)
3931 blend_blocks_add_untextured_builder(off)
3932 blend_blocks_add_untextured_builder(on)
3933
3934 #define blend_blocks_subtract_set_blend_mask_textured()                        \
3935   vclt.s16 blend_mask, pixels_next, #0                                         \
3936
3937 #define blend_blocks_subtract_combine_textured()                               \
3938   vbif.u16 blend_pixels, pixels, blend_mask                                    \
3939
3940 #define blend_blocks_subtract_set_stb_textured()                               \
3941   vorr.u16 blend_pixels, #0x8000                                               \
3942
3943 #define blend_blocks_subtract_msb_mask_textured()                              \
3944   vorr.u16 pixels, pixels_next, msb_mask                                       \
3945
3946 #define blend_blocks_subtract_set_blend_mask_untextured()                      \
3947
3948 #define blend_blocks_subtract_combine_untextured()                             \
3949
3950 #define blend_blocks_subtract_set_stb_untextured()                             \
3951   vorr.u16 blend_pixels, blend_pixels, msb_mask                                \
3952
3953 #define blend_blocks_subtract_msb_mask_untextured()                            \
3954
3955
3956 #define blend_blocks_subtract_mask_set_on()                                    \
3957   vclt.s16 write_mask, fb_pixels, #0                                           \
3958
3959 #define blend_blocks_subtract_mask_copy_on()                                   \
3960   vorr.u16 draw_mask, draw_mask_next, write_mask                               \
3961
3962 #define blend_blocks_subtract_mask_set_off()                                   \
3963
3964 #define blend_blocks_subtract_mask_copy_off()                                  \
3965   vmov draw_mask, draw_mask_next                                               \
3966
3967
3968 #define blend_blocks_subtract_builder(texturing, mask_evaluate)                \
3969 .align 3;                                                                      \
3970                                                                                \
3971 function(blend_blocks_##texturing##_subtract_##mask_evaluate)                  \
3972   stmdb sp!, { r4, r14 };                                                      \
3973   add mask_msb_ptr, psx_gpu, #psx_gpu_mask_msb_offset;                         \
3974   ldrh num_blocks, [ psx_gpu, #psx_gpu_num_blocks_offset ];                    \
3975                                                                                \
3976   add pixel_ptr, psx_gpu, #(psx_gpu_blocks_offset + 16);                       \
3977   vld1.u16 { msb_mask_low[], msb_mask_high[] }, [ mask_msb_ptr, :16 ];         \
3978                                                                                \
3979   add draw_mask_ptr, psx_gpu, #psx_gpu_blocks_offset;                          \
3980   mov c_64, #64;                                                               \
3981                                                                                \
3982   vmov.u16 d128_0x7C1F, #0x7C00;                                               \
3983   vmov.u16 d128_0x03E0, #0x0300;                                               \
3984   vorr.u16 d128_0x7C1F, #0x001F;                                               \
3985   vorr.u16 d128_0x03E0, #0x00E0;                                               \
3986                                                                                \
3987   vld1.u32 { draw_mask_next }, [ draw_mask_ptr, :128 ], c_64;                  \
3988   ldr fb_ptr_next, [ pixel_ptr, #28 ];                                         \
3989   vld1.u32 { pixels_next }, [ pixel_ptr, :128 ], c_64;                         \
3990   blend_blocks_subtract_set_blend_mask_##texturing();                          \
3991   vld1.u16 { fb_pixels }, [ fb_ptr_next ];                                     \
3992   blend_blocks_subtract_mask_set_##mask_evaluate();                            \
3993   vand.u16 pixels_rb, pixels_next, d128_0x7C1F;                                \
3994                                                                                \
3995   vand.u16 pixels_g, pixels_next, d128_0x03E0;                                 \
3996   vand.u16 fb_pixels_rb, fb_pixels, d128_0x7C1F;                               \
3997   vand.u16 fb_pixels_g, fb_pixels, d128_0x03E0;                                \
3998   vqsub.u8 fb_pixels_rb, fb_pixels_rb, pixels_rb;                              \
3999   vqsub.u16 fb_pixels_g, fb_pixels_g, pixels_g;                                \
4000                                                                                \
4001   subs num_blocks, num_blocks, #1;                                             \
4002   beq 1f;                                                                      \
4003                                                                                \
4004  0:                                                                            \
4005   blend_blocks_subtract_mask_copy_##mask_evaluate();                           \
4006   mov fb_ptr, fb_ptr_next;                                                     \
4007   ldr fb_ptr_next, [ pixel_ptr, #28 ];                                         \
4008                                                                                \
4009   vld1.u32 { draw_mask_next }, [ draw_mask_ptr, :128 ], c_64;                  \
4010   blend_blocks_subtract_msb_mask_##texturing();                                \
4011                                                                                \
4012   vld1.u32 { pixels_next }, [ pixel_ptr, :128 ], c_64;                         \
4013   vorr.u16 blend_pixels, fb_pixels_rb, fb_pixels_g;                            \
4014   vand.u16 pixels_rb, pixels_next, d128_0x7C1F;                                \
4015   blend_blocks_subtract_set_stb_##texturing();                                 \
4016   vand.u16 pixels_g, pixels_next, d128_0x03E0;                                 \
4017   blend_blocks_subtract_combine_##texturing();                                 \
4018   blend_blocks_subtract_set_blend_mask_##texturing();                          \
4019   vbit.u16 blend_pixels, fb_pixels, draw_mask;                                 \
4020                                                                                \
4021   sub fb_ptr_cmp, fb_ptr_next, fb_ptr;                                         \
4022   add fb_ptr_cmp, fb_ptr_cmp, #14;                                             \
4023   cmp fb_ptr_cmp, #28;                                                         \
4024   bls 2f;                                                                      \
4025                                                                                \
4026   vld1.u16 { fb_pixels }, [ fb_ptr_next ];                                     \
4027   blend_blocks_subtract_mask_set_##mask_evaluate();                            \
4028   vand.u16 fb_pixels_rb, fb_pixels, d128_0x7C1F;                               \
4029   vand.u16 fb_pixels_g, fb_pixels, d128_0x03E0;                                \
4030   vqsub.u8 fb_pixels_rb, fb_pixels_rb, pixels_rb;                              \
4031   vst1.u16 { blend_pixels }, [ fb_ptr ];                                       \
4032   vqsub.u16 fb_pixels_g, fb_pixels_g, pixels_g;                                \
4033                                                                                \
4034  3:                                                                            \
4035   subs num_blocks, num_blocks, #1;                                             \
4036   bne 0b;                                                                      \
4037                                                                                \
4038  1:                                                                            \
4039   blend_blocks_subtract_mask_copy_##mask_evaluate();                           \
4040                                                                                \
4041   blend_blocks_subtract_msb_mask_##texturing();                                \
4042   vorr.u16 blend_pixels, fb_pixels_rb, fb_pixels_g;                            \
4043   blend_blocks_subtract_set_stb_##texturing();                                 \
4044   blend_blocks_subtract_combine_##texturing();                                 \
4045   vbit.u16 blend_pixels, fb_pixels, draw_mask;                                 \
4046   vst1.u16 { blend_pixels }, [ fb_ptr_next ];                                  \
4047                                                                                \
4048   ldmia sp!, { r4, pc };                                                       \
4049                                                                                \
4050  2:                                                                            \
4051   vst1.u16 { blend_pixels }, [ fb_ptr ];                                       \
4052   vld1.u16 { fb_pixels }, [ fb_ptr_next ];                                     \
4053   blend_blocks_subtract_mask_set_##mask_evaluate();                            \
4054   vand.u16 fb_pixels_rb, fb_pixels, d128_0x7C1F;                               \
4055   vand.u16 fb_pixels_g, fb_pixels, d128_0x03E0;                                \
4056   vqsub.u8 fb_pixels_rb, fb_pixels_rb, pixels_rb;                              \
4057   vqsub.u16 fb_pixels_g, fb_pixels_g, pixels_g;                                \
4058   bal 3b                                                                       \
4059
4060
4061 blend_blocks_subtract_builder(textured, off)
4062 blend_blocks_subtract_builder(textured, on)
4063 blend_blocks_subtract_builder(untextured, off)
4064 blend_blocks_subtract_builder(untextured, on)
4065
4066
4067 #define blend_blocks_add_fourth_textured_builder(mask_evaluate)                \
4068 .align 3;                                                                      \
4069                                                                                \
4070 function(blend_blocks_textured_add_fourth_##mask_evaluate)                     \
4071   stmdb sp!, { r4, r14 };                                                      \
4072   add mask_msb_ptr, psx_gpu, #psx_gpu_mask_msb_offset;                         \
4073   ldrh num_blocks, [ psx_gpu, #psx_gpu_num_blocks_offset ];                    \
4074                                                                                \
4075   add pixel_ptr, psx_gpu, #(psx_gpu_blocks_offset + 16);                       \
4076   vld1.u16 { msb_mask_low[], msb_mask_high[] }, [ mask_msb_ptr, :16 ];         \
4077                                                                                \
4078   add draw_mask_ptr, psx_gpu, #psx_gpu_blocks_offset;                          \
4079   mov c_64, #64;                                                               \
4080                                                                                \
4081   vmov.u16 d128_0x7C1F, #0x7C00;                                               \
4082   vmov.u16 d128_0x03E0, #0x0300;                                               \
4083   vmov.u16 d128_0x83E0, #0x8300;                                               \
4084   vmov.u16 d128_0x1C07, #0x1C00;                                               \
4085   vmov.u16 d128_0x80E0, #0x8000;                                               \
4086   vorr.u16 d128_0x7C1F, #0x001F;                                               \
4087   vorr.u16 d128_0x03E0, #0x00E0;                                               \
4088   vorr.u16 d128_0x83E0, #0x00E0;                                               \
4089   vorr.u16 d128_0x1C07, #0x0007;                                               \
4090   vorr.u16 d128_0x80E0, #0x00E0;                                               \
4091                                                                                \
4092   vld1.u32 { draw_mask }, [ draw_mask_ptr, :128 ], c_64;                       \
4093   ldr fb_ptr_next, [ pixel_ptr, #28 ];                                         \
4094   vld1.u32 { pixels }, [ pixel_ptr, :128 ], c_64;                              \
4095   vclt.s16 blend_mask, pixels, #0;                                             \
4096   vld1.u16 { fb_pixels }, [ fb_ptr_next ];                                     \
4097   blend_blocks_add_mask_set_##mask_evaluate();                                 \
4098   vshr.s16 pixels_fourth, pixels, #2;                                          \
4099                                                                                \
4100   blend_blocks_add_mask_copy_##mask_evaluate();                                \
4101   vorr.u16 pixels, pixels, msb_mask;                                           \
4102   vand.u16 pixels_rb, pixels_fourth, d128_0x1C07;                              \
4103   vand.u16 fb_pixels_masked, fb_pixels, blend_mask;                            \
4104   vand.u16 pixels_mg, pixels_fourth, d128_0x80E0;                              \
4105   vand.u16 fb_pixels_rb, fb_pixels_masked, d128_0x7C1F;                        \
4106   vand.u16 fb_pixels_g, fb_pixels_masked, d128_0x03E0;                         \
4107   vadd.u16 fb_pixels_rb, fb_pixels_rb, pixels_rb;                              \
4108   vadd.u16 fb_pixels_g, fb_pixels_g, pixels_mg;                                \
4109   vmin.u8 fb_pixels_rb, fb_pixels_rb, d128_0x7C1F;                             \
4110   vmin.u16 fb_pixels_g, fb_pixels_g, d128_0x83E0;                              \
4111                                                                                \
4112   subs num_blocks, num_blocks, #1;                                             \
4113   beq 1f;                                                                      \
4114                                                                                \
4115  0:                                                                            \
4116   mov fb_ptr, fb_ptr_next;                                                     \
4117                                                                                \
4118   ldr fb_ptr_next, [ pixel_ptr, #28 ];                                         \
4119                                                                                \
4120   vld1.u32 { pixels }, [ pixel_ptr, :128 ], c_64;                              \
4121   vclt.s16 blend_mask, pixels, #0;                                             \
4122                                                                                \
4123   vshr.s16 pixels_fourth, pixels, #2;                                          \
4124   vorr.u16 pixels, pixels, msb_mask;                                           \
4125   vorr.u16 blend_pixels, fb_pixels_rb, fb_pixels_g;                            \
4126   vand.u16 pixels_rb, pixels_fourth, d128_0x1C07;                              \
4127                                                                                \
4128   vbit.u16 blend_pixels, fb_pixels, draw_mask;                                 \
4129   vld1.u32 { draw_mask }, [ draw_mask_ptr, :128 ], c_64;                       \
4130                                                                                \
4131   sub fb_ptr_cmp, fb_ptr_next, fb_ptr;                                         \
4132   add fb_ptr_cmp, fb_ptr_cmp, #14;                                             \
4133   cmp fb_ptr_cmp, #28;                                                         \
4134   bls 2f;                                                                      \
4135                                                                                \
4136   vld1.u16 { fb_pixels }, [ fb_ptr_next ];                                     \
4137   blend_blocks_add_mask_set_##mask_evaluate();                                 \
4138   vand.u16 fb_pixels_masked, fb_pixels, blend_mask;                            \
4139   blend_blocks_add_mask_copy_##mask_evaluate();                                \
4140   vand.u16 pixels_mg, pixels_fourth, d128_0x80E0;                              \
4141   vand.u16 fb_pixels_rb, fb_pixels_masked, d128_0x7C1F;                        \
4142   vst1.u16 { blend_pixels }, [ fb_ptr ];                                       \
4143                                                                                \
4144  3:                                                                            \
4145   vand.u16 fb_pixels_g, fb_pixels_masked, d128_0x03E0;                         \
4146   vadd.u16 fb_pixels_rb, fb_pixels_rb, pixels_rb;                              \
4147   vadd.u16 fb_pixels_g, fb_pixels_g, pixels_mg;                                \
4148   vmin.u8 fb_pixels_rb, fb_pixels_rb, d128_0x7C1F;                             \
4149   vmin.u16 fb_pixels_g, fb_pixels_g, d128_0x83E0;                              \
4150                                                                                \
4151   subs num_blocks, num_blocks, #1;                                             \
4152   bne 0b;                                                                      \
4153                                                                                \
4154  1:                                                                            \
4155   vorr.u16 blend_pixels, fb_pixels_rb, fb_pixels_g;                            \
4156   vbit.u16 blend_pixels, fb_pixels, draw_mask;                                 \
4157   vst1.u16 { blend_pixels }, [ fb_ptr_next ];                                  \
4158                                                                                \
4159   ldmia sp!, { r4, pc };                                                       \
4160                                                                                \
4161  2:                                                                            \
4162   vst1.u16 { blend_pixels }, [ fb_ptr ];                                       \
4163   vand.u16 pixels_mg, pixels_fourth, d128_0x80E0;                              \
4164                                                                                \
4165   vld1.u16 { fb_pixels }, [ fb_ptr_next ];                                     \
4166   blend_blocks_add_mask_set_##mask_evaluate();                                 \
4167   vand.u16 fb_pixels_masked, fb_pixels, blend_mask;                            \
4168   blend_blocks_add_mask_copy_##mask_evaluate();                                \
4169   vand.u16 fb_pixels_rb, fb_pixels_masked, d128_0x7C1F;                        \
4170   bal 3b                                                                       \
4171
4172
4173 #define blend_blocks_add_fourth_untextured_builder(mask_evaluate)              \
4174 .align 3;                                                                      \
4175                                                                                \
4176 function(blend_blocks_untextured_add_fourth_##mask_evaluate)                   \
4177   stmdb sp!, { r4, r14 };                                                      \
4178   add mask_msb_ptr, psx_gpu, #psx_gpu_mask_msb_offset;                         \
4179   ldrh num_blocks, [ psx_gpu, #psx_gpu_num_blocks_offset ];                    \
4180                                                                                \
4181   add pixel_ptr, psx_gpu, #(psx_gpu_blocks_offset + 16);                       \
4182   vld1.u16 { msb_mask_low[], msb_mask_high[] }, [ mask_msb_ptr, :16 ];         \
4183                                                                                \
4184   add draw_mask_ptr, psx_gpu, #psx_gpu_blocks_offset;                          \
4185   mov c_64, #64;                                                               \
4186                                                                                \
4187   vmov.u16 d128_0x7C1F, #0x7C00;                                               \
4188   vmov.u16 d128_0x03E0, #0x0300;                                               \
4189   vmov.u16 d128_0x83E0, #0x8300;                                               \
4190   vmov.u16 d128_0x1C07, #0x1C00;                                               \
4191   vmov.u16 d128_0x00E0, #0x00E0;                                               \
4192   vorr.u16 d128_0x7C1F, #0x001F;                                               \
4193   vorr.u16 d128_0x03E0, #0x00E0;                                               \
4194   vorr.u16 d128_0x83E0, #0x00E0;                                               \
4195   vorr.u16 d128_0x1C07, #0x0007;                                               \
4196                                                                                \
4197   vld1.u32 { draw_mask }, [ draw_mask_ptr, :128 ], c_64;                       \
4198   ldr fb_ptr_next, [ pixel_ptr, #28 ];                                         \
4199   vld1.u32 { pixels }, [ pixel_ptr, :128 ], c_64;                              \
4200   vld1.u16 { fb_pixels }, [ fb_ptr_next ];                                     \
4201   blend_blocks_add_mask_set_##mask_evaluate();                                 \
4202   vshr.s16 pixels_fourth, pixels, #2;                                          \
4203   vand.u16 pixels_rb, pixels_fourth, d128_0x1C07;                              \
4204                                                                                \
4205   blend_blocks_add_mask_copy_##mask_evaluate();                                \
4206   vand.u16 pixels_g, pixels_fourth, d128_0x00E0;                               \
4207   vand.u16 fb_pixels_rb, fb_pixels, d128_0x7C1F;                               \
4208   vand.u16 fb_pixels_g, fb_pixels, d128_0x03E0;                                \
4209   vadd.u16 fb_pixels_rb, fb_pixels_rb, pixels_rb;                              \
4210   vadd.u16 fb_pixels_g, fb_pixels_g, pixels_g;                                 \
4211   vmin.u8 fb_pixels_rb, fb_pixels_rb, d128_0x7C1F;                             \
4212   vmin.u16 fb_pixels_g, fb_pixels_g, d128_0x03E0;                              \
4213                                                                                \
4214   subs num_blocks, num_blocks, #1;                                             \
4215   beq 1f;                                                                      \
4216                                                                                \
4217  0:                                                                            \
4218   mov fb_ptr, fb_ptr_next;                                                     \
4219                                                                                \
4220   ldr fb_ptr_next, [ pixel_ptr, #28 ];                                         \
4221                                                                                \
4222   vld1.u32 { pixels }, [ pixel_ptr, :128 ], c_64;                              \
4223                                                                                \
4224   vorr.u16 blend_pixels, fb_pixels_rb, fb_pixels_g;                            \
4225   vshr.s16 pixels_fourth, pixels, #2;                                          \
4226   vorr.u16 blend_pixels, blend_pixels, msb_mask;                               \
4227   vand.u16 pixels_rb, pixels_fourth, d128_0x1C07;                              \
4228                                                                                \
4229   vbit.u16 blend_pixels, fb_pixels, draw_mask;                                 \
4230   vld1.u32 { draw_mask }, [ draw_mask_ptr, :128 ], c_64;                       \
4231                                                                                \
4232   sub fb_ptr_cmp, fb_ptr_next, fb_ptr;                                         \
4233   add fb_ptr_cmp, fb_ptr_cmp, #14;                                             \
4234   cmp fb_ptr_cmp, #28;                                                         \
4235   bls 2f;                                                                      \
4236                                                                                \
4237   vld1.u16 { fb_pixels }, [ fb_ptr_next ];                                     \
4238   blend_blocks_add_mask_set_##mask_evaluate();                                 \
4239   blend_blocks_add_mask_copy_##mask_evaluate();                                \
4240   vand.u16 pixels_g, pixels_fourth, d128_0x00E0;                               \
4241   vand.u16 fb_pixels_rb, fb_pixels, d128_0x7C1F;                               \
4242   vst1.u16 { blend_pixels }, [ fb_ptr ];                                       \
4243                                                                                \
4244  3:                                                                            \
4245   vand.u16 fb_pixels_g, fb_pixels, d128_0x03E0;                                \
4246   vadd.u16 fb_pixels_rb, fb_pixels_rb, pixels_rb;                              \
4247   vadd.u16 fb_pixels_g, fb_pixels_g, pixels_g;                                 \
4248   vmin.u8 fb_pixels_rb, fb_pixels_rb, d128_0x7C1F;                             \
4249   vmin.u16 fb_pixels_g, fb_pixels_g, d128_0x03E0;                              \
4250                                                                                \
4251   subs num_blocks, num_blocks, #1;                                             \
4252   bne 0b;                                                                      \
4253                                                                                \
4254  1:                                                                            \
4255   vorr.u16 blend_pixels, fb_pixels_rb, fb_pixels_g;                            \
4256   vorr.u16 blend_pixels, blend_pixels, msb_mask;                               \
4257   vbit.u16 blend_pixels, fb_pixels, draw_mask;                                 \
4258   vst1.u16 { blend_pixels }, [ fb_ptr_next ];                                  \
4259                                                                                \
4260   ldmia sp!, { r4, pc };                                                       \
4261                                                                                \
4262  2:                                                                            \
4263   vst1.u16 { blend_pixels }, [ fb_ptr ];                                       \
4264   vand.u16 pixels_g, pixels_fourth, d128_0x00E0;                               \
4265                                                                                \
4266   vld1.u16 { fb_pixels }, [ fb_ptr_next ];                                     \
4267   blend_blocks_add_mask_set_##mask_evaluate();                                 \
4268   blend_blocks_add_mask_copy_##mask_evaluate();                                \
4269   vand.u16 fb_pixels_rb, fb_pixels, d128_0x7C1F;                               \
4270   bal 3b                                                                       \
4271
4272
4273 blend_blocks_add_fourth_textured_builder(off)
4274 blend_blocks_add_fourth_textured_builder(on)
4275 blend_blocks_add_fourth_untextured_builder(off)
4276 blend_blocks_add_fourth_untextured_builder(on)
4277
4278 // TODO: Optimize this more. Need a scene that actually uses it for
4279 // confirmation..
4280
4281 .align 3
4282
4283 function(blend_blocks_textured_unblended_on)         
4284   stmdb sp!, { r4, r14 }
4285   add mask_msb_ptr, psx_gpu, #psx_gpu_mask_msb_offset
4286   ldrh num_blocks, [ psx_gpu, #psx_gpu_num_blocks_offset ]
4287
4288   add pixel_ptr, psx_gpu, #(psx_gpu_blocks_offset + 16)
4289   vld1.u16 { msb_mask_low[], msb_mask_high[] }, [ mask_msb_ptr, :16 ]
4290
4291   add draw_mask_ptr, psx_gpu, #psx_gpu_blocks_offset
4292   mov c_64, #64
4293
4294   ldr fb_ptr, [ pixel_ptr, #28 ]
4295   vld1.u16 { fb_pixels }, [ fb_ptr ]
4296   vld1.u32 { draw_mask }, [ draw_mask_ptr, :128 ], c_64
4297   vclt.s16 write_mask, fb_pixels, #0
4298   vld1.u32 { pixels }, [ pixel_ptr, :128 ], c_64
4299
4300   subs num_blocks, num_blocks, #1
4301   beq 1f
4302
4303  0:
4304   vorr.u16 draw_mask, draw_mask, write_mask
4305   vbif.u16 fb_pixels, pixels, draw_mask
4306   vst1.u16 { fb_pixels }, [ fb_ptr ]
4307
4308   ldr fb_ptr, [ pixel_ptr, #28 ]
4309   vld1.u16 { fb_pixels }, [ fb_ptr ]
4310   vld1.u32 { draw_mask }, [ draw_mask_ptr, :128 ], c_64
4311   vclt.s16 write_mask, fb_pixels, #0
4312   vld1.u32 { pixels }, [ pixel_ptr, :128 ], c_64
4313
4314   subs num_blocks, num_blocks, #1
4315   bne 0b
4316  
4317  1:
4318   vorr.u16 draw_mask, draw_mask, write_mask
4319   vbif.u16 fb_pixels, pixels, draw_mask
4320   vst1.u16 { fb_pixels }, [ fb_ptr ]
4321
4322   ldmia sp!, { r4, pc }
4323
4324
4325 function(blend_blocks_textured_unblended_off)
4326   bx lr
4327
4328
4329 function(warmup)
4330   mov r3, #64
4331   cmp r0, #0
4332   bxeq lr
4333
4334  0:
4335   vld1.u32 { u_whole_8, v_whole_8 }, [ r1, :128 ], r3
4336
4337   subs r0, r0, #1
4338   bne 0b
4339
4340   bx lr
4341
4342 #undef color
4343 #undef y
4344 #undef height
4345
4346 #define psx_gpu                                           r0
4347 #define color                                             r1
4348 #define x                                                 r2
4349 #define y                                                 r3
4350
4351 #define vram_ptr                                          r0
4352 #define width                                             r3
4353 #define height                                            r12
4354
4355 #define parameter_width_offset                            0
4356 #define parameter_height_offset                           4
4357
4358 #define color_r                                           r14
4359 #define color_g                                           r4
4360 #define color_b                                           r5  
4361
4362 #define left_unaligned                                    r14
4363 #define right_unaligned                                   r4
4364 #define pitch                                             r5
4365 #define num_unaligned                                     r2
4366 #define num_width                                         r6
4367
4368 #undef colors
4369
4370 #define colors                                            q0
4371
4372 .align 3
4373
4374 function(render_block_fill_body)
4375   ldr vram_ptr, [ psx_gpu, #psx_gpu_vram_ptr_offset ]
4376   ldr height, [ sp, #parameter_height_offset ]
4377
4378   add vram_ptr, vram_ptr, y, lsl #11
4379   ldr width, [ sp, #parameter_width_offset ]
4380
4381   add vram_ptr, vram_ptr, x, lsl #1
4382   stmdb sp!, { r4 - r6, r14 }
4383
4384   ubfx color_r, color, #3, #5
4385   ubfx color_g, color, #11, #5
4386
4387   ubfx color_b, color, #19, #5
4388   orr color, color_r, color_g, lsl #5
4389
4390   orr color, color, color_b, lsl #10
4391   add left_unaligned, x, #0x7
4392
4393   bic left_unaligned, left_unaligned, #0x7
4394   vdup.u16 colors, color
4395
4396   sub left_unaligned, left_unaligned, x
4397   mov pitch, #2048
4398
4399   sub pitch, pitch, width, lsl #1
4400   sub width, width, left_unaligned
4401
4402   and right_unaligned, width, #0x7
4403   bic width, width, #0x7
4404
4405  0:
4406   mov num_width, width, lsr #3
4407
4408   movs num_unaligned, left_unaligned
4409   beq 2f
4410
4411  1:
4412   strh color, [ vram_ptr ], #2
4413
4414   subs num_unaligned, num_unaligned, #1
4415   bne 1b
4416
4417  2:
4418   vst1.u32 { colors }, [ vram_ptr, :128 ]!
4419   subs num_width, num_width, #1
4420   bne 2b
4421
4422   movs num_unaligned, right_unaligned
4423   beq 4f
4424
4425  3:
4426   strh color, [ vram_ptr ], #2
4427   
4428   subs num_unaligned, num_unaligned, #1
4429   bne 3b
4430
4431  4:
4432   add vram_ptr, vram_ptr, pitch
4433   subs height, height, #1
4434   bne 0b
4435   
4436   ldmia sp!, { r4 - r6, pc }
4437
4438
4439 #undef x
4440 #undef y
4441 #undef width
4442 #undef height
4443 #undef fb_ptr
4444 #undef texture_mask
4445 #undef num_blocks
4446 #undef temp
4447 #undef dirty_textures_mask
4448 #undef clut_ptr
4449 #undef current_texture_mask
4450
4451 #define psx_gpu                                           r0
4452 #define x                                                 r1
4453 #define y                                                 r2
4454 #define u                                                 r3
4455 #define v                                                 r4
4456 #define width                                             r5
4457 #define height                                            r6
4458 #define offset_u                                          r8
4459 #define offset_v                                          r9
4460 #define offset_u_right                                    r10
4461 #define width_rounded                                     r11
4462 #define height_rounded                                    r12
4463
4464 #define texture_offset_base                               r1
4465 #define tile_width                                        r2
4466 #define tile_height                                       r3
4467 #define num_blocks                                        r4
4468 #define block                                             r5
4469 #define sub_tile_height                                   r6
4470 #define fb_ptr                                            r7
4471 #define texture_mask                                      r8
4472 #define column_data                                       r9
4473 #define texture_offset                                    r10
4474 #define tiles_remaining                                   r11
4475 #define fb_ptr_advance_column                             r12
4476 #define texture_block_ptr                                 r14
4477
4478 #define texture_page_ptr                                  r3
4479 #define left_block_mask                                   r4
4480 #define right_block_mask                                  r5
4481 #define texture_mask_rev                                  r10
4482 #define control_mask                                      r11
4483
4484 #define dirty_textures_mask                               r4
4485 #define clut_ptr                                          r5
4486 #define current_texture_mask                              r6
4487
4488
4489 #undef texels
4490 #undef clut_low_a
4491 #undef clut_low_b
4492 #undef clut_high_a
4493 #undef clut_high_b
4494 #undef clut_a
4495 #undef clut_b
4496 #undef texels_low
4497 #undef texels_high
4498
4499 #define texels                                            d0
4500 #define draw_masks_fb_ptrs                                q1
4501
4502 #define draw_mask_fb_ptr_left                             d2
4503 #define draw_mask_fb_ptr_right                            d3
4504
4505 #define clut_low_a                                        d4
4506 #define clut_low_b                                        d5
4507 #define clut_high_a                                       d6
4508 #define clut_high_b                                       d7
4509
4510 #define block_masks                                       d8
4511 #define block_masks_shifted                               d9
4512
4513 #define clut_a                                            q2
4514 #define clut_b                                            q3
4515
4516 #define texels_low                                        d10
4517 #define texels_high                                       d11
4518
4519
4520 setup_sprite_flush_blocks_single:
4521   vpush { q1 - q4 }
4522
4523   stmdb sp!, { r0 - r3, r12, r14 }
4524   bl flush_render_block_buffer
4525   ldmia sp!, { r0 - r3, r12, r14 }
4526
4527   vpop { q1 - q4 }
4528
4529   add block, psx_gpu, #psx_gpu_blocks_offset
4530
4531   mov num_blocks, sub_tile_height
4532   bx lr
4533
4534
4535 setup_sprite_flush_blocks_double:
4536   vpush { q1 - q4 }
4537
4538   stmdb sp!, { r0 - r3, r12, r14 }
4539   bl flush_render_block_buffer
4540   ldmia sp!, { r0 - r3, r12, r14 }
4541
4542   vpop { q1 - q4 }
4543
4544   add block, psx_gpu, #psx_gpu_blocks_offset
4545
4546   mov num_blocks, sub_tile_height, lsl #1
4547   bx lr
4548
4549
4550 setup_sprite_update_texture_4bpp_cache:
4551   stmdb sp!, { r0 - r3, r14 }
4552   bl update_texture_4bpp_cache
4553   ldmia sp!, { r0 - r3, pc }
4554
4555
4556 setup_sprite_update_texture_8bpp_cache:
4557   stmdb sp!, { r0 - r3, r14 }
4558   bl update_texture_8bpp_cache
4559   ldmia sp!, { r0 - r3, pc }
4560
4561
4562 #define setup_sprite_tiled_initialize_4bpp()                                   \
4563   ldr dirty_textures_mask,                                                     \
4564    [ psx_gpu, #psx_gpu_dirty_textures_4bpp_mask_offset ];                      \
4565   ldr clut_ptr, [ psx_gpu, #psx_gpu_clut_ptr_offset ];                         \
4566                                                                                \
4567   ldr current_texture_mask, [ psx_gpu, #psx_gpu_current_texture_mask_offset ]; \
4568   vld1.u32 { clut_a, clut_b }, [ clut_ptr, :128 ];                             \
4569                                                                                \
4570   tst current_texture_mask, dirty_textures_mask;                               \
4571   vuzp.u8 clut_a, clut_b;                                                      \
4572                                                                                \
4573   blne setup_sprite_update_texture_4bpp_cache                                  \
4574
4575 #define setup_sprite_tiled_initialize_8bpp()                                   \
4576   ldr dirty_textures_mask,                                                     \
4577    [ psx_gpu, #psx_gpu_dirty_textures_8bpp_mask_offset ];                      \
4578   ldr current_texture_mask, [ psx_gpu, #psx_gpu_current_texture_mask_offset ]; \
4579                                                                                \
4580   tst current_texture_mask, dirty_textures_mask;                               \
4581   blne setup_sprite_update_texture_8bpp_cache                                  \
4582
4583
4584 #define setup_sprite_tile_setup_block_no(side, offset, texture_mode)           \
4585
4586 #define setup_sprite_block_count_single()                                      \
4587   sub_tile_height                                                              \
4588
4589 #define setup_sprite_block_count_double()                                      \
4590   sub_tile_height, lsl #1                                                      \
4591
4592 #define setup_sprite_tile_add_blocks(type)                                     \
4593   add num_blocks, num_blocks, setup_sprite_block_count_##type();               \
4594   cmp num_blocks, #MAX_BLOCKS;                                                 \
4595                                                                                \
4596   blgt setup_sprite_flush_blocks_##type                                        \
4597
4598
4599 #define setup_sprite_tile_full_4bpp(edge)                                      \
4600   setup_sprite_tile_add_blocks(double);                                        \
4601                                                                                \
4602  4:                                                                            \
4603   and texture_block_ptr, texture_offset, texture_mask;                         \
4604   vmov.u32 draw_mask_fb_ptr_left[1], fb_ptr;                                   \
4605                                                                                \
4606   pld [ fb_ptr ];                                                              \
4607   add texture_block_ptr, texture_page_ptr, texture_block_ptr;                  \
4608   vld1.u32 { texels }, [ texture_block_ptr, :64 ];                             \
4609                                                                                \
4610   vtbl.8 texels_low, { clut_low_a, clut_low_b }, texels;                       \
4611   vtbl.8 texels_high, { clut_high_a, clut_high_b }, texels;                    \
4612                                                                                \
4613   vst2.u8 { texels_low, texels_high }, [ block, :128 ];                        \
4614   add texture_block_ptr, texture_offset, #8;                                   \
4615                                                                                \
4616   and texture_block_ptr, texture_block_ptr, texture_mask;                      \
4617   add block, block, #40;                                                       \
4618                                                                                \
4619   add texture_block_ptr, texture_page_ptr, texture_block_ptr;                  \
4620   add fb_ptr, fb_ptr, #16;                                                     \
4621                                                                                \
4622   vst1.u32 { draw_mask_fb_ptr_left }, [ block, :64 ];                          \
4623   add block, block, #24;                                                       \
4624                                                                                \
4625   vld1.u32 { texels }, [ texture_block_ptr, :64 ];                             \
4626   vtbl.8 texels_low, { clut_low_a, clut_low_b }, texels;                       \
4627                                                                                \
4628   pld [ fb_ptr ];                                                              \
4629   vmov.u32 draw_mask_fb_ptr_right[1], fb_ptr;                                  \
4630   vtbl.8 texels_high, { clut_high_a, clut_high_b }, texels;                    \
4631                                                                                \
4632   vst2.u8 { texels_low, texels_high }, [ block, :128 ];                        \
4633   add block, block, #40;                                                       \
4634                                                                                \
4635   add texture_offset, texture_offset, #0x10;                                   \
4636   add fb_ptr, fb_ptr, #(2048 - 16);                                            \
4637                                                                                \
4638   vst1.u32 { draw_mask_fb_ptr_right }, [ block, :64 ];                         \
4639   add block, block, #24;                                                       \
4640                                                                                \
4641   subs sub_tile_height, sub_tile_height, #1;                                   \
4642   bne 4b;                                                                      \
4643                                                                                \
4644   add texture_offset, texture_offset, #0xF00;                                  \
4645   strh num_blocks, [ psx_gpu, #psx_gpu_num_blocks_offset ]                     \
4646
4647   
4648 #define setup_sprite_tile_half_4bpp(edge)                                      \
4649   setup_sprite_tile_add_blocks(single);                                        \
4650                                                                                \
4651  4:                                                                            \
4652   and texture_block_ptr, texture_offset, texture_mask;                         \
4653   vmov.u32 draw_mask_fb_ptr_##edge[1], fb_ptr;                                 \
4654                                                                                \
4655   pld [ fb_ptr ];                                                              \
4656   add texture_block_ptr, texture_page_ptr, texture_block_ptr;                  \
4657   vld1.u32 { texels }, [ texture_block_ptr, :64 ];                             \
4658                                                                                \
4659   vtbl.8 texels_low, { clut_low_a, clut_low_b }, texels;                       \
4660   vtbl.8 texels_high, { clut_high_a, clut_high_b }, texels;                    \
4661                                                                                \
4662   vst2.u8 { texels_low, texels_high }, [ block, :128 ];                        \
4663   add block, block, #40;                                                       \
4664                                                                                \
4665   add texture_block_ptr, texture_page_ptr, texture_block_ptr;                  \
4666   vst1.u32 { draw_mask_fb_ptr_##edge }, [ block, :64 ];                        \
4667                                                                                \
4668   add block, block, #24;                                                       \
4669   add texture_offset, texture_offset, #0x10;                                   \
4670                                                                                \
4671   add fb_ptr, fb_ptr, #2048;                                                   \
4672   subs sub_tile_height, sub_tile_height, #1;                                   \
4673                                                                                \
4674   bne 4b;                                                                      \
4675                                                                                \
4676   add texture_offset, texture_offset, #0xF00;                                  \
4677   strh num_blocks, [ psx_gpu, #psx_gpu_num_blocks_offset ]                     \
4678  
4679  
4680 #define setup_sprite_tile_full_8bpp(edge)                                      \
4681   setup_sprite_tile_add_blocks(double);                                        \
4682   add block, block, #16;                                                       \
4683                                                                                \
4684  4:                                                                            \
4685   and texture_block_ptr, texture_offset, texture_mask;                         \
4686   vmov.u32 draw_mask_fb_ptr_left[1], fb_ptr;                                   \
4687                                                                                \
4688   pld [ fb_ptr ];                                                              \
4689   add texture_block_ptr, texture_page_ptr, texture_block_ptr;                  \
4690   vld1.u32 { texels }, [ texture_block_ptr, :64 ];                             \
4691                                                                                \
4692   add texture_block_ptr, texture_offset, #8;                                   \
4693   vst1.u32 { texels }, [ block, :64 ];                                         \
4694                                                                                \
4695   and texture_block_ptr, texture_block_ptr, texture_mask;                      \
4696   add block, block, #24;                                                       \
4697                                                                                \
4698   add texture_block_ptr, texture_page_ptr, texture_block_ptr;                  \
4699                                                                                \
4700   add fb_ptr, fb_ptr, #16;                                                     \
4701   vst1.u32 { draw_mask_fb_ptr_left }, [ block, :64 ];                          \
4702                                                                                \
4703   add block, block, #40;                                                       \
4704   vld1.u32 { texels }, [ texture_block_ptr, :64 ];                             \
4705   pld [ fb_ptr ];                                                              \
4706                                                                                \
4707   vmov.u32 draw_mask_fb_ptr_right[1], fb_ptr;                                  \
4708   vst1.u32 { texels }, [ block, :64 ];                                         \
4709   add block, block, #24;                                                       \
4710                                                                                \
4711   add texture_offset, texture_offset, #0x10;                                   \
4712   add fb_ptr, fb_ptr, #(2048 - 16);                                            \
4713                                                                                \
4714   vst1.u32 { draw_mask_fb_ptr_right }, [ block, :64 ];                         \
4715   add block, block, #40;                                                       \
4716                                                                                \
4717   subs sub_tile_height, sub_tile_height, #1;                                   \
4718   bne 4b;                                                                      \
4719                                                                                \
4720   sub block, block, #16;                                                       \
4721   add texture_offset, texture_offset, #0xF00;                                  \
4722   strh num_blocks, [ psx_gpu, #psx_gpu_num_blocks_offset ]                     \
4723
4724   
4725 #define setup_sprite_tile_half_8bpp(edge)                                      \
4726   setup_sprite_tile_add_blocks(single);                                        \
4727   add block, block, #16;                                                       \
4728                                                                                \
4729  4:                                                                            \
4730   and texture_block_ptr, texture_offset, texture_mask;                         \
4731   vmov.u32 draw_mask_fb_ptr_##edge[1], fb_ptr;                                 \
4732   pld [ fb_ptr ];                                                              \
4733                                                                                \
4734   add texture_block_ptr, texture_page_ptr, texture_block_ptr;                  \
4735   vld1.u32 { texels }, [ texture_block_ptr, :64 ];                             \
4736                                                                                \
4737   vst1.u32 { texels }, [ block, :64 ];                                         \
4738   add block, block, #24;                                                       \
4739                                                                                \
4740   vst1.u32 { draw_mask_fb_ptr_##edge }, [ block, :64 ];                        \
4741   add block, block, #40;                                                       \
4742                                                                                \
4743   add texture_offset, texture_offset, #0x10;                                   \
4744   add fb_ptr, fb_ptr, #2048;                                                   \
4745                                                                                \
4746   subs sub_tile_height, sub_tile_height, #1;                                   \
4747   bne 4b;                                                                      \
4748                                                                                \
4749   sub block, block, #16;                                                       \
4750   add texture_offset, texture_offset, #0xF00;                                  \
4751   strh num_blocks, [ psx_gpu, #psx_gpu_num_blocks_offset ]                     \
4752
4753  
4754 #define setup_sprite_tile_column_edge_pre_adjust_half_right()                  \
4755   add texture_offset, texture_offset_base, #8;                                 \
4756   add fb_ptr, fb_ptr, #16                                                      \
4757
4758 #define setup_sprite_tile_column_edge_pre_adjust_half_left()                   \
4759   mov texture_offset, texture_offset_base                                      \
4760
4761 #define setup_sprite_tile_column_edge_pre_adjust_half(edge)                    \
4762   setup_sprite_tile_column_edge_pre_adjust_half_##edge()                       \
4763
4764 #define setup_sprite_tile_column_edge_pre_adjust_full(edge)                    \
4765   mov texture_offset, texture_offset_base                                      \
4766
4767 #define setup_sprite_tile_column_edge_post_adjust_half_right()                 \
4768   sub fb_ptr, fb_ptr, #16                                                      \
4769
4770 #define setup_sprite_tile_column_edge_post_adjust_half_left()                  \
4771
4772 #define setup_sprite_tile_column_edge_post_adjust_half(edge)                   \
4773   setup_sprite_tile_column_edge_post_adjust_half_##edge()                      \
4774
4775 #define setup_sprite_tile_column_edge_post_adjust_full(edge)                   \
4776
4777
4778 #define setup_sprite_tile_column_height_single(edge_mode, edge, texture_mode)  \
4779   mov sub_tile_height, column_data;                                            \
4780   setup_sprite_tile_column_edge_pre_adjust_##edge_mode(edge);                  \
4781   setup_sprite_tile_##edge_mode##_##texture_mode(edge);                        \
4782   setup_sprite_tile_column_edge_post_adjust_##edge_mode(edge)                  \
4783
4784 #define setup_sprite_tile_column_height_multi(edge_mode, edge, texture_mode)   \
4785   and sub_tile_height, column_data, #0xFF;                                     \
4786   mov tiles_remaining, column_data, lsr #16;                                   \
4787   setup_sprite_tile_column_edge_pre_adjust_##edge_mode(edge);                  \
4788   setup_sprite_tile_##edge_mode##_##texture_mode(edge);                        \
4789                                                                                \
4790   subs tiles_remaining, tiles_remaining, #1;                                   \
4791   beq 2f;                                                                      \
4792                                                                                \
4793  3:                                                                            \
4794   mov sub_tile_height, #16;                                                    \
4795   setup_sprite_tile_##edge_mode##_##texture_mode(edge);                        \
4796   subs tiles_remaining, tiles_remaining, #1;                                   \
4797   bne 3b;                                                                      \
4798                                                                                \
4799  2:                                                                            \
4800   uxtb sub_tile_height, column_data, ror #8;                                   \
4801   setup_sprite_tile_##edge_mode##_##texture_mode(edge);                        \
4802   setup_sprite_tile_column_edge_post_adjust_##edge_mode(edge)                  \
4803
4804
4805 #define setup_sprite_column_data_single()                                      \
4806   mov column_data, height;                                                     \
4807   ldr texture_page_ptr, [ psx_gpu, #psx_gpu_texture_page_ptr_offset ]          \
4808
4809 #define setup_sprite_column_data_multi()                                       \
4810   and height_rounded, height_rounded, #0xF;                                    \
4811   rsb column_data, offset_v, #16;                                              \
4812                                                                                \
4813   add height_rounded, height_rounded, #1;                                      \
4814   sub tile_height, tile_height, #1;                                            \
4815                                                                                \
4816   orr column_data, column_data, tile_height, lsl #16;                          \
4817   ldr texture_page_ptr, [ psx_gpu, #psx_gpu_texture_page_ptr_offset ];         \
4818                                                                                \
4819   orr column_data, column_data, height_rounded, lsl #8                         \
4820
4821 #define setup_sprite_tile_column_width_single(texture_mode, multi_height,      \
4822  edge_mode, edge)                                                              \
4823  setup_sprite_##texture_mode##_single_##multi_height##_##edge_mode##_##edge:   \
4824   setup_sprite_column_data_##multi_height();                                   \
4825   vext.32 block_masks_shifted, block_masks, block_masks, #1;                   \
4826   vorr.u32 block_masks, block_masks, block_masks_shifted;                      \
4827   vdup.u8 draw_mask_fb_ptr_left, block_masks[0];                               \
4828   vdup.u8 draw_mask_fb_ptr_right, block_masks[1];                              \
4829                                                                                \
4830   setup_sprite_tile_column_height_##multi_height(edge_mode, edge,              \
4831    texture_mode);                                                              \
4832   ldmia sp!, { r4 - r11, pc }                                                  \
4833
4834 #define setup_sprite_tiled_advance_column()                                    \
4835   add texture_offset_base, texture_offset_base, #0x100;                        \
4836   tst texture_offset_base, #0xF00;                                             \
4837   subeq texture_offset_base, texture_offset_base, #(0x100 + 0xF00)             \
4838
4839 #define setup_sprite_tile_column_width_multi(tm, multi_height, left_mode,      \
4840  right_mode)                                                                   \
4841  setup_sprite_##tm##_multi_##multi_height##_##left_mode##_##right_mode:        \
4842   setup_sprite_column_data_##multi_height();                                   \
4843   mov fb_ptr_advance_column, #32;                                              \
4844                                                                                \
4845   sub fb_ptr_advance_column, height, lsl #11;                                  \
4846   vdup.u8 draw_mask_fb_ptr_left, block_masks[0];                               \
4847                                                                                \
4848   vdup.u8 draw_mask_fb_ptr_right, block_masks[1];                              \
4849   setup_sprite_tile_column_height_##multi_height(left_mode, right, tm);        \
4850                                                                                \
4851   subs tile_width, tile_width, #2;                                             \
4852   add fb_ptr, fb_ptr, fb_ptr_advance_column;                                   \
4853                                                                                \
4854   vmov.u8 draw_masks_fb_ptrs, #0;                                              \
4855   beq 1f;                                                                      \
4856                                                                                \
4857  0:                                                                            \
4858   setup_sprite_tiled_advance_column();                                         \
4859   setup_sprite_tile_column_height_##multi_height(full, none, tm);              \
4860   add fb_ptr, fb_ptr, fb_ptr_advance_column;                                   \
4861   subs tile_width, tile_width, #1;                                             \
4862   bne 0b;                                                                      \
4863                                                                                \
4864  1:                                                                            \
4865   vdup.u8 draw_mask_fb_ptr_left, block_masks[4];                               \
4866   vdup.u8 draw_mask_fb_ptr_right, block_masks[5];                              \
4867                                                                                \
4868   setup_sprite_tiled_advance_column();                                         \
4869   setup_sprite_tile_column_height_##multi_height(right_mode, left, tm);        \
4870   ldmia sp!, { r4 - r11, pc }                                                  \
4871
4872
4873 // r0: psx_gpu
4874 // r1: x
4875 // r2: y
4876 // r3: u
4877 // [ sp ]: v
4878 // [ sp + 4 ]: width
4879 // [ sp + 8 ]: height
4880 // [ sp + 12 ]: color (unused)
4881
4882 #define setup_sprite_tiled_builder(texture_mode)                               \
4883                                                                                \
4884 setup_sprite_tile_column_width_multi(texture_mode,  multi,  full, full);       \
4885 setup_sprite_tile_column_width_single(texture_mode, multi,  full, none);       \
4886 setup_sprite_tile_column_width_multi(texture_mode,  single, full, full);       \
4887 setup_sprite_tile_column_width_single(texture_mode, single, full, none);       \
4888 setup_sprite_tile_column_width_multi(texture_mode,  multi,  half, full);       \
4889 setup_sprite_tile_column_width_single(texture_mode, multi,  half, right);      \
4890 setup_sprite_tile_column_width_multi(texture_mode,  single, half, full);       \
4891 setup_sprite_tile_column_width_single(texture_mode, single, half, right);      \
4892 setup_sprite_tile_column_width_multi(texture_mode,  multi,  full, half);       \
4893 setup_sprite_tile_column_width_single(texture_mode, multi,  half, left);       \
4894 setup_sprite_tile_column_width_multi(texture_mode,  single, full, half);       \
4895 setup_sprite_tile_column_width_single(texture_mode, single, half, left);       \
4896 setup_sprite_tile_column_width_multi(texture_mode,  multi,  half, half);       \
4897 setup_sprite_tile_column_width_multi(texture_mode,  single, half, half);       \
4898                                                                                \
4899 .align 4;                                                                      \
4900                                                                                \
4901 function(setup_sprite_##texture_mode)                                          \
4902   stmdb sp!, { r4 - r11, r14 };                                                \
4903   setup_sprite_tiled_initialize_##texture_mode();                              \
4904                                                                                \
4905   ldr v, [ sp, #36 ];                                                          \
4906   and offset_u, u, #0xF;                                                       \
4907                                                                                \
4908   ldr width, [ sp, #40 ];                                                      \
4909   ldr fb_ptr, [ psx_gpu, #psx_gpu_vram_ptr_offset ];                           \
4910                                                                                \
4911   ldr height, [ sp, #44 ];                                                     \
4912   add fb_ptr, fb_ptr, y, lsl #11;                                              \
4913                                                                                \
4914   add fb_ptr, fb_ptr, x, lsl #1;                                               \
4915   and offset_v, v, #0xF;                                                       \
4916                                                                                \
4917   sub fb_ptr, fb_ptr, offset_u, lsl #1;                                        \
4918   add width_rounded, offset_u, width;                                          \
4919                                                                                \
4920   add height_rounded, offset_v, height;                                        \
4921   add width_rounded, width_rounded, #15;                                       \
4922                                                                                \
4923   add height_rounded, height_rounded, #15;                                     \
4924   mov tile_width, width_rounded, lsr #4;                                       \
4925                                                                                \
4926   /* texture_offset_base = VH-VL-00-00                                       */\
4927   mov texture_offset_base, v, lsl #8;                                          \
4928   and offset_u_right, width_rounded, #0xF;                                     \
4929                                                                                \
4930   /* texture_offset_base = VH-UH-UL-00                                       */\
4931   bfi texture_offset_base, u, #4, #8;                                          \
4932   movw right_block_mask, #0xFFFE;                                              \
4933                                                                                \
4934   /* texture_offset_base = VH-UH-VL-00                                       */\
4935   bfi texture_offset_base, v, #4, #4;                                          \
4936   movw left_block_mask, #0xFFFF;                                               \
4937                                                                                \
4938   mov tile_height, height_rounded, lsr #4;                                     \
4939   mvn left_block_mask, left_block_mask, lsl offset_u;                          \
4940                                                                                \
4941   /* texture_mask = HH-HL-WH-WL                                              */\
4942   ldrh texture_mask, [ psx_gpu, #psx_gpu_texture_mask_width_offset ];          \
4943   mov right_block_mask, right_block_mask, lsl offset_u_right;                  \
4944                                                                                \
4945   /* texture_mask_rev = WH-WL-HH-HL                                          */\
4946   rev16 texture_mask_rev, texture_mask;                                        \
4947   vmov block_masks, left_block_mask, right_block_mask;                         \
4948                                                                                \
4949   /* texture_mask = HH-HL-HL-WL                                              */\
4950   bfi texture_mask, texture_mask_rev, #4, #4;                                  \
4951   /* texture_mask_rev = 00-00-00-WH                                          */\
4952   mov texture_mask_rev, texture_mask_rev, lsr #12;                             \
4953                                                                                \
4954   /* texture_mask = HH-WH-HL-WL                                              */\
4955   bfi texture_mask, texture_mask_rev, #8, #4;                                  \
4956   and left_block_mask, left_block_mask, #0xFF;                                 \
4957                                                                                \
4958   mov control_mask, #0;                                                        \
4959   cmp left_block_mask, #0xFF;                                                  \
4960                                                                                \
4961   uxtb right_block_mask, right_block_mask, ror #8;                             \
4962   orreq control_mask, control_mask, #0x4;                                      \
4963                                                                                \
4964   ldrh num_blocks, [ psx_gpu, #psx_gpu_num_blocks_offset ];                    \
4965   cmp right_block_mask, #0xFF;                                                 \
4966                                                                                \
4967   orreq control_mask, control_mask, #0x8;                                      \
4968   cmp tile_width, #1;                                                          \
4969                                                                                \
4970   add block, psx_gpu, #psx_gpu_blocks_offset;                                  \
4971   orreq control_mask, control_mask, #0x1;                                      \
4972                                                                                \
4973   cmp tile_height, #1;                                                         \
4974   add block, block, num_blocks, lsl #6;                                        \
4975                                                                                \
4976   orreq control_mask, control_mask, #0x2;                                      \
4977   ldr pc, [ pc, control_mask, lsl #2 ];                                        \
4978   nop;                                                                         \
4979                                                                                \
4980  .word setup_sprite_##texture_mode##_multi_multi_full_full;                    \
4981  .word setup_sprite_##texture_mode##_single_multi_full_none;                   \
4982  .word setup_sprite_##texture_mode##_multi_single_full_full;                   \
4983  .word setup_sprite_##texture_mode##_single_single_full_none;                  \
4984  .word setup_sprite_##texture_mode##_multi_multi_half_full;                    \
4985  .word setup_sprite_##texture_mode##_single_multi_half_right;                  \
4986  .word setup_sprite_##texture_mode##_multi_single_half_full;                   \
4987  .word setup_sprite_##texture_mode##_single_single_half_right;                 \
4988  .word setup_sprite_##texture_mode##_multi_multi_full_half;                    \
4989  .word setup_sprite_##texture_mode##_single_multi_half_left;                   \
4990  .word setup_sprite_##texture_mode##_multi_single_full_half;                   \
4991  .word setup_sprite_##texture_mode##_single_single_half_left;                  \
4992  .word setup_sprite_##texture_mode##_multi_multi_half_half;                    \
4993  .word 0x00000000;                                                             \
4994  .word setup_sprite_##texture_mode##_multi_single_half_half                    \
4995
4996
4997 setup_sprite_tiled_builder(4bpp);
4998 setup_sprite_tiled_builder(8bpp);
4999
5000
5001 #undef block_ptr
5002 #undef num_blocks
5003 #undef clut_ptr
5004
5005 #define psx_gpu                                           r0
5006 #define block_ptr                                         r0
5007 #define num_blocks                                        r1
5008 #define clut_ptr                                          r2
5009 #define texel_shift_mask                                  r3
5010 #define block_pixels_a                                    r4
5011 #define block_pixels_b                                    r5
5012 #define texel_0                                           r6
5013 #define texel_2                                           r7
5014 #define texel_4                                           r8
5015 #define texel_6                                           r9
5016 #define texel_1                                           r10
5017 #define texel_3                                           r11
5018 #define texel_5                                           r12
5019 #define texel_7                                           r14
5020 #define texels_01                                         r6
5021 #define texels_23                                         r7
5022 #define texels_45                                         r8
5023 #define texels_67                                         r9
5024
5025 function(texture_sprite_blocks_8bpp)
5026   stmdb sp!, { r4 - r11, r14 }
5027   movw texel_shift_mask, #(0xFF << 1)
5028
5029   ldrh num_blocks, [ psx_gpu, #psx_gpu_num_blocks_offset ]
5030   ldr clut_ptr, [ psx_gpu, #psx_gpu_clut_ptr_offset ]
5031
5032   add block_ptr, psx_gpu, #psx_gpu_blocks_offset
5033   ldr block_pixels_a, [ block_ptr, #16 ]
5034
5035  0:
5036   and texel_0, texel_shift_mask, block_pixels_a, lsl #1
5037   ldr block_pixels_b, [ block_ptr, #20 ]
5038
5039   and texel_1, texel_shift_mask, block_pixels_a, lsr #7
5040   ldrh texel_0, [ clut_ptr, texel_0 ]
5041
5042   and texel_2, texel_shift_mask, block_pixels_a, lsr #15
5043   ldrh texel_1, [ clut_ptr, texel_1 ]
5044
5045   and texel_3, texel_shift_mask, block_pixels_a, lsr #23
5046   ldr block_pixels_a, [ block_ptr, #(64 + 16) ]
5047
5048   ldrh texel_2, [ clut_ptr, texel_2 ]
5049   and texel_4, texel_shift_mask, block_pixels_b, lsl #1
5050
5051   ldrh texel_3, [ clut_ptr, texel_3 ]
5052   and texel_5, texel_shift_mask, block_pixels_b, lsr #7
5053
5054   ldrh texel_4, [ clut_ptr, texel_4 ]
5055   and texel_6, texel_shift_mask, block_pixels_b, lsr #15
5056
5057   ldrh texel_5, [ clut_ptr, texel_5 ]
5058   and texel_7, texel_shift_mask, block_pixels_b, lsr #23
5059
5060   ldrh texel_6, [ clut_ptr, texel_6 ]
5061   orr texels_01, texel_0, texel_1, lsl #16
5062
5063   ldrh texel_7, [ clut_ptr, texel_7 ]
5064   orr texels_23, texel_2, texel_3, lsl #16
5065
5066   orr texels_45, texel_4, texel_5, lsl #16
5067   str texels_01, [ block_ptr, #0 ]
5068
5069   orr texels_67, texel_6, texel_7, lsl #16
5070   str texels_23, [ block_ptr, #4 ]
5071
5072   subs num_blocks, num_blocks, #1
5073   str texels_45, [ block_ptr, #8 ]
5074
5075   str texels_67, [ block_ptr, #12 ]
5076   add block_ptr, block_ptr, #64
5077
5078   bne 0b
5079
5080   ldmia sp!, { r4 - r11, pc }
5081
5082
5083 #undef width_rounded
5084 #undef texture_mask
5085 #undef num_blocks
5086 #undef texture_offset
5087
5088 #define psx_gpu                                           r0
5089 #define x                                                 r1
5090 #define y                                                 r2
5091 #define u                                                 r3
5092 #define v                                                 r4
5093 #define width                                             r5
5094 #define height                                            r6
5095 #define left_offset                                       r8
5096 #define width_rounded                                     r9
5097 #define right_width                                       r10
5098 #define block_width                                       r11
5099
5100 #define texture_offset_base                               r1
5101 #define texture_mask                                      r2
5102 #define texture_page_ptr                                  r3
5103 #define num_blocks                                        r4
5104 #define block                                             r5
5105 #define fb_ptr                                            r7
5106 #define texture_offset                                    r8
5107 #define blocks_remaining                                  r9
5108 #define fb_ptr_pitch                                      r12
5109 #define texture_block_ptr                                 r14
5110
5111 #define texture_mask_width                                r2
5112 #define texture_mask_height                               r3
5113 #define left_mask_bits                                    r4
5114 #define right_mask_bits                                   r5
5115
5116
5117 #undef block_masks
5118 #undef block_masks_shifted
5119 #undef texels
5120
5121 #define block_masks                                       d0
5122 #define block_masks_shifted                               d1
5123 #define draw_mask_fb_ptr                                  d2
5124 #define texels                                            q2
5125
5126
5127 setup_sprites_16bpp_flush_single:
5128   vpush { d0 - d2 }
5129
5130   stmdb sp!, { r0 - r3, r12, r14 }
5131   bl flush_render_block_buffer
5132   ldmia sp!, { r0 - r3, r12, r14 }
5133
5134   vpop { d0 - d2 }
5135
5136   add block, psx_gpu, #psx_gpu_blocks_offset
5137   mov num_blocks, #1
5138
5139   bx lr
5140
5141 setup_sprites_16bpp_flush_row:
5142   vpush { d0 - d2 }
5143
5144   stmdb sp!, { r0 - r3, r12, r14 }
5145   bl flush_render_block_buffer
5146   ldmia sp!, { r0 - r3, r12, r14 }
5147
5148   vpop { d0 - d2 }
5149
5150   add block, psx_gpu, #psx_gpu_blocks_offset
5151   mov num_blocks, block_width
5152
5153   bx lr
5154
5155 function(setup_sprite_16bpp)
5156   stmdb sp!, { r4 - r11, r14 }
5157   ldr fb_ptr, [ psx_gpu, #psx_gpu_vram_ptr_offset ]
5158
5159   ldr v, [ sp, #36 ]
5160   add fb_ptr, fb_ptr, y, lsl #11
5161
5162   ldr width, [ sp, #40 ]
5163   add fb_ptr, fb_ptr, x, lsl #1
5164
5165   ldr height, [ sp, #44 ]
5166   and left_offset, u, #0x7
5167
5168   add texture_offset_base, u, u
5169   add width_rounded, width, #7
5170
5171   add texture_offset_base, v, lsl #11
5172   mov left_mask_bits, #0xFF
5173   
5174   ldrb texture_mask_width, [ psx_gpu, #psx_gpu_texture_mask_width_offset ]
5175   add width_rounded, width_rounded, left_offset
5176
5177   ldrb texture_mask_height, [ psx_gpu, #psx_gpu_texture_mask_height_offset ]
5178   sub fb_ptr, fb_ptr, left_offset, lsl #1
5179
5180   add texture_mask, texture_mask_width, texture_mask_width
5181   mov right_mask_bits, #0xFE
5182
5183   and right_width, width_rounded, #0x7
5184   mvn left_mask_bits, left_mask_bits, lsl left_offset
5185
5186   add texture_mask, texture_mask_height, lsl #11
5187   mov block_width, width_rounded, lsr #3
5188
5189   mov right_mask_bits, right_mask_bits, lsl right_width
5190   movw fb_ptr_pitch, #(2048 + 16)
5191
5192   sub fb_ptr_pitch, fb_ptr_pitch, block_width, lsl #4
5193   vmov block_masks, left_mask_bits, right_mask_bits
5194
5195   ldrh num_blocks, [ psx_gpu, #psx_gpu_num_blocks_offset ]
5196   add block, psx_gpu, #psx_gpu_blocks_offset
5197
5198   bic texture_offset_base, texture_offset_base, #0xF
5199   cmp block_width, #1
5200
5201   ldr texture_page_ptr, [ psx_gpu, #psx_gpu_texture_page_ptr_offset ]
5202   add block, block, num_blocks, lsl #6
5203
5204   bne 0f
5205
5206   vext.32 block_masks_shifted, block_masks, block_masks, #1
5207   vorr.u32 block_masks, block_masks, block_masks_shifted
5208   vdup.u8 draw_mask_fb_ptr, block_masks[0]
5209
5210  1:
5211   add num_blocks, num_blocks, #1
5212   cmp num_blocks, #MAX_BLOCKS
5213   blgt setup_sprites_16bpp_flush_single
5214
5215   and texture_block_ptr, texture_offset_base, texture_mask
5216   subs height, height, #1
5217
5218   add texture_block_ptr, texture_page_ptr, texture_block_ptr
5219   vld1.u32 { texels }, [ texture_block_ptr, :128 ]
5220
5221   vst1.u32 { texels }, [ block, :128 ]
5222   add block, block, #40
5223
5224   vmov.u32 draw_mask_fb_ptr[1], fb_ptr
5225   pld [ fb_ptr ]
5226
5227   vst1.u32 { draw_mask_fb_ptr }, [ block, :64 ]
5228
5229   add block, block, #24
5230   add texture_offset_base, texture_offset_base, #2048
5231   add fb_ptr, fb_ptr, #2048
5232   strh num_blocks, [ psx_gpu, #psx_gpu_num_blocks_offset ]
5233   bne 1b
5234
5235   ldmia sp!, { r4 - r11, pc }
5236
5237  0:
5238   add num_blocks, num_blocks, block_width
5239   mov texture_offset, texture_offset_base
5240
5241   cmp num_blocks, #MAX_BLOCKS
5242   blgt setup_sprites_16bpp_flush_row
5243
5244   add texture_offset_base, texture_offset_base, #2048
5245   and texture_block_ptr, texture_offset, texture_mask
5246
5247   add texture_block_ptr, texture_page_ptr, texture_block_ptr
5248   vld1.u32 { texels }, [ texture_block_ptr, :128 ]  
5249
5250   vst1.u32 { texels }, [ block, :128 ]
5251   add block, block, #40
5252
5253   vdup.u8 draw_mask_fb_ptr, block_masks[0]
5254   vmov.u32 draw_mask_fb_ptr[1], fb_ptr
5255   pld [ fb_ptr ]
5256
5257   vst1.u32 { draw_mask_fb_ptr }, [ block, :64 ]
5258   subs blocks_remaining, block_width, #2
5259
5260   add texture_offset, texture_offset, #16
5261   add fb_ptr, fb_ptr, #16
5262
5263   vmov.u8 draw_mask_fb_ptr, #0
5264
5265   add block, block, #24
5266   beq 2f
5267
5268  1:
5269   and texture_block_ptr, texture_offset, texture_mask
5270   subs blocks_remaining, blocks_remaining, #1
5271
5272   add texture_block_ptr, texture_page_ptr, texture_block_ptr
5273   vld1.u32 { texels }, [ texture_block_ptr, :128 ]
5274
5275   vst1.u32 { texels }, [ block, :128 ]
5276   add block, block, #40
5277
5278   vmov.u32 draw_mask_fb_ptr[1], fb_ptr
5279   pld [ fb_ptr ]
5280
5281   vst1.u32 { draw_mask_fb_ptr }, [ block, :64 ]
5282   
5283   add texture_offset, texture_offset, #16
5284   add fb_ptr, fb_ptr, #16
5285
5286   add block, block, #24
5287   bne 1b
5288
5289  2:
5290   and texture_block_ptr, texture_offset, texture_mask
5291   add texture_block_ptr, texture_page_ptr, texture_block_ptr
5292
5293   vld1.u32 { texels }, [ texture_block_ptr, :128 ]
5294   vdup.u8 draw_mask_fb_ptr, block_masks[4]
5295
5296   vst1.u32 { texels }, [ block, :128 ]
5297   add block, block, #40
5298
5299   vmov.u32 draw_mask_fb_ptr[1], fb_ptr
5300   vst1.u32 { draw_mask_fb_ptr }, [ block, :64 ]
5301   
5302   add block, block, #24
5303   subs height, height, #1
5304
5305   add fb_ptr, fb_ptr, fb_ptr_pitch
5306   strh num_blocks, [ psx_gpu, #psx_gpu_num_blocks_offset ]
5307
5308   bne 0b
5309
5310   ldmia sp!, { r4 - r11, pc }
5311
5312
5313 #undef texture_page_ptr
5314 #undef vram_ptr
5315 #undef dirty_textures_mask
5316 #undef current_texture_mask
5317
5318 #define psx_gpu                                           r0
5319 #define current_texture_page                              r1
5320 #define texture_page_ptr                                  r2
5321 #define vram_ptr_a                                        r3
5322 #define current_texture_page_x                            r12
5323 #define current_texture_page_y                            r4
5324 #define dirty_textures_mask                               r5
5325 #define tile_y                                            r6
5326 #define tile_x                                            r7
5327 #define sub_y                                             r8
5328 #define current_texture_mask                              r9
5329 #define c_4096                                            r10
5330 #define vram_ptr_b                                        r11
5331
5332 #define texel_block_a                                     d0
5333 #define texel_block_b                                     d1
5334 #define texel_block_expanded_a                            q1
5335 #define texel_block_expanded_b                            q2
5336 #define texel_block_expanded_ab                           q2
5337 #define texel_block_expanded_c                            q3
5338 #define texel_block_expanded_d                            q4
5339 #define texel_block_expanded_cd                           q3
5340
5341 function(update_texture_4bpp_cache)
5342   stmdb sp!, { r4 - r11, r14 }
5343   vpush { q0 - q3 }
5344
5345   ldrb current_texture_page, [ psx_gpu, #psx_gpu_current_texture_page_offset ]
5346
5347   ldr texture_page_ptr, [ psx_gpu, #psx_gpu_texture_page_base_offset ]
5348   ldr vram_ptr_a, [ psx_gpu, #psx_gpu_vram_ptr_offset ]
5349
5350   and current_texture_page_x, current_texture_page, #0xF
5351   ldr current_texture_mask, [ psx_gpu, #psx_gpu_current_texture_mask_offset ]
5352
5353   mov current_texture_page_y, current_texture_page, lsr #4
5354   ldr dirty_textures_mask, [ psx_gpu, #psx_gpu_dirty_textures_4bpp_mask_offset ]
5355
5356   add vram_ptr_a, vram_ptr_a, current_texture_page_y, lsl #19
5357   mov tile_y, #16
5358
5359   add vram_ptr_a, vram_ptr_a, current_texture_page_x, lsl #7  
5360   bic dirty_textures_mask, current_texture_mask
5361   
5362   mov tile_x, #16
5363   str dirty_textures_mask, [ psx_gpu, #psx_gpu_dirty_textures_4bpp_mask_offset ]
5364
5365   mov sub_y, #8
5366   movw c_4096, #4096
5367
5368   add vram_ptr_b, vram_ptr_a, #2048
5369
5370  0:
5371   vld1.u32 { texel_block_a }, [ vram_ptr_a, :64 ], c_4096
5372   vld1.u32 { texel_block_b }, [ vram_ptr_b, :64 ], c_4096
5373
5374   vmovl.u8 texel_block_expanded_a, texel_block_a
5375   vshll.u8 texel_block_expanded_b, texel_block_a, #4
5376   vmovl.u8 texel_block_expanded_c, texel_block_b
5377   vshll.u8 texel_block_expanded_d, texel_block_b, #4
5378
5379   vbic.u16 texel_block_expanded_a, #0x00F0
5380   vbic.u16 texel_block_expanded_b, #0x00F0
5381   vbic.u16 texel_block_expanded_c, #0x00F0
5382   vbic.u16 texel_block_expanded_d, #0x00F0
5383
5384   vorr.u16 texel_block_expanded_ab, texel_block_expanded_a,                    \
5385    texel_block_expanded_b
5386   vorr.u16 texel_block_expanded_cd, texel_block_expanded_c,                    \
5387    texel_block_expanded_d
5388
5389   vst1.u32 { texel_block_expanded_ab, texel_block_expanded_cd },               \
5390    [ texture_page_ptr, :256 ]!
5391
5392   subs sub_y, sub_y, #1
5393   bne 0b
5394
5395   mov sub_y, #8
5396   add vram_ptr_a, vram_ptr_a, #8
5397   add vram_ptr_b, vram_ptr_b, #8
5398
5399   sub vram_ptr_a, vram_ptr_a, #(16 * 2048)
5400   sub vram_ptr_b, vram_ptr_b, #(16 * 2048)
5401
5402   subs tile_x, tile_x, #1
5403   bne 0b
5404
5405   mov tile_x, #16
5406   add vram_ptr_a, vram_ptr_a, #(16 * 2048)
5407   add vram_ptr_b, vram_ptr_b, #(16 * 2048)
5408
5409   sub vram_ptr_a, vram_ptr_a, #(8 * 16)
5410   sub vram_ptr_b, vram_ptr_b, #(8 * 16)
5411
5412   subs tile_y, tile_y, #1
5413   bne 0b
5414
5415   vpop { q0 - q3 }
5416   ldmia sp!, { r4 - r11, pc }
5417
5418
5419 #undef current_texture_page
5420
5421 #define psx_gpu                                           r0
5422 #define texture_page                                      r1
5423 #define texture_page_ptr                                  r2
5424 #define vram_ptr_a                                        r3
5425 #define texture_page_x                                    r12
5426 #define texture_page_y                                    r4
5427 #define current_texture_page                              r5
5428 #define tile_y                                            r6
5429 #define tile_x                                            r7
5430 #define sub_y                                             r8
5431 #define c_4096                                            r10
5432 #define vram_ptr_b                                        r11
5433
5434
5435 #undef texels_a
5436 #undef texels_b
5437
5438 #define texels_a                                          q0
5439 #define texels_b                                          q1
5440 #define texels_c                                          q2
5441 #define texels_d                                          q3
5442
5443
5444 function(update_texture_8bpp_cache_slice)
5445   stmdb sp!, { r4 - r11, r14 }
5446   vpush { q0 - q3 }
5447
5448   ldrb current_texture_page, [ psx_gpu, #psx_gpu_current_texture_page_offset ]
5449   ldr vram_ptr_a, [ psx_gpu, #psx_gpu_vram_ptr_offset ]
5450
5451   ldr texture_page_ptr, [ psx_gpu, #psx_gpu_texture_page_base_offset ]
5452   mov tile_y, #16
5453
5454   and texture_page_x, texture_page, #0xF
5455   mov texture_page_y, texture_page, lsr #4
5456
5457   add vram_ptr_a, vram_ptr_a, texture_page_x, lsl #7  
5458   mov tile_x, #8
5459
5460   add vram_ptr_a, vram_ptr_a, texture_page_y, lsl #19
5461   eor current_texture_page, current_texture_page, texture_page
5462
5463   ands current_texture_page, current_texture_page, #0x1
5464   mov sub_y, #4
5465
5466   addne texture_page_ptr, texture_page_ptr, #(8 * 16 * 16)
5467   movw c_4096, #4096
5468
5469   add vram_ptr_b, vram_ptr_a, #2048
5470
5471  0:
5472   vld1.u32 { texels_a }, [ vram_ptr_a, :128 ], c_4096
5473   vld1.u32 { texels_b }, [ vram_ptr_b, :128 ], c_4096
5474   vld1.u32 { texels_c }, [ vram_ptr_a, :128 ], c_4096
5475   vld1.u32 { texels_d }, [ vram_ptr_b, :128 ], c_4096
5476
5477   vst1.u32 { texels_a, texels_b }, [ texture_page_ptr, :256 ]!
5478   vst1.u32 { texels_c, texels_d }, [ texture_page_ptr, :256 ]!
5479
5480   subs sub_y, sub_y, #1
5481   bne 0b
5482
5483   mov sub_y, #4
5484
5485   add vram_ptr_a, vram_ptr_a, #16
5486   add vram_ptr_b, vram_ptr_b, #16
5487
5488   sub vram_ptr_a, vram_ptr_a, #(16 * 2048)
5489   sub vram_ptr_b, vram_ptr_b, #(16 * 2048)
5490
5491   subs tile_x, tile_x, #1
5492   bne 0b
5493
5494   mov tile_x, #8
5495
5496   add vram_ptr_a, vram_ptr_a, #(16 * 2048)
5497   add vram_ptr_b, vram_ptr_b, #(16 * 2048)
5498
5499   sub vram_ptr_a, vram_ptr_a, #(8 * 16)
5500   sub vram_ptr_b, vram_ptr_b, #(8 * 16)
5501
5502   subs tile_y, tile_y, #1
5503   add texture_page_ptr, texture_page_ptr, #(8 * 16 * 16)
5504
5505   bne 0b
5506
5507   vpop { q0 - q3 }
5508   ldmia sp!, { r4 - r11, pc }
5509