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