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