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