| Previous | 15994 Revisions | Next |
| r9855 Friday 31st December, 2010 at 06:35:26 UTC by MooglyGuy |
|---|
| Massive re-port of angrylion's RDP and RSP code; fixes more graphical bugs than can be listed, but it should now have pixel-accurate or nearly pixel-accurate rasterization. Additionally, Dr. Mario 64, The New Tetris, Doubutsu No Mori, The New Tetris, and many others no longer have triangle dropout or Z miscalculation with the RSP DRC. [angrylion, Harmony] |
| [src/emu/cpu/rsp] | rsp.c rsp.h rspdiv.h* rspdrc.c |
| [src/mame] | mame.mak |
| [src/mame/machine] | n64.c |
| [src/mame/video] | n64.c n64.h rdpblend.c rdpblend.h rdpfb.c rdpfb.h |
| [src/mess] | mess.mak |
| [src/mess/drivers] | n64.c |
| r9854 | r9855 | |
|---|---|---|
| 390 | 390 | src = (UINT8*)&rdram[sp_dram_addr / 4]; |
| 391 | 391 | dst = (sp_mem_addr & 0x1000) ? (UINT8*)&rsp_imem[(sp_mem_addr & 0xfff) / 4] : (UINT8*)&rsp_dmem[(sp_mem_addr & 0xfff) / 4]; |
| 392 | 392 | |
| 393 | //printf("CPU %08x -> RSP %08x\n", sp_dram_addr, 0x04000000 | sp_mem_addr); | |
| 393 | 394 | for (i=0; i < sp_dma_length; i++) |
| 394 | 395 | { |
| 395 | dst[BYTE4_XOR_BE(i)] = src[BYTE4_XOR_BE(i)]; | |
| 396 | //printf("%02x ", src[i]); | |
| 397 | dst[i] = src[i]; | |
| 396 | 398 | } |
| 399 | //printf("\n"); | |
| 397 | 400 | |
| 398 | 401 | sp_mem_addr += sp_dma_length; |
| 399 | 402 | sp_dram_addr += sp_dma_length; |
| r9854 | r9855 | |
| 408 | 411 | src = (sp_mem_addr & 0x1000) ? (UINT8*)&rsp_imem[(sp_mem_addr & 0xfff) / 4] : (UINT8*)&rsp_dmem[(sp_mem_addr & 0xfff) / 4]; |
| 409 | 412 | dst = (UINT8*)&rdram[sp_dram_addr / 4]; |
| 410 | 413 | |
| 414 | //printf("RSP %08x -> CPU %08x\n", 0x04000000 | sp_mem_addr, sp_dram_addr); | |
| 411 | 415 | for (i=0; i < sp_dma_length; i++) |
| 412 | 416 | { |
| 413 | dst[BYTE4_XOR_BE(i)] = src[BYTE4_XOR_BE(i)]; | |
| 417 | //printf("%02x ", src[i]); | |
| 418 | dst[i] = src[i]; | |
| 414 | 419 | } |
| 420 | //printf("\n"); | |
| 415 | 421 | |
| 416 | 422 | sp_mem_addr += sp_dma_length; |
| 417 | 423 | sp_dram_addr += sp_dma_length; |
| r9854 | r9855 | |
| 729 | 735 | { |
| 730 | 736 | _n64_state *state = device->machine->driver_data<_n64_state>(); |
| 731 | 737 | |
| 738 | //printf("%08x\n", offset); | |
| 732 | 739 | switch (offset) |
| 733 | 740 | { |
| 734 | 741 | case 0x00/4: // DP_START_REG |
| r9854 | r9855 | |
| 755 | 762 | { |
| 756 | 763 | _n64_state *state = device->machine->driver_data<_n64_state>(); |
| 757 | 764 | |
| 765 | //printf("%08x: %08x\n", offset, data); | |
| 758 | 766 | switch (offset) |
| 759 | 767 | { |
| 760 | 768 | case 0x00/4: // DP_START_REG |
| r9854 | r9855 | |
| 1091 | 1099 | } |
| 1092 | 1100 | } |
| 1093 | 1101 | |
| 1102 | #define N64_ATTOTIME_NORMALIZE(a) do { while ((a).attoseconds >= ATTOSECONDS_PER_SECOND) { (a).seconds++; (a).attoseconds -= ATTOSECONDS_PER_SECOND; } } while (0) | |
| 1103 | ||
| 1094 | 1104 | static void start_audio_dma(running_machine *machine) |
| 1095 | 1105 | { |
| 1096 | 1106 | INT16 *ram = (INT16*)rdram; |
| r9854 | r9855 | |
| 2011 | 2021 | /* configure fast RAM regions for DRC */ |
| 2012 | 2022 | mips3drc_add_fastram(machine->device("maincpu"), 0x00000000, 0x007fffff, FALSE, rdram); |
| 2013 | 2023 | |
| 2014 | rspdrc_set_options(machine->device("rsp"), | |
| 2024 | rspdrc_set_options(machine->device("rsp"), RSPDRC_STRICT_VERIFY); | |
| 2015 | 2025 | rspdrc_add_imem(machine->device("rsp"), rsp_imem); |
| 2016 | 2026 | rspdrc_add_dmem(machine->device("rsp"), rsp_dmem); |
| 2017 | 2027 | rspdrc_flush_drc_cache(machine->device("rsp")); |
| r9854 | r9855 | |
|---|---|---|
| 1206 | 1206 | $(DRIVERS)/feversoc.o \ |
| 1207 | 1207 | |
| 1208 | 1208 | $(MAMEOBJ)/seta.a: \ |
| 1209 | $(DRIVERS)/aleck64.o $(MACHINE)/n64.o $(VIDEO)/n64.o $(VIDEO)/rdpblend.o $(VIDEO)/rdpfb.o $(VIDEO)/rdpspn16.o $(VIDEO)/rdpt | |
| 1209 | $(DRIVERS)/aleck64.o $(MACHINE)/n64.o $(VIDEO)/n64.o $(VIDEO)/rdpblend.o $(VIDEO)/rdpfb.o $(VIDEO)/rdpspn16.o $(VIDEO)/rdpt | |
| 1210 | 1210 | $(DRIVERS)/darkhors.o \ |
| 1211 | 1211 | $(DRIVERS)/hanaawas.o $(VIDEO)/hanaawas.o \ |
| 1212 | 1212 | $(DRIVERS)/macs.o \ |
| r9854 | r9855 | |
|---|---|---|
| 1 | #include "emu.h" | |
| 2 | #include "includes/n64.h" | |
| 3 | #include "video/n64.h" | |
| 4 | ||
| 5 | namespace N64 | |
| 6 | { | |
| 7 | ||
| 8 | namespace RDP | |
| 9 | { | |
| 10 | ||
| 11 | #define LookUpCC(A, B, C, D) m_rdp->GetCCLUT2()[(m_rdp->GetCCLUT1()[(A << 16) | (B << 8) | C] << 8) | D] | |
| 12 | ||
| 13 | void Rectangle::SetMachine(running_machine* machine) | |
| 14 | { | |
| 15 | _n64_state *state = machine->driver_data<_n64_state>(); | |
| 16 | ||
| 17 | m_machine = machine; | |
| 18 | m_rdp = &state->m_rdp; | |
| 19 | m_misc_state = m_rdp->GetMiscState(); | |
| 20 | m_other_modes = m_rdp->GetOtherModes(); | |
| 21 | m_blender = m_rdp->GetBlender(); | |
| 22 | } | |
| 23 | ||
| 24 | void Rectangle::Draw() | |
| 25 | { | |
| 26 | switch(m_other_modes->cycle_type) | |
| 27 | { | |
| 28 | case CYCLE_TYPE_1: | |
| 29 | Draw1Cycle(); | |
| 30 | return; | |
| 31 | ||
| 32 | case CYCLE_TYPE_2: | |
| 33 | Draw2Cycle(); | |
| 34 | return; | |
| 35 | ||
| 36 | case CYCLE_TYPE_FILL: | |
| 37 | DrawFill(); | |
| 38 | return; | |
| 39 | ||
| 40 | default: | |
| 41 | fatalerror("Unsupported cycle type for Textured Rectangle: %d\n", m_other_modes->cycle_type); | |
| 42 | return; | |
| 43 | } | |
| 44 | } | |
| 45 | ||
| 46 | void Rectangle::Draw1Cycle() | |
| 47 | { | |
| 48 | UINT16 *fb = (UINT16*)&rdram[(m_misc_state->m_fb_address / 4)]; | |
| 49 | UINT8* hb = &m_rdp->GetHiddenBits()[m_misc_state->m_fb_address >> 1]; | |
| 50 | ||
| 51 | int index, i, j; | |
| 52 | int x1 = m_xh >> 2; | |
| 53 | int x2 = m_xl >> 2; | |
| 54 | int y1 = m_yh >> 2; | |
| 55 | int y2 = m_yl >> 2; | |
| 56 | UINT16 fill_color1 = (m_rdp->GetFillColor32() >> 16) & 0xffff; | |
| 57 | UINT16 fill_color2 = (m_rdp->GetFillColor32() >> 0) & 0xffff; | |
| 58 | int fill_cvg1 = (fill_color1 & 1) ? 8 : 1; | |
| 59 | int fill_cvg2 = (fill_color2 & 1) ? 8 : 1; | |
| 60 | ||
| 61 | if (x2 <= x1) | |
| 62 | { | |
| 63 | x2=x1+1; // SCARS (E) | |
| 64 | } | |
| 65 | if (y2 == y1) | |
| 66 | { | |
| 67 | y2=y1+1; // Goldeneye | |
| 68 | } | |
| 69 | ||
| 70 | // clip | |
| 71 | if (x1 < m_rdp->GetScissor()->m_xh) | |
| 72 | { | |
| 73 | x1 = m_rdp->GetScissor()->m_xh; | |
| 74 | } | |
| 75 | if (y1 < m_rdp->GetScissor()->m_yh) | |
| 76 | { | |
| 77 | y1 = m_rdp->GetScissor()->m_yh; | |
| 78 | } | |
| 79 | if (x2 >= m_rdp->GetScissor()->m_xl) | |
| 80 | { | |
| 81 | x2 = m_rdp->GetScissor()->m_xl - 1; | |
| 82 | } | |
| 83 | if (y2 >= m_rdp->GetScissor()->m_yl) | |
| 84 | { | |
| 85 | y2 = m_rdp->GetScissor()->m_yl - 1; | |
| 86 | } | |
| 87 | ||
| 88 | m_rdp->GetShadeColor()->c = 0; // Needed by Command & Conquer menus | |
| 89 | ||
| 90 | if(m_other_modes->rgb_dither_sel == 0) | |
| 91 | { | |
| 92 | for (int j = y1; j <= y2; j++) | |
| 93 | { | |
| 94 | Color c1; | |
| 95 | int dith = 0; | |
| 96 | index = j * m_misc_state->m_fb_width; | |
| 97 | for (i = x1; i <= x2; i++) | |
| 98 | { | |
| 99 | m_misc_state->m_curpixel_cvg = (i & 1) ? fill_cvg1 : fill_cvg2; | |
| 100 | ||
| 101 | c1.i.r = LookUpCC(*m_rdp->GetColorInputs()->combiner_rgbsub_a_r[1], | |
| 102 | *m_rdp->GetColorInputs()->combiner_rgbsub_b_r[1], | |
| 103 | *m_rdp->GetColorInputs()->combiner_rgbmul_r[1], | |
| 104 | *m_rdp->GetColorInputs()->combiner_rgbadd_r[1]); | |
| 105 | c1.i.g = LookUpCC(*m_rdp->GetColorInputs()->combiner_rgbsub_a_g[1], | |
| 106 | *m_rdp->GetColorInputs()->combiner_rgbsub_b_g[1], | |
| 107 | *m_rdp->GetColorInputs()->combiner_rgbmul_g[1], | |
| 108 | *m_rdp->GetColorInputs()->combiner_rgbadd_g[1]); | |
| 109 | c1.i.b = LookUpCC(*m_rdp->GetColorInputs()->combiner_rgbsub_a_b[1], | |
| 110 | *m_rdp->GetColorInputs()->combiner_rgbsub_b_b[1], | |
| 111 | *m_rdp->GetColorInputs()->combiner_rgbmul_b[1], | |
| 112 | *m_rdp->GetColorInputs()->combiner_rgbadd_b[1]); | |
| 113 | c1.i.a = LookUpCC(*m_rdp->GetColorInputs()->combiner_alphasub_a[1], | |
| 114 | *m_rdp->GetColorInputs()->combiner_alphasub_b[1], | |
| 115 | *m_rdp->GetColorInputs()->combiner_alphamul[1], | |
| 116 | *m_rdp->GetColorInputs()->combiner_alphaadd[1]); | |
| 117 | m_rdp->GetAlphaCvg(&c1.i.a); | |
| 118 | ||
| 119 | dith = m_rdp->GetMagicMatrix()[(((j) & 3) << 2) + ((i ^ WORD_ADDR_XOR) & 3)]; | |
| 120 | ||
| 121 | m_blender->Blend(&fb[(index + i) ^ WORD_ADDR_XOR], &hb[(index + i) ^ BYTE_ADDR_XOR], c1, *m_rdp->GetZero(), dith); | |
| 122 | } | |
| 123 | } | |
| 124 | } | |
| 125 | else if(m_other_modes->rgb_dither_sel == 1) | |
| 126 | { | |
| 127 | for (j = y1; j <= y2; j++) | |
| 128 | { | |
| 129 | Color c1; | |
| 130 | int dith = 0; | |
| 131 | index = j * m_misc_state->m_fb_width; | |
| 132 | for (i = x1; i <= x2; i++) | |
| 133 | { | |
| 134 | m_misc_state->m_curpixel_cvg = (i & 1) ? fill_cvg1 : fill_cvg2; | |
| 135 | ||
| 136 | c1.i.r = LookUpCC(*m_rdp->GetColorInputs()->combiner_rgbsub_a_r[1], | |
| 137 | *m_rdp->GetColorInputs()->combiner_rgbsub_b_r[1], | |
| 138 | *m_rdp->GetColorInputs()->combiner_rgbmul_r[1], | |
| 139 | *m_rdp->GetColorInputs()->combiner_rgbadd_r[1]); | |
| 140 | c1.i.g = LookUpCC(*m_rdp->GetColorInputs()->combiner_rgbsub_a_g[1], | |
| 141 | *m_rdp->GetColorInputs()->combiner_rgbsub_b_g[1], | |
| 142 | *m_rdp->GetColorInputs()->combiner_rgbmul_g[1], | |
| 143 | *m_rdp->GetColorInputs()->combiner_rgbadd_g[1]); | |
| 144 | c1.i.b = LookUpCC(*m_rdp->GetColorInputs()->combiner_rgbsub_a_b[1], | |
| 145 | *m_rdp->GetColorInputs()->combiner_rgbsub_b_b[1], | |
| 146 | *m_rdp->GetColorInputs()->combiner_rgbmul_b[1], | |
| 147 | *m_rdp->GetColorInputs()->combiner_rgbadd_b[1]); | |
| 148 | c1.i.a = LookUpCC(*m_rdp->GetColorInputs()->combiner_alphasub_a[1], | |
| 149 | *m_rdp->GetColorInputs()->combiner_alphasub_b[1], | |
| 150 | *m_rdp->GetColorInputs()->combiner_alphamul[1], | |
| 151 | *m_rdp->GetColorInputs()->combiner_alphaadd[1]); | |
| 152 | m_rdp->GetAlphaCvg(&c1.i.a); | |
| 153 | ||
| 154 | dith = m_rdp->GetBayerMatrix()[(((j) & 3) << 2) + ((i ^ WORD_ADDR_XOR) & 3)]; | |
| 155 | m_blender->Blend(&fb[(index + i) ^ WORD_ADDR_XOR], &hb[(index + i) ^ BYTE_ADDR_XOR], c1, *m_rdp->GetZero(), dith); | |
| 156 | } | |
| 157 | } | |
| 158 | } | |
| 159 | else | |
| 160 | { | |
| 161 | for (j = y1; j <= y2; j++) | |
| 162 | { | |
| 163 | Color c1; | |
| 164 | index = j * m_misc_state->m_fb_width; | |
| 165 | for (i = x1; i <= x2; i++) | |
| 166 | { | |
| 167 | m_misc_state->m_curpixel_cvg = (i & 1) ? fill_cvg1 : fill_cvg2; | |
| 168 | ||
| 169 | c1.i.r = LookUpCC(*m_rdp->GetColorInputs()->combiner_rgbsub_a_r[1], | |
| 170 | *m_rdp->GetColorInputs()->combiner_rgbsub_b_r[1], | |
| 171 | *m_rdp->GetColorInputs()->combiner_rgbmul_r[1], | |
| 172 | *m_rdp->GetColorInputs()->combiner_rgbadd_r[1]); | |
| 173 | c1.i.g = LookUpCC(*m_rdp->GetColorInputs()->combiner_rgbsub_a_g[1], | |
| 174 | *m_rdp->GetColorInputs()->combiner_rgbsub_b_g[1], | |
| 175 | *m_rdp->GetColorInputs()->combiner_rgbmul_g[1], | |
| 176 | *m_rdp->GetColorInputs()->combiner_rgbadd_g[1]); | |
| 177 | c1.i.b = LookUpCC(*m_rdp->GetColorInputs()->combiner_rgbsub_a_b[1], | |
| 178 | *m_rdp->GetColorInputs()->combiner_rgbsub_b_b[1], | |
| 179 | *m_rdp->GetColorInputs()->combiner_rgbmul_b[1], | |
| 180 | *m_rdp->GetColorInputs()->combiner_rgbadd_b[1]); | |
| 181 | c1.i.a = LookUpCC(*m_rdp->GetColorInputs()->combiner_alphasub_a[1], | |
| 182 | *m_rdp->GetColorInputs()->combiner_alphasub_b[1], | |
| 183 | *m_rdp->GetColorInputs()->combiner_alphamul[1], | |
| 184 | *m_rdp->GetColorInputs()->combiner_alphaadd[1]); | |
| 185 | m_rdp->GetAlphaCvg(&c1.i.a); | |
| 186 | ||
| 187 | m_blender->Blend(&fb[(index + i) ^ WORD_ADDR_XOR], &hb[(index + i) ^ BYTE_ADDR_XOR], c1, *m_rdp->GetZero(), 0); | |
| 188 | } | |
| 189 | } | |
| 190 | } | |
| 191 | } | |
| 192 | ||
| 193 | void Rectangle::Draw2Cycle() | |
| 194 | { | |
| 195 | UINT16 *fb = (UINT16*)&rdram[(m_misc_state->m_fb_address / 4)]; | |
| 196 | UINT8* hb = &m_rdp->GetHiddenBits()[m_misc_state->m_fb_address >> 1]; | |
| 197 | ||
| 198 | int index, i, j; | |
| 199 | int x1 = m_xh >> 2; | |
| 200 | int x2 = m_xl >> 2; | |
| 201 | int y1 = m_yh >> 2; | |
| 202 | int y2 = m_yl >> 2; | |
| 203 | UINT16 fill_color1; | |
| 204 | UINT16 fill_color2; | |
| 205 | int fill_cvg1; | |
| 206 | int fill_cvg2; | |
| 207 | ||
| 208 | if (x2 <= x1) | |
| 209 | { | |
| 210 | x2=x1+1; // SCARS (E) | |
| 211 | } | |
| 212 | if (y2 == y1) | |
| 213 | { | |
| 214 | y2=y1+1; // Goldeneye | |
| 215 | } | |
| 216 | ||
| 217 | ||
| 218 | fill_color1 = (m_rdp->GetFillColor32() >> 16) & 0xffff; | |
| 219 | fill_color2 = (m_rdp->GetFillColor32() >> 0) & 0xffff; | |
| 220 | fill_cvg1 = (fill_color1 & 1) ? 8 : 1; | |
| 221 | fill_cvg2 = (fill_color2 & 1) ? 8 : 1; | |
| 222 | ||
| 223 | // clip | |
| 224 | if (x1 < m_rdp->GetScissor()->m_xh) | |
| 225 | { | |
| 226 | x1 = m_rdp->GetScissor()->m_xh; | |
| 227 | } | |
| 228 | if (y1 < m_rdp->GetScissor()->m_yh) | |
| 229 | { | |
| 230 | y1 = m_rdp->GetScissor()->m_yh; | |
| 231 | } | |
| 232 | if (x2 >= m_rdp->GetScissor()->m_xl) | |
| 233 | { | |
| 234 | x2 = m_rdp->GetScissor()->m_xl - 1; | |
| 235 | } | |
| 236 | if (y2 >= m_rdp->GetScissor()->m_yl) | |
| 237 | { | |
| 238 | y2 = m_rdp->GetScissor()->m_yl - 1; | |
| 239 | } | |
| 240 | ||
| 241 | m_rdp->GetShadeColor()->c = 0; // Needed by Command & Conquer menus | |
| 242 | ||
| 243 | if(m_other_modes->rgb_dither_sel == 0) | |
| 244 | { | |
| 245 | for (j=y1; j <= y2; j++) | |
| 246 | { | |
| 247 | Color c1; | |
| 248 | Color c2; | |
| 249 | int dith = 0; | |
| 250 | index = j * m_misc_state->m_fb_width; | |
| 251 | for (i=x1; i <= x2; i++) | |
| 252 | { | |
| 253 | m_misc_state->m_curpixel_cvg = (i & 1) ? fill_cvg1 : fill_cvg2; | |
| 254 | ||
| 255 | c1.i.r = LookUpCC(*m_rdp->GetColorInputs()->combiner_rgbsub_a_r[0], | |
| 256 | *m_rdp->GetColorInputs()->combiner_rgbsub_b_r[0], | |
| 257 | *m_rdp->GetColorInputs()->combiner_rgbmul_r[0], | |
| 258 | *m_rdp->GetColorInputs()->combiner_rgbadd_r[0]); | |
| 259 | c1.i.g = LookUpCC(*m_rdp->GetColorInputs()->combiner_rgbsub_a_g[0], | |
| 260 | *m_rdp->GetColorInputs()->combiner_rgbsub_b_g[0], | |
| 261 | *m_rdp->GetColorInputs()->combiner_rgbmul_g[0], | |
| 262 | *m_rdp->GetColorInputs()->combiner_rgbadd_g[0]); | |
| 263 | c1.i.b = LookUpCC(*m_rdp->GetColorInputs()->combiner_rgbsub_a_b[0], | |
| 264 | *m_rdp->GetColorInputs()->combiner_rgbsub_b_b[0], | |
| 265 | *m_rdp->GetColorInputs()->combiner_rgbmul_b[0], | |
| 266 | *m_rdp->GetColorInputs()->combiner_rgbadd_b[0]); | |
| 267 | c1.i.a = LookUpCC(*m_rdp->GetColorInputs()->combiner_alphasub_a[0], | |
| 268 | *m_rdp->GetColorInputs()->combiner_alphasub_b[0], | |
| 269 | *m_rdp->GetColorInputs()->combiner_alphamul[0], | |
| 270 | *m_rdp->GetColorInputs()->combiner_alphaadd[0]); | |
| 271 | m_rdp->GetCombinedColor()->c = c1.c; | |
| 272 | c2.c = m_rdp->GetTexel0Color()->c; | |
| 273 | m_rdp->GetTexel0Color()->c = m_rdp->GetTexel1Color()->c; | |
| 274 | m_rdp->GetTexel1Color()->c = c2.c; | |
| 275 | c2.i.r = LookUpCC(*m_rdp->GetColorInputs()->combiner_rgbsub_a_r[1], | |
| 276 | *m_rdp->GetColorInputs()->combiner_rgbsub_b_r[1], | |
| 277 | *m_rdp->GetColorInputs()->combiner_rgbmul_r[1], | |
| 278 | *m_rdp->GetColorInputs()->combiner_rgbadd_r[1]); | |
| 279 | c2.i.g = LookUpCC(*m_rdp->GetColorInputs()->combiner_rgbsub_a_g[1], | |
| 280 | *m_rdp->GetColorInputs()->combiner_rgbsub_b_g[1], | |
| 281 | *m_rdp->GetColorInputs()->combiner_rgbmul_g[1], | |
| 282 | *m_rdp->GetColorInputs()->combiner_rgbadd_g[1]); | |
| 283 | c2.i.b = LookUpCC(*m_rdp->GetColorInputs()->combiner_rgbsub_a_b[1], | |
| 284 | *m_rdp->GetColorInputs()->combiner_rgbsub_b_b[1], | |
| 285 | *m_rdp->GetColorInputs()->combiner_rgbmul_b[1], | |
| 286 | *m_rdp->GetColorInputs()->combiner_rgbadd_b[1]); | |
| 287 | c2.i.a = LookUpCC(*m_rdp->GetColorInputs()->combiner_alphasub_a[1], | |
| 288 | *m_rdp->GetColorInputs()->combiner_alphasub_b[1], | |
| 289 | *m_rdp->GetColorInputs()->combiner_alphamul[1], | |
| 290 | *m_rdp->GetColorInputs()->combiner_alphaadd[1]); | |
| 291 | m_rdp->GetAlphaCvg(&c2.i.a); | |
| 292 | ||
| 293 | dith = m_rdp->GetMagicMatrix()[(((j) & 3) << 2) + ((i ^ WORD_ADDR_XOR) & 3)]; | |
| 294 | m_blender->Blend(&fb[(index + i) ^ WORD_ADDR_XOR], &hb[(index + i) ^ BYTE_ADDR_XOR], c1, c2, dith); | |
| 295 | } | |
| 296 | } | |
| 297 | } | |
| 298 | else if(m_other_modes->rgb_dither_sel == 1) | |
| 299 | { | |
| 300 | for (j=y1; j <= y2; j++) | |
| 301 | { | |
| 302 | Color c1; | |
| 303 | Color c2; | |
| 304 | int dith = 0; | |
| 305 | index = j * m_misc_state->m_fb_width; | |
| 306 | for (i=x1; i <= x2; i++) | |
| 307 | { | |
| 308 | m_misc_state->m_curpixel_cvg = (i & 1) ? fill_cvg1 : fill_cvg2; | |
| 309 | ||
| 310 | c1.i.r = LookUpCC(*m_rdp->GetColorInputs()->combiner_rgbsub_a_r[0], | |
| 311 | *m_rdp->GetColorInputs()->combiner_rgbsub_b_r[0], | |
| 312 | *m_rdp->GetColorInputs()->combiner_rgbmul_r[0], | |
| 313 | *m_rdp->GetColorInputs()->combiner_rgbadd_r[0]); | |
| 314 | c1.i.g = LookUpCC(*m_rdp->GetColorInputs()->combiner_rgbsub_a_g[0], | |
| 315 | *m_rdp->GetColorInputs()->combiner_rgbsub_b_g[0], | |
| 316 | *m_rdp->GetColorInputs()->combiner_rgbmul_g[0], | |
| 317 | *m_rdp->GetColorInputs()->combiner_rgbadd_g[0]); | |
| 318 | c1.i.b = LookUpCC(*m_rdp->GetColorInputs()->combiner_rgbsub_a_b[0], | |
| 319 | *m_rdp->GetColorInputs()->combiner_rgbsub_b_b[0], | |
| 320 | *m_rdp->GetColorInputs()->combiner_rgbmul_b[0], | |
| 321 | *m_rdp->GetColorInputs()->combiner_rgbadd_b[0]); | |
| 322 | c1.i.a = LookUpCC(*m_rdp->GetColorInputs()->combiner_alphasub_a[0], | |
| 323 | *m_rdp->GetColorInputs()->combiner_alphasub_b[0], | |
| 324 | *m_rdp->GetColorInputs()->combiner_alphamul[0], | |
| 325 | *m_rdp->GetColorInputs()->combiner_alphaadd[0]); | |
| 326 | m_rdp->GetCombinedColor()->c = c1.c; | |
| 327 | c2.c = m_rdp->GetTexel0Color()->c; | |
| 328 | m_rdp->GetTexel0Color()->c = m_rdp->GetTexel1Color()->c; | |
| 329 | m_rdp->GetTexel1Color()->c = c2.c; | |
| 330 | c2.i.r = LookUpCC(*m_rdp->GetColorInputs()->combiner_rgbsub_a_r[1], | |
| 331 | *m_rdp->GetColorInputs()->combiner_rgbsub_b_r[1], | |
| 332 | *m_rdp->GetColorInputs()->combiner_rgbmul_r[1], | |
| 333 | *m_rdp->GetColorInputs()->combiner_rgbadd_r[1]); | |
| 334 | c2.i.g = LookUpCC(*m_rdp->GetColorInputs()->combiner_rgbsub_a_g[1], | |
| 335 | *m_rdp->GetColorInputs()->combiner_rgbsub_b_g[1], | |
| 336 | *m_rdp->GetColorInputs()->combiner_rgbmul_g[1], | |
| 337 | *m_rdp->GetColorInputs()->combiner_rgbadd_g[1]); | |
| 338 | c2.i.b = LookUpCC(*m_rdp->GetColorInputs()->combiner_rgbsub_a_b[1], | |
| 339 | *m_rdp->GetColorInputs()->combiner_rgbsub_b_b[1], | |
| 340 | *m_rdp->GetColorInputs()->combiner_rgbmul_b[1], | |
| 341 | *m_rdp->GetColorInputs()->combiner_rgbadd_b[1]); | |
| 342 | c2.i.a = LookUpCC(*m_rdp->GetColorInputs()->combiner_alphasub_a[1], | |
| 343 | *m_rdp->GetColorInputs()->combiner_alphasub_b[1], | |
| 344 | *m_rdp->GetColorInputs()->combiner_alphamul[1], | |
| 345 | *m_rdp->GetColorInputs()->combiner_alphaadd[1]); | |
| 346 | m_rdp->GetAlphaCvg(&c2.i.a); | |
| 347 | ||
| 348 | dith = m_rdp->GetBayerMatrix()[(((j) & 3) << 2) + ((i ^ WORD_ADDR_XOR) & 3)]; | |
| 349 | m_blender->Blend(&fb[(index + i) ^ WORD_ADDR_XOR], &hb[(index + i) ^ BYTE_ADDR_XOR], c1, c2, dith); | |
| 350 | } | |
| 351 | } | |
| 352 | } | |
| 353 | else | |
| 354 | { | |
| 355 | for (j=y1; j <= y2; j++) | |
| 356 | { | |
| 357 | Color c1, c2; | |
| 358 | index = j * m_misc_state->m_fb_width; | |
| 359 | for (i=x1; i <= x2; i++) | |
| 360 | { | |
| 361 | m_misc_state->m_curpixel_cvg = (i & 1) ? fill_cvg1 : fill_cvg2; | |
| 362 | ||
| 363 | c1.i.r = LookUpCC(*m_rdp->GetColorInputs()->combiner_rgbsub_a_r[0], | |
| 364 | *m_rdp->GetColorInputs()->combiner_rgbsub_b_r[0], | |
| 365 | *m_rdp->GetColorInputs()->combiner_rgbmul_r[0], | |
| 366 | *m_rdp->GetColorInputs()->combiner_rgbadd_r[0]); | |
| 367 | c1.i.g = LookUpCC(*m_rdp->GetColorInputs()->combiner_rgbsub_a_g[0], | |
| 368 | *m_rdp->GetColorInputs()->combiner_rgbsub_b_g[0], | |
| 369 | *m_rdp->GetColorInputs()->combiner_rgbmul_g[0], | |
| 370 | *m_rdp->GetColorInputs()->combiner_rgbadd_g[0]); | |
| 371 | c1.i.b = LookUpCC(*m_rdp->GetColorInputs()->combiner_rgbsub_a_b[0], | |
| 372 | *m_rdp->GetColorInputs()->combiner_rgbsub_b_b[0], | |
| 373 | *m_rdp->GetColorInputs()->combiner_rgbmul_b[0], | |
| 374 | *m_rdp->GetColorInputs()->combiner_rgbadd_b[0]); | |
| 375 | c1.i.a = LookUpCC(*m_rdp->GetColorInputs()->combiner_alphasub_a[0], | |
| 376 | *m_rdp->GetColorInputs()->combiner_alphasub_b[0], | |
| 377 | *m_rdp->GetColorInputs()->combiner_alphamul[0], | |
| 378 | *m_rdp->GetColorInputs()->combiner_alphaadd[0]); | |
| 379 | m_rdp->GetCombinedColor()->c = c1.c; | |
| 380 | c2.c = m_rdp->GetTexel0Color()->c; | |
| 381 | m_rdp->GetTexel0Color()->c = m_rdp->GetTexel1Color()->c; | |
| 382 | m_rdp->GetTexel1Color()->c = c2.c; | |
| 383 | c2.i.r = LookUpCC(*m_rdp->GetColorInputs()->combiner_rgbsub_a_r[1], | |
| 384 | *m_rdp->GetColorInputs()->combiner_rgbsub_b_r[1], | |
| 385 | *m_rdp->GetColorInputs()->combiner_rgbmul_r[1], | |
| 386 | *m_rdp->GetColorInputs()->combiner_rgbadd_r[1]); | |
| 387 | c2.i.g = LookUpCC(*m_rdp->GetColorInputs()->combiner_rgbsub_a_g[1], | |
| 388 | *m_rdp->GetColorInputs()->combiner_rgbsub_b_g[1], | |
| 389 | *m_rdp->GetColorInputs()->combiner_rgbmul_g[1], | |
| 390 | *m_rdp->GetColorInputs()->combiner_rgbadd_g[1]); | |
| 391 | c2.i.b = LookUpCC(*m_rdp->GetColorInputs()->combiner_rgbsub_a_b[1], | |
| 392 | *m_rdp->GetColorInputs()->combiner_rgbsub_b_b[1], | |
| 393 | *m_rdp->GetColorInputs()->combiner_rgbmul_b[1], | |
| 394 | *m_rdp->GetColorInputs()->combiner_rgbadd_b[1]); | |
| 395 | c2.i.a = LookUpCC(*m_rdp->GetColorInputs()->combiner_alphasub_a[1], | |
| 396 | *m_rdp->GetColorInputs()->combiner_alphasub_b[1], | |
| 397 | *m_rdp->GetColorInputs()->combiner_alphamul[1], | |
| 398 | *m_rdp->GetColorInputs()->combiner_alphaadd[1]); | |
| 399 | m_rdp->GetAlphaCvg(&c2.i.a); | |
| 400 | ||
| 401 | m_blender->Blend(&fb[(index + i) ^ WORD_ADDR_XOR], &hb[(index + i) ^ BYTE_ADDR_XOR], c1, c2, 0); | |
| 402 | } | |
| 403 | } | |
| 404 | } | |
| 405 | } | |
| 406 | ||
| 407 | void Rectangle::DrawFill() | |
| 408 | { | |
| 409 | UINT16 *fb = (UINT16*)&rdram[(m_misc_state->m_fb_address / 4)]; | |
| 410 | UINT8* hb = &m_rdp->GetHiddenBits()[m_misc_state->m_fb_address >> 1]; | |
| 411 | ||
| 412 | int index, i, j; | |
| 413 | int x1 = m_xh >> 2; | |
| 414 | int x2 = m_xl >> 2; | |
| 415 | int y1 = m_yh >> 2; | |
| 416 | int y2 = m_yl >> 2; | |
| 417 | UINT16 fill_color1; | |
| 418 | UINT16 fill_color2; | |
| 419 | int fill_cvg1; | |
| 420 | int fill_cvg2; | |
| 421 | ||
| 422 | if (x2 <= x1) | |
| 423 | { | |
| 424 | x2=x1+1; // SCARS (E) | |
| 425 | } | |
| 426 | if (y2 == y1) | |
| 427 | { | |
| 428 | y2=y1+1; // Goldeneye | |
| 429 | } | |
| 430 | ||
| 431 | ||
| 432 | fill_color1 = (m_rdp->GetFillColor32() >> 16) & 0xffff; | |
| 433 | fill_color2 = (m_rdp->GetFillColor32() >> 0) & 0xffff; | |
| 434 | fill_cvg1 = (fill_color1 & 1) ? 8 : 1; | |
| 435 | fill_cvg2 = (fill_color2 & 1) ? 8 : 1; | |
| 436 | ||
| 437 | // clip | |
| 438 | if (x1 < m_rdp->GetScissor()->m_xh) | |
| 439 | { | |
| 440 | x1 = m_rdp->GetScissor()->m_xh; | |
| 441 | } | |
| 442 | if (y1 < m_rdp->GetScissor()->m_yh) | |
| 443 | { | |
| 444 | y1 = m_rdp->GetScissor()->m_yh; | |
| 445 | } | |
| 446 | if (x2 >= m_rdp->GetScissor()->m_xl) | |
| 447 | { | |
| 448 | x2 = m_rdp->GetScissor()->m_xl - 1; | |
| 449 | } | |
| 450 | if (y2 >= m_rdp->GetScissor()->m_yl) | |
| 451 | { | |
| 452 | y2 = m_rdp->GetScissor()->m_yl - 1; | |
| 453 | } | |
| 454 | ||
| 455 | m_rdp->GetShadeColor()->c = 0; // Needed by Command & Conquer menus | |
| 456 | ||
| 457 | fill_cvg1 = (fill_color1 & 1) ? 3 : 0; | |
| 458 | fill_cvg2 = (fill_color2 & 1) ? 3 : 0; | |
| 459 | ||
| 460 | if(x1 & 1) | |
| 461 | { | |
| 462 | for (j=y1; j <= y2; j++) | |
| 463 | { | |
| 464 | index = j * m_misc_state->m_fb_width; | |
| 465 | for (i=x1; i <= x2; i += 2) | |
| 466 | { | |
| 467 | int curpixel = index + i; | |
| 468 | fb[curpixel ^ WORD_ADDR_XOR] = fill_color2; | |
| 469 | hb[curpixel ^ BYTE_ADDR_XOR] = fill_cvg2; | |
| 470 | } | |
| 471 | } | |
| 472 | for (j=y1; j <= y2; j++) | |
| 473 | { | |
| 474 | index = j * m_misc_state->m_fb_width; | |
| 475 | for (i=x1+1; i <= x2; i += 2) | |
| 476 | { | |
| 477 | int curpixel = index + i; | |
| 478 | fb[curpixel ^ WORD_ADDR_XOR] = fill_color1; | |
| 479 | hb[curpixel ^ BYTE_ADDR_XOR] = fill_cvg1; | |
| 480 | } | |
| 481 | } | |
| 482 | } | |
| 483 | else | |
| 484 | { | |
| 485 | for (j=y1; j <= y2; j++) | |
| 486 | { | |
| 487 | index = j * m_misc_state->m_fb_width; | |
| 488 | for (i=x1; i <= x2; i += 2) | |
| 489 | { | |
| 490 | int curpixel = index + i; | |
| 491 | fb[curpixel ^ WORD_ADDR_XOR] = fill_color1; | |
| 492 | hb[curpixel ^ BYTE_ADDR_XOR] = fill_cvg1; | |
| 493 | } | |
| 494 | } | |
| 495 | for (j=y1; j <= y2; j++) | |
| 496 | { | |
| 497 | index = j * m_misc_state->m_fb_width; | |
| 498 | for (i=x1+1; i <= x2; i += 2) | |
| 499 | { | |
| 500 | int curpixel = index + i; | |
| 501 | fb[curpixel ^ WORD_ADDR_XOR] = fill_color2; | |
| 502 | hb[curpixel ^ BYTE_ADDR_XOR] = fill_cvg2; | |
| 503 | } | |
| 504 | } | |
| 505 | } | |
| 506 | } | |
| 507 | ||
| 508 | } // namespace RDP | |
| 509 | ||
| 510 | } // namespace N64 |
| r9854 | r9855 | |
|---|---|---|
| 1 | #ifndef _VIDEO_RDPFILLRECT_H_ | |
| 2 | #define _VIDEO_RDPFILLRECT_H_ | |
| 3 | ||
| 4 | #include "emu.h" | |
| 5 | #include "video/rdpblend.h" | |
| 6 | ||
| 7 | namespace N64 | |
| 8 | { | |
| 9 | ||
| 10 | namespace RDP | |
| 11 | { | |
| 12 | ||
| 13 | class OtherModes; | |
| 14 | class MiscState; | |
| 15 | class Processor; | |
| 16 | class Blender; | |
| 17 | class Color; | |
| 18 | ||
| 19 | class Rectangle | |
| 20 | { | |
| 21 | public: | |
| 22 | Rectangle() {} | |
| 23 | Rectangle(running_machine *machine, UINT32 *data) | |
| 24 | { | |
| 25 | SetMachine(machine); | |
| 26 | InitFromBuffer(data); | |
| 27 | } | |
| 28 | ||
| 29 | void Draw(); | |
| 30 | void SetMachine(running_machine *machine); | |
| 31 | void InitFromBuffer(UINT32 *data); | |
| 32 | ||
| 33 | UINT16 m_xl; // 10.2 fixed-point | |
| 34 | UINT16 m_yl; // 10.2 fixed-point | |
| 35 | UINT16 m_xh; // 10.2 fixed-point | |
| 36 | UINT16 m_yh; // 10.2 fixed-point | |
| 37 | ||
| 38 | private: | |
| 39 | void Draw1Cycle(); | |
| 40 | void Draw2Cycle(); | |
| 41 | void DrawFill(); | |
| 42 | ||
| 43 | running_machine* m_machine; | |
| 44 | Processor* m_rdp; | |
| 45 | MiscState* m_misc_state; | |
| 46 | OtherModes* m_other_modes; | |
| 47 | Blender* m_blender; | |
| 48 | }; | |
| 49 | ||
| 50 | } // namespace RDP | |
| 51 | ||
| 52 | } // namespace N64 | |
| 53 | ||
| 54 | #endif // _VIDEO_RDPFILLRECT_H_ |
| r9854 | r9855 | |
|---|---|---|
| 1 | #include "emu.h" | |
| 2 | #include "includes/n64.h" | |
| 3 | #include "video/n64.h" | |
| 4 | ||
| 5 | namespace N64 | |
| 6 | { | |
| 7 | ||
| 8 | namespace RDP | |
| 9 | { | |
| 10 | ||
| 11 | void TexFetch::SetMachine(running_machine *machine) | |
| 12 | { | |
| 13 | _n64_state *state = machine->driver_data<_n64_state>(); | |
| 14 | ||
| 15 | m_machine = machine; | |
| 16 | m_rdp = &state->m_rdp; | |
| 17 | m_other_modes = m_rdp->GetOtherModes(); | |
| 18 | m_misc_state = m_rdp->GetMiscState(); | |
| 19 | m_tiles = m_rdp->GetTiles(); | |
| 20 | } | |
| 21 | ||
| 22 | UINT32 TexFetch::Fetch(UINT32 s, UINT32 t, Tile* tile) | |
| 23 | { | |
| 24 | UINT32 tformat = tile->format; | |
| 25 | ||
| 26 | if (t < 0) t = 0; | |
| 27 | if (s < 0) s = 0; | |
| 28 | ||
| 29 | switch (tformat) | |
| 30 | { | |
| 31 | case 0: // RGBA | |
| 32 | return FetchRGBA(s, t, tile); | |
| 33 | ||
| 34 | case 1: // YUV: Bottom of the 9th, Pokemon Stadium, Ogre Battle 64 | |
| 35 | return FetchYUV(s, t, tile); | |
| 36 | ||
| 37 | case 2: // Color Index | |
| 38 | return FetchCI(s, t, tile); | |
| 39 | ||
| 40 | case 3: // Intensity + Alpha | |
| 41 | return FetchIA(s, t, tile); | |
| 42 | ||
| 43 | case 4: // Intensity | |
| 44 | return FetchI(s, t, tile); | |
| 45 | ||
| 46 | default: | |
| 47 | fatalerror("FETCH_TEXEL: unknown texture format %d\n", tformat); | |
| 48 | return 0xffffffff; | |
| 49 | } | |
| 50 | ||
| 51 | return 0; | |
| 52 | } | |
| 53 | ||
| 54 | UINT32 TexFetch::FetchRGBA(UINT32 s, UINT32 t, Tile* tile) | |
| 55 | { | |
| 56 | UINT32 twidth = tile->line; | |
| 57 | UINT32 tbase = tile->tmem; | |
| 58 | UINT32 tpal = tile->palette & 0xf; | |
| 59 | ||
| 60 | switch (tile->size) | |
| 61 | { | |
| 62 | case PIXEL_SIZE_4BIT: | |
| 63 | { | |
| 64 | UINT8 *tc = (UINT8*)m_rdp->GetTMEM(); | |
| 65 | int taddr = ((tbase + ((t) * twidth) + ((s) / 2)) ^ ((t & 1) ? XOR_SWAP_BYTE : 0)) & 0x7ff; | |
| 66 | UINT8 p = ((s) & 1) ? (tc[taddr ^ BYTE_ADDR_XOR] & 0xf) : (tc[taddr ^ BYTE_ADDR_XOR] >> 4); | |
| 67 | UINT16 c = m_rdp->GetTLUT()[(((tpal << 4) | p) ^ WORD_ADDR_XOR) << 2]; | |
| 68 | ||
| 69 | if (m_other_modes->en_tlut) | |
| 70 | { | |
| 71 | if (m_other_modes->tlut_type == 0) | |
| 72 | { | |
| 73 | return m_rdp->LookUp16To32(c); | |
| 74 | } | |
| 75 | else | |
| 76 | { | |
| 77 | return m_rdp->LookUpIA8To32(c); | |
| 78 | } | |
| 79 | } | |
| 80 | else | |
| 81 | { | |
| 82 | return ((tpal << 4) | p) * 0x01010101; | |
| 83 | } | |
| 84 | break; | |
| 85 | } | |
| 86 | case PIXEL_SIZE_8BIT: | |
| 87 | { | |
| 88 | UINT8 *tc = m_rdp->GetTMEM(); | |
| 89 | int taddr = ((tbase + ((t) * twidth) + ((s))) ^ ((t & 1) ? XOR_SWAP_BYTE : 0)) & 0x7ff; | |
| 90 | UINT8 p = tc[taddr ^ BYTE_ADDR_XOR]; | |
| 91 | UINT16 c = m_rdp->GetTLUT()[(p ^ WORD_ADDR_XOR) << 2]; | |
| 92 | ||
| 93 | if (m_other_modes->en_tlut) | |
| 94 | { | |
| 95 | if (m_other_modes->tlut_type == 0) | |
| 96 | { | |
| 97 | return m_rdp->LookUp16To32(c); | |
| 98 | } | |
| 99 | else | |
| 100 | { | |
| 101 | return m_rdp->LookUpIA8To32(c); | |
| 102 | } | |
| 103 | } | |
| 104 | else | |
| 105 | { | |
| 106 | return p * 0x01010101; | |
| 107 | } | |
| 108 | break; | |
| 109 | } | |
| 110 | case PIXEL_SIZE_16BIT: | |
| 111 | { | |
| 112 | UINT16 *tc = m_rdp->GetTMEM16(); | |
| 113 | int taddr = ((tbase>>1) + ((t) * (twidth>>1)) + (s)) ^ ((t & 1) ? XOR_SWAP_WORD : 0); | |
| 114 | UINT16 c = tc[(taddr & 0x7ff) ^ WORD_ADDR_XOR]; // PGA European Tour (U) | |
| 115 | ||
| 116 | if (!m_other_modes->en_tlut) | |
| 117 | { | |
| 118 | return m_rdp->LookUp16To32(c); | |
| 119 | } | |
| 120 | else | |
| 121 | { | |
| 122 | if (m_other_modes->tlut_type == 0) //Golden Eye 007, sea, "frigate" level | |
| 123 | { | |
| 124 | return m_rdp->LookUp16To32(m_rdp->GetTLUT()[(c >> 8) << 2]); | |
| 125 | } | |
| 126 | else // Beetle Adventure Racing, Mount Mayhem | |
| 127 | { | |
| 128 | return m_rdp->LookUpIA8To32(m_rdp->GetTLUT()[(c >> 8) << 2]); | |
| 129 | } | |
| 130 | } | |
| 131 | break; | |
| 132 | } | |
| 133 | case PIXEL_SIZE_32BIT: | |
| 134 | { | |
| 135 | UINT32 *tc = m_rdp->GetTMEM32(); | |
| 136 | int xorval = (m_misc_state->m_fb_size == PIXEL_SIZE_16BIT) ? XOR_SWAP_WORD : XOR_SWAP_DWORD; // Conker's Bad Fur Day, Jet Force Gemini, Super Smash Bros., Mickey's Speedway USA, Ogre Battle, Wave Race, Gex 3, South Park Rally | |
| 137 | int taddr = (((tbase >> 2) + ((t) * (twidth >> 1)) + (s)) ^ ((t & 1) ? xorval : 0)) & 0x3ff; | |
| 138 | ||
| 139 | if (!m_other_modes->en_tlut) | |
| 140 | { | |
| 141 | return tc[taddr]; | |
| 142 | } | |
| 143 | else | |
| 144 | { | |
| 145 | if (!m_other_modes->tlut_type) | |
| 146 | { | |
| 147 | return m_rdp->LookUp16To32(m_rdp->GetTLUT()[(tc[taddr] >> 24) << 2]); | |
| 148 | } | |
| 149 | else | |
| 150 | { | |
| 151 | return m_rdp->LookUpIA8To32(m_rdp->GetTLUT()[(tc[taddr] >> 24) << 2]); | |
| 152 | } | |
| 153 | } | |
| 154 | break; | |
| 155 | } | |
| 156 | default: | |
| 157 | fatalerror("FETCH_TEXEL: unknown RGBA texture size %d\n", tile->size); | |
| 158 | return 0xffffffff; | |
| 159 | } | |
| 160 | } | |
| 161 | ||
| 162 | UINT32 TexFetch::FetchYUV(UINT32 s, UINT32 t, Tile* tile) | |
| 163 | { | |
| 164 | UINT32 twidth = tile->line; | |
| 165 | UINT32 tsize = tile->size; | |
| 166 | UINT32 tbase = tile->tmem; | |
| 167 | Color out; | |
| 168 | ||
| 169 | out.c = 0; | |
| 170 | ||
| 171 | if(tsize == PIXEL_SIZE_16BIT) | |
| 172 | { | |
| 173 | INT32 newr = 0; | |
| 174 | INT32 newg = 0; | |
| 175 | INT32 newb = 0; | |
| 176 | UINT16 *tc = m_rdp->GetTMEM16(); | |
| 177 | int taddr = ((tbase >> 1) + ((t) * (twidth)) + (s)) ^ ((t & 1) ? XOR_SWAP_WORD : 0); | |
| 178 | UINT16 c1, c2; | |
| 179 | INT32 y; | |
| 180 | INT32 u, v; | |
| 181 | c1 = tc[taddr ^ WORD_ADDR_XOR]; | |
| 182 | c2 = tc[taddr]; // other word | |
| 183 | ||
| 184 | if (!(taddr & 1)) | |
| 185 | { | |
| 186 | v = c2 >> 8; | |
| 187 | u = c1 >> 8; | |
| 188 | y = c1 & 0xff; | |
| 189 | } | |
| 190 | else | |
| 191 | { | |
| 192 | v = c1 >> 8; | |
| 193 | u = c2 >> 8; | |
| 194 | y = c1 & 0xff; | |
| 195 | } | |
| 196 | v -= 128; | |
| 197 | u -= 128; | |
| 198 | ||
| 199 | if (!m_other_modes->bi_lerp0) | |
| 200 | { | |
| 201 | newr = y + ((m_rdp->GetK0() * v) >> 8); | |
| 202 | newg = y + ((m_rdp->GetK1() * u) >> 8) + ((m_rdp->GetK2() * v) >> 8); | |
| 203 | newb = y + ((m_rdp->GetK2() * u) >> 8); | |
| 204 | } | |
| 205 | out.i.r = (newr < 0) ? 0 : ((newr > 0xff) ? 0xff : newr); | |
| 206 | out.i.g = (newg < 0) ? 0 : ((newg > 0xff) ? 0xff : newg); | |
| 207 | out.i.b = (newb < 0) ? 0 : ((newb > 0xff) ? 0xff : newb); | |
| 208 | out.i.a = 0xff; | |
| 209 | } | |
| 210 | ||
| 211 | return out.c; | |
| 212 | } | |
| 213 | ||
| 214 | UINT32 TexFetch::FetchCI(UINT32 s, UINT32 t, Tile* tile) | |
| 215 | { | |
| 216 | UINT32 twidth = tile->line; | |
| 217 | UINT32 tsize = tile->size; | |
| 218 | UINT32 tbase = tile->tmem; | |
| 219 | UINT32 tpal = tile->palette & 0xf; | |
| 220 | ||
| 221 | switch (tsize) | |
| 222 | { | |
| 223 | case PIXEL_SIZE_4BIT: | |
| 224 | { | |
| 225 | UINT8 *tc = m_rdp->GetTMEM(); | |
| 226 | int taddr = ((tbase + ((t) * twidth) + ((s) / 2)) ^ ((t & 1) ? XOR_SWAP_BYTE : 0)) & 0x7ff; | |
| 227 | UINT8 p = ((s) & 1) ? (tc[taddr ^ BYTE_ADDR_XOR] & 0xf) : (tc[taddr ^ BYTE_ADDR_XOR] >> 4); | |
| 228 | UINT16 c = m_rdp->GetTLUT()[((tpal << 4) | p) << 2]; | |
| 229 | ||
| 230 | if (m_other_modes->en_tlut) | |
| 231 | { | |
| 232 | if (m_other_modes->tlut_type == 0) | |
| 233 | { | |
| 234 | return m_rdp->LookUp16To32(c); | |
| 235 | } | |
| 236 | else | |
| 237 | { | |
| 238 | return m_rdp->LookUpIA8To32(c); | |
| 239 | } | |
| 240 | } | |
| 241 | else | |
| 242 | { | |
| 243 | return ((tpal << 4) | p) * 0x01010101; | |
| 244 | } | |
| 245 | break; | |
| 246 | } | |
| 247 | case PIXEL_SIZE_8BIT: | |
| 248 | { | |
| 249 | UINT8 *tc = m_rdp->GetTMEM(); | |
| 250 | int taddr = ((tbase + ((t) * twidth) + ((s))) ^ ((t & 1) ? XOR_SWAP_BYTE : 0)) & 0x7ff; | |
| 251 | UINT8 p = tc[taddr ^ BYTE_ADDR_XOR]; | |
| 252 | UINT16 c = m_rdp->GetTLUT()[p << 2]; | |
| 253 | ||
| 254 | if (m_other_modes->en_tlut) | |
| 255 | { | |
| 256 | if (m_other_modes->tlut_type == 0) | |
| 257 | { | |
| 258 | return m_rdp->LookUp16To32(c); | |
| 259 | } | |
| 260 | else | |
| 261 | { | |
| 262 | return m_rdp->LookUpIA8To32(c); | |
| 263 | } | |
| 264 | } | |
| 265 | else | |
| 266 | { | |
| 267 | return p * 0x01010101; | |
| 268 | } | |
| 269 | break; | |
| 270 | } | |
| 271 | case PIXEL_SIZE_16BIT: | |
| 272 | { | |
| 273 | // 16-bit CI is a "valid" mode; some games use it, it behaves the same as 16-bit RGBA | |
| 274 | UINT16 *tc = m_rdp->GetTMEM16(); | |
| 275 | int taddr = ((tbase>>1) + ((t) * (twidth>>1)) + (s)) ^ ((t & 1) ? XOR_SWAP_WORD : 0); | |
| 276 | UINT16 c = tc[(taddr & 0x7ff) ^ WORD_ADDR_XOR]; // PGA European Tour (U) | |
| 277 | ||
| 278 | if (!m_other_modes->en_tlut) | |
| 279 | { | |
| 280 | return m_rdp->LookUp16To32(c); | |
| 281 | } | |
| 282 | else | |
| 283 | { | |
| 284 | if (!m_other_modes->tlut_type) // GoldenEye 007, sea, "frigate" level | |
| 285 | { | |
| 286 | return m_rdp->LookUp16To32(m_rdp->GetTLUT()[(c >> 8) << 2]); | |
| 287 | } | |
| 288 | else // Beetle Adventure Racing, Mount Mayhem | |
| 289 | { | |
| 290 | return m_rdp->LookUpIA8To32(m_rdp->GetTLUT()[(c >> 8) << 2]); | |
| 291 | } | |
| 292 | } | |
| 293 | break; | |
| 294 | } | |
| 295 | ||
| 296 | default: | |
| 297 | fatalerror("FETCH_TEXEL: unknown CI texture size %d\n", tsize); | |
| 298 | return 0xffffffff; | |
| 299 | } | |
| 300 | ||
| 301 | return 0; | |
| 302 | } | |
| 303 | ||
| 304 | UINT32 TexFetch::FetchIA(UINT32 s, UINT32 t, Tile* tile) | |
| 305 | { | |
| 306 | UINT32 twidth = tile->line; | |
| 307 | UINT32 tsize = tile->size; | |
| 308 | UINT32 tbase = tile->tmem; | |
| 309 | UINT32 tpal = tile->palette & 0xf; | |
| 310 | ||
| 311 | switch (tsize) | |
| 312 | { | |
| 313 | case PIXEL_SIZE_4BIT: | |
| 314 | { | |
| 315 | UINT8 *tc = m_rdp->GetTMEM(); | |
| 316 | int taddr = (tbase + ((t) * twidth) + (s >> 1)) ^ ((t & 1) ? XOR_SWAP_BYTE : 0); | |
| 317 | UINT8 p = ((s) & 1) ? (tc[taddr ^ BYTE_ADDR_XOR] & 0xf) : (tc[taddr ^ BYTE_ADDR_XOR] >> 4); | |
| 318 | UINT8 i = ((p & 0xe) << 4) | ((p & 0xe) << 1) | (p & 0xe >> 2); | |
| 319 | ||
| 320 | if (!m_other_modes->en_tlut) | |
| 321 | { | |
| 322 | return (i * 0x01010100) | ((p & 0x1) ? 0xff : 0); | |
| 323 | } | |
| 324 | else | |
| 325 | { | |
| 326 | UINT16 c = m_rdp->GetTLUT()[((tpal << 4) | p) << 2]; | |
| 327 | if (!m_other_modes->tlut_type) | |
| 328 | { | |
| 329 | return m_rdp->LookUp16To32(c); | |
| 330 | } | |
| 331 | else | |
| 332 | { | |
| 333 | return m_rdp->LookUpIA8To32(c); | |
| 334 | } | |
| 335 | } | |
| 336 | break; | |
| 337 | } | |
| 338 | case PIXEL_SIZE_8BIT: | |
| 339 | { | |
| 340 | UINT8 *tc = m_rdp->GetTMEM(); | |
| 341 | int taddr = ((tbase + ((t) * twidth) + ((s))) ^ ((t & 1) ? XOR_SWAP_BYTE : 0)) & 0xfff; | |
| 342 | UINT8 p = tc[taddr ^ BYTE_ADDR_XOR]; | |
| 343 | ||
| 344 | if (!m_other_modes->en_tlut) | |
| 345 | { | |
| 346 | UINT8 i = (p >> 4) | (p & 0xf0); | |
| 347 | return (i * 0x01010100) | ((p & 0xf) | ((p << 4) & 0xf0)); | |
| 348 | } | |
| 349 | else | |
| 350 | { | |
| 351 | UINT16 c = m_rdp->GetTLUT()[p << 2]; | |
| 352 | if (!m_other_modes->tlut_type) | |
| 353 | { | |
| 354 | return m_rdp->LookUp16To32(c); | |
| 355 | } | |
| 356 | else | |
| 357 | { | |
| 358 | return m_rdp->LookUpIA8To32(c); | |
| 359 | } | |
| 360 | } | |
| 361 | break; | |
| 362 | } | |
| 363 | case PIXEL_SIZE_16BIT: | |
| 364 | { | |
| 365 | UINT16 *tc = m_rdp->GetTMEM16(); | |
| 366 | int taddr = ((tbase >> 1) + ((t) * (twidth >> 1)) + (s)) ^ ((t & 1) ? XOR_SWAP_WORD : 0); | |
| 367 | UINT16 c = tc[taddr ^ WORD_ADDR_XOR]; | |
| 368 | ||
| 369 | if (m_other_modes->en_tlut) | |
| 370 | { | |
| 371 | c = m_rdp->GetTLUT()[(c >> 8) << 2]; | |
| 372 | if (m_other_modes->tlut_type == 0) | |
| 373 | { | |
| 374 | return m_rdp->LookUp16To32(c); | |
| 375 | } | |
| 376 | else | |
| 377 | { | |
| 378 | return m_rdp->LookUpIA8To32(c); | |
| 379 | } | |
| 380 | } | |
| 381 | else | |
| 382 | { | |
| 383 | return m_rdp->LookUpIA8To32(c); | |
| 384 | } | |
| 385 | ||
| 386 | break; | |
| 387 | } | |
| 388 | default: | |
| 389 | return 0xffffffff; | |
| 390 | fatalerror("FETCH_TEXEL: unknown IA texture size %d\n", tsize); | |
| 391 | break; | |
| 392 | } | |
| 393 | ||
| 394 | return 0; | |
| 395 | } | |
| 396 | ||
| 397 | UINT32 TexFetch::FetchI(UINT32 s, UINT32 t, Tile* tile) | |
| 398 | { | |
| 399 | UINT32 twidth = tile->line; | |
| 400 | UINT32 tsize = tile->size; | |
| 401 | UINT32 tbase = tile->tmem; | |
| 402 | UINT32 tpal = tile->palette & 0xf; | |
| 403 | ||
| 404 | switch (tsize) | |
| 405 | { | |
| 406 | case PIXEL_SIZE_4BIT: | |
| 407 | { | |
| 408 | UINT8 *tc = m_rdp->GetTMEM(); | |
| 409 | int taddr = ((tbase + ((t) * twidth) + ((s) / 2)) ^ ((t & 1) ? XOR_SWAP_BYTE : 0)) & 0xfff; | |
| 410 | UINT8 c = ((s) & 1) ? (tc[taddr ^ BYTE_ADDR_XOR] & 0xf) : (tc[taddr ^ BYTE_ADDR_XOR] >> 4); | |
| 411 | c |= (c << 4); | |
| 412 | ||
| 413 | if (!m_other_modes->en_tlut) | |
| 414 | { | |
| 415 | return c * 0x01010101; | |
| 416 | } | |
| 417 | else | |
| 418 | { | |
| 419 | UINT16 k = m_rdp->GetTLUT()[((tpal << 4) | c) << 2]; | |
| 420 | if (!m_other_modes->tlut_type) | |
| 421 | { | |
| 422 | return m_rdp->LookUp16To32(k); | |
| 423 | } | |
| 424 | else | |
| 425 | { | |
| 426 | return m_rdp->LookUpIA8To32(k); | |
| 427 | } | |
| 428 | } | |
| 429 | break; | |
| 430 | } | |
| 431 | case PIXEL_SIZE_8BIT: | |
| 432 | { | |
| 433 | UINT8 *tc = m_rdp->GetTMEM(); | |
| 434 | int taddr = ((tbase + ((t) * twidth) + ((s))) ^ ((t & 1) ? XOR_SWAP_BYTE : 0)) & 0xfff; | |
| 435 | UINT8 c = tc[taddr ^ BYTE_ADDR_XOR]; | |
| 436 | ||
| 437 | if (!m_other_modes->en_tlut) | |
| 438 | { | |
| 439 | return c * 0x01010101; | |
| 440 | } | |
| 441 | else | |
| 442 | { | |
| 443 | UINT16 k = m_rdp->GetTLUT()[ c << 2]; | |
| 444 | if (!m_other_modes->tlut_type) | |
| 445 | { | |
| 446 | return m_rdp->LookUp16To32(k); | |
| 447 | } | |
| 448 | else | |
| 449 | { | |
| 450 | return m_rdp->LookUpIA8To32(k); | |
| 451 | } | |
| 452 | } | |
| 453 | break; | |
| 454 | } | |
| 455 | default: | |
| 456 | //fatalerror("FETCH_TEXEL: unknown I texture size %d\n", tsize); | |
| 457 | return 0xffffffff; | |
| 458 | } | |
| 459 | ||
| 460 | return 0; | |
| 461 | } | |
| 462 | ||
| 463 | } // namespace RDP | |
| 464 | ||
| 465 | } // namespace N64 |
| r9854 | r9855 | |
|---|---|---|
| 1 | #ifndef _VIDEO_RDPFETCH_H_ | |
| 2 | #define _VIDEO_RDPFETCH_H_ | |
| 3 | ||
| 4 | #include "emu.h" | |
| 5 | ||
| 6 | namespace N64 | |
| 7 | { | |
| 8 | ||
| 9 | namespace RDP | |
| 10 | { | |
| 11 | ||
| 12 | class Processor; | |
| 13 | class OtherModes; | |
| 14 | class MiscState; | |
| 15 | class Tile; | |
| 16 | ||
| 17 | class TexFetch | |
| 18 | { | |
| 19 | public: | |
| 20 | TexFetch() { } | |
| 21 | ||
| 22 | UINT32 Fetch(UINT32 s, UINT32 t, Tile* tile); | |
| 23 | ||
| 24 | void SetMachine(running_machine* machine); | |
| 25 | ||
| 26 | private: | |
| 27 | running_machine* m_machine; | |
| 28 | Processor* m_rdp; | |
| 29 | OtherModes* m_other_modes; | |
| 30 | MiscState* m_misc_state; | |
| 31 | Tile* m_tiles; | |
| 32 | ||
| 33 | UINT32 FetchRGBA(UINT32 s, UINT32 t, Tile* tile); | |
| 34 | UINT32 FetchYUV(UINT32 s, UINT32 t, Tile* tile); | |
| 35 | UINT32 FetchCI(UINT32 s, UINT32 t, Tile* tile); | |
| 36 | UINT32 FetchIA(UINT32 s, UINT32 t, Tile* tile); | |
| 37 | UINT32 FetchI(UINT32 s, UINT32 t, Tile* tile); | |
| 38 | }; | |
| 39 | ||
| 40 | } // namespace RDP | |
| 41 | ||
| 42 | } // namespace N64 | |
| 43 | ||
| 44 | #endif // _VIDEO_RDPFETCH_H_ |
| r9854 | r9855 | |
|---|---|---|
| 1 | #include "emu.h" | |
| 2 | #include "includes/n64.h" | |
| 3 | #include "video/n64.h" | |
| 4 | ||
| 5 | namespace N64 | |
| 6 | { | |
| 7 | ||
| 8 | namespace RDP | |
| 9 | { | |
| 10 | ||
| 11 | #define LookUpCC(A, B, C, D) m_rdp->GetCCLUT2()[(m_rdp->GetCCLUT1()[(A << 16) | (B << 8) | C] << 8) | D] | |
| 12 | ||
| 13 | void TexRectangle::SetMachine(running_machine* machine) | |
| 14 | { | |
| 15 | _n64_state *state = machine->driver_data<_n64_state>(); | |
| 16 | ||
| 17 | m_machine = machine; | |
| 18 | m_rdp = &state->m_rdp; | |
| 19 | m_other_modes = m_rdp->GetOtherModes(); | |
| 20 | m_misc_state = m_rdp->GetMiscState(); | |
| 21 | } | |
| 22 | ||
| 23 | void TexRectangle::Draw() | |
| 24 | { | |
| 25 | switch(m_other_modes->cycle_type) | |
| 26 | { | |
| 27 | case CYCLE_TYPE_1: | |
| 28 | case CYCLE_TYPE_2: | |
| 29 | DrawDefault(); | |
| 30 | return; | |
| 31 | ||
| 32 | case CYCLE_TYPE_COPY: | |
| 33 | DrawCopy(); | |
| 34 | return; | |
| 35 | ||
| 36 | default: | |
| 37 | fatalerror("Unsupported cycle type for Textured Rectangle: %d\n", m_other_modes->cycle_type); | |
| 38 | return; | |
| 39 | } | |
| 40 | } | |
| 41 | ||
| 42 | void TexRectangle::DrawDefault() | |
| 43 | { | |
| 44 | UINT16 *fb = (UINT16*)&rdram[(m_misc_state->m_fb_address / 4)]; | |
| 45 | UINT8 *hb = &m_rdp->GetHiddenBits()[m_misc_state->m_fb_address >> 1]; | |
| 46 | UINT16 *zb = (UINT16*)&rdram[m_misc_state->m_zb_address / 4]; | |
| 47 | UINT8 *zhb = &m_rdp->GetHiddenBits()[m_misc_state->m_zb_address >> 1]; | |
| 48 | ||
| 49 | UINT32 tilenum = m_tilenum; | |
| 50 | N64::RDP::Tile *tex_tile = &m_rdp->GetTiles()[m_tilenum]; | |
| 51 | UINT32 tilenum2 = 0; | |
| 52 | N64::RDP::Tile *tex_tile2 = NULL; | |
| 53 | ||
| 54 | int x1 = m_xh >> 2; | |
| 55 | int x2 = m_xl >> 2; | |
| 56 | int y1 = m_yh >> 2; | |
| 57 | int y2 = m_yl >> 2; | |
| 58 | ||
| 59 | if (x2 <= x1) | |
| 60 | { | |
| 61 | x2 = x1 + 1; | |
| 62 | } | |
| 63 | if (y1 == y2) | |
| 64 | { | |
| 65 | y2 = y1 + 1; // Needed by Goldeneye | |
| 66 | } | |
| 67 | ||
| 68 | if ((m_xl & 3) == 3) // Needed by Mega Man 64 | |
| 69 | { | |
| 70 | x2++; | |
| 71 | } | |
| 72 | if ((m_yl & 3) == 3) | |
| 73 | { | |
| 74 | y2++; | |
| 75 | } | |
| 76 | ||
| 77 | m_rdp->GetTexPipe()->CalculateClampDiffs(tilenum); | |
| 78 | ||
| 79 | if(m_other_modes->cycle_type == CYCLE_TYPE_2) | |
| 80 | { | |
| 81 | if (!m_other_modes->tex_lod_en) | |
| 82 | { | |
| 83 | tilenum2 = (tilenum + 1) & 7; | |
| 84 | tex_tile2 = &m_rdp->GetTiles()[tilenum2]; | |
| 85 | } | |
| 86 | else | |
| 87 | { | |
| 88 | tilenum2 = (tilenum + 1) & 7; | |
| 89 | tex_tile2 = &m_rdp->GetTiles()[tilenum2]; | |
| 90 | } | |
| 91 | } | |
| 92 | ||
| 93 | m_rdp->GetShadeColor()->c = 0; // Needed by Pilotwings 64 | |
| 94 | ||
| 95 | if(y1 < m_rdp->GetScissor()->m_yh) | |
| 96 | { | |
| 97 | m_t += m_dtdy * (m_rdp->GetScissor()->m_yh - y1); | |
| 98 | y1 = m_rdp->GetScissor()->m_yh; | |
| 99 | } | |
| 100 | if(y2 > m_rdp->GetScissor()->m_yl) | |
| 101 | { | |
| 102 | y2 = m_rdp->GetScissor()->m_yl; | |
| 103 | } | |
| 104 | if(x1 < m_rdp->GetScissor()->m_xh) | |
| 105 | { | |
| 106 | m_s += m_dsdx * (m_rdp->GetScissor()->m_xh - x1); | |
| 107 | x1 = m_rdp->GetScissor()->m_xh; | |
| 108 | } | |
| 109 | if(x2 > m_rdp->GetScissor()->m_xl) | |
| 110 | { | |
| 111 | x2 = m_rdp->GetScissor()->m_xl; | |
| 112 | } | |
| 113 | m_dsdx >>= 5; | |
| 114 | m_dtdy >>= 5; | |
| 115 | ||
| 116 | int t = ((int)(m_t)); | |
| 117 | ||
| 118 | if(m_flip) | |
| 119 | { | |
| 120 | for (int j = y1; j < y2; j++) | |
| 121 | { | |
| 122 | int fb_index = j * m_misc_state->m_fb_width; | |
| 123 | int mline = 0; | |
| 124 | if(!(m_other_modes->rgb_dither_sel & 2)) | |
| 125 | { | |
| 126 | mline = (j & 3) << 2; | |
| 127 | } | |
| 128 | int s = ((int)(m_s)); | |
| 129 | ||
| 130 | for (int i = x1; i < x2; i++) | |
| 131 | { | |
| 132 | N64::RDP::Color c1; | |
| 133 | N64::RDP::Color c2; | |
| 134 | int dith = 0; | |
| 135 | int curpixel = fb_index + i; | |
| 136 | UINT16* fbcur = &fb[curpixel ^ WORD_ADDR_XOR]; | |
| 137 | UINT8* hbcur = &hb[curpixel ^ BYTE_ADDR_XOR]; | |
| 138 | UINT16* zbcur = &zb[curpixel ^ WORD_ADDR_XOR]; | |
| 139 | UINT8* zhbcur = &zhb[curpixel ^ BYTE_ADDR_XOR]; | |
| 140 | ||
| 141 | m_misc_state->m_curpixel_cvg = 8; | |
| 142 | ||
| 143 | if(m_other_modes->cycle_type == CYCLE_TYPE_1) | |
| 144 | { | |
| 145 | m_rdp->GetTexel0Color()->c = m_rdp->GetTexPipe()->Fetch(t, s, tex_tile); | |
| 146 | ||
| 147 | c1.i.r = LookUpCC(*m_rdp->GetColorInputs()->combiner_rgbsub_a_r[1], | |
| 148 | *m_rdp->GetColorInputs()->combiner_rgbsub_b_r[1], | |
| 149 | *m_rdp->GetColorInputs()->combiner_rgbmul_r[1], | |
| 150 | *m_rdp->GetColorInputs()->combiner_rgbadd_r[1]); | |
| 151 | c1.i.g = LookUpCC(*m_rdp->GetColorInputs()->combiner_rgbsub_a_g[1], | |
| 152 | *m_rdp->GetColorInputs()->combiner_rgbsub_b_g[1], | |
| 153 | *m_rdp->GetColorInputs()->combiner_rgbmul_g[1], | |
| 154 | *m_rdp->GetColorInputs()->combiner_rgbadd_g[1]); | |
| 155 | c1.i.b = LookUpCC(*m_rdp->GetColorInputs()->combiner_rgbsub_a_b[1], | |
| 156 | *m_rdp->GetColorInputs()->combiner_rgbsub_b_b[1], | |
| 157 | *m_rdp->GetColorInputs()->combiner_rgbmul_b[1], | |
| 158 | *m_rdp->GetColorInputs()->combiner_rgbadd_b[1]); | |
| 159 | c1.i.a = LookUpCC(*m_rdp->GetColorInputs()->combiner_alphasub_a[1], | |
| 160 | *m_rdp->GetColorInputs()->combiner_alphasub_b[1], | |
| 161 | *m_rdp->GetColorInputs()->combiner_alphamul[1], | |
| 162 | *m_rdp->GetColorInputs()->combiner_alphaadd[1]); | |
| 163 | m_rdp->GetAlphaCvg(&c1.i.a); | |
| 164 | } | |
| 165 | else | |
| 166 | { | |
| 167 | m_rdp->GetTexel0Color()->c = m_rdp->GetTexPipe()->Fetch(t, s, tex_tile); | |
| 168 | m_rdp->GetTexel1Color()->c = m_rdp->GetTexPipe()->Fetch(t, s, tex_tile2); | |
| 169 | ||
| 170 | c1.i.r = LookUpCC(*m_rdp->GetColorInputs()->combiner_rgbsub_a_r[0], | |
| 171 | *m_rdp->GetColorInputs()->combiner_rgbsub_b_r[0], | |
| 172 | *m_rdp->GetColorInputs()->combiner_rgbmul_r[0], | |
| 173 | *m_rdp->GetColorInputs()->combiner_rgbadd_r[0]); | |
| 174 | c1.i.g = LookUpCC(*m_rdp->GetColorInputs()->combiner_rgbsub_a_g[0], | |
| 175 | *m_rdp->GetColorInputs()->combiner_rgbsub_b_g[0], | |
| 176 | *m_rdp->GetColorInputs()->combiner_rgbmul_g[0], | |
| 177 | *m_rdp->GetColorInputs()->combiner_rgbadd_g[0]); | |
| 178 | c1.i.b = LookUpCC(*m_rdp->GetColorInputs()->combiner_rgbsub_a_b[0], | |
| 179 | *m_rdp->GetColorInputs()->combiner_rgbsub_b_b[0], | |
| 180 | *m_rdp->GetColorInputs()->combiner_rgbmul_b[0], | |
| 181 | *m_rdp->GetColorInputs()->combiner_rgbadd_b[0]); | |
| 182 | c1.i.a = LookUpCC(*m_rdp->GetColorInputs()->combiner_alphasub_a[0], | |
| 183 | *m_rdp->GetColorInputs()->combiner_alphasub_b[0], | |
| 184 | *m_rdp->GetColorInputs()->combiner_alphamul[0], | |
| 185 | *m_rdp->GetColorInputs()->combiner_alphaadd[0]); | |
| 186 | m_rdp->GetCombinedColor()->c = c1.c; | |
| 187 | c2.c = m_rdp->GetTexel0Color()->c; | |
| 188 | m_rdp->GetTexel0Color()->c = m_rdp->GetTexel1Color()->c; | |
| 189 | m_rdp->GetTexel1Color()->c = c2.c; | |
| 190 | c2.i.r = LookUpCC(*m_rdp->GetColorInputs()->combiner_rgbsub_a_r[1], | |
| 191 | *m_rdp->GetColorInputs()->combiner_rgbsub_b_r[1], | |
| 192 | *m_rdp->GetColorInputs()->combiner_rgbmul_r[1], | |
| 193 | *m_rdp->GetColorInputs()->combiner_rgbadd_r[1]); | |
| 194 | c2.i.g = LookUpCC(*m_rdp->GetColorInputs()->combiner_rgbsub_a_g[1], | |
| 195 | *m_rdp->GetColorInputs()->combiner_rgbsub_b_g[1], | |
| 196 | *m_rdp->GetColorInputs()->combiner_rgbmul_g[1], | |
| 197 | *m_rdp->GetColorInputs()->combiner_rgbadd_g[1]); | |
| 198 | c2.i.b = LookUpCC(*m_rdp->GetColorInputs()->combiner_rgbsub_a_b[1], | |
| 199 | *m_rdp->GetColorInputs()->combiner_rgbsub_b_b[1], | |
| 200 | *m_rdp->GetColorInputs()->combiner_rgbmul_b[1], | |
| 201 | *m_rdp->GetColorInputs()->combiner_rgbadd_b[1]); | |
| 202 | c2.i.a = LookUpCC(*m_rdp->GetColorInputs()->combiner_alphasub_a[1], | |
| 203 | *m_rdp->GetColorInputs()->combiner_alphasub_b[1], | |
| 204 | *m_rdp->GetColorInputs()->combiner_alphamul[1], | |
| 205 | *m_rdp->GetColorInputs()->combiner_alphaadd[1]); | |
| 206 | m_rdp->GetAlphaCvg(&c2.i.a); | |
| 207 | } | |
| 208 | ||
| 209 | if(m_other_modes->rgb_dither_sel == 0) | |
| 210 | { | |
| 211 | dith = m_rdp->GetMagicMatrix()[mline + ((i ^ WORD_ADDR_XOR) & 3)]; | |
| 212 | } | |
| 213 | else if(m_other_modes->rgb_dither_sel == 1) | |
| 214 | { | |
| 215 | dith = m_rdp->GetBayerMatrix()[mline + ((i ^ WORD_ADDR_XOR) & 3)]; | |
| 216 | } | |
| 217 | ||
| 218 | bool z_compare_result = true; | |
| 219 | if(m_other_modes->z_compare_en) | |
| 220 | { | |
| 221 | z_compare_result = m_rdp->ZCompare(fbcur, hbcur, zbcur, zhbcur, ((UINT32)m_misc_state->m_primitive_z)<<3, m_misc_state->m_primitive_delta_z); | |
| 222 | } | |
| 223 | ||
| 224 | if(z_compare_result) | |
| 225 | { | |
| 226 | bool rendered = m_rdp->GetBlender()->Blend(fbcur, hbcur, c1, c2, dith); | |
| 227 | ||
| 228 | if(m_other_modes->z_update_en && rendered) | |
| 229 | { | |
| 230 | m_rdp->ZStore(zbcur, zhbcur, ((UINT32)m_misc_state->m_primitive_z) << 3, m_misc_state->m_primitive_delta_z); | |
| 231 | } | |
| 232 | } | |
| 233 | ||
| 234 | s += (int)(m_dsdx); | |
| 235 | } | |
| 236 | t += (int)(m_dtdy); | |
| 237 | } | |
| 238 | } | |
| 239 | else | |
| 240 | { | |
| 241 | for (int j = y1; j < y2; j++) | |
| 242 | { | |
| 243 | int fb_index = j * m_misc_state->m_fb_width; | |
| 244 | int mline = 0; | |
| 245 | if(!(m_other_modes->rgb_dither_sel & 2)) | |
| 246 | { | |
| 247 | mline = (j & 3) << 2; | |
| 248 | } | |
| 249 | ||
| 250 | int s = ((int)(m_s)); | |
| 251 | ||
| 252 | for (int i = x1; i < x2; i++) | |
| 253 | { | |
| 254 | N64::RDP::Color c1; | |
| 255 | N64::RDP::Color c2; | |
| 256 | int dith = 0; | |
| 257 | int curpixel = fb_index + i; | |
| 258 | UINT16* fbcur = &fb[curpixel ^ WORD_ADDR_XOR]; | |
| 259 | UINT8* hbcur = &hb[curpixel ^ BYTE_ADDR_XOR]; | |
| 260 | UINT16* zbcur = &zb[curpixel ^ WORD_ADDR_XOR]; | |
| 261 | UINT8* zhbcur = &zhb[curpixel ^ BYTE_ADDR_XOR]; | |
| 262 | ||
| 263 | m_misc_state->m_curpixel_cvg = 8; | |
| 264 | ||
| 265 | if(m_other_modes->cycle_type == CYCLE_TYPE_1) | |
| 266 | { | |
| 267 | m_rdp->GetTexel0Color()->c = m_rdp->GetTexPipe()->Fetch(s, t, tex_tile); | |
| 268 | ||
| 269 | c1.i.r = LookUpCC(*m_rdp->GetColorInputs()->combiner_rgbsub_a_r[1], | |
| 270 | *m_rdp->GetColorInputs()->combiner_rgbsub_b_r[1], | |
| 271 | *m_rdp->GetColorInputs()->combiner_rgbmul_r[1], | |
| 272 | *m_rdp->GetColorInputs()->combiner_rgbadd_r[1]); | |
| 273 | c1.i.g = LookUpCC(*m_rdp->GetColorInputs()->combiner_rgbsub_a_g[1], | |
| 274 | *m_rdp->GetColorInputs()->combiner_rgbsub_b_g[1], | |
| 275 | *m_rdp->GetColorInputs()->combiner_rgbmul_g[1], | |
| 276 | *m_rdp->GetColorInputs()->combiner_rgbadd_g[1]); | |
| 277 | c1.i.b = LookUpCC(*m_rdp->GetColorInputs()->combiner_rgbsub_a_b[1], | |
| 278 | *m_rdp->GetColorInputs()->combiner_rgbsub_b_b[1], | |
| 279 | *m_rdp->GetColorInputs()->combiner_rgbmul_b[1], | |
| 280 | *m_rdp->GetColorInputs()->combiner_rgbadd_b[1]); | |
| 281 | c1.i.a = LookUpCC(*m_rdp->GetColorInputs()->combiner_alphasub_a[1], | |
| 282 | *m_rdp->GetColorInputs()->combiner_alphasub_b[1], | |
| 283 | *m_rdp->GetColorInputs()->combiner_alphamul[1], | |
| 284 | *m_rdp->GetColorInputs()->combiner_alphaadd[1]); | |
| 285 | m_rdp->GetAlphaCvg(&c1.i.a); | |
| 286 | } | |
| 287 | else | |
| 288 | { | |
| 289 | m_rdp->GetTexel0Color()->c = m_rdp->GetTexPipe()->Fetch(s, t, tex_tile); | |
| 290 | m_rdp->GetTexel1Color()->c = m_rdp->GetTexPipe()->Fetch(s, t, tex_tile2); | |
| 291 | ||
| 292 | c1.i.r = LookUpCC(*m_rdp->GetColorInputs()->combiner_rgbsub_a_r[0], | |
| 293 | *m_rdp->GetColorInputs()->combiner_rgbsub_b_r[0], | |
| 294 | *m_rdp->GetColorInputs()->combiner_rgbmul_r[0], | |
| 295 | *m_rdp->GetColorInputs()->combiner_rgbadd_r[0]); | |
| 296 | c1.i.g = LookUpCC(*m_rdp->GetColorInputs()->combiner_rgbsub_a_g[0], | |
| 297 | *m_rdp->GetColorInputs()->combiner_rgbsub_b_g[0], | |
| 298 | *m_rdp->GetColorInputs()->combiner_rgbmul_g[0], | |
| 299 | *m_rdp->GetColorInputs()->combiner_rgbadd_g[0]); | |
| 300 | c1.i.b = LookUpCC(*m_rdp->GetColorInputs()->combiner_rgbsub_a_b[0], | |
| 301 | *m_rdp->GetColorInputs()->combiner_rgbsub_b_b[0], | |
| 302 | *m_rdp->GetColorInputs()->combiner_rgbmul_b[0], | |
| 303 | *m_rdp->GetColorInputs()->combiner_rgbadd_b[0]); | |
| 304 | c1.i.a = LookUpCC(*m_rdp->GetColorInputs()->combiner_alphasub_a[0], | |
| 305 | *m_rdp->GetColorInputs()->combiner_alphasub_b[0], | |
| 306 | *m_rdp->GetColorInputs()->combiner_alphamul[0], | |
| 307 | *m_rdp->GetColorInputs()->combiner_alphaadd[0]); | |
| 308 | m_rdp->GetCombinedColor()->c = c1.c; | |
| 309 | c2.c = m_rdp->GetTexel0Color()->c; | |
| 310 | m_rdp->GetTexel0Color()->c = m_rdp->GetTexel1Color()->c; | |
| 311 | m_rdp->GetTexel1Color()->c = c2.c; | |
| 312 | c2.i.r = LookUpCC(*m_rdp->GetColorInputs()->combiner_rgbsub_a_r[1], | |
| 313 | *m_rdp->GetColorInputs()->combiner_rgbsub_b_r[1], | |
| 314 | *m_rdp->GetColorInputs()->combiner_rgbmul_r[1], | |
| 315 | *m_rdp->GetColorInputs()->combiner_rgbadd_r[1]); | |
| 316 | c2.i.g = LookUpCC(*m_rdp->GetColorInputs()->combiner_rgbsub_a_g[1], | |
| 317 | *m_rdp->GetColorInputs()->combiner_rgbsub_b_g[1], | |
| 318 | *m_rdp->GetColorInputs()->combiner_rgbmul_g[1], | |
| 319 | *m_rdp->GetColorInputs()->combiner_rgbadd_g[1]); | |
| 320 | c2.i.b = LookUpCC(*m_rdp->GetColorInputs()->combiner_rgbsub_a_b[1], | |
| 321 | *m_rdp->GetColorInputs()->combiner_rgbsub_b_b[1], | |
| 322 | *m_rdp->GetColorInputs()->combiner_rgbmul_b[1], | |
| 323 | *m_rdp->GetColorInputs()->combiner_rgbadd_b[1]); | |
| 324 | c2.i.a = LookUpCC(*m_rdp->GetColorInputs()->combiner_alphasub_a[1], | |
| 325 | *m_rdp->GetColorInputs()->combiner_alphasub_b[1], | |
| 326 | *m_rdp->GetColorInputs()->combiner_alphamul[1], | |
| 327 | *m_rdp->GetColorInputs()->combiner_alphaadd[1]); | |
| 328 | m_rdp->GetAlphaCvg(&c2.i.a); | |
| 329 | } | |
| 330 | ||
| 331 | if(m_other_modes->rgb_dither_sel == 0) | |
| 332 | { | |
| 333 | dith = m_rdp->GetMagicMatrix()[mline + ((i ^ WORD_ADDR_XOR) & 3)]; | |
| 334 | } | |
| 335 | else if(m_other_modes->rgb_dither_sel == 1) | |
| 336 | { | |
| 337 | dith = m_rdp->GetBayerMatrix()[mline + ((i ^ WORD_ADDR_XOR) & 3)]; | |
| 338 | } | |
| 339 | ||
| 340 | bool z_compare_result = true; | |
| 341 | if(m_other_modes->z_compare_en) | |
| 342 | { | |
| 343 | z_compare_result = m_rdp->ZCompare(fbcur, hbcur, zbcur, zhbcur, ((UINT32)m_misc_state->m_primitive_z)<<3, m_misc_state->m_primitive_delta_z); | |
| 344 | } | |
| 345 | ||
| 346 | if(z_compare_result) | |
| 347 | { | |
| 348 | bool rendered = m_rdp->GetBlender()->Blend(fbcur, hbcur, c1, c2, dith); | |
| 349 | ||
| 350 | if(m_other_modes->z_update_en && rendered) | |
| 351 | { | |
| 352 | m_rdp->ZStore(zbcur, zhbcur, ((UINT32)m_misc_state->m_primitive_z) << 3, m_misc_state->m_primitive_delta_z); | |
| 353 | } | |
| 354 | } | |
| 355 | ||
| 356 | s += (int)(m_dsdx); | |
| 357 | } | |
| 358 | t += (int)(m_dtdy); | |
| 359 | } | |
| 360 | } | |
| 361 | } | |
| 362 | ||
| 363 | void TexRectangle::DrawCopy() | |
| 364 | { | |
| 365 | UINT16 *fb = (UINT16*)&rdram[(m_misc_state->m_fb_address / 4)]; | |
| 366 | ||
| 367 | N64::RDP::Tile *tex_tile = &m_rdp->GetTiles()[m_tilenum]; | |
| 368 | ||
| 369 | int x1 = m_xh >> 2; | |
| 370 | int x2 = m_xl >> 2; | |
| 371 | int y1 = m_yh >> 2; | |
| 372 | int y2 = m_yl >> 2; | |
| 373 | ||
| 374 | if (x2 <= x1) | |
| 375 | { | |
| 376 | x2 = x1 + 1; | |
| 377 | } | |
| 378 | if (y1 == y2) | |
| 379 | { | |
| 380 | y2 = y1 + 1; // Needed by Goldeneye | |
| 381 | } | |
| 382 | ||
| 383 | m_dsdx /= 4; | |
| 384 | x2 += 1; | |
| 385 | y2 += 1; | |
| 386 | ||
| 387 | m_rdp->GetShadeColor()->c = 0; // Needed by Pilotwings 64 | |
| 388 | ||
| 389 | if(y1 < m_rdp->GetScissor()->m_yh) | |
| 390 | { | |
| 391 | m_t += m_dtdy * (m_rdp->GetScissor()->m_yh - y1); | |
| 392 | y1 = m_rdp->GetScissor()->m_yh; | |
| 393 | } | |
| 394 | if(y2 > m_rdp->GetScissor()->m_yl) | |
| 395 | { | |
| 396 | y2 = m_rdp->GetScissor()->m_yl; | |
| 397 | } | |
| 398 | if(x1 < m_rdp->GetScissor()->m_xh) | |
| 399 | { | |
| 400 | m_s += m_dsdx * (m_rdp->GetScissor()->m_xh - x1); | |
| 401 | x1 = m_rdp->GetScissor()->m_xh; | |
| 402 | } | |
| 403 | if(x2 > m_rdp->GetScissor()->m_xl) | |
| 404 | { | |
| 405 | x2 = m_rdp->GetScissor()->m_xl; | |
| 406 | } | |
| 407 | m_dsdx >>= 5; | |
| 408 | m_dtdy >>= 5; | |
| 409 | ||
| 410 | int t = (int)m_t; | |
| 411 | ||
| 412 | if(m_flip) | |
| 413 | { | |
| 414 | for (int j = y1; j < y2; j++) | |
| 415 | { | |
| 416 | int fb_index = j * m_misc_state->m_fb_width; | |
| 417 | int s = (int)(m_s); | |
| 418 | ||
| 419 | for (int i = x1; i < x2; i++) | |
| 420 | { | |
| 421 | m_rdp->GetTexel0Color()->c = m_rdp->GetTexPipe()->Fetch(t, s, tex_tile); | |
| 422 | ||
| 423 | m_misc_state->m_curpixel_cvg = 8; | |
| 424 | ||
| 425 | if ((m_rdp->GetTexel0Color()->i.a != 0)||(!m_other_modes->alpha_compare_en)) | |
| 426 | { | |
| 427 | fb[(fb_index + i) ^ WORD_ADDR_XOR] = ((m_rdp->GetTexel0Color()->i.r >> 3) << 11) | ((m_rdp->GetTexel0Color()->i.g >> 3) << 6) | ((m_rdp->GetTexel0Color()->i.b >> 3) << 1)|1; | |
| 428 | } | |
| 429 | s += m_dsdx; | |
| 430 | } | |
| 431 | t += m_dtdy; | |
| 432 | } | |
| 433 | } | |
| 434 | else | |
| 435 | { | |
| 436 | for (int j = y1; j < y2; j++) | |
| 437 | { | |
| 438 | int fb_index = j * m_misc_state->m_fb_width; | |
| 439 | int s = (int)(m_s); | |
| 440 | ||
| 441 | for (int i = x1; i < x2; i++) | |
| 442 | { | |
| 443 | m_rdp->GetTexel0Color()->c = m_rdp->GetTexPipe()->Fetch(s, t, tex_tile); | |
| 444 | ||
| 445 | m_misc_state->m_curpixel_cvg = 8; | |
| 446 | ||
| 447 | if ((m_rdp->GetTexel0Color()->i.a != 0)||(!m_other_modes->alpha_compare_en)) | |
| 448 | { | |
| 449 | fb[(fb_index + i) ^ WORD_ADDR_XOR] = ((m_rdp->GetTexel0Color()->i.r >> 3) << 11) | ((m_rdp->GetTexel0Color()->i.g >> 3) << 6) | ((m_rdp->GetTexel0Color()->i.b >> 3) << 1)|1; | |
| 450 | } | |
| 451 | s += m_dsdx; | |
| 452 | } | |
| 453 | t += m_dtdy; | |
| 454 | } | |
| 455 | } | |
| 456 | } | |
| 457 | ||
| 458 | } // namespace RDP | |
| 459 | ||
| 460 | } // namespace N64 |
| r9854 | r9855 | |
|---|---|---|
| 1 | #ifndef _VIDEO_RDPTEXRECT_H_ | |
| 2 | #define _VIDEO_RDPTEXRECT_H_ | |
| 3 | ||
| 4 | #include "emu.h" | |
| 5 | ||
| 6 | namespace N64 | |
| 7 | { | |
| 8 | ||
| 9 | namespace RDP | |
| 10 | { | |
| 11 | ||
| 12 | class OtherModes; | |
| 13 | class MiscState; | |
| 14 | class Processor; | |
| 15 | class Color; | |
| 16 | ||
| 17 | class TexRectangle | |
| 18 | { | |
| 19 | public: | |
| 20 | TexRectangle() {} | |
| 21 | TexRectangle(running_machine *machine, UINT32 *data, int flip) | |
| 22 | { | |
| 23 | SetMachine(machine); | |
| 24 | InitFromBuffer(data); | |
| 25 | m_flip = flip; | |
| 26 | } | |
| 27 | ||
| 28 | void Draw(); | |
| 29 | void SetMachine(running_machine *machine); | |
| 30 | void InitFromBuffer(UINT32 *data); | |
| 31 | ||
| 32 | int m_tilenum; | |
| 33 | UINT16 m_xl; // 10.2 fixed-point | |
| 34 | UINT16 m_yl; // 10.2 fixed-point | |
| 35 | UINT16 m_xh; // 10.2 fixed-point | |
| 36 | UINT16 m_yh; // 10.2 fixed-point | |
| 37 | INT16 m_s; // 10.5 fixed-point | |
| 38 | INT16 m_t; // 10.5 fixed-point | |
| 39 | INT16 m_dsdx; // 5.10 fixed-point | |
| 40 | INT16 m_dtdy; // 5.10 fixed-point | |
| 41 | int m_flip; | |
| 42 | ||
| 43 | private: | |
| 44 | void DrawDefault(); | |
| 45 | void DrawCopy(); | |
| 46 | ||
| 47 | running_machine* m_machine; | |
| 48 | Processor* m_rdp; | |
| 49 | MiscState* m_misc_state; | |
| 50 | OtherModes* m_other_modes; | |
| 51 | }; | |
| 52 | ||
| 53 | } // namespace RDP | |
| 54 | ||
| 55 | } // namespace N64 | |
| 56 | ||
| 57 | #endif // _VIDEO_RDPTEXRECT_H_ |
| r9854 | r9855 | |
|---|---|---|
| 16 | 16 | { |
| 17 | 17 | public: |
| 18 | 18 | Triangle() { fatalerror("Please don't use the default constructor for N64::RDP::Triangle\n"); } |
| 19 | Triangle(running_machine | |
| 19 | Triangle(running_machine | |
| 20 | 20 | |
| 21 | void InitFromData(running_machine* machine, bool shade, bool texture, bool zbuffer); | |
| 21 | void InitFromData(running_machine* machine, bool shade, bool texture, bool zbuffer, bool rect, bool flip); | |
| 22 | 22 | void Draw(); |
| 23 | 23 | |
| 24 | 24 | private: |
| 25 | void compute_cvg_noflip(INT32* majorx, INT32* minorx, INT32* majorxint, INT32* minorxint, INT32 scanline, INT32 yh, INT32 yl); | |
| 26 | void compute_cvg_flip(INT32* majorx, INT32* minorx, INT32* majorxint, INT32* minorxint, INT32 scanline, INT32 yh, INT32 yl); | |
| 27 | ||
| 25 | 28 | running_machine* m_machine; |
| 26 | 29 | UINT32* m_cmd_data; |
| 27 | 30 | MiscState* m_misc_state; |
| r9854 | r9855 | |
| 29 | 32 | bool m_shade; |
| 30 | 33 | bool m_texture; |
| 31 | 34 | bool m_zbuffer; |
| 35 | bool m_rect; | |
| 32 | 36 | }; |
| 33 | 37 | |
| 34 | 38 | } // namespace RDP |
| r9854 | r9855 | |
|---|---|---|
| 17 | 17 | m_machine = machine; |
| 18 | 18 | m_rdp = &state->m_rdp; |
| 19 | 19 | m_other_modes = m_rdp->GetOtherModes(); |
| 20 | m_misc_state = m_rdp->GetMiscState(); | |
| 21 | } | |
| 20 | 22 | |
| 21 | m_tex_fetch.SetMachine(m_machine); | |
| 23 | void TexturePipe::Mask(INT32* S, INT32* T, INT32 num) | |
| 24 | { | |
| 25 | Tile* tile = m_rdp->GetTiles(); | |
| 26 | ||
| 27 | if (tile[num].mask_s) | |
| 28 | { | |
| 29 | INT32 wrap = *S >> (tile[num].mask_s > 10 ? 10 : tile[num].mask_s); | |
| 30 | wrap &= 1; | |
| 31 | if (tile[num].ms && wrap) | |
| 32 | { | |
| 33 | *S = (~(*S)); | |
| 34 | } | |
| 35 | *S &= m_maskbits_table[tile[num].mask_s]; | |
| 36 | } | |
| 37 | ||
| 38 | if (tile[num].mask_t) | |
| 39 | { | |
| 40 | INT32 wrap = *T >> (tile[num].mask_t > 10 ? 10 : tile[num].mask_t); | |
| 41 | wrap &= 1; | |
| 42 | if (tile[num].mt && wrap) | |
| 43 | { | |
| 44 | *T = (~(*T)); | |
| 45 | } | |
| 46 | *T &= m_maskbits_table[tile[num].mask_t]; | |
| 47 | } | |
| 22 | 48 | } |
| 23 | 49 | |
| 24 | void TexturePipe:: | |
| 50 | void TexturePipe::MaskCoupl | |
| 25 | 51 | { |
| 26 | int start; | |
| 27 | int end; | |
| 28 | if (m_other_modes->tex_lod_en || prim_tile == 7) | |
| 52 | Tile* tile = m_rdp->GetTiles(); | |
| 53 | ||
| 54 | if (tile[num].mask_s) | |
| 29 | 55 | { |
| 30 | start = 0; | |
| 31 | end = 7; | |
| 56 | INT32 maskbits_s = m_maskbits_table[tile[num].mask_s]; | |
| 57 | if (tile[num].ms) | |
| 58 | { | |
| 59 | INT32 swrapthreshold = tile[num].mask_s > 10 ? 10 : tile[num].mask_s; | |
| 60 | INT32 wrap = (*S >> swrapthreshold) & 1; | |
| 61 | INT32 wrap1 = (*S1 >> swrapthreshold) & 1; | |
| 62 | if (wrap) | |
| 63 | { | |
| 64 | *S = (~(*S)); | |
| 65 | } | |
| 66 | if (wrap1) | |
| 67 | { | |
| 68 | *S1 = (~(*S1)); | |
| 69 | } | |
| 70 | } | |
| 71 | *S &= maskbits_s; | |
| 72 | *S1 &= maskbits_s; | |
| 32 | 73 | } |
| 74 | ||
| 75 | if (tile[num].mask_t) | |
| 76 | { | |
| 77 | INT32 maskbits_t = m_maskbits_table[tile[num].mask_t]; | |
| 78 | if (tile[num].mt) | |
| 79 | { | |
| 80 | INT32 twrapthreshold = tile[num].mask_t > 10 ? 10 : tile[num].mask_t; | |
| 81 | INT32 wrap = (*T >> twrapthreshold) & 1; | |
| 82 | INT32 wrap1 = (*T1 >> twrapthreshold) & 1; | |
| 83 | if (wrap) | |
| 84 | { | |
| 85 | *T = (~(*T)); | |
| 86 | } | |
| 87 | if (wrap1) | |
| 88 | { | |
| 89 | *T1 = (~(*T1)); | |
| 90 | } | |
| 91 | } | |
| 92 | *T &= maskbits_t; | |
| 93 | *T1 &= maskbits_t; | |
| 94 | } | |
| 95 | } | |
| 96 | ||
| 97 | void TexturePipe::ShiftCycle(INT32* S, INT32* T, INT32* maxs, INT32* maxt, UINT32 num) | |
| 98 | { | |
| 99 | Tile* tile = m_rdp->GetTiles(); | |
| 100 | *S = SIGN16(*S); | |
| 101 | *T = SIGN16(*T); | |
| 102 | if (tile[num].shift_s < 11) | |
| 103 | { | |
| 104 | *S >>= tile[num].shift_s; | |
| 105 | } | |
| 33 | 106 | else |
| 34 | 107 | { |
| 35 | start = prim_tile; | |
| 36 | end = prim_tile + 1; | |
| 108 | *S <<= (16 - tile[num].shift_s); | |
| 37 | 109 | } |
| 38 | for (; start <= end; start++) | |
| 110 | *S = SIGN16(*S); | |
| 111 | if (tile[num].shift_t < 11) | |
| 39 | 112 | { |
| 40 | m_clamp_s_diff[start] = (m_rdp->GetTiles()[start].sh >> 2) - (m_rdp->GetTiles()[start].sl >> 2); | |
| 41 | m_clamp_t_diff[start] = (m_rdp->GetTiles()[start].th >> 2) - (m_rdp->GetTiles()[start].tl >> 2); | |
| 113 | *T >>= tile[num].shift_t; | |
| 42 | 114 | } |
| 115 | else | |
| 116 | { | |
| 117 | *T <<= (16 - tile[num].shift_t); | |
| 118 | } | |
| 119 | *T = SIGN16(*T); | |
| 120 | ||
| 121 | *maxs = ((*S >> 3) >= tile[num].sh); | |
| 122 | *maxt = ((*T >> 3) >= tile[num].th); | |
| 43 | 123 | } |
| 44 | 124 | |
| 45 | void TexturePipe:: | |
| 125 | void TexturePipe::ShiftCopy(INT32* S, INT32* T, UINT32 | |
| 46 | 126 | { |
| 47 | INT32 swrap, twrap; | |
| 127 | Tile* tile = m_rdp->GetTiles(); | |
| 128 | *S = SIGN16(*S); | |
| 129 | *T = SIGN16(*T); | |
| 130 | if (tile[num].shift_s < 11)//ô-ÿ tcu_tile | |
| 131 | { | |
| 132 | *S >>= tile[num].shift_s; | |
| 133 | } | |
| 134 | else | |
| 135 | { | |
| 136 | *S <<= (16 - tile[num].shift_s); | |
| 137 | } | |
| 138 | *S = SIGN16(*S); | |
| 139 | if (tile[num].shift_t < 11) | |
| 140 | { | |
| 141 | *T >>= tile[num].shift_t; | |
| 142 | } | |
| 143 | else | |
| 144 | { | |
| 145 | *T <<= (16 - tile[num].shift_t); | |
| 146 | } | |
| 147 | *T = SIGN16(*T); | |
| 148 | } | |
| 48 | 149 | |
| 49 | if (tile->mask_s) // Select clamp if mask == 0 | |
| 150 | void TexturePipe::ClampCycle(INT32* S, INT32* T, INT32* SFRAC, INT32* TFRAC, INT32 maxs, INT32 maxt, INT32 num) | |
| 151 | { | |
| 152 | Tile* tile = m_rdp->GetTiles(); | |
| 153 | int dos = tile[num].cs || !tile[num].mask_s; | |
| 154 | int dot = tile[num].ct || !tile[num].mask_t; | |
| 155 | ||
| 156 | if (dos) | |
| 50 | 157 | { |
| 51 | swrap = *S >> (tile->mask_s > 10 ? 10 : tile->mask_s); | |
| 52 | swrap &= 1; | |
| 53 | if (tile->ms && swrap) | |
| 158 | if (*S & 0x10000) | |
| 54 | 159 | { |
| 55 | *S = (~(*S)) & m_maskbits_table[tile->mask_s]; // Mirroring and masking | |
| 160 | *S = 0; | |
| 161 | *SFRAC = 0; | |
| 56 | 162 | } |
| 57 | else if ( | |
| 163 | else if ( | |
| 58 | 164 | { |
| 59 | *S &= m_maskbits_table[tile->mask_s]; // Masking | |
| 165 | *S = m_clamp_s_diff[num]; | |
| 166 | *SFRAC = 0; | |
| 60 | 167 | } |
| 168 | else | |
| 169 | { | |
| 170 | *S = (SIGN17(*S) >> 5) & 0x1fff; | |
| 171 | } | |
| 61 | 172 | } |
| 173 | else | |
| 174 | { | |
| 175 | *S = (SIGN17(*S) >> 5) & 0x1fff; | |
| 176 | } | |
| 62 | 177 | |
| 63 | if ( | |
| 178 | if (do | |
| 64 | 179 | { |
| 65 | twrap = *T >> (tile->mask_t > 10 ? 10 : tile->mask_t); | |
| 66 | twrap &= 1; | |
| 67 | if (tile->mt && twrap) | |
| 180 | if (*T & 0x10000) | |
| 68 | 181 | { |
| 69 | *T = (~(*T)) & m_maskbits_table[tile->mask_t]; // Mirroring and masking | |
| 182 | *T = 0; | |
| 183 | *TFRAC = 0; | |
| 70 | 184 | } |
| 71 | else if ( | |
| 185 | else if ( | |
| 72 | 186 | { |
| 73 | *T &= m_maskbits_table[tile->mask_t]; | |
| 187 | *T = m_clamp_t_diff[num]; | |
| 188 | *TFRAC = 0; | |
| 74 | 189 | } |
| 190 | else | |
| 191 | { | |
| 192 | *T = (SIGN17(*T) >> 5) & 0x1fff; | |
| 193 | } | |
| 75 | 194 | } |
| 195 | else | |
| 196 | { | |
| 197 | *T = (SIGN17(*T) >> 5) & 0x1fff; | |
| 198 | } | |
| 76 | 199 | } |
| 77 | 200 | |
| 78 | void TexturePipe:: | |
| 201 | void TexturePipe::ClampCycleL | |
| 79 | 202 | { |
| 80 | *S = SIGN16(*S); | |
| 81 | *T = SIGN16(*T); | |
| 203 | Tile* tile = m_rdp->GetTiles(); | |
| 204 | int dos = tile[num].cs || !tile[num].mask_s; | |
| 205 | int dot = tile[num].ct || !tile[num].mask_t; | |
| 82 | 206 | |
| 83 | if ( | |
| 207 | if (do | |
| 84 | 208 | { |
| 85 | if ( | |
| 209 | if (*S | |
| 86 | 210 | { |
| 87 | *S | |
| 211 | *S | |
| 88 | 212 | } |
| 213 | else if (maxs) | |
| 214 | { | |
| 215 | *S = m_clamp_s_diff[num]; | |
| 216 | } | |
| 89 | 217 | else |
| 90 | 218 | { |
| 91 | *S | |
| 219 | *S | |
| 92 | 220 | } |
| 93 | *S = SIGN16(*S); | |
| 94 | 221 | } |
| 222 | else | |
| 223 | { | |
| 224 | *S = (SIGN17(*S) >> 5) & 0x1fff; | |
| 225 | } | |
| 95 | 226 | |
| 96 | if (t | |
| 227 | if (dot | |
| 97 | 228 | { |
| 98 | if ( | |
| 229 | if (*T | |
| 99 | 230 | { |
| 100 | *T | |
| 231 | *T | |
| 101 | 232 | } |
| 102 | else | |
| 103 | { | |
| 104 | *T <<= (16 - tile->shift_t); | |
| 233 | else if (maxt) | |
| 234 | { | |
| 235 | *T = m_clamp_t_diff[num]; | |
| 105 | 236 | } |
| 106 | *T = SIGN16(*T); | |
| 237 | else | |
| 238 | { | |
| 239 | *T = (SIGN17(*T) >> 5) & 0x1fff; | |
| 240 | } | |
| 107 | 241 | } |
| 108 | ||
| 109 | *maxs = ((*S >> 3) >= tile->sh); | |
| 110 | *maxt = ((*T >> 3) >= tile->th); | |
| 242 | else | |
| 243 | { | |
| 244 | *T = (SIGN17(*T) >> 5) & 0x1fff; | |
| 245 | } | |
| 111 | 246 | } |
| 112 | 247 | |
| 113 | void TexturePipe::Cl | |
| 248 | void TexturePipe::Cycle | |
| 114 | 249 | { |
| 115 | bool notcopy = (m_other_modes->cycle_type != CYCLE_TYPE_COPY); | |
| 116 | bool dosfrac = (tile->cs || !tile->mask_s); | |
| 117 | bool dos = dosfrac && notcopy; | |
| 118 | bool dotfrac = (tile->ct || !tile->mask_t); | |
| 119 | bool dot = dotfrac && notcopy; | |
| 120 | bool overunders = false; | |
| 121 | bool overundert = false; | |
| 122 | if (*S & 0x10000 && dos) | |
| 250 | Tile* tile = m_rdp->GetTiles(); | |
| 251 | ||
| 252 | #define TRELATIVE(x, y) ((((x) >> 3) - (y)) << 3) | (x & 7); | |
| 253 | INT32 bilerp = cycle ? m_other_modes->bi_lerp1 : m_other_modes->bi_lerp0; | |
| 254 | int convert = m_other_modes->convert_one && cycle; | |
| 255 | Color t0; | |
| 256 | Color t1; | |
| 257 | Color t2; | |
| 258 | Color t3; | |
| 259 | if (m_other_modes->sample_type) | |
| 123 | 260 | { |
| 124 | *S = 0; | |
| 125 | overunders = true; | |
| 261 | int sss1, sst1, sss2, sst2; | |
| 262 | ||
| 263 | INT32 invsf = 0; | |
| 264 | INT32 invtf = 0; | |
| 265 | int center = 0; | |
| 266 | ||
| 267 | sss1 = SSS; | |
| 268 | sst1 = SST; | |
| 269 | ||
| 270 | INT32 maxs; | |
| 271 | INT32 maxt; | |
| 272 | ||
| 273 | ShiftCycle(&sss1, &sst1, &maxs, &maxt, tilenum); | |
| 274 | ||
| 275 | sss1 = TRELATIVE(sss1, tile[tilenum].sl); | |
| 276 | sst1 = TRELATIVE(sst1, tile[tilenum].tl); | |
| 277 | ||
| 278 | INT32 sfrac = sss1 & 0x1f; | |
| 279 | INT32 tfrac = sst1 & 0x1f; | |
| 280 | ||
| 281 | ClampCycle(&sss1, &sst1, &sfrac, &tfrac, maxs, maxt, tilenum); | |
| 282 | ||
| 283 | sss2 = sss1 + 1; | |
| 284 | sst2 = sst1 + 1; | |
| 285 | ||
| 286 | MaskCoupled(&sss1, &sss2, &sst1, &sst2, tilenum); | |
| 287 | ||
| 288 | bool upper = ((sfrac + tfrac) >= 0x20); | |
| 289 | ||
| 290 | if (upper) | |
| 291 | { | |
| 292 | invsf = 0x20 - sfrac; | |
| 293 | invtf = 0x20 - tfrac; | |
| 294 | } | |
| 295 | ||
| 296 | center = (sfrac == 0x10) && (tfrac == 0x10) && m_other_modes->mid_texel; | |
| 297 | ||
| 298 | invsf <<= 3; | |
| 299 | invtf <<= 3; | |
| 300 | sfrac <<= 3; | |
| 301 | tfrac <<= 3; | |
| 302 | ||
| 303 | t0.c = Fetch(sss1, sst1, tilenum); | |
| 304 | ||
| 305 | if (bilerp) | |
| 306 | { | |
| 307 | t1.c = Fetch(sss2, sst1, tilenum); | |
| 308 | t2.c = Fetch(sss1, sst2, tilenum); | |
| 309 | t3.c = Fetch(sss2, sst2, tilenum); | |
| 310 | if (!center) | |
| 311 | { | |
| 312 | if (upper) | |
| 313 | { | |
| 314 | TEX->i.r = t3.i.r + (((invsf * (t2.i.r - t3.i.r)) + (invtf * (t1.i.r - t3.i.r)) + 0x80) >> 8); | |
| 315 | TEX->i.g = t3.i.g + (((invsf * (t2.i.g - t3.i.g)) + (invtf * (t1.i.g - t3.i.g)) + 0x80) >> 8); | |
| 316 | TEX->i.b = t3.i.b + (((invsf * (t2.i.b - t3.i.b)) + (invtf * (t1.i.b - t3.i.b)) + 0x80) >> 8); | |
| 317 | TEX->i.a = t3.i.a + (((invsf * (t2.i.a - t3.i.a)) + (invtf * (t1.i.a - t3.i.a)) + 0x80) >> 8); | |
| 318 | } | |
| 319 | else | |
| 320 | { | |
| 321 | TEX->i.r = t0.i.r + (((sfrac * (t1.i.r - t0.i.r)) + (tfrac * (t2.i.r - t0.i.r)) + 0x80) >> 8); | |
| 322 | TEX->i.g = t0.i.g + (((sfrac * (t1.i.g - t0.i.g)) + (tfrac * (t2.i.g - t0.i.g)) + 0x80) >> 8); | |
| 323 | TEX->i.b = t0.i.b + (((sfrac * (t1.i.b - t0.i.b)) + (tfrac * (t2.i.b - t0.i.b)) + 0x80) >> 8); | |
| 324 | TEX->i.a = t0.i.a + (((sfrac * (t1.i.a - t0.i.a)) + (tfrac * (t2.i.a - t0.i.a)) + 0x80) >> 8); | |
| 325 | } | |
| 326 | TEX->i.r &= 0x1ff; | |
| 327 | TEX->i.g &= 0x1ff; | |
| 328 | TEX->i.b &= 0x1ff; | |
| 329 | TEX->i.a &= 0x1ff; | |
| 330 | } | |
| 331 | else//tf.c,24 | |
| 332 | { | |
| 333 | TEX->i.r = (t0.i.r + t1.i.r + t2.i.r + t3.i.r) >> 2; | |
| 334 | TEX->i.g = (t0.i.g + t1.i.g + t2.i.g + t3.i.g) >> 2; | |
| 335 | TEX->i.b = (t0.i.b + t1.i.b + t2.i.b + t3.i.b) >> 2; | |
| 336 | TEX->i.a = (t0.i.a + t1.i.a + t2.i.a + t3.i.a) >> 2; | |
| 337 | } | |
| 338 | } | |
| 339 | else | |
| 340 | { | |
| 341 | INT32 newk0 = SIGN9(m_rdp->GetK0()); | |
| 342 | INT32 newk1 = SIGN9(m_rdp->GetK1()); | |
| 343 | INT32 newk2 = SIGN9(m_rdp->GetK2()); | |
| 344 | INT32 newk3 = SIGN9(m_rdp->GetK3()); | |
| 345 | INT32 invk0 = ~newk0; | |
| 346 | INT32 invk1 = ~newk1; | |
| 347 | INT32 invk2 = ~newk2; | |
| 348 | INT32 invk3 = ~newk3; | |
| 349 | if (convert) | |
| 350 | { | |
| 351 | t0 = *prev; | |
| 352 | } | |
| 353 | t0.i.r = SIGN9(t0.i.r); t0.i.g = SIGN9(t0.i.g); t0.i.b = SIGN9(t0.i.b); | |
| 354 | TEX->i.r = t0.i.b + (((newk0 - invk0) * t0.i.g + 0x80) >> 8); | |
| 355 | TEX->i.g = t0.i.b + (((newk1 - invk1) * t0.i.r + (newk2 - invk2) * t0.i.g + 0x80) >> 8); | |
| 356 | TEX->i.b = t0.i.b + (((newk3 - invk3) * t0.i.r + 0x80) >> 8); | |
| 357 | TEX->i.a = t0.i.b; | |
| 358 | TEX->i.r &= 0x1ff; | |
| 359 | TEX->i.g &= 0x1ff; | |
| 360 | TEX->i.b &= 0x1ff; | |
| 361 | TEX->i.a &= 0x1ff; | |
| 362 | } | |
| 126 | 363 | } |
| 127 | else | |
| 364 | else | |
| 128 | 365 | { |
| 129 | *S = m_clamp_s_diff[tile->num]; | |
| 130 | overunders = true; | |
| 366 | INT32 sss1 = SSS; | |
| 367 | INT32 sst1 = SST; | |
| 368 | ||
| 369 | INT32 maxs; | |
| 370 | INT32 maxt; | |
| 371 | ||
| 372 | ShiftCycle(&sss1, &sst1, &maxs, &maxt, tilenum); | |
| 373 | sss1 = TRELATIVE(sss1, tile[tilenum].sl); | |
| 374 | sst1 = TRELATIVE(sst1, tile[tilenum].tl); | |
| 375 | ||
| 376 | ClampCycleLight(&sss1, &sst1, maxs, maxt, tilenum); | |
| 377 | ||
| 378 | Mask(&sss1, &sst1, tilenum); | |
| 379 | ||
| 380 | t0.c = Fetch(sss1, sst1, tilenum); | |
| 381 | if (bilerp) | |
| 382 | { | |
| 383 | *TEX = t0; | |
| 384 | } | |
| 385 | else | |
| 386 | { | |
| 387 | INT32 newk0 = SIGN9(m_rdp->GetK0()); | |
| 388 | INT32 newk1 = SIGN9(m_rdp->GetK1()); | |
| 389 | INT32 newk2 = SIGN9(m_rdp->GetK2()); | |
| 390 | INT32 newk3 = SIGN9(m_rdp->GetK3()); | |
| 391 | INT32 invk0 = ~newk0; | |
| 392 | INT32 invk1 = ~newk1; | |
| 393 | INT32 invk2 = ~newk2; | |
| 394 | INT32 invk3 = ~newk3; | |
| 395 | if (convert) | |
| 396 | { | |
| 397 | t0 = *prev; | |
| 398 | } | |
| 399 | t0.i.r = SIGN9(t0.i.r); | |
| 400 | t0.i.g = SIGN9(t0.i.g); | |
| 401 | t0.i.b = SIGN9(t0.i.b); | |
| 402 | TEX->i.r = t0.i.b + (((newk0 - invk0) * t0.i.g + 0x80) >> 8); | |
| 403 | TEX->i.g = t0.i.b + (((newk1 - invk1) * t0.i.r + (newk2 - invk2) * t0.i.g + 0x80) >> 8); | |
| 404 | TEX->i.b = t0.i.b + (((newk3 - invk3) * t0.i.r + 0x80) >> 8); | |
| 405 | TEX->i.a = t0.i.b; | |
| 406 | TEX->i.r &= 0x1ff; | |
| 407 | TEX->i.g &= 0x1ff; | |
| 408 | TEX->i.b &= 0x1ff; | |
| 409 | TEX->i.a &= 0x1ff; | |
| 410 | } | |
| 131 | 411 | } |
| 132 | else | |
| 412 | } | |
| 413 | ||
| 414 | void TexturePipe::Copy(Color* TEX, INT32 SSS, INT32 SST, UINT32 tilenum) | |
| 415 | { | |
| 416 | Tile* tile = m_rdp->GetTiles(); | |
| 417 | INT32 sss1 = SSS; | |
| 418 | INT32 sst1 = SST; | |
| 419 | ShiftCopy(&sss1, &sst1, tilenum); | |
| 420 | sss1 = TRELATIVE(sss1, tile[tilenum].sl); | |
| 421 | sst1 = TRELATIVE(sst1, tile[tilenum].tl); | |
| 422 | sss1 = (SIGN17(sss1) >> 5) & 0x1fff; | |
| 423 | sst1 = (SIGN17(sst1) >> 5) & 0x1fff; | |
| 424 | Mask(&sss1, &sst1, tilenum); | |
| 425 | TEX->c = Fetch(sss1, sst1, tilenum); | |
| 426 | } | |
| 427 | ||
| 428 | void TexturePipe::LOD1Cycle(INT32* sss, INT32* sst, INT32 s, INT32 t, INT32 w, INT32 dsinc, INT32 dtinc, INT32 dwinc) | |
| 429 | { | |
| 430 | INT32 nextsw = (w + dwinc) >> 16; | |
| 431 | INT32 nexts = (s + dsinc) >> 16; | |
| 432 | INT32 nextt = (t + dtinc) >> 16; | |
| 433 | ||
| 434 | if (m_other_modes->persp_tex_en) | |
| 133 | 435 | { |
| 134 | | |
| 436 | m_rdp->TCDiv(nexts, | |
| 135 | 437 | } |
| 136 | | |
| 438 | | |
| 137 | 439 | { |
| 138 | | |
| 440 | m_rdp->TCDivNoPersp(nexts, nextt, nextsw, &nexts, &nextt); | |
| 139 | 441 | } |
| 140 | 442 | |
| 141 | if (*T & 0x10000 && dot) | |
| 443 | m_start_span = false; | |
| 444 | m_precomp_s = nexts; | |
| 445 | m_precomp_t = nextt; | |
| 446 | ||
| 447 | int tempanded; | |
| 448 | if (*sss & 0x40000) | |
| 142 | 449 | { |
| 143 | *T = 0; | |
| 144 | overundert = true; | |
| 450 | *sss = 0x7fff; | |
| 145 | 451 | } |
| 146 | else if ( | |
| 452 | else if (*sss & | |
| 147 | 453 | { |
| 148 | *T = m_clamp_t_diff[tile->num]; | |
| 149 | overundert = true; | |
| 454 | *sss = 0x8000; | |
| 150 | 455 | } |
| 151 | 456 | else |
| 152 | 457 | { |
| 153 | *T = (SIGN17(*T) >> 5) & 0x1fff; | |
| 458 | tempanded = *sss & 0x18000; | |
| 459 | if (tempanded == 0x8000) | |
| 460 | { | |
| 461 | *sss = 0x7fff; | |
| 462 | } | |
| 463 | else if (tempanded == 0x10000) | |
| 464 | { | |
| 465 | *sss = 0x8000; | |
| 466 | } | |
| 467 | else | |
| 468 | { | |
| 469 | *sss &= 0xffff; | |
| 470 | } | |
| 154 | 471 | } |
| 155 | if (overundert && dotfrac) | |
| 472 | ||
| 473 | if (*sst & 0x40000) | |
| 156 | 474 | { |
| 157 | * | |
| 475 | *sst | |
| 158 | 476 | } |
| 477 | else if (*sst & 0x20000) | |
| 478 | { | |
| 479 | *sst = 0x8000; | |
| 480 | } | |
| 481 | else | |
| 482 | { | |
| 483 | tempanded = *sst & 0x18000; | |
| 484 | if (tempanded == 0x8000) | |
| 485 | { | |
| 486 | *sst = 0x7fff; | |
| 487 | } | |
| 488 | else if (tempanded == 0x10000) | |
| 489 | { | |
| 490 | *sst = 0x8000; | |
| 491 | } | |
| 492 | else | |
| 493 | { | |
| 494 | *sst &= 0xffff; | |
| 495 | } | |
| 496 | } | |
| 159 | 497 | } |
| 160 | 498 | |
| 161 | void TexturePipe::Cl | |
| 499 | void TexturePipe::LOD2Cycle | |
| 162 | 500 | { |
| 163 | bool notcopy = (m_other_modes->cycle_type != CYCLE_TYPE_COPY); | |
| 164 | bool dos = (tile->cs || !tile->mask_s) && notcopy; | |
| 165 | bool dot = (tile->ct || !tile->mask_t) && notcopy; | |
| 501 | INT32 nextsw = (w + dwinc) >> 16; | |
| 502 | INT32 nexts = (s + dsinc) >> 16; | |
| 503 | INT32 nextt = (t + dtinc) >> 16; | |
| 166 | 504 | |
| 167 | if ( | |
| 505 | if (m_ | |
| 168 | 506 | { |
| 169 | | |
| 507 | m_rdp->TCDiv(nexts, nextt, nextsw, &nexts, &nextt); | |
| 170 | 508 | } |
| 171 | else | |
| 509 | else | |
| 172 | 510 | { |
| 173 | | |
| 511 | | |
| 174 | 512 | } |
| 513 | ||
| 514 | m_start_span = false; | |
| 515 | m_precomp_s = nexts; | |
| 516 | m_precomp_t = nextt; | |
| 517 | ||
| 518 | INT32 lodclamp = (((*sst & 0x60000) > 0) | ((nextt & 0x60000) > 0)) || (((*sss & 0x60000) > 0) | ((nexts & 0x60000) > 0)); | |
| 519 | ||
| 520 | INT32 horstep = SIGN17(nexts & 0x1ffff) - SIGN17(*sss & 0x1ffff); | |
| 521 | INT32 vertstep = SIGN17(nextt & 0x1ffff) - SIGN17(*sst & 0x1ffff); | |
| 522 | if (horstep & 0x20000) | |
| 523 | { | |
| 524 | horstep = ~horstep & 0x1ffff; | |
| 525 | } | |
| 526 | if (vertstep & 0x20000) | |
| 527 | { | |
| 528 | vertstep = ~vertstep & 0x1ffff; | |
| 529 | } | |
| 530 | ||
| 531 | INT32 lod = (horstep >= vertstep) ? horstep : vertstep; | |
| 532 | ||
| 533 | INT32 temp_anded; | |
| 534 | if (*sss & 0x40000) | |
| 535 | { | |
| 536 | *sss = 0x7fff; | |
| 537 | } | |
| 538 | else if (*sss & 0x20000) | |
| 539 | { | |
| 540 | *sss = 0x8000; | |
| 541 | } | |
| 175 | 542 | else |
| 176 | 543 | { |
| 177 | *S = (SIGN17(*S) >> 5) & 0x1fff; | |
| 544 | temp_anded = *sss & 0x18000; | |
| 545 | if (temp_anded == 0x8000) | |
| 546 | { | |
| 547 | *sss = 0x7fff; | |
| 548 | } | |
| 549 | else if (temp_anded == 0x10000) | |
| 550 | { | |
| 551 | *sss = 0x8000; | |
| 552 | } | |
| 553 | else | |
| 554 | { | |
| 555 | *sss &= 0xffff; | |
| 556 | } | |
| 178 | 557 | } |
| 179 | 558 | |
| 180 | if (* | |
| 559 | if (*sst & 0x40000 | |
| 181 | 560 | { |
| 182 | * | |
| 561 | *sst = 0x7fff; | |
| 183 | 562 | } |
| 184 | else if ( | |
| 563 | else if (*sst & | |
| 185 | 564 | { |
| 186 | * | |
| 565 | *sst = 0x8000 | |
| 187 | 566 | } |
| 188 | 567 | else |
| 189 | 568 | { |
| 190 | *T = (SIGN17(*T) >> 5) & 0x1fff; | |
| 569 | temp_anded = *sst & 0x18000; | |
| 570 | if (temp_anded == 0x8000) | |
| 571 | { | |
| 572 | *sst = 0x7fff; | |
| 573 | } | |
| 574 | else if (temp_anded == 0x10000) | |
| 575 | { | |
| 576 | *sst = 0x8000; | |
| 577 | } | |
| 578 | else | |
| 579 | { | |
| 580 | *sst &= 0xffff; | |
| 581 | } | |
| 191 | 582 | } |
| 192 | } | |
| 193 | 583 | |
| 194 | UINT32 TexturePipe::Fetch(INT32 SSS, INT32 SST, Tile* tile) | |
| 195 | { | |
| 196 | Color TEX; | |
| 197 | if (m_other_modes->sample_type) | |
| 584 | if ((lod & 0x4000) || lodclamp) | |
| 198 | 585 | { |
| 199 | INT32 rt[4] = { 0 }; | |
| 200 | INT32 gt[4] = { 0 }; | |
| 201 | INT32 bt[4] = { 0 }; | |
| 202 | INT32 at[4] = { 0 }; | |
| 203 | Color t0; | |
| 204 | Color t1; | |
| 205 | Color t2; | |
| 206 | Color t3; | |
| 586 | lod = 0x7fff; | |
| 587 | } | |
| 588 | else if (lod < m_misc_state->m_min_level) | |
| 589 | { | |
| 590 | lod = m_misc_state->m_min_level; | |
| 591 | } | |
| 207 | 592 | |
| 208 | int sss1 = SSS; | |
| 209 | int sst1 = SST; | |
| 210 | bool maxs = false; | |
| 211 | bool maxt = false; | |
| 212 | TexShift(&sss1, &sst1, &maxs, &maxt, tile); | |
| 593 | bool magnify = (lod < 32); | |
| 594 | INT32 l_tile = m_rdp->GetLog2((lod >> 5) & 0xff); | |
| 595 | bool distant = ((lod & 0x6000) || (l_tile >= m_misc_state->m_max_level)); | |
| 213 | 596 | |
| 214 | int sss2 = sss1 + 32; | |
| 215 | int sst2 = sst1 + 32; | |
| 216 | bool maxs2 = ((sss2 >> 3) >= tile->sh); | |
| 217 | bool maxt2 = ((sst2 >> 3) >= tile->th); | |
| 597 | m_rdp->SetLODFrac(((lod << 3) >> l_tile) & 0xff); | |
| 218 | 598 | |
| 219 | sss1 = RELATIVE(sss1, tile->sl); | |
| 220 | sst1 = RELATIVE(sst1, tile->tl); | |
| 221 | sss2 = RELATIVE(sss2, tile->sl); | |
| 222 | sst2 = RELATIVE(sst2, tile->tl); | |
| 599 | if(!m_other_modes->sharpen_tex_en && !m_other_modes->detail_tex_en) | |
| 600 | { | |
| 601 | if (distant) | |
| 602 | { | |
| 603 | m_rdp->SetLODFrac(0xff); | |
| 604 | } | |
| 605 | else if (magnify) | |
| 606 | { | |
| 607 | m_rdp->SetLODFrac(0); | |
| 608 | } | |
| 609 | } | |
| 223 | 610 | |
| 224 | INT32 SFRAC = sss1 & 0x1f; | |
| 225 | INT32 TFRAC = sst1 & 0x1f; | |
| 611 | if(m_other_modes->sharpen_tex_en && magnify) | |
| 612 | { | |
| 613 | m_rdp->SetLODFrac(m_rdp->GetLODFrac() | 0x100); | |
| 614 | } | |
| 226 | 615 | |
| 227 | Clamp(&sss1, &sst1, &SFRAC, &TFRAC, maxs, maxt, tile); | |
| 228 | ClampLight(&sss2, &sst2, maxs2, maxt2, tile); | |
| 616 | if (m_other_modes->tex_lod_en) | |
| 617 | { | |
| 618 | if (distant) | |
| 619 | { | |
| 620 | l_tile = m_misc_state->m_max_level; | |
| 621 | } | |
| 622 | if (!m_other_modes->detail_tex_en) | |
| 623 | { | |
| 624 | *t1 = (prim_tile + l_tile) & 7; | |
| 625 | if (!(distant || (!m_other_modes->sharpen_tex_en && magnify))) | |
| 626 | { | |
| 627 | *t2 = (*t1 + 1) & 7; | |
| 628 | } | |
| 629 | else | |
| 630 | { | |
| 631 | *t2 = *t1; // World Driver Championship, Stunt Race 64, Beetle Adventure Racing | |
| 632 | } | |
| 633 | } | |
| 634 | else // Beetle Adventure Racing, World Driver Championship (ingame_, NFL Blitz 2001, Pilotwings | |
| 635 | { | |
| 636 | if (!magnify) | |
| 637 | { | |
| 638 | *t1 = (prim_tile + l_tile + 1); | |
| 639 | } | |
| 640 | else | |
| 641 | { | |
| 642 | *t1 = (prim_tile + l_tile); | |
| 643 | } | |
| 644 | *t1 &= 7; | |
| 645 | if (!distant && !magnify) | |
| 646 | { | |
| 647 | *t2 = (prim_tile + l_tile + 2) & 7; | |
| 648 | } | |
| 649 | else | |
| 650 | { | |
| 651 | *t2 = (prim_tile + l_tile + 1) & 7; | |
| 652 | } | |
| 653 | } | |
| 654 | } | |
| 655 | } | |
| 229 | 656 | |
| 230 | Mask(&sss1, &sst1, tile); | |
| 231 | Mask(&sss2, &sst2, tile); | |
| 657 | void TexturePipe::LOD2CycleLimited(INT32* sss, INT32* sst, INT32 s, INT32 t, INT32 w, INT32 dsinc, INT32 dtinc, INT32 dwinc, INT32 prim_tile, INT32* t1) | |
| 658 | { | |
| 659 | INT32 nextsw = (w + dwinc) >> 16; | |
| 660 | INT32 nexts = (s + dsinc) >> 16; | |
| 661 | INT32 nextt = (t + dtinc) >> 16; | |
| 232 | 662 | |
| 233 | bool upper = ((SFRAC + TFRAC) >= 0x20); | |
| 234 | INT32 INVSF = 0; | |
| 235 | INT32 INVTF = 0; | |
| 236 | if (upper) | |
| 663 | if (m_other_modes->persp_tex_en) | |
| 664 | { | |
| 665 | m_rdp->TCDiv(nexts, nextt, nextsw, &nexts, &nextt); | |
| 666 | } | |
| 667 | else | |
| 668 | { | |
| 669 | m_rdp->TCDivNoPersp(nexts, nextt, nextsw, &nexts, &nextt); | |
| 670 | } | |
| 671 | ||
| 672 | INT32 lodclamp = (((*sst & 0x60000) > 0) | ((nextt & 0x60000) > 0)) || (((*sss & 0x60000) > 0) | ((nexts & 0x60000) > 0)); | |
| 673 | ||
| 674 | INT32 horstep = SIGN17(nexts & 0x1ffff) - SIGN17(*sss & 0x1ffff); | |
| 675 | INT32 vertstep = SIGN17(nextt & 0x1ffff) - SIGN17(*sst & 0x1ffff); | |
| 676 | if (horstep & 0x20000) | |
| 677 | { | |
| 678 | horstep = ~horstep & 0x1ffff; | |
| 679 | } | |
| 680 | if (vertstep & 0x20000) | |
| 681 | { | |
| 682 | vertstep = ~vertstep & 0x1ffff; | |
| 683 | } | |
| 684 | ||
| 685 | INT32 lod = (horstep >= vertstep) ? horstep : vertstep; | |
| 686 | ||
| 687 | INT32 tempanded; | |
| 688 | if (*sss & 0x40000) | |
| 689 | { | |
| 690 | *sss = 0x7fff; | |
| 691 | } | |
| 692 | else if (*sss & 0x20000) | |
| 693 | { | |
| 694 | *sss = 0x8000; | |
| 695 | } | |
| 696 | else | |
| 697 | { | |
| 698 | tempanded = *sss & 0x18000; | |
| 699 | if (tempanded == 0x8000) | |
| 237 | 700 | { |
| 238 | INVSF = 0x20 - SFRAC; | |
| 239 | INVTF = 0x20 - TFRAC; | |
| 701 | *sss = 0x7fff; | |
| 240 | 702 | } |
| 703 | else if (tempanded == 0x10000) | |
| 704 | { | |
| 705 | *sss = 0x8000; | |
| 706 | } | |
| 707 | else | |
| 708 | { | |
| 709 | *sss &= 0xffff; | |
| 710 | } | |
| 711 | } | |
| 241 | 712 | |
| 242 | t1.c = m_tex_fetch.Fetch(sss2, sst1, tile); | |
| 243 | t2.c = m_tex_fetch.Fetch(sss1, sst2, tile); | |
| 244 | if(m_other_modes->mid_texel || !upper) | |
| 713 | if (*sst & 0x40000) | |
| 714 | { | |
| 715 | *sst = 0x7fff; | |
| 716 | } | |
| 717 | else if (*sst & 0x20000) | |
| 718 | { | |
| 719 | *sst = 0x8000; | |
| 720 | } | |
| 721 | else | |
| 722 | { | |
| 723 | tempanded = *sst & 0x18000; | |
| 724 | if (tempanded == 0x8000) | |
| 245 | 725 | { |
| 246 | t0.c = m_tex_fetch.Fetch(sss1, sst1, tile); | |
| 247 | rt[0] = t0.i.r; gt[0] = t0.i.g; bt[0] = t0.i.b; at[0] = t0.i.a; | |
| 726 | *sst = 0x7fff; | |
| 248 | 727 | } |
| 249 | rt[1] = t1.i.r; gt[1] = t1.i.g; bt[1] = t1.i.b; at[1] = t1.i.a; | |
| 250 | rt[2] = t2.i.r; gt[2] = t2.i.g; bt[2] = t2.i.b; at[2] = t2.i.a; | |
| 251 | if (m_other_modes->mid_texel || upper) | |
| 728 | else if (tempanded == 0x10000) | |
| 252 | 729 | { |
| 253 | t3.c = m_tex_fetch.Fetch(sss2, sst2, tile); | |
| 254 | rt[3] = t3.i.r; gt[3] = t3.i.g; bt[3] = t3.i.b; at[3] = t3.i.a; | |
| 730 | *sst = 0x8000; | |
| 255 | 731 | } |
| 732 | else | |
| 733 | { | |
| 734 | *sst &= 0xffff; | |
| 735 | } | |
| 736 | } | |
| 256 | 737 | |
| 257 | if (!m_other_modes->mid_texel || SFRAC!= 0x10 || TFRAC != 0x10) | |
| 738 | if ((lod & 0x4000) || lodclamp) | |
| 739 | { | |
| 740 | lod = 0x7fff; | |
| 741 | } | |
| 742 | else if (lod < m_misc_state->m_min_level) | |
| 743 | { | |
| 744 | lod = m_misc_state->m_min_level; | |
| 745 | } | |
| 746 | ||
| 747 | bool magnify = (lod < 32); | |
| 748 | INT32 l_tile = m_rdp->GetLog2((lod >> 5) & 0xff); | |
| 749 | bool distant = (lod & 0x6000) || (l_tile >= m_misc_state->m_max_level); | |
| 750 | ||
| 751 | if (m_other_modes->tex_lod_en) | |
| 752 | { | |
| 753 | if (distant) | |
| 258 | 754 | { |
| 259 | if (upper) | |
| 755 | l_tile = m_misc_state->m_max_level; | |
| 756 | } | |
| 757 | if (!m_other_modes->detail_tex_en) | |
| 758 | { | |
| 759 | *t1 = (prim_tile + l_tile) & 7; | |
| 760 | } | |
| 761 | else | |
| 762 | { | |
| 763 | if (!magnify) | |
| 260 | 764 | { |
| 261 | INT32 R32 = rt[3] + ((INVSF*(rt[2] - rt[3]))>>5) + ((INVTF*(rt[1] - rt[3]))>>5); | |
| 262 | INT32 G32 = gt[3] + ((INVSF*(gt[2] - gt[3]))>>5) + ((INVTF*(gt[1] - gt[3]))>>5); | |
| 263 | INT32 B32 = bt[3] + ((INVSF*(bt[2] - bt[3]))>>5) + ((INVTF*(bt[1] - bt[3]))>>5); | |
| 264 | INT32 A32 = at[3] + ((INVSF*(at[2] - at[3]))>>5) + ((INVTF*(at[1] - at[3]))>>5); | |
| 265 | TEX.i.r = (R32 < 0) ? 0 : R32; | |
| 266 | TEX.i.g = (G32 < 0) ? 0 : G32; | |
| 267 | TEX.i.b = (B32 < 0) ? 0 : B32; | |
| 268 | TEX.i.a = (A32 < 0) ? 0 : A32; | |
| 765 | *t1 = (prim_tile + l_tile + 1); | |
| 269 | 766 | } |
| 270 | 767 | else |
| 271 | 768 | { |
| 272 | INT32 R32 = rt[0] + ((SFRAC*(rt[1] - rt[0]))>>5) + ((TFRAC*(rt[2] - rt[0]))>>5); | |
| 273 | INT32 G32 = gt[0] + ((SFRAC*(gt[1] - gt[0]))>>5) + ((TFRAC*(gt[2] - gt[0]))>>5); | |
| 274 | INT32 B32 = bt[0] + ((SFRAC*(bt[1] - bt[0]))>>5) + ((TFRAC*(bt[2] - bt[0]))>>5); | |
| 275 | INT32 A32 = at[0] + ((SFRAC*(at[1] - at[0]))>>5) + ((TFRAC*(at[2] - at[0]))>>5); | |
| 276 | TEX.i.r = (R32 < 0) ? 0 : R32; | |
| 277 | TEX.i.g = (G32 < 0) ? 0 : G32; | |
| 278 | TEX.i.b = (B32 < 0) ? 0 : B32; | |
| 279 | TEX.i.a = (A32 < 0) ? 0 : A32; | |
| 769 | *t1 = (prim_tile + l_tile); | |
| 280 | 770 | } |
| 771 | *t1 &= 7; | |
| 281 | 772 | } |
| 282 | else // Is this accurate? | |
| 773 | } | |
| 774 | } | |
| 775 | ||
| 776 | void TexturePipe::CalculateClampDiffs(UINT32 prim_tile) | |
| 777 | { | |
| 778 | Tile* tile = m_rdp->GetTiles(); | |
| 779 | if (m_other_modes->cycle_type == CYCLE_TYPE_2) | |
| 780 | { | |
| 781 | if (m_other_modes->tex_lod_en) | |
| 283 | 782 | { |
| 284 | TEX.i.r = (rt[0] + rt[1] + rt[2] + rt[3]) >> 2; | |
| 285 | TEX.i.g = (gt[0] + gt[1] + gt[2] + gt[3]) >> 2; | |
| 286 | TEX.i.b = (bt[0] + bt[1] + bt[2] + bt[3]) >> 2; | |
| 287 | TEX.i.a = (at[0] + at[1] + at[2] + at[3]) >> 2; | |
| 783 | int start = 0; | |
| 784 | int end = 7; | |
| 785 | for (; start <= end; start++) | |
| 786 | { | |
| 787 | m_clamp_s_diff[start] = (tile[start].sh >> 2) - (tile[start].sl >> 2); | |
| 788 | m_clamp_t_diff[start] = (tile[start].th >> 2) - (tile[start].tl >> 2); | |
| 789 | } | |
| 288 | 790 | } |
| 791 | else | |
| 792 | { | |
| 793 | int start = prim_tile; | |
| 794 | int end = (prim_tile + 1) & 7; | |
| 795 | m_clamp_s_diff[start] = (tile[start].sh >> 2) - (tile[start].sl >> 2); | |
| 796 | m_clamp_t_diff[start] = (tile[start].th >> 2) - (tile[start].tl >> 2); | |
| 797 | m_clamp_s_diff[end] = (tile[end].sh >> 2) - (tile[end].sl >> 2); | |
| 798 | m_clamp_t_diff[end] = (tile[end].th >> 2) - (tile[end].tl >> 2); | |
| 799 | } | |
| 289 | 800 | } |
| 290 | else | |
| 801 | else//1-cycle or copy | |
| 291 | 802 | { |
| 292 | int sss1 = SSS; | |
| 293 | int sst1 = SST; | |
| 803 | m_clamp_s_diff[prim_tile] = (tile[prim_tile].sh >> 2) - (tile[prim_tile].sl >> 2); | |
| 804 | m_clamp_t_diff[prim_tile] = (tile[prim_tile].th >> 2) - (tile[prim_tile].tl >> 2); | |
| 805 | } | |
| 806 | } | |
| 294 | 807 | |
| 295 | bool maxs = false; | |
| 296 | bool maxt = false; | |
| 297 | TexShift(&sss1, &sst1, &maxs, &maxt, tile); | |
| 808 | UINT32 TexturePipe::Fetch(INT32 s, INT32 t, INT32 tilenum) | |
| 809 | { | |
| 810 | Tile* tile = m_rdp->GetTiles(); | |
| 811 | Color color; | |
| 812 | UINT32 tbase = (tile[tilenum].line * t) & 0x1ff; | |
| 813 | UINT32 tformat = tile[tilenum].format; | |
| 814 | UINT32 tsize = tile[tilenum].size; | |
| 815 | tbase += tile[tilenum].tmem; | |
| 816 | UINT32 tpal = tile[tilenum].palette; | |
| 298 | 817 | |
| 299 | sss1 = RELATIVE(sss1, tile->sl); | |
| 300 | sst1 = RELATIVE(sst1, tile->tl); | |
| 818 | if (tformat == FORMAT_I && tsize > PIXEL_SIZE_8BIT) | |
| 819 | { | |
| 820 | tformat = FORMAT_RGBA; // Used by Supercross 2000 (in-game) | |
| 821 | } | |
| 822 | if (tformat == FORMAT_CI && tsize > PIXEL_SIZE_8BIT) | |
| 823 | { | |
| 824 | tformat = FORMAT_RGBA; // Used by Clay Fighter - Sculptor's Cut | |
| 825 | } | |
| 301 | 826 | |
| 302 | sss1 += 0x10; | |
| 303 | sst1 += 0x10; | |
| 827 | if (tformat == FORMAT_RGBA && tsize < PIXEL_SIZE_16BIT) | |
| 828 | { | |
| 829 | tformat = FORMAT_CI; // Used by Exterem-G2, Madden Football 64, and Rat Attack | |
| 830 | } | |
| 304 | 831 | |
| 305 | INT32 SFRAC = sss1 & 0x1f; | |
| 306 | INT32 TFRAC = sst1 & 0x1f; | |
| 832 | UINT16 *tc16 = m_rdp->GetTMEM16(); | |
| 307 | 833 | |
| 308 | Clamp(&sss1, &sst1, &SFRAC, &TFRAC, maxs, maxt, tile); | |
| 834 | switch (tformat) | |
| 835 | { | |
| 836 | case FORMAT_RGBA: | |
| 837 | { | |
| 838 | switch (tsize) | |
| 839 | { | |
| 840 | case PIXEL_SIZE_4BIT: | |
| 841 | break; | |
| 842 | case PIXEL_SIZE_8BIT: | |
| 843 | break; | |
| 844 | case PIXEL_SIZE_16BIT: | |
| 845 | { | |
| 846 | int taddr = (tbase << 2) + s; | |
| 847 | taddr ^= ((t & 1) ? WORD_XOR_DWORD_SWAP : WORD_ADDR_XOR); | |
| 848 | taddr &= 0x7ff; | |
| 309 | 849 | |
| 310 | Mask(&sss1, &sst1, tile); | |
| 850 | if (!m_other_modes->en_tlut) | |
| 851 | { | |
| 852 | UINT16 c = tc16[taddr]; | |
| 853 | color.i.r = GET_HI_RGBA16_TMEM(c); | |
| 854 | color.i.g = GET_MED_RGBA16_TMEM(c); | |
| 855 | color.i.b = GET_LOW_RGBA16_TMEM(c); | |
| 856 | color.i.a = (c & 1) ? 0xff : 0; | |
| 857 | } | |
| 858 | else | |
| 859 | { | |
| 860 | UINT16 c = tc16[taddr]; | |
| 861 | c = m_rdp->GetTLUT()[(c >> 8) << 2]; | |
| 862 | if (m_other_modes->tlut_type == 0) // Used by Goldeneye 007 (ocean in Frigate) | |
| 863 | { | |
| 864 | color.i.r = GET_HI_RGBA16_TMEM(c); | |
| 865 | color.i.g = GET_MED_RGBA16_TMEM(c); | |
| 866 | color.i.b = GET_LOW_RGBA16_TMEM(c); | |
| 867 | color.i.a = (c & 1) ? 0xff : 0; | |
| 868 | } | |
| 869 | else // Used by Beetle Adventure Racing (Mount Mayhem level) | |
| 870 | { | |
| 871 | color.i.r = color.i.g = color.i.b = (c >> 8) & 0xff; | |
| 872 | color.i.a = c & 0xff; | |
| 873 | } | |
| 874 | } | |
| 875 | break; | |
| 876 | } | |
| 877 | case PIXEL_SIZE_32BIT: | |
| 878 | { | |
| 879 | UINT32 *tc = m_rdp->GetTMEM32(); | |
| 880 | int taddr = (tbase << 2) + s; | |
| 881 | taddr ^= ((t & 1) ? WORD_XOR_DWORD_SWAP : WORD_ADDR_XOR); | |
| 311 | 882 | |
| 312 | /* point sample */ | |
| 313 | TEX.c = m_tex_fetch.Fetch(sss1, sst1, tile); | |
| 883 | if (!m_other_modes->en_tlut) | |
| 884 | { | |
| 885 | taddr &= 0x3ff; | |
| 886 | UINT32 c = tc16[taddr]; | |
| 887 | color.i.r = (c >> 8) & 0xff; | |
| 888 | color.i.g = c & 0xff; | |
| 889 | c = tc16[taddr | 0x400]; | |
| 890 | color.i.b = (c >> 8) & 0xff; | |
| 891 | color.i.a = c & 0xff; | |
| 892 | } | |
| 893 | else // Used by California Speed, attract mode | |
| 894 | { | |
| 895 | taddr &= 0x3ff; | |
| 896 | UINT32 c = tc[taddr]; | |
| 897 | c = m_rdp->GetTLUT()[(c >> 24) << 2]; | |
| 898 | if (m_other_modes->tlut_type == 0) | |
| 899 | { | |
| 900 | color.i.r = GET_HI_RGBA16_TMEM(c); | |
| 901 | color.i.g = GET_MED_RGBA16_TMEM(c); | |
| 902 | color.i.b = GET_LOW_RGBA16_TMEM(c); | |
| 903 | color.i.a = (c & 1) ? 0xff : 0; | |
| 904 | } | |
| 905 | else | |
| 906 | { | |
| 907 | color.i.r = color.i.g = color.i.b = (c >> 8) & 0xff; | |
| 908 | color.i.a = c & 0xff; | |
| 909 | } | |
| 910 | } | |
| 911 | ||
| 912 | break; | |
| 913 | } | |
| 914 | default: | |
| 915 | fatalerror("FETCH_TEXEL: unknown RGBA texture size %d\n", tsize); | |
| 916 | break; | |
| 917 | } | |
| 918 | break; | |
| 919 | } | |
| 920 | case FORMAT_YUV: // Used by: Bottom of the 9th, Pokemon Stadium, Ogre Battle, Major League Baseball, Ken Griffey Jr.'s Slugfest, Vigilante 8 Second Offense | |
| 921 | { | |
| 922 | switch(tsize) | |
| 923 | { | |
| 924 | case PIXEL_SIZE_16BIT: | |
| 925 | { | |
| 926 | UINT16 *tc = m_rdp->GetTMEM16(); | |
| 927 | ||
| 928 | int taddr = (tbase << 3) + s; | |
| 929 | int taddrlow = taddr >> 1; | |
| 930 | ||
| 931 | taddr ^= ((t & 1) ? BYTE_XOR_DWORD_SWAP : BYTE_ADDR_XOR); | |
| 932 | taddrlow ^= ((t & 1) ? WORD_XOR_DWORD_SWAP : WORD_ADDR_XOR); | |
| 933 | ||
| 934 | taddr &= 0x7ff; | |
| 935 | taddrlow &= 0x3ff; | |
| 936 | ||
| 937 | UINT16 c = tc[taddrlow]; | |
| 938 | ||
| 939 | INT32 y = m_rdp->GetTMEM()[taddr | 0x800]; | |
| 940 | INT32 u = c >> 8; | |
| 941 | INT32 v = c & 0xff; | |
| 942 | ||
| 943 | v ^= 0x80; u ^= 0x80; | |
| 944 | if (v & 0x80) | |
| 945 | { | |
| 946 | v |= 0x100; | |
| 947 | } | |
| 948 | if (u & 0x80) | |
| 949 | { | |
| 950 | u |= 0x100; | |
| 951 | } | |
| 952 | ||
| 953 | color.i.r = u; | |
| 954 | color.i.g = v; | |
| 955 | color.i.b = y; | |
| 956 | color.i.a = y; | |
| 957 | break; | |
| 958 | } | |
| 959 | default: | |
| 960 | fatalerror("FETCH_TEXEL: unknown YUV texture size %d\n",tsize); | |
| 961 | break; | |
| 962 | } | |
| 963 | break; | |
| 964 | } | |
| 965 | case FORMAT_CI: | |
| 966 | { | |
| 967 | switch (tsize) | |
| 968 | { | |
| 969 | case PIXEL_SIZE_4BIT: // Madden Football 64, Bust-A-Move 2 | |
| 970 | { | |
| 971 | UINT8 *tc = m_rdp->GetTMEM(); | |
| 972 | int taddr = ((tbase << 4) + s) >> 1; | |
| 973 | taddr ^= ((t & 1) ? BYTE_XOR_DWORD_SWAP : BYTE_ADDR_XOR); | |
| 974 | taddr &= 0xfff; | |
| 975 | ||
| 976 | if (m_other_modes->en_tlut) | |
| 977 | { | |
| 978 | taddr &= 0x7ff; | |
| 979 | UINT8 p = (s & 1) ? (tc[taddr] & 0xf) : (tc[taddr] >> 4); | |
| 980 | UINT16 c = m_rdp->GetTLUT()[((tpal << 4) | p) << 2]; | |
| 981 | ||
| 982 | if (m_other_modes->tlut_type == 0) | |
| 983 | { | |
| 984 | color.i.r = GET_HI_RGBA16_TMEM(c); | |
| 985 | color.i.g = GET_MED_RGBA16_TMEM(c); | |
| 986 | color.i.b = GET_LOW_RGBA16_TMEM(c); | |
| 987 | color.i.a = (c & 1) ? 0xff : 0; | |
| 988 | } | |
| 989 | else | |
| 990 | { | |
| 991 | color.i.r = color.i.g = color.i.b = (c >> 8) & 0xff; | |
| 992 | color.i.a = c & 0xff; | |
| 993 | } | |
| 994 | } | |
| 995 | else | |
| 996 | { | |
| 997 | UINT8 p = (s & 1) ? (tc[taddr] & 0xf) : (tc[taddr] >> 4); | |
| 998 | p = (tpal << 4) | p; | |
| 999 | color.i.r = color.i.g = color.i.b = color.i.a = p; | |
| 1000 | } | |
| 1001 | ||
| 1002 | break; | |
| 1003 | } | |
| 1004 | case PIXEL_SIZE_8BIT: | |
| 1005 | { | |
| 1006 | UINT8 *tc = m_rdp->GetTMEM(); | |
| 1007 | int taddr = (tbase << 3) + s; | |
| 1008 | taddr ^= ((t & 1) ? BYTE_XOR_DWORD_SWAP : BYTE_ADDR_XOR); | |
| 1009 | taddr &= 0xfff; | |
| 1010 | ||
| 1011 | if (m_other_modes->en_tlut) | |
| 1012 | { | |
| 1013 | taddr &= 0x7ff; | |
| 1014 | UINT8 p = tc[taddr]; | |
| 1015 | UINT16 c = m_rdp->GetTLUT()[p << 2]; | |
| 1016 | ||
| 1017 | if (m_other_modes->tlut_type == 0) | |
| 1018 | { | |
| 1019 | color.i.r = GET_HI_RGBA16_TMEM(c); | |
| 1020 | color.i.g = GET_MED_RGBA16_TMEM(c); | |
| 1021 | color.i.b = GET_LOW_RGBA16_TMEM(c); | |
| 1022 | color.i.a = (c & 1) ? 0xff : 0; | |
| 1023 | } | |
| 1024 | else | |
| 1025 | { | |
| 1026 | color.i.r = color.i.g = color.i.b = (c >> 8) & 0xff; | |
| 1027 | color.i.a = c & 0xff; | |
| 1028 | } | |
| 1029 | } | |
| 1030 | else | |
| 1031 | { | |
| 1032 | UINT8 p = tc[taddr]; | |
| 1033 | color.i.r = p; | |
| 1034 | color.i.g = p; | |
| 1035 | color.i.b = p; | |
| 1036 | color.i.a = p; | |
| 1037 | } | |
| 1038 | break; | |
| 1039 | } | |
| 1040 | default: | |
| 1041 | fatalerror("FETCH_TEXEL: unknown CI texture size %d\n", tsize); | |
| 1042 | break; | |
| 1043 | } | |
| 1044 | break; | |
| 1045 | } | |
| 1046 | case FORMAT_IA: | |
| 1047 | { | |
| 1048 | switch (tsize) | |
| 1049 | { | |
| 1050 | case PIXEL_SIZE_4BIT: | |
| 1051 | { | |
| 1052 | UINT8 *tc = m_rdp->GetTMEM(); | |
| 1053 | int taddr = ((tbase << 4) + s) >> 1; | |
| 1054 | taddr ^= ((t & 1) ? BYTE_XOR_DWORD_SWAP : BYTE_ADDR_XOR); | |
| 1055 | taddr &= 0xfff; | |
| 1056 | ||
| 1057 | if (!m_other_modes->en_tlut) | |
| 1058 | { | |
| 1059 | UINT8 p = ((s) & 1) ? (tc[taddr] & 0xf) : (tc[taddr] >> 4); | |
| 1060 | UINT8 i = p & 0xe; | |
| 1061 | i = (i << 4) | (i << 1) | (i >> 2); | |
| 1062 | color.i.r = i; | |
| 1063 | color.i.g = i; | |
| 1064 | color.i.b = i; | |
| 1065 | color.i.a = (p & 0x1) ? 0xff : 0; | |
| 1066 | } | |
| 1067 | else | |
| 1068 | { | |
| 1069 | taddr &= 0x7ff; | |
| 1070 | UINT8 p = ((s) & 1) ? (tc[taddr] & 0xf) : (tc[taddr] >> 4); | |
| 1071 | UINT16 c = m_rdp->GetTLUT()[((tpal << 4) | p) << 2]; | |
| 1072 | if (!m_other_modes->tlut_type) | |
| 1073 | { | |
| 1074 | color.i.r = GET_HI_RGBA16_TMEM(c); | |
| 1075 | color.i.g = GET_MED_RGBA16_TMEM(c); | |
| 1076 | color.i.b = GET_LOW_RGBA16_TMEM(c); | |
| 1077 | color.i.a = (c & 1) ? 0xff : 0; | |
| 1078 | } | |
| 1079 | else | |
| 1080 | { | |
| 1081 | color.i.r = color.i.g = color.i.b = (c >> 8) & 0xff; | |
| 1082 | color.i.a = c & 0xff; | |
| 1083 | } | |
| 1084 | } | |
| 1085 | break; | |
| 1086 | } | |
| 1087 | case PIXEL_SIZE_8BIT: | |
| 1088 | { | |
| 1089 | UINT8 *tc = m_rdp->GetTMEM(); | |
| 1090 | int taddr = (tbase << 3) + s; | |
| 1091 | taddr ^= ((t & 1) ? BYTE_XOR_DWORD_SWAP : BYTE_ADDR_XOR); | |
| 1092 | taddr &= 0xfff; | |
| 1093 | if (!m_other_modes->en_tlut) | |
| 1094 | { | |
| 1095 | UINT8 p = tc[taddr]; | |
| 1096 | UINT8 i = p & 0xf0; | |
| 1097 | i |= (i >> 4); | |
| 1098 | color.i.r = i; | |
| 1099 | color.i.g = i; | |
| 1100 | color.i.b = i; | |
| 1101 | color.i.a = ((p & 0xf) << 4) | (p & 0xf); | |
| 1102 | } | |
| 1103 | else | |
| 1104 | { | |
| 1105 | UINT8 p = tc[taddr & 0x7ff]; | |
| 1106 | UINT16 c = m_rdp->GetTLUT()[p << 2]; | |
| 1107 | if (!m_other_modes->tlut_type) | |
| 1108 | { | |
| 1109 | color.i.r = GET_HI_RGBA16_TMEM(c); | |
| 1110 | color.i.g = GET_MED_RGBA16_TMEM(c); | |
| 1111 | color.i.b = GET_LOW_RGBA16_TMEM(c); | |
| 1112 | color.i.a = (c & 1) ? 0xff : 0; | |
| 1113 | } | |
| 1114 | else | |
| 1115 | { | |
| 1116 | color.i.r = color.i.g = color.i.b = (c >> 8) & 0xff; | |
| 1117 | color.i.a = c & 0xff; | |
| 1118 | } | |
| 1119 | } | |
| 1120 | break; | |
| 1121 | } | |
| 1122 | case PIXEL_SIZE_16BIT: | |
| 1123 | { | |
| 1124 | UINT16 *tc = m_rdp->GetTMEM16(); | |
| 1125 | int taddr = (tbase << 2) + s; | |
| 1126 | taddr ^= ((t & 1) ? WORD_XOR_DWORD_SWAP : WORD_ADDR_XOR); | |
| 1127 | taddr &= 0x7ff; | |
| 1128 | ||
| 1129 | if (!m_other_modes->en_tlut) | |
| 1130 | { | |
| 1131 | UINT16 c = tc[taddr]; | |
| 1132 | UINT8 i = (c >> 8); | |
| 1133 | color.i.r = i; | |
| 1134 | color.i.g = i; | |
| 1135 | color.i.b = i; | |
| 1136 | color.i.a = c & 0xff; | |
| 1137 | } | |
| 1138 | else | |
| 1139 | { | |
| 1140 | UINT16 c = tc[taddr & 0x3ff]; | |
| 1141 | c = m_rdp->GetTLUT()[(c >> 8) << 2]; | |
| 1142 | if (m_other_modes->tlut_type == 1) | |
| 1143 | { | |
| 1144 | color.i.r = c >> 8; | |
| 1145 | color.i.g = c >> 8; | |
| 1146 | color.i.b = c >> 8; | |
| 1147 | color.i.a = c & 0xff; | |
| 1148 | } | |
| 1149 | else | |
| 1150 | { | |
| 1151 | color.i.r = GET_HI_RGBA16_TMEM(c); | |
| 1152 | color.i.g = GET_MED_RGBA16_TMEM(c); | |
| 1153 | color.i.b = GET_LOW_RGBA16_TMEM(c); | |
| 1154 | color.i.a = (c & 1) ? 0xff : 0; | |
| 1155 | } | |
| 1156 | } | |
| 1157 | break; | |
| 1158 | } | |
| 1159 | default: | |
| 1160 | color.i.r = color.i.g = color.i.b = color.i.a = 0xff; | |
| 1161 | fatalerror("FETCH_TEXEL: unknown IA texture size %d\n", tsize); | |
| 1162 | break; | |
| 1163 | } | |
| 1164 | break; | |
| 1165 | } | |
| 1166 | case FORMAT_I: | |
| 1167 | { | |
| 1168 | switch (tsize) | |
| 1169 | { | |
| 1170 | case PIXEL_SIZE_4BIT: | |
| 1171 | { | |
| 1172 | UINT8 *tc = m_rdp->GetTMEM(); | |
| 1173 | int taddr = ((tbase << 4) + s) >> 1; | |
| 1174 | taddr ^= ((t & 1) ? BYTE_XOR_DWORD_SWAP : BYTE_ADDR_XOR); | |
| 1175 | taddr &= 0xfff; | |
| 1176 | ||
| 1177 | if (!m_other_modes->en_tlut) | |
| 1178 | { | |
| 1179 | UINT8 byteval = tc[taddr]; | |
| 1180 | UINT8 c = ((s & 1)) ? (byteval & 0xf) : ((byteval >> 4) & 0xf); | |
| 1181 | c |= (c << 4); | |
| 1182 | color.i.r = c; | |
| 1183 | color.i.g = c; | |
| 1184 | color.i.b = c; | |
| 1185 | color.i.a = c; | |
| 1186 | } | |
| 1187 | else | |
| 1188 | { | |
| 1189 | UINT8 byteval = tc[taddr & 0x7ff]; | |
| 1190 | UINT8 c = ((s & 1)) ? (byteval & 0xf) : ((byteval >> 4) & 0xf); | |
| 1191 | UINT16 k = m_rdp->GetTLUT()[((tpal << 4) | c) << 2]; | |
| 1192 | if (!m_other_modes->tlut_type) | |
| 1193 | { | |
| 1194 | color.i.r = GET_HI_RGBA16_TMEM(k); | |
| 1195 | color.i.g = GET_MED_RGBA16_TMEM(k); | |
| 1196 | color.i.b = GET_LOW_RGBA16_TMEM(k); | |
| 1197 | color.i.a = (k & 1) ? 0xff : 0; | |
| 1198 | } | |
| 1199 | else | |
| 1200 | { | |
| 1201 | color.i.r = color.i.g = color.i.b = (k >> 8) & 0xff; | |
| 1202 | color.i.a = k & 0xff; | |
| 1203 | } | |
| 1204 | } | |
| 1205 | break; | |
| 1206 | } | |
| 1207 | case PIXEL_SIZE_8BIT: | |
| 1208 | { | |
| 1209 | UINT8 *tc = m_rdp->GetTMEM(); | |
| 1210 | int taddr = (tbase << 3) + s; | |
| 1211 | taddr ^= ((t & 1) ? BYTE_XOR_DWORD_SWAP : BYTE_ADDR_XOR); | |
| 1212 | taddr &= 0xfff; | |
| 1213 | ||
| 1214 | if (!m_other_modes->en_tlut) | |
| 1215 | { | |
| 1216 | UINT8 c = tc[taddr]; | |
| 1217 | color.i.r = c; | |
| 1218 | color.i.g = c; | |
| 1219 | color.i.b = c; | |
| 1220 | color.i.a = c; | |
| 1221 | } | |
| 1222 | else | |
| 1223 | { | |
| 1224 | UINT8 c = tc[taddr & 0x7ff]; | |
| 1225 | UINT16 k = m_rdp->GetTLUT()[c << 2]; | |
| 1226 | if (!m_other_modes->tlut_type) | |
| 1227 | { | |
| 1228 | color.i.r = GET_HI_RGBA16_TMEM(k); | |
| 1229 | color.i.g = GET_MED_RGBA16_TMEM(k); | |
| 1230 | color.i.b = GET_LOW_RGBA16_TMEM(k); | |
| 1231 | color.i.a = (k & 1) ? 0xff : 0; | |
| 1232 | } | |
| 1233 | else | |
| 1234 | { | |
| 1235 | color.i.r = color.i.g = color.i.b = (k >> 8) & 0xff; | |
| 1236 | color.i.a = k & 0xff; | |
| 1237 | } | |
| 1238 | } | |
| 1239 | ||
| 1240 | break; | |
| 1241 | } | |
| 1242 | default: | |
| 1243 | fatalerror("FETCH_TEXEL: unknown I texture size %d\n", tsize); | |
| 1244 | break; | |
| 1245 | } | |
| 1246 | break; | |
| 1247 | } | |
| 1248 | default: | |
| 1249 | { | |
| 1250 | fatalerror("FETCH_TEXEL: unknown texture format %d, tilenum %d\n", tformat, tilenum); | |
| 1251 | break; | |
| 1252 | } | |
| 314 | 1253 | } |
| 315 | 1254 | |
| 316 | return | |
| 1255 | return color.c; | |
| 317 | 1256 | } |
| 318 | 1257 | |
| 319 | 1258 | } // namespace RDP |
| r9854 | r9855 | |
|---|---|---|
| 25 | 25 | { |
| 26 | 26 | m_maskbits_table[i] = ((UINT16)(0xffff) >> (16 - i)) & 0x3ff; |
| 27 | 27 | } |
| 28 | m_start_span = false; | |
| 29 | m_precomp_s = 0; | |
| 30 | m_precomp_t = 0; | |
| 28 | 31 | } |
| 29 | 32 | |
| 30 | UINT32 Fetch(INT32 SSS, INT32 SST, Tile* tile); | |
| 33 | void Cycle(Color* TEX, Color* prev, INT32 SSS, INT32 SST, UINT32 tilenum, UINT32 cycle); | |
| 34 | void Copy(Color* TEX, INT32 SSS, INT32 SST, UINT32 tilenum); | |
| 35 | UINT32 Fetch(INT32 SSS, INT32 SST, INT32 tile); | |
| 31 | 36 | void CalculateClampDiffs(UINT32 prim_tile); |
| 37 | void LOD1Cycle(INT32* sss, INT32* sst, INT32 s, INT32 t, INT32 w, INT32 dsinc, INT32 dtinc, INT32 dwinc); | |
| 38 | void LOD2Cycle(INT32* sss, INT32* sst, INT32 s, INT32 t, INT32 w, INT32 dsinc, INT32 dtinc, INT32 dwinc, INT32 prim_tile, INT32* t1, INT32* t2); | |
| 39 | void LOD2CycleLimited(INT32* sss, INT32* sst, INT32 s, INT32 t, INT32 w, INT32 dsinc, INT32 dtinc, INT32 dwinc, INT32 prim_tile, INT32* t1); | |
| 32 | 40 | |
| 33 | 41 | void SetMachine(running_machine* machine); |
| 34 | 42 | |
| 43 | bool m_start_span; | |
| 44 | INT32 m_precomp_s; | |
| 45 | INT32 m_precomp_t; | |
| 46 | ||
| 35 | 47 | private: |
| 36 | void Mask(INT32* S, INT32* T, Tile* tile); | |
| 37 | void TexShift(INT32* S, INT32* T, bool* maxs, bool* maxt, Tile *tile); | |
| 38 | void Clamp(INT32* S, INT32* T, INT32* SFRAC, INT32* TFRAC, bool maxs, bool maxt, Tile* tile); | |
| 39 | void ClampLight(INT32* S, INT32* T, bool maxs, bool maxt, Tile* tile); | |
| 48 | void Mask(INT32* S, INT32* T, INT32 num); | |
| 49 | void MaskCoupled(INT32* S, INT32* S1, INT32* T, INT32* T1, INT32 num); | |
| 40 | 50 | |
| 51 | void ShiftCycle(INT32* S, INT32* T, INT32* maxs, INT32* maxt, UINT32 num); | |
| 52 | void ShiftCopy(INT32* S, INT32* T, UINT32 num); | |
| 53 | ||
| 54 | void ClampCycle(INT32* S, INT32* T, INT32* SFRAC, INT32* TFRAC, INT32 maxs, INT32 maxt, INT32 num); | |
| 55 | void ClampCycleLight(INT32* S, INT32* T, bool maxs, bool maxt, INT32 num); | |
| 56 | ||
| 41 | 57 | running_machine* m_machine; |
| 42 | 58 | OtherModes* m_other_modes; |
| 59 | MiscState* m_misc_state; | |
| 43 | 60 | Processor* m_rdp; |
| 44 | TexFetch m_tex_fetch; | |
| 45 | 61 | |
| 46 | 62 | INT32 m_maskbits_table[16]; |
| 47 | 63 | INT32 m_clamp_t_diff[8]; |
| r9854 | r9855 | |
|---|---|---|
| 5 | 5 | namespace N64 |
| 6 | 6 | { |
| 7 | 7 | |
| 8 | ||
| 8 | ||
| 9 | 9 | { |
| 10 | switch(m_misc_state->m_fb_size) | |
| 11 | { | |
| 12 | case PIXEL_SIZE_16BIT: | |
| 13 | return Blend16Bit((UINT16*)in_fb, hb, c1, c2, dith); | |
| 14 | 10 | |
| 15 | case PIXEL_SIZE_32BIT: | |
| 16 | return Blend32Bit((UINT32*)in_fb, c1, c2); | |
| 17 | ||
| 18 | default: | |
| 19 | fatalerror("Unsupported bit depth: %d\n", m_misc_state->m_fb_size); | |
| 20 | break; | |
| 21 | } | |
| 22 | ||
| 23 | return false; | |
| 24 | } | |
| 25 | ||
| 26 | bool RDP::Blender::Blend16Bit(UINT16* fb, UINT8* hb, RDP::Color c1, RDP::Color c2, int dith) | |
| 11 | bool Blender::Blend1Cycle(UINT32* fr, UINT32* fg, UINT32* fb, int dith, int adseed, int partialreject, int special_bsel) | |
| 27 | 12 | { |
| 28 | switch(m_other_modes->cycle_type) | |
| 29 | { | |
| 30 | case CYCLE_TYPE_1: | |
| 31 | return Blend16Bit1Cycle(fb, hb, c1, dith); | |
| 13 | ColorInputs* ci = m_rdp->GetColorInputs(); | |
| 14 | INT32 r, g, b; | |
| 32 | 15 | |
| 33 | case CYCLE_TYPE_2: | |
| 34 | return Blend16Bit2Cycle(fb, hb, c1, c2, dith); | |
| 35 | ||
| 36 | default: | |
| 37 | fatalerror("Unsupported cycle type for Blend16Bit: %d\n", m_other_modes->cycle_type); | |
| 38 | break; | |
| 16 | if (!m_other_modes->alpha_cvg_select) | |
| 17 | { | |
| 18 | DitherA(&m_rdp->GetPixelColor()->i.a, adseed); | |
| 39 | 19 | } |
| 40 | 20 | |
| 41 | return false; | |
| 42 | } | |
| 21 | DitherA(&m_rdp->GetShadeColor()->i.a, adseed); | |
| 43 | 22 | |
| 44 | bool RDP::Blender::Blend16Bit1Cycle(UINT16* fb, UINT8* hb, RDP::Color c, int dith) | |
| 45 | { | |
| 46 | UINT16 mem = *fb; | |
| 47 | UINT32 memory_cvg = 7; | |
| 48 | if(m_other_modes->image_read_en) | |
| 23 | if (!AlphaCompare(m_rdp->GetPixelColor()->i.a)) | |
| 49 | 24 | { |
| 50 | | |
| 25 | //return | |
| 51 | 26 | } |
| 52 | 27 | |
| 53 | // Alpha compare | |
| 54 | if (!AlphaCompare(c.i.a)) | |
| 28 | if (m_other_modes->antialias_en ? (!m_misc_state->m_curpixel_cvg) : (!m_misc_state->m_curpixel_cvbit)) | |
| 55 | 29 | { |
| 56 | 30 | return false; |
| 57 | 31 | } |
| 58 | 32 | |
| 59 | if (!m_misc_state->m_curpixel_cvg) // New coverage is zero, so abort | |
| 33 | bool dontblend = (partialreject && m_rdp->GetPixelColor()->i.a >= 0xff); | |
| 34 | if (!m_blend_enable || dontblend) | |
| 60 | 35 | { |
| 61 | return false; | |
| 36 | r = *ci->blender1a_r[0]; | |
| 37 | g = *ci->blender1a_g[0]; | |
| 38 | b = *ci->blender1a_b[0]; | |
| 62 | 39 | } |
| 63 | ||
| 64 | int special_bsel = 0; | |
| 65 | if (m_rdp->GetColorInputs()->blender2b_a[0] == &m_rdp->GetMemoryColor()->i.a) | |
| 66 | { | |
| 67 | special_bsel = 1; | |
| 68 | } | |
| 69 | ||
| 70 | m_rdp->GetPixelColor()->c = c.c; | |
| 71 | ||
| 72 | if(!m_other_modes->z_compare_en) | |
| 73 | { | |
| 74 | m_misc_state->m_curpixel_overlap = 0; | |
| 75 | } | |
| 76 | ||
| 77 | m_rdp->GetMemoryColor()->c = m_rdp->LookUp16To32(mem); | |
| 78 | m_rdp->GetMemoryColor()->i.a = (memory_cvg << 5) & 0xe0; | |
| 79 | ||
| 80 | int r; | |
| 81 | int g; | |
| 82 | int b; | |
| 83 | ||
| 84 | if(m_other_modes->z_compare_en) | |
| 85 | { | |
| 86 | if(m_other_modes->force_blend) | |
| 87 | { | |
| 88 | m_rdp->GetInvPixelColor()->i.a = 0xff - *m_rdp->GetColorInputs()->blender1b_a[0]; | |
| 89 | BlendEquation0Force(&r, &g, &b, special_bsel); | |
| 90 | } | |
| 91 | else | |
| 92 | { | |
| 93 | if (!m_misc_state->m_curpixel_overlap) | |
| 94 | { | |
| 95 | r = *m_rdp->GetColorInputs()->blender1a_r[0]; | |
| 96 | g = *m_rdp->GetColorInputs()->blender1a_g[0]; | |
| 97 | b = *m_rdp->GetColorInputs()->blender1a_b[0]; | |
| 98 | } | |
| 99 | else | |
| 100 | { | |
| 101 | m_rdp->GetInvPixelColor()->i.a = 0xff - *m_rdp->GetColorInputs()->blender1b_a[0]; | |
| 102 | ||
| 103 | BlendEquation0NoForce(&r, &g, &b, special_bsel); | |
| 104 | } | |
| 105 | } | |
| 106 | } | |
| 107 | 40 | else |
| 108 | 41 | { |
| 109 | if(m_other_modes->force_blend) | |
| 110 | { | |
| 111 | m_rdp->GetInvPixelColor()->i.a = 0xff - *m_rdp->GetColorInputs()->blender1b_a[0]; | |
| 112 | ||
| 113 | BlendEquation0Force(&r, &g, &b, special_bsel); | |
| 114 | } | |
| 115 | else | |
| 116 | { | |
| 117 | r = *m_rdp->GetColorInputs()->blender1a_r[0]; | |
| 118 | g = *m_rdp->GetColorInputs()->blender1a_g[0]; | |
| 119 | b = *m_rdp->GetColorInputs()->blender1a_b[0]; | |
| 120 | } | |
| 42 | m_rdp->GetInvPixelColor()->i.a = 0xff - *ci->blender1b_a[0]; | |
| 43 | BlendEquationCycle0(&r, &g, &b, special_bsel); | |
| 121 | 44 | } |
| 122 | 45 | |
| 123 | if( | |
| 46 | if ( | |
| 124 | 47 | { |
| 125 | // Hack to prevent "double-dithering" artifacts | |
| 126 | if (!(((r & 0xf8)==(m_rdp->GetMemoryColor()->i.r&0xf8) && (g & 0xf8) == (m_rdp->GetMemoryColor()->i.g & 0xf8) &&(b&0xf8)==(m_rdp->GetMemoryColor()->i.b&0xf8)))) | |
| 127 | { | |
| 128 | DitherRGB(&r, &g, &b, dith); | |
| 129 | } | |
| 48 | DitherRGB(&r, &g, &b, dith); | |
| 130 | 49 | } |
| 131 | ||
| 132 | return m_rdp->GetFramebuffer()->Write(fb, hb, r, g, b); | |
| 50 | *fr = r; | |
| 51 | *fg = g; | |
| 52 | *fb = b; | |
| 53 | return true; | |
| 133 | 54 | } |
| 134 | 55 | |
| 135 | bool | |
| 56 | bool | |
| 136 | 57 | { |
| 137 | UINT16 mem = *fb; | |
| 138 | UINT32 memory_cvg = 7; | |
| 139 | if(m_other_modes->image_read_en) | |
| 58 | ColorInputs* ci = m_rdp->GetColorInputs(); | |
| 59 | if (!m_other_modes->alpha_cvg_select) | |
| 140 | 60 | { |
| 141 | | |
| 61 | Dithe | |
| 142 | 62 | } |
| 143 | 63 | |
| 144 | // Alpha compare | |
| 145 | if (!AlphaCompare(c2.i.a)) | |
| 64 | DitherA(&m_rdp->GetShadeColor()->i.a, adseed); | |
| 65 | ||
| 66 | if (!AlphaCompare(m_rdp->GetPixelColor()->i.a)) | |
| 146 | 67 | { |
| 147 | return false; | |
| 68 | //return false; | |
| 148 | 69 | } |
| 149 | 70 | |
| 150 | if (!m_misc_state->m_curpixel_cvg) | |
| 71 | if (m_other_modes->antialias_en ? (!m_misc_state->m_curpixel_cvg) : (!m_misc_state->m_curpixel_cvbit)) | |
| 151 | 72 | { |
| 152 | 73 | return false; |
| 153 | 74 | } |
| 154 | 75 | |
| 155 | int special_bsel = 0; | |
| 156 | if (m_rdp->GetColorInputs()->blender2b_a[0] == &m_rdp->GetMemoryColor()->i.a) | |
| 157 | { | |
| 158 | special_bsel = 1; | |
| 159 | } | |
| 76 | m_rdp->GetInvPixelColor()->i.a = 0xff - *ci->blender1b_a[0]; | |
| 160 | 77 | |
| 161 | m_rdp->GetPixelColor()->c = c2.c; | |
| 78 | INT32 r, g, b; | |
| 79 | BlendEquationCycle0(&r, &g, &b, special_bsel0); | |
| 162 | 80 | |
| 163 | if(m_other_modes->z_compare_en) | |
| 164 | { | |
| 165 | m_misc_state->m_curpixel_overlap = 0; | |
| 166 | } | |
| 167 | ||
| 168 | m_rdp->GetMemoryColor()->c = m_rdp->LookUp16To32(mem); | |
| 169 | m_rdp->GetMemoryColor()->i.a = (memory_cvg << 5) & 0xe0; | |
| 170 | ||
| 171 | m_rdp->GetInvPixelColor()->i.a = 0xff - *m_rdp->GetColorInputs()->blender1b_a[0]; | |
| 172 | ||
| 173 | int r, g, b; | |
| 174 | if(m_other_modes->force_blend) | |
| 175 | { | |
| 176 | BlendEquation0Force(&r, &g, &b, special_bsel); | |
| 177 | } | |
| 178 | else | |
| 179 | { | |
| 180 | BlendEquation0NoForce(&r, &g, &b, special_bsel); | |
| 181 | } | |
| 182 | ||
| 183 | 81 | m_rdp->GetBlendedColor()->i.r = r; |
| 184 | 82 | m_rdp->GetBlendedColor()->i.g = g; |
| 185 | 83 | m_rdp->GetBlendedColor()->i.b = b; |
| 186 | 84 | m_rdp->GetBlendedColor()->i.a = m_rdp->GetPixelColor()->i.a; |
| 187 | 85 | |
| 188 | m_rdp->GetPixelColor()->i.r = r; | |
| 189 | m_rdp->GetPixelColor()->i.g = g; | |
| 190 | m_rdp->GetPixelColor()->i.b = b; | |
| 191 | ||
| 192 | m_rdp->GetInvPixelColor()->i.a = 0xff - *m_rdp->GetColorInputs()->blender1b_a[1]; | |
| 193 | ||
| 194 | if(m_other_modes->force_blend) | |
| 86 | bool dontblend = (partialreject && m_rdp->GetPixelColor()->i.a >= 0xff); | |
| 87 | if (!m_blend_enable || dontblend) | |
| 195 | 88 | { |
| 196 | if (m_rdp->GetColorInputs()->blender2b_a[1] == &m_rdp->GetMemoryColor()->i.a) | |
| 197 | { | |
| 198 | special_bsel = 1; | |
| 199 | } | |
| 200 | else | |
| 201 | { | |
| 202 | special_bsel = 0; | |
| 203 | } | |
| 204 | ||
| 205 | BlendEquation1Force(&r, &g, &b, special_bsel); | |
| 89 | r = *ci->blender1a_r[1]; | |
| 90 | g = *ci->blender1a_g[1]; | |
| 91 | b = *ci->blender1a_b[1]; | |
| 206 | 92 | } |
| 207 | 93 | else |
| 208 | 94 | { |
| 209 | if (!m_misc_state->m_curpixel_overlap) | |
| 210 | { | |
| 211 | r = *m_rdp->GetColorInputs()->blender1a_r[1]; | |
| 212 | g = *m_rdp->GetColorInputs()->blender1a_g[1]; | |
| 213 | b = *m_rdp->GetColorInputs()->blender1a_b[1]; | |
| 214 | } | |
| 215 | else | |
| 216 | { | |
| 217 | if (m_rdp->GetColorInputs()->blender2b_a[1] == &m_rdp->GetMemoryColor()->i.a) | |
| 218 | { | |
| 219 | special_bsel = 1; | |
| 220 | } | |
| 221 | else | |
| 222 | { | |
| 223 | special_bsel = 0; | |
| 224 | } | |
| 225 | ||
| 226 | BlendEquation1NoForce(&r, &g, &b, special_bsel); | |
| 227 | } | |
| 95 | m_rdp->GetInvPixelColor()->i.a = 0xff - *ci->blender1b_a[1]; | |
| 96 | BlendEquationCycle1(&r, &g, &b, special_bsel1); | |
| 228 | 97 | } |
| 229 | 98 | |
| 230 | if( | |
| 99 | if ( | |
| 231 | 100 | { |
| 232 | // Hack to prevent "double-dithering" artifacts | |
| 233 | if (!(((r & 0xf8)==(m_rdp->GetMemoryColor()->i.r&0xf8) && (g & 0xf8) == (m_rdp->GetMemoryColor()->i.g & 0xf8) &&(b&0xf8)==(m_rdp->GetMemoryColor()->i.b&0xf8)))) | |
| 234 | { | |
| 235 | DitherRGB(&r, &g, &b, dith); | |
| 236 | } | |
| 101 | DitherRGB(&r, &g, &b, dith); | |
| 237 | 102 | } |
| 238 | 103 | |
| 239 | return m_rdp->GetFramebuffer()->Write(fb, hb, r, g, b); | |
| 240 | } | |
| 104 | *fr = r; | |
| 105 | *fg = g; | |
| 106 | *fb = b; | |
| 241 | 107 | |
| 242 | bool RDP::Blender::Blend32Bit(UINT32* fb, RDP::Color c1, RDP::Color c2) | |
| 243 | { | |
| 244 | switch(m_other_modes->cycle_type) | |
| 245 | { | |
| 246 | case CYCLE_TYPE_1: | |
| 247 | return Blend32Bit1Cycle(fb, c1); | |
| 248 | ||
| 249 | case CYCLE_TYPE_2: | |
| 250 | return Blend32Bit2Cycle(fb, c1, c2); | |
| 251 | ||
| 252 | default: | |
| 253 | fatalerror("Unsupported cycle type for Blend16Bit: %d\n", m_other_modes->cycle_type); | |
| 254 | break; | |
| 255 | } | |
| 256 | ||
| 257 | return false; | |
| 108 | return true; | |
| 258 | 109 | } |
| 259 | 110 | |
| 260 | ||
| 111 | void | |
| 261 | 112 | { |
| 262 | UINT32 mem = *fb; | |
| 263 | int r, g, b; | |
| 113 | ColorInputs* ci = m_rdp->GetColorInputs(); | |
| 114 | UINT8 blend1a = *ci->blender1b_a[0] >> 3; | |
| 115 | UINT8 blend2a = *ci->blender2b_a[0] >> 3; | |
| 264 | 116 | |
| 265 | // Alpha compare | |
| 266 | if (!AlphaCompare(c.i.a)) | |
| 117 | if (bsel_special) | |
| 267 | 118 | { |
| 268 | return 0; | |
| 119 | blend1a = (blend1a >> m_shift_a) & 0x1C; | |
| 120 | blend2a = (blend2a >> m_shift_b) & 0x1C; | |
| 269 | 121 | } |
| 270 | 122 | |
| 271 | if (!m_misc_state->m_curpixel_cvg) | |
| 272 | { | |
| 273 | return 0; | |
| 274 | } | |
| 123 | UINT32 sum = ((blend1a >> 2) + (blend2a >> 2) + 1) & 0xf; | |
| 275 | 124 | |
| 276 | m_rdp->GetPixelColor()->c = c.c; | |
| 277 | if (!m_other_modes->z_compare_en) | |
| 278 | { | |
| 279 | m_misc_state->m_curpixel_overlap = 0; | |
| 280 | } | |
| 125 | *r = (((int)(*ci->blender1a_r[0]) * (int)(blend1a))) + | |
| 126 | (((int)(*ci->blender2a_r[0]) * (int)(blend2a))); | |
| 281 | 127 | |
| 282 | m_rdp->GetMemoryColor()->i.r = (mem >> 24) & 0xff; | |
| 283 | m_rdp->GetMemoryColor()->i.g = (mem >> 16) & 0xff; | |
| 284 | m_rdp->GetMemoryColor()->i.b = (mem >> 8) & 0xff; | |
| 128 | *g = (((int)(*ci->blender1a_g[0]) * (int)(blend1a))) + | |
| 129 | (((int)(*ci->blender2a_g[0]) * (int)(blend2a))); | |
| 285 | 130 | |
| 286 | if (m_other_modes->image_read_en) | |
| 131 | *b = (((int)(*ci->blender1a_b[0]) * (int)(blend1a))) + | |
| 132 | (((int)(*ci->blender2a_b[0]) * (int)(blend2a))); | |
| 133 | ||
| 134 | if (bsel_special) | |
| 287 | 135 | { |
| 288 | m_rdp->GetMemoryColor()->i.a = mem & 0xe0; | |
| 136 | *r += (((int)*ci->blender2a_r[0]) << 2); | |
| 137 | *g += (((int)*ci->blender2a_g[0]) << 2); | |
| 138 | *b += (((int)*ci->blender2a_b[0]) << 2); | |
| 289 | 139 | } |
| 290 | 140 | else |
| 291 | 141 | { |
| 292 | m_rdp->GetMemoryColor()->i.a = 0xe0; | |
| 142 | *r += (int)*ci->blender2a_r[0]; | |
| 143 | *g += (int)*ci->blender2a_g[0]; | |
| 144 | *b += (int)*ci->blender2a_b[0]; | |
| 293 | 145 | } |
| 294 | 146 | |
| 295 | if (!m_misc_state->m_curpixel_overlap && !m_other_modes->force_blend) | |
| 147 | *r >>= 2; | |
| 148 | *g >>= 2; | |
| 149 | *b >>= 2; | |
| 150 | ||
| 151 | if (m_other_modes->force_blend) | |
| 296 | 152 | { |
| 297 | r = *m_rdp->GetColorInputs()->blender1a_r[0]; | |
| 298 | g = *m_rdp->GetColorInputs()->blender1a_g[0]; | |
| 299 | b = *m_rdp->GetColorInputs()->blender1a_b[0]; | |
| 153 | *r >>= 3; | |
| 154 | *g >>= 3; | |
| 155 | *b >>= 3; | |
| 300 | 156 | } |
| 301 | 157 | else |
| 302 | 158 | { |
| 303 | m_rdp->GetInvPixelColor()->i.a = 0xff - *m_rdp->GetColorInputs()->blender1b_a[0]; | |
| 304 | ||
| 305 | if(m_other_modes->force_blend) | |
| 159 | if (sum) | |
| 306 | 160 | { |
| 307 | BlendEquation0Force(&r, &g, &b, m_misc_state->m_special_bsel0); | |
| 161 | *r /= sum; | |
| 162 | *g /= sum; | |
| 163 | *b /= sum; | |
| 308 | 164 | } |
| 309 | 165 | else |
| 310 | 166 | { |
| 311 | | |
| 167 | * | |
| 312 | 168 | } |
| 313 | 169 | } |
| 314 | 170 | |
| 315 | return m_rdp->GetFramebuffer()->Write(fb, NULL, r, g, b); | |
| 171 | if (*r > 255) *r = 255; | |
| 172 | if (*g > 255) *g = 255; | |
| 173 | if (*b > 255) *b = 255; | |
| 316 | 174 | } |
| 317 | 175 | |
| 318 | ||
| 176 | void | |
| 319 | 177 | { |
| 320 | UINT32 mem = *fb; | |
| 321 | int r, g, b; | |
| 178 | ColorInputs* ci = m_rdp->GetColorInputs(); | |
| 179 | UINT8 blend1a = *ci->blender1b_a[1] >> 3; | |
| 180 | UINT8 blend2a = *ci->blender2b_a[1] >> 3; | |
| 322 | 181 | |
| 323 | // Alpha compare | |
| 324 | if (!AlphaCompare(c2.i.a)) | |
| 182 | if (bsel_special) | |
| 325 | 183 | { |
| 326 | return 0; | |
| 184 | blend1a = (blend1a >> m_shift_a) & 0x1C; | |
| 185 | blend2a = (blend2a >> m_shift_b) & 0x1C; | |
| 327 | 186 | } |
| 328 | 187 | |
| 329 | if (!m_misc_state->m_curpixel_cvg) | |
| 330 | { | |
| 331 | return 0; | |
| 332 | } | |
| 188 | UINT32 sum = ((blend1a >> 2) + (blend2a >> 2) + 1) & 0xf; | |
| 333 | 189 | |
| 334 | m_rdp->GetPixelColor()->c = c2.c; | |
| 335 | if (!m_other_modes->z_compare_en) | |
| 336 | { | |
| 337 | m_misc_state->m_curpixel_overlap = 0; | |
| 338 | } | |
| 190 | *r = (((int)(*ci->blender1a_r[1]) * (int)(blend1a))) + | |
| 191 | (((int)(*ci->blender2a_r[1]) * (int)(blend2a))); | |
| 339 | 192 | |
| 340 | m_rdp->GetMemoryColor()->i.r = (mem >>24) & 0xff; | |
| 341 | m_rdp->GetMemoryColor()->i.g = (mem >> 16) & 0xff; | |
| 342 | m_rdp->GetMemoryColor()->i.b = (mem >> 8) & 0xff; | |
| 193 | *g = (((int)(*ci->blender1a_g[1]) * (int)(blend1a))) + | |
| 194 | (((int)(*ci->blender2a_g[1]) * (int)(blend2a))); | |
| 343 | 195 | |
| 344 | if (m_other_modes->image_read_en) | |
| 345 | { | |
| 346 | m_rdp->GetMemoryColor()->i.a = (mem & 0xe0); | |
| 347 | } | |
| 348 | else | |
| 349 | { | |
| 350 | m_rdp->GetMemoryColor()->i.a = 0xe0; | |
| 351 | } | |
| 196 | *b = (((int)(*ci->blender1a_b[1]) * (int)(blend1a))) + | |
| 197 | (((int)(*ci->blender2a_b[1]) * (int)(blend2a))); | |
| 352 | 198 | |
| 353 | m_rdp->GetInvPixelColor()->i.a = 0xff - *m_rdp->GetColorInputs()->blender1b_a[0]; | |
| 354 | ||
| 355 | if(m_other_modes->force_blend) | |
| 199 | if (bsel_special) | |
| 356 | 200 | { |
| 357 | BlendEquation0Force(&r, &g, &b, m_misc_state->m_special_bsel0); | |
| 201 | *r += (((int)*ci->blender2a_r[1]) << 2); | |
| 202 | *g += (((int)*ci->blender2a_g[1]) << 2); | |
| 203 | *b += (((int)*ci->blender2a_b[1]) << 2); | |
| 358 | 204 | } |
| 359 | 205 | else |
| 360 | 206 | { |
| 361 | BlendEquation0NoForce(&r, &g, &b, m_misc_state->m_special_bsel0); | |
| 207 | *r += (int)*ci->blender2a_r[1]; | |
| 208 | *g += (int)*ci->blender2a_g[1]; | |
| 209 | *b += (int)*ci->blender2a_b[1]; | |
| 362 | 210 | } |
| 363 | 211 | |
| 364 | m_rdp->GetBlendedColor()->i.r = r; | |
| 365 | m_rdp->GetBlendedColor()->i.g = g; | |
| 366 | m_rdp->GetBlendedColor()->i.b = b; | |
| 212 | *r >>= 2; | |
| 213 | *g >>= 2; | |
| 214 | *b >>= 2; | |
| 367 | 215 | |
| 368 | m_rdp->GetPixelColor()->i.r = r; | |
| 369 | m_rdp->GetPixelColor()->i.g = g; | |
| 370 | m_rdp->GetPixelColor()->i.b = b; | |
| 371 | ||
| 372 | if (!m_misc_state->m_curpixel_overlap && !m_other_modes->force_blend) | |
| 216 | if (m_other_modes->force_blend) | |
| 373 | 217 | { |
| 374 | r = *m_rdp->GetColorInputs()->blender1a_r[1]; | |
| 375 | g = *m_rdp->GetColorInputs()->blender1a_g[1]; | |
| 376 | b = *m_rdp->GetColorInputs()->blender1a_b[1]; | |
| 218 | *r >>= 3; | |
| 219 | *g >>= 3; | |
| 220 | *b >>= 3; | |
| 377 | 221 | } |
| 378 | 222 | else |
| 379 | 223 | { |
| 380 | m_rdp->GetInvPixelColor()->i.a = 0xff - *m_rdp->GetColorInputs()->blender1b_a[1]; | |
| 381 | ||
| 382 | if(m_other_modes->force_blend) | |
| 224 | if (sum) | |
| 383 | 225 | { |
| 384 | BlendEquation1Force(&r, &g, &b, m_misc_state->m_special_bsel1); | |
| 226 | *r /= sum; | |
| 227 | *g /= sum; | |
| 228 | *b /= sum; | |
| 385 | 229 | } |
| 386 | 230 | else |
| 387 | 231 | { |
| 388 | | |
| 232 | * | |
| 389 | 233 | } |
| 390 | 234 | } |
| 391 | 235 | |
| 392 | return m_rdp->GetFramebuffer()->Write(fb, NULL, r, g, b); | |
| 236 | if (*r > 255) *r = 255; | |
| 237 | if (*g > 255) *g = 255; | |
| 238 | if (*b > 255) *b = 255; | |
| 393 | 239 | } |
| 394 | 240 | |
| 395 | ||
| 241 | bool | |
| 396 | 242 | { |
| 397 | int blend1a = *m_rdp->GetColorInputs()->blender1b_a[0]; | |
| 398 | if (bsel_special) | |
| 243 | INT32 threshold; | |
| 244 | if (m_other_modes->alpha_compare_en) | |
| 399 | 245 | { |
| 400 | blend1a &= 0xe0; | |
| 246 | threshold = (m_other_modes->dither_alpha_en) ? (mame_rand(m_machine) & 0xff) : m_rdp->GetBlendColor()->i.a; | |
| 247 | if (alpha < threshold) | |
| 248 | { | |
| 249 | return false; | |
| 250 | } | |
| 251 | return true; | |
| 401 | 252 | } |
| 402 | ||
| 403 | INT32 tr = ((int)(*m_rdp->GetColorInputs()->blender1a_r[0]) * blend1a + (int)(*m_rdp->GetColorInputs()->blender2a_r[0]) * *m_rdp->GetColorInputs()->blender2b_a[0] + ((int)(*m_rdp->GetColorInputs()->blender2a_r[0]) << (3 + bsel_special))) >> 8; | |
| 404 | INT32 tg = ((int)(*m_rdp->GetColorInputs()->blender1a_g[0]) * blend1a + (int)(*m_rdp->GetColorInputs()->blender2a_g[0]) * *m_rdp->GetColorInputs()->blender2b_a[0] + ((int)(*m_rdp->GetColorInputs()->blender2a_g[0]) << (3 + bsel_special))) >> 8; | |
| 405 | INT32 tb = ((int)(*m_rdp->GetColorInputs()->blender1a_b[0]) * blend1a + (int)(*m_rdp->GetColorInputs()->blender2a_b[0]) * *m_rdp->GetColorInputs()->blender2b_a[0] + ((int)(*m_rdp->GetColorInputs()->blender2a_b[0]) << (3 + bsel_special))) >> 8; | |
| 406 | ||
| 407 | if (tr > 255) *r = 255; else *r = tr; | |
| 408 | if (tg > 255) *g = 255; else *g = tg; | |
| 409 | if (tb > 255) *b = 255; else *b = tb; | |
| 253 | return true; | |
| 410 | 254 | } |
| 411 | 255 | |
| 412 | void | |
| 256 | void | |
| 413 | 257 | { |
| 414 | UINT8 blend1a = *m_rdp->GetColorInputs()->blender1b_a[0]; | |
| 415 | UINT8 blend2a = *m_rdp->GetColorInputs()->blender2b_a[0]; | |
| 416 | if (bsel_special) | |
| 258 | INT32 new_a = *a + dith; | |
| 259 | if(new_a & 0x100) | |
| 417 | 260 | { |
| 418 | | |
| 261 | | |
| 419 | 262 | } |
| 420 | ||
| 421 | UINT32 sum = (((blend1a >> 5) + (blend2a >> 5) + 1) & 0xf) << 5; | |
| 422 | ||
| 423 | INT32 tr = (((int)(*m_rdp->GetColorInputs()->blender1a_r[0]) * (int)(blend1a))) + | |
| 424 | (((int)(*m_rdp->GetColorInputs()->blender2a_r[0]) * (int)(blend2a))); | |
| 425 | tr += (bsel_special) ? (((int)(*m_rdp->GetColorInputs()->blender2a_r[0])) << 5) : (((int)(*m_rdp->GetColorInputs()->blender2a_r[0])) << 3); | |
| 426 | ||
| 427 | INT32 tg = (((int)(*m_rdp->GetColorInputs()->blender1a_g[0]) * (int)(blend1a))) + | |
| 428 | (((int)(*m_rdp->GetColorInputs()->blender2a_g[0]) * (int)(blend2a))); | |
| 429 | tg += (bsel_special) ? ((int)((*m_rdp->GetColorInputs()->blender2a_g[0])) << 5) : (((int)(*m_rdp->GetColorInputs()->blender2a_g[0])) << 3); | |
| 430 | ||
| 431 | INT32 tb = (((int)(*m_rdp->GetColorInputs()->blender1a_b[0]) * (int)(blend1a))) + | |
| 432 | (((int)(*m_rdp->GetColorInputs()->blender2a_b[0]) * (int)(blend2a))); | |
| 433 | tb += (bsel_special) ? (((int)(*m_rdp->GetColorInputs()->blender2a_b[0])) << 5) : (((int)(*m_rdp->GetColorInputs()->blender2a_b[0])) << 3); | |
| 434 | ||
| 435 | if (sum) | |
| 436 | { | |
| 437 | tr /= sum; | |
| 438 | tg /= sum; | |
| 439 | tb /= sum; | |
| 440 | } | |
| 441 | else | |
| 442 | { | |
| 443 | *r = *g = *b = 0xff; | |
| 444 | return; | |
| 445 | } | |
| 446 | ||
| 447 | if (tr > 255) *r = 255; else *r = tr; | |
| 448 | if (tg > 255) *g = 255; else *g = tg; | |
| 449 | if (tb > 255) *b = 255; else *b = tb; | |
| 263 | *a = (UINT8)new_a; | |
| 450 | 264 | } |
| 451 | 265 | |
| 452 | void | |
| 266 | void | |
| 453 | 267 | { |
| 454 | UINT8 blend1a = *m_rdp->GetColorInputs()->blender1b_a[1]; | |
| 455 | UINT8 blend2a = *m_rdp->GetColorInputs()->blender2b_a[1]; | |
| 456 | if (bsel_special) | |
| 457 | { | |
| 458 | blend1a &= 0xe0; | |
| 459 | } | |
| 460 | ||
| 461 | INT32 tr = (((int)(*m_rdp->GetColorInputs()->blender1a_r[1]) * (int)(blend1a))) + | |
| 462 | (((int)(*m_rdp->GetColorInputs()->blender2a_r[1]) * (int)(blend2a))); | |
| 463 | tr += (bsel_special) ? (((int)(*m_rdp->GetColorInputs()->blender2a_r[1])) << 5) : (((int)(*m_rdp->GetColorInputs()->blender2a_r[1])) << 3); | |
| 464 | ||
| 465 | INT32 tg = (((int)(*m_rdp->GetColorInputs()->blender1a_g[1]) * (int)(blend1a))) + | |
| 466 | (((int)(*m_rdp->GetColorInputs()->blender2a_g[1]) * (int)(blend2a))); | |
| 467 | tg += (bsel_special) ? ((int)((*m_rdp->GetColorInputs()->blender2a_g[1])) << 5) : (((int)(*m_rdp->GetColorInputs()->blender2a_g[1])) << 3); | |
| 468 | ||
| 469 | INT32 tb = (((int)(*m_rdp->GetColorInputs()->blender1a_b[1]) * (int)(blend1a))) + | |
| 470 | (((int)(*m_rdp->GetColorInputs()->blender2a_b[1]) * (int)(blend2a))); | |
| 471 | tb += (bsel_special) ? (((int)(*m_rdp->GetColorInputs()->blender2a_b[1])) << 5) : (((int)(*m_rdp->GetColorInputs()->blender2a_b[1])) << 3); | |
| 472 | ||
| 473 | tr >>= 8; | |
| 474 | tg >>= 8; | |
| 475 | tb >>= 8; | |
| 476 | ||
| 477 | if (tr > 255) *r = 255; else *r = tr; | |
| 478 | if (tg > 255) *g = 255; else *g = tg; | |
| 479 | if (tb > 255) *b = 255; else *b = tb; | |
| 480 | } | |
| 481 | ||
| 482 | void RDP::Blender::BlendEquation1NoForce(INT32* r, INT32* g, INT32* b, int bsel_special) | |
| 483 | { | |
| 484 | UINT8 blend1a = *m_rdp->GetColorInputs()->blender1b_a[1]; | |
| 485 | UINT8 blend2a = *m_rdp->GetColorInputs()->blender2b_a[1]; | |
| 486 | if (bsel_special) | |
| 487 | { | |
| 488 | blend1a &= 0xe0; | |
| 489 | } | |
| 490 | ||
| 491 | UINT32 sum = (((blend1a >> 5) + (blend2a >> 5) + 1) & 0xf) << 5; | |
| 492 | ||
| 493 | INT32 tr = (((int)(*m_rdp->GetColorInputs()->blender1a_r[1]) * (int)(blend1a))) + | |
| 494 | (((int)(*m_rdp->GetColorInputs()->blender2a_r[1]) * (int)(blend2a))); | |
| 495 | tr += (bsel_special) ? (((int)(*m_rdp->GetColorInputs()->blender2a_r[1])) << 5) : (((int)(*m_rdp->GetColorInputs()->blender2a_r[1])) << 3); | |
| 496 | ||
| 497 | INT32 tg = (((int)(*m_rdp->GetColorInputs()->blender1a_g[1]) * (int)(blend1a))) + | |
| 498 | (((int)(*m_rdp->GetColorInputs()->blender2a_g[1]) * (int)(blend2a))); | |
| 499 | tg += (bsel_special) ? ((int)((*m_rdp->GetColorInputs()->blender2a_g[1])) << 5) : (((int)(*m_rdp->GetColorInputs()->blender2a_g[1])) << 3); | |
| 500 | ||
| 501 | INT32 tb = (((int)(*m_rdp->GetColorInputs()->blender1a_b[1]) * (int)(blend1a))) + | |
| 502 | (((int)(*m_rdp->GetColorInputs()->blender2a_b[1]) * (int)(blend2a))); | |
| 503 | tb += (bsel_special) ? (((int)(*m_rdp->GetColorInputs()->blender2a_b[1])) << 5) : (((int)(*m_rdp->GetColorInputs()->blender2a_b[1])) << 3); | |
| 504 | ||
| 505 | if (sum) | |
| 506 | { | |
| 507 | tr /= sum; | |
| 508 | tg /= sum; | |
| 509 | tb /= sum; | |
| 510 | } | |
| 511 | else | |
| 512 | { | |
| 513 | *r = *g = *b = 0xff; | |
| 514 | return; | |
| 515 | } | |
| 516 | ||
| 517 | if (tr > 255) *r = 255; else *r = tr; | |
| 518 | if (tg > 255) *g = 255; else *g = tg; | |
| 519 | if (tb > 255) *b = 255; else *b = tb; | |
| 520 | } | |
| 521 | ||
| 522 | bool RDP::Blender::AlphaCompare(UINT8 alpha) | |
| 523 | { | |
| 524 | if(m_other_modes->alpha_compare_en) | |
| 525 | { | |
| 526 | if(m_other_modes->dither_alpha_en) | |
| 527 | { | |
| 528 | return (alpha > m_rdp->GetRandom()); | |
| 529 | } | |
| 530 | else | |
| 531 | { | |
| 532 | return (alpha > m_rdp->GetBlendColor()->i.a); | |
| 533 | } | |
| 534 | } | |
| 535 | return true; | |
| 536 | } | |
| 537 | ||
| 538 | void RDP::Blender::DitherRGB(INT32 *r, INT32 *g, INT32 *b, int dith) | |
| 539 | { | |
| 540 | 268 | if ((*r & 7) > dith) |
| 541 | 269 | { |
| 542 | 270 | *r = (*r & 0xf8) + 8; |
| r9854 | r9855 | |
| 563 | 291 | } |
| 564 | 292 | } |
| 565 | 293 | |
| 294 | } // namespace RDP | |
| 295 | ||
| 566 | 296 | } // namespace N64 |
| r9854 | r9855 | |
|---|---|---|
| 17 | 17 | class Blender |
| 18 | 18 | { |
| 19 | 19 | public: |
| 20 | Blender() { } | |
| 20 | Blender() | |
| 21 | { | |
| 22 | m_blend_enable = false; | |
| 23 | } | |
| 21 | 24 | |
| 22 | bool Blend(void* in_fb, UINT8* hb, Color c1, Color c2, int dith); | |
| 25 | bool Blend2Cycle(UINT32* fr, UINT32* fg, UINT32* fb, int dith, int adseed, int partialreject, int bsel0, int bsel1); | |
| 26 | bool Blend1Cycle(UINT32* fr, UINT32* fg, UINT32* fb, int dith, int adseed, int partialreject, int special_bsel); | |
| 23 | 27 | |
| 24 | 28 | void SetOtherModes(OtherModes* other_modes) { m_other_modes = other_modes; } |
| 25 | 29 | void SetMiscState(MiscState* misc_state) { m_misc_state = misc_state; } |
| 26 | 30 | void SetMachine(running_machine* machine) { m_machine = machine; } |
| 27 | 31 | void SetProcessor(Processor* rdp) { m_rdp = rdp; } |
| 28 | 32 | |
| 33 | void SetBlendEnable(bool enable) { m_blend_enable = enable; } | |
| 34 | bool GetBlendEnable() { return m_blend_enable; } | |
| 35 | ||
| 36 | void SetShiftA(INT32 shift) { m_shift_a = shift; } | |
| 37 | void SetShiftB(INT32 shift) { m_shift_b = shift; } | |
| 38 | ||
| 29 | 39 | private: |
| 30 | 40 | running_machine* m_machine; |
| 31 | 41 | OtherModes* m_other_modes; |
| 32 | 42 | MiscState* m_misc_state; |
| 33 | 43 | Processor* m_rdp; |
| 34 | 44 | |
| 35 | bool Blend16Bit(UINT16* fb, UINT8* hb, RDP::Color c1, RDP::Color c2, int dith); | |
| 36 | bool Blend16Bit1Cycle(UINT16* fb, UINT8* hb, RDP::Color c, int dith); | |
| 37 | bool Blend16Bit2Cycle(UINT16* fb, UINT8* hb, RDP::Color c1, RDP::Color c2, int dith); | |
| 38 | bool Blend32Bit(UINT32* fb, RDP::Color c1, RDP::Color c2); | |
| 39 | bool Blend32Bit1Cycle(UINT32* fb, RDP::Color c); | |
| 40 | bool Blend32Bit2Cycle(UINT32* fb, RDP::Color c1, RDP::Color c2); | |
| 45 | bool m_blend_enable; | |
| 46 | INT32 m_shift_a; | |
| 47 | INT32 m_shift_b; | |
| 48 | ||
| 49 | void BlendEquationCycle0(INT32* r, INT32* g, INT32* b, int bsel_special); | |
| 50 | void BlendEquationCycle1(INT32* r, INT32* g, INT32* b, int bsel_special); | |
| 51 | ||
| 41 | 52 | bool AlphaCompare(UINT8 alpha); |
| 42 | 53 | |
| 43 | void BlendEquation0Force(INT32* r, INT32* g, INT32* b, int bsel_special); | |
| 44 | void BlendEquation0NoForce(INT32* r, INT32* g, INT32* b, int bsel_special); | |
| 45 | void BlendEquation1Force(INT32* r, INT32* g, INT32* b, int bsel_special); | |
| 46 | void BlendEquation1NoForce(INT32* r, INT32* g, INT32* b, int bsel_special); | |
| 47 | ||
| 48 | 54 | void DitherRGB(INT32* r, INT32* g, INT32* b, int dith); |
| 55 | void DitherA(UINT8* a, int dith); | |
| 49 | 56 | }; |
| 50 | 57 | |
| 51 | 58 | } // namespace RDP |
| r9854 | r9855 | |
|---|---|---|
| 10 | 10 | |
| 11 | 11 | #define LookUpCC(A, B, C, D) m_rdp->GetCCLUT2()[(m_rdp->GetCCLUT1()[(A << 16) | (B << 8) | C] << 8) | D] |
| 12 | 12 | |
| 13 | void Processor::RenderSpans(int start, int end, int tilenum, bool | |
| 13 | void Processor::RenderSpans(int start, int end, int tilenum, bool | |
| 14 | 14 | { |
| 15 | m_tex_pipe.CalculateClampDiffs(tilenum); | |
| 16 | ||
| 17 | 15 | int clipy1 = GetScissor()->m_yh; |
| 18 | 16 | int clipy2 = GetScissor()->m_yl; |
| 19 | 17 | |
| r9854 | r9855 | |
| 37 | 35 | for(int i = start; i <= end; i++) |
| 38 | 36 | { |
| 39 | 37 | m_span[i].SetMachine(m_machine); |
| 40 | m_span[i].Draw(i, tilenum, shade, texture, zbuffer, flip); | |
| 38 | switch(m_other_modes.cycle_type) | |
| 39 | { | |
| 40 | case CYCLE_TYPE_1: m_span[i].Draw1Cycle(i, tilenum, flip); break; | |
| 41 | case CYCLE_TYPE_2: m_span[i].Draw2Cycle(i, tilenum, flip); break; | |
| 42 | case CYCLE_TYPE_COPY: m_span[i].DrawCopy(i, tilenum, flip); break; | |
| 43 | case CYCLE_TYPE_FILL: m_span[i].DrawFill(i, tilenum, flip); break; | |
| 44 | } | |
| 45 | ||
| 41 | 46 | } |
| 42 | 47 | } |
| 43 | 48 | |
| r9854 | r9855 | |
| 60 | 65 | printf("%d", m_cvg[index]); |
| 61 | 66 | } |
| 62 | 67 | printf("\n"); |
| 63 | ||
| 64 | printf(" m_dymax = %08x\n", m_dymax); | |
| 65 | printf(" m_ds.w = %08x\n", m_ds.w); | |
| 66 | printf(" m_dt.w = %08x\n", m_dt.w); | |
| 67 | printf(" m_dw.w = %08x\n", m_dw.w); | |
| 68 | printf(" m_dr.w = %08x\n", m_dr.w); | |
| 69 | printf(" m_dg.w = %08x\n", m_dg.w); | |
| 70 | printf(" m_db.w = %08x\n", m_db.w); | |
| 71 | printf(" m_da.w = %08x\n", m_da.w); | |
| 72 | printf(" m_dz.w = %08x\n", m_dz.w); | |
| 73 | printf(" m_dzpix = %08x\n", m_dzpix); | |
| 74 | 68 | } |
| 75 | 69 | |
| 76 | 70 | void Span::SetMachine(running_machine *machine) |
| r9854 | r9855 | |
| 83 | 77 | m_misc_state = m_rdp->GetMiscState(); |
| 84 | 78 | } |
| 85 | 79 | |
| 86 | void Span:: | |
| 80 | void Span::RGBAZClip(int sr | |
| 87 | 81 | { |
| 82 | m_rdp->GetShadeColor()->i.r = m_rdp->GetSpecial9BitClampTable()[sr & 0x1ff]; | |
| 83 | m_rdp->GetShadeColor()->i.g = m_rdp->GetSpecial9BitClampTable()[sg & 0x1ff]; | |
| 84 | m_rdp->GetShadeColor()->i.b = m_rdp->GetSpecial9BitClampTable()[sb & 0x1ff]; | |
| 85 | m_rdp->GetShadeColor()->i.a = m_rdp->GetSpecial9BitClampTable()[sa & 0x1ff]; | |
| 86 | ||
| 87 | INT32 zanded = (*sz) & 0x60000; | |
| 88 | ||
| 89 | zanded >>= 17; | |
| 90 | switch(zanded) | |
| 91 | { | |
| 92 | case 0: *sz &= 0x3ffff; break; | |
| 93 | case 1: *sz &= 0x3ffff; break; | |
| 94 | case 2: *sz = 0x3ffff; break; | |
| 95 | case 3: *sz = 0x3ffff; break; | |
| 96 | } | |
| 97 | } | |
| 98 | ||
| 99 | void Span::RGBAZCorrectTriangle(INT32 offx, INT32 offy, INT32* r, INT32* g, INT32* b, INT32* a, INT32* z) | |
| 100 | { | |
| 101 | if (m_rdp->GetMiscState()->m_curpixel_cvg == 8) | |
| 102 | { | |
| 103 | *r >>= 2; | |
| 104 | *g >>= 2; | |
| 105 | *b >>= 2; | |
| 106 | *a >>= 2; | |
| 107 | *z = (*z >> 3) & 0x7ffff; | |
| 108 | } | |
| 109 | else | |
| 110 | { | |
| 111 | INT32 summand_xr = offx * SIGN13(m_rdp->m_span_dr >> 14); | |
| 112 | INT32 summand_yr = offy * SIGN13(m_rdp->m_span_drdy >> 14); | |
| 113 | INT32 summand_xb = offx * SIGN13(m_rdp->m_span_db >> 14); | |
| 114 | INT32 summand_yb = offy * SIGN13(m_rdp->m_span_dbdy >> 14); | |
| 115 | INT32 summand_xg = offx * SIGN13(m_rdp->m_span_dg >> 14); | |
| 116 | INT32 summand_yg = offy * SIGN13(m_rdp->m_span_dgdy >> 14); | |
| 117 | INT32 summand_xa = offx * SIGN13(m_rdp->m_span_da >> 14); | |
| 118 | INT32 summand_ya = offy * SIGN13(m_rdp->m_span_dady >> 14); | |
| 119 | ||
| 120 | INT32 summand_xz = offx * SIGN22(m_rdp->m_span_dz >> 10); | |
| 121 | INT32 summand_yz = offy * SIGN22(m_rdp->m_span_dzdy >> 10); | |
| 122 | ||
| 123 | *r = ((*r << 2) + summand_xr + summand_yr) >> 4; | |
| 124 | *g = ((*g << 2) + summand_xg + summand_yg) >> 4; | |
| 125 | *b = ((*b << 2) + summand_xb + summand_yb) >> 4; | |
| 126 | *a = ((*a << 2) + summand_xa + summand_ya) >> 4; | |
| 127 | *z = (((*z << 2) + summand_xz + summand_yz) >> 5) & 0x7ffff; | |
| 128 | } | |
| 129 | } | |
| 130 | ||
| 131 | void Span::Draw1Cycle(int index, int tilenum, bool flip) | |
| 132 | { | |
| 88 | 133 | int clipx1 = m_rdp->GetScissor()->m_xh; |
| 89 | 134 | int clipx2 = m_rdp->GetScissor()->m_xl; |
| 90 | 135 | |
| r9854 | r9855 | |
| 97 | 142 | SpanParam t = m_t; |
| 98 | 143 | SpanParam w = m_w; |
| 99 | 144 | |
| 100 | UINT16 *fb = (UINT16*)&rdram[m_misc_state->m_fb_address / 4]; | |
| 101 | UINT16 *zb = (UINT16*)&rdram[m_misc_state->m_zb_address / 4]; | |
| 102 | UINT8 *hb = &m_rdp->GetHiddenBits()[m_misc_state->m_fb_address >> 1]; | |
| 103 | UINT8 *zhb = &m_rdp->GetHiddenBits()[m_misc_state->m_zb_address >> 1]; | |
| 145 | UINT32 zb = m_misc_state->m_zb_address >> 1; | |
| 146 | UINT32 zhb = zb; | |
| 147 | UINT8 offx = 0, offy = 0; | |
| 104 | 148 | |
| 105 | UINT32 prim_tile = tilenum; | |
| 106 | UINT32 tilenum2 = 0; | |
| 149 | INT32 tile1 = tilenum; | |
| 107 | 150 | |
| 108 | int dzpix = m_dzpix; | |
| 109 | int drinc = flip ? (m_dr.w) : -m_dr.w; | |
| 110 | int dginc = flip ? (m_dg.w) : -m_dg.w; | |
| 111 | int dbinc = flip ? (m_db.w) : -m_db.w; | |
| 112 | int dainc = flip ? (m_da.w) : -m_da.w; | |
| 113 | int dzinc = flip ? (m_dz.w) : -m_dz.w; | |
| 114 | int dsinc = flip ? (m_ds.w) : -m_ds.w; | |
| 115 | int dtinc = flip ? (m_dt.w) : -m_dt.w; | |
| 116 | int dwinc = flip ? (m_dw.w) : -m_dw.w; | |
| 151 | m_rdp->GetTexPipe()->CalculateClampDiffs(tile1); | |
| 152 | ||
| 153 | bool noisecompute = m_rdp->GetColorInputs()->combiner_rgbsub_a_r[1] == &m_rdp->GetNoiseColor()->i.r; | |
| 154 | bool partialreject = (m_rdp->GetColorInputs()->blender2b_a[0] == &m_rdp->GetInvPixelColor()->i.a && m_rdp->GetColorInputs()->blender1b_a[0] == &m_rdp->GetPixelColor()->i.a); | |
| 155 | bool bsel0 = (m_rdp->GetColorInputs()->blender2b_a[0] == &m_rdp->GetMemoryColor()->i.a); | |
| 156 | ||
| 157 | int drinc = flip ? (m_rdp->m_span_dr) : -m_rdp->m_span_dr; | |
| 158 | int dginc = flip ? (m_rdp->m_span_dg) : -m_rdp->m_span_dg; | |
| 159 | int dbinc = flip ? (m_rdp->m_span_db) : -m_rdp->m_span_db; | |
| 160 | int dainc = flip ? (m_rdp->m_span_da) : -m_rdp->m_span_da; | |
| 161 | int dzinc = flip ? (m_rdp->m_span_dz) : -m_rdp->m_span_dz; | |
| 162 | int dsinc = flip ? (m_rdp->m_span_ds) : -m_rdp->m_span_ds; | |
| 163 | int dtinc = flip ? (m_rdp->m_span_dt) : -m_rdp->m_span_dt; | |
| 164 | int dwinc = flip ? (m_rdp->m_span_dw) : -m_rdp->m_span_dw; | |
| 165 | int dzpix = m_rdp->m_span_dzpix; | |
| 117 | 166 | int xinc = flip ? 1 : -1; |
| 118 | 167 | |
| 119 | int nexts; | |
| 120 | int nextt; | |
| 121 | int nextsw; | |
| 122 | ||
| 123 | 168 | int fb_index = m_misc_state->m_fb_width * index; |
| 124 | 169 | |
| 125 | int x = m_rx; | |
| 170 | int cdith = 0; | |
| 171 | int adith = 0; | |
| 126 | 172 | |
| 127 | int length = flip ? (m_lx - m_rx) : (m_rx - m_lx); | |
| 173 | int xstart = m_lx; | |
| 174 | int xend = m_unscissored_rx; | |
| 175 | int xend_scissored = m_rx; | |
| 128 | 176 | |
| 129 | bool disable_lod = false; | |
| 130 | if (m_other_modes->cycle_type != CYCLE_TYPE_2) // Used by World Driver Championship | |
| 131 | { | |
| 132 | disable_lod = true; | |
| 133 | } | |
| 177 | int x = xend; | |
| 134 | 178 | |
| 135 | if (m_other_modes->cycle_type == CYCLE_TYPE_2 && texture && !m_other_modes->tex_lod_en) | |
| 136 | { | |
| 137 | tilenum2 = (prim_tile + 1) & 7; | |
| 138 | } | |
| 179 | int length = flip ? (xstart - xend) : (xend - xstart); | |
| 180 | m_rdp->GetTexPipe()->m_start_span = true; | |
| 181 | UINT32 fir, fig, fib; | |
| 139 | 182 | |
| 140 | if (texture && !m_other_modes->tex_lod_en) | |
| 141 | { | |
| 142 | tilenum = prim_tile; | |
| 143 | } | |
| 144 | ||
| 145 | if(!shade) | |
| 146 | { | |
| 147 | m_rdp->GetShadeColor()->c = m_rdp->GetPrimColor()->c; | |
| 148 | } | |
| 149 | ||
| 150 | 183 | for (int j = 0; j <= length; j++) |
| 151 | 184 | { |
| 152 | int sr = 0; | |
| 153 | int sg = 0; | |
| 154 | int sb = 0; | |
| 155 | int sa = 0; | |
| 156 | int ss = 0; | |
| 157 | int st = 0; | |
| 158 | int sw = 0; | |
| 159 | int sz = 0; | |
| 160 | int sss = 0; | |
| 161 | int sst = 0; | |
| 162 | Color c1; | |
| 163 | Color c2; | |
| 185 | int sr = r.w >> 14; | |
| 186 | int sg = g.w >> 14; | |
| 187 | int sb = b.w >> 14; | |
| 188 | int sa = a.w >> 14; | |
| 189 | int ss = s.w >> 16; | |
| 190 | int st = t.w >> 16; | |
| 191 | int sw = w.w >> 16; | |
| 192 | int sz = (z.w >> 10) & 0x3fffff; | |
| 193 | INT32 sss = 0; | |
| 194 | INT32 sst = 0; | |
| 164 | 195 | |
| 165 | if( | |
| 196 | if (m_other_modes->z_source_sel) | |
| 166 | 197 | { |
| 167 | sr = r.h.h; | |
| 168 | sg = g.h.h; | |
| 169 | sb = b.h.h; | |
| 170 | sa = a.h.h; | |
| 198 | sz = (((UINT32)m_misc_state->m_primitive_z) << 6) & 0x3fffff; | |
| 199 | dzpix = m_misc_state->m_primitive_delta_z; | |
| 200 | dzinc = m_rdp->m_span_dz = m_rdp->m_span_dzdy = 0; | |
| 171 | 201 | } |
| 172 | 202 | |
| 173 | if(texture) | |
| 174 | { | |
| 175 | ss = s.h.h; | |
| 176 | st = t.h.h; | |
| 177 | sw = w.h.h; | |
| 178 | } | |
| 203 | bool valid_x = (flip) ? (x >= xend_scissored) : (x <= xend_scissored); | |
| 179 | 204 | |
| 180 | if( | |
| 205 | if (x >= clipx1 && x < clipx2 && valid_x) | |
| 181 | 206 | { |
| 182 | s | |
| 207 | m_rdp->lookup_cvmask_derivatives(m_cvg[x], &offx, &offy) | |
| 183 | 208 | |
| 184 | if (m_ | |
| 209 | if (m_ | |
| 185 | 210 | { |
| 186 | sz = (((UINT32)m_misc_state->m_primitive_z) << 3) & 0x3ffff; | |
| 187 | dzpix = m_misc_state->m_primitive_delta_z; | |
| 211 | if (m_other_modes->persp_tex_en) | |
| 212 | { | |
| 213 | m_rdp->TCDiv(ss, st, sw, &sss, &sst); | |
| 214 | } | |
| 215 | else | |
| 216 | { | |
| 217 | m_rdp->TCDivNoPersp(ss, st, sw, &sss, &sst); | |
| 218 | } | |
| 188 | 219 | } |
| 189 | } | |
| 220 | else | |
| 221 | { | |
| 222 | sss = m_rdp->GetTexPipe()->m_precomp_s; | |
| 223 | sst = m_rdp->GetTexPipe()->m_precomp_t; | |
| 224 | } | |
| 190 | 225 | |
| 191 | if (x >= clipx1 && x < clipx2) | |
| 192 | { | |
| 193 | bool z_compare_result = true; | |
| 226 | m_rdp->GetTexPipe()->LOD1Cycle(&sss, &sst, s.w, t.w, w.w, dsinc, dtinc, dwinc); | |
| 194 | 227 | |
| 195 | m_misc_state->m_curpixel_cvg = m_cvg[x]; | |
| 228 | RGBAZCorrectTriangle(offx, offy, &sr, &sg, &sb, &sa, &sz); | |
| 229 | RGBAZClip(sr, sg, sb, sa, &sz); | |
| 196 | 230 | |
| 197 | if (m_misc_state->m_curpixel_cvg) | |
| 231 | m_rdp->GetTexPipe()->Cycle(m_rdp->GetTexel0Color(), m_rdp->GetTexel0Color(), sss, sst, tilenum, 0); | |
| 232 | ||
| 233 | m_rdp->ColorCombiner1Cycle(noisecompute); | |
| 234 | ||
| 235 | UINT32 curpixel = fb_index + x; | |
| 236 | UINT32 zbcur = zb + curpixel; | |
| 237 | UINT32 zhbcur = zhb + curpixel; | |
| 238 | ||
| 239 | m_rdp->GetFramebuffer()->Read(curpixel); | |
| 240 | ||
| 241 | if(m_rdp->ZCompare(zbcur, zhbcur, sz, dzpix)) | |
| 198 | 242 | { |
| 199 | int curpixel = fb_index + x; | |
| 200 | UINT16* fbcur = &fb[curpixel ^ WORD_ADDR_XOR]; | |
| 201 | UINT16* zbcur = &zb[curpixel ^ WORD_ADDR_XOR]; | |
| 202 | UINT8* hbcur = &hb[curpixel ^ BYTE_ADDR_XOR]; | |
| 203 | UINT8* zhbcur = &zhb[curpixel ^ BYTE_ADDR_XOR]; | |
| 243 | m_rdp->GetDitherValues(index, j, &cdith, &adith); | |
| 204 | 244 | |
| 205 | if(texture) | |
| 245 | bool rendered = m_rdp->GetBlender()->Blend1Cycle(&fir, &fig, &fib, cdith, adith, partialreject, bsel0); | |
| 246 | ||
| 247 | if (rendered) | |
| 206 | 248 | { |
| 207 | if (m_other_modes->persp_tex_en) | |
| 249 | m_rdp->GetFramebuffer()->Write(curpixel, fir, fig, fib); | |
| 250 | if (m_other_modes->z_update_en) | |
| 208 | 251 | { |
| 209 | m_rdp-> | |
| 252 | m_rdp->ZStore(zbcur, zhbcur, sz | |
| 210 | 253 | } |
| 211 | else // Hack for Bust-a-Move 2 | |
| 212 | { | |
| 213 | sss = ss; | |
| 214 | sst = st; | |
| 215 | } | |
| 254 | } | |
| 255 | } | |
| 256 | } | |
| 216 | 257 | |
| 217 | if (m_other_modes->tex_lod_en && !disable_lod) | |
| 218 | { | |
| 219 | if (m_other_modes->persp_tex_en) | |
| 220 | { | |
| 221 | nextsw = (w.w + dwinc) >> 16; | |
| 222 | nexts = (s.w + dsinc) >> 16; | |
| 223 | nextt = (t.w + dtinc) >> 16; | |
| 224 | m_rdp->TCDiv(nexts, nextt, nextsw, &nexts, &nextt); | |
| 225 | } | |
| 226 | else | |
| 227 | { | |
| 228 | nexts = (s.w + dsinc)>>16; | |
| 229 | nextt = (t.w + dtinc)>>16; | |
| 230 | } | |
| 258 | r.w += drinc; | |
| 259 | g.w += dginc; | |
| 260 | b.w += dbinc; | |
| 261 | a.w += dainc; | |
| 262 | s.w += dsinc; | |
| 263 | t.w += dtinc; | |
| 264 | w.w += dwinc; | |
| 265 | z.w += dzinc; | |
| 231 | 266 | |
| 232 | INT32 horstep = SIGN17(nexts & 0x1ffff) - SIGN17(sss & 0x1ffff); | |
| 233 | INT32 vertstep = SIGN17(nextt & 0x1ffff) - SIGN17(sst & 0x1ffff); | |
| 234 | if (horstep & 0x20000) | |
| 235 | { | |
| 236 | horstep = ~horstep & 0x1ffff; | |
| 237 | } | |
| 238 | if (vertstep & 0x20000) | |
| 239 | { | |
| 240 | vertstep = ~vertstep & 0x1ffff; | |
| 241 | } | |
| 267 | x += xinc; | |
| 268 | } | |
| 269 | } | |
| 242 | 270 | |
| 243 | int LOD = (horstep >= vertstep) ? horstep : vertstep; | |
| 244 | LOD = (LOD >= m_dymax) ? LOD : m_dymax; | |
| 271 | void Span::Draw2Cycle(int index, int tilenum, bool flip) | |
| 272 | { | |
| 273 | int clipx1 = m_rdp->GetScissor()->m_xh; | |
| 274 | int clipx2 = m_rdp->GetScissor()->m_xl; | |
| 245 | 275 | |
| 246 | if (LOD & 0x1c000) | |
| 247 | { | |
| 248 | LOD = 0x7fff; | |
| 249 | } | |
| 250 | if (LOD < m_misc_state->m_min_level) | |
| 251 | { | |
| 252 | LOD = m_misc_state->m_min_level; | |
| 253 | } | |
| 276 | SpanParam r = m_r; | |
| 277 | SpanParam g = m_g; | |
| 278 | SpanParam b = m_b; | |
| 279 | SpanParam a = m_a; | |
| 280 | SpanParam z = m_z; | |
| 281 | SpanParam s = m_s; | |
| 282 | SpanParam t = m_t; | |
| 283 | SpanParam w = m_w; | |
| 254 | 284 | |
| 255 | bool magnify = (LOD < 32); | |
| 256 | INT32 l_tile = m_rdp->GetLog2((LOD >> 5) & 0xff); | |
| 257 | bool distant = ((LOD & 0x6000) || (l_tile >= m_misc_state->m_max_level)); | |
| 285 | UINT32 zb = m_misc_state->m_zb_address >> 1; | |
| 286 | UINT32 zhb = zb; | |
| 287 | UINT8 offx = 0, offy = 0; | |
| 258 | 288 | |
| 259 | m_rdp->SetLODFrac(((LOD << 3) >> l_tile) & 0xff); | |
| 289 | INT32 tile2 = (tilenum + 1) & 7; | |
| 290 | INT32 tile1 = tilenum; | |
| 291 | UINT32 prim_tile = tilenum; | |
| 260 | 292 | |
| 261 | if (distant) | |
| 262 | { | |
| 263 | l_tile = m_misc_state->m_max_level; | |
| 264 | } | |
| 265 | if(!m_other_modes->sharpen_tex_en && !m_other_modes->detail_tex_en && magnify) | |
| 266 | { | |
| 267 | m_rdp->SetLODFrac(0); | |
| 268 | } | |
| 269 | if(!m_other_modes->sharpen_tex_en && !m_other_modes->detail_tex_en && distant) | |
| 270 | { | |
| 271 | m_rdp->SetLODFrac(0xff); | |
| 272 | } | |
| 273 | if(m_other_modes->sharpen_tex_en && magnify) | |
| 274 | { | |
| 275 | m_rdp->SetLODFrac(*(m_rdp->GetLODFrac()) | 0x100); | |
| 276 | } | |
| 293 | int newtile1 = tile1; | |
| 294 | INT32 news = 0; | |
| 295 | INT32 newt = 0; | |
| 277 | 296 | |
| 278 | if (!m_other_modes->detail_tex_en) | |
| 279 | { | |
| 280 | tilenum = (prim_tile + l_tile); | |
| 281 | tilenum &= 7; | |
| 282 | if (m_other_modes->sharpen_tex_en) | |
| 283 | { | |
| 284 | tilenum2 = (tilenum + 1) & 7; | |
| 285 | } | |
| 286 | else if (!distant) | |
| 287 | { | |
| 288 | tilenum2 = (tilenum + 1) & 7; | |
| 289 | } | |
| 290 | else | |
| 291 | { | |
| 292 | tilenum2 = tilenum; | |
| 293 | } | |
| 294 | } | |
| 295 | else | |
| 296 | { | |
| 297 | if (!magnify) | |
| 298 | { | |
| 299 | tilenum = (prim_tile + l_tile + 1); | |
| 300 | } | |
| 301 | else | |
| 302 | { | |
| 303 | tilenum = (prim_tile + l_tile); | |
| 304 | } | |
| 305 | tilenum &= 7; | |
| 297 | m_rdp->GetTexPipe()->CalculateClampDiffs(tile1); | |
| 306 | 298 | |
| 307 | if (!distant && !magnify) | |
| 308 | { | |
| 309 | tilenum2 = (prim_tile + l_tile + 2) & 7; | |
| 310 | } | |
| 311 | else | |
| 312 | { | |
| 313 | tilenum2 = (prim_tile + l_tile + 1) & 7; | |
| 314 | } | |
| 315 | } | |
| 316 | } | |
| 299 | bool noisecompute = (m_rdp->GetColorInputs()->combiner_rgbsub_a_r[0] == &m_rdp->GetNoiseColor()->i.r || m_rdp->GetColorInputs()->combiner_rgbsub_a_r[1] == &m_rdp->GetPixelColor()->i.r); | |
| 300 | bool partialreject = (m_rdp->GetColorInputs()->blender2b_a[1] == &m_rdp->GetInvPixelColor()->i.a && m_rdp->GetColorInputs()->blender1b_a[1] == &m_rdp->GetPixelColor()->i.a); | |
| 301 | bool bsel0 = (m_rdp->GetColorInputs()->blender2b_a[0] == &m_rdp->GetMemoryColor()->i.a); | |
| 302 | bool bsel1 = (m_rdp->GetColorInputs()->blender2b_a[1] == &m_rdp->GetMemoryColor()->i.a); | |
| 317 | 303 | |
| 318 | if (m_other_modes->cycle_type == CYCLE_TYPE_1) | |
| 319 | { | |
| 320 | m_rdp->GetTexel0Color()->c = m_rdp->GetTexPipe()->Fetch(sss, sst, &m_rdp->GetTiles()[tilenum]); | |
| 321 | } | |
| 322 | else | |
| 323 | { | |
| 324 | m_rdp->GetTexel0Color()->c = m_rdp->GetTexPipe()->Fetch(sss, sst, &m_rdp->GetTiles()[tilenum]); | |
| 325 | m_rdp->GetTexel1Color()->c = m_rdp->GetTexPipe()->Fetch(sss, sst, &m_rdp->GetTiles()[tilenum2]); | |
| 326 | } | |
| 327 | } | |
| 304 | int dzpix = m_rdp->m_span_dzpix; | |
| 305 | int drinc = flip ? (m_rdp->m_span_dr) : -m_rdp->m_span_dr; | |
| 306 | int dginc = flip ? (m_rdp->m_span_dg) : -m_rdp->m_span_dg; | |
| 307 | int dbinc = flip ? (m_rdp->m_span_db) : -m_rdp->m_span_db; | |
| 308 | int dainc = flip ? (m_rdp->m_span_da) : -m_rdp->m_span_da; | |
| 309 | int dzinc = flip ? (m_rdp->m_span_dz) : -m_rdp->m_span_dz; | |
| 310 | int dsinc = flip ? (m_rdp->m_span_ds) : -m_rdp->m_span_ds; | |
| 311 | int dtinc = flip ? (m_rdp->m_span_dt) : -m_rdp->m_span_dt; | |
| 312 | int dwinc = flip ? (m_rdp->m_span_dw) : -m_rdp->m_span_dw; | |
| 313 | int xinc = flip ? 1 : -1; | |
| 328 | 314 | |
| 329 | if (shade) | |
| 330 | { | |
| 331 | if (sr > 0xff) sr = 0xff; | |
| 332 | if (sg > 0xff) sg = 0xff; | |
| 333 | if (sb > 0xff) sb = 0xff; | |
| 334 | if (sa > 0xff) sa = 0xff; | |
| 335 | if (sr < 0) sr = 0; | |
| 336 | if (sg < 0) sg = 0; | |
| 337 | if (sb < 0) sb = 0; | |
| 338 | if (sa < 0) sa = 0; | |
| 339 | m_rdp->GetShadeColor()->i.r = sr; | |
| 340 | m_rdp->GetShadeColor()->i.g = sg; | |
| 341 | m_rdp->GetShadeColor()->i.b = sb; | |
| 342 | m_rdp->GetShadeColor()->i.a = sa; | |
| 343 | } | |
| 315 | int fb_index = m_misc_state->m_fb_width * index; | |
| 344 | 316 | |
| 345 | if (m_other_modes->cycle_type == CYCLE_TYPE_1) | |
| 317 | int cdith = 0; | |
| 318 | int adith = 0; | |
| 319 | ||
| 320 | int xstart = m_lx; | |
| 321 | int xend = m_unscissored_rx; | |
| 322 | int xend_scissored = m_rx; | |
| 323 | ||
| 324 | int x = xend; | |
| 325 | ||
| 326 | int length = flip ? (xstart - xend) : (xend - xstart); | |
| 327 | m_rdp->GetTexPipe()->m_start_span = true; | |
| 328 | UINT32 fir, fig, fib; | |
| 329 | ||
| 330 | //printf( "Span length: %d\n", length); | |
| 331 | ||
| 332 | for (int j = 0; j <= length; j++) | |
| 333 | { | |
| 334 | int sr = r.w >> 14; | |
| 335 | int sg = g.w >> 14; | |
| 336 | int sb = b.w >> 14; | |
| 337 | int sa = a.w >> 14; | |
| 338 | int ss = s.h.h; | |
| 339 | int st = t.h.h; | |
| 340 | int sw = w.h.h; | |
| 341 | int sz = (z.w >> 10) & 0x3fffff; | |
| 342 | INT32 sss = 0; | |
| 343 | INT32 sst = 0; | |
| 344 | Color c1; | |
| 345 | Color c2; | |
| 346 | ||
| 347 | if (m_other_modes->z_source_sel) | |
| 348 | { | |
| 349 | sz = (((UINT32)m_misc_state->m_primitive_z) << 6) & 0x3fffff; | |
| 350 | dzpix = m_misc_state->m_primitive_delta_z; | |
| 351 | dzinc = m_rdp->m_span_dz = m_rdp->m_span_dzdy = 0; | |
| 352 | } | |
| 353 | ||
| 354 | bool valid_x = (flip) ? (x >= xend_scissored) : (x <= xend_scissored); | |
| 355 | ||
| 356 | if (x >= clipx1 && x < clipx2 && valid_x) | |
| 357 | { | |
| 358 | m_rdp->lookup_cvmask_derivatives(m_cvg[x], &offx, &offy); | |
| 359 | ||
| 360 | if (m_rdp->GetTexPipe()->m_start_span) | |
| 361 | { | |
| 362 | if (m_other_modes->persp_tex_en) | |
| 346 | 363 | { |
| 347 | c1.i.r = LookUpCC(*m_rdp->GetColorInputs()->combiner_rgbsub_a_r[1], | |
| 348 | *m_rdp->GetColorInputs()->combiner_rgbsub_b_r[1], | |
| 349 | *m_rdp->GetColorInputs()->combiner_rgbmul_r[1], | |
| 350 | *m_rdp->GetColorInputs()->combiner_rgbadd_r[1]); | |
| 351 | c1.i.g = LookUpCC(*m_rdp->GetColorInputs()->combiner_rgbsub_a_g[1], | |
| 352 | *m_rdp->GetColorInputs()->combiner_rgbsub_b_g[1], | |
| 353 | *m_rdp->GetColorInputs()->combiner_rgbmul_g[1], | |
| 354 | *m_rdp->GetColorInputs()->combiner_rgbadd_g[1]); | |
| 355 | c1.i.b = LookUpCC(*m_rdp->GetColorInputs()->combiner_rgbsub_a_b[1], | |
| 356 | *m_rdp->GetColorInputs()->combiner_rgbsub_b_b[1], | |
| 357 | *m_rdp->GetColorInputs()->combiner_rgbmul_b[1], | |
| 358 | *m_rdp->GetColorInputs()->combiner_rgbadd_b[1]); | |
| 359 | c1.i.a = LookUpCC(*m_rdp->GetColorInputs()->combiner_alphasub_a[1], | |
| 360 | *m_rdp->GetColorInputs()->combiner_alphasub_b[1], | |
| 361 | *m_rdp->GetColorInputs()->combiner_alphamul[1], | |
| 362 | *m_rdp->GetColorInputs()->combiner_alphaadd[1]); | |
| 363 | m_rdp->GetAlphaCvg(&c1.i.a); | |
| 364 | m_rdp->TCDiv(ss, st, sw, &sss, &sst); | |
| 364 | 365 | } |
| 365 | else | |
| 366 | else | |
| 366 | 367 | { |
| 367 | c1.i.r = LookUpCC(*m_rdp->GetColorInputs()->combiner_rgbsub_a_r[0], | |
| 368 | *m_rdp->GetColorInputs()->combiner_rgbsub_b_r[0], | |
| 369 | *m_rdp->GetColorInputs()->combiner_rgbmul_r[0], | |
| 370 | *m_rdp->GetColorInputs()->combiner_rgbadd_r[0]); | |
| 371 | c1.i.g = LookUpCC(*m_rdp->GetColorInputs()->combiner_rgbsub_a_g[0], | |
| 372 | *m_rdp->GetColorInputs()->combiner_rgbsub_b_g[0], | |
| 373 | *m_rdp->GetColorInputs()->combiner_rgbmul_g[0], | |
| 374 | *m_rdp->GetColorInputs()->combiner_rgbadd_g[0]); | |
| 375 | c1.i.b = LookUpCC(*m_rdp->GetColorInputs()->combiner_rgbsub_a_b[0], | |
| 376 | *m_rdp->GetColorInputs()->combiner_rgbsub_b_b[0], | |
| 377 | *m_rdp->GetColorInputs()->combiner_rgbmul_b[0], | |
| 378 | *m_rdp->GetColorInputs()->combiner_rgbadd_b[0]); | |
| 379 | c1.i.a = LookUpCC(*m_rdp->GetColorInputs()->combiner_alphasub_a[0], | |
| 380 | *m_rdp->GetColorInputs()->combiner_alphasub_b[0], | |
| 381 | *m_rdp->GetColorInputs()->combiner_alphamul[0], | |
| 382 | *m_rdp->GetColorInputs()->combiner_alphaadd[0]); | |
| 383 | m_rdp->GetCombinedColor()->c = c1.c; | |
| 384 | c2.c = m_rdp->GetTexel0Color()->c; | |
| 385 | m_rdp->GetTexel0Color()->c = m_rdp->GetTexel1Color()->c; | |
| 386 | m_rdp->GetTexel1Color()->c = c2.c; | |
| 387 | c2.i.r = LookUpCC(*m_rdp->GetColorInputs()->combiner_rgbsub_a_r[1], | |
| 388 | *m_rdp->GetColorInputs()->combiner_rgbsub_b_r[1], | |
| 389 | *m_rdp->GetColorInputs()->combiner_rgbmul_r[1], | |
| 390 | *m_rdp->GetColorInputs()->combiner_rgbadd_r[1]); | |
| 391 | c2.i.g = LookUpCC(*m_rdp->GetColorInputs()->combiner_rgbsub_a_g[1], | |
| 392 | *m_rdp->GetColorInputs()->combiner_rgbsub_b_g[1], | |
| 393 | *m_rdp->GetColorInputs()->combiner_rgbmul_g[1], | |
| 394 | *m_rdp->GetColorInputs()->combiner_rgbadd_g[1]); | |
| 395 | c2.i.b = LookUpCC(*m_rdp->GetColorInputs()->combiner_rgbsub_a_b[1], | |
| 396 | *m_rdp->GetColorInputs()->combiner_rgbsub_b_b[1], | |
| 397 | *m_rdp->GetColorInputs()->combiner_rgbmul_b[1], | |
| 398 | *m_rdp->GetColorInputs()->combiner_rgbadd_b[1]); | |
| 399 | c2.i.a = LookUpCC(*m_rdp->GetColorInputs()->combiner_alphasub_a[1], | |
| 400 | *m_rdp->GetColorInputs()->combiner_alphasub_b[1], | |
| 401 | *m_rdp->GetColorInputs()->combiner_alphamul[1], | |
| 402 | *m_rdp->GetColorInputs()->combiner_alphaadd[1]); | |
| 403 | m_rdp->GetAlphaCvg(&c2.i.a); | |
| 368 | m_rdp->TCDivNoPersp(ss, st, sw, &sss, &sst); | |
| 404 | 369 | } |
| 370 | } | |
| 371 | else | |
| 372 | { | |
| 373 | sss = m_rdp->GetTexPipe()->m_precomp_s; | |
| 374 | sst = m_rdp->GetTexPipe()->m_precomp_t; | |
| 375 | } | |
| 405 | 376 | |
| 406 | if ((zbuffer || m_other_modes->z_source_sel) && m_other_modes->z_compare_en) | |
| 407 | { | |
| 408 | z_compare_result = m_rdp->ZCompare(fbcur, hbcur, zbcur, zhbcur, sz, dzpix); | |
| 409 | } | |
| 377 | m_rdp->GetTexPipe()->LOD2Cycle(&sss, &sst, s.w, t.w, w.w, dsinc, dtinc, dwinc, prim_tile, &tile1, &tile2); | |
| 410 | 378 | |
| 411 | if(z_compare_result) | |
| 412 | { | |
| 413 | bool rendered = false; | |
| 414 | int dith = 0; | |
| 415 | if (!m_other_modes->rgb_dither_sel) | |
| 416 | { | |
| 417 | dith = m_rdp->GetMagicMatrix()[(((index) & 3) << 2) + ((x ^ WORD_ADDR_XOR) & 3)]; | |
| 418 | } | |
| 419 | else if (m_other_modes->rgb_dither_sel == 1) | |
| 420 | { | |
| 421 | dith = m_rdp->GetBayerMatrix()[(((index) & 3) << 2) + ((x ^ WORD_ADDR_XOR) & 3)]; | |
| 422 | } | |
| 379 | news = m_rdp->GetTexPipe()->m_precomp_s; | |
| 380 | newt = m_rdp->GetTexPipe()->m_precomp_t; | |
| 381 | m_rdp->GetTexPipe()->LOD2CycleLimited(&news, &newt, s.w + dsinc, t.w + dtinc, w.w + dwinc, dsinc, dtinc, dwinc, prim_tile, &newtile1); | |
| 423 | 382 | |
| 424 | rendered = m_rdp->GetBlender()->Blend(fbcur, hbcur, c1, c2, dith); | |
| 383 | RGBAZCorrectTriangle(offx, offy, &sr, &sg, &sb, &sa, &sz); | |
| 384 | RGBAZClip(sr, sg, sb, sa, &sz); | |
| 425 | 385 | |
| 426 | if (m_other_modes->z_update_en && rendered) | |
| 386 | m_rdp->GetTexPipe()->Cycle(m_rdp->GetTexel0Color(), m_rdp->GetTexel0Color(), sss, sst, tile1, 0); | |
| 387 | m_rdp->GetTexPipe()->Cycle(m_rdp->GetTexel1Color(), m_rdp->GetTexel0Color(), sss, sst, tile2, 1); | |
| 388 | ||
| 389 | m_rdp->GetTexPipe()->Cycle(m_rdp->GetNextTexelColor(), m_rdp->GetNextTexelColor(), sss, sst, tile2, 1); | |
| 390 | ||
| 391 | m_rdp->ColorCombiner2Cycle(noisecompute); | |
| 392 | ||
| 393 | UINT32 curpixel = fb_index + x; | |
| 394 | UINT32 zbcur = zb + curpixel; | |
| 395 | UINT32 zhbcur = zhb + curpixel; | |
| 396 | ||
| 397 | m_rdp->GetFramebuffer()->Read(curpixel); | |
| 398 | ||
| 399 | if(m_rdp->ZCompare(zbcur, zhbcur, sz, dzpix)) | |
| 400 | { | |
| 401 | m_rdp->GetDitherValues(index, j, &cdith, &adith); | |
| 402 | ||
| 403 | bool rendered = m_rdp->GetBlender()->Blend2Cycle(&fir, &fig, &fib, cdith, adith, partialreject, bsel0, bsel1); | |
| 404 | ||
| 405 | if (rendered) | |
| 406 | { | |
| 407 | m_rdp->GetFramebuffer()->Write(curpixel, fir, fig, fib); | |
| 408 | if (m_other_modes->z_update_en) | |
| 427 | 409 | { |
| 428 | m_rdp->ZStore(zbcur, zhbcur, sz | |
| 410 | m_rdp->ZStore(zbcur, zhbcur, sz | |
| 429 | 411 | } |
| 430 | 412 | } |
| 431 | 413 | } |
| 432 | 414 | } |
| 433 | 415 | |
| 434 | if (shade) | |
| 416 | r.w += drinc; | |
| 417 | g.w += dginc; | |
| 418 | b.w += dbinc; | |
| 419 | a.w += dainc; | |
| 420 | s.w += dsinc; | |
| 421 | t.w += dtinc; | |
| 422 | w.w += dwinc; | |
| 423 | z.w += dzinc; | |
| 424 | ||
| 425 | x += xinc; | |
| 426 | } | |
| 427 | } | |
| 428 | ||
| 429 | void Span::DrawCopy(int index, int tilenum, bool flip) | |
| 430 | { | |
| 431 | int clipx1 = m_rdp->GetScissor()->m_xh; | |
| 432 | int clipx2 = m_rdp->GetScissor()->m_xl; | |
| 433 | ||
| 434 | SpanParam s = m_s; | |
| 435 | SpanParam t = m_t; | |
| 436 | ||
| 437 | int ds = m_rdp->m_span_ds / 4; | |
| 438 | int dt = m_rdp->m_span_dt / 4; | |
| 439 | int dsinc = flip ? (ds) : -ds; | |
| 440 | int dtinc = flip ? (dt) : -dt; | |
| 441 | int xinc = flip ? 1 : -1; | |
| 442 | ||
| 443 | int fb_index = m_misc_state->m_fb_width * index; | |
| 444 | ||
| 445 | int xstart = m_lx; | |
| 446 | int xend = m_unscissored_rx; | |
| 447 | int xend_scissored = m_rx; | |
| 448 | ||
| 449 | int x = xend; | |
| 450 | ||
| 451 | int length = flip ? (xstart - xend) : (xend - xstart); | |
| 452 | ||
| 453 | for (int j = 0; j <= length; j++) | |
| 454 | { | |
| 455 | bool valid_x = (flip) ? (x >= xend_scissored) : (x <= xend_scissored); | |
| 456 | ||
| 457 | if (x >= clipx1 && x < clipx2 && valid_x) | |
| 435 | 458 | { |
| 436 | r.w += drinc; | |
| 437 | g.w += dginc; | |
| 438 | b.w += dbinc; | |
| 439 | a.w += dainc; | |
| 459 | INT32 sss = s.h.h; | |
| 460 | INT32 sst = t.h.h; | |
| 461 | m_rdp->GetTexPipe()->Copy(m_rdp->GetTexel0Color(), sss, sst, tilenum); | |
| 462 | ||
| 463 | UINT32 curpixel = fb_index + x; | |
| 464 | m_misc_state->m_curpixel_cvg = m_rdp->GetTexel0Color()->i.a ? 7 : 0; | |
| 465 | if ((m_rdp->GetTexel0Color()->i.a != 0) || (!m_other_modes->alpha_compare_en)) | |
| 466 | { | |
| 467 | m_rdp->GetFramebuffer()->Copy(curpixel, m_rdp->GetTexel0Color()->i.r, m_rdp->GetTexel0Color()->i.g, m_rdp->GetTexel0Color()->i.b); | |
| 468 | } | |
| 440 | 469 | } |
| 441 | if (texture) | |
| 470 | ||
| 471 | s.w += dsinc; | |
| 472 | t.w += dtinc; | |
| 473 | x += xinc; | |
| 474 | } | |
| 475 | } | |
| 476 | ||
| 477 | void Span::DrawFill(int index, int tilenum, bool flip) | |
| 478 | { | |
| 479 | int clipx1 = m_rdp->GetScissor()->m_xh; | |
| 480 | int clipx2 = m_rdp->GetScissor()->m_xl; | |
| 481 | ||
| 482 | int xinc = flip ? 1 : -1; | |
| 483 | ||
| 484 | int fb_index = m_misc_state->m_fb_width * index; | |
| 485 | ||
| 486 | int xstart = m_lx; | |
| 487 | int xend_scissored = m_rx; | |
| 488 | ||
| 489 | int x = xend_scissored; | |
| 490 | ||
| 491 | int length = flip ? (xstart - xend_scissored) : (xend_scissored - xstart); | |
| 492 | ||
| 493 | for (int j = 0; j <= length; j++) | |
| 494 | { | |
| 495 | if (x >= clipx1 && x < clipx2) | |
| 442 | 496 | { |
| 443 | s.w += dsinc; | |
| 444 | t.w += dtinc; | |
| 445 | w.w += dwinc; | |
| 497 | UINT32 curpixel = fb_index + x; | |
| 498 | m_rdp->GetFramebuffer()->Fill(curpixel); | |
| 446 | 499 | } |
| 447 | if (zbuffer) | |
| 448 | { | |
| 449 | z.w += dzinc; | |
| 450 | } | |
| 451 | 500 | |
| 452 | 501 | x += xinc; |
| 453 | 502 | } |
| r9854 | r9855 | |
|---|---|---|
| 34 | 34 | public: |
| 35 | 35 | Span() { } |
| 36 | 36 | |
| 37 | void Draw(int index, int tilenum, bool shade, bool texture, bool zbuffer, bool flip); | |
| 38 | 37 | void Dump(); |
| 39 | 38 | void SetMachine(running_machine* machine); |
| 40 | 39 | |
| 40 | void Draw1Cycle(int index, int tilenum, bool flip); | |
| 41 | void Draw2Cycle(int index, int tilenum, bool flip); | |
| 42 | void DrawCopy(int index, int tilenum, bool flip); | |
| 43 | void DrawFill(int index, int tilenum, bool flip); | |
| 44 | ||
| 41 | 45 | public: |
| 42 | 46 | int m_lx; |
| 43 | 47 | int m_rx; |
| 48 | int m_unscissored_rx; | |
| 44 | 49 | |
| 45 | 50 | SpanParam m_s; |
| 46 | 51 | SpanParam m_t; |
| r9854 | r9855 | |
| 51 | 56 | SpanParam m_a; |
| 52 | 57 | SpanParam m_z; |
| 53 | 58 | |
| 54 | UINT | |
| 59 | UINT16 m_cvg[RDP_CVG_SPAN_MAX]; | |
| 55 | 60 | |
| 56 | int m_dymax; | |
| 57 | ||
| 58 | SpanParam m_ds; | |
| 59 | SpanParam m_dt; | |
| 60 | SpanParam m_dw; | |
| 61 | SpanParam m_dr; | |
| 62 | SpanParam m_dg; | |
| 63 | SpanParam m_db; | |
| 64 | SpanParam m_da; | |
| 65 | SpanParam m_dz; | |
| 66 | ||
| 67 | int m_dzpix; | |
| 68 | ||
| 69 | 61 | private: |
| 62 | void RGBAZClip(int sr, int sg, int sb, int sa, int *sz); | |
| 63 | void RGBAZCorrectTriangle(INT32 offx, INT32 offy, INT32* r, INT32* g, INT32* b, INT32* a, INT32* z); | |
| 64 | ||
| 70 | 65 | running_machine* m_machine; |
| 71 | 66 | Processor* m_rdp; |
| 72 | 67 | MiscState* m_misc_state; |
| r9854 | r9855 | |
|---|---|---|
| 5 | 5 | namespace N64 |
| 6 | 6 | { |
| 7 | 7 | |
| 8 | ||
| 8 | n | |
| 9 | 9 | { |
| 10 | ||
| 11 | void Framebuffer::Write(UINT32 curpixel, UINT32 r, UINT32 g, UINT32 b) | |
| 12 | { | |
| 10 | 13 | switch(m_misc_state->m_fb_size) |
| 11 | 14 | { |
| 12 | 15 | case PIXEL_SIZE_16BIT: |
| 13 | return Write16Bit((UINT16*)fb, hb, r, g, b); | |
| 16 | Write16Bit(curpixel, r, g, b); | |
| 17 | break; | |
| 14 | 18 | |
| 15 | 19 | case PIXEL_SIZE_32BIT: |
| 16 | return Write32Bit((UINT32*)fb, r, g, b); | |
| 20 | Write32Bit(curpixel, r, g, b); | |
| 21 | break; | |
| 17 | 22 | |
| 18 | 23 | default: |
| 19 | 24 | fatalerror("Unsupported bit depth: %d\n", m_misc_state->m_fb_size); |
| 20 | 25 | break; |
| 21 | 26 | } |
| 22 | ||
| 23 | return false; | |
| 24 | 27 | } |
| 25 | 28 | |
| 26 | ||
| 29 | void | |
| 27 | 30 | { |
| 28 | 31 | #undef CVG_DRAW |
| 29 | //#define CVG_DRAW | |
| 30 | 32 | #ifdef CVG_DRAW |
| 31 | int covdraw; | |
| 32 | if (m_misc_state->m_curpixel_cvg == 8) | |
| 33 | { | |
| 34 | covdraw = 255; | |
| 35 | } | |
| 36 | else | |
| 37 | { | |
| 38 | covdraw = m_misc_state->m_curpixel_cvg << 5; | |
| 39 | } | |
| 33 | int covdraw = (curpixel_cvg - 1) << 5; | |
| 40 | 34 | r = covdraw; |
| 41 | 35 | g = covdraw; |
| 42 | 36 | b = covdraw; |
| 43 | 37 | #endif |
| 44 | 38 | |
| 45 | if (!m_other_modes->z_compare_en) | |
| 39 | UINT32 fb = (m_misc_state->m_fb_address >> 1) + curpixel; | |
| 40 | UINT32 hb = fb; | |
| 41 | ||
| 42 | #if 0 | |
| 43 | if (m_misc_state->m_curpixel_cvg > 8 && m_other_modes->z_mode != 1) | |
| 46 | 44 | { |
| 47 | m_misc_state->m_curpixel_ | |
| 45 | stricterror("FBWRITE_16: curpixel_cvg %d", m_misc_state->m_curpixel_cvg) | |
| 48 | 46 | } |
| 47 | #endif | |
| 49 | 48 | |
| 50 | UINT32 memory_cvg = 8; | |
| 51 | if (m_other_modes->image_read_en) | |
| 49 | UINT16 finalcolor = ((r >> 3) << 11) | ((g >> 3) << 6) | ((b >> 3) << 1); | |
| 50 | UINT32 finalcvg = 0; | |
| 51 | ||
| 52 | if (m_other_modes->color_on_cvg && !m_pre_wrap) | |
| 52 | 53 | { |
| 53 | | |
| 54 | finalcolor | |
| 54 | 55 | } |
| 55 | 56 | |
| 56 | UINT32 newcvg = m_misc_state->m_curpixel_cvg + memory_cvg; | |
| 57 | bool wrapped = newcvg > 8; | |
| 57 | switch(m_other_modes->cvg_dest) | |
| 58 | { | |
| 59 | case 0: | |
| 60 | if (!m_rdp->GetBlender()->GetBlendEnable()) | |
| 61 | { | |
| 62 | finalcvg = (m_misc_state->m_curpixel_cvg - 1) & 7; | |
| 63 | RWRITEIDX16(fb, finalcolor | ((finalcvg >> 2) & 1)); | |
| 64 | HWRITEADDR8(hb, finalcvg & 3); | |
| 65 | } | |
| 66 | else | |
| 67 | { | |
| 68 | finalcvg = m_misc_state->m_curpixel_cvg + m_misc_state->m_curpixel_memcvg; | |
| 69 | if (finalcvg & 8) | |
| 70 | { | |
| 71 | finalcvg = 7; | |
| 72 | } | |
| 73 | RWRITEIDX16(fb, finalcolor | ((finalcvg >> 2) & 1)); | |
| 74 | HWRITEADDR8(hb, finalcvg & 3); | |
| 75 | } | |
| 76 | break; | |
| 77 | case 1: | |
| 78 | finalcvg = (m_misc_state->m_curpixel_cvg + m_misc_state->m_curpixel_memcvg) & 7; | |
| 79 | RWRITEIDX16(fb, finalcolor | ((finalcvg >> 2) & 1)); | |
| 80 | HWRITEADDR8(hb, finalcvg & 3); | |
| 81 | break; | |
| 82 | case 2: | |
| 83 | RWRITEIDX16(fb, finalcolor | 1); | |
| 84 | HWRITEADDR8(hb, 3); | |
| 85 | break; | |
| 86 | case 3: | |
| 87 | RWRITEIDX16(fb, finalcolor | ((m_misc_state->m_curpixel_memcvg >> 2) & 1)); | |
| 88 | HWRITEADDR8(hb, m_misc_state->m_curpixel_memcvg & 3); | |
| 89 | break; | |
| 90 | } | |
| 91 | } | |
| 58 | 92 | |
| 59 | UINT16 finalcolor = ((r >> 3) << 11) | ((g >> 3) << 6) | ((b >> 3) << 1); | |
| 93 | void Framebuffer::Write32Bit(UINT32 curpixel, UINT32 r, UINT32 g, UINT32 b) | |
| 94 | { | |
| 95 | UINT32 fb = (m_misc_state->m_fb_address >> 2) + curpixel; | |
| 96 | UINT32 finalcolor = (r << 24) | (g << 16) | (b << 8);//cvg as 3 MSBs of alpha channel; | |
| 97 | UINT32 finalcvg = 0; | |
| 60 | 98 | |
| 61 | UINT32 clamped_cvg = wrapped ? 8 : newcvg; | |
| 62 | newcvg = wrapped ? (newcvg - 8) : newcvg; | |
| 99 | #if 0 | |
| 100 | if (curpixel_cvg > 8 && m_other_modes->z_mode != 1) | |
| 101 | { | |
| 102 | stricterror("FBWRITE_16: curpixel_cvg %d", curpixel_cvg); | |
| 103 | } | |
| 104 | #endif | |
| 63 | 105 | |
| 64 | m_misc_state->m_curpixel_cvg--; | |
| 65 | newcvg--; | |
| 66 | memory_cvg--; | |
| 67 | clamped_cvg--; | |
| 68 | ||
| 69 | if (m_other_modes->color_on_cvg && !wrapped) | |
| 106 | if (m_other_modes->color_on_cvg && !m_pre_wrap) | |
| 70 | 107 | { |
| 71 | *fb &= 0xfffe; | |
| 72 | *fb |= ((newcvg >> 2) & 1); | |
| 73 | *hb = (newcvg & 3); | |
| 74 | return false; | |
| 108 | finalcolor = RREADIDX32(fb) & 0xffffff00; | |
| 75 | 109 | } |
| 76 | 110 | |
| 77 | 111 | switch(m_other_modes->cvg_dest) |
| 78 | 112 | { |
| 79 | case 0: | |
| 80 | if (!m_other_modes->force_blend && !m_misc_state->m_curpixel_overlap) | |
| 113 | case 0: //normal | |
| 114 | if (!m_rdp->GetBlender()->GetBlendEnable()) | |
| 115 | { | |
| 116 | finalcvg = (m_misc_state->m_curpixel_cvg - 1) & 7; | |
| 117 | finalcolor |= (finalcvg << 5); | |
| 118 | RWRITEIDX32(fb, finalcolor); | |
| 119 | } | |
| 120 | else | |
| 121 | { | |
| 122 | finalcvg = m_misc_state->m_curpixel_cvg + m_misc_state->m_curpixel_memcvg; | |
| 123 | if (finalcvg & 8) | |
| 81 | 124 | { |
| 82 | *fb = finalcolor | ((m_misc_state->m_curpixel_cvg >> 2) & 1); | |
| 83 | *hb = (m_misc_state->m_curpixel_cvg & 3); | |
| 125 | finalcvg = 7; | |
| 84 | 126 | } |
| 85 | else | |
| 86 | { | |
| 87 | *fb = finalcolor | ((clamped_cvg >> 2) & 1); | |
| 88 | *hb = (clamped_cvg & 3); | |
| 89 | } | |
| 90 | break; | |
| 127 | finalcolor |= (finalcvg << 5); | |
| 128 | RWRITEIDX32(fb, finalcolor); | |
| 129 | } | |
| 130 | break; | |
| 131 | case 1: | |
| 132 | finalcvg = (m_misc_state->m_curpixel_cvg + m_misc_state->m_curpixel_memcvg) & 7; | |
| 133 | finalcolor |= (finalcvg << 5); | |
| 134 | RWRITEIDX32(fb, finalcolor); | |
| 135 | break; | |
| 136 | case 2: | |
| 137 | RWRITEIDX32(fb, finalcolor | 0xE0); | |
| 138 | break; | |
| 139 | case 3: | |
| 140 | finalcolor |= (m_misc_state->m_curpixel_memcvg << 5); | |
| 141 | RWRITEIDX32(fb, finalcolor); | |
| 142 | break; | |
| 143 | } | |
| 144 | } | |
| 91 | 145 | |
| 92 | case 1: | |
| 93 | *fb = finalcolor | ((newcvg >> 2) & 1); | |
| 94 | *hb = (newcvg & 3); | |
| 146 | void Framebuffer::Read(UINT32 curpixel) | |
| 147 | { | |
| 148 | switch(m_misc_state->m_fb_size) | |
| 149 | { | |
| 150 | case PIXEL_SIZE_16BIT: | |
| 151 | Read16Bit(curpixel); | |
| 95 | 152 | break; |
| 96 | 153 | |
| 97 | case 2: | |
| 98 | *fb = finalcolor | 1; | |
| 99 | *hb = 3; | |
| 154 | case PIXEL_SIZE_32BIT: | |
| 155 | Read32Bit(curpixel); | |
| 100 | 156 | break; |
| 101 | 157 | |
| 102 | case 3: | |
| 103 | *fb = finalcolor | ((memory_cvg >> 2) & 1); | |
| 104 | *hb = (memory_cvg & 3); | |
| 158 | default: | |
| 159 | fatalerror("Unsupported bit depth: %d\n", m_misc_state->m_fb_size); | |
| 105 | 160 | break; |
| 106 | 161 | } |
| 162 | } | |
| 107 | 163 | |
| 108 | return true; | |
| 164 | void Framebuffer::Read16Bit(UINT32 curpixel) | |
| 165 | { | |
| 166 | UINT16 fword = RREADIDX16((m_misc_state->m_fb_address >> 1) + curpixel); | |
| 167 | UINT8 hbyte = HREADADDR8((m_misc_state->m_fb_address >> 1) + curpixel); | |
| 168 | m_rdp->GetMemoryColor()->i.r = GETHICOL(fword); | |
| 169 | m_rdp->GetMemoryColor()->i.g = GETMEDCOL(fword); | |
| 170 | m_rdp->GetMemoryColor()->i.b = GETLOWCOL(fword); | |
| 171 | if (m_other_modes->image_read_en) | |
| 172 | { | |
| 173 | m_misc_state->m_curpixel_memcvg = ((fword & 1) << 2) | (hbyte & 3); | |
| 174 | m_rdp->GetMemoryColor()->i.a = m_misc_state->m_curpixel_memcvg << 5; | |
| 175 | } | |
| 176 | else | |
| 177 | { | |
| 178 | m_misc_state->m_curpixel_memcvg = 7; | |
| 179 | m_rdp->GetMemoryColor()->i.a = 0xff; | |
| 180 | } | |
| 109 | 181 | } |
| 110 | 182 | |
| 111 | ||
| 183 | void | |
| 112 | 184 | { |
| 113 | UINT32 finalcolor = (r << 24) | (g << 16) | (b << 8); | |
| 114 | UINT32 memory_alphachannel = *fb & 0xff; | |
| 115 | ||
| 116 | UINT32 memory_cvg = 8; | |
| 185 | UINT32 mem = RREADIDX32((m_misc_state->m_fb_address >> 2) + curpixel); | |
| 186 | m_rdp->GetMemoryColor()->i.r = (mem >> 24) & 0xff; | |
| 187 | m_rdp->GetMemoryColor()->i.g = (mem >> 16) & 0xff; | |
| 188 | m_rdp->GetMemoryColor()->i.b = (mem >> 8) & 0xff; | |
| 117 | 189 | if (m_other_modes->image_read_en) |
| 118 | 190 | { |
| 119 | memory_cvg = ((*fb >>5) & 7) + 1; | |
| 191 | m_misc_state->m_curpixel_memcvg = (mem >> 5) & 7; | |
| 192 | m_rdp->GetMemoryColor()->i.a = (mem) & 0xff; | |
| 120 | 193 | } |
| 194 | else | |
| 195 | { | |
| 196 | m_misc_state->m_curpixel_memcvg = 7; | |
| 197 | m_rdp->GetMemoryColor()->i.a = 0xff; | |
| 198 | } | |
| 199 | } | |
| 121 | 200 | |
| 122 | UINT32 newcvg = m_misc_state->m_curpixel_cvg + memory_cvg; | |
| 123 | bool wrapped = (newcvg > 8); | |
| 124 | UINT32 clamped_cvg = wrapped ? 8 : newcvg; | |
| 125 | newcvg = (wrapped) ? (newcvg - 8) : newcvg; | |
| 201 | void Framebuffer::Copy(UINT32 curpixel, UINT32 r, UINT32 g, UINT32 b) | |
| 202 | { | |
| 203 | switch(m_misc_state->m_fb_size) | |
| 204 | { | |
| 205 | case PIXEL_SIZE_16BIT: | |
| 206 | Copy16Bit(curpixel, r, g, b); | |
| 207 | break; | |
| 126 | 208 | |
| 127 | m_misc_state->m_curpixel_cvg--; | |
| 128 | newcvg--; | |
| 129 | memory_cvg--; | |
| 130 | clamped_cvg--; | |
| 209 | case PIXEL_SIZE_32BIT: | |
| 210 | Copy32Bit(curpixel, r, g, b); | |
| 211 | break; | |
| 131 | 212 | |
| 132 | if (m_other_modes->color_on_cvg && !wrapped) | |
| 133 | { | |
| 134 | *fb &= 0xffffff00; | |
| 135 | *fb |= ((newcvg << 5) & 0xff); | |
| 136 | return 0; | |
| 213 | default: | |
| 214 | fatalerror("Unsupported bit depth: %d\n", m_misc_state->m_fb_size); | |
| 215 | break; | |
| 137 | 216 | } |
| 217 | } | |
| 138 | 218 | |
| 139 | switch(m_other_modes->cvg_dest) | |
| 219 | void Framebuffer::Copy16Bit(UINT32 curpixel, UINT32 r, UINT32 g, UINT32 b) | |
| 220 | { | |
| 221 | UINT16 val = ((r >> 3) << 11) | ((g >> 3) << 6) | ((b >> 3) << 1) | ((m_misc_state->m_curpixel_cvg >> 2) & 1); | |
| 222 | RWRITEIDX16((m_misc_state->m_fb_address >> 1) + curpixel, val); | |
| 223 | HWRITEADDR8((m_misc_state->m_fb_address >> 1) + curpixel, m_misc_state->m_curpixel_cvg & 3); | |
| 224 | } | |
| 225 | ||
| 226 | void Framebuffer::Copy32Bit(UINT32 curpixel, UINT32 r, UINT32 g, UINT32 b) | |
| 227 | { | |
| 228 | UINT32 val = (r << 24) | (g << 16) | (b << 8) | (m_misc_state->m_curpixel_cvg << 5); | |
| 229 | RWRITEIDX32((m_misc_state->m_fb_address >> 2) + curpixel, val); | |
| 230 | } | |
| 231 | ||
| 232 | void Framebuffer::Fill(UINT32 curpixel) | |
| 233 | { | |
| 234 | switch(m_misc_state->m_fb_size) | |
| 140 | 235 | { |
| 141 | case 0: | |
| 142 | if (!m_other_modes->force_blend && !m_misc_state->m_curpixel_overlap) | |
| 143 | { | |
| 144 | *fb = finalcolor|(m_misc_state->m_curpixel_cvg << 5); | |
| 145 | } | |
| 146 | else | |
| 147 | { | |
| 148 | *fb = finalcolor|(clamped_cvg << 5); | |
| 149 | } | |
| 236 | case PIXEL_SIZE_16BIT: | |
| 237 | Fill16Bit(curpixel); | |
| 150 | 238 | break; |
| 151 | case 1: | |
| 152 | *fb = finalcolor | (newcvg << 5); | |
| 239 | ||
| 240 | case PIXEL_SIZE_32BIT: | |
| 241 | Fill32Bit(curpixel); | |
| 153 | 242 | break; |
| 154 | case 2: | |
| 155 | *fb = finalcolor | 0xE0; | |
| 243 | ||
| 244 | default: | |
| 245 | fatalerror("Unsupported bit depth: %d\n", m_misc_state->m_fb_size); | |
| 156 | 246 | break; |
| 157 | case 3: | |
| 158 | *fb = finalcolor | memory_alphachannel; | |
| 159 | break; | |
| 160 | 247 | } |
| 248 | } | |
| 161 | 249 | |
| 162 | return true; | |
| 250 | void Framebuffer::Fill16Bit(UINT32 curpixel) | |
| 251 | { | |
| 252 | UINT16 val; | |
| 253 | if (curpixel & 1) | |
| 254 | { | |
| 255 | val = m_rdp->GetFillColor32() & 0xffff; | |
| 256 | } | |
| 257 | else | |
| 258 | { | |
| 259 | val = (m_rdp->GetFillColor32() >> 16) & 0xffff; | |
| 260 | } | |
| 261 | RWRITEIDX16((m_misc_state->m_fb_address >> 1) + curpixel, val); | |
| 262 | HWRITEADDR8((m_misc_state->m_fb_address >> 1) + curpixel, ((val & 1) << 1) | (val & 1)); | |
| 163 | 263 | } |
| 164 | 264 | |
| 265 | void Framebuffer::Fill32Bit(UINT32 curpixel) | |
| 266 | { | |
| 267 | UINT32 fill_color = m_rdp->GetFillColor32(); | |
| 268 | RWRITEIDX32((m_misc_state->m_fb_address >> 2) + curpixel, fill_color); | |
| 269 | HWRITEADDR8((m_misc_state->m_fb_address >> 1) + (curpixel << 1), (fill_color & 0x10000) ? 3 : 0); | |
| 270 | HWRITEADDR8((m_misc_state->m_fb_address >> 1) + (curpixel << 1) + 1, (fill_color & 0x1) ? 3 : 0); | |
| 271 | } | |
| 272 | ||
| 273 | } // namespace RDP | |
| 274 | ||
| 165 | 275 | } // namespace N64 |
| r9854 | r9855 | |
|---|---|---|
| 15 | 15 | class Framebuffer |
| 16 | 16 | { |
| 17 | 17 | public: |
| 18 | Framebuffer() { } | |
| 18 | Framebuffer() | |
| 19 | { | |
| 20 | m_pre_wrap = false; | |
| 21 | } | |
| 19 | 22 | |
| 20 | bool Write(void* fb, UINT8* hb, UINT32 r, UINT32 g, UINT32 b); | |
| 23 | void Write(UINT32 curpixel, UINT32 r, UINT32 g, UINT32 b); | |
| 24 | void Read(UINT32 index); | |
| 25 | void Copy(UINT32 curpixel, UINT32 r, UINT32 g, UINT32 b); | |
| 26 | void Fill(UINT32 curpixel); | |
| 21 | 27 | |
| 28 | void SetProcessor(Processor* rdp) { m_rdp = rdp; } | |
| 22 | 29 | void SetOtherModes(OtherModes* other_modes) { m_other_modes = other_modes; } |
| 23 | 30 | void SetMiscState(MiscState* misc_state) { m_misc_state = misc_state; } |
| 31 | void SetPreWrap(bool prewrap) { m_pre_wrap = prewrap; } | |
| 24 | 32 | |
| 25 | 33 | private: |
| 34 | Processor* m_rdp; | |
| 26 | 35 | OtherModes* m_other_modes; |
| 27 | 36 | MiscState* m_misc_state; |
| 37 | bool m_pre_wrap; | |
| 28 | 38 | |
| 29 | bool Write16Bit(UINT16* fb, UINT8* hb, UINT32 r, UINT32 g, UINT32 b); | |
| 30 | bool Write32Bit(UINT32* fb, UINT32 r, UINT32 g, UINT32 b); | |
| 39 | void Write16Bit(UINT32 curpixel, UINT32 r, UINT32 g, UINT32 b); | |
| 40 | void Write32Bit(UINT32 curpixel, UINT32 r, UINT32 g, UINT32 b); | |
| 41 | void Read16Bit(UINT32 curpixel); | |
| 42 | void Read32Bit(UINT32 curpixel); | |
| 43 | void Copy16Bit(UINT32 curpixel, UINT32 r, UINT32 g, UINT32 b); | |
| 44 | void Copy32Bit(UINT32 curpixel, UINT32 r, UINT32 g, UINT32 b); | |
| 45 | void Fill16Bit(UINT32 curpixel); | |
| 46 | void Fill32Bit(UINT32 curpixel); | |
| 31 | 47 | }; |
| 32 | 48 | |
| 33 | 49 | } // namespace RDP |
| r9854 | r9855 | |
|---|---|---|
| 27 | 27 | #include "includes/n64.h" |
| 28 | 28 | #include "video/n64.h" |
| 29 | 29 | |
| 30 | #define LOG_RDP_EXECUTION | |
| 30 | #define LOG_RDP_EXECUTION 1 | |
| 31 | 31 | |
| 32 | 32 | static FILE *rdp_exec; |
| 33 | 33 | |
| 34 | 34 | /*****************************************************************************/ |
| 35 | 35 | |
| 36 | #define LookUpCC(A, B, C, D) state->m_rdp.GetCCLUT2()[(state->m_rdp.GetCCLUT1()[(A << 16) | (B << 8) | C] << 8) | D] | |
| 37 | ||
| 38 | 36 | // The functions in this file should be moved into the parent Processor class. |
| 39 | 37 | #include "rdpfiltr.c" |
| 40 | 38 | |
| r9854 | r9855 | |
| 46 | 44 | |
| 47 | 45 | void Processor::GetAlphaCvg(UINT8 *comb_alpha) |
| 48 | 46 | { |
| 49 | if(m_other_modes.cvg_times_alpha) | |
| 47 | INT32 temp = *comb_alpha; | |
| 48 | INT32 temp2 = m_misc_state.m_curpixel_cvg; | |
| 49 | INT32 temp3 = 0; | |
| 50 | ||
| 51 | if (m_other_modes.cvg_times_alpha) | |
| 50 | 52 | { |
| 51 | if(m_other_modes.alpha_cvg_select) | |
| 52 | { | |
| 53 | UINT32 temp = *comb_alpha; | |
| 54 | UINT32 temp2 = m_misc_state.m_curpixel_cvg; | |
| 55 | ||
| 56 | UINT32 temp3 = (temp * temp2) + 4; | |
| 57 | m_misc_state.m_curpixel_cvg = temp3 >> 8; | |
| 58 | ||
| 59 | temp = (temp3 >> 3); | |
| 60 | ||
| 61 | if (temp > 0xff) | |
| 62 | { | |
| 63 | *comb_alpha = 0xff; | |
| 64 | } | |
| 65 | else | |
| 66 | { | |
| 67 | *comb_alpha = (UINT8)temp; | |
| 68 | } | |
| 69 | } | |
| 70 | else | |
| 71 | { | |
| 72 | UINT32 temp = *comb_alpha; | |
| 73 | UINT32 temp2 = m_misc_state.m_curpixel_cvg; | |
| 74 | UINT32 temp3 = (temp * temp2) + 4; | |
| 75 | ||
| 76 | m_misc_state.m_curpixel_cvg = temp3 >> 8; | |
| 77 | ||
| 78 | if (temp > 0xff) | |
| 79 | { | |
| 80 | *comb_alpha = 0xff; | |
| 81 | } | |
| 82 | else | |
| 83 | { | |
| 84 | *comb_alpha = (UINT8)temp; | |
| 85 | } | |
| 86 | } | |
| 53 | temp3 = (temp * temp2) + 4; | |
| 54 | m_misc_state.m_curpixel_cvg = (temp3 >> 8) & 0xf; | |
| 87 | 55 | } |
| 88 | else | |
| 56 | if (m_other_modes.alpha_cvg_select) | |
| 89 | 57 | { |
| 90 | if(m_other_modes.alpha_cvg_select) | |
| 91 | { | |
| 92 | UINT32 temp2 = m_misc_state.m_curpixel_cvg; | |
| 93 | UINT32 temp = temp2 << 5; | |
| 94 | ||
| 95 | if (temp > 0xff) | |
| 96 | { | |
| 97 | *comb_alpha = 0xff; | |
| 98 | } | |
| 99 | else | |
| 100 | { | |
| 101 | *comb_alpha = (UINT8)temp; | |
| 102 | } | |
| 103 | } | |
| 58 | temp = (m_other_modes.cvg_times_alpha) ? (temp3 >> 3) : (temp2 << 5); | |
| 104 | 59 | } |
| 60 | if (temp > 0xff) | |
| 61 | { | |
| 62 | temp = 0xff; | |
| 63 | } | |
| 64 | *comb_alpha = temp; | |
| 105 | 65 | } |
| 106 | 66 | |
| 107 | 67 | /*****************************************************************************/ |
| r9854 | r9855 | |
| 119 | 79 | break; |
| 120 | 80 | |
| 121 | 81 | default: |
| 122 | fatalerror("Unsupported framebuffer depth: m_fb_size=%d\n", m_misc_state.m_fb_size); | |
| 82 | //fatalerror("Unsupported framebuffer depth: m_fb_size=%d\n", m_misc_state.m_fb_size); | |
| 123 | 83 | break; |
| 124 | 84 | } |
| 125 | 85 | } |
| r9854 | r9855 | |
| 182 | 142 | next_cvg = ((frame_buffer[(pixels + 1)^WORD_ADDR_XOR] & 1) << 2) | (hidden_buffer[(pixels + 1)^BYTE_ADDR_XOR] & 3); |
| 183 | 143 | } |
| 184 | 144 | } |
| 185 | c.c = LookUp16To32(pix); | |
| 186 | //r = ((pix >> 8) & 0xf8) | (pix >> 13); | |
| 187 | //g = ((pix >> 3) & 0xf8) | ((pix >> 8) & 0x07); | |
| 188 | //b = ((pix << 2) & 0xf8) | ((pix >> 3) & 0x07); | |
| 145 | c.i.r = ((pix >> 8) & 0xf8) | (pix >> 13); | |
| 146 | c.i.g = ((pix >> 3) & 0xf8) | ((pix >> 8) & 0x07); | |
| 147 | c.i.b = ((pix << 2) & 0xf8) | ((pix >> 3) & 0x07); | |
| 189 | 148 | |
| 190 | 149 | if(fsaa) |
| 191 | 150 | { |
| r9854 | r9855 | |
| 342 | 301 | |
| 343 | 302 | /*****************************************************************************/ |
| 344 | 303 | |
| 304 | void Processor::TCDivNoPersp(INT32 ss, INT32 st, INT32 sw, INT32* sss, INT32* sst) | |
| 305 | { | |
| 306 | *sss = (SIGN16(ss)) & 0x1ffff; | |
| 307 | *sst = (SIGN16(st)) & 0x1ffff; | |
| 308 | } | |
| 309 | ||
| 345 | 310 | void Processor::TCDiv(INT32 ss, INT32 st, INT32 sw, INT32* sss, INT32* sst) |
| 346 | 311 | { |
| 347 | int shift; | |
| 312 | int w_carry = 0; | |
| 313 | if ((sw & 0x8000) || !(sw & 0x7fff)) | |
| 314 | { | |
| 315 | w_carry = 1; | |
| 316 | } | |
| 348 | 317 | |
| 349 | 318 | sw &= 0x7fff; |
| 350 | for(shift = 1; shift <= 14 && !((sw << shift) & 0x8000); shift++); | |
| 319 | ||
| 320 | int shift; | |
| 321 | for (shift = 1; shift <= 14 && !((sw << shift) & 0x8000); shift++); | |
| 351 | 322 | shift -= 1; |
| 352 | 323 | |
| 353 | int normout = ((sw << shift) & 0x3fff) >> 8; | |
| 354 | int wnorm = ((sw << shift) & 0xff) << 2; | |
| 324 | int normout = (sw << shift) & 0x3fff; | |
| 325 | int wnorm = (normout & 0xff) << 2; | |
| 326 | normout >>= 8; | |
| 355 | 327 | |
| 356 | int tlu_rcp = ((-(m_norm_slope_rom[normout] * wnorm)) >> 10) + m_norm_point_rom[normout]; | |
| 328 | int temppoint = m_norm_point_rom[normout]; | |
| 329 | int tempslope = m_norm_slope_rom[normout]; | |
| 357 | 330 | |
| 358 | if(shift == 14) | |
| 331 | int tlu_rcp = ((-(tempslope * wnorm)) >> 10) + temppoint; | |
| 332 | ||
| 333 | int sprod = SIGN16(ss) * tlu_rcp; | |
| 334 | int tprod = SIGN16(st) * tlu_rcp; | |
| 335 | int tempmask = ((1 << (shift + 1)) - 1) << (29 - shift);//tc.c,658 | |
| 336 | int shift_value = 13 - shift;//tc.c,653 | |
| 337 | ||
| 338 | int outofbounds_s = sprod & tempmask;//tc.c, 661 | |
| 339 | int outofbounds_t = tprod & tempmask; | |
| 340 | if (shift == 0xe)//tc.c, 664 | |
| 359 | 341 | { |
| 360 | *sss = (SIGN16(ss) * tlu_rcp) << 1; | |
| 361 | *sst = (SIGN16(st) * tlu_rcp) << 1; | |
| 342 | *sss = sprod << 1;//sw, tw çäåñü íå èçìåíèëèñü | |
| 343 | *sst = tprod << 1; | |
| 362 | 344 | } |
| 363 | 345 | else |
| 364 | 346 | { |
| 365 | int shift_value = 13 - shift; | |
| 366 | *sss = (SIGN16(ss) * tlu_rcp) >> shift_value; | |
| 367 | *sst = (SIGN16(st) * tlu_rcp) >> shift_value; | |
| 347 | *sss = sprod = (sprod >> shift_value); | |
| 348 | *sst = tprod = (tprod >> shift_value); | |
| 368 | 349 | } |
| 350 | //compute clamp flags | |
| 351 | int under_s = 0; | |
| 352 | int under_t = 0; | |
| 353 | int over_s = 0; | |
| 354 | int over_t = 0; | |
| 355 | ||
| 356 | if (outofbounds_s != tempmask && outofbounds_s != 0) | |
| 357 | { | |
| 358 | if (sprod & (1 << 29)) | |
| 359 | { | |
| 360 | under_s = 1; | |
| 361 | } | |
| 362 | else | |
| 363 | { | |
| 364 | over_s = 1; | |
| 365 | } | |
| 366 | } | |
| 367 | ||
| 368 | if (outofbounds_t != tempmask && outofbounds_t != 0) | |
| 369 | { | |
| 370 | if (tprod & (1 << 29)) | |
| 371 | { | |
| 372 | under_t = 1; | |
| 373 | } | |
| 374 | else | |
| 375 | { | |
| 376 | over_t = 1; | |
| 377 | } | |
| 378 | } | |
| 379 | ||
| 380 | over_s |= w_carry; | |
| 381 | over_t |= w_carry; | |
| 382 | ||
| 383 | *sss = (*sss & 0x1ffff) | (over_s << 18) | (under_s << 17); | |
| 384 | *sst = (*sst & 0x1ffff) | (over_s << 18) | (under_s << 17); | |
| 369 | 385 | } |
| 370 | 386 | |
| 387 | INT32 Processor::ColorCombinerEquation(INT32 a, INT32 b, INT32 c, INT32 d) | |
| 388 | { | |
| 389 | a = KURT_AKELEY_SIGN9(a); | |
| 390 | b = KURT_AKELEY_SIGN9(b); | |
| 391 | c = SIGN9(c); | |
| 392 | d = KURT_AKELEY_SIGN9(d); | |
| 393 | a = (((a - b) * c) + (d << 8) + 0x80); | |
| 394 | a = SIGN17(a) >> 8; | |
| 395 | a = m_special_9bit_clamptable[a & 0x1ff]; | |
| 396 | return a; | |
| 397 | } | |
| 398 | ||
| 399 | INT32 Processor::AlphaCombinerEquation(INT32 a, INT32 b, INT32 c, INT32 d) | |
| 400 | { | |
| 401 | a = KURT_AKELEY_SIGN9(a); | |
| 402 | b = KURT_AKELEY_SIGN9(b); | |
| 403 | c = SIGN9(c); | |
| 404 | d = KURT_AKELEY_SIGN9(d); | |
| 405 | a = (((a - b) * c) + (d << 8) + 0x80) >> 8; | |
| 406 | a = SIGN9(a); | |
| 407 | a = m_special_9bit_clamptable[a & 0x1ff]; | |
| 408 | return a; | |
| 409 | } | |
| 410 | ||
| 411 | void Processor::ColorCombiner1Cycle(bool noisecompute) | |
| 412 | { | |
| 413 | if (noisecompute) | |
| 414 | { | |
| 415 | m_noise_color.i.r = m_noise_color.i.g = m_noise_color.i.b = mame_rand(m_machine) & 0xff; // Not accurate... | |
| 416 | } | |
| 417 | ||
| 418 | m_pixel_color.i.r = ColorCombinerEquation(*m_color_inputs.combiner_rgbsub_a_r[1],*m_color_inputs.combiner_rgbsub_b_r[1],*m_color_inputs.combiner_rgbmul_r[1],*m_color_inputs.combiner_rgbadd_r[1]); | |
| 419 | m_pixel_color.i.g = ColorCombinerEquation(*m_color_inputs.combiner_rgbsub_a_g[1],*m_color_inputs.combiner_rgbsub_b_g[1],*m_color_inputs.combiner_rgbmul_g[1],*m_color_inputs.combiner_rgbadd_g[1]); | |
| 420 | m_pixel_color.i.b = ColorCombinerEquation(*m_color_inputs.combiner_rgbsub_a_b[1],*m_color_inputs.combiner_rgbsub_b_b[1],*m_color_inputs.combiner_rgbmul_b[1],*m_color_inputs.combiner_rgbadd_b[1]); | |
| 421 | m_pixel_color.i.a = AlphaCombinerEquation(*m_color_inputs.combiner_alphasub_a[1],*m_color_inputs.combiner_alphasub_b[1],*m_color_inputs.combiner_alphamul[1],*m_color_inputs.combiner_alphaadd[1]); | |
| 422 | ||
| 423 | //Alpha coverage combiner | |
| 424 | GetAlphaCvg(&m_pixel_color.i.a); | |
| 425 | } | |
| 426 | ||
| 427 | void Processor::ColorCombiner2Cycle(bool noisecompute) | |
| 428 | { | |
| 429 | if (noisecompute) | |
| 430 | { | |
| 431 | m_noise_color.i.r = m_noise_color.i.g = m_noise_color.i.b = mame_rand(m_machine) & 0xff; // HACK | |
| 432 | } | |
| 433 | ||
| 434 | m_combined_color.i.r = ColorCombinerEquation(*m_color_inputs.combiner_rgbsub_a_r[0],*m_color_inputs.combiner_rgbsub_b_r[0],*m_color_inputs.combiner_rgbmul_r[0],*m_color_inputs.combiner_rgbadd_r[0]); | |
| 435 | m_combined_color.i.g = ColorCombinerEquation(*m_color_inputs.combiner_rgbsub_a_g[0],*m_color_inputs.combiner_rgbsub_b_g[0],*m_color_inputs.combiner_rgbmul_g[0],*m_color_inputs.combiner_rgbadd_g[0]); | |
| 436 | m_combined_color.i.b = ColorCombinerEquation(*m_color_inputs.combiner_rgbsub_a_b[0],*m_color_inputs.combiner_rgbsub_b_b[0],*m_color_inputs.combiner_rgbmul_b[0],*m_color_inputs.combiner_rgbadd_b[0]); | |
| 437 | m_combined_color.i.a = AlphaCombinerEquation(*m_color_inputs.combiner_alphasub_a[0],*m_color_inputs.combiner_alphasub_b[0],*m_color_inputs.combiner_alphamul[0],*m_color_inputs.combiner_alphaadd[0]); | |
| 438 | ||
| 439 | m_texel0_color = m_texel1_color; | |
| 440 | m_texel1_color = m_next_texel_color; | |
| 441 | ||
| 442 | m_pixel_color.i.r = ColorCombinerEquation(*m_color_inputs.combiner_rgbsub_a_r[1],*m_color_inputs.combiner_rgbsub_b_r[1],*m_color_inputs.combiner_rgbmul_r[1],*m_color_inputs.combiner_rgbadd_r[1]); | |
| 443 | m_pixel_color.i.g = ColorCombinerEquation(*m_color_inputs.combiner_rgbsub_a_g[1],*m_color_inputs.combiner_rgbsub_b_g[1],*m_color_inputs.combiner_rgbmul_g[1],*m_color_inputs.combiner_rgbadd_g[1]); | |
| 444 | m_pixel_color.i.b = ColorCombinerEquation(*m_color_inputs.combiner_rgbsub_a_b[1],*m_color_inputs.combiner_rgbsub_b_b[1],*m_color_inputs.combiner_rgbmul_b[1],*m_color_inputs.combiner_rgbadd_b[1]); | |
| 445 | m_pixel_color.i.a = AlphaCombinerEquation(*m_color_inputs.combiner_alphasub_a[1],*m_color_inputs.combiner_alphasub_b[1],*m_color_inputs.combiner_alphamul[1],*m_color_inputs.combiner_alphaadd[1]); | |
| 446 | ||
| 447 | GetAlphaCvg(&m_pixel_color.i.a); | |
| 448 | } | |
| 449 | ||
| 371 | 450 | void Processor::SetSubAInputRGB(UINT8 **input_r, UINT8 **input_g, UINT8 **input_b, int code) |
| 372 | 451 | { |
| 373 | 452 | switch (code & 0xf) |
| r9854 | r9855 | |
| 468 | 547 | { |
| 469 | 548 | switch (code & 0x7) |
| 470 | 549 | { |
| 471 | case 0: *input = &m_lod_frac; break; | |
| 550 | case 0: *input = &m_lod_frac; break; | |
| 472 | 551 | case 1: *input = &m_texel0_color.i.a; break; |
| 473 | 552 | case 2: *input = &m_texel1_color.i.a; break; |
| 474 | 553 | case 3: *input = &m_prim_color.i.a; break; |
| 475 | 554 | case 4: *input = &m_shade_color.i.a; break; |
| 476 | 555 | case 5: *input = &m_env_color.i.a; break; |
| 477 | case 6: *input = &m_prim_lod_frac; break; | |
| 556 | case 6: *input = &m_prim_lod_frac; break; | |
| 478 | 557 | case 7: *input = &m_zero_color.i.a; break; |
| 479 | 558 | } |
| 480 | 559 | } |
| r9854 | r9855 | |
| 563 | 642 | 7, 1, 6, 0 |
| 564 | 643 | }; |
| 565 | 644 | |
| 566 | const Processor::ZDecompressEntry Processor:: | |
| 645 | const Processor::ZDecompressEntry Processor:: | |
| 567 | 646 | { |
| 568 | 647 | { 6, 0x00000 }, |
| 569 | 648 | { 5, 0x20000 }, |
| r9854 | r9855 | |
| 577 | 656 | |
| 578 | 657 | /*****************************************************************************/ |
| 579 | 658 | |
| 580 | void Processor:: | |
| 659 | void Processor::z_build_com_t | |
| 581 | 660 | { |
| 582 | for(int j = 0; j < 0x40000; j++) | |
| 661 | UINT16 altmem = 0; | |
| 662 | for(int z = 0; z < 0x40000; z++) | |
| 583 | 663 | { |
| 584 | UINT32 exponent = 0; | |
| 585 | UINT32 testbit = 0x20000; | |
| 586 | UINT32 mantissa = 0; | |
| 587 | while( (j & testbit) && (exponent < 7) ) | |
| 588 | { | |
| 589 | exponent++; | |
| 590 | testbit = 1 << (17 - exponent); | |
| 591 | } | |
| 664 | switch((z >> 11) & 0x7f) | |
| 665 | { | |
| 666 | case 0x00: | |
| 667 | case 0x01: | |
| 668 | case 0x02: | |
| 669 | case 0x03: | |
| 670 | case 0x04: | |
| 671 | case 0x05: | |
| 672 | case 0x06: | |
| 673 | case 0x07: | |
| 674 | case 0x08: | |
| 675 | case 0x09: | |
| 676 | case 0x0a: | |
| 677 | case 0x0b: | |
| 678 | case 0x0c: | |
| 679 | case 0x0d: | |
| 680 | case 0x0e: | |
| 681 | case 0x0f: | |
| 682 | case 0x10: | |
| 683 | case 0x11: | |
| 684 | case 0x12: | |
| 685 | case 0x13: | |
| 686 | case 0x14: | |
| 687 | case 0x15: | |
| 688 | case 0x16: | |
| 689 | case 0x17: | |
| 690 | case 0x18: | |
| 691 | case 0x19: | |
| 692 | case 0x1a: | |
| 693 | case 0x1b: | |
| 694 | case 0x1c: | |
| 695 | case 0x1d: | |
| 696 | case 0x1e: | |
| 697 | case 0x1f: | |
| 698 | case 0x20: | |
| 699 | case 0x21: | |
| 700 | case 0x22: | |
| 701 | case 0x23: | |
| 702 | case 0x24: | |
| 703 | case 0x25: | |
| 704 | case 0x26: | |
| 705 | case 0x27: | |
| 706 | case 0x28: | |
| 707 | case 0x29: | |
| 708 | case 0x2a: | |
| 709 | case 0x2b: | |
| 710 | case 0x2c: | |
| 711 | case 0x2d: | |
| 712 | case 0x2e: | |
| 713 | case 0x2f: | |
| 714 | case 0x30: | |
| 715 | case 0x31: | |
| 716 | case 0x32: | |
| 717 | case 0x33: | |
| 718 | case 0x34: | |
| 719 | case 0x35: | |
| 720 | case 0x36: | |
| 721 | case 0x37: | |
| 722 | case 0x38: | |
| 723 | case 0x39: | |
| 724 | case 0x3a: | |
| 725 | case 0x3b: | |
| 726 | case 0x3c: | |
| 727 | case 0x3d: | |
| 728 | case 0x3e: | |
| 729 | case 0x3f: | |
| 730 | altmem = (z >> 4) & 0x1ffc; | |
| 731 | break; | |
| 732 | case 0x40: | |
| 733 | case 0x41: | |
| 734 | case 0x42: | |
| 735 | case 0x43: | |
| 736 | case 0x44: | |
| 737 | case 0x45: | |
| 738 | case 0x46: | |
| 739 | case 0x47: | |
| 740 | case 0x48: | |
| 741 | case 0x49: | |
| 742 | case 0x4a: | |
| 743 | case 0x4b: | |
| 744 | case 0x4c: | |
| 745 | case 0x4d: | |
| 746 | case 0x4e: | |
| 747 | case 0x4f: | |
| 748 | case 0x50: | |
| 749 | case 0x51: | |
| 750 | case 0x52: | |
| 751 | case 0x53: | |
| 752 | case 0x54: | |
| 753 | case 0x55: | |
| 754 | case 0x56: | |
| 755 | case 0x57: | |
| 756 | case 0x58: | |
| 757 | case 0x59: | |
| 758 | case 0x5a: | |
| 759 | case 0x5b: | |
| 760 | case 0x5c: | |
| 761 | case 0x5d: | |
| 762 | case 0x5e: | |
| 763 | case 0x5f: | |
| 764 | altmem = ((z >> 3) & 0x1ffc) | 0x2000; | |
| 765 | break; | |
| 766 | case 0x60: | |
| 767 | case 0x61: | |
| 768 | case 0x62: | |
| 769 | case 0x63: | |
| 770 | case 0x64: | |
| 771 | case 0x65: | |
| 772 | case 0x66: | |
| 773 | case 0x67: | |
| 774 | case 0x68: | |
| 775 | case 0x69: | |
| 776 | case 0x6a: | |
| 777 | case 0x6b: | |
| 778 | case 0x6c: | |
| 779 | case 0x6d: | |
| 780 | case 0x6e: | |
| 781 | case 0x6f: | |
| 782 | altmem = ((z >> 2) & 0x1ffc) | 0x4000; | |
| 783 | break; | |
| 784 | case 0x70: | |
| 785 | case 0x71: | |
| 786 | case 0x72: | |
| 787 | case 0x73: | |
| 788 | case 0x74: | |
| 789 | case 0x75: | |
| 790 | case 0x76: | |
| 791 | case 0x77: | |
| 792 | altmem = ((z >> 1) & 0x1ffc) | 0x6000; | |
| 793 | break; | |
| 794 | case 0x78://uncompressed z = 0x3c000 | |
| 795 | case 0x79: | |
| 796 | case 0x7a: | |
| 797 | case 0x7b: | |
| 798 | altmem = (z & 0x1ffc) | 0x8000; | |
| 799 | break; | |
| 800 | case 0x7c://uncompressed z = 0x3e000 | |
| 801 | case 0x7d: | |
| 802 | altmem = ((z << 1) & 0x1ffc) | 0xa000; | |
| 803 | break; | |
| 804 | case 0x7e://uncompressed z = 0x3f000 | |
| 805 | altmem = ((z << 2) & 0x1ffc) | 0xc000; | |
| 806 | break; | |
| 807 | case 0x7f://uncompressed z = 0x3f000 | |
| 808 | altmem = ((z << 2) & 0x1ffc) | 0xe000; | |
| 809 | break; | |
| 810 | } | |
| 592 | 811 | |
| 593 | mantissa = (j >> (6 - (6 < exponent ? 6 : exponent))) & 0x7ff; | |
| 594 | m_z_compress_table[j] = (UINT16)(((exponent << 11) | mantissa) << 2); | |
| 595 | } | |
| 812 | z_com_table[z] = altmem; | |
| 813 | ||
| 814 | } | |
| 596 | 815 | } |
| 597 | 816 | |
| 598 | void Processor:: | |
| 817 | void Processor::p | |
| 599 | 818 | { |
| 600 | UINT8 deltazmem = 15; | |
| 601 | z &= 0x3ffff; | |
| 602 | deltaz &= 0xffff; | |
| 603 | for(int j = 15; j >= 0; j--) | |
| 819 | const UINT8 yarray[16] = {0, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0}; | |
| 820 | const UINT8 xarray[16] = {0, 3, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0}; | |
| 821 | ||
| 822 | for (int i = 0; i < 0x10000; i++) | |
| 604 | 823 | { |
| 605 | if( (deltaz >> j) == 1 ) | |
| 824 | compressed_cvmasks[i] = (i & 1) | ((i & 4) >> 1) | ((i & 0x20) >> 3) | ((i & 0x80) >> 4) | | |
| 825 | ((i & 0x100) >> 4) | ((i & 0x400) >> 5) | ((i & 0x2000) >> 7) | ((i & 0x8000) >> 8); | |
| 826 | } | |
| 827 | ||
| 828 | for (int i = 0; i < 0x100; i++) | |
| 829 | { | |
| 830 | UINT16 mask = decompress_cvmask_frombyte(i); | |
| 831 | cvarray[i].cvg = cvarray[i].cvbit = 0; | |
| 832 | cvarray[i].cvbit = (i >> 7) & 1; | |
| 833 | for (int k = 0; k < 8; k++) | |
| 606 | 834 | { |
| 607 | | |
| 835 | cvarray[i].cvg += ((i >> k) & 1); | |
| 608 | 836 | } |
| 609 | else | |
| 837 | ||
| 838 | UINT16 masky = 0; | |
| 839 | for (int k = 0; k < 4; k++) | |
| 610 | 840 | { |
| 611 | | |
| 841 | m | |
| 612 | 842 | } |
| 843 | UINT8 offy = yarray[masky]; | |
| 844 | ||
| 845 | UINT16 maskx = (mask & (0xf000 >> (offy << 2))) >> ((offy ^ 3) << 2); | |
| 846 | UINT8 offx = xarray[maskx]; | |
| 847 | ||
| 848 | cvarray[i].xoff = offx; | |
| 849 | cvarray[i].yoff = offy; | |
| 613 | 850 | } |
| 614 | if (deltazmem>15) | |
| 615 | { | |
| 616 | deltazmem=0; | |
| 617 | } | |
| 618 | *zb = m_z_compress_table[z] | (deltazmem>>2); | |
| 619 | *zhb = (deltazmem & 3); | |
| 620 | 851 | } |
| 621 | 852 | |
| 622 | UINT | |
| 853 | UINT16 Processor::decompress_cvmask_frombyte(UINT8 | |
| 623 | 854 | { |
| 624 | UINT32 exponent = (*zb >> 13) & 7; | |
| 625 | UINT32 mantissa = (*zb >> 2) & 0x7ff; | |
| 626 | return ((mantissa << m_z_decompress_table[exponent].shift) + m_z_decompress_table[exponent].add); | |
| 855 | UINT16 y = (x & 1) | ((x & 2) << 1) | ((x & 4) << 3) | ((x & 8) << 4) | | |
| 856 | ((x & 0x10) << 4) | ((x & 0x20) << 5) | ((x & 0x40) << 7) | ((x & 0x80) << 8); | |
| 857 | return y; | |
| 627 | 858 | } |
| 628 | 859 | |
| 629 | ||
| 860 | void | |
| 630 | 861 | { |
| 631 | UINT32 dz_compressed = (((*zb & 3) << 2)|(*zhb & 3)); | |
| 632 | return (1 << dz_compressed); | |
| 862 | UINT32 index; | |
| 863 | /* | |
| 864 | if (mask != (mask & 0xa5a5))//never happens | |
| 865 | stricterror("wrong cvmask computed: %x", mask); | |
| 866 | */ | |
| 867 | index = compressed_cvmasks[mask];//ñîãëàñíî VTune, ãäå-òî íà 50% áûñòðåå, ÷åì ñæàòèå äî 8 áèò íà ìåñòå â ýòîé ô-èè | |
| 868 | m_misc_state.m_curpixel_cvg = cvarray[index].cvg; | |
| 869 | m_misc_state.m_curpixel_cvbit = cvarray[index].cvbit;//áèò mask15b: cv.c, bl.c | |
| 870 | *offx = cvarray[index].xoff; | |
| 871 | *offy = cvarray[index].yoff; | |
| 633 | 872 | } |
| 634 | 873 | |
| 874 | void Processor::ZStore(UINT32 zcurpixel, UINT32 dzcurpixel, UINT32 z) | |
| 875 | { | |
| 876 | UINT16 zval = z_com_table[z & 0x3ffff]|(m_dzpix_enc >> 2); | |
| 877 | if(zcurpixel <= MEM16_LIMIT) | |
| 878 | { | |
| 879 | ((UINT16*)rdram)[zcurpixel ^ WORD_ADDR_XOR] = zval; | |
| 880 | } | |
| 881 | if(dzcurpixel <= MEM8_LIMIT) | |
| 882 | { | |
| 883 | m_hidden_bits[dzcurpixel ^ BYTE_ADDR_XOR] = m_dzpix_enc & 3; | |
| 884 | } | |
| 885 | } | |
| 886 | ||
| 635 | 887 | INT32 Processor::NormalizeDZPix(INT32 sum) |
| 636 | 888 | { |
| 637 | 889 | if (sum & 0xc000) |
| r9854 | r9855 | |
| 652 | 904 | return 0; |
| 653 | 905 | } |
| 654 | 906 | |
| 655 | ||
| 907 | UINT32 Processor::ZDecomp | |
| 656 | 908 | { |
| 657 | int force_coplanar = 0; | |
| 658 | UINT32 oz = DecompressZ(zb); | |
| 659 | UINT32 dzmem = DecompressDZ(zb, zhb); | |
| 660 | UINT32 dznew = 0; | |
| 661 | UINT32 diff = 0; | |
| 662 | int precision_factor = (oz >> 15) & 0xf; | |
| 663 | int cvgcoeff = 0; | |
| 664 | UINT32 mempixel; | |
| 665 | UINT32 memory_cvg; | |
| 909 | UINT32 zb = RREADIDX16(zcurpixel); | |
| 910 | return z_complete_dec_table[(zb >> 2) & 0x3fff]; | |
| 911 | } | |
| 666 | 912 | |
| 667 | sz &= 0x3ffff; | |
| 668 | if (dzmem == 0x8000 && precision_factor < 3) | |
| 913 | UINT32 Processor::DZDecompress(UINT32 zcurpixel, UINT32 dzcurpixel) | |
| 914 | { | |
| 915 | UINT16 zval = RREADIDX16(zcurpixel); | |
| 916 | UINT8 dzval = (((dzcurpixel) <= 0x7fffff) ? (GetHiddenBits()[(dzcurpixel) ^ BYTE_ADDR_XOR]) : 0); | |
| 917 | UINT32 dz_compressed = ((zval & 3) << 2) | (dzval & 3); | |
| 918 | return (1 << dz_compressed); | |
| 919 | } | |
| 920 | ||
| 921 | UINT32 Processor::DZCompress(UINT32 value) | |
| 922 | { | |
| 923 | INT32 j = 0; | |
| 924 | for (; value > 1; j++, value >>= 1); | |
| 925 | return j; | |
| 926 | } | |
| 927 | ||
| 928 | void Processor::GetDitherValues(int x, int y, int* cdith, int* adith) | |
| 929 | { | |
| 930 | int dithindex = ((y & 3) << 2) | (x & 3); | |
| 931 | switch((m_other_modes.rgb_dither_sel << 2) | m_other_modes.alpha_dither_sel) | |
| 669 | 932 | { |
| 670 | force_coplanar = 1; | |
| 933 | case 0: | |
| 934 | *adith = *cdith = s_magic_matrix[dithindex]; | |
| 935 | break; | |
| 936 | case 1: | |
| 937 | *cdith = s_magic_matrix[dithindex]; | |
| 938 | *adith = (~(*cdith)) & 7; | |
| 939 | break; | |
| 940 | case 2: | |
| 941 | *cdith = s_magic_matrix[dithindex]; | |
| 942 | *adith = mame_rand(m_machine) & 7; | |
| 943 | break; | |
| 944 | case 3: | |
| 945 | *cdith = s_magic_matrix[dithindex]; | |
| 946 | *adith = 0; | |
| 947 | break; | |
| 948 | case 4: | |
| 949 | *adith = *cdith = s_bayer_matrix[dithindex]; | |
| 950 | break; | |
| 951 | case 5: | |
| 952 | *cdith = s_bayer_matrix[dithindex]; | |
| 953 | *adith = (~(*cdith)) & 7; | |
| 954 | break; | |
| 955 | case 6: | |
| 956 | *cdith = s_bayer_matrix[dithindex]; | |
| 957 | *adith = mame_rand(m_machine) & 7; | |
| 958 | break; | |
| 959 | case 7: | |
| 960 | *cdith = s_bayer_matrix[dithindex]; | |
| 961 | *adith = 0; | |
| 962 | break; | |
| 963 | case 8: | |
| 964 | *cdith = mame_rand(m_machine) & 7; | |
| 965 | *adith = s_magic_matrix[dithindex]; | |
| 966 | break; | |
| 967 | case 9: | |
| 968 | *cdith = mame_rand(m_machine) & 7; | |
| 969 | *adith = (~s_magic_matrix[dithindex]) & 7; | |
| 970 | break; | |
| 971 | case 10: | |
| 972 | *cdith = mame_rand(m_machine) & 7; | |
| 973 | *adith = (*cdith + 17) & 7; | |
| 974 | break; | |
| 975 | case 11: | |
| 976 | *cdith = mame_rand(m_machine) & 7; | |
| 977 | *adith = 0; | |
| 978 | break; | |
| 979 | case 12: | |
| 980 | *cdith = 0; | |
| 981 | *adith = s_bayer_matrix[dithindex]; | |
| 982 | break; | |
| 983 | case 13: | |
| 984 | *cdith = 0; | |
| 985 | *adith = (~s_bayer_matrix[dithindex]) & 7; | |
| 986 | break; | |
| 987 | case 14: | |
| 988 | *cdith = 0; | |
| 989 | *adith = mame_rand(m_machine) & 7; | |
| 990 | break; | |
| 991 | case 15: | |
| 992 | *adith = *cdith = 0; | |
| 993 | break; | |
| 671 | 994 | } |
| 672 | if (!precision_factor) | |
| 995 | } | |
| 996 | ||
| 997 | INT32 CLAMP(INT32 in, INT32 min, INT32 max) | |
| 998 | { | |
| 999 | if(in < min) return min; | |
| 1000 | if(in > max) return max; | |
| 1001 | return in; | |
| 1002 | } | |
| 1003 | ||
| 1004 | bool Processor::ZCompare(UINT32 zcurpixel, UINT32 dzcurpixel, UINT32 sz, UINT16 dzpix) | |
| 1005 | { | |
| 1006 | bool force_coplanar = false; | |
| 1007 | sz &= 0x3ffff; | |
| 1008 | ||
| 1009 | UINT32 oz; | |
| 1010 | UINT32 dzmem; | |
| 1011 | UINT32 zval; | |
| 1012 | INT32 rawdzmem; | |
| 1013 | ||
| 1014 | if (m_other_modes.z_compare_en) | |
| 673 | 1015 | { |
| 674 | dzmem = ((dzmem << 1) > 16) ? (dzmem << 1) : 16; | |
| 1016 | oz = ZDecompress(zcurpixel); | |
| 1017 | dzmem = DZDecompress(zcurpixel, dzcurpixel); | |
| 1018 | zval = RREADIDX16(zcurpixel); | |
| 1019 | rawdzmem = ((zval & 3) << 2) | ((((dzcurpixel) <= 0x3fffff) ? (GetHiddenBits()[(dzcurpixel) ^ BYTE_ADDR_XOR]) : 0) & 3); | |
| 675 | 1020 | } |
| 676 | else | |
| 1021 | else | |
| 677 | 1022 | { |
| 678 | dzmem = ((dzmem << 1) > 8) ? (dzmem << 1) : 8; | |
| 1023 | oz = 0; | |
| 1024 | dzmem = 1 << 0xf; | |
| 1025 | zval = 0x3; | |
| 1026 | rawdzmem = 0xf; | |
| 679 | 1027 | } |
| 680 | else if (precision_factor == 2) | |
| 1028 | ||
| 1029 | m_dzpix_enc = DZCompress(dzpix & 0xffff); | |
| 1030 | m_blender.SetShiftA(CLAMP(m_dzpix_enc - rawdzmem, 0, 4)); | |
| 1031 | m_blender.SetShiftB(CLAMP(rawdzmem - m_dzpix_enc, 0, 4)); | |
| 1032 | ||
| 1033 | int precision_factor = (zval >> 13) & 0xf; | |
| 1034 | ||
| 1035 | bool precision_important = precision_factor < 3; | |
| 1036 | int dzmemmodifier; | |
| 1037 | if (precision_important) | |
| 681 | 1038 | { |
| 682 | dzmem = ((dzmem << 1) > 4) ? (dzmem << 1) : 4; | |
| 1039 | dzmemmodifier = 16 >> precision_factor; | |
| 1040 | if (dzmem == 0x8000) | |
| 1041 | { | |
| 1042 | force_coplanar = true; | |
| 1043 | } | |
| 1044 | dzmem <<= 1; | |
| 1045 | if (dzmem <= dzmemmodifier) | |
| 1046 | { | |
| 1047 | dzmem = dzmemmodifier; | |
| 1048 | } | |
| 1049 | if (!dzmem) | |
| 1050 | { | |
| 1051 | dzmem = 0xffff; | |
| 1052 | } | |
| 683 | 1053 | } |
| 684 | if (dzmem == 0 && precision_factor < 3) | |
| 685 | { | |
| 686 | dzmem = 0xffff; | |
| 687 | } | |
| 688 | 1054 | if (dzmem > 0x8000) |
| 689 | 1055 | { |
| 690 | 1056 | dzmem = 0xffff; |
| 691 | 1057 | } |
| 692 | dznew =((dzmem > dzpix) ? dzmem : (UINT32)dzpix) << 3; | |
| 693 | dznew &= 0x3ffff; | |
| 694 | 1058 | |
| 695 | bool farther = ((sz + dznew) >= oz); | |
| 696 | diff = (sz >= dznew) ? (sz - dznew) : 0; | |
| 697 | bool nearer = (diff <= oz); | |
| 698 | bool infront = (sz < oz); | |
| 699 | bool max = (dzmem == 0x3ffff); | |
| 1059 | UINT32 dznew = (dzmem > dzpix) ? dzmem : (UINT32)dzpix; | |
| 1060 | UINT32 dznotshift = dznew; | |
| 1061 | dznew <<= 3; | |
| 700 | 1062 | |
| 1063 | bool farther = (sz + dznew) >= oz; | |
| 1064 | bool infront = sz < oz; | |
| 1065 | ||
| 701 | 1066 | if (force_coplanar) |
| 702 | 1067 | { |
| 703 | farther = | |
| 1068 | farther = | |
| 704 | 1069 | } |
| 705 | 1070 | |
| 706 | m_misc_state.m_curpixel_overlap = 0; | |
| 1071 | bool overflow = ((m_misc_state.m_curpixel_memcvg + m_misc_state.m_curpixel_cvg) & 8) > 0; | |
| 1072 | m_blender.SetBlendEnable(m_other_modes.force_blend || (!overflow && m_other_modes.antialias_en && farther)); | |
| 1073 | m_framebuffer.SetPreWrap(overflow); | |
| 707 | 1074 | |
| 708 | switch(m_misc_state.m_fb_size) | |
| 1075 | int cvgcoeff = 0; | |
| 1076 | UINT32 dzenc = 0; | |
| 1077 | ||
| 1078 | if (m_other_modes.z_mode == 1 && infront && farther && overflow) | |
| 709 | 1079 | { |
| 710 | case 1: /* Banjo Tooie */ | |
| 711 | memory_cvg = 0; //?? | |
| 712 | break; | |
| 713 | case 2: | |
| 714 | mempixel = *(UINT16*)fb; | |
| 715 | memory_cvg = ((mempixel & 1) << 2) + (*hb & 3); | |
| 716 | break; | |
| 717 | case 3: | |
| 718 | mempixel = *(UINT32*)fb; | |
| 719 | memory_cvg = (mempixel >> 5) & 7; | |
| 720 | break; | |
| 721 | default: | |
| 722 | fatalerror("z_compare: fb_size = %d",m_misc_state.m_fb_size); | |
| 723 | break; | |
| 1080 | dzenc = DZCompress(dznotshift & 0xffff); | |
| 1081 | cvgcoeff = ((oz >> dzenc) - (sz >> dzenc)) & 0xf; | |
| 1082 | m_misc_state.m_curpixel_cvg = ((cvgcoeff * m_misc_state.m_curpixel_cvg) >> 3) & 0xf; | |
| 724 | 1083 | } |
| 725 | 1084 | |
| 726 | if (!m_other_modes. | |
| 1085 | if (!m_other_modes.z_compa | |
| 727 | 1086 | { |
| 728 | | |
| 1087 | return | |
| 729 | 1088 | } |
| 730 | 1089 | |
| 731 | bool overflow = ((memory_cvg + m_misc_state.m_curpixel_cvg - 1) > 7); | |
| 732 | m_misc_state.m_curpixel_overlap = (m_other_modes.force_blend || (!overflow && m_other_modes.antialias_en && farther)); | |
| 733 | ||
| 734 | if (m_other_modes.z_mode == 1 && infront && farther && overflow) | |
| 1090 | INT32 diff = (INT32)sz - (INT32)dznew; | |
| 1091 | bool nearer = diff <= (INT32)oz; | |
| 1092 | bool max = (oz == 0x3ffff); | |
| 1093 | if (force_coplanar) | |
| 735 | 1094 | { |
| 736 | cvgcoeff = ((dzmem >> dznew) - (sz >> dznew)) & 0xf; | |
| 737 | m_misc_state.m_curpixel_cvg = ((cvgcoeff * (m_misc_state.m_curpixel_cvg - 1)) >> 3) & 0xf; | |
| 1095 | nearer = true; | |
| 738 | 1096 | } |
| 739 | if (m_misc_state.m_curpixel_cvg > 8) | |
| 740 | { | |
| 741 | m_misc_state.m_curpixel_cvg = 8; | |
| 742 | } | |
| 743 | 1097 | |
| 744 | 1098 | switch(m_other_modes.z_mode) |
| 745 | 1099 | { |
| 746 | case 0: // Opaque | |
| 747 | return (max || (overflow ? infront : nearer)); | |
| 748 | case 1: // Interpenetrating | |
| 749 | return (max || (overflow ? infront : nearer)); | |
| 750 | case 2: // Transparent | |
| 751 | return (infront || max); | |
| 752 | case 3: // Decal | |
| 753 | return (farther && nearer && !max); | |
| 754 | default: | |
| 755 | fatalerror( "z_mode = %d", m_other_modes.z_mode); | |
| 756 | break; | |
| 1100 | case 0: | |
| 1101 | return (max || (overflow ? infront : nearer)); | |
| 1102 | break; | |
| 1103 | case 1: | |
| 1104 | return (max || (overflow ? infront : nearer)); | |
| 1105 | break; | |
| 1106 | case 2: | |
| 1107 | return (infront || max); | |
| 1108 | break; | |
| 1109 | case 3: | |
| 1110 | return (farther && nearer && !max); | |
| 1111 | break; | |
| 757 | 1112 | } |
| 1113 | ||
| 1114 | return false; | |
| 758 | 1115 | } |
| 759 | 1116 | |
| 760 | 1117 | UINT32 Processor::GetLog2(UINT32 lod_clamp) |
| r9854 | r9855 | |
| 942 | 1299 | sprintf(buffer, "Tri_NoShade %d, XL: %s, XM: %s, XH: %s, YL: %s, YM: %s, YH: %s\n", lft, xl,xm,xh,yl,ym,yh); |
| 943 | 1300 | break; |
| 944 | 1301 | } |
| 1302 | case 0x09: // Tri_NoShadeZ | |
| 1303 | { | |
| 1304 | int lft = (command >> 23) & 0x1; | |
| 1305 | ||
| 1306 | if (length != rdp_command_length[command]) | |
| 1307 | { | |
| 1308 | sprintf(buffer, "ERROR: Tri_NoShadeZ length = %d\n", length); | |
| 1309 | return; | |
| 1310 | } | |
| 1311 | ||
| 1312 | cmd[2] = m_cmd_data[m_cmd_cur+2]; | |
| 1313 | cmd[3] = m_cmd_data[m_cmd_cur+3]; | |
| 1314 | cmd[4] = m_cmd_data[m_cmd_cur+4]; | |
| 1315 | cmd[5] = m_cmd_data[m_cmd_cur+5]; | |
| 1316 | cmd[6] = m_cmd_data[m_cmd_cur+6]; | |
| 1317 | cmd[7] = m_cmd_data[m_cmd_cur+7]; | |
| 1318 | ||
| 1319 | sprintf(yl, "%4.4f", (float)((cmd[0] >> 0) & 0x1fff) / 4.0f); | |
| 1320 | sprintf(ym, "%4.4f", (float)((cmd[1] >> 16) & 0x1fff) / 4.0f); | |
| 1321 | sprintf(yh, "%4.4f", (float)((cmd[1] >> 0) & 0x1fff) / 4.0f); | |
| 1322 | sprintf(xl, "%4.4f", (float)(cmd[2] / 65536.0f)); | |
| 1323 | sprintf(dxldy, "%4.4f", (float)(cmd[3] / 65536.0f)); | |
| 1324 | sprintf(xh, "%4.4f", (float)(cmd[4] / 65536.0f)); | |
| 1325 | sprintf(dxhdy, "%4.4f", (float)(cmd[5] / 65536.0f)); | |
| 1326 | sprintf(xm, "%4.4f", (float)(cmd[6] / 65536.0f)); | |
| 1327 | sprintf(dxmdy, "%4.4f", (float)(cmd[7] / 65536.0f)); | |
| 1328 | ||
| 1329 | sprintf(buffer, "Tri_NoShadeZ %d, XL: %s, XM: %s, XH: %s, YL: %s, YM: %s, YH: %s\n", lft, xl,xm,xh,yl,ym,yh); | |
| 1330 | break; | |
| 1331 | } | |
| 945 | 1332 | case 0x0a: // Tri_Tex |
| 946 | 1333 | { |
| 947 | 1334 | int lft = (command >> 23) & 0x1; |
| r9854 | r9855 | |
| 992 | 1379 | buffer+=sprintf(buffer, " DSDY: %s, DTDY: %s, DWDY: %s\n", dsdy, dtdy, dwdy); |
| 993 | 1380 | break; |
| 994 | 1381 | } |
| 1382 | case 0x0b: // Tri_TexZ | |
| 1383 | { | |
| 1384 | int lft = (command >> 23) & 0x1; | |
| 1385 | ||
| 1386 | if (length < rdp_command_length[command]) | |
| 1387 | { | |
| 1388 | sprintf(buffer, "ERROR: Tri_TexZ length = %d\n", length); | |
| 1389 | return; | |
| 1390 | } | |
| 1391 | ||
| 1392 | for (i=2; i < 24; i++) | |
| 1393 | { | |
| 1394 | cmd[i] = m_cmd_data[m_cmd_cur+i]; | |
| 1395 | } | |
| 1396 | ||
| 1397 | sprintf(yl, "%4.4f", (float)((cmd[0] >> 0) & 0x1fff) / 4.0f); | |
| 1398 | sprintf(ym, "%4.4f", (float)((cmd[1] >> 16) & 0x1fff) / 4.0f); | |
| 1399 | sprintf(yh, "%4.4f", (float)((cmd[1] >> 0) & 0x1fff) / 4.0f); | |
| 1400 | sprintf(xl, "%4.4f", (float)((INT32)cmd[2] / 65536.0f)); | |
| 1401 | sprintf(dxldy, "%4.4f", (float)((INT32)cmd[3] / 65536.0f)); | |
| 1402 | sprintf(xh, "%4.4f", (float)((INT32)cmd[4] / 65536.0f)); | |
| 1403 | sprintf(dxhdy, "%4.4f", (float)((INT32)cmd[5] / 65536.0f)); | |
| 1404 | sprintf(xm, "%4.4f", (float)((INT32)cmd[6] / 65536.0f)); | |
| 1405 | sprintf(dxmdy, "%4.4f", (float)((INT32)cmd[7] / 65536.0f)); | |
| 1406 | ||
| 1407 | sprintf(s, "%4.4f", (float)(INT32)((cmd[ 8] & 0xffff0000) | ((cmd[12] >> 16) & 0xffff)) / 65536.0f); | |
| 1408 | sprintf(t, "%4.4f", (float)(INT32)(((cmd[ 8] & 0xffff) << 16) | (cmd[12] & 0xffff)) / 65536.0f); | |
| 1409 | sprintf(w, "%4.4f", (float)(INT32)((cmd[ 9] & 0xffff0000) | ((cmd[13] >> 16) & 0xffff)) / 65536.0f); | |
| 1410 | sprintf(dsdx, "%4.4f", (float)(INT32)((cmd[10] & 0xffff0000) | ((cmd[14] >> 16) & 0xffff)) / 65536.0f); | |
| 1411 | sprintf(dtdx, "%4.4f", (float)(INT32)(((cmd[10] & 0xffff) << 16) | (cmd[14] & 0xffff)) / 65536.0f); | |
| 1412 | sprintf(dwdx, "%4.4f", (float)(INT32)((cmd[11] & 0xffff0000) | ((cmd[15] >> 16) & 0xffff)) / 65536.0f); | |
| 1413 | sprintf(dsde, "%4.4f", (float)(INT32)((cmd[16] & 0xffff0000) | ((cmd[20] >> 16) & 0xffff)) / 65536.0f); | |
| 1414 | sprintf(dtde, "%4.4f", (float)(INT32)(((cmd[16] & 0xffff) << 16) | (cmd[20] & 0xffff)) / 65536.0f); | |
| 1415 | sprintf(dwde, "%4.4f", (float)(INT32)((cmd[17] & 0xffff0000) | ((cmd[21] >> 16) & 0xffff)) / 65536.0f); | |
| 1416 | sprintf(dsdy, "%4.4f", (float)(INT32)((cmd[18] & 0xffff0000) | ((cmd[22] >> 16) & 0xffff)) / 65536.0f); | |
| 1417 | sprintf(dtdy, "%4.4f", (float)(INT32)(((cmd[18] & 0xffff) << 16) | (cmd[22] & 0xffff)) / 65536.0f); | |
| 1418 | sprintf(dwdy, "%4.4f", (float)(INT32)((cmd[19] & 0xffff0000) | ((cmd[23] >> 16) & 0xffff)) / 65536.0f); | |
| 1419 | ||
| 1420 | ||
| 1421 | buffer+=sprintf(buffer, "Tri_TexZ %d, XL: %s, XM: %s, XH: %s, YL: %s, YM: %s, YH: %s\n", lft, xl,xm,xh,yl,ym,yh); | |
| 1422 | buffer+=sprintf(buffer, " "); | |
| 1423 | buffer+=sprintf(buffer, " S: %s, T: %s, W: %s\n", s, t, w); | |
| 1424 | buffer+=sprintf(buffer, " "); | |
| 1425 | buffer+=sprintf(buffer, " DSDX: %s, DTDX: %s, DWDX: %s\n", dsdx, dtdx, dwdx); | |
| 1426 | buffer+=sprintf(buffer, " "); | |
| 1427 | buffer+=sprintf(buffer, " DSDE: %s, DTDE: %s, DWDE: %s\n", dsde, dtde, dwde); | |
| 1428 | buffer+=sprintf(buffer, " "); | |
| 1429 | buffer+=sprintf(buffer, " DSDY: %s, DTDY: %s, DWDY: %s\n", dsdy, dtdy, dwdy); | |
| 1430 | break; | |
| 1431 | } | |
| 995 | 1432 | case 0x0c: // Tri_Shade |
| 996 | 1433 | { |
| 997 | 1434 | int lft = (command >> 23) & 0x1; |
| r9854 | r9855 | |
| 1044 | 1481 | buffer+=sprintf(buffer, " DRDY: %s, DGDY: %s, DBDY: %s, DADY: %s\n", drdy, dgdy, dbdy, dady); |
| 1045 | 1482 | break; |
| 1046 | 1483 | } |
| 1484 | case 0x0d: // Tri_ShadeZ | |
| 1485 | { | |
| 1486 | int lft = (command >> 23) & 0x1; | |
| 1487 | ||
| 1488 | if (length != rdp_command_length[command]) | |
| 1489 | { | |
| 1490 | sprintf(buffer, "ERROR: Tri_ShadeZ length = %d\n", length); | |
| 1491 | return; | |
| 1492 | } | |
| 1493 | ||
| 1494 | for (i=2; i < 24; i++) | |
| 1495 | { | |
| 1496 | cmd[i] = m_cmd_data[i]; | |
| 1497 | } | |
| 1498 | ||
| 1499 | sprintf(yl, "%4.4f", (float)((cmd[0] >> 0) & 0x1fff) / 4.0f); | |
| 1500 | sprintf(ym, "%4.4f", (float)((cmd[1] >> 16) & 0x1fff) / 4.0f); | |
| 1501 | sprintf(yh, "%4.4f", (float)((cmd[1] >> 0) & 0x1fff) / 4.0f); | |
| 1502 | sprintf(xl, "%4.4f", (float)((INT32)cmd[2] / 65536.0f)); | |
| 1503 | sprintf(dxldy, "%4.4f", (float)((INT32)cmd[3] / 65536.0f)); | |
| 1504 | sprintf(xh, "%4.4f", (float)((INT32)cmd[4] / 65536.0f)); | |
| 1505 | sprintf(dxhdy, "%4.4f", (float)((INT32)cmd[5] / 65536.0f)); | |
| 1506 | sprintf(xm, "%4.4f", (float)((INT32)cmd[6] / 65536.0f)); | |
| 1507 | sprintf(dxmdy, "%4.4f", (float)((INT32)cmd[7] / 65536.0f)); | |
| 1508 | sprintf(rt, "%4.4f", (float)(INT32)((cmd[8] & 0xffff0000) | ((cmd[12] >> 16) & 0xffff)) / 65536.0f); | |
| 1509 | sprintf(gt, "%4.4f", (float)(INT32)(((cmd[8] & 0xffff) << 16) | (cmd[12] & 0xffff)) / 65536.0f); | |
| 1510 | sprintf(bt, "%4.4f", (float)(INT32)((cmd[9] & 0xffff0000) | ((cmd[13] >> 16) & 0xffff)) / 65536.0f); | |
| 1511 | sprintf(at, "%4.4f", (float)(INT32)(((cmd[9] & 0xffff) << 16) | (cmd[13] & 0xffff)) / 65536.0f); | |
| 1512 | sprintf(drdx, "%4.4f", (float)(INT32)((cmd[10] & 0xffff0000) | ((cmd[14] >> 16) & 0xffff)) / 65536.0f); | |
| 1513 | sprintf(dgdx, "%4.4f", (float)(INT32)(((cmd[10] & 0xffff) << 16) | (cmd[14] & 0xffff)) / 65536.0f); | |
| 1514 | sprintf(dbdx, "%4.4f", (float)(INT32)((cmd[11] & 0xffff0000) | ((cmd[15] >> 16) & 0xffff)) / 65536.0f); | |
| 1515 | sprintf(dadx, "%4.4f", (float)(INT32)(((cmd[11] & 0xffff) << 16) | (cmd[15] & 0xffff)) / 65536.0f); | |
| 1516 | sprintf(drde, "%4.4f", (float)(INT32)((cmd[16] & 0xffff0000) | ((cmd[20] >> 16) & 0xffff)) / 65536.0f); | |
| 1517 | sprintf(dgde, "%4.4f", (float)(INT32)(((cmd[16] & 0xffff) << 16) | (cmd[20] & 0xffff)) / 65536.0f); | |
| 1518 | sprintf(dbde, "%4.4f", (float)(INT32)((cmd[17] & 0xffff0000) | ((cmd[21] >> 16) & 0xffff)) / 65536.0f); | |
| 1519 | sprintf(dade, "%4.4f", (float)(INT32)(((cmd[17] & 0xffff) << 16) | (cmd[21] & 0xffff)) / 65536.0f); | |
| 1520 | sprintf(drdy, "%4.4f", (float)(INT32)((cmd[18] & 0xffff0000) | ((cmd[22] >> 16) & 0xffff)) / 65536.0f); | |
| 1521 | sprintf(dgdy, "%4.4f", (float)(INT32)(((cmd[18] & 0xffff) << 16) | (cmd[22] & 0xffff)) / 65536.0f); | |
| 1522 | sprintf(dbdy, "%4.4f", (float)(INT32)((cmd[19] & 0xffff0000) | ((cmd[23] >> 16) & 0xffff)) / 65536.0f); | |
| 1523 | sprintf(dady, "%4.4f", (float)(INT32)(((cmd[19] & 0xffff) << 16) | (cmd[23] & 0xffff)) / 65536.0f); | |
| 1524 | ||
| 1525 | buffer+=sprintf(buffer, "Tri_ShadeZ %d, XL: %s, XM: %s, XH: %s, YL: %s, YM: %s, YH: %s\n", lft, xl,xm,xh,yl,ym,yh); | |
| 1526 | buffer+=sprintf(buffer, " "); | |
| 1527 | buffer+=sprintf(buffer, " R: %s, G: %s, B: %s, A: %s\n", rt, gt, bt, at); | |
| 1528 | buffer+=sprintf(buffer, " "); | |
| 1529 | buffer+=sprintf(buffer, " DRDX: %s, DGDX: %s, DBDX: %s, DADX: %s\n", drdx, dgdx, dbdx, dadx); | |
| 1530 | buffer+=sprintf(buffer, " "); | |
| 1531 | buffer+=sprintf(buffer, " DRDE: %s, DGDE: %s, DBDE: %s, DADE: %s\n", drde, dgde, dbde, dade); | |
| 1532 | buffer+=sprintf(buffer, " "); | |
| 1533 | buffer+=sprintf(buffer, " DRDY: %s, DGDY: %s, DBDY: %s, DADY: %s\n", drdy, dgdy, dbdy, dady); | |
| 1534 | break; | |
| 1535 | } | |
| 1047 | 1536 | case 0x0e: // Tri_TexShade |
| 1048 | 1537 | { |
| 1049 | 1538 | int lft = (command >> 23) & 0x1; |
| r9854 | r9855 | |
| 1119 | 1608 | buffer+=sprintf(buffer, " DSDY: %s, DTDY: %s, DWDY: %s\n", dsdy, dtdy, dwdy); |
| 1120 | 1609 | break; |
| 1121 | 1610 | } |
| 1611 | case 0x0f: // Tri_TexShadeZ | |
| 1612 | { | |
| 1613 | int lft = (command >> 23) & 0x1; | |
| 1614 | ||
| 1615 | if (length < rdp_command_length[command]) | |
| 1616 | { | |
| 1617 | sprintf(buffer, "ERROR: Tri_TexShadeZ length = %d\n", length); | |
| 1618 | return; | |
| 1619 | } | |
| 1620 | ||
| 1621 | for (i=2; i < 40; i++) | |
| 1622 | { | |
| 1623 | cmd[i] = m_cmd_data[m_cmd_cur+i]; | |
| 1624 | } | |
| 1625 | ||
| 1626 | sprintf(yl, "%4.4f", (float)((cmd[0] >> 0) & 0x1fff) / 4.0f); | |
| 1627 | sprintf(ym, "%4.4f", (float)((cmd[1] >> 16) & 0x1fff) / 4.0f); | |
| 1628 | sprintf(yh, "%4.4f", (float)((cmd[1] >> 0) & 0x1fff) / 4.0f); | |
| 1629 | sprintf(xl, "%4.4f", (float)((INT32)cmd[2] / 65536.0f)); | |
| 1630 | sprintf(dxldy, "%4.4f", (float)((INT32)cmd[3] / 65536.0f)); | |
| 1631 | sprintf(xh, "%4.4f", (float)((INT32)cmd[4] / 65536.0f)); | |
| 1632 | sprintf(dxhdy, "%4.4f", (float)((INT32)cmd[5] / 65536.0f)); | |
| 1633 | sprintf(xm, "%4.4f", (float)((INT32)cmd[6] / 65536.0f)); | |
| 1634 | sprintf(dxmdy, "%4.4f", (float)((INT32)cmd[7] / 65536.0f)); | |
| 1635 | sprintf(rt, "%4.4f", (float)(INT32)((cmd[8] & 0xffff0000) | ((cmd[12] >> 16) & 0xffff)) / 65536.0f); | |
| 1636 | sprintf(gt, "%4.4f", (float)(INT32)(((cmd[8] & 0xffff) << 16) | (cmd[12] & 0xffff)) / 65536.0f); | |
| 1637 | sprintf(bt, "%4.4f", (float)(INT32)((cmd[9] & 0xffff0000) | ((cmd[13] >> 16) & 0xffff)) / 65536.0f); | |
| 1638 | sprintf(at, "%4.4f", (float)(INT32)(((cmd[9] & 0xffff) << 16) | (cmd[13] & 0xffff)) / 65536.0f); | |
| 1639 | sprintf(drdx, "%4.4f", (float)(INT32)((cmd[10] & 0xffff0000) | ((cmd[14] >> 16) & 0xffff)) / 65536.0f); | |
| 1640 | sprintf(dgdx, "%4.4f", (float)(INT32)(((cmd[10] & 0xffff) << 16) | (cmd[14] & 0xffff)) / 65536.0f); | |
| 1641 | sprintf(dbdx, "%4.4f", (float)(INT32)((cmd[11] & 0xffff0000) | ((cmd[15] >> 16) & 0xffff)) / 65536.0f); | |
| 1642 | sprintf(dadx, "%4.4f", (float)(INT32)(((cmd[11] & 0xffff) << 16) | (cmd[15] & 0xffff)) / 65536.0f); | |
| 1643 | sprintf(drde, "%4.4f", (float)(INT32)((cmd[16] & 0xffff0000) | ((cmd[20] >> 16) & 0xffff)) / 65536.0f); | |
| 1644 | sprintf(dgde, "%4.4f", (float)(INT32)(((cmd[16] & 0xffff) << 16) | (cmd[20] & 0xffff)) / 65536.0f); | |
| 1645 | sprintf(dbde, "%4.4f", (float)(INT32)((cmd[17] & 0xffff0000) | ((cmd[21] >> 16) & 0xffff)) / 65536.0f); | |
| 1646 | sprintf(dade, "%4.4f", (float)(INT32)(((cmd[17] & 0xffff) << 16) | (cmd[21] & 0xffff)) / 65536.0f); | |
| 1647 | sprintf(drdy, "%4.4f", (float)(INT32)((cmd[18] & 0xffff0000) | ((cmd[22] >> 16) & 0xffff)) / 65536.0f); | |
| 1648 | sprintf(dgdy, "%4.4f", (float)(INT32)(((cmd[18] & 0xffff) << 16) | (cmd[22] & 0xffff)) / 65536.0f); | |
| 1649 | sprintf(dbdy, "%4.4f", (float)(INT32)((cmd[19] & 0xffff0000) | ((cmd[23] >> 16) & 0xffff)) / 65536.0f); | |
| 1650 | sprintf(dady, "%4.4f", (float)(INT32)(((cmd[19] & 0xffff) << 16) | (cmd[23] & 0xffff)) / 65536.0f); | |
| 1651 | ||
| 1652 | sprintf(s, "%4.4f", (float)(INT32)((cmd[24] & 0xffff0000) | ((cmd[28] >> 16) & 0xffff)) / 65536.0f); | |
| 1653 | sprintf(t, "%4.4f", (float)(INT32)(((cmd[24] & 0xffff) << 16) | (cmd[28] & 0xffff)) / 65536.0f); | |
| 1654 | sprintf(w, "%4.4f", (float)(INT32)((cmd[25] & 0xffff0000) | ((cmd[29] >> 16) & 0xffff)) / 65536.0f); | |
| 1655 | sprintf(dsdx, "%4.4f", (float)(INT32)((cmd[26] & 0xffff0000) | ((cmd[30] >> 16) & 0xffff)) / 65536.0f); | |
| 1656 | sprintf(dtdx, "%4.4f", (float)(INT32)(((cmd[26] & 0xffff) << 16) | (cmd[30] & 0xffff)) / 65536.0f); | |
| 1657 | sprintf(dwdx, "%4.4f", (float)(INT32)((cmd[27] & 0xffff0000) | ((cmd[31] >> 16) & 0xffff)) / 65536.0f); | |
| 1658 | sprintf(dsde, "%4.4f", (float)(INT32)((cmd[32] & 0xffff0000) | ((cmd[36] >> 16) & 0xffff)) / 65536.0f); | |
| 1659 | sprintf(dtde, "%4.4f", (float)(INT32)(((cmd[32] & 0xffff) << 16) | (cmd[36] & 0xffff)) / 65536.0f); | |
| 1660 | sprintf(dwde, "%4.4f", (float)(INT32)((cmd[33] & 0xffff0000) | ((cmd[37] >> 16) & 0xffff)) / 65536.0f); | |
| 1661 | sprintf(dsdy, "%4.4f", (float)(INT32)((cmd[34] & 0xffff0000) | ((cmd[38] >> 16) & 0xffff)) / 65536.0f); | |
| 1662 | sprintf(dtdy, "%4.4f", (float)(INT32)(((cmd[34] & 0xffff) << 16) | (cmd[38] & 0xffff)) / 65536.0f); | |
| 1663 | sprintf(dwdy, "%4.4f", (float)(INT32)((cmd[35] & 0xffff0000) | ((cmd[39] >> 16) & 0xffff)) / 65536.0f); | |
| 1664 | ||
| 1665 | ||
| 1666 | buffer+=sprintf(buffer, "Tri_TexShadeZ %d, XL: %s, XM: %s, XH: %s, YL: %s, YM: %s, YH: %s\n", lft, xl,xm,xh,yl,ym,yh); | |
| 1667 | buffer+=sprintf(buffer, " "); | |
| 1668 | buffer+=sprintf(buffer, " R: %s, G: %s, B: %s, A: %s\n", rt, gt, bt, at); | |
| 1669 | buffer+=sprintf(buffer, " "); | |
| 1670 | buffer+=sprintf(buffer, " DRDX: %s, DGDX: %s, DBDX: %s, DADX: %s\n", drdx, dgdx, dbdx, dadx); | |
| 1671 | buffer+=sprintf(buffer, " "); | |
| 1672 | buffer+=sprintf(buffer, " DRDE: %s, DGDE: %s, DBDE: %s, DADE: %s\n", drde, dgde, dbde, dade); | |
| 1673 | buffer+=sprintf(buffer, " "); | |
| 1674 | buffer+=sprintf(buffer, " DRDY: %s, DGDY: %s, DBDY: %s, DADY: %s\n", drdy, dgdy, dbdy, dady); | |
| 1675 | ||
| 1676 | buffer+=sprintf(buffer, " "); | |
| 1677 | buffer+=sprintf(buffer, " S: %s, T: %s, W: %s\n", s, t, w); | |
| 1678 | buffer+=sprintf(buffer, " "); | |
| 1679 | buffer+=sprintf(buffer, " DSDX: %s, DTDX: %s, DWDX: %s\n", dsdx, dtdx, dwdx); | |
| 1680 | buffer+=sprintf(buffer, " "); | |
| 1681 | buffer+=sprintf(buffer, " DSDE: %s, DTDE: %s, DWDE: %s\n", dsde, dtde, dwde); | |
| 1682 | buffer+=sprintf(buffer, " "); | |
| 1683 | buffer+=sprintf(buffer, " DSDY: %s, DTDY: %s, DWDY: %s\n", dsdy, dtdy, dwdy); | |
| 1684 | break; | |
| 1685 | } | |
| 1122 | 1686 | case 0x24: |
| 1123 | 1687 | case 0x25: |
| 1124 | 1688 | { |
| r9854 | r9855 | |
| 1169 | 1733 | |
| 1170 | 1734 | /*****************************************************************************/ |
| 1171 | 1735 | |
| 1172 | N64::RDP::Triangle::Triangle(running_machine *machine, bool shade, bool texture, bool zbuffer) | |
| 1736 | N64::RDP::Triangle::Triangle(running_machine *machine, bool shade, bool texture, bool zbuffer, bool rect, bool flip) | |
| 1173 | 1737 | { |
| 1174 | InitFromData(machine, shade, texture, zbuffer); | |
| 1738 | InitFromData(machine, shade, texture, zbuffer, rect, flip); | |
| 1175 | 1739 | } |
| 1176 | 1740 | |
| 1177 | void N64::RDP::Triangle::InitFromData(running_machine *machine, bool shade, bool texture, bool zbuffer) | |
| 1741 | void N64::RDP::Triangle::InitFromData(running_machine *machine, bool shade, bool texture, bool zbuffer, bool rect, bool flip) | |
| 1178 | 1742 | { |
| 1179 | 1743 | m_machine = machine; |
| 1180 | 1744 | m_rdp = &(machine->driver_data<_n64_state>())->m_rdp; |
| 1181 | m_cmd_data = m_rdp->GetCommandData(); | |
| 1745 | m_cmd_data = rect ? m_rdp->GetTempRectData() : m_rdp->GetCommandData(); | |
| 1182 | 1746 | m_misc_state = m_rdp->GetMiscState(); |
| 1183 | 1747 | m_shade = shade; |
| 1184 | 1748 | m_texture = texture; |
| 1185 | 1749 | m_zbuffer = zbuffer; |
| 1750 | m_rect = rect; | |
| 1186 | 1751 | } |
| 1187 | 1752 | |
| 1753 | static UINT32 rightcvghex(UINT32 x, UINT32 fmask) | |
| 1754 | { | |
| 1755 | UINT32 stickybit = ((x >> 1) & 0x1fff) > 0; | |
| 1756 | UINT32 covered = ((x >> 14) & 3) + stickybit; | |
| 1757 | covered = (0xf0 >> covered) & 0xf; | |
| 1758 | return (covered & fmask); | |
| 1759 | } | |
| 1760 | ||
| 1761 | static UINT32 leftcvghex(UINT32 x, UINT32 fmask) | |
| 1762 | { | |
| 1763 | UINT32 stickybit = ((x >> 1) & 0x1fff) > 0; | |
| 1764 | UINT32 covered = ((x >> 14) & 3) + stickybit; | |
| 1765 | covered = 0xf >> covered; | |
| 1766 | return (covered & fmask); | |
| 1767 | } | |
| 1768 | ||
| 1769 | static INT32 CLIP(INT32 value,INT32 min,INT32 max) | |
| 1770 | { | |
| 1771 | if (value < min) | |
| 1772 | { | |
| 1773 | return min; | |
| 1774 | } | |
| 1775 | else if (value > max) | |
| 1776 | { | |
| 1777 | return max; | |
| 1778 | } | |
| 1779 | else | |
| 1780 | { | |
| 1781 | return value; | |
| 1782 | } | |
| 1783 | } | |
| 1784 | ||
| 1785 | void N64::RDP::Triangle::compute_cvg_noflip(INT32* majorx, INT32* minorx, INT32* majorxint, INT32* minorxint, INT32 scanline, INT32 yh, INT32 yl) | |
| 1786 | { | |
| 1787 | INT32 purgestart = 0xfff; | |
| 1788 | INT32 purgeend = 0; | |
| 1789 | bool writablescanline = !(scanline & ~0x3ff); | |
| 1790 | INT32 scanlinespx = scanline << 2; | |
| 1791 | ||
| 1792 | if (!writablescanline) return; | |
| 1793 | ||
| 1794 | for(int i = 0; i < 4; i++) | |
| 1795 | { | |
| 1796 | if (minorxint[i] < purgestart) | |
| 1797 | { | |
| 1798 | purgestart = minorxint[i]; | |
| 1799 | } | |
| 1800 | if (majorxint[i] > purgeend) | |
| 1801 | { | |
| 1802 | purgeend = majorxint[i]; | |
| 1803 | } | |
| 1804 | } | |
| 1805 | ||
| 1806 | purgestart = CLIP(purgestart, 0, 1023); | |
| 1807 | purgeend = CLIP(purgeend, 0, 1023); | |
| 1808 | INT32 length = purgeend - purgestart; | |
| 1809 | ||
| 1810 | if (length < 0) return; | |
| 1811 | ||
| 1812 | memset(&m_rdp->GetSpans()[scanline].m_cvg[purgestart], 0, (length + 1) << 2); | |
| 1813 | ||
| 1814 | for(int i = 0; i < 4; i++) | |
| 1815 | { | |
| 1816 | INT32 minorcur = minorx[i]; | |
| 1817 | INT32 majorcur = majorx[i]; | |
| 1818 | INT32 minorcurint = minorxint[i]; | |
| 1819 | INT32 majorcurint = majorxint[i]; | |
| 1820 | length = majorcurint - minorcurint; | |
| 1821 | ||
| 1822 | INT32 fmask = (i & 1) ? 5 : 0xa; | |
| 1823 | INT32 maskshift = (i ^ 3) << 2; | |
| 1824 | INT32 fmaskshifted = fmask << maskshift; | |
| 1825 | INT32 fleft = CLIP(minorcurint + 1, 0, 647); | |
| 1826 | INT32 fright = CLIP(majorcurint - 1, 0, 647); | |
| 1827 | bool valid_y = ((scanlinespx + i) >= yh && (scanlinespx + i) < yl); | |
| 1828 | if (valid_y && length >= 0) | |
| 1829 | { | |
| 1830 | if (minorcurint != majorcurint) | |
| 1831 | { | |
| 1832 | if (!(minorcurint & ~0x3ff)) | |
| 1833 | { | |
| 1834 | m_rdp->GetSpans()[scanline].m_cvg[minorcurint] |= (leftcvghex(minorcur, fmask) << maskshift); | |
| 1835 | } | |
| 1836 | if (!(majorcurint & ~0x3ff)) | |
| 1837 | { | |
| 1838 | m_rdp->GetSpans()[scanline].m_cvg[majorcurint] |= (rightcvghex(majorcur, fmask) << maskshift); | |
| 1839 | } | |
| 1840 | } | |
| 1841 | else | |
| 1842 | { | |
| 1843 | if (!(majorcurint & ~0x3ff)) | |
| 1844 | { | |
| 1845 | INT32 samecvg = leftcvghex(minorcur, fmask) & rightcvghex(majorcur, fmask); | |
| 1846 | m_rdp->GetSpans()[scanline].m_cvg[majorcurint] |= (samecvg << maskshift); | |
| 1847 | } | |
| 1848 | } | |
| 1849 | for (; fleft <= fright; fleft++) | |
| 1850 | { | |
| 1851 | m_rdp->GetSpans()[scanline].m_cvg[fleft] |= fmaskshifted; | |
| 1852 | } | |
| 1853 | } | |
| 1854 | } | |
| 1855 | } | |
| 1856 | ||
| 1857 | void N64::RDP::Triangle::compute_cvg_flip(INT32* majorx, INT32* minorx, INT32* majorxint, INT32* minorxint, INT32 scanline, INT32 yh, INT32 yl) | |
| 1858 | { | |
| 1859 | INT32 purgestart = 0xfff; | |
| 1860 | INT32 purgeend = 0; | |
| 1861 | bool writablescanline = !(scanline & ~0x3ff); | |
| 1862 | INT32 scanlinespx = scanline << 2; | |
| 1863 | ||
| 1864 | if(!writablescanline) return; | |
| 1865 | ||
| 1866 | for(int i = 0; i < 4; i++) | |
| 1867 | { | |
| 1868 | if (majorxint[i] < purgestart) | |
| 1869 | { | |
| 1870 | purgestart = majorxint[i]; | |
| 1871 | } | |
| 1872 | if (minorxint[i] > purgeend) | |
| 1873 | { | |
| 1874 | purgeend = minorxint[i]; | |
| 1875 | } | |
| 1876 | } | |
| 1877 | ||
| 1878 | purgestart = CLIP(purgestart, 0, 1023); | |
| 1879 | purgeend = CLIP(purgeend, 0, 1023); | |
| 1880 | ||
| 1881 | int length = purgeend - purgestart; | |
| 1882 | ||
| 1883 | if (length < 0) return; | |
| 1884 | ||
| 1885 | memset(&m_rdp->GetSpans()[scanline].m_cvg[purgestart], 0, (length + 1) << 2); | |
| 1886 | ||
| 1887 | for(int i = 0; i < 4; i++) | |
| 1888 | { | |
| 1889 | INT32 minorcur = minorx[i]; | |
| 1890 | INT32 majorcur = majorx[i]; | |
| 1891 | INT32 minorcurint = minorxint[i]; | |
| 1892 | INT32 majorcurint = majorxint[i]; | |
| 1893 | length = minorcurint - majorcurint; | |
| 1894 | ||
| 1895 | INT32 fmask = (i & 1) ? 5 : 0xa; | |
| 1896 | INT32 maskshift = (i ^ 3) << 2; | |
| 1897 | INT32 fmaskshifted = fmask << maskshift; | |
| 1898 | INT32 fleft = CLIP(majorcurint + 1, 0, 647); | |
| 1899 | INT32 fright = CLIP(minorcurint - 1, 0, 647); | |
| 1900 | bool valid_y = ((scanlinespx + i) >= yh && (scanlinespx + i) < yl); | |
| 1901 | if (valid_y && length >= 0) | |
| 1902 | { | |
| 1903 | if (minorcurint != majorcurint) | |
| 1904 | { | |
| 1905 | if (!(minorcurint & ~0x3ff)) | |
| 1906 | { | |
| 1907 | m_rdp->GetSpans()[scanline].m_cvg[minorcurint] |= (rightcvghex(minorcur, fmask) << maskshift); | |
| 1908 | } | |
| 1909 | if (!(majorcurint & ~0x3ff)) | |
| 1910 | { | |
| 1911 | m_rdp->GetSpans()[scanline].m_cvg[majorcurint] |= (leftcvghex(majorcur, fmask) << maskshift); | |
| 1912 | } | |
| 1913 | } | |
| 1914 | else | |
| 1915 | { | |
| 1916 | if (!(majorcurint & ~0x3ff)) | |
| 1917 | { | |
| 1918 | INT32 samecvg = rightcvghex(minorcur, fmask) & leftcvghex(majorcur, fmask); | |
| 1919 | m_rdp->GetSpans()[scanline].m_cvg[majorcurint] |= (samecvg << maskshift); | |
| 1920 | } | |
| 1921 | } | |
| 1922 | for (; fleft <= fright; fleft++) | |
| 1923 | { | |
| 1924 | m_rdp->GetSpans()[scanline].m_cvg[fleft] |= fmaskshifted; | |
| 1925 | } | |
| 1926 | } | |
| 1927 | } | |
| 1928 | } | |
| 1929 | ||
| 1188 | 1930 | void N64::RDP::Triangle::Draw() |
| 1189 | 1931 | { |
| 1190 | UINT32 w1 = m_cmd_data[m_rdp->GetCurrFIFOIndex()+0]; | |
| 1191 | UINT32 w2 = m_cmd_data[m_rdp->GetCurrFIFOIndex()+1]; | |
| 1932 | UINT32 fifo_index = m_rect ? 0 : m_rdp->GetCurrFIFOIndex(); | |
| 1933 | UINT32 w1 = m_cmd_data[fifo_index + 0]; | |
| 1934 | UINT32 w2 = m_cmd_data[fifo_index + 1]; | |
| 1192 | 1935 | |
| 1193 | 1936 | int flip = (w1 & 0x800000) ? 1 : 0; |
| 1194 | int sign = (w1 & 0x800000) ? -1 : 1; | |
| 1195 | int inv_sign = (w1 & 0x800000) ? 1 : -1; | |
| 1937 | m_misc_state->m_max_level = ((w1 >> 19) & 7); | |
| 1938 | int tilenum = (w1 >> 16) & 0x7; | |
| 1196 | 1939 | |
| 1197 | 1940 | int dsdiff = 0, dtdiff = 0, dwdiff = 0, drdiff = 0, dgdiff = 0, dbdiff = 0, dadiff = 0, dzdiff = 0; |
| 1198 | int dseoff = 0, dteoff = 0, dweoff = 0, dreoff = 0, dgeoff = 0, dbeoff = 0, daeoff = 0, dzeoff = 0; | |
| 1199 | 1941 | int dsdeh = 0, dtdeh = 0, dwdeh = 0, drdeh = 0, dgdeh = 0, dbdeh = 0, dadeh = 0, dzdeh = 0; |
| 1200 | 1942 | int dsdxh = 0, dtdxh = 0, dwdxh = 0, drdxh = 0, dgdxh = 0, dbdxh = 0, dadxh = 0, dzdxh = 0; |
| 1201 | 1943 | int dsdyh = 0, dtdyh = 0, dwdyh = 0, drdyh = 0, dgdyh = 0, dbdyh = 0, dadyh = 0, dzdyh = 0; |
| 1202 | int xfrac = 0; | |
| 1203 | 1944 | |
| 1204 | 1945 | INT32 maxxmx = 0; |
| 1205 | 1946 | INT32 minxmx = 0; |
| 1206 | 1947 | INT32 maxxhx = 0; |
| 1207 | 1948 | INT32 minxhx = 0; |
| 1208 | 1949 | |
| 1209 | int shade_base = m_rdp->GetCurrFIFOIndex() + 8; | |
| 1210 | int texture_base = m_rdp->GetCurrFIFOIndex() + 8; | |
| 1211 | int zbuffer_base = m_rdp->GetCurrFIFOIndex() + 8; | |
| 1212 | if(m_texture) | |
| 1950 | int shade_base = fifo_index + 8; | |
| 1951 | int texture_base = fifo_index + 8; | |
| 1952 | int zbuffer_base = fifo_index + 8; | |
| 1953 | if(m_shade) | |
| 1213 | 1954 | { |
| 1214 | 1955 | texture_base += 16; |
| 1215 | 1956 | zbuffer_base += 16; |
| 1216 | 1957 | } |
| 1217 | if(m_ | |
| 1958 | if(m_t | |
| 1218 | 1959 | { |
| 1219 | 1960 | zbuffer_base += 16; |
| 1220 | 1961 | } |
| 1221 | 1962 | |
| 1222 | UINT32 w3 = m_cmd_data[m_rdp->GetCurrFIFOIndex()+2]; | |
| 1223 | UINT32 w4 = m_cmd_data[m_rdp->GetCurrFIFOIndex()+3]; | |
| 1224 | UINT32 w5 = m_cmd_data[m_rdp->GetCurrFIFOIndex()+4]; | |
| 1225 | UINT32 w6 = m_cmd_data[m_rdp->GetCurrFIFOIndex()+5]; | |
| 1226 | UINT32 w7 = m_cmd_data[m_rdp->GetCurrFIFOIndex()+6]; | |
| 1227 | UINT32 w8 = m_cmd_data[m_rdp->GetCurrFIFOIndex()+7]; | |
| 1963 | UINT32 w3 = m_cmd_data[fifo_index + 2]; | |
| 1964 | UINT32 w4 = m_cmd_data[fifo_index + 3]; | |
| 1965 | UINT32 w5 = m_cmd_data[fifo_index + 4]; | |
| 1966 | UINT32 w6 = m_cmd_data[fifo_index + 5]; | |
| 1967 | UINT32 w7 = m_cmd_data[fifo_index + 6]; | |
| 1968 | UINT32 w8 = m_cmd_data[fifo_index + 7]; | |
| 1228 | 1969 | |
| 1229 | 1970 | INT32 yl = (w1 & 0x3fff); |
| 1230 | 1971 | INT32 ym = ((w2 >> 16) & 0x3fff); |
| r9854 | r9855 | |
| 1237 | 1978 | INT32 dxhdy = (INT32)(w6); |
| 1238 | 1979 | INT32 dxmdy = (INT32)(w8); |
| 1239 | 1980 | |
| 1240 | m_misc_state->m_max_level = ((w1 >> 19) & 7); | |
| 1241 | int tilenum = (w1 >> 16) & 0x7; | |
| 1242 | ||
| 1243 | 1981 | if (yl & 0x2000) yl |= 0xffffc000; |
| 1244 | 1982 | if (ym & 0x2000) ym |= 0xffffc000; |
| 1245 | 1983 | if (yh & 0x2000) yh |= 0xffffc000; |
| r9854 | r9855 | |
| 1281 | 2019 | int dzde = m_cmd_data[zbuffer_base+2]; |
| 1282 | 2020 | int dzdy = m_cmd_data[zbuffer_base+3]; |
| 1283 | 2021 | |
| 2022 | //printf("%08x %08x %08x %08x\n", m_cmd_data[0], m_cmd_data[1], m_cmd_data[2], m_cmd_data[3]); | |
| 2023 | //printf("%08x %08x %08x %08x\n", m_cmd_data[4], m_cmd_data[5], m_cmd_data[6], m_cmd_data[7]); | |
| 2024 | //printf("%08x %08x %08x %08x\n", m_cmd_data[8], m_cmd_data[9], m_cmd_data[10], m_cmd_data[11]); | |
| 2025 | //printf("%08x %08x %08x %08x\n", m_cmd_data[12], m_cmd_data[13], m_cmd_data[14], m_cmd_data[15]); | |
| 2026 | //printf("%08x %08x %08x %08x\n", m_cmd_data[16], m_cmd_data[17], m_cmd_data[18], m_cmd_data[19]); | |
| 2027 | //printf("%08x %08x %08x %08x\n", m_cmd_data[20], m_cmd_data[21], m_cmd_data[22], m_cmd_data[23]); | |
| 2028 | //printf("%08x %08x %08x %08x\n", m_cmd_data[24], m_cmd_data[25], m_cmd_data[26], m_cmd_data[27]); | |
| 2029 | //printf("%08x %08x %08x %08x\n", m_cmd_data[28], m_cmd_data[29], m_cmd_data[30], m_cmd_data[31]); | |
| 2030 | //printf("%08x %08x %08x %08x\n", m_cmd_data[32], m_cmd_data[33], m_cmd_data[34], m_cmd_data[35]); | |
| 2031 | //printf("%08x %08x %08x %08x\n", m_cmd_data[36], m_cmd_data[37], m_cmd_data[38], m_cmd_data[39]); | |
| 2032 | //printf("%08x %08x %08x %08x\n", m_cmd_data[40], m_cmd_data[41], m_cmd_data[42], m_cmd_data[43]); | |
| 2033 | //printf("%08x %08x %08x %08x\n", m_cmd_data[44], m_cmd_data[45], m_cmd_data[46], m_cmd_data[47]); | |
| 2034 | ||
| 1284 | 2035 | int dzdy_dz = (dzdy >> 16) & 0xffff; |
| 1285 | 2036 | int dzdx_dz = (dzdx >> 16) & 0xffff; |
| 1286 | int dsdylod = dsdy >> 16; | |
| 1287 | int dtdylod = dtdy >> 16; | |
| 1288 | if (dsdylod & 0x20000) | |
| 1289 | { | |
| 1290 | dsdylod = ~dsdylod & 0x1ffff; | |
| 1291 | } | |
| 1292 | if (dtdylod & 0x20000) | |
| 1293 | { | |
| 1294 | dtdylod = ~dtdylod & 0x1ffff; | |
| 1295 | } | |
| 1296 | 2037 | |
| 1297 | int xleft_inc = dxmdy >> 2; | |
| 1298 | int xright_inc = dxhdy >> 2; | |
| 2038 | m_rdp->set_span_base_y(drdy, dgdy, dbdy, dady, dzdy); | |
| 2039 | UINT32 temp_dzpix = ((dzdy_dz & 0x8000) ? ((~dzdy_dz) & 0x7fff) : dzdy_dz) + ((dzdx_dz & 0x8000) ? ((~dzdx_dz) & 0x7fff) : dzdx_dz); | |
| 2040 | m_rdp->set_span_base(drdx & ~0x1f, | |
| 2041 | dgdx & ~0x1f, | |
| 2042 | dbdx & ~0x1f, | |
| 2043 | dadx & ~0x1f, | |
| 2044 | dsdx, | |
| 2045 | dtdx, | |
| 2046 | dwdx, | |
| 2047 | dzdx, | |
| 2048 | 0, | |
| 2049 | m_rdp->NormalizeDZPix(temp_dzpix & 0xffff) & 0xffff | |
| 2050 | ); | |
| 1299 | 2051 | |
| 1300 | int xright = xh; | |
| 1301 | int xleft = xm; | |
| 2052 | int xleft_inc = (dxmdy >> 2) & ~1; | |
| 2053 | int xright_inc = (dxhdy >> 2) & ~1; | |
| 1302 | 2054 | |
| 1303 | INT32 limcvg = ((yl>>2) <= 1023) ? (yl>>2) : 1023; // Needed by 40 Winks | |
| 1304 | if (limcvg < 0) | |
| 1305 | { | |
| 1306 | limcvg = 0; | |
| 1307 | } | |
| 2055 | int xright = xh & ~1; | |
| 2056 | int xleft = xm & ~1; | |
| 1308 | 2057 | |
| 1309 | INT32 startcvg = ((yh>>2)>=0) ? (yh>>2) : 0; | |
| 1310 | for (int k = startcvg; k <= limcvg; k++) | |
| 1311 | { | |
| 1312 | memset((void*)&m_rdp->GetSpans()[k].m_cvg[0],0,640); | |
| 1313 | } | |
| 1314 | ||
| 1315 | 2058 | int sign_dxhdy = (dxhdy & 0x80000000) ? 1 : 0; |
| 1316 | 2059 | int do_offset = !(sign_dxhdy ^ (flip)); |
| 1317 | 2060 | |
| r9854 | r9855 | |
| 1326 | 2069 | dadeh = dade >> 9; dadyh = dady >> 9; |
| 1327 | 2070 | dzdeh = dzde >> 9; dzdyh = dzdy >> 9; |
| 1328 | 2071 | |
| 1329 | dsdiff = (dsdeh*3 - dsdyh*3) << 7; | |
| 1330 | dtdiff = (dtdeh*3 - dtdyh*3) << 7; | |
| 1331 | dwdiff = (dwdeh*3 - dwdyh*3) << 7; | |
| 1332 | drdiff = (drdeh*3 - drdyh*3) << 7; | |
| 1333 | dgdiff = (dgdeh*3 - dgdyh*3) << 7; | |
| 1334 | dbdiff = (dbdeh*3 - dbdyh*3) << 7; | |
| 1335 | dadiff = (dadeh*3 - dadyh*3) << 7; | |
| 1336 | dzdiff = (dzdeh*3 - dzdyh*3) << 7; | |
| 1337 | ||
| 1338 | dseoff = (dsdeh*3) << 7; | |
| 1339 | dteoff = (dtdeh*3) << 7; | |
| 1340 | dweoff = (dwdeh*3) << 7; | |
| 1341 | dreoff = (drdeh*3) << 7; | |
| 1342 | dgeoff = (dgdeh*3) << 7; | |
| 1343 | dbeoff = (dbdeh*3) << 7; | |
| 1344 | daeoff = (dadeh*3) << 7; | |
| 1345 | dzeoff = (dzdeh*3) << 7; | |
| 2072 | dsdiff = (dsdeh << 8) + (dsdeh << 7) - (dsdyh << 8) - (dsdyh << 7); | |
| 2073 | dtdiff = (dtdeh << 8) + (dtdeh << 7) - (dtdyh << 8) - (dtdyh << 7); | |
| 2074 | dwdiff = (dwdeh << 8) + (dwdeh << 7) - (dwdyh << 8) - (dwdyh << 7); | |
| 2075 | drdiff = (drdeh << 8) + (drdeh << 7) - (drdyh << 8) - (drdyh << 7); | |
| 2076 | dgdiff = (dgdeh << 8) + (dgdeh << 7) - (dgdyh << 8) - (dgdyh << 7); | |
| 2077 | dbdiff = (dbdeh << 8) + (dbdeh << 7) - (dbdyh << 8) - (dbdyh << 7); | |
| 2078 | dadiff = (dadeh << 8) + (dadeh << 7) - (dadyh << 8) - (dadyh << 7); | |
| 2079 | dzdiff = (dzdeh << 8) + (dzdeh << 7) - (dzdyh << 8) - (dzdyh << 7); | |
| 1346 | 2080 | } |
| 1347 | 2081 | else |
| 1348 | 2082 | { |
| 1349 | 2083 | dsdiff = dtdiff = dwdiff = drdiff = dgdiff = dbdiff = dadiff = dzdiff = 0; |
| 1350 | dseoff = dteoff = dweoff = dreoff = dgeoff = dbeoff = daeoff = dzeoff = 0; | |
| 1351 | 2084 | } |
| 1352 | 2085 | |
| 1353 | 2086 | dsdxh = dsdx >> 8; |
| r9854 | r9855 | |
| 1359 | 2092 | dadxh = dadx >> 8; |
| 1360 | 2093 | dzdxh = dzdx >> 8; |
| 1361 | 2094 | |
| 1362 | int ycur = yh & ~3; | |
| 1363 | int ylfar = yl | 3; | |
| 1364 | int ldflag = (sign_dxhdy ^ flip) ? 0 : 3; | |
| 1365 | int yhpix = yh >> 2; | |
| 1366 | int ylpix = yl >> 2; | |
| 2095 | INT32 ycur = yh & ~3; | |
| 2096 | INT32 ylfar = yl | 3; | |
| 2097 | INT32 ldflag = (sign_dxhdy ^ flip) ? 0 : 3; | |
| 2098 | INT32 majorx[4]; | |
| 2099 | INT32 minorx[4]; | |
| 2100 | INT32 majorxint[4]; | |
| 2101 | INT32 minorxint[4]; | |
| 2102 | bool valid_y = true; | |
| 1367 | 2103 | |
| 1368 | if(ylfar >= 0x1000) | |
| 1369 | { | |
| 1370 | ylfar = 0x0fff; | |
| 1371 | } | |
| 2104 | int xfrac = ((xright >> 8) & 0xff); | |
| 1372 | 2105 | |
| 1373 | 2106 | if(flip) |
| 1374 | 2107 | { |
| r9854 | r9855 | |
| 1376 | 2109 | { |
| 1377 | 2110 | if (k == ym) |
| 1378 | 2111 | { |
| 1379 | xleft = xl; | |
| 1380 | xleft_inc = dxldy >> 2; | |
| 2112 | xleft = xl & ~1; | |
| 2113 | xleft_inc = (dxldy >> 2) & ~1; | |
| 1381 | 2114 | } |
| 1382 | 2115 | |
| 1383 | 2116 | int xstart = xleft >> 16; |
| 1384 | 2117 | int xend = xright >> 16; |
| 1385 | 2118 | int j = k >> 2; |
| 1386 | 2119 | int spix = k & 3; |
| 2120 | valid_y = !(k < yh || k >= yl); | |
| 1387 | 2121 | |
| 1388 | int m = 0; | |
| 1389 | int n = 0; | |
| 1390 | UINT32 min = 0; | |
| 1391 | UINT32 max = 3; | |
| 1392 | if (j == yhpix) | |
| 2122 | if (k >= 0 && k < 0x1000) | |
| 1393 | 2123 | { |
| 1394 | min = yh & 3; | |
| 1395 | } | |
| 1396 | if (j == ylpix) | |
| 1397 | { | |
| 1398 | max = yl & 3; | |
| 1399 | } | |
| 1400 | if (spix >= min && spix <= max) | |
| 1401 | { | |
| 1402 | if (spix == min) | |
| 2124 | majorxint[spix] = xend; | |
| 2125 | minorxint[spix] = xstart; | |
| 2126 | majorx[spix] = xright; | |
| 2127 | minorx[spix] = xleft; | |
| 2128 | ||
| 2129 | if (spix == 0) | |
| 1403 | 2130 | { |
| 1404 | minxmx = maxxmx = xstart; | |
| 1405 | minxhx = maxxhx = xend; | |
| 2131 | maxxmx = 0; | |
| 2132 | minxhx = 0xfff; | |
| 1406 | 2133 | } |
| 1407 | else | |
| 2134 | ||
| 2135 | if (valid_y) | |
| 1408 | 2136 | { |
| 1409 | minxmx = (xstart < minxmx) ? xstart : minxmx; | |
| 1410 | 2137 | maxxmx = (xstart > maxxmx) ? xstart : maxxmx; |
| 1411 | 2138 | minxhx = (xend < minxhx) ? xend : minxhx; |
| 1412 | maxxhx = (xend > maxxhx) ? xend : maxxhx; | |
| 1413 | 2139 | } |
| 1414 | } | |
| 1415 | 2140 | |
| 1416 | if (spix == max) | |
| 1417 | { | |
| 1418 | m_rdp->GetSpans()[j].m_lx = maxxmx; | |
| 1419 | m_rdp->GetSpans()[j].m_rx = minxhx; | |
| 1420 | if(m_shade) | |
| 2141 | if (spix == 3) | |
| 1421 | 2142 | { |
| 1422 | m_rdp->GetSpans()[j].m_dr.w = drdx & ~0x1f; | |
| 1423 | m_rdp->GetSpans()[j].m_dg.w = dgdx & ~0x1f; | |
| 1424 | m_rdp->GetSpans()[j].m_db.w = dbdx & ~0x1f; | |
| 1425 | m_rdp->GetSpans()[j].m_da.w = dadx & ~0x1f; | |
| 2143 | m_rdp->GetSpans()[j].m_lx = maxxmx; | |
| 2144 | m_rdp->GetSpans()[j].m_rx = minxhx; | |
| 2145 | compute_cvg_flip(majorx, minorx, majorxint, minorxint, j, yh, yl); | |
| 1426 | 2146 | } |
| 1427 | else | |
| 1428 | { | |
| 1429 | m_rdp->GetSpans()[j].m_dr.w = 0; | |
| 1430 | m_rdp->GetSpans()[j].m_dg.w = 0; | |
| 1431 | m_rdp->GetSpans()[j].m_db.w = 0; | |
| 1432 | m_rdp->GetSpans()[j].m_da.w = 0; | |
| 1433 | } | |
| 1434 | if(m_texture) | |
| 1435 | { | |
| 1436 | m_rdp->GetSpans()[j].m_ds.w = dsdx; | |
| 1437 | m_rdp->GetSpans()[j].m_dt.w = dtdx; | |
| 1438 | m_rdp->GetSpans()[j].m_dw.w = dwdx; | |
| 1439 | } | |
| 1440 | else | |
| 1441 | { | |
| 1442 | m_rdp->GetSpans()[j].m_ds.w = 0; | |
| 1443 | m_rdp->GetSpans()[j].m_dt.w = 0; | |
| 1444 | m_rdp->GetSpans()[j].m_dw.w = 0; | |
| 1445 | } | |
| 1446 | if(m_zbuffer) | |
| 1447 | { | |
| 1448 | m_rdp->GetSpans()[j].m_dymax = (dsdylod > dtdylod)? dsdylod : dtdylod; | |
| 1449 | m_rdp->GetSpans()[j].m_dz.w = dzdx; | |
| 1450 | m_rdp->GetSpans()[j].m_dzpix = ((dzdy_dz & 0x8000) ? ((~dzdy_dz) & 0x7fff) : dzdy_dz) + ((dzdx_dz & 0x8000) ? ((~dzdx_dz) & 0x7fff) : dzdx_dz); | |
| 1451 | m_rdp->GetSpans()[j].m_dzpix = m_rdp->NormalizeDZPix(m_rdp->GetSpans()[j].m_dzpix); | |
| 1452 | } | |
| 1453 | else | |
| 1454 | { | |
| 1455 | m_rdp->GetSpans()[j].m_dymax = 0; | |
| 1456 | m_rdp->GetSpans()[j].m_dz.w = 0; | |
| 1457 | m_rdp->GetSpans()[j].m_dzpix = 0; | |
| 1458 | m_rdp->GetSpans()[j].m_dzpix = 0; | |
| 1459 | } | |
| 1460 | } | |
| 1461 | 2147 | |
| 1462 | int length = (xend - xstart) * sign; | |
| 1463 | ||
| 1464 | if (spix == ldflag) | |
| 1465 | { | |
| 1466 | xfrac = ((xright >> 8) & 0xff); | |
| 1467 | if(m_shade) | |
| 2148 | if (spix == ldflag) | |
| 1468 | 2149 | { |
| 1469 | m_rdp->GetSpans()[j].m_r.w = r + drdiff - (xfrac * drdxh); | |
| 1470 | m_rdp->GetSpans()[j].m_g.w = g + dgdiff - (xfrac * dgdxh); | |
| 1471 | m_rdp->GetSpans()[j].m_b.w = b + dbdiff - (xfrac * dbdxh); | |
| 1472 | m_rdp->GetSpans()[j].m_a.w = a + dadiff - (xfrac * dadxh); | |
| 2150 | m_rdp->GetSpans()[j].m_unscissored_rx = xend; | |
| 2151 | xfrac = ((xright >> 8) & 0xff); | |
| 2152 | m_rdp->GetSpans()[j].m_r.w = ((r >> 9) << 9) + drdiff - (xfrac * drdxh); | |
| 2153 | m_rdp->GetSpans()[j].m_g.w = ((g >> 9) << 9) + dgdiff - (xfrac * dgdxh); | |
| 2154 | m_rdp->GetSpans()[j].m_b.w = ((b >> 9) << 9) + dbdiff - (xfrac * dbdxh); | |
| 2155 | m_rdp->GetSpans()[j].m_a.w = ((a >> 9) << 9) + dadiff - (xfrac * dadxh); | |
| 2156 | m_rdp->GetSpans()[j].m_s.w = (((s >> 9) << 9) + dsdiff - (xfrac * dsdxh)) & ~0x1f; | |
| 2157 | m_rdp->GetSpans()[j].m_t.w = (((t >> 9) << 9) + dtdiff - (xfrac * dtdxh)) & ~0x1f; | |
| 2158 | m_rdp->GetSpans()[j].m_w.w = (((w >> 9) << 9) + dwdiff - (xfrac * dwdxh)) & ~0x1f; | |
| 2159 | m_rdp->GetSpans()[j].m_z.w = ((z >> 9) << 9) + dzdiff - (xfrac * dzdxh); | |
| 2160 | //printf("%d - %08x\n", j, m_rdp->GetSpans()[j].m_z.w); | |
| 1473 | 2161 | } |
| 1474 | else | |
| 1475 | { | |
| 1476 | m_rdp->GetSpans()[j].m_r.w = m_rdp->GetSpans()[j].m_g.w = m_rdp->GetSpans()[j].m_b.w = m_rdp->GetSpans()[j].m_a.w = 0; | |
| 1477 | } | |
| 1478 | if(m_texture) | |
| 1479 | { | |
| 1480 | m_rdp->GetSpans()[j].m_s.w = (s + dsdiff - (xfrac * dsdxh)) & ~0x1f; | |
| 1481 | m_rdp->GetSpans()[j].m_t.w = (t + dtdiff - (xfrac * dtdxh)) & ~0x1f; | |
| 1482 | m_rdp->GetSpans()[j].m_w.w = (w + dwdiff - (xfrac * dwdxh)) & ~0x1f; | |
| 1483 | } | |
| 1484 | else | |
| 1485 | { | |
| 1486 | m_rdp->GetSpans()[j].m_s.w = m_rdp->GetSpans()[j].m_t.w = m_rdp->GetSpans()[j].m_w.w = 0; | |
| 1487 | } | |
| 1488 | if(m_zbuffer) | |
| 1489 | { | |
| 1490 | m_rdp->GetSpans()[j].m_z.w = z + dzdiff - (xfrac * dzdxh); | |
| 1491 | } | |
| 1492 | else | |
| 1493 | { | |
| 1494 | m_rdp->GetSpans()[j].m_z.w = 0; | |
| 1495 | } | |
| 1496 | 2162 | } |
| 1497 | 2163 | |
| 1498 | m = xend + 1; | |
| 1499 | ||
| 1500 | if (k >= yh && length >= 0 && k <= yl) | |
| 2164 | if (spix == 3) | |
| 1501 | 2165 | { |
| 1502 | if (xstart>=0 && xstart <1024) | |
| 1503 | { | |
| 1504 | m_rdp->GetSpans()[j].m_cvg[xstart] += m_rdp->AddRightCvg(xleft, k); | |
| 1505 | } | |
| 1506 | if (xend>=0 && xend<1024) | |
| 1507 | { | |
| 1508 | if (xstart != xend) | |
| 1509 | { | |
| 1510 | m_rdp->GetSpans()[j].m_cvg[xend] += m_rdp->AddLeftCvg(xright, k); | |
| 1511 | } | |
| 1512 | else | |
| 1513 | { | |
| 1514 | m_rdp->GetSpans()[j].m_cvg[xend] -= (2 - m_rdp->AddLeftCvg(xright, k)); | |
| 1515 | } | |
| 1516 | } | |
| 1517 | for (n = 0; n < (length - 1); n++) | |
| 1518 | { | |
| 1519 | if (m>=0 && m < 640) | |
| 1520 | { | |
| 1521 | m_rdp->GetSpans()[j].m_cvg[m] += 2; | |
| 1522 | } | |
| 1523 | ||
| 1524 | m += inv_sign; | |
| 1525 | } | |
| 2166 | r += drde; | |
| 2167 | g += dgde; | |
| 2168 | b += dbde; | |
| 2169 | a += dade; | |
| 2170 | s += dsde; | |
| 2171 | t += dtde; | |
| 2172 | w += dwde; | |
| 2173 | z += dzde; | |
| 1526 | 2174 | } |
| 1527 | 2175 | |
| 1528 | if (spix == 3) | |
| 1529 | { | |
| 1530 | if(m_shade) | |
| 1531 | { | |
| 1532 | r += drde; | |
| 1533 | g += dgde; | |
| 1534 | b += dbde; | |
| 1535 | a += dade; | |
| 1536 | } | |
| 1537 | if(m_texture) | |
| 1538 | { | |
| 1539 | s += dsde; | |
| 1540 | t += dtde; | |
| 1541 | w += dwde; | |
| 1542 | } | |
| 1543 | if(m_zbuffer) | |
| 1544 | { | |
| 1545 | z += dzde; | |
| 1546 | } | |
| 1547 | } | |
| 1548 | 2176 | xleft += xleft_inc; |
| 1549 | 2177 | xright += xright_inc; |
| 1550 | 2178 | } |
| r9854 | r9855 | |
| 1555 | 2183 | { |
| 1556 | 2184 | if (k == ym) |
| 1557 | 2185 | { |
| 1558 | xleft = xl; | |
| 1559 | xleft_inc = dxldy >> 2; | |
| 2186 | xleft = xl & ~1; | |
| 2187 | xleft_inc = (dxldy >> 2) & ~1; | |
| 1560 | 2188 | } |
| 1561 | 2189 | |
| 1562 | 2190 | int xstart = xleft >> 16; |
| 1563 | 2191 | int xend = xright >> 16; |
| 1564 | 2192 | int j = k >> 2; |
| 1565 | 2193 | int spix = k & 3; |
| 2194 | valid_y = !(k < yh || k >= yl); | |
| 1566 | 2195 | |
| 1567 | int m = 0; | |
| 1568 | int n = 0; | |
| 1569 | UINT32 min = 0; | |
| 1570 | UINT32 max = 3; | |
| 1571 | if (j == yhpix) | |
| 2196 | if (k >= 0 && k < 0x1000) | |
| 1572 | 2197 | { |
| 1573 | min = yh & 3; | |
| 1574 | } | |
| 1575 | if (j == ylpix) | |
| 1576 | { | |
| 1577 | max = yl & 3; | |
| 1578 | } | |
| 1579 | if (spix >= min && spix <= max) | |
| 1580 | { | |
| 1581 | if (spix == min) | |
| 2198 | majorxint[spix] = xend; | |
| 2199 | minorxint[spix] = xstart; | |
| 2200 | majorx[spix] = xright; | |
| 2201 | minorx[spix] = xleft; | |
| 2202 | ||
| 2203 | if (spix == 0) | |
| 1582 | 2204 | { |
| 1583 | minxmx = maxxmx = xstart; | |
| 1584 | minxhx = maxxhx = xend; | |
| 2205 | maxxhx = 0; | |
| 2206 | minxmx = 0xfff; | |
| 1585 | 2207 | } |
| 1586 | else | |
| 2208 | ||
| 2209 | if (valid_y) | |
| 1587 | 2210 | { |
| 1588 | 2211 | minxmx = (xstart < minxmx) ? xstart : minxmx; |
| 1589 | maxxmx = (xstart > maxxmx) ? xstart : maxxmx; | |
| 1590 | minxhx = (xend < minxhx) ? xend : minxhx; | |
| 1591 | 2212 | maxxhx = (xend > maxxhx) ? xend : maxxhx; |
| 1592 | 2213 | } |
| 1593 | } | |
| 1594 | 2214 | |
| 1595 | if (spix == max) | |
| 1596 | { | |
| 1597 | m_rdp->GetSpans()[j].m_lx = minxmx; | |
| 1598 | m_rdp->GetSpans()[j].m_rx = maxxhx; | |
| 1599 | m_rdp->GetSpans()[j].m_dymax = (dsdylod > dtdylod)? dsdylod : dtdylod; | |
| 1600 | if(m_shade) | |
| 2215 | if (spix == 3) | |
| 1601 | 2216 | { |
| 1602 | m_rdp->GetSpans()[j].m_dr.w = drdx & ~0x1f; | |
| 1603 | m_rdp->GetSpans()[j].m_dg.w = dgdx & ~0x1f; | |
| 1604 | m_rdp->GetSpans()[j].m_db.w = dbdx & ~0x1f; | |
| 1605 | m_rdp->GetSpans()[j].m_da.w = dadx & ~0x1f; | |
| 2217 | m_rdp->GetSpans()[j].m_lx = minxmx; | |
| 2218 | m_rdp->GetSpans()[j].m_rx = maxxhx; | |
| 2219 | compute_cvg_noflip(majorx, minorx, majorxint, minorxint, j, yh, yl); | |
| 1606 | 2220 | } |
| 1607 | if(m_texture) | |
| 1608 | { | |
| 1609 | m_rdp->GetSpans()[j].m_ds.w = dsdx; | |
| 1610 | m_rdp->GetSpans()[j].m_dt.w = dtdx; | |
| 1611 | m_rdp->GetSpans()[j].m_dw.w = dwdx; | |
| 1612 | } | |
| 1613 | if(m_zbuffer) | |
| 1614 | { | |
| 1615 | m_rdp->GetSpans()[j].m_dz.w = dzdx; | |
| 1616 | m_rdp->GetSpans()[j].m_dzpix = ((dzdy_dz & 0x8000) ? ((~dzdy_dz) & 0x7fff) : dzdy_dz) + ((dzdx_dz & 0x8000) ? ((~dzdx_dz) & 0x7fff) : dzdx_dz); | |
| 1617 | m_rdp->GetSpans()[j].m_dzpix = m_rdp->NormalizeDZPix(m_rdp->GetSpans()[j].m_dzpix); | |
| 1618 | } | |
| 1619 | } | |
| 1620 | 2221 | |
| 1621 | int length = (xend - xstart) * sign; | |
| 1622 | ||
| 1623 | if (spix == ldflag) | |
| 1624 | { | |
| 1625 | xfrac = ((xright >> 8) & 0xff); | |
| 1626 | if(m_texture) | |
| 2222 | if (spix == ldflag) | |
| 1627 | 2223 | { |
| 1628 | m_rdp->GetSpans()[j].m_s.w = (s + dsdiff - (xfrac * dsdxh)) & ~0x1f; | |
| 1629 | m_rdp->GetSpans()[j].m_t.w = (t + dtdiff - (xfrac * dtdxh)) & ~0x1f; | |
| 1630 | m_rdp->GetSpans()[j].m_w.w = (w + dwdiff - (xfrac * dwdxh)) & ~0x1f; | |
| 2224 | m_rdp->GetSpans()[j].m_unscissored_rx = xend; | |
| 2225 | xfrac = ((xright >> 8) & 0xff); | |
| 2226 | m_rdp->GetSpans()[j].m_r.w = ((r >> 9) << 9) + drdiff - (xfrac * drdxh); | |
| 2227 | m_rdp->GetSpans()[j].m_g.w = ((g >> 9) << 9) + dgdiff - (xfrac * dgdxh); | |
| 2228 | m_rdp->GetSpans()[j].m_b.w = ((b >> 9) << 9) + dbdiff - (xfrac * dbdxh); | |
| 2229 | m_rdp->GetSpans()[j].m_a.w = ((a >> 9) << 9) + dadiff - (xfrac * dadxh); | |
| 2230 | m_rdp->GetSpans()[j].m_s.w = (((s >> 9) << 9) + dsdiff - (xfrac * dsdxh)) & ~0x1f; | |
| 2231 | m_rdp->GetSpans()[j].m_t.w = (((t >> 9) << 9) + dtdiff - (xfrac * dtdxh)) & ~0x1f; | |
| 2232 | m_rdp->GetSpans()[j].m_w.w = (((w >> 9) << 9) + dwdiff - (xfrac * dwdxh)) & ~0x1f; | |
| 2233 | m_rdp->GetSpans()[j].m_z.w = ((z >> 9) << 9) + dzdiff - (xfrac * dzdxh); | |
| 1631 | 2234 | } |
| 1632 | if(m_shade) | |
| 1633 | { | |
| 1634 | m_rdp->GetSpans()[j].m_r.w = r + drdiff - (xfrac * drdxh); | |
| 1635 | m_rdp->GetSpans()[j].m_g.w = g + dgdiff - (xfrac * dgdxh); | |
| 1636 | m_rdp->GetSpans()[j].m_b.w = b + dbdiff - (xfrac * dbdxh); | |
| 1637 | m_rdp->GetSpans()[j].m_a.w = a + dadiff - (xfrac * dadxh); | |
| 1638 | } | |
| 1639 | if(m_zbuffer) | |
| 1640 | { | |
| 1641 | m_rdp->GetSpans()[j].m_z.w = z + dzdiff - (xfrac * dzdxh); | |
| 1642 | } | |
| 1643 | 2235 | } |
| 1644 | 2236 | |
| 1645 | m = xend - 1; | |
| 1646 | ||
| 1647 | if (k >= yh && length >= 0 && k <= yl) | |
| 1648 | { | |
| 1649 | if (xstart>=0 && xstart <1024) | |
| 1650 | { | |
| 1651 | m_rdp->GetSpans()[j].m_cvg[xstart] += m_rdp->AddLeftCvg(xleft, k); | |
| 1652 | } | |
| 1653 | if (xend>=0 && xend<1024) | |
| 1654 | { | |
| 1655 | if (xstart != xend) | |
| 1656 | { | |
| 1657 | m_rdp->GetSpans()[j].m_cvg[xend] += m_rdp->AddRightCvg(xright, k); | |
| 1658 | } | |
| 1659 | else | |
| 1660 | { | |
| 1661 | m_rdp->GetSpans()[j].m_cvg[xend] -= (2 - m_rdp->AddRightCvg(xright, k)); | |
| 1662 | if (m_rdp->GetSpans()[j].m_cvg[xend] > 200) | |
| 1663 | { | |
| 1664 | m_rdp->GetSpans()[j].m_cvg[xend] = 0; | |
| 1665 | } | |
| 1666 | } | |
| 1667 | } | |
| 1668 | for (n = 0; n < (length - 1); n++) | |
| 1669 | { | |
| 1670 | if (m>=0 && m < 640) | |
| 1671 | { | |
| 1672 | m_rdp->GetSpans()[j].m_cvg[m] += 2; | |
| 1673 | } | |
| 1674 | ||
| 1675 | m += inv_sign; | |
| 1676 | } | |
| 1677 | } | |
| 1678 | ||
| 1679 | 2237 | if (spix == 3) |
| 1680 | 2238 | { |
| 1681 | if(m_shade) | |
| 1682 | { | |
| 1683 | r += drde; | |
| 1684 | g += dgde; | |
| 1685 | b += dbde; | |
| 1686 | a += dade; | |
| 1687 | } | |
| 1688 | if(m_texture) | |
| 1689 | { | |
| 1690 | s += dsde; | |
| 1691 | t += dtde; | |
| 1692 | w += dwde; | |
| 1693 | } | |
| 1694 | if(m_zbuffer) | |
| 1695 | { | |
| 1696 | z += dzde; | |
| 1697 | } | |
| 2239 | r += drde; | |
| 2240 | g += dgde; | |
| 2241 | b += dbde; | |
| 2242 | a += dade; | |
| 2243 | s += dsde; | |
| 2244 | t += dtde; | |
| 2245 | w += dwde; | |
| 2246 | z += dzde; | |
| 1698 | 2247 | } |
| 1699 | 2248 | xleft += xleft_inc; |
| 1700 | 2249 | xright += xright_inc; |
| 1701 | 2250 | } |
| 1702 | 2251 | } |
| 1703 | 2252 | |
| 1704 | m_rdp->RenderSpans(yh >> 2, yl >> 2, tilenum, | |
| 2253 | m_rdp->RenderSpans(yh >> 2, yl >> 2, tilenum, | |
| 1705 | 2254 | } |
| 1706 | 2255 | |
| 1707 | 2256 | /*****************************************************************************/ |
| r9854 | r9855 | |
| 1712 | 2261 | |
| 1713 | 2262 | void N64::RDP::Processor::Triangle(bool shade, bool texture, bool zbuffer) |
| 1714 | 2263 | { |
| 1715 | N64::RDP::Triangle tri(m_machine, shade, texture, zbuffer); | |
| 2264 | N64::RDP::Triangle tri(m_machine, shade, texture, zbuffer, false, false); | |
| 1716 | 2265 | tri.Draw(); |
| 1717 | 2266 | } |
| 1718 | 2267 | |
| r9854 | r9855 | |
| 1756 | 2305 | Triangle(true, true, true); |
| 1757 | 2306 | } |
| 1758 | 2307 | |
| 1759 | void N64::RDP:: | |
| 2308 | void N64::RDP::Proc | |
| 1760 | 2309 | { |
| 1761 | m_xl = (data[0] >> 12) & 0xfff; | |
| 1762 | m_yl = (data[0] >> 0) & 0xfff; | |
| 1763 | m_xh = (data[1] >> 12) & 0xfff; | |
| 1764 | m_yh = (data[1] >> 0) & 0xfff; | |
| 1765 | } | |
| 2310 | UINT32 *data = m_cmd_data + m_cmd_cur; | |
| 1766 | 2311 | |
| 1767 | void N64::RDP::TexRectangle::InitFromBuffer(UINT32 *data) | |
| 1768 | { | |
| 1769 | m_tilenum = (data[1] >> 24) & 0x7; | |
| 1770 | m_xl = (data[0] >> 12) & 0xfff; | |
| 1771 | m_yl = (data[0] >> 0) & 0xfff; | |
| 1772 | m_xh = (data[1] >> 12) & 0xfff; | |
| 1773 | m_yh = (data[1] >> 0) & 0xfff; | |
| 1774 | m_s = (data[2] >> 16) & 0xffff; | |
| 1775 | m_t = (data[2] >> 0) & 0xffff; | |
| 1776 | m_dsdx = (data[3] >> 16) & 0xffff; | |
| 1777 | m_dtdy = (data[3] >> 0) & 0xffff; | |
| 1778 | } | |
| 2312 | UINT32 w3 = data[2]; | |
| 2313 | UINT32 w4 = data[3]; | |
| 1779 | 2314 | |
| 1780 | void N64::RDP::Processor::CmdTexRect(UINT32 w1, UINT32 w2) | |
| 1781 | { | |
| 1782 | N64::RDP::TexRectangle rect(m_machine, m_cmd_data + m_cmd_cur, 0); | |
| 1783 | rect.Draw(); | |
| 2315 | UINT32 tilenum = (w2 >> 24) & 0x7; | |
| 2316 | UINT32 xl = (w1 >> 12) & 0xfff; | |
| 2317 | UINT32 yl = (w1 >> 0) & 0xfff; | |
| 2318 | UINT32 xh = (w2 >> 12) & 0xfff; | |
| 2319 | UINT32 yh = (w2 >> 0) & 0xfff; | |
| 2320 | INT32 s = (w3 >> 16) & 0xffff; | |
| 2321 | INT32 t = (w3 >> 0) & 0xffff; | |
| 2322 | INT32 dsdx = (w4 >> 16) & 0xffff; | |
| 2323 | INT32 dtdy = (w4 >> 0) & 0xffff; | |
| 2324 | ||
| 2325 | dsdx = SIGN16(dsdx); | |
| 2326 | dtdy = SIGN16(dtdy); | |
| 2327 | ||
| 2328 | if (m_other_modes.cycle_type == CYCLE_TYPE_FILL || m_other_modes.cycle_type == CYCLE_TYPE_COPY) | |
| 2329 | { | |
| 2330 | yl |= 3; | |
| 2331 | } | |
| 2332 | ||
| 2333 | UINT32 xlint = (xl >> 2) & 0x3ff; | |
| 2334 | UINT32 xhint = (xh >> 2) & 0x3ff; | |
| 2335 | ||
| 2336 | UINT32* ewdata = GetTempRectData(); | |
| 2337 | ewdata[0] = (0x24 << 24) | ((0x80 | tilenum) << 16) | yl; // command, flipped, tile, yl | |
| 2338 | ewdata[1] = (yl << 16) | yh; // ym, yh | |
| 2339 | ewdata[2] = (xlint << 16) | ((xl & 3) << 14); // xl, xl frac | |
| 2340 | ewdata[3] = 0; // dxldy, dxldy frac | |
| 2341 | ewdata[4] = (xhint << 16) | ((xh & 3) << 14); // xh, xh frac | |
| 2342 | ewdata[5] = 0; // dxhdy, dxhdy frac | |
| 2343 | ewdata[6] = (xlint << 16) | ((xl & 3) << 14); // xm, xm frac | |
| 2344 | ewdata[7] = 0; // dxmdy, dxmdy frac | |
| 2345 | memset(&ewdata[8], 0, 16 * sizeof(UINT32)); // shade | |
| 2346 | ewdata[24] = (s << 16) | t; // s, t | |
| 2347 | ewdata[25] = 0; // w | |
| 2348 | ewdata[26] = ((dsdx >> 5) << 16); // dsdx, dtdx | |
| 2349 | ewdata[27] = 0; // dwdx | |
| 2350 | ewdata[28] = 0; // s frac, t frac | |
| 2351 | ewdata[29] = 0; // w frac | |
| 2352 | ewdata[30] = ((dsdx & 0x1f) << 11) << 16; // dsdx frac, dtdx frac | |
| 2353 | ewdata[31] = 0; // dwdx frac | |
| 2354 | ewdata[32] = (dtdy >> 5) & 0xffff;//dsde, dtde | |
| 2355 | ewdata[33] = 0;//dwde | |
| 2356 | ewdata[34] = (dtdy >> 5) & 0xffff;//dsdy, dtdy | |
| 2357 | ewdata[35] = 0;//dwdy | |
| 2358 | ewdata[36] = (dtdy & 0x1f) << 11;//dsde frac, dtde frac | |
| 2359 | ewdata[37] = 0;//dwde frac | |
| 2360 | ewdata[38] = (dtdy & 0x1f) << 11;//dsdy frac, dtdy frac | |
| 2361 | ewdata[39] = 0;//dwdy frac | |
| 2362 | memset(&ewdata[40], 0, 4 * sizeof(UINT32));//depth | |
| 2363 | ||
| 2364 | N64::RDP::Triangle tri(m_machine, true, true, false, true, false); | |
| 2365 | tri.Draw(); | |
| 1784 | 2366 | } |
| 1785 | 2367 | |
| 1786 | 2368 | void N64::RDP::Processor::CmdTexRectFlip(UINT32 w1, UINT32 w2) |
| 1787 | 2369 | { |
| 1788 | N64::RDP::TexRectangle rect(m_machine, m_cmd_data + m_cmd_cur, 1); | |
| 1789 | rect.Draw(); | |
| 2370 | UINT32 *data = m_cmd_data + m_cmd_cur; | |
| 2371 | ||
| 2372 | UINT32 w3 = data[2]; | |
| 2373 | UINT32 w4 = data[3]; | |
| 2374 | ||
| 2375 | UINT32 tilenum = (w2 >> 24) & 0x7; | |
| 2376 | UINT32 xl = (w1 >> 12) & 0xfff; | |
| 2377 | UINT32 yl = (w1 >> 0) & 0xfff; | |
| 2378 | UINT32 xh = (w2 >> 12) & 0xfff; | |
| 2379 | UINT32 yh = (w2 >> 0) & 0xfff; | |
| 2380 | INT32 s = (w3 >> 16) & 0xffff; | |
| 2381 | INT32 t = (w3 >> 0) & 0xffff; | |
| 2382 | INT32 dsdx = (w4 >> 16) & 0xffff; | |
| 2383 | INT32 dtdy = (w4 >> 0) & 0xffff; | |
| 2384 | ||
| 2385 | dsdx = SIGN16(dsdx); | |
| 2386 | dtdy = SIGN16(dtdy); | |
| 2387 | ||
| 2388 | if (m_other_modes.cycle_type == CYCLE_TYPE_FILL || m_other_modes.cycle_type == CYCLE_TYPE_COPY) | |
| 2389 | { | |
| 2390 | yl |= 3; | |
| 2391 | } | |
| 2392 | ||
| 2393 | UINT32 xlint = (xl >> 2) & 0x3ff; | |
| 2394 | UINT32 xhint = (xh >> 2) & 0x3ff; | |
| 2395 | ||
| 2396 | UINT32* ewdata = GetTempRectData(); | |
| 2397 | ewdata[0] = (0x25 << 24) | ((0x80 | tilenum) << 16) | yl;//command, flipped, tile, yl | |
| 2398 | ewdata[1] = (yl << 16) | yh;//ym, yh | |
| 2399 | ewdata[2] = (xlint << 16) | ((xl & 3) << 14);//xl, xl frac | |
| 2400 | ewdata[3] = 0;//dxldy, dxldy frac | |
| 2401 | ewdata[4] = (xhint << 16) | ((xh & 3) << 14);//xh, xh frac | |
| 2402 | ewdata[5] = 0;//dxhdy, dxhdy frac | |
| 2403 | ewdata[6] = (xlint << 16) | ((xl & 3) << 14);//xm, xm frac | |
| 2404 | ewdata[7] = 0;//dxmdy, dxmdy frac | |
| 2405 | memset(&ewdata[8], 0, 16 * sizeof(UINT32));//shade | |
| 2406 | ewdata[24] = (s << 16) | t;//s, t | |
| 2407 | ewdata[25] = 0;//w | |
| 2408 | ewdata[26] = (dtdy >> 5) & 0xffff;//dsdx, dtdx | |
| 2409 | ewdata[27] = 0;//dwdx | |
| 2410 | ewdata[28] = 0;//s frac, t frac | |
| 2411 | ewdata[29] = 0;//w frac | |
| 2412 | ewdata[30] = ((dtdy & 0x1f) << 11);//dsdx frac, dtdx frac | |
| 2413 | ewdata[31] = 0;//dwdx frac | |
| 2414 | ewdata[32] = (dsdx >> 5) << 16;//dsde, dtde | |
| 2415 | ewdata[33] = 0;//dwde | |
| 2416 | ewdata[34] = (dsdx >> 5) << 16;//dsdy, dtdy | |
| 2417 | ewdata[35] = 0;//dwdy | |
| 2418 | ewdata[36] = (dsdx & 0x1f) << 27;//dsde frac, dtde frac | |
| 2419 | ewdata[37] = 0;//dwde frac | |
| 2420 | ewdata[38] = (dsdx & 0x1f) << 27;//dsdy frac, dtdy frac | |
| 2421 | ewdata[39] = 0;//dwdy frac | |
| 2422 | memset(&ewdata[40], 0, 4 * sizeof(UINT32));//depth | |
| 2423 | ||
| 2424 | N64::RDP::Triangle tri(m_machine, true, true, false, true, false); | |
| 2425 | tri.Draw(); | |
| 1790 | 2426 | } |
| 1791 | 2427 | |
| 1792 | 2428 | void N64::RDP::Processor::CmdSyncLoad(UINT32 w1, UINT32 w2) |
| r9854 | r9855 | |
| 1861 | 2497 | |
| 1862 | 2498 | void N64::RDP::Processor::CmdSetOtherModes(UINT32 w1, UINT32 w2) |
| 1863 | 2499 | { |
| 1864 | m_other_modes.cycle_type = (w1 >> 20) & 0x3; | |
| 1865 | m_other_modes.persp_tex_en = (w1 & 0x80000) ? true : false; | |
| 1866 | m_other_modes.detail_tex_en = (w1 & 0x40000) ? true : false; | |
| 1867 | m_other_modes.sharpen_tex_en = (w1 & 0x20000) ? true : false; | |
| 1868 | m_other_modes.tex_lod_en = (w1 & 0x10000) ? true : false; | |
| 1869 | m_other_modes.en_tlut = (w1 & 0x08000) ? true : false; | |
| 1870 | m_other_modes.tlut_type = (w1 & 0x04000) ? true : false; | |
| 1871 | m_other_modes.sample_type = (w1 & 0x02000) ? true : false; | |
| 1872 | m_other_modes.mid_texel = (w1 & 0x01000) ? true : false; | |
| 1873 | m_other_modes.bi_lerp0 = (w1 & 0x00800) ? true : false; | |
| 1874 | m_other_modes.bi_lerp1 = (w1 & 0x00400) ? true : false; | |
| 1875 | m_other_modes.convert_one = (w1 & 0x00200) ? true : false; | |
| 1876 | m_other_modes.key_en = (w1 & 0x00100) ? true : false; | |
| 1877 | m_other_modes.rgb_dither_sel = (w1 >> 6) & 0x3; | |
| 1878 | m_other_modes.alpha_dither_sel = (w1 >> 4) & 0x3; | |
| 1879 | m_other_modes.blend_m1a_0 = (w2 >> 30) & 0x3; | |
| 1880 | m_other_modes.blend_m1a_1 = (w2 >> 28) & 0x3; | |
| 1881 | m_other_modes.blend_m1b_0 = (w2 >> 26) & 0x3; | |
| 1882 | m_other_modes.blend_m1b_1 = (w2 >> 24) & 0x3; | |
| 1883 | m_other_modes.blend_m2a_0 = (w2 >> 22) & 0x3; | |
| 1884 | m_other_modes.blend_m2a_1 = (w2 >> 20) & 0x3; | |
| 1885 | m_other_modes.blend_m2b_0 = (w2 >> 18) & 0x3; | |
| 1886 | m_other_modes.blend_m2b_1 = (w2 >> 16) & 0x3; | |
| 1887 | m_other_modes.force_blend = (w2 & 0x4000) ? true : false; | |
| 1888 | m_other_modes.alpha_cvg_select = (w2 & 0x2000) ? true : false; | |
| 1889 | m_other_modes.cvg_times_alpha = (w2 & 0x1000) ? true : false; | |
| 1890 | m_other_modes.z_mode = (w2 >> 10) & 0x3; | |
| 1891 | m_other_modes.cvg_dest = (w2 >> 8) & 0x3; | |
| 1892 | m_other_modes.color_on_cvg = (w2 & 0x80) ? true : false; | |
| 1893 | m_other_modes.image_read_en = (w2 & 0x40) ? true : false; | |
| 1894 | m_other_modes.z_update_en = (w2 & 0x20) ? true : false; | |
| 1895 | m_other_modes.z_compare_en = (w2 & 0x10) ? true : false; | |
| 1896 | m_other_modes.antialias_en = (w2 & 0x08) ? true : false; | |
| 1897 | m_other_modes.z_source_sel = (w2 & 0x04) ? true : false; | |
| 1898 | m_other_modes.dither_alpha_en = (w2 & 0x02) ? true : false; | |
| 1899 | m_other_modes.alpha_compare_en = (w2 & 0x01) ? true : false; | |
| 2500 | m_other_modes.cycle_type = (w1 >> 20) & 0x3; // 01 | |
| 2501 | m_other_modes.persp_tex_en = (w1 & 0x80000) ? 1 : 0; // 1 | |
| 2502 | m_other_modes.detail_tex_en = (w1 & 0x40000) ? 1 : 0; // 0 | |
| 2503 | m_other_modes.sharpen_tex_en = (w1 & 0x20000) ? 1 : 0; // 0 | |
| 2504 | m_other_modes.tex_lod_en = (w1 & 0x10000) ? 1 : 0; // 0 | |
| 2505 | m_other_modes.en_tlut = (w1 & 0x08000) ? 1 : 0; // 0 | |
| 2506 | m_other_modes.tlut_type = (w1 & 0x04000) ? 1 : 0; // 0 | |
| 2507 | m_other_modes.sample_type = (w1 & 0x02000) ? 1 : 0; // 1 | |
| 2508 | m_other_modes.mid_texel = (w1 & 0x01000) ? 1 : 0; // 0 | |
| 2509 | m_other_modes.bi_lerp0 = (w1 & 0x00800) ? 1 : 0; // 1 | |
| 2510 | m_other_modes.bi_lerp1 = (w1 & 0x00400) ? 1 : 0; // 1 | |
| 2511 | m_other_modes.convert_one = (w1 & 0x00200) ? 1 : 0; // 0 | |
| 2512 | m_other_modes.key_en = (w1 & 0x00100) ? 1 : 0; // 0 | |
| 2513 | m_other_modes.rgb_dither_sel = (w1 >> 6) & 0x3; // 00 | |
| 2514 | m_other_modes.alpha_dither_sel = (w1 >> 4) & 0x3; // 01 | |
| 2515 | m_other_modes.blend_m1a_0 = (w2 >> 30) & 0x3; // 11 | |
| 2516 | m_other_modes.blend_m1a_1 = (w2 >> 28) & 0x3; // 00 | |
| 2517 | m_other_modes.blend_m1b_0 = (w2 >> 26) & 0x3; // 10 | |
| 2518 | m_other_modes.blend_m1b_1 = (w2 >> 24) & 0x3; // 00 | |
| 2519 | m_other_modes.blend_m2a_0 = (w2 >> 22) & 0x3; // 00 | |
| 2520 | m_other_modes.blend_m2a_1 = (w2 >> 20) & 0x3; // 01 | |
| 2521 | m_other_modes.blend_m2b_0 = (w2 >> 18) & 0x3; // 00 | |
| 2522 | m_other_modes.blend_m2b_1 = (w2 >> 16) & 0x3; // 01 | |
| 2523 | m_other_modes.force_blend = (w2 >> 14) & 1; // 0 | |
| 2524 | m_other_modes.alpha_cvg_select = (w2 >> 13) & 1; // 1 | |
| 2525 | m_other_modes.cvg_times_alpha = (w2 >> 12) & 1; // 0 | |
| 2526 | m_other_modes.z_mode = (w2 >> 10) & 0x3; // 00 | |
| 2527 | m_other_modes.cvg_dest = (w2 >> 8) & 0x3; // 00 | |
| 2528 | m_other_modes.color_on_cvg = (w2 >> 7) & 1; // 0 | |
| 2529 | m_other_modes.image_read_en = (w2 >> 6) & 1; // 1 | |
| 2530 | m_other_modes.z_update_en = (w2 >> 5) & 1; // 1 | |
| 2531 | m_other_modes.z_compare_en = (w2 >> 4) & 1; // 1 | |
| 2532 | m_other_modes.antialias_en = (w2 >> 3) & 1; // 1 | |
| 2533 | m_other_modes.z_source_sel = (w2 >> 2) & 1; // 0 | |
| 2534 | m_other_modes.dither_alpha_en = (w2 >> 1) & 1; // 0 | |
| 2535 | m_other_modes.alpha_compare_en = (w2) & 1; // 0 | |
| 1900 | 2536 | |
| 1901 | 2537 | // These should belong to the Blender class |
| 1902 | 2538 | SetBlenderInput(0, 0, &m_color_inputs.blender1a_r[0], &m_color_inputs.blender1a_g[0], &m_color_inputs.blender1a_b[0], &m_color_inputs.blender1b_a[0], m_other_modes.blend_m1a_0, m_other_modes.blend_m1b_0); |
| 1903 | 2539 | SetBlenderInput(0, 1, &m_color_inputs.blender2a_r[0], &m_color_inputs.blender2a_g[0], &m_color_inputs.blender2a_b[0], &m_color_inputs.blender2b_a[0], m_other_modes.blend_m2a_0, m_other_modes.blend_m2b_0); |
| 1904 | 2540 | SetBlenderInput(1, 0, &m_color_inputs.blender1a_r[1], &m_color_inputs.blender1a_g[1], &m_color_inputs.blender1a_b[1], &m_color_inputs.blender1b_a[1], m_other_modes.blend_m1a_1, m_other_modes.blend_m1b_1); |
| 1905 | 2541 | SetBlenderInput(1, 1, &m_color_inputs.blender2a_r[1], &m_color_inputs.blender2a_g[1], &m_color_inputs.blender2a_b[1], &m_color_inputs.blender2b_a[1], m_other_modes.blend_m2a_1, m_other_modes.blend_m2b_1); |
| 1906 | m_misc_state.m_special_bsel0 = (m_color_inputs.blender2b_a[0] == &m_memory_color.i.a) ? 2 : 0; | |
| 1907 | m_misc_state.m_special_bsel1 = (m_color_inputs.blender2b_a[1] == &m_memory_color.i.a) ? 2 : 0; | |
| 1908 | 2542 | } |
| 1909 | 2543 | |
| 1910 | 2544 | void N64::RDP::Processor::CmdLoadTLUT(UINT32 w1, UINT32 w2) |
| 1911 | 2545 | { |
| 1912 | const int tilenum = (w2 >> 24) & 7; | |
| 1913 | N64::RDP::Tile* tex_tile = &m_tiles[tilenum]; | |
| 2546 | Tile* tile = GetTiles(); | |
| 1914 | 2547 | |
| 1915 | int sl = tex_tile->sl = (w1 >> 12) & 0xfff; | |
| 1916 | int tl = tex_tile->tl = (w1 >> 0) & 0xfff; | |
| 1917 | int sh = tex_tile->sh = (w2 >> 12) & 0xfff; | |
| 2548 | int tilenum = (w2 >> 24) & 0x7; | |
| 2549 | int sl = tile[tilenum].sl = ((w1 >> 12) & 0xfff); | |
| 2550 | int tl = tile[tilenum].tl = w1 & 0xfff; | |
| 2551 | int sh = tile[tilenum].sh = ((w2 >> 12) & 0xfff); | |
| 2552 | int th = tile[tilenum].th = w2 & 0xfff; | |
| 1918 | 2553 | |
| 2554 | if (tl != th) | |
| 2555 | { | |
| 2556 | fatalerror("Load tlut: tl=%d, th=%d",tl,th); | |
| 2557 | } | |
| 2558 | ||
| 2559 | int count = (sh >> 2) - (sl >> 2) + 1; | |
| 2560 | count <<= 2; | |
| 2561 | ||
| 1919 | 2562 | switch (m_misc_state.m_ti_size) |
| 1920 | 2563 | { |
| 1921 | 2564 | case PIXEL_SIZE_16BIT: |
| 1922 | 2565 | { |
| 1923 | UINT16 *src = (UINT16*)rdram; | |
| 2566 | if (tile[tilenum].tmem < 256) | |
| 2567 | { | |
| 2568 | fatalerror("rdp_load_tlut: loading tlut into low half at %d qwords",tile[tilenum].tmem); | |
| 2569 | } | |
| 1924 | 2570 | UINT32 srcstart = (m_misc_state.m_ti_address + (tl >> 2) * (m_misc_state.m_ti_width << 1) + (sl >> 1)) >> 1; |
| 1925 | UINT16 *dst = (UINT16*)&m_tmem[tex_tile->tmem]; | |
| 1926 | int count = ((sh >> 2) - (sl >> 2)) + 1; | |
| 2571 | UINT16 *dst = GetTMEM16(); | |
| 2572 | UINT32 dststart = tile[tilenum].tmem << 2; | |
| 1927 | 2573 | |
| 1928 | for (int i = 0; i < count; i+ | |
| 2574 | for (int i = 0; i < count; i += 4) | |
| 1929 | 2575 | { |
| 1930 | if( | |
| 2576 | if (dststart < 20 | |
| 1931 | 2577 | { |
| 1932 | dst[i*4] = src[(srcstart + i) ^ WORD_ADDR_XOR]; | |
| 1933 | dst[i*4+1] = 0; | |
| 1934 | dst[i*4+2] = 0; | |
| 1935 | dst[i*4+3] = 0; | |
| 2578 | dst[dststart] = RREADIDX16(srcstart); | |
| 2579 | dst[dststart + 1] = dst[dststart]; | |
| 2580 | dst[dststart + 2] = dst[dststart]; | |
| 2581 | dst[dststart + 3] = dst[dststart]; | |
| 2582 | dststart += 4; | |
| 2583 | srcstart += 1; | |
| 1936 | 2584 | } |
| 1937 | 2585 | } |
| 1938 | 2586 | break; |
| 1939 | 2587 | } |
| 1940 | default: fatalerror("RDP: | |
| 2588 | default: fatalerror("RDP: load_tlut: size = %d\n", m_misc_state.m_ti_size); | |
| 1941 | 2589 | } |
| 1942 | 2590 | } |
| 1943 | 2591 | |
| r9854 | r9855 | |
| 1953 | 2601 | |
| 1954 | 2602 | void N64::RDP::Processor::CmdLoadBlock(UINT32 w1, UINT32 w2) |
| 1955 | 2603 | { |
| 1956 | const int tilenum = (w2 >> 24) & 0x7; | |
| 1957 | const UINT32 ti_address2 = m_misc_state.m_ti_address - ((m_misc_state.m_ti_address & 3) ? 4 : 0); | |
| 1958 | UINT16 *ram16 = (UINT16*)rdram; | |
| 1959 | int ti_width2 = m_misc_state.m_ti_width; | |
| 1960 | int slindwords = 0; | |
| 2604 | Tile* tile = GetTiles(); | |
| 1961 | 2605 | |
| 1962 | UINT32 sl = m_tiles[tilenum].sl = ((w1 >> 12) & 0xfff); | |
| 1963 | UINT32 tl = m_tiles[tilenum].tl = ((w1 >> 0) & 0xfff); | |
| 1964 | UINT32 sh = m_tiles[tilenum].sh = ((w2 >> 12) & 0xfff); | |
| 1965 | UINT32 dxt = ((w2 >> 0) & 0xfff); | |
| 2606 | int tilenum = (w2 >> 24) & 0x7; | |
| 2607 | UINT16* tc = GetTMEM16(); | |
| 1966 | 2608 | |
| 1967 | int width = (sh - sl) + 1; | |
| 2609 | UINT16 sl, sh, tl; | |
| 2610 | tile[tilenum].sl = sl = ((w1 >> 12) & 0xfff); | |
| 2611 | tile[tilenum].tl = tl = ((w1 >> 0) & 0xfff); | |
| 2612 | tile[tilenum].sh = sh = ((w2 >> 12) & 0xfff); | |
| 2613 | UINT16 dxt = ((w2 >> 0) & 0xfff); | |
| 1968 | 2614 | |
| 1969 | if ( | |
| 2615 | if (s | |
| 1970 | 2616 | { |
| 1971 | | |
| 2617 | fa | |
| 1972 | 2618 | } |
| 1973 | 2619 | |
| 1974 | if ((m_misc_state.m_ti_address & 3) && (m_misc_state.m_ti_address & 0xffffff00) != 0xf8a00) | |
| 2620 | INT32 width = (sh - sl) + 1; | |
| 2621 | ||
| 2622 | width = (width << m_misc_state.m_ti_size) >> 1; | |
| 2623 | if (width & 7) | |
| 1975 | 2624 | { |
| 1976 | | |
| 2625 | width | |
| 1977 | 2626 | } |
| 2627 | width >>= 3; | |
| 1978 | 2628 | |
| 1979 | UINT32* src = (UINT32*)&ram16[ti_address2 >> 1]; | |
| 1980 | UINT32* tc = GetTMEM32(); | |
| 1981 | UINT32 tb = m_tiles[tilenum].tmem >> 2; | |
| 2629 | UINT32 tb = tile[tilenum].tmem << 2; | |
| 1982 | 2630 | |
| 1983 | slindwords = sl; | |
| 2631 | int tiwinwords = m_misc_state.m_ti_width; | |
| 2632 | UINT32 slinwords = sl; | |
| 1984 | 2633 | |
| 1985 | switch (m_misc_state.m_ti_size) // slindwords Neededby Vigilante 8 | |
| 1986 | { | |
| 1987 | case PIXEL_SIZE_4BIT: ti_width2 >>= 1; slindwords >>= 3; width >>= 1; break; | |
| 1988 | case PIXEL_SIZE_8BIT: slindwords >>= 2; break; | |
| 1989 | case PIXEL_SIZE_16BIT: ti_width2 <<= 1; slindwords >>= 1; width <<= 1; break; | |
| 1990 | case PIXEL_SIZE_32BIT: ti_width2 <<= 2; width <<= 2; break; | |
| 1991 | } | |
| 2634 | tiwinwords = (tiwinwords << m_misc_state.m_ti_size) >> 2; | |
| 2635 | slinwords = (slinwords << m_misc_state.m_ti_size) >> 2; | |
| 1992 | 2636 | |
| 1993 | if ((tb + (width >> 2)) > 0x400) | |
| 1994 | { | |
| 1995 | width = 0x1000 - tb*4; // Hack for Magical Tetris Challenge | |
| 1996 | } | |
| 2637 | int ptr = 0, srcptr = 0; | |
| 2638 | UINT16 first, sec; | |
| 2639 | UINT32 src = (m_misc_state.m_ti_address >> 1) + (tl * tiwinwords) + slinwords; | |
| 1997 | 2640 | |
| 1998 | if (width & 7) // Sigh... another Rat Attack-specific thing. | |
| 1999 | { | |
| 2000 | width = (width & (~7)) + 8; | |
| 2001 | } | |
| 2002 | ||
| 2003 | 2641 | if (dxt != 0) |
| 2004 | 2642 | { |
| 2005 | 2643 | int j = 0; |
| 2006 | 2644 | int t = 0; |
| 2007 | 2645 | int oldt = 0; |
| 2008 | int ptr; | |
| 2009 | int xorval = (m_misc_state.m_fb_size == PIXEL_SIZE_16BIT && | |
| 2010 | m_misc_state.m_ti_size == PIXEL_SIZE_32BIT ) ? 2 : 1; // Wave Race-specific | |
| 2011 | UINT32 srcstart = ((tl * ti_width2) >> 2) + slindwords; | |
| 2012 | src = &src[srcstart]; | |
| 2013 | for (int i = 0; i < (width >> 2); i += 2) | |
| 2646 | ||
| 2647 | if (tile[tilenum].size != PIXEL_SIZE_32BIT && tile[tilenum].format != FORMAT_YUV) | |
| 2014 | 2648 | { |
| 2015 | oldt = t; | |
| 2016 | t = ((j >> 11) & 1) ? xorval : 0; | |
| 2017 | if (t > oldt) | |
| 2649 | for (int i = 0; i < width; i ++) | |
| 2018 | 2650 | { |
| 2019 | i += ((m_tiles[tilenum].line >> 3) << 1); | |
| 2651 | oldt = t; | |
| 2652 | t = ((j >> 11) & 1) ? WORD_XOR_DWORD_SWAP : WORD_ADDR_XOR; | |
| 2653 | if (t != oldt) | |
| 2654 | { | |
| 2655 | i += tile[tilenum].line; | |
| 2656 | } | |
| 2657 | ||
| 2658 | ptr = tb + (i << 2); | |
| 2659 | srcptr = src + (i << 2); | |
| 2660 | ||
| 2661 | tc[(ptr ^ t) & 0x7ff] = RREADIDX16(srcptr); | |
| 2662 | tc[((ptr + 1) ^ t) & 0x7ff] = RREADIDX16(srcptr + 1); | |
| 2663 | tc[((ptr + 2) ^ t) & 0x7ff] = RREADIDX16(srcptr + 2); | |
| 2664 | tc[((ptr + 3) ^ t) & 0x7ff] = RREADIDX16(srcptr + 3); | |
| 2665 | j += dxt; | |
| 2020 | 2666 | } |
| 2021 | ptr = tb + i; | |
| 2022 | tc[ptr & 0x3ff] = src[i ^ t]; | |
| 2023 | tc[(ptr + 1) & 0x3ff] = src[(i + 1) ^ t]; | |
| 2024 | j += dxt; | |
| 2025 | 2667 | } |
| 2026 | m_tiles[tilenum].th = tl + (j >> 11); | |
| 2668 | else if (tile[tilenum].format == FORMAT_YUV) | |
| 2669 | { | |
| 2670 | for (int i = 0; i < width; i ++) | |
| 2671 | { | |
| 2672 | oldt = t; | |
| 2673 | t = ((j >> 11) & 1) ? WORD_XOR_DWORD_SWAP : WORD_ADDR_XOR; | |
| 2674 | if (t != oldt) | |
| 2675 | { | |
| 2676 | i += tile[tilenum].line; | |
| 2677 | } | |
| 2678 | ||
| 2679 | ptr = ((tb + (i << 1)) ^ t) & 0x3ff; | |
| 2680 | srcptr = src + (i << 2); | |
| 2681 | ||
| 2682 | first = RREADIDX16(srcptr); | |
| 2683 | sec = RREADIDX16(srcptr + 1); | |
| 2684 | tc[ptr] = ((first >> 8) << 8) | (sec >> 8); | |
| 2685 | tc[ptr | 0x400] = ((first & 0xff) << 8) | (sec & 0xff); | |
| 2686 | ||
| 2687 | ptr = ((tb + (i << 1) + 1) ^ t) & 0x3ff; | |
| 2688 | first = RREADIDX16(srcptr + 2); | |
| 2689 | sec = RREADIDX16(srcptr + 3); | |
| 2690 | tc[ptr] = ((first >> 8) << 8) | (sec >> 8); | |
| 2691 | tc[ptr | 0x400] = ((first & 0xff) << 8) | (sec & 0xff); | |
| 2692 | ||
| 2693 | j += dxt; | |
| 2694 | } | |
| 2695 | } | |
| 2696 | else | |
| 2697 | { | |
| 2698 | for (int i = 0; i < width; i ++) | |
| 2699 | { | |
| 2700 | oldt = t; | |
| 2701 | t = ((j >> 11) & 1) ? WORD_XOR_DWORD_SWAP : WORD_ADDR_XOR; | |
| 2702 | if (t != oldt) | |
| 2703 | i += tile[tilenum].line; | |
| 2704 | ||
| 2705 | ptr = ((tb + (i << 1)) ^ t) & 0x3ff; | |
| 2706 | srcptr = src + (i << 2); | |
| 2707 | tc[ptr] = RREADIDX16(srcptr); | |
| 2708 | tc[ptr | 0x400] = RREADIDX16(srcptr + 1); | |
| 2709 | ||
| 2710 | ptr = ((tb + (i << 1) + 1) ^ t) & 0x3ff; | |
| 2711 | tc[ptr] = RREADIDX16(srcptr + 2); | |
| 2712 | tc[ptr | 0x400] = RREADIDX16(srcptr + 3); | |
| 2713 | ||
| 2714 | j += dxt; | |
| 2715 | } | |
| 2716 | } | |
| 2717 | tile[tilenum].th = tl + (j >> 11); | |
| 2027 | 2718 | } |
| 2028 | else | |
| 2719 | else | |
| 2029 | 2720 | { |
| 2030 | UINT32 srcstart = ((tl * ti_width2) >> 2) + slindwords; | |
| 2031 | memcpy(&tc[tb],&src[srcstart],width); | |
| 2032 | m_tiles[tilenum].th = tl; | |
| 2721 | if (tile[tilenum].size != PIXEL_SIZE_32BIT && tile[tilenum].format != FORMAT_YUV) | |
| 2722 | { | |
| 2723 | for (int i = 0; i < width; i ++) | |
| 2724 | { | |
| 2725 | ptr = tb + (i << 2); | |
| 2726 | srcptr = src + (i << 2); | |
| 2727 | tc[(ptr ^ WORD_ADDR_XOR) & 0x7ff] = RREADIDX16(srcptr); | |
| 2728 | tc[((ptr + 1) ^ WORD_ADDR_XOR) & 0x7ff] = RREADIDX16(srcptr + 1); | |
| 2729 | tc[((ptr + 2) ^ WORD_ADDR_XOR) & 0x7ff] = RREADIDX16(srcptr + 2); | |
| 2730 | tc[((ptr + 3) ^ WORD_ADDR_XOR) & 0x7ff] = RREADIDX16(srcptr + 3); | |
| 2731 | } | |
| 2732 | } | |
| 2733 | else if (tile[tilenum].format == FORMAT_YUV) | |
| 2734 | { | |
| 2735 | for (int i = 0; i < width; i ++) | |
| 2736 | { | |
| 2737 | ptr = ((tb + (i << 1)) ^ WORD_ADDR_XOR) & 0x3ff; | |
| 2738 | srcptr = src + (i << 2); | |
| 2739 | first = RREADIDX16(srcptr); | |
| 2740 | sec = RREADIDX16(srcptr + 1); | |
| 2741 | tc[ptr] = ((first >> 8) << 8) | (sec >> 8);//UV pair | |
| 2742 | tc[ptr | 0x400] = ((first & 0xff) << 8) | (sec & 0xff); | |
| 2743 | ||
| 2744 | ptr = ((tb + (i << 1) + 1) ^ WORD_ADDR_XOR) & 0x3ff; | |
| 2745 | first = RREADIDX16(srcptr + 2); | |
| 2746 | sec = RREADIDX16(srcptr + 3); | |
| 2747 | tc[ptr] = ((first >> 8) << 8) | (sec >> 8); | |
| 2748 | tc[ptr | 0x400] = ((first & 0xff) << 8) | (sec & 0xff); | |
| 2749 | } | |
| 2750 | } | |
| 2751 | else | |
| 2752 | { | |
| 2753 | for (int i = 0; i < width; i ++) | |
| 2754 | { | |
| 2755 | ptr = ((tb + (i << 1)) ^ WORD_ADDR_XOR) & 0x3ff; | |
| 2756 | srcptr = src + (i << 2); | |
| 2757 | tc[ptr] = RREADIDX16(srcptr); | |
| 2758 | tc[ptr | 0x400] = RREADIDX16(srcptr + 1); | |
| 2759 | ||
| 2760 | ptr = ((tb + (i << 1) + 1) ^ WORD_ADDR_XOR) & 0x3ff; | |
| 2761 | tc[ptr] = RREADIDX16(srcptr + 2); | |
| 2762 | tc[ptr | 0x400] = RREADIDX16(srcptr + 3); | |
| 2763 | } | |
| 2764 | } | |
| 2765 | tile[tilenum].th = tl; | |
| 2033 | 2766 | } |
| 2034 | 2767 | } |
| 2035 | 2768 | |
| 2036 | 2769 | void N64::RDP::Processor::CmdLoadTile(UINT32 w1, UINT32 w2) |
| 2037 | 2770 | { |
| 2038 | const int tilenum = (w2 >> 24) & 0x7; | |
| 2039 | N64::RDP::Tile *tex_tile = &m_tiles[tilenum]; | |
| 2040 | int line = tex_tile->line; // Per Ziggy | |
| 2041 | int toppad = 0; | |
| 2771 | Tile* tile = GetTiles(); | |
| 2772 | int tilenum = (w2 >> 24) & 0x7; | |
| 2042 | 2773 | |
| 2043 | if (!line) | |
| 2044 | { | |
| 2045 | return; // Needed by Wipeout 64 | |
| 2046 | } | |
| 2774 | tile[tilenum].sl = ((w1 >> 12) & 0xfff); | |
| 2775 | tile[tilenum].tl = ((w1 >> 0) & 0xfff); | |
| 2776 | tile[tilenum].sh = ((w2 >> 12) & 0xfff); | |
| 2777 | tile[tilenum].th = ((w2 >> 0) & 0xfff); | |
| 2047 | 2778 | |
| 2048 | tex_tile->sl = ((w1 >> 12) & 0xfff); | |
| 2049 | tex_tile->tl = ((w1 >> 0) & 0xfff); | |
| 2050 | tex_tile->sh = ((w2 >> 12) & 0xfff); | |
| 2051 | tex_tile->th = ((w2 >> 0) & 0xfff); | |
| 2779 | UINT16 sl = tile[tilenum].sl >> 2; | |
| 2780 | UINT16 tl = tile[tilenum].tl >> 2; | |
| 2781 | UINT16 sh = tile[tilenum].sh >> 2; | |
| 2782 | UINT16 th = tile[tilenum].th >> 2; | |
| 2052 | 2783 | |
| 2053 | UINT16 sl = tex_tile->sl >> 2; | |
| 2054 | UINT16 tl = tex_tile->tl >> 2; | |
| 2055 | UINT16 sh = tex_tile->sh >> 2; | |
| 2056 | UINT16 th = tex_tile->th >> 2; | |
| 2784 | INT32 width = (sh - sl) + 1; | |
| 2785 | INT32 height = (th - tl) + 1; | |
| 2057 | 2786 | |
| 2058 | int width = (sh - sl) + 1; | |
| 2059 | int height = (th - tl) + 1; | |
| 2060 | ||
| 2787 | int topad; | |
| 2061 | 2788 | if (m_misc_state.m_ti_size < 3) |
| 2062 | 2789 | { |
| 2063 | top | |
| 2790 | top | |
| 2064 | 2791 | } |
| 2065 | 2792 | else |
| 2066 | 2793 | { |
| 2067 | top | |
| 2794 | top | |
| 2068 | 2795 | } |
| 2069 | top | |
| 2796 | top | |
| 2070 | 2797 | |
| 2071 | 2798 | switch (m_misc_state.m_ti_size) |
| 2072 | 2799 | { |
| 2073 | 2800 | case PIXEL_SIZE_8BIT: |
| 2074 | 2801 | { |
| 2075 | UINT | |
| 2802 | UINT32 | |
| 2076 | 2803 | UINT8 *tc = GetTMEM(); |
| 2077 | int tb = | |
| 2804 | int tb = | |
| 2078 | 2805 | |
| 2079 | if (tb + (width * height) > 4096) | |
| 2080 | { | |
| 2081 | height = (4096 - tb) / line; // Per Ziggy | |
| 2082 | } | |
| 2083 | ||
| 2084 | 2806 | for (int j = 0; j < height; j++) |
| 2085 | 2807 | { |
| 2086 | int tline = tb + (te | |
| 2808 | int tline = tb + ((tile[ | |
| 2087 | 2809 | int s = ((j + tl) * m_misc_state.m_ti_width) + sl; |
| 2088 | #define BYTE_XOR_DWORD_SWAP 7 | |
| 2089 | int xorval8 = ((j & 1) ? BYTE_XOR_DWORD_SWAP : BYTE_ADDR_XOR); // Per Ziggy | |
| 2090 | 2810 | |
| 2811 | int xorval8 = ((j & 1) ? BYTE_XOR_DWORD_SWAP : BYTE_ADDR_XOR);//ïîïðîùå,÷åì ó Ziggy | |
| 2091 | 2812 | for (int i = 0; i < width; i++) |
| 2092 | 2813 | { |
| 2093 | tc[(tline + i) ^ xorval8] = | |
| 2814 | tc[((tline + i) ^ xorval8) & 0xfff] = RREADADDR8( | |
| 2094 | 2815 | } |
| 2095 | 2816 | } |
| 2096 | 2817 | break; |
| 2097 | 2818 | } |
| 2098 | 2819 | case PIXEL_SIZE_16BIT: |
| 2099 | 2820 | { |
| 2100 | UINT16 *src = (UINT16*)rdram; | |
| 2101 | UINT32 ti_addr16 = m_misc_state.m_ti_address >> 1; | |
| 2821 | UINT32 src = m_misc_state.m_ti_address >> 1; | |
| 2102 | 2822 | UINT16 *tc = GetTMEM16(); |
| 2103 | int tb = (tex_tile->tmem / 2); | |
| 2104 | int taddr; | |
| 2823 | UINT16 yuvword; | |
| 2105 | 2824 | |
| 2106 | if ( | |
| 2825 | if ( | |
| 2107 | 2826 | { |
| 2108 | height = (2048 - tb) / (line / 2); // Per Ziggy | |
| 2827 | for (int j = 0; j < height; j++) | |
| 2828 | { | |
| 2829 | int tb = tile[tilenum].tmem << 2; | |
| 2830 | int tline = tb + ((tile[tilenum].line << 2) * j); | |
| 2831 | int s = ((j + tl) * m_misc_state.m_ti_width) + sl; | |
| 2832 | int xorval16 = (j & 1) ? WORD_XOR_DWORD_SWAP : WORD_ADDR_XOR; | |
| 2833 | ||
| 2834 | for (int i = 0; i < width; i++) | |
| 2835 | { | |
| 2836 | UINT32 taddr = (tline + i) ^ xorval16; | |
| 2837 | tc[taddr & 0x7ff] = RREADIDX16(src + s + i); | |
| 2838 | } | |
| 2839 | } | |
| 2109 | 2840 | } |
| 2110 | ||
| 2111 | for (int j = 0; j < height; j++) | |
| 2841 | else | |
| 2112 | 2842 | { |
| 2113 | int tline = tb + ((tex_tile->line / 2) * j); | |
| 2114 | int s = 0; | |
| 2115 | int xorval16 = 0; | |
| 2116 | if (tex_tile->format == 1) // Needed by Ogre Battle 64 | |
| 2843 | for (int j = 0; j < height; j++) | |
| 2117 | 2844 | { |
| 2118 | tline = tb + (tex_tile->line * j); | |
| 2119 | } | |
| 2120 | s = ((j + tl) * m_misc_state.m_ti_width) + sl; | |
| 2121 | #define WORD_XOR_DWORD_SWAP 3 | |
| 2122 | xorval16 = (j & 1) ? WORD_XOR_DWORD_SWAP : WORD_ADDR_XOR; | |
| 2845 | int tb = tile[tilenum].tmem << 3; | |
| 2846 | int tline = tb + ((tile[tilenum].line << 3) * j); | |
| 2847 | int s = ((j + tl) * m_misc_state.m_ti_width) + sl; | |
| 2848 | int xorval8 = (j & 1) ? BYTE_XOR_DWORD_SWAP : BYTE_ADDR_XOR; | |
| 2123 | 2849 | |
| 2124 | for (int i = 0; i < width; i++) | |
| 2125 | { | |
| 2126 | taddr = (tline+i) ^ xorval16; | |
| 2127 | if (taddr < 2048) // Needed by World Driver Championship | |
| 2850 | for (int i = 0; i < width; i++) | |
| 2128 | 2851 | { |
| 2129 | tc[taddr] = src[(ti_addr16 + s + i) ^ WORD_ADDR_XOR]; | |
| 2852 | UINT32 taddr = ((tline + i) ^ xorval8) & 0x7ff; | |
| 2853 | yuvword = RREADIDX16(src + s + i); | |
| 2854 | GetTMEM()[taddr] = yuvword >> 8; | |
| 2855 | GetTMEM()[taddr | 0x800] = yuvword & 0xff; | |
| 2130 | 2856 | } |
| 2131 | 2857 | } |
| 2132 | //for (int k=0; k < (topad>>1); k++) // Padding is possibly necessary, not yet known. | |
| 2133 | //{ | |
| 2134 | // tc[((tline+i+k) ^ xorval16] = src[(ti_addr16+s+i) ^ WORD_ADDR_XOR]; | |
| 2135 | //} | |
| 2136 | 2858 | } |
| 2137 | 2859 | break; |
| 2138 | 2860 | } |
| 2139 | 2861 | case PIXEL_SIZE_32BIT: |
| 2140 | 2862 | { |
| 2141 | UINT32 *src = (UINT32*)&rdram[m_misc_state.m_ti_address / 4]; | |
| 2142 | UINT32 *tc = GetTMEM32(); | |
| 2143 | int tb = (tex_tile->tmem / 4); | |
| 2144 | int xorval32 = ((m_misc_state.m_fb_size == PIXEL_SIZE_16BIT) ? 2 : 1); | |
| 2863 | UINT32 src = m_misc_state.m_ti_address >> 2; | |
| 2864 | UINT16 *tc16 = GetTMEM16(); | |
| 2865 | int tb = (tile[tilenum].tmem << 2); | |
| 2145 | 2866 | |
| 2146 | | |
| 2867 | | |
| 2147 | 2868 | { |
| 2148 | height = (1024 - tb) / (line/4); // Per Ziggy | |
| 2149 | } | |
| 2869 | int tline = tb + ((tile[tilenum].line << 2) * j); | |
| 2150 | 2870 | |
| 2151 | for (int j = 0; j < height; j++) | |
| 2152 | { | |
| 2153 | int tline = tb + ((tex_tile->line / 2) * j); | |
| 2154 | 2871 | int s = ((j + tl) * m_misc_state.m_ti_width) + sl; |
| 2155 | int xorval32cur = (j & 1) ? | |
| 2872 | int xorval32cur = (j & 1) ? WORD_XOR_DWORD_SWAP : WORD_ADDR_XOR; | |
| 2156 | 2873 | for (int i = 0; i < width; i++) |
| 2157 | 2874 | { |
| 2158 | tc[(tline + i) ^ xorval32cur] = src[s + i]; | |
| 2875 | UINT32 c = RREADIDX32(src + s + i); | |
| 2876 | UINT32 ptr = ((tline + i) ^ xorval32cur) & 0x3ff; | |
| 2877 | tc16[ptr] = c >> 16; | |
| 2878 | tc16[ptr | 0x400] = c & 0xffff; | |
| 2159 | 2879 | } |
| 2160 | 2880 | } |
| 2161 | 2881 | break; |
| r9854 | r9855 | |
| 2172 | 2892 | |
| 2173 | 2893 | tex_tile->format = (w1 >> 21) & 0x7; |
| 2174 | 2894 | tex_tile->size = (w1 >> 19) & 0x3; |
| 2175 | tex_tile->line = ((w1 >> 9) & 0x1ff) * 8; | |
| 2176 | tex_tile->tmem = ((w1 >> 0) & 0x1ff) * 8; | |
| 2895 | tex_tile->line = (w1 >> 9) & 0x1ff; | |
| 2896 | tex_tile->tmem = (w1 >> 0) & 0x1ff; | |
| 2177 | 2897 | tex_tile->palette = (w2 >> 20) & 0xf; |
| 2178 | 2898 | tex_tile->ct = (w2 >> 19) & 0x1; |
| 2179 | 2899 | tex_tile->mt = (w2 >> 18) & 0x1; |
| r9854 | r9855 | |
| 2183 | 2903 | tex_tile->ms = (w2 >> 8) & 0x1; |
| 2184 | 2904 | tex_tile->mask_s = (w2 >> 4) & 0xf; |
| 2185 | 2905 | tex_tile->shift_s = (w2 >> 0) & 0xf; |
| 2186 | ||
| 2187 | tex_tile->mask_s = (tex_tile->mask_s > 10) ? 10 : tex_tile->mask_s; | |
| 2188 | tex_tile->mask_t = (tex_tile->mask_t > 10) ? 10 : tex_tile->mask_t; | |
| 2189 | 2906 | } |
| 2190 | 2907 | |
| 2191 | 2908 | void N64::RDP::Processor::CmdFillRect(UINT32 w1, UINT32 w2) |
| 2192 | 2909 | { |
| 2193 | N64::RDP::Rectangle rect(m_machine, m_cmd_data + m_cmd_cur); | |
| 2910 | UINT32 xl = (w1 >> 12) & 0xfff; | |
| 2911 | UINT32 yl = (w1 >> 0) & 0xfff; | |
| 2912 | UINT32 xh = (w2 >> 12) & 0xfff; | |
| 2913 | UINT32 yh = (w2 >> 0) & 0xfff; | |
| 2194 | 2914 | |
| 2195 | rect.Draw(); | |
| 2915 | if (m_other_modes.cycle_type == CYCLE_TYPE_FILL || m_other_modes.cycle_type == CYCLE_TYPE_COPY) | |
| 2916 | { | |
| 2917 | yl |= 3; | |
| 2918 | } | |
| 2919 | ||
| 2920 | UINT32 xlint = (xl >> 2) & 0x3ff; | |
| 2921 | UINT32 xhint = (xh >> 2) & 0x3ff; | |
| 2922 | ||
| 2923 | UINT32* ewdata = GetTempRectData(); | |
| 2924 | ewdata[0] = (0x3680 << 16) | yl;//command, flipped, tile, yl | |
| 2925 | ewdata[1] = (yl << 16) | yh;//ym, yh | |
| 2926 | ewdata[2] = (xlint << 16) | ((xl & 3) << 14);//xl, xl frac | |
| 2927 | ewdata[3] = 0;//dxldy, dxldy frac | |
| 2928 | ewdata[4] = (xhint << 16) | ((xh & 3) << 14);//xh, xh frac | |
| 2929 | ewdata[5] = 0;//dxhdy, dxhdy frac | |
| 2930 | ewdata[6] = (xlint << 16) | ((xl & 3) << 14);//xm, xm frac | |
| 2931 | ewdata[7] = 0;//dxmdy, dxmdy frac | |
| 2932 | memset(&ewdata[8], 0, 36 * sizeof(UINT32));//shade, texture, depth | |
| 2933 | ||
| 2934 | N64::RDP::Triangle tri(m_machine, false, false, false, true, false); | |
| 2935 | tri.Draw(); | |
| 2196 | 2936 | } |
| 2197 | 2937 | |
| 2198 | 2938 | void N64::RDP::Processor::CmdSetFogColor(UINT32 w1, UINT32 w2) |
| r9854 | r9855 | |
| 2408 | 3148 | UINT32 cmd = (m_cmd_data[0] >> 24) & 0x3f; |
| 2409 | 3149 | UINT32 cmd_length = (m_cmd_ptr + 1) * 4; |
| 2410 | 3150 | |
| 3151 | SetStatusReg(GetStatusReg() &~ DP_STATUS_FREEZE); | |
| 3152 | ||
| 2411 | 3153 | // check if more data is needed |
| 2412 | 3154 | if (cmd_length < rdp_command_length[cmd]) |
| 2413 | 3155 | { |
| r9854 | r9855 | |
| 2515 | 3257 | |
| 2516 | 3258 | state->m_rdp.GetFramebuffer()->SetOtherModes(state->m_rdp.GetOtherModes()); |
| 2517 | 3259 | state->m_rdp.GetFramebuffer()->SetMiscState(state->m_rdp.GetMiscState()); |
| 3260 | state->m_rdp.GetFramebuffer()->SetProcessor(&state->m_rdp); | |
| 2518 | 3261 | |
| 2519 | 3262 | state->m_rdp.GetTexPipe()->SetMachine(machine); |
| 2520 | 3263 |
| r9854 | r9855 | |
|---|---|---|
| 5 | 5 | #include "video/rdpblend.h" |
| 6 | 6 | #include "video/rdptri.h" |
| 7 | 7 | #include "video/rdpfb.h" |
| 8 | #include "video/rdpfrect.h" | |
| 9 | #include "video/rdptrect.h" | |
| 10 | 8 | #include "video/rdptpipe.h" |
| 11 | 9 | #include "video/rdpspn16.h" |
| 12 | #include "video/rdpfetch.h" | |
| 13 | 10 | |
| 14 | 11 | /*****************************************************************************/ |
| 15 | 12 | |
| r9854 | r9855 | |
| 37 | 34 | #define XOR_SWAP_WORD 2 |
| 38 | 35 | #define XOR_SWAP_DWORD 1 |
| 39 | 36 | |
| 37 | #define FORMAT_RGBA 0 | |
| 38 | #define FORMAT_YUV 1 | |
| 39 | #define FORMAT_CI 2 | |
| 40 | #define FORMAT_IA 3 | |
| 41 | #define FORMAT_I 4 | |
| 42 | ||
| 43 | #if LSB_FIRST | |
| 44 | #define BYTE_XOR_DWORD_SWAP 7 | |
| 45 | #define WORD_XOR_DWORD_SWAP 3 | |
| 46 | #else | |
| 47 | #define BYTE_XOR_DWORD_SWAP 4 | |
| 48 | #define WORD_XOR_DWORD_SWAP 2 | |
| 49 | #endif | |
| 50 | #define DWORD_XOR_DWORD_SWAP 1 | |
| 51 | ||
| 52 | #define GET_LOW_RGBA16_TMEM(x) (m_rdp->ReplicatedRGBA()[((x) >> 1) & 0x1f]) | |
| 53 | #define GET_MED_RGBA16_TMEM(x) (m_rdp->ReplicatedRGBA()[((x) >> 6) & 0x1f]) | |
| 54 | #define GET_HI_RGBA16_TMEM(x) (m_rdp->ReplicatedRGBA()[((x) >> 11) & 0x1f]) | |
| 55 | ||
| 56 | #define MEM8_LIMIT 0x7fffff | |
| 57 | #define MEM16_LIMIT 0x3fffff | |
| 58 | #define MEM32_LIMIT 0x1fffff | |
| 59 | ||
| 60 | #define RREADADDR8(in) (((in) <= MEM8_LIMIT) ? (((UINT8*)rdram)[(in) ^ BYTE_ADDR_XOR]) : 0) | |
| 61 | #define RREADIDX16(in) (((in) <= MEM16_LIMIT) ? (((UINT16*)rdram)[(in) ^ WORD_ADDR_XOR]) : 0) | |
| 62 | #define RREADIDX32(in) (((in) <= MEM32_LIMIT) ? (rdram[(in)]) : 0) | |
| 63 | ||
| 64 | #define RWRITEADDR8(in, val) {if ((in) <= MEM8_LIMIT) ((UINT8*)rdram)[(in) ^ BYTE_ADDR_XOR] = val;} | |
| 65 | #define RWRITEIDX16(in, val) {if ((in) <= MEM16_LIMIT) ((UINT16*)rdram)[(in) ^ WORD_ADDR_XOR] = val;} | |
| 66 | #define RWRITEIDX32(in, val) {if ((in) <= MEM32_LIMIT) rdram[(in)] = val;} | |
| 67 | ||
| 68 | #define GETLOWCOL(x) (((x) & 0x3e) << 2) | |
| 69 | #define GETMEDCOL(x) (((x) & 0x7c0) >> 3) | |
| 70 | #define GETHICOL(x) (((x) & 0xf800) >> 8) | |
| 71 | ||
| 72 | #define HREADADDR8(in) (((in) <= MEM8_LIMIT) ? (m_rdp->GetHiddenBits()[(in) ^ BYTE_ADDR_XOR]) : 0) | |
| 73 | #define HWRITEADDR8(in, val) {if ((in) <= MEM8_LIMIT) m_rdp->GetHiddenBits()[(in) ^ BYTE_ADDR_XOR] = val;} | |
| 74 | ||
| 40 | 75 | //sign-extension macros |
| 76 | #define SIGN22(x) (((x) & 0x200000) ? ((x) | ~0x3fffff) : ((x) & 0x3fffff)) | |
| 41 | 77 | #define SIGN17(x) (((x) & 0x10000) ? ((x) | ~0x1ffff) : ((x) & 0x1ffff)) |
| 42 | 78 | #define SIGN16(x) (((x) & 0x8000) ? ((x) | ~0xffff) : ((x) & 0xffff)) |
| 79 | #define SIGN13(x) (((x) & 0x1000) ? ((x) | ~0x1fff) : ((x) & 0x1fff)) | |
| 43 | 80 | #define SIGN11(x) (((x) & 0x400) ? ((x) | ~0x7ff) : ((x) & 0x7ff)) |
| 81 | #define SIGN9(x) (((x) & 0x100) ? ((x) | ~0x1ff) : ((x) & 0x1ff)) | |
| 82 | #define SIGN8(x) (((x) & 0x80) ? ((x) | ~0xff) : ((x) & 0xff)) | |
| 44 | 83 | |
| 84 | #define KURT_AKELEY_SIGN9(x) ((((x) & 0x180) == 0x180) ? ((x) | ~0x1ff) : ((x) & 0x1ff)) | |
| 85 | ||
| 45 | 86 | /*****************************************************************************/ |
| 46 | 87 | |
| 47 | 88 | namespace N64 |
| r9854 | r9855 | |
| 86 | 127 | public: |
| 87 | 128 | int format; // Image data format: RGBA, YUV, CI, IA, I |
| 88 | 129 | int size; // Size of texel element: 4b, 8b, 16b, 32b |
| 89 | UINT32 line; // Size of tile line in bytes | |
| 90 | UINT32 tmem; // Starting tmem address for this tile in bytes | |
| 130 | int line; // Size of tile line in bytes | |
| 131 | int tmem; // Starting tmem address for this tile in bytes | |
| 91 | 132 | int palette; // Palette number for 4b CI texels |
| 92 | 133 | int ct, mt, cs, ms; // Clamp / mirror enable bits for S / T direction |
| 93 | 134 | int mask_t, shift_t, mask_s, shift_s; // Mask values / LOD shifts |
| r9854 | r9855 | |
| 101 | 142 | MiscState() |
| 102 | 143 | { |
| 103 | 144 | m_curpixel_cvg = 0; |
| 145 | m_curpixel_memcvg = 0; | |
| 146 | m_curpixel_cvbit = 0; | |
| 104 | 147 | m_curpixel_overlap = 0; |
| 105 | 148 | |
| 106 | 149 | m_max_level = 0; |
| r9854 | r9855 | |
| 121 | 164 | UINT32 m_ti_address; |
| 122 | 165 | |
| 123 | 166 | UINT32 m_curpixel_cvg; |
| 167 | UINT32 m_curpixel_memcvg; | |
| 168 | UINT32 m_curpixel_cvbit; | |
| 124 | 169 | UINT32 m_curpixel_overlap; |
| 125 | 170 | |
| 126 | 171 | UINT8 m_random_seed; |
| r9854 | r9855 | |
| 232 | 277 | UINT8 *blender2b_a[2]; |
| 233 | 278 | }; |
| 234 | 279 | |
| 280 | struct Rectangle | |
| 281 | { | |
| 282 | UINT16 m_xl; // 10.2 fixed-point | |
| 283 | UINT16 m_yl; // 10.2 fixed-point | |
| 284 | UINT16 m_xh; // 10.2 fixed-point | |
| 285 | UINT16 m_yh; // 10.2 fixed-point | |
| 286 | }; | |
| 287 | ||
| 235 | 288 | class Processor |
| 236 | 289 | { |
| 237 | 290 | public: |
| r9854 | r9855 | |
| 245 | 298 | m_current = 0; |
| 246 | 299 | m_status = 0x88; |
| 247 | 300 | |
| 248 | for(int i = 0; i < (1 << 16); i++) | |
| 249 | { | |
| 250 | UINT8 r = ((i >> 8) & 0xf8) | (i >> 13); | |
| 251 | UINT8 g = ((i >> 3) & 0xf8) | ((i >> 8) & 0x07); | |
| 252 | UINT8 b = ((i << 2) & 0xf8) | ((i >> 3) & 0x07); | |
| 253 | UINT8 a = (i & 1) ? 0xff : 0; | |
| 254 | m_rgb16_to_rgb32_lut[i] = (r << 24) | (g << 16) | (b << 8) | a; | |
| 255 | ||
| 256 | r = g = b = (i >> 8) & 0xff; | |
| 257 | a = i & 0xff; | |
| 258 | m_ia8_to_rgb32_lut[i] = (r << 24) | (g << 16) | (b << 8) | a; | |
| 259 | } | |
| 260 | ||
| 261 | for(int i = 0; i < (1 << 24); i++) | |
| 262 | { | |
| 263 | UINT8 A = (i >> 16) & 0x000000ff; | |
| 264 | UINT8 B = (i >> 8) & 0x000000ff; | |
| 265 | UINT8 C = i & 0x000000ff; | |
| 266 | m_cc_lut1[i] = (INT16)((((((INT32)A - (INT32)B) * (INT32)C) + 0x80) >> 8) & 0x0000ffff); | |
| 267 | } | |
| 268 | ||
| 269 | for(int i = 0; i < (1 << 16); i++) | |
| 270 | { | |
| 271 | for(int j = 0; j < (1 << 8); j++) | |
| 272 | { | |
| 273 | INT32 temp = (INT32)((INT16)i) + j; | |
| 274 | if(temp > 255) | |
| 275 | { | |
| 276 | m_cc_lut2[(i << 8) | j] = 255; | |
| 277 | } | |
| 278 | else if(temp < 0) | |
| 279 | { | |
| 280 | m_cc_lut2[(i << 8) | j] = 0; | |
| 281 | } | |
| 282 | else | |
| 283 | { | |
| 284 | m_cc_lut2[(i << 8) | j] = (UINT8)temp; | |
| 285 | } | |
| 286 | } | |
| 287 | } | |
| 288 | ||
| 289 | 301 | for (int i = 0; i < 8; i++) |
| 290 | 302 | { |
| 291 | 303 | m_tiles[i].num = i; |
| r9854 | r9855 | |
| 325 | 337 | |
| 326 | 338 | m_machine = NULL; |
| 327 | 339 | |
| 328 | memset(m_hidden_bits, 3, | |
| 340 | //memset(m_hidden_bits, 3, 8 | |
| 329 | 341 | |
| 330 | 342 | m_prim_lod_frac = 0; |
| 331 | 343 | m_lod_frac = 0; |
| r9854 | r9855 | |
| 342 | 354 | m_gamma_dither_table[i] <<= 1; |
| 343 | 355 | } |
| 344 | 356 | |
| 345 | BuildCompressedZTable(); | |
| 357 | z_build_com_table(); | |
| 358 | ||
| 359 | for (int i = 0; i < 0x4000; i++) | |
| 360 | { | |
| 361 | UINT32 exponent = (i >> 11) & 7; | |
| 362 | UINT32 mantissa = i & 0x7ff; | |
| 363 | z_complete_dec_table[i] = ((mantissa << z_dec_table[exponent].shift) + z_dec_table[exponent].add) & 0x3fffff; | |
| 364 | } | |
| 365 | ||
| 366 | precalc_cvmask_derivatives(); | |
| 367 | ||
| 368 | for(int i = 0; i < 0x200; i++) | |
| 369 | { | |
| 370 | switch((i >> 7) & 3) | |
| 371 | { | |
| 372 | case 0: | |
| 373 | case 1: | |
| 374 | m_special_9bit_clamptable[i] = i & 0xff; | |
| 375 | break; | |
| 376 | case 2: | |
| 377 | m_special_9bit_clamptable[i] = 0xff; | |
| 378 | break; | |
| 379 | case 3: | |
| 380 | m_special_9bit_clamptable[i] = 0; | |
| 381 | break; | |
| 382 | } | |
| 383 | } | |
| 384 | ||
| 385 | for(int i = 0; i < 32; i++) | |
| 386 | { | |
| 387 | m_replicated_rgba[i] = (i << 3) | ((i >> 2) & 7); | |
| 388 | } | |
| 346 | 389 | } |
| 347 | 390 | |
| 348 | 391 | ~Processor() { } |
| 349 | 392 | |
| 393 | UINT8* ReplicatedRGBA() { return m_replicated_rgba; } | |
| 394 | ||
| 350 | 395 | void Dasm(char *buffer); |
| 351 | 396 | |
| 352 | 397 | void ProcessList(); |
| 353 | 398 | UINT32 ReadData(UINT32 address); |
| 354 | 399 | |
| 400 | void set_span_base(int dr, int dg, int db, int da, int ds, int dt, int dw, int dz, int dymax, int dzpix) | |
| 401 | { | |
| 402 | m_span_dr = dr; | |
| 403 | m_span_dg = dg; | |
| 404 | m_span_db = db; | |
| 405 | m_span_da = da; | |
| 406 | m_span_ds = ds; | |
| 407 | m_span_dt = dt; | |
| 408 | m_span_dw = dw; | |
| 409 | m_span_dz = dz; | |
| 410 | m_span_dymax = dymax; | |
| 411 | m_span_dzpix = dzpix; | |
| 412 | } | |
| 413 | ||
| 414 | void set_span_base_y(int dr, int dg, int db, int da, int dz) | |
| 415 | { | |
| 416 | m_span_drdy = dr; | |
| 417 | m_span_dgdy = dg; | |
| 418 | m_span_dbdy = db; | |
| 419 | m_span_dady = da; | |
| 420 | m_span_dzdy = dz; | |
| 421 | } | |
| 422 | ||
| 355 | 423 | void InitInternalState() |
| 356 | 424 | { |
| 357 | 425 | if(m_machine) |
| r9854 | r9855 | |
| 362 | 430 | UINT8 *normpoint = memory_region(m_machine, "normpoint"); |
| 363 | 431 | UINT8 *normslope = memory_region(m_machine, "normslope"); |
| 364 | 432 | |
| 365 | for( | |
| 433 | for(INT32 i = 0; i < 64; i++) | |
| 366 | 434 | { |
| 367 | 435 | m_norm_point_rom[i] = (normpoint[(i << 1) + 1] << 8) | normpoint[i << 1]; |
| 368 | 436 | m_norm_slope_rom[i] = (normslope[(i << 1) + 1] << 8) | normslope[i << 1]; |
| r9854 | r9855 | |
| 430 | 498 | Color* GetTexel1Color() { return &m_texel1_color; } |
| 431 | 499 | void SetTexel1Color(UINT32 color) { m_texel1_color.c = color; } |
| 432 | 500 | |
| 501 | Color* GetNextTexelColor() { return &m_next_texel_color; } | |
| 502 | void SetNextTexelColor(UINT32 color) { m_next_texel_color.c = color; } | |
| 503 | ||
| 433 | 504 | Color* GetShadeColor() { return &m_shade_color; } |
| 434 | 505 | void SetShadeColor(UINT32 color) { m_shade_color.c = color; } |
| 435 | 506 | |
| r9854 | r9855 | |
| 442 | 513 | Color* GetOne() { return &m_one_color; } |
| 443 | 514 | Color* GetZero() { return &m_zero_color; } |
| 444 | 515 | |
| 445 | UINT8 | |
| 516 | UINT8 | |
| 446 | 517 | void SetLODFrac(UINT8 lod_frac) { m_lod_frac = lod_frac; } |
| 447 | 518 | |
| 448 | UINT8 | |
| 519 | UINT8 | |
| 449 | 520 | void SetPrimLODFrac(UINT8 prim_lod_frac) { m_prim_lod_frac = prim_lod_frac; } |
| 450 | 521 | |
| 451 | 522 | // Color Combiner |
| 523 | INT32 ColorCombinerEquation(INT32 a, INT32 b, INT32 c, INT32 d); | |
| 524 | INT32 AlphaCombinerEquation(INT32 a, INT32 b, INT32 c, INT32 d); | |
| 525 | void ColorCombiner2Cycle(bool noisecompute); | |
| 526 | void ColorCombiner1Cycle(bool noisecompute); | |
| 452 | 527 | void SetSubAInputRGB(UINT8 **input_r, UINT8 **input_g, UINT8 **input_b, int code); |
| 453 | 528 | void SetSubBInputRGB(UINT8 **input_r, UINT8 **input_g, UINT8 **input_b, int code); |
| 454 | 529 | void SetMulInputRGB(UINT8 **input_r, UINT8 **input_g, UINT8 **input_b, int code); |
| r9854 | r9855 | |
| 464 | 539 | Tile* GetTiles(){ return m_tiles; } |
| 465 | 540 | |
| 466 | 541 | // Emulation Accelerators |
| 467 | UINT32 LookUp16To32(UINT16 in) const { return m_rgb16_to_rgb32_lut[in]; } | |
| 468 | UINT32 LookUpIA8To32(UINT16 in) const { return m_ia8_to_rgb32_lut[in]; } | |
| 469 | UINT16* GetCCLUT1() { return m_cc_lut1; } | |
| 470 | UINT8* GetCCLUT2() { return m_cc_lut2; } | |
| 471 | 542 | UINT8 GetRandom() { return m_misc_state.m_random_seed += 0x13; } |
| 472 | 543 | |
| 473 | 544 | // YUV Factors |
| r9854 | r9855 | |
| 485 | 556 | // Render-related (move into eventual drawing-related classes?) |
| 486 | 557 | Rectangle* GetScissor() { return &m_scissor; } |
| 487 | 558 | void TCDiv(INT32 ss, INT32 st, INT32 sw, INT32* sss, INT32* sst); |
| 559 | void TCDivNoPersp(INT32 ss, INT32 st, INT32 sw, INT32* sss, INT32* sst); | |
| 488 | 560 | UINT32 GetLog2(UINT32 lod_clamp); |
| 489 | void RenderSpans(int start, int end, int tilenum, bool | |
| 561 | void RenderSpans(int start, int end, int tilenum, bool | |
| 490 | 562 | UINT8* GetHiddenBits() { return m_hidden_bits; } |
| 491 | 563 | void GetAlphaCvg(UINT8 *comb_alpha); |
| 492 | 564 | const UINT8* GetBayerMatrix() const { return s_bayer_matrix; } |
| r9854 | r9855 | |
| 495 | 567 | int GetCurrFIFOIndex() const { return m_cmd_cur; } |
| 496 | 568 | UINT32 GetFillColor32() const { return m_fill_color; } |
| 497 | 569 | |
| 498 | void ZStore(UINT16* zb, UINT8* zhb, UINT32 z, UINT32 deltaz); | |
| 499 | UINT32 DecompressZ(UINT16 *zb); | |
| 500 | UINT16 DecompressDZ(UINT16* zb, UINT8* zhb); | |
| 570 | void ZStore(UINT32 zcurpixel, UINT32 dzcurpixel, UINT32 z); | |
| 571 | UINT32 ZDecompress(UINT32 zcurpixel); | |
| 572 | UINT32 DZDecompress(UINT32 zcurpixel, UINT32 dzcurpixel); | |
| 573 | UINT32 DZCompress(UINT32 value); | |
| 501 | 574 | INT32 NormalizeDZPix(INT32 sum); |
| 502 | bool ZCompare( | |
| 575 | bool ZCompare( | |
| 503 | 576 | |
| 504 | 577 | // Fullscreen update-related |
| 505 | 578 | void VideoUpdate(bitmap_t *bitmap); |
| r9854 | r9855 | |
| 548 | 621 | UINT32 AddLeftCvg(UINT32 x, UINT32 k); |
| 549 | 622 | |
| 550 | 623 | UINT32* GetCommandData() { return m_cmd_data; } |
| 624 | UINT32* GetTempRectData() { return m_temp_rect_data; } | |
| 551 | 625 | |
| 626 | void GetDitherValues(int x, int y, int* cdith, int* adith); | |
| 627 | ||
| 628 | ||
| 629 | int m_span_dr; | |
| 630 | int m_span_drdy; | |
| 631 | int m_span_dg; | |
| 632 | int m_span_dgdy; | |
| 633 | int m_span_db; | |
| 634 | int m_span_dbdy; | |
| 635 | int m_span_da; | |
| 636 | int m_span_dady; | |
| 637 | int m_span_ds; | |
| 638 | int m_span_dt; | |
| 639 | int m_span_dw; | |
| 640 | int m_span_dz; | |
| 641 | int m_span_dzdy; | |
| 642 | int m_span_dymax; | |
| 643 | int m_span_dzpix; | |
| 644 | ||
| 645 | UINT32* GetSpecial9BitClampTable() { return m_special_9bit_clamptable; } | |
| 646 | ||
| 647 | UINT16 decompress_cvmask_frombyte(UINT8 x); | |
| 648 | void lookup_cvmask_derivatives(UINT32 mask, UINT8* offx, UINT8* offy); | |
| 649 | ||
| 552 | 650 | protected: |
| 553 | 651 | Blender m_blender; |
| 554 | 652 | Framebuffer m_framebuffer; |
| r9854 | r9855 | |
| 571 | 669 | Color m_combined_color; |
| 572 | 670 | Color m_texel0_color; |
| 573 | 671 | Color m_texel1_color; |
| 672 | Color m_next_texel_color; | |
| 574 | 673 | Color m_shade_color; |
| 575 | 674 | Color m_key_scale; |
| 576 | 675 | Color m_noise_color; |
| r9854 | r9855 | |
| 582 | 681 | |
| 583 | 682 | UINT32 m_fill_color; |
| 584 | 683 | |
| 585 | UINT16 m_cc_lut1[(1<<24)]; | |
| 586 | UINT8 m_cc_lut2[(1<<24)]; | |
| 587 | UINT32 m_rgb16_to_rgb32_lut[(1 << 16)]; | |
| 588 | UINT32 m_ia8_to_rgb32_lut[(1 << 16)]; | |
| 684 | typedef struct | |
| 685 | { | |
| 686 | UINT8 cvg; | |
| 687 | UINT8 cvbit; | |
| 688 | UINT8 xoff; | |
| 689 | UINT8 yoff; | |
| 690 | } CVMASKDERIVATIVE; | |
| 691 | CVMASKDERIVATIVE cvarray[(1 << 8)]; | |
| 589 | 692 | |
| 693 | UINT16 z_com_table[0x40000]; //precalced table of compressed z values, 18b: 512 KB array! | |
| 694 | UINT32 z_complete_dec_table[0x4000]; //the same for decompressed z values, 14b | |
| 695 | UINT8 compressed_cvmasks[0x10000]; //16bit cvmask -> to byte | |
| 696 | ||
| 590 | 697 | UINT32 m_cmd_data[0x1000]; |
| 698 | UINT32 m_temp_rect_data[0x1000]; | |
| 699 | ||
| 591 | 700 | int m_cmd_ptr; |
| 592 | 701 | int m_cmd_cur; |
| 593 | 702 | |
| r9854 | r9855 | |
| 627 | 736 | INT32 m_gamma_table[256]; |
| 628 | 737 | INT32 m_gamma_dither_table[0x4000]; |
| 629 | 738 | |
| 739 | UINT32 m_special_9bit_clamptable[512]; | |
| 740 | ||
| 741 | UINT8 m_replicated_rgba[32]; | |
| 742 | ||
| 743 | INT32 m_dzpix_enc; | |
| 744 | INT32 m_dz_enc; | |
| 745 | ||
| 630 | 746 | class ZDecompressEntry |
| 631 | 747 | { |
| 632 | 748 | public: |
| r9854 | r9855 | |
| 634 | 750 | UINT32 add; |
| 635 | 751 | }; |
| 636 | 752 | |
| 637 | void BuildCompressedZTable(); | |
| 638 | UINT16 m_z_compress_table[0x40000]; | |
| 639 | static const ZDecompressEntry m_z_decompress_table[8]; | |
| 753 | void precalc_cvmask_derivatives(void); | |
| 754 | void z_build_com_table(void); | |
| 755 | static const ZDecompressEntry z_dec_table[8]; | |
| 640 | 756 | |
| 641 | 757 | // Internal screen-update functions |
| 642 | 758 | void VideoUpdate16(bitmap_t *bitmap); |
| r9854 | r9855 | |
|---|---|---|
| 7 | 7 | #include "emu.h" |
| 8 | 8 | #include "debugger.h" |
| 9 | 9 | #include "rsp.h" |
| 10 | #include "rspdiv.h" | |
| 10 | 11 | |
| 11 | 12 | CPU_DISASSEMBLE( rsp ); |
| 12 | 13 | |
| r9854 | r9855 | |
| 18 | 19 | #define RSP_TEST_SYNC 0 |
| 19 | 20 | |
| 20 | 21 | #define PRINT_VECREG(x) mame_printf_debug("V%d: %04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X\n", (x), \ |
| 21 | (UINT16)R_VREG_S((x),0), (UINT16)R_VREG_S((x),1), \ | |
| 22 | (UINT16)R_VREG_S((x),2), (UINT16)R_VREG_S((x),3), \ | |
| 23 | (UINT16)R_VREG_S((x),4), (UINT16)R_VREG_S((x),5), \ | |
| 24 | (UINT16)R_VREG_S((x),6), (UINT16)R_VREG_S((x),7)) | |
| 22 | (UINT16)VREG_S((x),0), (UINT16)VREG_S((x),1), \ | |
| 23 | (UINT16)VREG_S((x),2), (UINT16)VREG_S((x),3), \ | |
| 24 | (UINT16)VREG_S((x),4), (UINT16)VREG_S((x),5), \ | |
| 25 | (UINT16)VREG_S((x),6), (UINT16)VREG_S((x),7)) | |
| 25 | 26 | |
| 26 | 27 | #define PRINT_ACCUM(x) mame_printf_debug("A%d: %08X|%08X\n", (x), \ |
| 27 | 28 | (UINT32)( ( ACCUM(x) >> 32 ) & 0x00000000ffffffff ), \ |
| r9854 | r9855 | |
| 46 | 47 | #define JUMP_REL_L(offset,l) { rsp->nextpc = 0x04001000 | ((rsp->pc + ((offset) << 2)) & 0xfff); rsp->r[l] = rsp->pc + 4; } |
| 47 | 48 | #define JUMP_PC(addr) { rsp->nextpc = 0x04001000 | ((addr) & 0xfff); } |
| 48 | 49 | #define JUMP_PC_L(addr,l) { rsp->nextpc = 0x04001000 | ((addr) & 0xfff); rsp->r[l] = rsp->pc + 4; } |
| 50 | #define LINK(l) { rsp->r[l] = rsp->pc + 4; } | |
| 49 | 51 | |
| 50 | #define VDREG ((op >> 6) & 0x1f) | |
| 51 | #define VS1REG ((op >> 11) & 0x1f) | |
| 52 | #define VS2REG ((op >> 16) & 0x1f) | |
| 53 | #define EL ((op >> 21) & 0xf) | |
| 52 | #define VREG_B(reg, offset) rsp->v[(reg)].b[(offset)^1] | |
| 53 | #define VREG_S(reg, offset) rsp->v[(reg)].s[(offset)] | |
| 54 | #define VREG_L(reg, offset) rsp->v[(reg)].l[(offset)] | |
| 54 | 55 | |
| 55 | #define S_VREG_B(offset) (((15 - (offset)) & 0x07) << 3) | |
| 56 | #define S_VREG_S(offset) (((7 - (offset)) & 0x03) << 4) | |
| 57 | #define S_VREG_L(offset) (((3 - (offset)) & 0x01) << 5) | |
| 56 | #define R_VREG_B(reg, offset) rsp->v[(reg)].b[(offset)^1] | |
| 57 | #define R_VREG_S(reg, offset) (INT16)rsp->v[(reg)].s[(offset)] | |
| 58 | #define R_VREG_L(reg, offset) rsp->v[(reg)].l[(offset)] | |
| 58 | 59 | |
| 59 | #define M_VREG_B(offset) ((UINT64)0x00FF << S_VREG_B(offset)) | |
| 60 | #define M_VREG_S(offset) ((UINT64)0x0000FFFFul << S_VREG_S(offset)) | |
| 61 | #define M_VREG_L(offset) ((UINT64)0x00000000FFFFFFFFull << S_VREG_L(offset)) | |
| 60 | #define W_VREG_B(reg, offset, val) (rsp->v[(reg)].b[(offset)^1] = val) | |
| 61 | #define W_VREG_S(reg, offset, val) (rsp->v[(reg)].s[(offset)] = val) | |
| 62 | #define W_VREG_L(reg, offset, val) (rsp->v[(reg)].l[(offset)] = val) | |
| 62 | 63 | |
| 63 | #define R_VREG_B(reg, offset) ((rsp->v[(reg)].d[(15 - (offset)) >> 3] >> S_VREG_B(offset)) & 0x00FF) | |
| 64 | #define R_VREG_S(reg, offset) (INT16)((rsp->v[(reg)].d[(7 - (offset)) >> 2] >> S_VREG_S(offset)) & 0x0000FFFFul) | |
| 65 | #define R_VREG_L(reg, offset) ((rsp->v[(reg)].d[(3 - (offset)) >> 1] >> S_VREG_L(offset)) & 0x00000000FFFFFFFFull) | |
| 64 | #define VEC_EL_2(x,z) (vector_elements[(x)][(z)]) | |
| 66 | 65 | |
| 67 | #define W_VREG_B(reg, offset, val) (rsp->v[(reg)].d[(15 - (offset)) >> 3] = (rsp->v[(reg)].d[(15 - (offset)) >> 3] & ~M_VREG_B(offset)) | (M_VREG_B(offset) & ((UINT64)(val) << S_VREG_B(offset)))) | |
| 68 | #define W_VREG_S(reg, offset, val) (rsp->v[(reg)].d[(7 - (offset)) >> 2] = (rsp->v[(reg)].d[(7 - (offset)) >> 2] & ~M_VREG_S(offset)) | (M_VREG_S(offset) & ((UINT64)(val) << S_VREG_S(offset)))) | |
| 69 | #define W_VREG_L(reg, offset, val) (rsp->v[(reg)].d[(3 - (offset)) >> 1] = (rsp->v[(reg)].d[(3 - (offset)) >> 1] & ~M_VREG_L(offset)) | (M_VREG_L(offset) & ((UINT64)(val) << S_VREG_L(offset)))) | |
| 66 | #define ACCUM(x) rsp->accum[((x))].q | |
| 67 | #define ACCUM_H(x) rsp->accum[((x))].w[3] | |
| 68 | #define ACCUM_M(x) rsp->accum[((x))].w[2] | |
| 69 | #define ACCUM_L(x) rsp->accum[((x))].w[1] | |
| 70 | 70 | |
| 71 | #define VEC_EL_1(x,z) (vector_elements_1[(x)][(z)]) | |
| 72 | #define VEC_EL_2(x,z) (vector_elements_2[(x)][(z)]) | |
| 73 | ||
| 74 | #define ACCUM(x) (rsp->accum[(7-(x))].l) | |
| 75 | ||
| 76 | #define S_ACCUM_H (3 << 4) | |
| 77 | #define S_ACCUM_M (2 << 4) | |
| 78 | #define S_ACCUM_L (1 << 4) | |
| 79 | ||
| 80 | #define M_ACCUM_H (((INT64)0x0000FFFF) << S_ACCUM_H) | |
| 81 | #define M_ACCUM_M (((INT64)0x0000FFFF) << S_ACCUM_M) | |
| 82 | #define M_ACCUM_L (((INT64)0x0000FFFF) << S_ACCUM_L) | |
| 83 | ||
| 84 | #define R_ACCUM_H(x) ((INT16)((ACCUM(x) >> S_ACCUM_H) & 0x00FFFF)) | |
| 85 | #define R_ACCUM_M(x) ((INT16)((ACCUM(x) >> S_ACCUM_M) & 0x00FFFF)) | |
| 86 | #define R_ACCUM_L(x) ((INT16)((ACCUM(x) >> S_ACCUM_L) & 0x00FFFF)) | |
| 87 | ||
| 88 | #define W_ACCUM_H(x, y) (ACCUM(x) = (ACCUM(x) & ~M_ACCUM_H) | (M_ACCUM_H & ((INT64)(y) << S_ACCUM_H))) | |
| 89 | #define W_ACCUM_M(x, y) (ACCUM(x) = (ACCUM(x) & ~M_ACCUM_M) | (M_ACCUM_M & ((INT64)(y) << S_ACCUM_M))) | |
| 90 | #define W_ACCUM_L(x, y) (ACCUM(x) = (ACCUM(x) & ~M_ACCUM_L) | (M_ACCUM_L & ((INT64)(y) << S_ACCUM_L))) | |
| 91 | ||
| 92 | 71 | #define CARRY_FLAG(x) ((rsp->flag[0] & (1 << ((x)))) ? 1 : 0) |
| 93 | 72 | #define CLEAR_CARRY_FLAGS() { rsp->flag[0] &= ~0xff; } |
| 94 | 73 | #define SET_CARRY_FLAG(x) { rsp->flag[0] |= (1 << ((x))); } |
| r9854 | r9855 | |
| 104 | 83 | #define SET_ZERO_FLAG(x) { rsp->flag[0] |= (1 << (8+(x))); } |
| 105 | 84 | #define CLEAR_ZERO_FLAG(x) { rsp->flag[0] &= ~(1 << (8+(x))); } |
| 106 | 85 | |
| 107 | #define | |
| 86 | #define | |
| 108 | 87 | |
| 88 | #define ROPCODE(pc) rsp->program->read_dword(pc) | |
| 89 | ||
| 109 | 90 | INLINE UINT8 READ8(rsp_state *rsp, UINT32 address) |
| 110 | 91 | { |
| 92 | UINT8 ret; | |
| 111 | 93 | address = 0x04000000 | (address & 0xfff); |
| 112 | return rsp->program->read_byte(address); | |
| 94 | ret = rsp->program->read_byte(address); | |
| 95 | printf("%04xr%02x\n", address & 0x0000ffff, ret); | |
| 96 | return ret; | |
| 113 | 97 | } |
| 114 | 98 | |
| 115 | 99 | INLINE UINT16 READ16(rsp_state *rsp, UINT32 address) |
| 116 | 100 | { |
| 101 | UINT16 ret; | |
| 117 | 102 | address = 0x04000000 | (address & 0xfff); |
| 118 | 103 | |
| 119 | if | |
| 104 | if | |
| 120 | 105 | { |
| 121 | //osd_die("RSP: READ16: unaligned %08X at %08X\n", address, rsp->ppc); | |
| 122 | return ((rsp->program->read_byte(address+0) & 0xff) << 8) | (rsp->program->read_byte(address+1) & 0xff); | |
| 106 | ret = ((rsp->program->read_byte(address + 0) & 0xff) << 8) | (rsp->program->read_byte(address + 1) & 0xff); | |
| 123 | 107 | } |
| 108 | else | |
| 109 | { | |
| 110 | ret = rsp->program->read_word(address); | |
| 111 | } | |
| 124 | 112 | |
| 125 | return rsp->program->read_word(address); | |
| 113 | printf("%04xr%04x\n", address & 0x0000ffff, ret); | |
| 114 | ||
| 115 | return ret; | |
| 126 | 116 | } |
| 127 | 117 | |
| 128 | 118 | INLINE UINT32 READ32(rsp_state *rsp, UINT32 address) |
| 129 | 119 | { |
| 120 | UINT32 ret; | |
| 130 | 121 | address = 0x04000000 | (address & 0xfff); |
| 131 | 122 | |
| 132 | if | |
| 123 | if | |
| 133 | 124 | { |
| 134 | //osd_die("RSP: READ32: unaligned %08X at %08X\n", address, rsp->ppc); | |
| 135 | return ((rsp->program->read_byte(address + 0) & 0xff) << 24) | | |
| 125 | ret = ((rsp->program->read_byte(address + 0) & 0xff) << 24) | | |
| 136 | 126 | ((rsp->program->read_byte(address + 1) & 0xff) << 16) | |
| 137 | 127 | ((rsp->program->read_byte(address + 2) & 0xff) << 8) | |
| 138 | 128 | ((rsp->program->read_byte(address + 3) & 0xff) << 0); |
| 139 | 129 | } |
| 130 | else | |
| 131 | { | |
| 132 | ret = rsp->program->read_dword(address); | |
| 133 | } | |
| 140 | 134 | |
| 141 | return rsp->program->read_dword(address); | |
| 135 | printf("%04xr%08x\n", address & 0x0000ffff, ret); | |
| 136 | return ret; | |
| 142 | 137 | } |
| 143 | 138 | |
| 144 | 139 | INLINE void WRITE8(rsp_state *rsp, UINT32 address, UINT8 data) |
| 145 | 140 | { |
| 146 | 141 | address = 0x04000000 | (address & 0xfff); |
| 142 | printf("%04x:%02x\n", address & 0x0000ffff, data); | |
| 147 | 143 | rsp->program->write_byte(address, data); |
| 148 | 144 | } |
| 149 | 145 | |
| 150 | 146 | INLINE void WRITE16(rsp_state *rsp, UINT32 address, UINT16 data) |
| 151 | 147 | { |
| 152 | 148 | address = 0x04000000 | (address & 0xfff); |
| 149 | printf("%04x:%04x\n", address & 0x0000ffff, data); | |
| 153 | 150 | |
| 154 | if | |
| 151 | if | |
| 155 | 152 | { |
| 156 | //fatalerror("RSP: WRITE16: unaligned %08X, %04X at %08X\n", address, data, rsp->ppc); | |
| 157 | 153 | rsp->program->write_byte(address + 0, (data >> 8) & 0xff); |
| 158 | 154 | rsp->program->write_byte(address + 1, (data >> 0) & 0xff); |
| 159 | 155 | return; |
| r9854 | r9855 | |
| 165 | 161 | INLINE void WRITE32(rsp_state *rsp, UINT32 address, UINT32 data) |
| 166 | 162 | { |
| 167 | 163 | address = 0x04000000 | (address & 0xfff); |
| 164 | printf("%04x:%08x\n", address & 0x0000ffff, data); | |
| 168 | 165 | |
| 169 | if | |
| 166 | if | |
| 170 | 167 | { |
| 171 | //osd_die("RSP: WRITE32: unaligned %08X, %08X at %08X\n", address, data, rsp->ppc); | |
| 172 | 168 | rsp->program->write_byte(address + 0, (data >> 24) & 0xff); |
| 173 | 169 | rsp->program->write_byte(address + 1, (data >> 16) & 0xff); |
| 174 | 170 | rsp->program->write_byte(address + 2, (data >> 8) & 0xff); |
| r9854 | r9855 | |
| 183 | 179 | |
| 184 | 180 | static UINT32 get_cop0_reg(rsp_state *rsp, int reg) |
| 185 | 181 | { |
| 186 | if (reg >= 0 && reg < 8) | |
| 182 | reg &= 0xf; | |
| 183 | if (reg < 8) | |
| 187 | 184 | { |
| 188 | 185 | return (rsp->config->sp_reg_r)(rsp->device, reg, 0x00000000); |
| 189 | 186 | } |
| r9854 | r9855 | |
| 191 | 188 | { |
| 192 | 189 | return (rsp->config->dp_reg_r)(rsp->device, reg - 8, 0x00000000); |
| 193 | 190 | } |
| 194 | else | |
| 195 | { | |
| 196 | fatalerror("RSP: get_cop0_reg: %d", reg); | |
| 197 | } | |
| 191 | ||
| 192 | return 0; | |
| 198 | 193 | } |
| 199 | 194 | |
| 200 | 195 | static void set_cop0_reg(rsp_state *rsp, int reg, UINT32 data) |
| 201 | 196 | { |
| 202 | if (reg >= 0 && reg < 8) | |
| 197 | reg &= 0xf; | |
| 198 | if (reg < 8) | |
| 203 | 199 | { |
| 204 | 200 | (rsp->config->sp_reg_w)(rsp->device, reg, data, 0x00000000); |
| 205 | 201 | } |
| r9854 | r9855 | |
| 207 | 203 | { |
| 208 | 204 | (rsp->config->dp_reg_w)(rsp->device, reg - 8, data, 0x00000000); |
| 209 | 205 | } |
| 210 | else | |
| 211 | { | |
| 212 | fatalerror("RSP: set_cop0_reg: %d, %08X\n", reg, data); | |
| 213 | } | |
| 214 | 206 | } |
| 215 | 207 | |
| 216 | 208 | static void unimplemented_opcode(rsp_state *rsp, UINT32 op) |
| r9854 | r9855 | |
| 257 | 249 | |
| 258 | 250 | /*****************************************************************************/ |
| 259 | 251 | |
| 260 | static const int vector_elements | |
| 252 | static const int vector_elements | |
| 261 | 253 | { |
| 262 | 254 | { 0, 1, 2, 3, 4, 5, 6, 7 }, // none |
| 263 | { 0, 1, 2, 3, 4, 5, 6 ,7 }, // ??? | |
| 264 | { 1, 3, 5, 7, 0, 2, 4, 6 }, // 0q | |
| 265 | { 0, 2, 4, 6, 1, 3, 5, 7 }, // 1q | |
| 266 | { 1, 2, 3, 5, 6, 7, 0, 4 }, // 0h | |
| 267 | { 0, 2, 3, 4, 6, 7, 1, 5 }, // 1h | |
| 268 | { 0, 1, 3, 4, 5, 7, 2, 6 }, // 2h | |
| 269 | { 0, 1, 2, 4, 5, 6, 3, 7 }, // 3h | |
| 270 | { 1, 2, 3, 4, 5, 6, 7, 0 }, // 0 | |
| 271 | { 0, 2, 3, 4, 5, 6, 7, 1 }, // 1 | |
| 272 | { 0, 1, 3, 4, 5, 6, 7, 2 }, // 2 | |
| 273 | { 0, 1, 2, 4, 5, 6, 7, 3 }, // 3 | |
| 274 | { 0, 1, 2, 3, 5, 6, 7, 4 }, // 4 | |
| 275 | { 0, 1, 2, 3, 4, 6, 7, 5 }, // 5 | |
| 276 | { 0, 1, 2, 3, 4, 5, 7, 6 }, // 6 | |
| 277 | { 0, 1, 2, 3, 4, 5, 6, 7 }, // 7 | |
| 278 | }; | |
| 279 | ||
| 280 | static const int vector_elements_2[16][8] = | |
| 281 | { | |
| 282 | { 0, 1, 2, 3, 4, 5, 6, 7 }, // none | |
| 283 | 255 | { 0, 1, 2, 3, 4, 5, 6, 7 }, // ??? |
| 284 | 256 | { 0, 0, 2, 2, 4, 4, 6, 6 }, // 0q |
| 285 | 257 | { 1, 1, 3, 3, 5, 5, 7, 7 }, // 1q |
| r9854 | r9855 | |
| 335 | 307 | // makes me retch uncontrollably. |
| 336 | 308 | for(accumIdx = 0; accumIdx < 8; accumIdx++ ) |
| 337 | 309 | { |
| 338 | rsp->accum[accumIdx]. | |
| 310 | rsp->accum[accumIdx].q = 0; | |
| 339 | 311 | } |
| 340 | 312 | |
| 341 | 313 | rsp->sr = RSP_STATUS_HALT; |
| r9854 | r9855 | |
| 419 | 391 | // Load 1 byte to vector byte index |
| 420 | 392 | |
| 421 | 393 | ea = (base) ? rsp->r[base] + offset : offset; |
| 422 | | |
| 394 | | |
| 423 | 395 | break; |
| 424 | 396 | } |
| 425 | 397 | case 0x01: /* LSV */ |
| r9854 | r9855 | |
| 437 | 409 | |
| 438 | 410 | for (i=index; i < end; i++) |
| 439 | 411 | { |
| 440 | | |
| 412 | | |
| 441 | 413 | ea++; |
| 442 | 414 | } |
| 443 | 415 | break; |
| r9854 | r9855 | |
| 457 | 429 | |
| 458 | 430 | for (i=index; i < end; i++) |
| 459 | 431 | { |
| 460 | | |
| 432 | | |
| 461 | 433 | ea++; |
| 462 | 434 | } |
| 463 | 435 | break; |
| r9854 | r9855 | |
| 477 | 449 | |
| 478 | 450 | for (i=index; i < end; i++) |
| 479 | 451 | { |
| 480 | | |
| 452 | | |
| 481 | 453 | ea++; |
| 482 | 454 | } |
| 483 | 455 | break; |
| r9854 | r9855 | |
| 498 | 470 | |
| 499 | 471 | for (i=index; i < end; i++) |
| 500 | 472 | { |
| 501 | | |
| 473 | | |
| 502 | 474 | ea++; |
| 503 | 475 | } |
| 504 | 476 | break; |
| r9854 | r9855 | |
| 520 | 492 | |
| 521 | 493 | for (i=index; i < end; i++) |
| 522 | 494 | { |
| 523 | | |
| 495 | | |
| 524 | 496 | ea++; |
| 525 | 497 | } |
| 526 | 498 | break; |
| r9854 | r9855 | |
| 538 | 510 | |
| 539 | 511 | for (i=0; i < 8; i++) |
| 540 | 512 | { |
| 541 | | |
| 513 | | |
| 542 | 514 | } |
| 543 | 515 | break; |
| 544 | 516 | } |
| r9854 | r9855 | |
| 555 | 527 | |
| 556 | 528 | for (i=0; i < 8; i++) |
| 557 | 529 | { |
| 558 | | |
| 530 | | |
| 559 | 531 | } |
| 560 | 532 | break; |
| 561 | 533 | } |
| r9854 | r9855 | |
| 572 | 544 | |
| 573 | 545 | for (i=0; i < 8; i++) |
| 574 | 546 | { |
| 575 | | |
| 547 | | |
| 576 | 548 | } |
| 577 | 549 | break; |
| 578 | 550 | } |
| r9854 | r9855 | |
| 585 | 557 | // |
| 586 | 558 | // Loads a byte as the bits 14-7 of upper or lower quad, with 4-byte stride |
| 587 | 559 | |
| 588 | fatalerror("RSP: LFV\n"); | |
| 589 | ||
| 590 | if (index & 0x7) fatalerror("RSP: LFV: index = %d at %08X\n", index, rsp->ppc); | |
| 591 | ||
| 592 | 560 | ea = (base) ? rsp->r[base] + (offset * 16) : (offset * 16); |
| 593 | 561 | |
| 594 | 562 | // not sure what happens if 16-byte boundary is crossed... |
| 595 | if ((ea & 0xf) > 0) fatalerror("RSP: LFV: 16-byte boundary crossing at %08X, recheck this!\n", rsp->ppc); | |
| 596 | 563 | |
| 597 | 564 | end = (index >> 1) + 4; |
| 598 | 565 | |
| 599 | 566 | for (i=index >> 1; i < end; i++) |
| 600 | 567 | { |
| 601 | | |
| 568 | | |
| 602 | 569 | ea += 4; |
| 603 | 570 | } |
| 604 | 571 | break; |
| r9854 | r9855 | |
| 622 | 589 | |
| 623 | 590 | for (i=(16 - index); i < end; i++) |
| 624 | 591 | { |
| 625 | | |
| 592 | | |
| 626 | 593 | ea += 4; |
| 627 | 594 | } |
| 628 | 595 | break; |
| r9854 | r9855 | |
| 654 | 621 | for (i=vs; i < ve; i++) |
| 655 | 622 | { |
| 656 | 623 | element = ((8 - (index >> 1) + (i-vs)) << 1); |
| 657 | W_VREG_B(i, (element & 0xf), READ8(rsp, ea)); | |
| 658 | W_VREG_B(i, ((element+1) & 0xf), READ8(rsp, ea+1)); | |
| 624 | VREG_B(i, (element & 0xf)) = READ8(rsp, ea); | |
| 625 | VREG_B(i, ((element + 1) & 0xf)) = READ8(rsp, ea + 1); | |
| 659 | 626 | |
| 660 | 627 | ea += 2; |
| 661 | 628 | } |
| r9854 | r9855 | |
| 694 | 661 | // Stores 1 byte from vector byte index |
| 695 | 662 | |
| 696 | 663 | ea = (base) ? rsp->r[base] + offset : offset; |
| 697 | WRITE8(rsp, ea, | |
| 664 | WRITE8(rsp, ea, | |
| 698 | 665 | break; |
| 699 | 666 | } |
| 700 | 667 | case 0x01: /* SSV */ |
| r9854 | r9855 | |
| 712 | 679 | |
| 713 | 680 | for (i=index; i < end; i++) |
| 714 | 681 | { |
| 715 | WRITE8(rsp, ea, | |
| 682 | WRITE8(rsp, ea, | |
| 716 | 683 | ea++; |
| 717 | 684 | } |
| 718 | 685 | break; |
| r9854 | r9855 | |
| 732 | 699 | |
| 733 | 700 | for (i=index; i < end; i++) |
| 734 | 701 | { |
| 735 | WRITE8(rsp, ea, | |
| 702 | WRITE8(rsp, ea, | |
| 736 | 703 | ea++; |
| 737 | 704 | } |
| 738 | 705 | break; |
| r9854 | r9855 | |
| 752 | 719 | |
| 753 | 720 | for (i=index; i < end; i++) |
| 754 | 721 | { |
| 755 | WRITE8(rsp, ea, | |
| 722 | WRITE8(rsp, ea, | |
| 756 | 723 | ea++; |
| 757 | 724 | } |
| 758 | 725 | break; |
| r9854 | r9855 | |
| 772 | 739 | |
| 773 | 740 | for (i=index; i < end; i++) |
| 774 | 741 | { |
| 775 | WRITE8(rsp, ea, | |
| 742 | WRITE8(rsp, ea, | |
| 776 | 743 | ea++; |
| 777 | 744 | } |
| 778 | 745 | break; |
| r9854 | r9855 | |
| 795 | 762 | |
| 796 | 763 | for (i=index; i < end; i++) |
| 797 | 764 | { |
| 798 | WRITE8(rsp, ea, | |
| 765 | WRITE8(rsp, ea, | |
| 799 | 766 | ea++; |
| 800 | 767 | } |
| 801 | 768 | break; |
| r9854 | r9855 | |
| 816 | 783 | { |
| 817 | 784 | if ((i & 0xf) < 8) |
| 818 | 785 | { |
| 819 | WRITE8(rsp, ea, | |
| 786 | WRITE8(rsp, ea, | |
| 820 | 787 | } |
| 821 | 788 | else |
| 822 | 789 | { |
| 823 | WRITE8(rsp, ea, | |
| 790 | WRITE8(rsp, ea, | |
| 824 | 791 | } |
| 825 | 792 | ea++; |
| 826 | 793 | } |
| r9854 | r9855 | |
| 842 | 809 | { |
| 843 | 810 | if ((i & 0xf) < 8) |
| 844 | 811 | { |
| 845 | WRITE8(rsp, ea, | |
| 812 | WRITE8(rsp, ea, | |
| 846 | 813 | } |
| 847 | 814 | else |
| 848 | 815 | { |
| 849 | WRITE8(rsp, ea, | |
| 816 | WRITE8(rsp, ea, | |
| 850 | 817 | } |
| 851 | 818 | ea++; |
| 852 | 819 | } |
| r9854 | r9855 | |
| 865 | 832 | |
| 866 | 833 | for (i=0; i < 8; i++) |
| 867 | 834 | { |
| 868 | UINT8 d = ((R_VREG_B(dest, ((index + (i << 1) + 0) & 0xf))) << 1) | | |
| 869 | ((R_VREG_B(dest, ((index + (i << 1) + 1) & 0xf))) >> 7); | |
| 835 | UINT8 d = ((VREG_B(dest, ((index + (i << 1) + 0) & 0xf))) << 1) | | |
| 836 | ((VREG_B(dest, ((index + (i << 1) + 1) & 0xf))) >> 7); | |
| 870 | 837 | |
| 871 | 838 | WRITE8(rsp, ea, d); |
| 872 | 839 | ea += 2; |
| r9854 | r9855 | |
| 895 | 862 | |
| 896 | 863 | for (i=index >> 1; i < end; i++) |
| 897 | 864 | { |
| 898 | WRITE8(rsp, ea + (eaoffset & 0xf), | |
| 865 | WRITE8(rsp, ea + (eaoffset & 0xf), | |
| 899 | 866 | eaoffset += 4; |
| 900 | 867 | } |
| 901 | 868 | break; |
| r9854 | r9855 | |
| 919 | 886 | |
| 920 | 887 | for (i=index; i < end; i++) |
| 921 | 888 | { |
| 922 | WRITE8(rsp, ea + (eaoffset & 0xf), | |
| 889 | WRITE8(rsp, ea + (eaoffset & 0xf), | |
| 923 | 890 | eaoffset++; |
| 924 | 891 | } |
| 925 | 892 | break; |
| r9854 | r9855 | |
| 940 | 907 | ve = 32; |
| 941 | 908 | |
| 942 | 909 | element = 8 - (index >> 1); |
| 943 | if (index & 0x1) fatalerror("RSP: STV: index = %d at %08X\n", index, rsp->ppc); | |
| 944 | 910 | |
| 945 | 911 | ea = (base) ? rsp->r[base] + (offset * 16) : (offset * 16); |
| 946 | 912 | |
| 947 | if (ea & 0x1) fatalerror("RSP: STV: ea = %08X at %08X\n", ea, rsp->ppc); | |
| 948 | ||
| 949 | 913 | eaoffset = (ea & 0xf) + (element * 2); |
| 950 | 914 | ea &= ~0xf; |
| 951 | 915 | |
| 952 | 916 | for (i=vs; i < ve; i++) |
| 953 | 917 | { |
| 954 | WRITE16(rsp, ea + (eaoffset & 0xf), | |
| 918 | WRITE16(rsp, ea + (eaoffset & 0xf), | |
| 955 | 919 | eaoffset += 2; |
| 956 | 920 | element++; |
| 957 | 921 | } |
| r9854 | r9855 | |
| 968 | 932 | |
| 969 | 933 | INLINE UINT16 SATURATE_ACCUM(rsp_state *rsp, int accum, int slice, UINT16 negative, UINT16 positive) |
| 970 | 934 | { |
| 971 | if ((INT16) | |
| 935 | if ((INT16) | |
| 972 | 936 | { |
| 973 | if ((UINT16)( | |
| 937 | if ((UINT16)( | |
| 974 | 938 | { |
| 975 | 939 | return negative; |
| 976 | 940 | } |
| 977 | 941 | else |
| 978 | 942 | { |
| 979 | if ((INT16) | |
| 943 | if ((INT16) | |
| 980 | 944 | { |
| 981 | 945 | return negative; |
| 982 | 946 | } |
| r9854 | r9855 | |
| 984 | 948 | { |
| 985 | 949 | if (slice == 0) |
| 986 | 950 | { |
| 987 | return | |
| 951 | return | |
| 988 | 952 | } |
| 989 | 953 | else if (slice == 1) |
| 990 | 954 | { |
| 991 | return | |
| 955 | return | |
| 992 | 956 | } |
| 993 | 957 | } |
| 994 | 958 | } |
| 995 | 959 | } |
| 996 | 960 | else |
| 997 | 961 | { |
| 998 | if ((UINT16)( | |
| 962 | if ((UINT16)( | |
| 999 | 963 | { |
| 1000 | 964 | return positive; |
| 1001 | 965 | } |
| 1002 | 966 | else |
| 1003 | 967 | { |
| 1004 | if ((INT16) | |
| 968 | if ((INT16) | |
| 1005 | 969 | { |
| 1006 | 970 | return positive; |
| 1007 | 971 | } |
| r9854 | r9855 | |
| 1009 | 973 | { |
| 1010 | 974 | if (slice == 0) |
| 1011 | 975 | { |
| 1012 | return | |
| 976 | return | |
| 1013 | 977 | } |
| 1014 | 978 | else |
| 1015 | 979 | { |
| 1016 | return | |
| 980 | return | |
| 1017 | 981 | } |
| 1018 | 982 | } |
| 1019 | 983 | } |
| r9854 | r9855 | |
| 1022 | 986 | return 0; |
| 1023 | 987 | } |
| 1024 | 988 | |
| 1025 | #define WRITEBACK_RESULT() \ | |
| 1026 | do { \ | |
| 1027 | W_VREG_S(VDREG, 0, vres[0]); \ | |
| 1028 | W_VREG_S(VDREG, 1, vres[1]); \ | |
| 1029 | W_VREG_S(VDREG, 2, vres[2]); \ | |
| 1030 | W_VREG_S(VDREG, 3, vres[3]); \ | |
| 1031 | W_VREG_S(VDREG, 4, vres[4]); \ | |
| 1032 | W_VREG_S(VDREG, 5, vres[5]); \ | |
| 1033 | W_VREG_S(VDREG, 6, vres[6]); \ | |
| 1034 | W_VREG_S(VDREG, 7, vres[7]); \ | |
| 1035 | } while(0) | |
| 989 | INLINE UINT16 SATURATE_ACCUM1(rsp_state *rsp, int accum, UINT16 negative, UINT16 positive) | |
| 990 | { | |
| 991 | if ((INT16)ACCUM_H(accum) < 0) | |
| 992 | { | |
| 993 | if ((UINT16)(ACCUM_H(accum)) != 0xffff) | |
| 994 | { | |
| 995 | return negative; | |
| 996 | } | |
| 997 | else | |
| 998 | { | |
| 999 | if ((INT16)ACCUM_M(accum) >= 0) | |
| 1000 | { | |
| 1001 | return negative; | |
| 1002 | } | |
| 1003 | else | |
| 1004 | { | |
| 1005 | return ACCUM_M(accum); | |
| 1006 | } | |
| 1007 | } | |
| 1008 | } | |
| 1009 | else | |
| 1010 | { | |
| 1011 | if ((UINT16)(ACCUM_H(accum)) != 0) | |
| 1012 | { | |
| 1013 | return positive; | |
| 1014 | } | |
| 1015 | else | |
| 1016 | { | |
| 1017 | if ((INT16)ACCUM_M(accum) < 0) | |
| 1018 | { | |
| 1019 | return positive; | |
| 1020 | } | |
| 1021 | else | |
| 1022 | { | |
| 1023 | return ACCUM_M(accum); | |
| 1024 | } | |
| 1025 | } | |
| 1026 | } | |
| 1036 | 1027 | |
| 1028 | return 0; | |
| 1029 | } | |
| 1030 | ||
| 1031 | #define WRITEBACK_RESULT() {memcpy(&rsp->v[VDREG].s[0], &vres[0], 16);} | |
| 1032 | ||
| 1037 | 1033 | #if 0 |
| 1038 | 1034 | static float float_round(float input) |
| 1039 | 1035 | { |
| r9854 | r9855 | |
| 1055 | 1051 | static void handle_vector_ops(rsp_state *rsp, UINT32 op) |
| 1056 | 1052 | { |
| 1057 | 1053 | int i; |
| 1054 | UINT32 VS1REG = (op >> 11) & 0x1f; | |
| 1055 | UINT32 VS2REG = (op >> 16) & 0x1f; | |
| 1056 | UINT32 VDREG = (op >> 6) & 0x1f; | |
| 1057 | UINT32 EL = (op >> 21) & 0xf; | |
| 1058 | 1058 | INT16 vres[8]; |
| 1059 | 1059 | |
| 1060 | 1060 | // Opcode legend: |
| r9854 | r9855 | |
| 1074 | 1074 | // |
| 1075 | 1075 | // Multiplies signed integer by signed integer * 2 |
| 1076 | 1076 | |
| 1077 | int sel; | |
| 1078 | INT32 s1, s2; | |
| 1079 | INT64 r; | |
| 1077 | 1080 | for (i=0; i < 8; i++) |
| 1078 | 1081 | { |
| 1079 | int del = VEC_EL_1(EL, i); | |
| 1080 | int sel = VEC_EL_2(EL, del); | |
| 1081 | INT32 s1 = (INT32)(INT16)R_VREG_S(VS1REG, del); | |
| 1082 | INT32 s2 = (INT32)(INT16)R_VREG_S(VS2REG, sel); | |
| 1082 | sel = VEC_EL_2(EL, i); | |
| 1083 | s1 = (INT32)(INT16)VREG_S(VS1REG, i); | |
| 1084 | s2 = (INT32)(INT16)VREG_S(VS2REG, sel); | |
| 1083 | 1085 | if (s1 == -32768 && s2 == -32768) |
| 1084 | 1086 | { |
| 1085 | 1087 | // overflow |
| 1086 | W_ACCUM_H(del, 0); | |
| 1087 | W_ACCUM_M(del, -32768); | |
| 1088 | W_ACCUM_L(del, -32768); | |
| 1089 | vres[del] = 0x7fff; | |
| 1088 | ACCUM_H(i) = 0; | |
| 1089 | ACCUM_M(i) = -32768; | |
| 1090 | ACCUM_L(i) = -32768; | |
| 1091 | vres[i] = 0x7fff; | |
| 1090 | 1092 | } |
| 1091 | 1093 | else |
| 1092 | 1094 | { |
| 1093 | | |
| 1095 | | |
| 1094 | 1096 | r += 0x8000; // rounding ? |
| 1095 | W_ACCUM_H(del, (r < 0) ? 0xffff : 0); // sign-extend to 48-bit | |
| 1096 | W_ACCUM_M(del, (INT16)(r >> 16)); | |
| 1097 | W_ACCUM_L(del, (UINT16)(r)); | |
| 1098 | vres[del] = R_ACCUM_M(del); | |
| 1097 | ACCUM_H(i) = (r < 0) ? 0xffff : 0; // sign-extend to 48-bit | |
| 1098 | ACCUM_M(i) = (INT16)(r >> 16); | |
| 1099 | ACCUM_L(i) = (UINT16)(r); | |
| 1100 | vres[i] = ACCUM_M(i); | |
| 1099 | 1101 | } |
| 1100 | 1102 | } |
| 1101 | 1103 | WRITEBACK_RESULT(); |
| r9854 | r9855 | |
| 1111 | 1113 | // ------------------------------------------------------ |
| 1112 | 1114 | // |
| 1113 | 1115 | |
| 1116 | int sel; | |
| 1117 | INT32 s1, s2; | |
| 1118 | INT64 r; | |
| 1114 | 1119 | for (i=0; i < 8; i++) |
| 1115 | 1120 | { |
| 1116 | int del = VEC_EL_1(EL, i); | |
| 1117 | int sel = VEC_EL_2(EL, del); | |
| 1118 | INT32 s1 = (INT32)(INT16)R_VREG_S(VS1REG, del); | |
| 1119 | INT32 s2 = (INT32)(INT16)R_VREG_S(VS2REG, sel); | |
| 1120 | INT64 r = s1 * s2 * 2; | |
| 1121 | sel = VEC_EL_2(EL, i); | |
| 1122 | s1 = (INT32)(INT16)VREG_S(VS1REG, i); | |
| 1123 | s2 = (INT32)(INT16)VREG_S(VS2REG, sel); | |
| 1124 | r = s1 * s2 * 2; | |
| 1121 | 1125 | r += 0x8000; // rounding ? |
| 1122 | 1126 | |
| 1123 | W_ACCUM_H(del, (UINT16)(r >> 32)); | |
| 1124 | W_ACCUM_M(del, (UINT16)(r >> 16)); | |
| 1125 | W_ACCUM_L(del, (UINT16)(r)); | |
| 1127 | ACCUM_H(i) = (UINT16)(r >> 32); | |
| 1128 | ACCUM_M(i) = (UINT16)(r >> 16); | |
| 1129 | ACCUM_L(i) = (UINT16)(r); | |
| 1126 | 1130 | |
| 1127 | 1131 | if (r < 0) |
| 1128 | 1132 | { |
| 1129 | vres[ | |
| 1133 | vres[i | |
| 1130 | 1134 | } |
| 1131 | else if (((INT16)( | |
| 1135 | else if (((INT16)( | |
| 1132 | 1136 | { |
| 1133 | vres[ | |
| 1137 | vres[i | |
| 1134 | 1138 | } |
| 1135 | 1139 | else |
| 1136 | 1140 | { |
| 1137 | vres[ | |
| 1141 | vres[i | |
| 1138 | 1142 | } |
| 1139 | 1143 | } |
| 1140 | 1144 | WRITEBACK_RESULT(); |
| r9854 | r9855 | |
| 1152 | 1156 | // Stores the higher 16 bits of the 32-bit result to accumulator |
| 1153 | 1157 | // The low slice of accumulator is stored into destination element |
| 1154 | 1158 | |
| 1159 | int sel; | |
| 1160 | UINT32 s1, s2; | |
| 1161 | UINT32 r; | |
| 1155 | 1162 | for (i=0; i < 8; i++) |
| 1156 | 1163 | { |
| 1157 | int del = VEC_EL_1(EL, i); | |
| 1158 | int sel = VEC_EL_2(EL, del); | |
| 1159 | UINT32 s1 = (UINT32)(UINT16)R_VREG_S(VS1REG, del); | |
| 1160 | UINT32 s2 = (UINT32)(UINT16)R_VREG_S(VS2REG, sel); | |
| 1161 | UINT32 r = s1 * s2; | |
| 1164 | sel = VEC_EL_2(EL, i); | |
| 1165 | s1 = (UINT32)(UINT16)VREG_S(VS1REG, i); | |
| 1166 | s2 = (UINT32)(UINT16)VREG_S(VS2REG, sel); | |
| 1167 | r = s1 * s2; | |
| 1162 | 1168 | |
| 1163 | W_ACCUM_H(del, 0); | |
| 1164 | W_ACCUM_M(del, 0); | |
| 1165 | W_ACCUM_L(del, (UINT16)(r >> 16)); | |
| 1169 | ACCUM_H(i) = 0; | |
| 1170 | ACCUM_M(i) = 0; | |
| 1171 | ACCUM_L(i) = (UINT16)(r >> 16); | |
| 1166 | 1172 | |
| 1167 | vres[ | |
| 1173 | vres[i | |
| 1168 | 1174 | } |
| 1169 | 1175 | WRITEBACK_RESULT(); |
| 1170 | 1176 | break; |
| r9854 | r9855 | |
| 1181 | 1187 | // The result is stored into accumulator |
| 1182 | 1188 | // The middle slice of accumulator is stored into destination element |
| 1183 | 1189 | |
| 1190 | int sel; | |
| 1191 | INT32 s1, s2; | |
| 1192 | INT32 r; | |
| 1184 | 1193 | for (i=0; i < 8; i++) |
| 1185 | 1194 | { |
| 1186 | int del = VEC_EL_1(EL, i); | |
| 1187 | int sel = VEC_EL_2(EL, del); | |
| 1188 | INT32 s1 = (INT32)(INT16)R_VREG_S(VS1REG, del); | |
| 1189 | INT32 s2 = (UINT16)R_VREG_S(VS2REG, sel); // not sign-extended | |
| 1190 | INT32 r = s1 * s2; | |
| 1195 | sel = VEC_EL_2(EL, i); | |
| 1196 | s1 = (INT32)(INT16)VREG_S(VS1REG, i); | |
| 1197 | s2 = (UINT16)VREG_S(VS2REG, sel); // not sign-extended | |
| 1198 | r = s1 * s2; | |
| 1191 | 1199 | |
| 1192 | W_ACCUM_H(del, (r < 0) ? 0xffff : 0); // sign-extend to 48-bit | |
| 1193 | W_ACCUM_M(del, (INT16)(r >> 16)); | |
| 1194 | W_ACCUM_L(del, (UINT16)(r)); | |
| 1200 | ACCUM_H(i) = (r < 0) ? 0xffff : 0; // sign-extend to 48-bit | |
| 1201 | ACCUM_M(i) = (INT16)(r >> 16); | |
| 1202 | ACCUM_L(i) = (UINT16)(r); | |
| 1195 | 1203 | |
| 1196 | vres[ | |
| 1204 | vres[i | |
| 1197 | 1205 | } |
| 1198 | 1206 | WRITEBACK_RESULT(); |
| 1199 | 1207 | break; |
| r9854 | r9855 | |
| 1211 | 1219 | // The result is stored into accumulator |
| 1212 | 1220 | // The low slice of accumulator is stored into destination element |
| 1213 | 1221 | |
| 1222 | int sel; | |
| 1223 | INT32 s1, s2; | |
| 1224 | INT32 r; | |
| 1214 | 1225 | for (i=0; i < 8; i++) |
| 1215 | 1226 | { |
| 1216 | int del = VEC_EL_1(EL, i); | |
| 1217 | int sel = VEC_EL_2(EL, del); | |
| 1218 | INT32 s1 = (UINT16)R_VREG_S(VS1REG, del); // not sign-extended | |
| 1219 | INT32 s2 = (INT32)(INT16)R_VREG_S(VS2REG, sel); | |
| 1220 | INT32 r = s1 * s2; | |
| 1227 | sel = VEC_EL_2(EL, i); | |
| 1228 | s1 = (UINT16)VREG_S(VS1REG, i); // not sign-extended | |
| 1229 | s2 = (INT32)(INT16)VREG_S(VS2REG, sel); | |
| 1230 | r = s1 * s2; | |
| 1221 | 1231 | |
| 1222 | W_ACCUM_H(del, (r < 0) ? 0xffff : 0); // sign-extend to 48-bit | |
| 1223 | W_ACCUM_M(del, (INT16)(r >> 16)); | |
| 1224 | W_ACCUM_L(del, (UINT16)(r)); | |
| 1232 | ACCUM_H(i) = (r < 0) ? 0xffff : 0; // sign-extend to 48-bit | |
| 1233 | ACCUM_M(i) = (INT16)(r >> 16); | |
| 1234 | ACCUM_L(i) = (UINT16)(r); | |
| 1225 | 1235 | |
| 1226 | vres[ | |
| 1236 | vres[i | |
| 1227 | 1237 | } |
| 1228 | 1238 | WRITEBACK_RESULT(); |
| 1229 | 1239 | break; |
| r9854 | r9855 | |
| 1240 | 1250 | // The result is stored into highest 32 bits of accumulator, the low slice is zero |
| 1241 | 1251 | // The highest 32 bits of accumulator is saturated into destination element |
| 1242 | 1252 | |
| 1253 | int sel; | |
| 1254 | INT32 s1, s2; | |
| 1255 | INT32 r; | |
| 1243 | 1256 | for (i=0; i < 8; i++) |
| 1244 | 1257 | { |
| 1245 | int del = VEC_EL_1(EL, i); | |
| 1246 | int sel = VEC_EL_2(EL, del); | |
| 1247 | INT32 s1 = (INT32)(INT16)R_VREG_S(VS1REG, del); | |
| 1248 | INT32 s2 = (INT32)(INT16)R_VREG_S(VS2REG, sel); | |
| 1249 | INT32 r = s1 * s2; | |
| 1258 | sel = VEC_EL_2(EL, i); | |
| 1259 | s1 = (INT32)(INT16)VREG_S(VS1REG, i); | |
| 1260 | s2 = (INT32)(INT16)VREG_S(VS2REG, sel); | |
| 1261 | r = s1 * s2; | |
| 1250 | 1262 | |
| 1251 | W_ACCUM_H(del, (INT16)(r >> 16)); | |
| 1252 | W_ACCUM_M(del, (UINT16)(r)); | |
| 1253 | W_ACCUM_L(del, 0); | |
| 1263 | ACCUM_H(i) = (INT16)(r >> 16); | |
| 1264 | ACCUM_M(i) = (UINT16)(r); | |
| 1265 | ACCUM_L(i) = 0; | |
| 1254 | 1266 | |
| 1255 | 1267 | if (r < -32768) r = -32768; |
| 1256 | 1268 | if (r > 32767) r = 32767; |
| 1257 | vres[ | |
| 1269 | vres[i | |
| 1258 | 1270 | } |
| 1259 | 1271 | WRITEBACK_RESULT(); |
| 1260 | 1272 | break; |
| r9854 | r9855 | |
| 1270 | 1282 | // Multiplies signed integer by signed integer * 2 |
| 1271 | 1283 | // The result is added to accumulator |
| 1272 | 1284 | |
| 1285 | int sel; | |
| 1286 | INT32 s1, s2; | |
| 1287 | INT32 r; | |
| 1288 | UINT16 res; | |
| 1273 | 1289 | for (i=0; i < 8; i++) |
| 1274 | 1290 | { |
| 1275 | UINT16 res; | |
| 1276 | int del = VEC_EL_1(EL, i); | |
| 1277 | int sel = VEC_EL_2(EL, del); | |
| 1278 | INT32 s1 = (INT32)(INT16)R_VREG_S(VS1REG, del); | |
| 1279 | INT32 s2 = (INT32)(INT16)R_VREG_S(VS2REG, sel); | |
| 1280 | INT32 r = s1 * s2; | |
| 1291 | sel = VEC_EL_2(EL, i); | |
| 1292 | s1 = (INT32)(INT16)VREG_S(VS1REG, i); | |
| 1293 | s2 = (INT32)(INT16)VREG_S(VS2REG, sel); | |
| 1294 | r = s1 * s2; | |
| 1281 | 1295 | |
| 1282 | ACCUM(del) += (INT64)(r) << 17; | |
| 1283 | res = SATURATE_ACCUM(rsp, del, 1, 0x8000, 0x7fff); | |
| 1296 | ACCUM(i) += (INT64)(r) << 17; | |
| 1297 | res = SATURATE_ACCUM(rsp, i, 1, 0x8000, 0x7fff); | |
| 1284 | 1298 | |
| 1285 | vres[ | |
| 1299 | vres[i | |
| 1286 | 1300 | } |
| 1287 | 1301 | WRITEBACK_RESULT(); |
| 1288 | 1302 | break; |
| r9854 | r9855 | |
| 1296 | 1310 | // ------------------------------------------------------ |
| 1297 | 1311 | // |
| 1298 | 1312 | |
| 1299 | for (i=0; i < 8; i++) | |
| 1313 | UINT16 res; | |
| 1314 | int sel; | |
| 1315 | INT32 s1, s2, r1; | |
| 1316 | UINT32 r2, r3; | |
| 1317 | for (i = 0; i < 8; i++) | |
| 1300 | 1318 | { |
| 1301 | UINT16 res; | |
| 1302 | int del = VEC_EL_1(EL, i); | |
| 1303 | int sel = VEC_EL_2(EL, del); | |
| 1304 | INT32 s1 = (INT32)(INT16)R_VREG_S(VS1REG, del); | |
| 1305 | INT32 s2 = (INT32)(INT16)R_VREG_S(VS2REG, sel); | |
| 1306 | INT32 r1 = s1 * s2; | |
| 1307 | UINT32 r2 = (UINT16)R_ACCUM_L(del) + ((UINT16)(r1) * 2); | |
| 1308 | UINT32 r3 = (UINT16)R_ACCUM_M(del) + (UINT16)((r1 >> 16) * 2) + (UINT16)(r2 >> 16); | |
| 1319 | sel = VEC_EL_2(EL, i); | |
| 1320 | s1 = (INT32)(INT16)VREG_S(VS1REG, i); | |
| 1321 | s2 = (INT32)(INT16)VREG_S(VS2REG, sel); | |
| 1322 | r1 = s1 * s2; | |
| 1323 | r2 = (UINT16)ACCUM_L(i) + ((UINT16)(r1) * 2); | |
| 1324 | r3 = (UINT16)ACCUM_M(i) + (UINT16)((r1 >> 16) * 2) + (UINT16)(r2 >> 16); | |
| 1309 | 1325 | |
| 1310 | W_ACCUM_L(del, (UINT16)(r2)); | |
| 1311 | W_ACCUM_M(del, (UINT16)(r3)); | |
| 1312 | W_ACCUM_H(del, (UINT16)R_ACCUM_H(del) + (UINT16)(r3 >> 16) + (UINT16)(r1 >> 31)); | |
| 1326 | ACCUM_L(i) = (UINT16)(r2); | |
| 1327 | ACCUM_M(i) = (UINT16)(r3); | |
| 1328 | ACCUM_H(i) += (UINT16)(r3 >> 16) + (UINT16)(r1 >> 31); | |
| 1313 | 1329 | |
| 1314 | //res = SATURATE_ACCUM(rsp, del, 1, 0x0000, 0xffff); | |
| 1315 | if ((INT16)R_ACCUM_H(del) < 0) | |
| 1330 | //res = SATURATE_ACCUM(i, 1, 0x0000, 0xffff); | |
| 1331 | if ((INT16)ACCUM_H(i) < 0) | |
| 1316 | 1332 | { |
| 1317 | 1333 | res = 0; |
| 1318 | 1334 | } |
| 1319 | 1335 | else |
| 1320 | 1336 | { |
| 1321 | if ( | |
| 1337 | if ( | |
| 1322 | 1338 | { |
| 1323 | 1339 | res = 0xffff; |
| 1324 | 1340 | } |
| 1325 | 1341 | else |
| 1326 | 1342 | { |
| 1327 | if ((INT16) | |
| 1343 | if ((INT16) | |
| 1328 | 1344 | { |
| 1329 | 1345 | res = 0xffff; |
| 1330 | 1346 | } |
| 1331 | 1347 | else |
| 1332 | 1348 | { |
| 1333 | res = | |
| 1349 | res = | |
| 1334 | 1350 | } |
| 1335 | 1351 | } |
| 1336 | 1352 | } |
| 1337 | 1353 | |
| 1338 | vres[ | |
| 1354 | vres[i | |
| 1339 | 1355 | } |
| 1340 | 1356 | WRITEBACK_RESULT(); |
| 1341 | 1357 | break; |
| r9854 | r9855 | |
| 1352 | 1368 | // Adds the higher 16 bits of the 32-bit result to accumulator |
| 1353 | 1369 | // The low slice of accumulator is stored into destination element |
| 1354 | 1370 | |
| 1355 | for (i=0; i < 8; i++) | |
| 1371 | UINT16 res; | |
| 1372 | int sel; | |
| 1373 | UINT32 s1, s2, r1; | |
| 1374 | UINT32 r2, r3; | |
| 1375 | for (i = 0; i < 8; i++) | |
| 1356 | 1376 | { |
| 1357 | UINT16 res; | |
| 1358 | int del = VEC_EL_1(EL, i); | |
| 1359 | int sel = VEC_EL_2(EL, del); | |
| 1360 | UINT32 s1 = (UINT32)(UINT16)R_VREG_S(VS1REG, del); | |
| 1361 | UINT32 s2 = (UINT32)(UINT16)R_VREG_S(VS2REG, sel); | |
| 1362 | UINT32 r1 = s1 * s2; | |
| 1363 | UINT32 r2 = (UINT16)R_ACCUM_L(del) + (r1 >> 16); | |
| 1364 | UINT32 r3 = (UINT16)R_ACCUM_M(del) + (r2 >> 16); | |
| 1377 | sel = VEC_EL_2(EL, i); | |
| 1378 | s1 = (UINT32)(UINT16)VREG_S(VS1REG, i); | |
| 1379 | s2 = (UINT32)(UINT16)VREG_S(VS2REG, sel); | |
| 1380 | r1 = s1 * s2; | |
| 1381 | r2 = (UINT16)ACCUM_L(i) + (r1 >> 16); | |
| 1382 | r3 = (UINT16)ACCUM_M(i) + (r2 >> 16); | |
| 1365 | 1383 | |
| 1366 | W_ACCUM_L(del, (UINT16)(r2)); | |
| 1367 | W_ACCUM_M(del, (UINT16)(r3)); | |
| 1368 | W_ACCUM_H(del, (INT16)R_ACCUM_H(del) + (INT16)(r3 >> 16)); | |
| 1384 | ACCUM_L(i) = (UINT16)(r2); | |
| 1385 | ACCUM_M(i) = (UINT16)(r3); | |
| 1386 | ACCUM_H(i) += (INT16)(r3 >> 16); | |
| 1369 | 1387 | |
| 1370 | res = SATURATE_ACCUM(rsp, | |
| 1388 | res = SATURATE_ACCUM(rsp, i | |
| 1371 | 1389 | |
| 1372 | vres[ | |
| 1390 | vres[i | |
| 1373 | 1391 | } |
| 1374 | 1392 | WRITEBACK_RESULT(); |
| 1375 | 1393 | break; |
| r9854 | r9855 | |
| 1386 | 1404 | // The result is added into accumulator |
| 1387 | 1405 | // The middle slice of accumulator is stored into destination element |
| 1388 | 1406 | |
| 1407 | UINT16 res; | |
| 1408 | int sel; | |
| 1409 | UINT32 s1, s2, r1; | |
| 1410 | UINT32 r2, r3; | |
| 1389 | 1411 | for (i=0; i < 8; i++) |
| 1390 | 1412 | { |
| 1391 | UINT16 res; | |
| 1392 | int del = VEC_EL_1(EL, i); | |
| 1393 | int sel = VEC_EL_2(EL, del); | |
| 1394 | UINT32 s1 = (INT32)(INT16)R_VREG_S(VS1REG, del); | |
| 1395 | UINT32 s2 = (UINT16)R_VREG_S(VS2REG, sel); // not sign-extended | |
| 1396 | UINT32 r1 = s1 * s2; | |
| 1397 | UINT32 r2 = (UINT16)R_ACCUM_L(del) + (UINT16)(r1); | |
| 1398 | UINT32 r3 = (UINT16)R_ACCUM_M(del) + (r1 >> 16) + (r2 >> 16); | |
| 1413 | sel = VEC_EL_2(EL, i); | |
| 1414 | s1 = (INT32)(INT16)VREG_S(VS1REG, i); | |
| 1415 | s2 = (UINT16)VREG_S(VS2REG, sel); // not sign-extended | |
| 1416 | r1 = s1 * s2; | |
| 1417 | r2 = (UINT16)ACCUM_L(i) + (UINT16)(r1); | |
| 1418 | r3 = (UINT16)ACCUM_M(i) + (r1 >> 16) + (r2 >> 16); | |
| 1399 | 1419 | |
| 1400 | W_ACCUM_L(del, (UINT16)(r2)); | |
| 1401 | W_ACCUM_M(del, (UINT16)(r3)); | |
| 1402 | W_ACCUM_H(del, (UINT16)R_ACCUM_H(del) + (UINT16)(r3 >> 16)); | |
| 1420 | ACCUM_L(i) = (UINT16)(r2); | |
| 1421 | ACCUM_M(i) = (UINT16)(r3); | |
| 1422 | ACCUM_H(i) += (UINT16)(r3 >> 16); | |
| 1403 | 1423 | if ((INT32)(r1) < 0) |
| 1404 | | |
| 1424 | | |
| 1405 | 1425 | |
| 1406 | res = SATURATE_ACCUM(rsp, | |
| 1426 | res = SATURATE_ACCUM(rsp, i | |
| 1407 | 1427 | |
| 1408 | vres[ | |
| 1428 | vres[i | |
| 1409 | 1429 | } |
| 1410 | 1430 | WRITEBACK_RESULT(); |
| 1411 | 1431 | break; |
| r9854 | r9855 | |
| 1422 | 1442 | // The result is added into accumulator |
| 1423 | 1443 | // The low slice of accumulator is stored into destination element |
| 1424 | 1444 | |
| 1445 | INT32 s1, s2; | |
| 1446 | UINT16 res; | |
| 1447 | int sel; | |
| 1425 | 1448 | for (i=0; i < 8; i++) |
| 1426 | 1449 | { |
| 1427 | UINT16 res; | |
| 1428 | int del = VEC_EL_1(EL, i); | |
| 1429 | int sel = VEC_EL_2(EL, del); | |
| 1430 | INT32 s1 = (UINT16)R_VREG_S(VS1REG, del); // not sign-extended | |
| 1431 | INT32 s2 = (INT32)(INT16)R_VREG_S(VS2REG, sel); | |
| 1432 | UINT32 r1 = s1 * s2; | |
| 1433 | UINT32 r2 = (UINT16)R_ACCUM_L(del) + (UINT16)(r1); | |
| 1434 | UINT32 r3 = (UINT16)R_ACCUM_M(del) + (r1 >> 16) + (r2 >> 16); | |
| 1450 | sel = VEC_EL_2(EL, i); | |
| 1451 | s1 = (UINT16)VREG_S(VS1REG, i); // not sign-extended | |
| 1452 | s2 = (INT32)(INT16)VREG_S(VS2REG, sel); | |
| 1435 | 1453 | |
| 1436 | W_ACCUM_L(del, (UINT16)(r2)); | |
| 1437 | W_ACCUM_M(del, (UINT16)(r3)); | |
| 1438 | W_ACCUM_H(del, (UINT16)R_ACCUM_H(del) + (UINT16)(r3 >> 16)); | |
| 1439 | if ((INT32)(r1) < 0) | |
| 1440 | W_ACCUM_H(del, (UINT16)R_ACCUM_H(del) - 1); | |
| 1454 | ACCUM(i) += (INT64)(s1*s2)<<16; | |
| 1441 | 1455 | |
| 1442 | res = SATURATE_ACCUM(rsp, del, 0, 0x0000, 0xffff); | |
| 1443 | ||
| 1444 | vres[del] = res; | |
| 1456 | res = SATURATE_ACCUM(rsp, i, 0, 0x0000, 0xffff); | |
| 1457 | vres[i] = res; | |
| 1445 | 1458 | } |
| 1446 | 1459 | WRITEBACK_RESULT(); |
| 1460 | ||
| 1447 | 1461 | break; |
| 1448 | 1462 | } |
| 1449 | 1463 | |
| r9854 | r9855 | |
| 1458 | 1472 | // The result is added into highest 32 bits of accumulator, the low slice is zero |
| 1459 | 1473 | // The highest 32 bits of accumulator is saturated into destination element |
| 1460 | 1474 | |
| 1461 | for (i=0; i < 8; i++) | |
| 1475 | UINT16 res; | |
| 1476 | int sel; | |
| 1477 | INT32 s1, s2; | |
| 1478 | for (i = 0; i < 8; i++) | |
| 1462 | 1479 | { |
| 1463 | UINT16 res; | |
| 1464 | int del = VEC_EL_1(EL, i); | |
| 1465 | int sel = VEC_EL_2(EL, del); | |
| 1466 | INT32 s1 = (INT32)(INT16)R_VREG_S(VS1REG, del); | |
| 1467 | INT32 s2 = (INT32)(INT16)R_VREG_S(VS2REG, sel); | |
| 1468 | INT64 r = s1 * s2; | |
| 1480 | sel = VEC_EL_2(EL, i); | |
| 1481 | s1 = (INT32)(INT16)VREG_S(VS1REG, i); | |
| 1482 | s2 = (INT32)(INT16)VREG_S(VS2REG, sel); | |
| 1469 | 1483 | |
| 1470 | | |
| 1484 | rsp->accum[i].l[1] += s1*s | |
| 1471 | 1485 | |
| 1472 | res = SATURATE_ACCUM(rsp, | |
| 1486 | res = SATURATE_ACCUM1(rsp, i | |
| 1473 | 1487 | |
| 1474 | vres[ | |
| 1488 | vres[i | |
| 1475 | 1489 | } |
| 1476 | 1490 | WRITEBACK_RESULT(); |
| 1491 | ||
| 1477 | 1492 | break; |
| 1478 | 1493 | } |
| 1479 | 1494 | |
| r9854 | r9855 | |
| 1488 | 1503 | |
| 1489 | 1504 | // TODO: check VS2REG == VDREG |
| 1490 | 1505 | |
| 1506 | int sel; | |
| 1507 | INT32 s1, s2, r; | |
| 1491 | 1508 | for (i=0; i < 8; i++) |
| 1492 | 1509 | { |
| 1493 | int del = VEC_EL_1(EL, i); | |
| 1494 | int sel = VEC_EL_2(EL, del); | |
| 1495 | INT32 s1 = (INT32)(INT16)R_VREG_S(VS1REG, del); | |
| 1496 | INT32 s2 = (INT32)(INT16)R_VREG_S(VS2REG, sel); | |
| 1497 | INT32 r = s1 + s2 + CARRY_FLAG(del); | |
| 1510 | sel = VEC_EL_2(EL, i); | |
| 1511 | s1 = (INT32)(INT16)VREG_S(VS1REG, i); | |
| 1512 | s2 = (INT32)(INT16)VREG_S(VS2REG, sel); | |
| 1513 | r = s1 + s2 + CARRY_FLAG(i); | |
| 1498 | 1514 | |
| 1499 | | |
| 1515 | | |
| 1500 | 1516 | |
| 1501 | 1517 | if (r > 32767) r = 32767; |
| 1502 | 1518 | if (r < -32768) r = -32768; |
| 1503 | vres[ | |
| 1519 | vres[i | |
| 1504 | 1520 | } |
| 1505 | 1521 | CLEAR_ZERO_FLAGS(); |
| 1506 | 1522 | CLEAR_CARRY_FLAGS(); |
| r9854 | r9855 | |
| 1519 | 1535 | |
| 1520 | 1536 | // TODO: check VS2REG == VDREG |
| 1521 | 1537 | |
| 1522 | for (i=0; i < 8; i++) | |
| 1538 | int sel; | |
| 1539 | INT32 s1, s2, r; | |
| 1540 | for (i = 0; i < 8; i++) | |
| 1523 | 1541 | { |
| 1524 | int del = VEC_EL_1(EL, i); | |
| 1525 | int sel = VEC_EL_2(EL, del); | |
| 1526 | INT32 s1 = (INT32)(INT16)R_VREG_S(VS1REG, del); | |
| 1527 | INT32 s2 = (INT32)(INT16)R_VREG_S(VS2REG, sel); | |
| 1528 | INT32 r = s1 - s2 - CARRY_FLAG(del); | |
| 1542 | sel = VEC_EL_2(EL, i); | |
| 1543 | s1 = (INT32)(INT16)VREG_S(VS1REG, i); | |
| 1544 | s2 = (INT32)(INT16)VREG_S(VS2REG, sel); | |
| 1545 | r = s1 - s2 - CARRY_FLAG(i); | |
| 1529 | 1546 | |
| 1530 | | |
| 1547 | | |
| 1531 | 1548 | |
| 1532 | 1549 | if (r > 32767) r = 32767; |
| 1533 | 1550 | if (r < -32768) r = -32768; |
| 1534 | 1551 | |
| 1535 | vres[ | |
| 1552 | vres[i | |
| 1536 | 1553 | } |
| 1537 | 1554 | CLEAR_ZERO_FLAGS(); |
| 1538 | 1555 | CLEAR_CARRY_FLAGS(); |
| r9854 | r9855 | |
| 1550 | 1567 | // Changes the sign of source register 2 if source register 1 is negative and stores |
| 1551 | 1568 | // the result to destination register |
| 1552 | 1569 | |
| 1570 | int sel; | |
| 1571 | INT16 s1, s2; | |
| 1553 | 1572 | for (i=0; i < 8; i++) |
| 1554 | 1573 | { |
| 1555 | int del = VEC_EL_1(EL, i); | |
| 1556 | int sel = VEC_EL_2(EL, del); | |
| 1557 | INT16 s1 = (INT16)R_VREG_S(VS1REG, del); | |
| 1558 | INT16 s2 = (INT16)R_VREG_S(VS2REG, sel); | |
| 1574 | sel = VEC_EL_2(EL, i); | |
| 1575 | s1 = (INT16)VREG_S(VS1REG, i); | |
| 1576 | s2 = (INT16)VREG_S(VS2REG, sel); | |
| 1559 | 1577 | |
| 1560 | 1578 | if (s1 < 0) |
| 1561 | 1579 | { |
| 1562 | 1580 | if (s2 == -32768) |
| 1563 | 1581 | { |
| 1564 | vres[ | |
| 1582 | vres[i | |
| 1565 | 1583 | } |
| 1566 | 1584 | else |
| 1567 | 1585 | { |
| 1568 | vres[ | |
| 1586 | vres[i | |
| 1569 | 1587 | } |
| 1570 | 1588 | } |
| 1571 | 1589 | else if (s1 > 0) |
| 1572 | 1590 | { |
| 1573 | vres[ | |
| 1591 | vres[i | |
| 1574 | 1592 | } |
| 1575 | 1593 | else |
| 1576 | 1594 | { |
| 1577 | vres[ | |
| 1595 | vres[i | |
| 1578 | 1596 | } |
| 1579 | 1597 | |
| 1580 | | |
| 1598 | | |
| 1581 | 1599 | } |
| 1582 | 1600 | WRITEBACK_RESULT(); |
| 1583 | 1601 | break; |
| r9854 | r9855 | |
| 1594 | 1612 | |
| 1595 | 1613 | // TODO: check VS2REG = VDREG |
| 1596 | 1614 | |
| 1615 | int sel; | |
| 1616 | INT32 s1, s2, r; | |
| 1597 | 1617 | CLEAR_ZERO_FLAGS(); |
| 1598 | 1618 | CLEAR_CARRY_FLAGS(); |
| 1599 | 1619 | |
| 1600 | 1620 | for (i=0; i < 8; i++) |
| 1601 | 1621 | { |
| 1602 | int del = VEC_EL_1(EL, i); | |
| 1603 | int sel = VEC_EL_2(EL, del); | |
| 1604 | INT32 s1 = (UINT32)(UINT16)R_VREG_S(VS1REG, del); | |
| 1605 | INT32 s2 = (UINT32)(UINT16)R_VREG_S(VS2REG, sel); | |
| 1606 | INT32 r = s1 + s2; | |
| 1622 | sel = VEC_EL_2(EL, i); | |
| 1623 | s1 = (UINT32)(UINT16)VREG_S(VS1REG, i); | |
| 1624 | s2 = (UINT32)(UINT16)VREG_S(VS2REG, sel); | |
| 1625 | r = s1 + s2; | |
| 1607 | 1626 | |
| 1608 | vres[del] = (INT16)(r); | |
| 1609 | W_ACCUM_L(del, (INT16)(r)); | |
| 1627 | vres[i] = (INT16)(r); | |
| 1628 | ACCUM_L(i) = (INT16)(r); | |
| 1610 | 1629 | |
| 1611 | 1630 | if (r & 0xffff0000) |
| 1612 | 1631 | { |
| 1613 | SET_CARRY_FLAG( | |
| 1632 | SET_CARRY_FLAG(i | |
| 1614 | 1633 | } |
| 1615 | 1634 | } |
| 1616 | 1635 | WRITEBACK_RESULT(); |
| r9854 | r9855 | |
| 1628 | 1647 | |
| 1629 | 1648 | // TODO: check VS2REG = VDREG |
| 1630 | 1649 | |
| 1650 | int sel; | |
| 1651 | INT32 s1, s2, r; | |
| 1631 | 1652 | CLEAR_ZERO_FLAGS(); |
| 1632 | 1653 | CLEAR_CARRY_FLAGS(); |
| 1633 | 1654 | |
| 1634 | 1655 | for (i=0; i < 8; i++) |
| 1635 | 1656 | { |
| 1636 | int del = VEC_EL_1(EL, i); | |
| 1637 | int sel = VEC_EL_2(EL, del); | |
| 1638 | INT32 s1 = (UINT32)(UINT16)R_VREG_S(VS1REG, del); | |
| 1639 | INT32 s2 = (UINT32)(UINT16)R_VREG_S(VS2REG, sel); | |
| 1640 | INT32 r = s1 - s2; | |
| 1657 | sel = VEC_EL_2(EL, i); | |
| 1658 | s1 = (UINT32)(UINT16)VREG_S(VS1REG, i); | |
| 1659 | s2 = (UINT32)(UINT16)VREG_S(VS2REG, sel); | |
| 1660 | r = s1 - s2; | |
| 1641 | 1661 | |
| 1642 | vres[del] = (INT16)(r); | |
| 1643 | W_ACCUM_L(del, (UINT16)(r)); | |
| 1662 | vres[i] = (INT16)(r); | |
| 1663 | ACCUM_L(i) = (UINT16)(r); | |
| 1644 | 1664 | |
| 1645 | 1665 | if ((UINT16)(r) != 0) |
| 1646 | 1666 | { |
| 1647 | SET_ZERO_FLAG( | |
| 1667 | SET_ZERO_FLAG(i | |
| 1648 | 1668 | } |
| 1649 | 1669 | if (r & 0xffff0000) |
| 1650 | 1670 | { |
| 1651 | SET_CARRY_FLAG( | |
| 1671 | SET_CARRY_FLAG(i | |
| 1652 | 1672 | } |
| 1653 | 1673 | } |
| 1654 | 1674 | WRITEBACK_RESULT(); |
| r9854 | r9855 | |
| 1670 | 1690 | { |
| 1671 | 1691 | for (i=0; i < 8; i++) |
| 1672 | 1692 | { |
| 1673 | | |
| 1693 | | |
| 1674 | 1694 | } |
| 1675 | 1695 | break; |
| 1676 | 1696 | } |
| r9854 | r9855 | |
| 1678 | 1698 | { |
| 1679 | 1699 | for (i=0; i < 8; i++) |
| 1680 | 1700 | { |
| 1681 | | |
| 1701 | | |
| 1682 | 1702 | } |
| 1683 | 1703 | break; |
| 1684 | 1704 | } |
| r9854 | r9855 | |
| 1686 | 1706 | { |
| 1687 | 1707 | for (i=0; i < 8; i++) |
| 1688 | 1708 | { |
| 1689 | | |
| 1709 | | |
| 1690 | 1710 | } |
| 1691 | 1711 | break; |
| 1692 | 1712 | } |
| 1693 | default: fatalerror("RSP: VSAW: el = %d\n", EL); | |
| 1713 | default: //fatalerror("RSP: VSAW: el = %d\n", EL);//ïîòóïèì | |
| 1714 | printf("RSP: VSAW: el = %d\n", EL);//ìîé êîä | |
| 1715 | exit(0); | |
| 1694 | 1716 | } |
| 1695 | 1717 | break; |
| 1696 | 1718 | } |
| r9854 | r9855 | |
| 1705 | 1727 | // Sets compare flags if elements in VS1 are less than VS2 |
| 1706 | 1728 | // Moves the element in VS2 to destination vector |
| 1707 | 1729 | |
| 1730 | int sel; | |
| 1708 | 1731 | rsp->flag[1] = 0; |
| 1709 | 1732 | |
| 1710 | 1733 | for (i=0; i < 8; i++) |
| 1711 | 1734 | { |
| 1712 | int del = VEC_EL_1(EL, i); | |
| 1713 | int sel = VEC_EL_2(EL, del); | |
| 1735 | sel = VEC_EL_2(EL, i); | |
| 1714 | 1736 | |
| 1715 | if ( | |
| 1737 | if ( | |
| 1716 | 1738 | { |
| 1717 | vres[del] = R_VREG_S(VS1REG, del); | |
| 1718 | SET_COMPARE_FLAG(del); | |
| 1739 | SET_COMPARE_FLAG(i); | |
| 1719 | 1740 | } |
| 1720 | else if ( | |
| 1741 | else if ( | |
| 1721 | 1742 | { |
| 1722 | vres[del] = R_VREG_S(VS1REG, del); | |
| 1723 | if (ZERO_FLAG(del) != 0 && CARRY_FLAG(del) != 0) | |
| 1743 | if (ZERO_FLAG(i) == 1 && CARRY_FLAG(i) != 0) | |
| 1724 | 1744 | { |
| 1725 | SET_COMPARE_FLAG( | |
| 1745 | SET_COMPARE_FLAG(i | |
| 1726 | 1746 | } |
| 1727 | 1747 | } |
| 1748 | ||
| 1749 | if (COMPARE_FLAG(i)) | |
| 1750 | { | |
| 1751 | vres[i] = VREG_S(VS1REG, i); | |
| 1752 | } | |
| 1728 | 1753 | else |
| 1729 | 1754 | { |
| 1730 | vres[ | |
| 1755 | vres[i | |
| 1731 | 1756 | } |
| 1732 | 1757 | |
| 1733 | | |
| 1758 | | |
| 1734 | 1759 | } |
| 1735 | 1760 | |
| 1736 | CLEAR_ZERO_FLAGS(); | |
| 1737 | CLEAR_CARRY_FLAGS(); | |
| 1761 | rsp->flag[0] = 0; | |
| 1738 | 1762 | WRITEBACK_RESULT(); |
| 1739 | 1763 | break; |
| 1740 | 1764 | } |
| r9854 | r9855 | |
| 1749 | 1773 | // Sets compare flags if elements in VS1 are equal with VS2 |
| 1750 | 1774 | // Moves the element in VS2 to destination vector |
| 1751 | 1775 | |
| 1776 | int sel; | |
| 1752 | 1777 | rsp->flag[1] = 0; |
| 1753 | 1778 | |
| 1754 | for (i=0; i < 8; i++) | |
| 1779 | for (i = 0; i < 8; i++) | |
| 1755 | 1780 | { |
| 1756 | int del = VEC_EL_1(EL, i); | |
| 1757 | int sel = VEC_EL_2(EL, del); | |
| 1781 | sel = VEC_EL_2(EL, i); | |
| 1758 | 1782 | |
| 1759 | vres[del] = R_VREG_S(VS2REG, sel); | |
| 1760 | W_ACCUM_L(del, vres[del]); | |
| 1761 | ||
| 1762 | if (R_VREG_S(VS1REG, del) == R_VREG_S(VS2REG, sel)) | |
| 1783 | if ((VREG_S(VS1REG, i) == VREG_S(VS2REG, sel)) && ZERO_FLAG(i) == 0) | |
| 1763 | 1784 | { |
| 1764 | if (ZERO_FLAG(del) == 0) | |
| 1765 | { | |
| 1766 | SET_COMPARE_FLAG(del); | |
| 1767 | } | |
| 1785 | SET_COMPARE_FLAG(i); | |
| 1786 | vres[i] = VREG_S(VS1REG, i); | |
| 1768 | 1787 | } |
| 1788 | else | |
| 1789 | { | |
| 1790 | vres[i] = VREG_S(VS2REG, sel); | |
| 1791 | } | |
| 1792 | ACCUM_L(i) = vres[i]; | |
| 1769 | 1793 | } |
| 1770 | 1794 | |
| 1771 | CLEAR_ZERO_FLAGS(); | |
| 1772 | CLEAR_CARRY_FLAGS(); | |
| 1795 | rsp->flag[0] = 0; | |
| 1773 | 1796 | WRITEBACK_RESULT(); |
| 1774 | 1797 | break; |
| 1775 | 1798 | } |
| r9854 | r9855 | |
| 1784 | 1807 | // Sets compare flags if elements in VS1 are not equal with VS2 |
| 1785 | 1808 | // Moves the element in VS2 to destination vector |
| 1786 | 1809 | |
| 1810 | int sel; | |
| 1787 | 1811 | rsp->flag[1] = 0; |
| 1788 | 1812 | |
| 1789 | for (i=0; i < 8; i++) | |
| 1813 | for (i=0; i < 8; i++)//ïåðåïèñàíî ìíîé | |
| 1790 | 1814 | { |
| 1791 | int del = VEC_EL_1(EL, i); | |
| 1792 | int sel = VEC_EL_2(EL, del); | |
| 1815 | sel = VEC_EL_2(EL, i); | |
| 1793 | 1816 | |
| 1794 | vres[del] = R_VREG_S(VS1REG, del); | |
| 1795 | W_ACCUM_L(del, vres[del]); | |
| 1796 | ||
| 1797 | if (R_VREG_S(VS1REG, del) != R_VREG_S(VS2REG, sel)) | |
| 1817 | if (VREG_S(VS1REG, i) != VREG_S(VS2REG, sel)) | |
| 1798 | 1818 | { |
| 1799 | SET_COMPARE_FLAG( | |
| 1819 | SET_COMPARE_FLAG(i | |
| 1800 | 1820 | } |
| 1801 | 1821 | else |
| 1802 | 1822 | { |
| 1803 | if (ZERO_FLAG( | |
| 1823 | if (ZERO_FLAG(i | |
| 1804 | 1824 | { |
| 1805 | SET_COMPARE_FLAG( | |
| 1825 | SET_COMPARE_FLAG(i | |
| 1806 | 1826 | } |
| 1807 | 1827 | } |
| 1828 | if (COMPARE_FLAG(i)) | |
| 1829 | { | |
| 1830 | vres[i] = VREG_S(VS1REG, i); | |
| 1831 | } | |
| 1832 | else | |
| 1833 | { | |
| 1834 | vres[i] = VREG_S(VS2REG, sel); | |
| 1835 | } | |
| 1836 | ACCUM_L(i) = vres[i]; | |
| 1808 | 1837 | } |
| 1809 | 1838 | |
| 1810 | CLEAR_ZERO_FLAGS(); | |
| 1811 | CLEAR_CARRY_FLAGS(); | |
| 1839 | rsp->flag[0] = 0; | |
| 1812 | 1840 | WRITEBACK_RESULT(); |
| 1813 | 1841 | break; |
| 1814 | 1842 | } |
| r9854 | r9855 | |
| 1823 | 1851 | // Sets compare flags if elements in VS1 are greater or equal with VS2 |
| 1824 | 1852 | // Moves the element in VS2 to destination vector |
| 1825 | 1853 | |
| 1854 | int sel; | |
| 1826 | 1855 | rsp->flag[1] = 0; |
| 1827 | 1856 | |
| 1828 | 1857 | for (i=0; i < 8; i++) |
| 1829 | 1858 | { |
| 1830 | int del = VEC_EL_1(EL, i); | |
| 1831 | int sel = VEC_EL_2(EL, del); | |
| 1859 | sel = VEC_EL_2(EL, i); | |
| 1832 | 1860 | |
| 1833 | if ( | |
| 1861 | if ( | |
| 1834 | 1862 | { |
| 1835 | if (ZERO_FLAG( | |
| 1863 | if (ZERO_FLAG(i | |
| 1836 | 1864 | { |
| 1837 | SET_COMPARE_FLAG( | |
| 1865 | SET_COMPARE_FLAG(i | |
| 1838 | 1866 | } |
| 1839 | 1867 | } |
| 1840 | else if ( | |
| 1868 | else if ( | |
| 1841 | 1869 | { |
| 1842 | SET_COMPARE_FLAG( | |
| 1870 | SET_COMPARE_FLAG(i | |
| 1843 | 1871 | } |
| 1844 | 1872 | |
| 1845 | if (COMPARE_FLAG( | |
| 1873 | if (COMPARE_FLAG(i | |
| 1846 | 1874 | { |
| 1847 | vres[ | |
| 1875 | vres[i | |
| 1848 | 1876 | } |
| 1849 | 1877 | else |
| 1850 | 1878 | { |
| 1851 | vres[ | |
| 1879 | vres[i | |
| 1852 | 1880 | } |
| 1853 | 1881 | |
| 1854 | | |
| 1882 | | |
| 1855 | 1883 | } |
| 1856 | 1884 | |
| 1857 | CLEAR_ZERO_FLAGS(); | |
| 1858 | CLEAR_CARRY_FLAGS(); | |
| 1885 | rsp->flag[0] = 0; | |
| 1859 | 1886 | WRITEBACK_RESULT(); |
| 1860 | 1887 | break; |
| 1861 | 1888 | } |
| r9854 | r9855 | |
| 1869 | 1896 | // |
| 1870 | 1897 | // Vector clip low |
| 1871 | 1898 | |
| 1872 | for (i=0; i < 8; i++) | |
| 1899 | int sel; | |
| 1900 | INT16 s1, s2; | |
| 1901 | for (i = 0; i < 8; i++) | |
| 1873 | 1902 | { |
| 1874 | int del = VEC_EL_1(EL, i); | |
| 1875 | int sel = VEC_EL_2(EL, del); | |
| 1876 | INT16 s1 = R_VREG_S(VS1REG, del); | |
| 1877 | INT16 s2 = R_VREG_S(VS2REG, sel); | |
| 1903 | sel = VEC_EL_2(EL, i); | |
| 1904 | s1 = VREG_S(VS1REG, i); | |
| 1905 | s2 = VREG_S(VS2REG, sel); | |
| 1878 | 1906 | |
| 1879 | if (CARRY_FLAG( | |
| 1907 | if (CARRY_FLAG(i | |
| 1880 | 1908 | { |
| 1881 | if (ZERO_FLAG(del) != 0) | |
| 1909 | ||
| 1910 | if (ZERO_FLAG(i) != 0) | |
| 1882 | 1911 | { |
| 1883 | if (COMPARE_FLAG(del) != 0) | |
| 1912 | ||
| 1913 | if (COMPARE_FLAG(i) != 0) | |
| 1884 | 1914 | { |
| 1885 | | |
| 1915 | | |
| 1886 | 1916 | } |
| 1887 | 1917 | else |
| 1888 | 1918 | { |
| 1889 | | |
| 1919 | | |
| 1890 | 1920 | } |
| 1891 | 1921 | } |
| 1892 | else | |
| 1922 | else//ZERO_FLAG(i)==0 | |
| 1893 | 1923 | { |
| 1894 | if (rsp->flag[2] & (1 << (del))) | |
| 1924 | ||
| 1925 | if (rsp->flag[2] & (1 << (i))) | |
| 1895 | 1926 | { |
| 1927 | ||
| 1896 | 1928 | if (((UINT32)(UINT16)(s1) + (UINT32)(UINT16)(s2)) > 0x10000) |
| 1897 | { | |
| 1898 | W_ACCUM_L(del, s1); | |
| 1899 | CLEAR_COMPARE_FLAG(del); | |
| 1929 | {//proper fix for Harvest Moon 64, r4 | |
| 1930 | ||
| 1931 | ACCUM_L(i) = s1; | |
| 1932 | CLEAR_COMPARE_FLAG(i); | |
| 1900 | 1933 | } |
| 1901 | 1934 | else |
| 1902 | 1935 | { |
| 1903 | W_ACCUM_L(del, -((UINT16)s2)); | |
| 1904 | SET_COMPARE_FLAG(del); | |
| 1936 | ||
| 1937 | ACCUM_L(i) = -((UINT16)s2); | |
| 1938 | SET_COMPARE_FLAG(i); | |
| 1905 | 1939 | } |
| 1906 | 1940 | } |
| 1907 | 1941 | else |
| 1908 | 1942 | { |
| 1909 | if (((UINT32)(INT16)(s1) + (UINT32)(INT16)(s2)) != 0) | |
| 1943 | if (((UINT32)(UINT16)(s1) + (UINT32)(UINT16)(s2)) != 0) | |
| 1910 | 1944 | { |
| 1911 | W_ACCUM_L(del, s1); | |
| 1912 | CLEAR_COMPARE_FLAG(del); | |
| 1945 | ACCUM_L(i) = s1; | |
| 1946 | CLEAR_COMPARE_FLAG(i); | |
| 1913 | 1947 | } |
| 1914 | 1948 | else |
| 1915 | 1949 | { |
| 1916 | W_ACCUM_L(del, -((UINT16)s2)); | |
| 1917 | SET_COMPARE_FLAG(del); | |
| 1950 | ACCUM_L(i) = -((UINT16)s2); | |
| 1951 | SET_COMPARE_FLAG(i); | |
| 1918 | 1952 | } |
| 1919 | 1953 | } |
| 1920 | 1954 | } |
| 1921 | } | |
| 1922 | else | |
| 1955 | }// | |
| 1956 | else//CARRY_FLAG(i)==0 | |
| 1923 | 1957 | { |
| 1924 | if (ZERO_FLAG(del) != 0) | |
| 1958 | ||
| 1959 | if (ZERO_FLAG(i) != 0) | |
| 1925 | 1960 | { |
| 1926 | if (rsp->flag[1] & (1 << (8+del))) | |
| 1961 | ||
| 1962 | if (rsp->flag[1] & (1 << (8+i))) | |
| 1927 | 1963 | { |
| 1928 | | |
| 1964 | | |
| 1929 | 1965 | } |
| 1930 | 1966 | else |
| 1931 | 1967 | { |
| 1932 | | |
| 1968 | | |
| 1933 | 1969 | } |
| 1934 | 1970 | } |
| 1935 | 1971 | else |
| 1936 | 1972 | { |
| 1937 | 1973 | if (((INT32)(UINT16)s1 - (INT32)(UINT16)s2) >= 0) |
| 1938 | 1974 | { |
| 1939 | W_ACCUM_L(del, s2); | |
| 1940 | rsp->flag[1] |= (1 << (8+del)); | |
| 1975 | ACCUM_L(i) = s2; | |
| 1976 | rsp->flag[1] |= (1 << (8+i)); | |
| 1941 | 1977 | } |
| 1942 | 1978 | else |
| 1943 | 1979 | { |
| 1944 | W_ACCUM_L(del, s1); | |
| 1945 | rsp->flag[1] &= ~(1 << (8+del)); | |
| 1980 | ACCUM_L(i) = s1; | |
| 1981 | rsp->flag[1] &= ~(1 << (8+i)); | |
| 1946 | 1982 | } |
| 1947 | 1983 | } |
| 1948 | 1984 | } |
| 1949 | 1985 | |
| 1950 | vres[ | |
| 1986 | vres[i | |
| 1951 | 1987 | } |
| 1952 | CLEAR_ZERO_FLAGS(); | |
| 1953 | CLEAR_CARRY_FLAGS(); | |
| 1988 | rsp->flag[0] = 0; | |
| 1954 | 1989 | rsp->flag[2] = 0; |
| 1955 | 1990 | WRITEBACK_RESULT(); |
| 1956 | 1991 | break; |
| r9854 | r9855 | |
| 1965 | 2000 | // |
| 1966 | 2001 | // Vector clip high |
| 1967 | 2002 | |
| 1968 | CLEAR_ZERO_FLAGS(); | |
| 1969 | CLEAR_CARRY_FLAGS(); | |
| 2003 | int sel; | |
| 2004 | INT16 s1, s2; | |
| 2005 | rsp->flag[0] = 0; | |
| 1970 | 2006 | rsp->flag[1] = 0; |
| 1971 | 2007 | rsp->flag[2] = 0; |
| 2008 | UINT32 vce = 0; | |
| 1972 | 2009 | |
| 1973 | 2010 | for (i=0; i < 8; i++) |
| 1974 | 2011 | { |
| 1975 | int del = VEC_EL_1(EL, i); | |
| 1976 | int sel = VEC_EL_2(EL, del); | |
| 1977 | INT16 s1 = R_VREG_S(VS1REG, del); | |
| 1978 | INT16 s2 = R_VREG_S(VS2REG, sel); | |
| 2012 | sel = VEC_EL_2(EL, i); | |
| 2013 | s1 = VREG_S(VS1REG, i); | |
| 2014 | s2 = VREG_S(VS2REG, sel); | |
| 1979 | 2015 | |
| 1980 | 2016 | if ((s1 ^ s2) < 0) |
| 1981 | 2017 | { |
| 1982 | SET_CARRY_FLAG(del); | |
| 2018 | vce = (s1 + s2 == -1); | |
| 2019 | SET_CARRY_FLAG(i); | |
| 1983 | 2020 | if (s2 < 0) |
| 1984 | 2021 | { |
| 1985 | rsp->flag[1] |= (1 << (8+ | |
| 2022 | rsp->flag[1] |= (1 << (8+i | |
| 1986 | 2023 | } |
| 1987 | 2024 | |
| 1988 | 2025 | if (s1 + s2 <= 0) |
| 1989 | 2026 | { |
| 1990 | if (s1 + s2 == -1) | |
| 1991 | { | |
| 1992 | rsp->flag[2] |= (1 << (del)); | |
| 1993 | } | |
| 1994 | SET_COMPARE_FLAG(del); | |
| 1995 | vres[del] = -((UINT16)s2); | |
| 2027 | SET_COMPARE_FLAG(i); | |
| 2028 | vres[i] = -((UINT16)s2); | |
| 1996 | 2029 | } |
| 1997 | 2030 | else |
| 1998 | 2031 | { |
| 1999 | vres[ | |
| 2032 | vres[i | |
| 2000 | 2033 | } |
| 2001 | 2034 | |
| 2002 | 2035 | if (s1 + s2 != 0) |
| 2003 | 2036 | { |
| 2004 | 2037 | if (s1 != ~s2) |
| 2005 | 2038 | { |
| 2006 | SET_ZERO_FLAG( | |
| 2039 | SET_ZERO_FLAG(i | |
| 2007 | 2040 | } |
| 2008 | 2041 | } |
| 2009 | } | |
| 2042 | }//sign | |
| 2010 | 2043 | else |
| 2011 | 2044 | { |
| 2045 | vce = 0; | |
| 2012 | 2046 | if (s2 < 0) |
| 2013 | 2047 | { |
| 2014 | SET_COMPARE_FLAG( | |
| 2048 | SET_COMPARE_FLAG(i | |
| 2015 | 2049 | } |
| 2016 | 2050 | if (s1 - s2 >= 0) |
| 2017 | 2051 | { |
| 2018 | rsp->flag[1] |= (1 << (8+del)); | |
| 2019 | vres[del] = s2; | |
| 2052 | rsp->flag[1] |= (1 << (8+i)); | |
| 2053 | vres[i] = s2; | |
| 2020 | 2054 | } |
| 2021 | 2055 | else |
| 2022 | 2056 | { |
| 2023 | vres[ | |
| 2057 | vres[i | |
| 2024 | 2058 | } |
| 2025 | 2059 | |
| 2026 | 2060 | if ((s1 - s2) != 0) |
| 2027 | 2061 | { |
| 2028 | 2062 | if (s1 != ~s2) |
| 2029 | 2063 | { |
| 2030 | SET_ZERO_FLAG( | |
| 2064 | SET_ZERO_FLAG(i | |
| 2031 | 2065 | } |
| 2032 | 2066 | } |
| 2033 | 2067 | } |
| 2034 | ||
| 2035 | W_ACCUM_L(del, vres[del]); | |
| 2068 | rsp->flag[2] |= (vce << (i)); | |
| 2069 | ACCUM_L(i) = vres[i]; | |
| 2036 | 2070 | } |
| 2037 | 2071 | WRITEBACK_RESULT(); |
| 2038 | 2072 | break; |
| r9854 | r9855 | |
| 2047 | 2081 | // |
| 2048 | 2082 | // Vector clip reverse |
| 2049 | 2083 | |
| 2084 | int sel; | |
| 2085 | INT16 s1, s2; | |
| 2050 | 2086 | rsp->flag[0] = 0; |
| 2051 | 2087 | rsp->flag[1] = 0; |
| 2052 | 2088 | rsp->flag[2] = 0; |
| 2053 | 2089 | |
| 2054 | 2090 | for (i=0; i < 8; i++) |
| 2055 | 2091 | { |
| 2056 | int del = VEC_EL_1(EL, i); | |
| 2057 | int sel = VEC_EL_2(EL, del); | |
| 2058 | INT16 s1 = R_VREG_S(VS1REG, del); | |
| 2059 | INT16 s2 = R_VREG_S(VS2REG, sel); | |
| 2092 | sel = VEC_EL_2(EL, i); | |
| 2093 | s1 = VREG_S(VS1REG, i); | |
| 2094 | s2 = VREG_S(VS2REG, sel); | |
| 2060 | 2095 | |
| 2061 | 2096 | if ((INT16)(s1 ^ s2) < 0) |
| 2062 | 2097 | { |
| 2063 | 2098 | if (s2 < 0) |
| 2064 | 2099 | { |
| 2065 | rsp->flag[1] |= (1 << (8+ | |
| 2100 | rsp->flag[1] |= (1 << (8+i | |
| 2066 | 2101 | } |
| 2067 | 2102 | if ((s1 + s2) <= 0) |
| 2068 | 2103 | { |
| 2069 | W_ACCUM_L(del, ~((UINT16)s2)); | |
| 2070 | SET_COMPARE_FLAG(del); | |
| 2104 | ACCUM_L(i) = ~((UINT16)s2); | |
| 2105 | SET_COMPARE_FLAG(i); | |
| 2071 | 2106 | } |
| 2072 | 2107 | else |
| 2073 | 2108 | { |
| 2074 | | |
| 2109 | | |
| 2075 | 2110 | } |
| 2076 | 2111 | } |
| 2077 | 2112 | else |
| 2078 | 2113 | { |
| 2079 | 2114 | if (s2 < 0) |
| 2080 | 2115 | { |
| 2081 | SET_COMPARE_FLAG( | |
| 2116 | SET_COMPARE_FLAG(i | |
| 2082 | 2117 | } |
| 2083 | 2118 | if ((s1 - s2) >= 0) |
| 2084 | 2119 | { |
| 2085 | W_ACCUM_L(del, s2); | |
| 2086 | rsp->flag[1] |= (1 << (8+del)); | |
| 2120 | ACCUM_L(i) = s2; | |
| 2121 | rsp->flag[1] |= (1 << (8+i)); | |
| 2087 | 2122 | } |
| 2088 | 2123 | else |
| 2089 | 2124 | { |
| 2090 | | |
| 2125 | | |
| 2091 | 2126 | } |
| 2092 | 2127 | } |
| 2093 | 2128 | |
| 2094 | vres[ | |
| 2129 | vres[i | |
| 2095 | 2130 | } |
| 2096 | 2131 | WRITEBACK_RESULT(); |
| 2097 | 2132 | break; |
| r9854 | r9855 | |
| 2106 | 2141 | // |
| 2107 | 2142 | // Merges two vectors according to compare flags |
| 2108 | 2143 | |
| 2109 | for (i=0; i < 8; i++) | |
| 2144 | int sel; | |
| 2145 | for (i = 0; i < 8; i++) | |
| 2110 | 2146 | { |
| 2111 | int del = VEC_EL_1(EL, i); | |
| 2112 | int sel = VEC_EL_2(EL, del); | |
| 2113 | if (COMPARE_FLAG(del) != 0) | |
| 2147 | sel = VEC_EL_2(EL, i); | |
| 2148 | if (COMPARE_FLAG(i) != 0) | |
| 2114 | 2149 | { |
| 2115 | vres[ | |
| 2150 | vres[i | |
| 2116 | 2151 | } |
| 2117 | 2152 | else |
| 2118 | 2153 | { |
| 2119 | vres[ | |
| 2154 | vres[i | |
| 2120 | 2155 | } |
| 2121 | 2156 | |
| 2122 | | |
| 2157 | | |
| 2123 | 2158 | } |
| 2124 | 2159 | WRITEBACK_RESULT(); |
| 2125 | 2160 | break; |
| r9854 | r9855 | |
| 2133 | 2168 | // |
| 2134 | 2169 | // Bitwise AND of two vector registers |
| 2135 | 2170 | |
| 2136 | for (i=0; i < 8; i++) | |
| 2171 | int sel; | |
| 2172 | for (i = 0; i < 8; i++) | |
| 2137 | 2173 | { |
| 2138 | int del = VEC_EL_1(EL, i); | |
| 2139 | int sel = VEC_EL_2(EL, del); | |
| 2140 | vres[del] = R_VREG_S(VS1REG, del) & R_VREG_S(VS2REG, sel); | |
| 2141 | W_ACCUM_L(del, vres[del]); | |
| 2174 | sel = VEC_EL_2(EL, i); | |
| 2175 | vres[i] = VREG_S(VS1REG, i) & VREG_S(VS2REG, sel); | |
| 2176 | ACCUM_L(i) = vres[i]; | |
| 2142 | 2177 | } |
| 2143 | 2178 | WRITEBACK_RESULT(); |
| 2144 | 2179 | break; |
| r9854 | r9855 | |
| 2152 | 2187 | // |
| 2153 | 2188 | // Bitwise NOT AND of two vector registers |
| 2154 | 2189 | |
| 2155 | for (i=0; i < 8; i++) | |
| 2190 | int sel; | |
| 2191 | for (i = 0; i < 8; i++) | |
| 2156 | 2192 | { |
| 2157 | int del = VEC_EL_1(EL, i); | |
| 2158 | int sel = VEC_EL_2(EL, del); | |
| 2159 | vres[del] = ~((R_VREG_S(VS1REG, del) & R_VREG_S(VS2REG, sel))); | |
| 2160 | W_ACCUM_L(del, vres[del]); | |
| 2193 | sel = VEC_EL_2(EL, i); | |
| 2194 | vres[i] = ~((VREG_S(VS1REG, i) & VREG_S(VS2REG, sel))); | |
| 2195 | ACCUM_L(i) = vres[i]; | |
| 2161 | 2196 | } |
| 2162 | 2197 | WRITEBACK_RESULT(); |
| 2163 | 2198 | break; |
| r9854 | r9855 | |
| 2171 | 2206 | // |
| 2172 | 2207 | // Bitwise OR of two vector registers |
| 2173 | 2208 | |
| 2174 | for (i=0; i < 8; i++) | |
| 2209 | int sel; | |
| 2210 | for (i = 0; i < 8; i++) | |
| 2175 | 2211 | { |
| 2176 | int del = VEC_EL_1(EL, i); | |
| 2177 | int sel = VEC_EL_2(EL, del); | |
| 2178 | vres[del] = R_VREG_S(VS1REG, del) | R_VREG_S(VS2REG, sel); | |
| 2179 | W_ACCUM_L(del, vres[del]); | |
| 2212 | sel = VEC_EL_2(EL, i); | |
| 2213 | vres[i] = VREG_S(VS1REG, i) | VREG_S(VS2REG, sel); | |
| 2214 | ACCUM_L(i) = vres[i]; | |
| 2180 | 2215 | } |
| 2181 | 2216 | WRITEBACK_RESULT(); |
| 2182 | 2217 | break; |
| r9854 | r9855 | |
| 2190 | 2225 | // |
| 2191 | 2226 | // Bitwise NOT OR of two vector registers |
| 2192 | 2227 | |
| 2228 | int sel; | |
| 2193 | 2229 | for (i=0; i < 8; i++) |
| 2194 | 2230 | { |
| 2195 | int del = VEC_EL_1(EL, i); | |
| 2196 | int sel = VEC_EL_2(EL, del); | |
| 2197 | vres[del] = ~((R_VREG_S(VS1REG, del) | R_VREG_S(VS2REG, sel))); | |
| 2198 | W_ACCUM_L(del, vres[del]); | |
| 2231 | sel = VEC_EL_2(EL, i); | |
| 2232 | vres[i] = ~((VREG_S(VS1REG, i) | VREG_S(VS2REG, sel))); | |
| 2233 | ACCUM_L(i) = vres[i]; | |
| 2199 | 2234 | } |
| 2200 | 2235 | WRITEBACK_RESULT(); |
| 2201 | 2236 | break; |
| r9854 | r9855 | |
| 2209 | 2244 | // |
| 2210 | 2245 | // Bitwise XOR of two vector registers |
| 2211 | 2246 | |
| 2247 | int sel; | |
| 2212 | 2248 | for (i=0; i < 8; i++) |
| 2213 | 2249 | { |
| 2214 | int del = VEC_EL_1(EL, i); | |
| 2215 | int sel = VEC_EL_2(EL, del); | |
| 2216 | vres[del] = R_VREG_S(VS1REG, del) ^ R_VREG_S(VS2REG, sel); | |
| 2217 | W_ACCUM_L(del, vres[del]); | |
| 2250 | sel = VEC_EL_2(EL, i); | |
| 2251 | vres[i] = VREG_S(VS1REG, i) ^ VREG_S(VS2REG, sel); | |
| 2252 | ACCUM_L(i) = vres[i]; | |
| 2218 | 2253 | } |
| 2219 | 2254 | WRITEBACK_RESULT(); |
| 2220 | 2255 | break; |
| r9854 | r9855 | |
| 2228 | 2263 | // |
| 2229 | 2264 | // Bitwise NOT XOR of two vector registers |
| 2230 | 2265 | |
| 2266 | int sel; | |
| 2231 | 2267 | for (i=0; i < 8; i++) |
| 2232 | 2268 | { |
| 2233 | int del = VEC_EL_1(EL, i); | |
| 2234 | int sel = VEC_EL_2(EL, del); | |
| 2235 | vres[del] = ~((R_VREG_S(VS1REG, del) ^ R_VREG_S(VS2REG, sel))); | |
| 2236 | W_ACCUM_L(del, vres[del]); | |
| 2269 | sel = VEC_EL_2(EL, i); | |
| 2270 | vres[i] = ~((VREG_S(VS1REG, i) ^ VREG_S(VS2REG, sel))); | |
| 2271 | ACCUM_L(i) = vres[i]; | |
| 2237 | 2272 | } |
| 2238 | 2273 | WRITEBACK_RESULT(); |
| 2239 | 2274 | break; |
| r9854 | r9855 | |
| 2247 | 2282 | // ------------------------------------------------------ |
| 2248 | 2283 | // |
| 2249 | 2284 | // Calculates reciprocal |
| 2250 | ||
| 2251 | int del = (VS1REG & 7); | |
| 2285 | int del = VS1REG & 7; | |
| 2252 | 2286 | int sel = EL & 7; |
| 2253 | INT32 | |
| 2287 | INT32 shifter = 0; | |
| 2254 | 2288 | |
| 2255 | rec = (INT16)(R_VREG_S(VS2REG, sel)); | |
| 2256 | ||
| 2257 | if (rec == 0) | |
| 2289 | INT32 rec = (INT16)(VREG_S(VS2REG, sel)); | |
| 2290 | INT32 datainput = (rec < 0) ? (-rec) : rec; | |
| 2291 | if (datainput) | |
| 2258 | 2292 | { |
| 2259 | // divide by zero -> overflow | |
| 2260 | rec = 0x7fffffff; | |
| 2261 | } | |
| 2262 | else | |
| 2263 | { | |
| 2264 | int sign = 0; | |
| 2265 | int exp = 0; | |
| 2266 | int mantissa = 0; | |
| 2267 | ||
| 2268 | if (rec < 0) | |
| 2293 | for (i = 0; i < 32; i++) | |
| 2269 | 2294 | { |
| 2270 | rec = -rec; // rec = MINUS rec | |
| 2271 | sign = 1; | |
| 2272 | } | |
| 2273 | ||
| 2274 | // restrict to 10-bit mantissa | |
| 2275 | for (i = 15; i >= 0; i--) | |
| 2276 | { | |
| 2277 | if (rec & (1 << i)) | |
| 2295 | if (datainput & (1 << ((~i) & 0x1f)))//ò.æ.÷òî 31 - i | |
| 2278 | 2296 | { |
| 2279 | exp = i; | |
| 2280 | mantissa = (rec << (15 - i)) >> 6; | |
| 2297 | shifter = i; | |
| 2281 | 2298 | break; |
| 2282 | 2299 | } |
| 2283 | 2300 | } |
| 2301 | } | |
| 2302 | else | |
| 2303 | { | |
| 2304 | shifter = 0x10; | |
| 2305 | } | |
| 2284 | 2306 | |
| 2285 | if (mantissa == 0x200) | |
| 2286 | { | |
| 2287 | rec = 0x7fffffff; | |
| 2288 | } | |
| 2289 | else | |
| 2290 | { | |
| 2291 | rec = 0xffffffffU / mantissa; | |
| 2307 | INT32 address = ((datainput << shifter) & 0x7fc00000) >> 22; | |
| 2308 | INT32 fetchval = rsp_divtable[address]; | |
| 2309 | INT32 temp = (0x40000000 | (fetchval << 14)) >> ((~shifter) & 0x1f); | |
| 2310 | if (rec < 0) | |
| 2311 | { | |
| 2312 | temp = ~temp; | |
| 2313 | } | |
| 2314 | if (!rec) | |
| 2315 | { | |
| 2316 | temp = 0x7fffffff; | |
| 2317 | } | |
| 2318 | else if (rec == 0xffff8000) | |
| 2319 | { | |
| 2320 | temp = 0xffff0000; | |
| 2321 | } | |
| 2322 | rec = temp; | |
| 2292 | 2323 | |
| 2293 | // | |
| 2294 | // simulate rounding error | |
| 2295 | // | |
| 2296 | // This has been verified on the real hardware. | |
| 2297 | // | |
| 2298 | // I was able to replicate this exact behaviour by using a five-round | |
| 2299 | // Newton reciprocal method using floorf() on intermediate results | |
| 2300 | // to force the use of IEEE 754 32bit floats. | |
| 2301 | // However, for the sake of portability, we'll use integer arithmetic. | |
| 2302 | // | |
| 2303 | if (rec & 0x800) | |
| 2304 | rec += 1; | |
| 2324 | rsp->reciprocal_res = rec; | |
| 2325 | rsp->dp_allowed = 0; | |
| 2305 | 2326 | |
| 2306 | rec <<= 8; | |
| 2307 | } | |
| 2327 | VREG_S(VDREG, del) = (UINT16)(rec & 0xffff); | |
| 2308 | 2328 | |
| 2309 | // restrict result to 17 significant bits | |
| 2310 | rec &= 0x7fffc000; | |
| 2311 | ||
| 2312 | rec >>= exp; | |
| 2313 | ||
| 2314 | if (sign) | |
| 2315 | { | |
| 2316 | rec = ~rec; // rec = BITWISE NOT rec | |
| 2317 | } | |
| 2318 | } | |
| 2319 | ||
| 2320 | for (i=0; i < 8; i++) | |
| 2329 | for (i = 0; i < 8; i++) | |
| 2321 | 2330 | { |
| 2322 | int element = VEC_EL_2(EL, i); | |
| 2323 | W_ACCUM_L(i, R_VREG_S(VS2REG, element)); | |
| 2331 | sel = VEC_EL_2(EL, i); | |
| 2332 | ACCUM_L(i) = VREG_S(VS2REG, sel); | |
| 2324 | 2333 | } |
| 2325 | 2334 | |
| 2326 | rsp->reciprocal_res = rec; | |
| 2327 | 2335 | |
| 2328 | W_VREG_S(VDREG, del, (UINT16)(rsp->reciprocal_res)); // store low part | |
| 2329 | 2336 | break; |
| 2330 | 2337 | } |
| 2331 | 2338 | |
| r9854 | r9855 | |
| 2338 | 2345 | // |
| 2339 | 2346 | // Calculates reciprocal low part |
| 2340 | 2347 | |
| 2341 | int del = (VS1REG & 7); | |
| 2342 | int sel = VEC_EL_2(EL, del); | |
| 2343 | INT32 rec; | |
| 2348 | int del = VS1REG & 7; | |
| 2349 | int sel = EL & 7; | |
| 2350 | INT32 shifter = 0; | |
| 2344 | 2351 | |
| 2345 | rec = ((UINT16)( | |
| 2352 | INT32 rec = ((UINT16)( | |
| 2346 | 2353 | |
| 2347 | if (rec == 0) | |
| 2354 | INT32 datainput = rec; | |
| 2355 | ||
| 2356 | if (rec < 0) | |
| 2348 | 2357 | { |
| 2349 | // divide by zero -> overflow | |
| 2350 | rec = 0x7fffffff; | |
| 2351 | } | |
| 2352 | else | |
| 2353 | { | |
| 2354 | int negative = 0; | |
| 2355 | if (rec < 0) | |
| 2358 | if (rsp->dp_allowed) | |
| 2356 | 2359 | { |
| 2357 | if ( | |
| 2360 | if ( | |
| 2358 | 2361 | { |
| 2359 | | |
| 2362 | datainput = ~datainput; | |
| 2360 | 2363 | } |
| 2361 | 2364 | else |
| 2362 | 2365 | { |
| 2363 | | |
| 2366 | datainput = -datainput; | |
| 2364 | 2367 | } |
| 2365 | negative = 1; | |
| 2366 | 2368 | } |
| 2367 | | |
| 2369 | else | |
| 2368 | 2370 | { |
| 2369 | if (rec & (1 << i)) | |
| 2370 | { | |
| 2371 | rec &= ((0xffc00000) >> (31 - i)); | |
| 2372 | i = 0; | |
| 2373 | } | |
| 2371 | datainput = -datainput; | |
| 2374 | 2372 | } |
| 2375 | rec = (0x7fffffff / rec); | |
| 2376 | for (i = 31; i > 0; i--) | |
| 2373 | } | |
| 2374 | ||
| 2375 | ||
| 2376 | if (datainput) | |
| 2377 | { | |
| 2378 | for (i = 0; i < 32; i++) | |
| 2377 | 2379 | { |
| 2378 | if ( | |
| 2380 | if (datainput & (1 << ((~i) & 0x1f)))//ò.æ.÷òî 31 - i | |
| 2379 | 2381 | { |
| 2380 | rec &= ((0xffff8000) >> (31 - i)); | |
| 2381 | i = 0; | |
| 2382 | shifter = i; | |
| 2383 | break; | |
| 2382 | 2384 | } |
| 2383 | 2385 | } |
| 2384 | if (negative) | |
| 2386 | } | |
| 2387 | else | |
| 2388 | { | |
| 2389 | if (rsp->dp_allowed) | |
| 2385 | 2390 | { |
| 2386 | | |
| 2391 | shifter = 0 | |
| 2387 | 2392 | } |
| 2393 | else | |
| 2394 | { | |
| 2395 | shifter = 0x10; | |
| 2396 | } | |
| 2388 | 2397 | } |
| 2389 | 2398 | |
| 2390 | for (i=0; i < 8; i++) | |
| 2399 | INT32 address = ((datainput << shifter) & 0x7fc00000) >> 22; | |
| 2400 | INT32 fetchval = rsp_divtable[address]; | |
| 2401 | INT32 temp = (0x40000000 | (fetchval << 14)) >> ((~shifter) & 0x1f); | |
| 2402 | if (rec < 0) | |
| 2391 | 2403 | { |
| 2392 | int element = VEC_EL_2(EL, i); | |
| 2393 | W_ACCUM_L(i, R_VREG_S(VS2REG, element)); | |
| 2404 | temp = ~temp; | |
| 2394 | 2405 | } |
| 2406 | if (!rec) | |
| 2407 | { | |
| 2408 | temp = 0x7fffffff; | |
| 2409 | } | |
| 2410 | else if (rec == 0xffff8000) | |
| 2411 | { | |
| 2412 | temp = 0xffff0000; | |
| 2413 | } | |
| 2414 | rec = temp; | |
| 2395 | 2415 | |
| 2396 | 2416 | rsp->reciprocal_res = rec; |
| 2417 | rsp->dp_allowed = 0; | |
| 2397 | 2418 | |
| 2398 | W_VREG_S(VDREG, del, (UINT16)(rsp->reciprocal_res)); // store low part | |
| 2419 | VREG_S(VDREG, del) = (UINT16)(rec & 0xffff); | |
| 2420 | ||
| 2421 | for (i = 0; i < 8; i++) | |
| 2422 | { | |
| 2423 | sel = VEC_EL_2(EL, i); | |
| 2424 | ACCUM_L(i) = VREG_S(VS2REG, sel); | |
| 2425 | } | |
| 2426 | ||
| 2399 | 2427 | break; |
| 2400 | 2428 | } |
| 2401 | 2429 | |
| r9854 | r9855 | |
| 2408 | 2436 | // |
| 2409 | 2437 | // Calculates reciprocal high part |
| 2410 | 2438 | |
| 2411 | int del = (VS1REG & 7); | |
| 2412 | int sel = VEC_EL_2(EL, del); | |
| 2439 | int del = VS1REG & 7; | |
| 2440 | int sel = EL & 7; | |
| 2413 | 2441 | |
| 2414 | rsp->reciprocal_high = R_VREG_S(VS2REG, sel); | |
| 2442 | rsp->reciprocal_high = (VREG_S(VS2REG, sel)) << 16; | |
| 2443 | rsp->dp_allowed = 1; | |
| 2415 | 2444 | |
| 2416 | for (i=0; i < 8; i++) | |
| 2445 | for (i = 0; i < 8; i++) | |
| 2417 | 2446 | { |
| 2418 | int element = VEC_EL_2(EL, i); | |
| 2419 | W_ACCUM_L(i, R_VREG_S(VS2REG, element)); // perhaps accumulator is used to store the intermediate values ? | |
| 2447 | sel = VEC_EL_2(EL, i); | |
| 2448 | ACCUM_L(i) = VREG_S(VS2REG, sel); | |
| 2420 | 2449 | } |
| 2421 | 2450 | |
| 2422 | W_VREG_S(VDREG, del, (INT16)(rsp->reciprocal_res >> 16)); // store high part | |
| 2451 | VREG_S(VDREG, del) = (INT16)(rsp->reciprocal_res >> 16); | |
| 2452 | ||
| 2423 | 2453 | break; |
| 2424 | 2454 | } |
| 2425 | 2455 | |
| r9854 | r9855 | |
| 2432 | 2462 | // |
| 2433 | 2463 | // Moves element from vector to destination vector |
| 2434 | 2464 | |
| 2435 | int element = VS1REG & 7; | |
| 2436 | W_VREG_S(VDREG, element, R_VREG_S(VS2REG, VEC_EL_2(EL, 7-element))); | |
| 2465 | int del = VS1REG & 7; | |
| 2466 | int sel = EL & 7; | |
| 2467 | ||
| 2468 | VREG_S(VDREG, del) = VREG_S(VS2REG, sel); | |
| 2469 | for (i = 0; i < 8; i++) | |
| 2470 | { | |
| 2471 | sel = VEC_EL_2(EL, i); | |
| 2472 | ACCUM_L(i) = VREG_S(VS2REG, sel); | |
| 2473 | } | |
| 2437 | 2474 | break; |
| 2438 | 2475 | } |
| 2439 | 2476 | |
| 2440 | case 0x3 | |
| 2477 | case 0x34: /* VRSQ | |
| 2441 | 2478 | { |
| 2442 | 2479 | // 31 25 24 20 15 10 5 0 |
| 2443 | 2480 | // ------------------------------------------------------ |
| 2444 | // | 010010 | 1 | EEEE | SSSSS | ?FFFF | DDDDD | 11010 | |
| 2481 | // | 010010 | 1 | EEEE | SSSSS | ?FFFF | DDDDD | 110100 | | |
| 2445 | 2482 | // ------------------------------------------------------ |
| 2446 | 2483 | // |
| 2447 | // Calculates reciprocal square-root | |
| 2484 | // Calculates reciprocal square-root | |
| 2448 | 2485 | |
| 2449 | int del = (VS1REG & 7); | |
| 2450 | int sel = VEC_EL_2(EL, del); | |
| 2451 | INT32 sqr; | |
| 2486 | int del = VS1REG & 7; | |
| 2487 | int sel = EL & 7; | |
| 2488 | INT32 shifter = 0; | |
| 2452 | 2489 | |
| 2453 | sqr = (UINT16)(R_VREG_S(VS2REG, sel)) | ((UINT32)(rsp->square_root_high) << 16); | |
| 2490 | INT32 rec = (INT16)(VREG_S(VS2REG, sel)); | |
| 2491 | INT32 datainput = (rec < 0) ? (-rec) : rec; | |
| 2492 | if (datainput) | |
| 2493 | { | |
| 2494 | for (i = 0; i < 32; i++) | |
| 2495 | { | |
| 2496 | if (datainput & (1 << ((~i) & 0x1f)))//ò.æ.÷òî 31 - i | |
| 2497 | { | |
| 2498 | shifter = i; | |
| 2499 | break; | |
| 2500 | } | |
| 2501 | } | |
| 2502 | } | |
| 2503 | else | |
| 2504 | { | |
| 2505 | shifter = 0x10; | |
| 2506 | } | |
| 2454 | 2507 | |
| 2455 | if (sqr == 0) | |
| 2508 | INT32 address = ((datainput << shifter) & 0x7fc00000) >> 22; | |
| 2509 | address = ((address | 0x200) & 0x3fe) | (shifter & 1); | |
| 2510 | ||
| 2511 | INT32 fetchval = rsp_divtable[address]; | |
| 2512 | INT32 temp = (0x40000000 | (fetchval << 14)) >> (((~shifter) & 0x1f) >> 1); | |
| 2513 | if (rec < 0) | |
| 2456 | 2514 | { |
| 2457 | // square root on 0 -> overflow | |
| 2458 | sqr = 0x7fffffff; | |
| 2515 | temp = ~temp; | |
| 2459 | 2516 | } |
| 2460 | | |
| 2517 | | |
| 2461 | 2518 | { |
| 2462 | // overflow ? | |
| 2463 | sqr = 0xffff8000; | |
| 2519 | temp = 0x7fffffff; | |
| 2464 | 2520 | } |
| 2465 | else | |
| 2521 | else if (rec == 0xffff8000) | |
| 2466 | 2522 | { |
| 2467 | int negative = 0; | |
| 2468 | if (sqr < 0) | |
| 2523 | temp = 0xffff0000; | |
| 2524 | } | |
| 2525 | rec = temp; | |
| 2526 | ||
| 2527 | rsp->reciprocal_res = rec; | |
| 2528 | rsp->dp_allowed = 0; | |
| 2529 | ||
| 2530 | VREG_S(VDREG, del) = (UINT16)(rec & 0xffff); | |
| 2531 | ||
| 2532 | for (i = 0; i < 8; i++) | |
| 2533 | { | |
| 2534 | sel = VEC_EL_2(EL, i); | |
| 2535 | ACCUM_L(i) = VREG_S(VS2REG, sel); | |
| 2536 | } | |
| 2537 | ||
| 2538 | break; | |
| 2539 | } | |
| 2540 | ||
| 2541 | case 0x35: /* VRSQL */ | |
| 2542 | { | |
| 2543 | // 31 25 24 20 15 10 5 0 | |
| 2544 | // ------------------------------------------------------ | |
| 2545 | // | 010010 | 1 | EEEE | SSSSS | ?FFFF | DDDDD | 110101 | | |
| 2546 | // ------------------------------------------------------ | |
| 2547 | // | |
| 2548 | // Calculates reciprocal square-root low part | |
| 2549 | ||
| 2550 | int del = VS1REG & 7; | |
| 2551 | int sel = EL & 7; | |
| 2552 | INT32 shifter = 0; | |
| 2553 | ||
| 2554 | INT32 rec = ((UINT16)(VREG_S(VS2REG, sel)) | ((UINT32)(rsp->reciprocal_high) & 0xffff0000)); | |
| 2555 | ||
| 2556 | INT32 datainput = rec; | |
| 2557 | ||
| 2558 | if (rec < 0) | |
| 2559 | { | |
| 2560 | if (rsp->dp_allowed) | |
| 2469 | 2561 | { |
| 2470 | if ( | |
| 2562 | if ( | |
| 2471 | 2563 | { |
| 2472 | | |
| 2564 | datainput = ~datainput; | |
| 2473 | 2565 | } |
| 2474 | 2566 | else |
| 2475 | 2567 | { |
| 2476 | | |
| 2568 | datainput = -datainput; | |
| 2477 | 2569 | } |
| 2478 | negative = 1; | |
| 2479 | 2570 | } |
| 2480 | | |
| 2571 | else | |
| 2481 | 2572 | { |
| 2482 | if (sqr & (1 << i)) | |
| 2483 | { | |
| 2484 | sqr &= (0xff800000 >> (31 - i)); | |
| 2485 | i = 0; | |
| 2486 | } | |
| 2573 | datainput = -datainput; | |
| 2487 | 2574 | } |
| 2488 | sqr = (INT32)(0x7fffffff / sqrt((double)sqr)); | |
| 2489 | for (i = 31; i > 0; i--) | |
| 2575 | } | |
| 2576 | ||
| 2577 | if (datainput) | |
| 2578 | { | |
| 2579 | for (i = 0; i < 32; i++) | |
| 2490 | 2580 | { |
| 2491 | if ( | |
| 2581 | if (datainput & (1 << ((~i) & 0x1f))) | |
| 2492 | 2582 | { |
| 2493 | sqr &= (0xffff8000 >> (31 - i)); | |
| 2494 | i = 0; | |
| 2583 | shifter = i; | |
| 2584 | break; | |
| 2495 | 2585 | } |
| 2496 | 2586 | } |
| 2497 | if (negative) | |
| 2587 | } | |
| 2588 | else | |
| 2589 | { | |
| 2590 | if (rsp->dp_allowed) | |
| 2498 | 2591 | { |
| 2499 | s | |
| 2592 | shifter = 0 | |
| 2500 | 2593 | } |
| 2594 | else | |
| 2595 | { | |
| 2596 | shifter = 0x10; | |
| 2597 | } | |
| 2501 | 2598 | } |
| 2502 | 2599 | |
| 2503 | for (i=0; i < 8; i++) | |
| 2600 | INT32 address = ((datainput << shifter) & 0x7fc00000) >> 22; | |
| 2601 | address = ((address | 0x200) & 0x3fe) | (shifter & 1); | |
| 2602 | ||
| 2603 | INT32 fetchval = rsp_divtable[address]; | |
| 2604 | INT32 temp = (0x40000000 | (fetchval << 14)) >> (((~shifter) & 0x1f) >> 1); | |
| 2605 | if (rec < 0) | |
| 2504 | 2606 | { |
| 2505 | int element = VEC_EL_2(EL, i); | |
| 2506 | W_ACCUM_L(i, R_VREG_S(VS2REG, element)); | |
| 2607 | temp = ~temp; | |
| 2507 | 2608 | } |
| 2609 | if (!rec) | |
| 2610 | { | |
| 2611 | temp = 0x7fffffff; | |
| 2612 | } | |
| 2613 | else if (rec == 0xffff8000) | |
| 2614 | { | |
| 2615 | temp = 0xffff0000; | |
| 2616 | } | |
| 2617 | rec = temp; | |
| 2508 | 2618 | |
| 2509 | rsp->square_root_res = sqr; | |
| 2619 | rsp->reciprocal_res = rec; | |
| 2620 | rsp->dp_allowed = 0; | |
| 2510 | 2621 | |
| 2511 | W_VREG_S(VDREG, del, (UINT16)(rsp->square_root_res)); // store low part | |
| 2622 | VREG_S(VDREG, del) = (UINT16)(rec & 0xffff); | |
| 2623 | ||
| 2624 | for (i = 0; i < 8; i++) | |
| 2625 | { | |
| 2626 | sel = VEC_EL_2(EL, i); | |
| 2627 | ACCUM_L(i) = VREG_S(VS2REG, sel); | |
| 2628 | } | |
| 2629 | ||
| 2512 | 2630 | break; |
| 2513 | 2631 | } |
| 2514 | 2632 | |
| r9854 | r9855 | |
| 2521 | 2639 | // |
| 2522 | 2640 | // Calculates reciprocal square-root high part |
| 2523 | 2641 | |
| 2524 | int del = (VS1REG & 7); | |
| 2525 | int sel = VEC_EL_2(EL, del); | |
| 2642 | int del = VS1REG & 7; | |
| 2643 | int sel = EL & 7; | |
| 2526 | 2644 | |
| 2527 | rsp->square_root_high = R_VREG_S(VS2REG, sel); | |
| 2645 | rsp->reciprocal_high = (VREG_S(VS2REG, sel)) << 16; | |
| 2646 | rsp->dp_allowed = 1; | |
| 2528 | 2647 | |
| 2529 | 2648 | for (i=0; i < 8; i++) |
| 2530 | 2649 | { |
| 2531 | int element = VEC_EL_2(EL, i); | |
| 2532 | W_ACCUM_L(i, R_VREG_S(VS2REG, element)); // perhaps accumulator is used to store the intermediate values ? | |
| 2650 | sel = VEC_EL_2(EL, i); | |
| 2651 | ACCUM_L(i) = VREG_S(VS2REG, sel); | |
| 2533 | 2652 | } |
| 2534 | 2653 | |
| 2535 | | |
| 2654 | | |
| 2536 | 2655 | break; |
| 2537 | 2656 | } |
| 2538 | 2657 | |
| 2658 | case 0x37: /* VNOP */ | |
| 2659 | { | |
| 2660 | // 31 25 24 20 15 10 5 0 | |
| 2661 | // ------------------------------------------------------ | |
| 2662 | // | 010010 | 1 | EEEE | SSSSS | ?FFFF | DDDDD | 110111 | | |
| 2663 | // ------------------------------------------------------ | |
| 2664 | // | |
| 2665 | // Vector null instruction | |
| 2666 | ||
| 2667 | break; | |
| 2668 | } | |
| 2669 | ||
| 2539 | 2670 | default: unimplemented_opcode(rsp, op); break; |
| 2540 | 2671 | } |
| 2541 | 2672 | } |
| r9854 | r9855 | |
| 2658 | 2789 | // |
| 2659 | 2790 | |
| 2660 | 2791 | int el = (op >> 7) & 0xf; |
| 2661 | UINT16 b1 = R_VREG_B(VS1REG, (el+0) & 0xf); | |
| 2662 | UINT16 b2 = R_VREG_B(VS1REG, (el+1) & 0xf); | |
| 2792 | UINT16 b1 = VREG_B(RDREG, (el+0) & 0xf); | |
| 2793 | UINT16 b2 = VREG_B(RDREG, (el+1) & 0xf); | |
| 2663 | 2794 | if (RTREG) RTVAL = (INT32)(INT16)((b1 << 8) | (b2)); |
| 2664 | 2795 | break; |
| 2665 | 2796 | } |
| r9854 | r9855 | |
| 2695 | 2826 | // |
| 2696 | 2827 | |
| 2697 | 2828 | int el = (op >> 7) & 0xf; |
| 2698 | W_VREG_B(VS1REG, (el+0) & 0xf, (RTVAL >> 8) & 0xff); | |
| 2699 | W_VREG_B(VS1REG, (el+1) & 0xf, (RTVAL >> 0) & 0xff); | |
| 2829 | W_VREG_B(RDREG, (el+0) & 0xf, (RTVAL >> 8) & 0xff); | |
| 2830 | W_VREG_B(RDREG, (el+1) & 0xf, (RTVAL >> 0) & 0xff); | |
| 2700 | 2831 | break; |
| 2701 | 2832 | } |
| 2702 | 2833 | case 0x06: /* CTC2 */ |
| r9854 | r9855 | |
| 2776 | 2907 | if (rsp->v[i].d[0] != prev_vecs[i].d[0] || rsp->v[i].d[1] != prev_vecs[i].d[1]) |
| 2777 | 2908 | { |
| 2778 | 2909 | fprintf(rsp->exec_output, "V%d: %04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X ", i, |
| 2779 | (UINT16) | |
| 2910 | (UINT16) | |
| 2780 | 2911 | } |
| 2781 | 2912 | prev_vecs[i].d[0] = rsp->v[i].d[0]; |
| 2782 | 2913 | prev_vecs[i].d[1] = rsp->v[i].d[1]; |
| r9854 | r9855 | |
| 2868 | 2999 | switch(state) |
| 2869 | 3000 | { |
| 2870 | 3001 | /* --- the following bits of info are returned as 64-bit signed integers --- */ |
| 2871 | case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(rsp_state); | |
| 3002 | case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(rsp_state); | |
| 2872 | 3003 | case CPUINFO_INT_INPUT_LINES: info->i = 1; break; |
| 2873 | 3004 | case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = 0; break; |
| 2874 | case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_ | |
| 3005 | case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_BIG | |
| 2875 | 3006 | case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break; |
| 2876 | 3007 | case CPUINFO_INT_CLOCK_DIVIDER: info->i = 1; break; |
| 2877 | 3008 | case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 4; break; |
| r9854 | r9855 | |
|---|---|---|
| 139 | 139 | |
| 140 | 140 | #define RSPDRC_STRICT_VERIFY 0x0001 /* verify all instructions */ |
| 141 | 141 | |
| 142 | typedef | |
| 142 | typedef | |
| 143 | 143 | { |
| 144 | union | |
| 145 | { | |
| 146 | UINT8 b[16]; | |
| 147 | UINT16 s[8]; | |
| 148 | UINT32 l[4]; | |
| 149 | UINT64 d[2]; | |
| 150 | }; | |
| 144 | UINT64 d[2]; | |
| 145 | UINT32 l[4]; | |
| 146 | INT16 s[8]; | |
| 147 | UINT8 b[16]; | |
| 151 | 148 | } VECTOR_REG; |
| 152 | 149 | |
| 153 | typedef | |
| 150 | typedef | |
| 154 | 151 | { |
| 155 | union | |
| 156 | { | |
| 157 | INT64 l; | |
| 158 | #ifdef LSB_FIRST | |
| 159 | struct | |
| 160 | { | |
| 161 | INT16 z; | |
| 162 | INT16 low; | |
| 163 | INT16 mid; | |
| 164 | INT16 high; | |
| 165 | } h; | |
| 166 | struct | |
| 167 | { | |
| 168 | INT32 zl; | |
| 169 | INT32 mh; | |
| 170 | } w; | |
| 171 | #else | |
| 172 | struct | |
| 173 | { | |
| 174 | INT16 high; | |
| 175 | INT16 mid; | |
| 176 | INT16 low; | |
| 177 | INT16 z; | |
| 178 | } h; | |
| 179 | struct | |
| 180 | { | |
| 181 | INT32 mh; | |
| 182 | INT32 zl; | |
| 183 | } w; | |
| 184 | #endif | |
| 185 | }; | |
| 186 | } ACCUMULATOR; | |
| 152 | INT64 q; | |
| 153 | INT32 l[2]; | |
| 154 | INT16 w[4]; | |
| 155 | } ACCUMULATOR_REG; | |
| 187 | 156 | |
| 188 | 157 | typedef struct _rspimp_state rspimp_state; |
| 189 | 158 | typedef struct _rsp_state rsp_state; |
| r9854 | r9855 | |
| 199 | 168 | UINT32 sr; |
| 200 | 169 | UINT32 step_count; |
| 201 | 170 | |
| 202 | ACCUMULATOR accum[8]; | |
| 171 | ACCUMULATOR_REG accum[8]; | |
| 203 | 172 | INT32 square_root_res; |
| 204 | 173 | INT32 square_root_high; |
| 205 | 174 | INT32 reciprocal_res; |
| 206 | 175 | INT32 reciprocal_high; |
| 176 | INT32 dp_allowed; | |
| 207 | 177 | |
| 208 | 178 | UINT32 ppc; |
| 209 | 179 | UINT32 nextpc; |
| r0 | r9855 | |
|---|---|---|
| 1 | static const UINT16 rsp_divtable[1024] = | |
| 2 | { | |
| 3 | 0xffff, | |
| 4 | 0xff00, | |
| 5 | 0xfe01, | |
| 6 | 0xfd04, | |
| 7 | 0xfc07, | |
| 8 | 0xfb0c, | |
| 9 | 0xfa11, | |
| 10 | 0xf918, | |
| 11 | 0xf81f, | |
| 12 | 0xf727, | |
| 13 | 0xf631, | |
| 14 | 0xf53b, | |
| 15 | 0xf446, | |
| 16 | 0xf352, | |
| 17 | 0xf25f, | |
| 18 | 0xf16d, | |
| 19 | 0xf07c, | |
| 20 | 0xef8b, | |
| 21 | 0xee9c, | |
| 22 | 0xedae, | |
| 23 | 0xecc0, | |
| 24 | 0xebd3, | |
| 25 | 0xeae8, | |
| 26 | 0xe9fd, | |
| 27 | 0xe913, | |
| 28 | 0xe829, | |
| 29 | 0xe741, | |
| 30 | 0xe65a, | |
| 31 | 0xe573, | |
| 32 | 0xe48d, | |
| 33 | 0xe3a9, | |
| 34 | 0xe2c5, | |
| 35 | 0xe1e1, | |
| 36 | 0xe0ff, | |
| 37 | 0xe01e, | |
| 38 | 0xdf3d, | |
| 39 | 0xde5d, | |
| 40 | 0xdd7e, | |
| 41 | 0xdca0, | |
| 42 | 0xdbc2, | |
| 43 | 0xdae6, | |
| 44 | 0xda0a, | |
| 45 | 0xd92f, | |
| 46 | 0xd854, | |
| 47 | 0xd77b, | |
| 48 | 0xd6a2, | |
| 49 | 0xd5ca, | |
| 50 | 0xd4f3, | |
| 51 | 0xd41d, | |
| 52 | 0xd347, | |
| 53 | 0xd272, | |
| 54 | 0xd19e, | |
| 55 | 0xd0cb, | |
| 56 | 0xcff8, | |
| 57 | 0xcf26, | |
| 58 | 0xce55, | |
| 59 | 0xcd85, | |
| 60 | 0xccb5, | |
| 61 | 0xcbe6, | |
| 62 | 0xcb18, | |
| 63 | 0xca4b, | |
| 64 | 0xc97e, | |
| 65 | 0xc8b2, | |
| 66 | 0xc7e7, | |
| 67 | 0xc71c, | |
| 68 | 0xc652, | |
| 69 | 0xc589, | |
| 70 | 0xc4c0, | |
| 71 | 0xc3f8, | |
| 72 | 0xc331, | |
| 73 | 0xc26b, | |
| 74 | 0xc1a5, | |
| 75 | 0xc0e0, | |
| 76 | 0xc01c, | |
| 77 | 0xbf58, | |
| 78 | 0xbe95, | |
| 79 | 0xbdd2, | |
| 80 | 0xbd10, | |
| 81 | 0xbc4f, | |
| 82 | 0xbb8f, | |
| 83 | 0xbacf, | |
| 84 | 0xba10, | |
| 85 | 0xb951, | |
| 86 | 0xb894, | |
| 87 | 0xb7d6, | |
| 88 | 0xb71a, | |
| 89 | 0xb65e, | |
| 90 | 0xb5a2, | |
| 91 | 0xb4e8, | |
| 92 | 0xb42e, | |
| 93 | 0xb374, | |
| 94 | 0xb2bb, | |
| 95 | 0xb203, | |
| 96 | 0xb14b, | |
| 97 | 0xb094, | |
| 98 | 0xafde, | |
| 99 | 0xaf28, | |
| 100 | 0xae73, | |
| 101 | 0xadbe, | |
| 102 | 0xad0a, | |
| 103 | 0xac57, | |
| 104 | 0xaba4, | |
| 105 | 0xaaf1, | |
| 106 | 0xaa40, | |
| 107 | 0xa98e, | |
| 108 | 0xa8de, | |
| 109 | 0xa82e, | |
| 110 | 0xa77e, | |
| 111 | 0xa6d0, | |
| 112 | 0xa621, | |
| 113 | 0xa574, | |
| 114 | 0xa4c6, | |
| 115 | 0xa41a, | |
| 116 | 0xa36e, | |
| 117 | 0xa2c2, | |
| 118 | 0xa217, | |
| 119 | 0xa16d, | |
| 120 | 0xa0c3, | |
| 121 | 0xa01a, | |
| 122 | 0x9f71, | |
| 123 | 0x9ec8, | |
| 124 | 0x9e21, | |
| 125 | 0x9d79, | |
| 126 | 0x9cd3, | |
| 127 | 0x9c2d, | |
| 128 | 0x9b87, | |
| 129 | 0x9ae2, | |
| 130 | 0x9a3d, | |
| 131 | 0x9999, | |
| 132 | 0x98f6, | |
| 133 | 0x9852, | |
| 134 | 0x97b0, | |
| 135 | 0x970e, | |
| 136 | 0x966c, | |
| 137 | 0x95cb, | |
| 138 | 0x952b, | |
| 139 | 0x948b, | |
| 140 | 0x93eb, | |
| 141 | 0x934c, | |
| 142 | 0x92ad, | |
| 143 | 0x920f, | |
| 144 | 0x9172, | |
| 145 | 0x90d4, | |
| 146 | 0x9038, | |
| 147 | 0x8f9c, | |
| 148 | 0x8f00, | |
| 149 | 0x8e65, | |
| 150 | 0x8dca, | |
| 151 | 0x8d30, | |
| 152 | 0x8c96, | |
| 153 | 0x8bfc, | |
| 154 | 0x8b64, | |
| 155 | 0x8acb, | |
| 156 | 0x8a33, | |
| 157 | 0x899c, | |
| 158 | 0x8904, | |
| 159 | 0x886e, | |
| 160 | 0x87d8, | |
| 161 | 0x8742, | |
| 162 | 0x86ad, | |
| 163 | 0x8618, | |
| 164 | 0x8583, | |
| 165 | 0x84f0, | |
| 166 | 0x845c, | |
| 167 | 0x83c9, | |
| 168 | 0x8336, | |
| 169 | 0x82a4, | |
| 170 | 0x8212, | |
| 171 | 0x8181, | |
| 172 | 0x80f0, | |
| 173 | 0x8060, | |
| 174 | 0x7fd0, | |
| 175 | 0x7f40, | |
| 176 | 0x7eb1, | |
| 177 | 0x7e22, | |
| 178 | 0x7d93, | |
| 179 | 0x7d05, | |
| 180 | 0x7c78, | |
| 181 | 0x7beb, | |
| 182 | 0x7b5e, | |
| 183 | 0x7ad2, | |
| 184 | 0x7a46, | |
| 185 | 0x79ba, | |
| 186 | 0x792f, | |
| 187 | 0x78a4, | |
| 188 | 0x781a, | |
| 189 | 0x7790, | |
| 190 | 0x7706, | |
| 191 | 0x767d, | |
| 192 | 0x75f5, | |
| 193 | 0x756c, | |
| 194 | 0x74e4, | |
| 195 | 0x745d, | |
| 196 | 0x73d5, | |
| 197 | 0x734f, | |
| 198 | 0x72c8, | |
| 199 | 0x7242, | |
| 200 | 0x71bc, | |
| 201 | 0x7137, | |
| 202 | 0x70b2, | |
| 203 | 0x702e, | |
| 204 | 0x6fa9, | |
| 205 | 0x6f26, | |
| 206 | 0x6ea2, | |
| 207 | 0x6e1f, | |
| 208 | 0x6d9c, | |
| 209 | 0x6d1a, | |
| 210 | 0x6c98, | |
| 211 | 0x6c16, | |
| 212 | 0x6b95, | |
| 213 | 0x6b14, | |
| 214 | 0x6a94, | |
| 215 | 0x6a13, | |
| 216 | 0x6993, | |
| 217 | 0x6914, | |
| 218 | 0x6895, | |
| 219 | 0x6816, | |
| 220 | 0x6798, | |
| 221 | 0x6719, | |
| 222 | 0x669c, | |
| 223 | 0x661e, | |
| 224 | 0x65a1, | |
| 225 | 0x6524, | |
| 226 | 0x64a8, | |
| 227 | 0x642c, | |
| 228 | 0x63b0, | |
| 229 | 0x6335, | |
| 230 | 0x62ba, | |
| 231 | 0x623f, | |
| 232 | 0x61c5, | |
| 233 | 0x614b, | |
| 234 | 0x60d1, | |
| 235 | 0x6058, | |
| 236 | 0x5fdf, | |
| 237 | 0x5f66, | |
| 238 | 0x5eed, | |
| 239 | 0x5e75, | |
| 240 | 0x5dfd, | |
| 241 | 0x5d86, | |
| 242 | 0x5d0f, | |
| 243 | 0x5c98, | |
| 244 | 0x5c22, | |
| 245 | 0x5bab, | |
| 246 | 0x5b35, | |
| 247 | 0x5ac0, | |
| 248 | 0x5a4b, | |
| 249 | 0x59d6, | |
| 250 | 0x5961, | |
| 251 | 0x58ed, | |
| 252 | 0x5879, | |
| 253 | 0x5805, | |
| 254 | 0x5791, | |
| 255 | 0x571e, | |
| 256 | 0x56ac, | |
| 257 | 0x5639, | |
| 258 | 0x55c7, | |
| 259 | 0x5555, | |
| 260 | 0x54e3, | |
| 261 | 0x5472, | |
| 262 | 0x5401, | |
| 263 | 0x5390, | |
| 264 | 0x5320, | |
| 265 | 0x52af, | |
| 266 | 0x5240, | |
| 267 | 0x51d0, | |
| 268 | 0x5161, | |
| 269 | 0x50f2, | |
| 270 | 0x5083, | |
| 271 | 0x5015, | |
| 272 | 0x4fa6, | |
| 273 | 0x4f38, | |
| 274 | 0x4ecb, | |
| 275 | 0x4e5e, | |
| 276 | 0x4df1, | |
| 277 | 0x4d84, | |
| 278 | 0x4d17, | |
| 279 | 0x4cab, | |
| 280 | 0x4c3f, | |
| 281 | 0x4bd3, | |
| 282 | 0x4b68, | |
| 283 | 0x4afd, | |
| 284 | 0x4a92, | |
| 285 | 0x4a27, | |
| 286 | 0x49bd, | |
| 287 | 0x4953, | |
| 288 | 0x48e9, | |
| 289 | 0x4880, | |
| 290 | 0x4817, | |
| 291 | 0x47ae, | |
| 292 | 0x4745, | |
| 293 | 0x46dc, | |
| 294 | 0x4674, | |
| 295 | 0x460c, | |
| 296 | 0x45a5, | |
| 297 | 0x453d, | |
| 298 | 0x44d6, | |
| 299 | 0x446f, | |
| 300 | 0x4408, | |
| 301 | 0x43a2, | |
| 302 | 0x433c, | |
| 303 | 0x42d6, | |
| 304 | 0x4270, | |
| 305 | 0x420b, | |
| 306 | 0x41a6, | |
| 307 | 0x4141, | |
| 308 | 0x40dc, | |
| 309 | 0x4078, | |
| 310 | 0x4014, | |
| 311 | 0x3fb0, | |
| 312 | 0x3f4c, | |
| 313 | 0x3ee8, | |
| 314 | 0x3e85, | |
| 315 | 0x3e22, | |
| 316 | 0x3dc0, | |
| 317 | 0x3d5d, | |
| 318 | 0x3cfb, | |
| 319 | 0x3c99, | |
| 320 | 0x3c37, | |
| 321 | 0x3bd6, | |
| 322 | 0x3b74, | |
| 323 | 0x3b13, | |
| 324 | 0x3ab2, | |
| 325 | 0x3a52, | |
| 326 | 0x39f1, | |
| 327 | 0x3991, | |
| 328 | 0x3931, | |
| 329 | 0x38d2, | |
| 330 | 0x3872, | |
| 331 | 0x3813, | |
| 332 | 0x37b4, | |
| 333 | 0x3755, | |
| 334 | 0x36f7, | |
| 335 | 0x3698, | |
| 336 | 0x363a, | |
| 337 | 0x35dc, | |
| 338 | 0x357f, | |
| 339 | 0x3521, | |
| 340 | 0x34c4, | |
| 341 | 0x3467, | |
| 342 | 0x340a, | |
| 343 | 0x33ae, | |
| 344 | 0x3351, | |
| 345 | 0x32f5, | |
| 346 | 0x3299, | |
| 347 | 0x323e, | |
| 348 | 0x31e2, | |
| 349 | 0x3187, | |
| 350 | 0x312c, | |
| 351 | 0x30d1, | |
| 352 | 0x3076, | |
| 353 | 0x301c, | |
| 354 | 0x2fc2, | |
| 355 | 0x2f68, | |
| 356 | 0x2f0e, | |
| 357 | 0x2eb4, | |
| 358 | 0x2e5b, | |
| 359 | 0x2e02, | |
| 360 | 0x2da9, | |
| 361 | 0x2d50, | |
| 362 | 0x2cf8, | |
| 363 | 0x2c9f, | |
| 364 | 0x2c47, | |
| 365 | 0x2bef, | |
| 366 | 0x2b97, | |
| 367 | 0x2b40, | |
| 368 | 0x2ae8, | |
| 369 | 0x2a91, | |
| 370 | 0x2a3a, | |
| 371 | 0x29e4, | |
| 372 | 0x298d, | |
| 373 | 0x2937, | |
| 374 | 0x28e0, | |
| 375 | 0x288b, | |
| 376 | 0x2835, | |
| 377 | 0x27df, | |
| 378 | 0x278a, | |
| 379 | 0x2735, | |
| 380 | 0x26e0, | |
| 381 | 0x268b, | |
| 382 | 0x2636, | |
| 383 | 0x25e2, | |
| 384 | 0x258d, | |
| 385 | 0x2539, | |
| 386 | 0x24e5, | |
| 387 | 0x2492, | |
| 388 | 0x243e, | |
| 389 | 0x23eb, | |
| 390 | 0x2398, | |
| 391 | 0x2345, | |
| 392 | 0x22f2, | |
| 393 | 0x22a0, | |
| 394 | 0x224d, | |
| 395 | 0x21fb, | |
| 396 | 0x21a9, | |
| 397 | 0x2157, | |
| 398 | 0x2105, | |
| 399 | 0x20b4, | |
| 400 | 0x2063, | |
| 401 | 0x2012, | |
| 402 | 0x1fc1, | |
| 403 | 0x1f70, | |
| 404 | 0x1f1f, | |
| 405 | 0x1ecf, | |
| 406 | 0x1e7f, | |
| 407 | 0x1e2e, | |
| 408 | 0x1ddf, | |
| 409 | 0x1d8f, | |
| 410 | 0x1d3f, | |
| 411 | 0x1cf0, | |
| 412 | 0x1ca1, | |
| 413 | 0x1c52, | |
| 414 | 0x1c03, | |
| 415 | 0x1bb4, | |
| 416 | 0x1b66, | |
| 417 | 0x1b17, | |
| 418 | 0x1ac9, | |
| 419 | 0x1a7b, | |
| 420 | 0x1a2d, | |
| 421 | 0x19e0, | |
| 422 | 0x1992, | |
| 423 | 0x1945, | |
| 424 | 0x18f8, | |
| 425 | 0x18ab, | |
| 426 | 0x185e, | |
| 427 | 0x1811, | |
| 428 | 0x17c4, | |
| 429 | 0x1778, | |
| 430 | 0x172c, | |
| 431 | 0x16e0, | |
| 432 | 0x1694, | |
| 433 | 0x1648, | |
| 434 | 0x15fd, | |
| 435 | 0x15b1, | |
| 436 | 0x1566, | |
| 437 | 0x151b, | |
| 438 | 0x14d0, | |
| 439 | 0x1485, | |
| 440 | 0x143b, | |
| 441 | 0x13f0, | |
| 442 | 0x13a6, | |
| 443 | 0x135c, | |
| 444 | 0x1312, | |
| 445 | 0x12c8, | |
| 446 | 0x127f, | |
| 447 | 0x1235, | |
| 448 | 0x11ec, | |
| 449 | 0x11a3, | |
| 450 | 0x1159, | |
| 451 | 0x1111, | |
| 452 | 0x10c8, | |
| 453 | 0x107f, | |
| 454 | 0x1037, | |
| 455 | 0x0fef, | |
| 456 | 0x0fa6, | |
| 457 | 0x0f5e, | |
| 458 | 0x0f17, | |
| 459 | 0x0ecf, | |
| 460 | 0x0e87, | |
| 461 | 0x0e40, | |
| 462 | 0x0df9, | |
| 463 | 0x0db2, | |
| 464 | 0x0d6b, | |
| 465 | 0x0d24, | |
| 466 | 0x0cdd, | |
| 467 | 0x0c97, | |
| 468 | 0x0c50, | |
| 469 | 0x0c0a, | |
| 470 | 0x0bc4, | |
| 471 | 0x0b7e, | |
| 472 | 0x0b38, | |
| 473 | 0x0af2, | |
| 474 | 0x0aad, | |
| 475 | 0x0a68, | |
| 476 | 0x0a22, | |
| 477 | 0x09dd, | |
| 478 | 0x0998, | |
| 479 | 0x0953, | |
| 480 | 0x090f, | |
| 481 | 0x08ca, | |
| 482 | 0x0886, | |
| 483 | 0x0842, | |
| 484 | 0x07fd, | |
| 485 | 0x07b9, | |
| 486 | 0x0776, | |
| 487 | 0x0732, | |
| 488 | 0x06ee, | |
| 489 | 0x06ab, | |
| 490 | 0x0668, | |
| 491 | 0x0624, | |
| 492 | 0x05e1, | |
| 493 | 0x059e, | |
| 494 | 0x055c, | |
| 495 | 0x0519, | |
| 496 | 0x04d6, | |
| 497 | 0x0494, | |
| 498 | 0x0452, | |
| 499 | 0x0410, | |
| 500 | 0x03ce, | |
| 501 | 0x038c, | |
| 502 | 0x034a, | |
| 503 | 0x0309, | |
| 504 | 0x02c7, | |
| 505 | 0x0286, | |
| 506 | 0x0245, | |
| 507 | 0x0204, | |
| 508 | 0x01c3, | |
| 509 | 0x0182, | |
| 510 | 0x0141, | |
| 511 | 0x0101, | |
| 512 | 0x00c0, | |
| 513 | 0x0080, | |
| 514 | 0x0040, | |
| 515 | 0x6a09, | |
| 516 | 0xffff, | |
| 517 | 0x6955, | |
| 518 | 0xff00, | |
| 519 | 0x68a1, | |
| 520 | 0xfe02, | |
| 521 | 0x67ef, | |
| 522 | 0xfd06, | |
| 523 | 0x673e, | |
| 524 | 0xfc0b, | |
| 525 | 0x668d, | |
| 526 | 0xfb12, | |
| 527 | 0x65de, | |
| 528 | 0xfa1a, | |
| 529 | 0x6530, | |
| 530 | 0xf923, | |
| 531 | 0x6482, | |
| 532 | 0xf82e, | |
| 533 | 0x63d6, | |
| 534 | 0xf73b, | |
| 535 | 0x632b, | |
| 536 | 0xf648, | |
| 537 | 0x6280, | |
| 538 | 0xf557, | |
| 539 | 0x61d7, | |
| 540 | 0xf467, | |
| 541 | 0x612e, | |
| 542 | 0xf379, | |
| 543 | 0x6087, | |
| 544 | 0xf28c, | |
| 545 | 0x5fe0, | |
| 546 | 0xf1a0, | |
| 547 | 0x5f3a, | |
| 548 | 0xf0b6, | |
| 549 | 0x5e95, | |
| 550 | 0xefcd, | |
| 551 | 0x5df1, | |
| 552 | 0xeee5, | |
| 553 | 0x5d4e, | |
| 554 | 0xedff, | |
| 555 | 0x5cac, | |
| 556 | 0xed19, | |
| 557 | 0x5c0b, | |
| 558 | 0xec35, | |
| 559 | 0x5b6b, | |
| 560 | 0xeb52, | |
| 561 | 0x5acb, | |
| 562 | 0xea71, | |
| 563 | 0x5a2c, | |
| 564 | 0xe990, | |
| 565 | 0x598f, | |
| 566 | 0xe8b1, | |
| 567 | 0x58f2, | |
| 568 | 0xe7d3, | |
| 569 | 0x5855, | |
| 570 | 0xe6f6, | |
| 571 | 0x57ba, | |
| 572 | 0xe61b, | |
| 573 | 0x5720, | |
| 574 | 0xe540, | |
| 575 | 0x5686, | |
| 576 | 0xe467, | |
| 577 | 0x55ed, | |
| 578 | 0xe38e, | |
| 579 | 0x5555, | |
| 580 | 0xe2b7, | |
| 581 | 0x54be, | |
| 582 | 0xe1e1, | |
| 583 | 0x5427, | |
| 584 | 0xe10d, | |
| 585 | 0x5391, | |
| 586 | 0xe039, | |
| 587 | 0x52fc, | |
| 588 | 0xdf66, | |
| 589 | 0x5268, | |
| 590 | 0xde94, | |
| 591 | 0x51d5, | |
| 592 | 0xddc4, | |
| 593 | 0x5142, | |
| 594 | 0xdcf4, | |
| 595 | 0x50b0, | |
| 596 | 0xdc26, | |
| 597 | 0x501f, | |
| 598 | 0xdb59, | |
| 599 | 0x4f8e, | |
| 600 | 0xda8c, | |
| 601 | 0x4efe, | |
| 602 | 0xd9c1, | |
| 603 | 0x4e6f, | |
| 604 | 0xd8f7, | |
| 605 | 0x4de1, | |
| 606 | 0xd82d, | |
| 607 | 0x4d53, | |
| 608 | 0xd765, | |
| 609 | 0x4cc6, | |
| 610 | 0xd69e, | |
| 611 | 0x4c3a, | |
| 612 | 0xd5d7, | |
| 613 | 0x4baf, | |
| 614 | 0xd512, | |
| 615 | 0x4b24, | |
| 616 | 0xd44e, | |
| 617 | 0x4a9a, | |
| 618 | 0xd38a, | |
| 619 | 0x4a10, | |
| 620 | 0xd2c8, | |
| 621 | 0x4987, | |
| 622 | 0xd206, | |
| 623 | 0x48ff, | |
| 624 | 0xd146, | |
| 625 | 0x4878, | |
| 626 | 0xd086, | |
| 627 | 0x47f1, | |
| 628 | 0xcfc7, | |
| 629 | 0x476b, | |
| 630 | 0xcf0a, | |
| 631 | 0x46e5, | |
| 632 | 0xce4d, | |
| 633 | 0x4660, | |
| 634 | 0xcd91, | |
| 635 | 0x45dc, | |
| 636 | 0xccd6, | |
| 637 | 0x4558, | |
| 638 | 0xcc1b, | |
| 639 | 0x44d5, | |
| 640 | 0xcb62, | |
| 641 | 0x4453, | |
| 642 | 0xcaa9, | |
| 643 | 0x43d1, | |
| 644 | 0xc9f2, | |
| 645 | 0x434f, | |
| 646 | 0xc93b, | |
| 647 | 0x42cf, | |
| 648 | 0xc885, | |
| 649 | 0x424f, | |
| 650 | 0xc7d0, | |
| 651 | 0x41cf, | |
| 652 | 0xc71c, | |
| 653 | 0x4151, | |
| 654 | 0xc669, | |
| 655 | 0x40d2, | |
| 656 | 0xc5b6, | |
| 657 | 0x4055, | |
| 658 | 0xc504, | |
| 659 | 0x3fd8, | |
| 660 | 0xc453, | |
| 661 | 0x3f5b, | |
| 662 | 0xc3a3, | |
| 663 | 0x3edf, | |
| 664 | 0xc2f4, | |
| 665 | 0x3e64, | |
| 666 | 0xc245, | |
| 667 | 0x3de9, | |
| 668 | 0xc198, | |
| 669 | 0x3d6e, | |
| 670 | 0xc0eb, | |
| 671 | 0x3cf5, | |
| 672 | 0xc03f, | |
| 673 | 0x3c7c, | |
| 674 | 0xbf93, | |
| 675 | 0x3c03, | |
| 676 | 0xbee9, | |
| 677 | 0x3b8b, | |
| 678 | 0xbe3f, | |
| 679 | 0x3b13, | |
| 680 | 0xbd96, | |
| 681 | 0x3a9c, | |
| 682 | 0xbced, | |
| 683 | 0x3a26, | |
| 684 | 0xbc46, | |
| 685 | 0x39b0, | |
| 686 | 0xbb9f, | |
| 687 | 0x393a, | |
| 688 | 0xbaf8, | |
| 689 | 0x38c5, | |
| 690 | 0xba53, | |
| 691 | 0x3851, | |
| 692 | 0xb9ae, | |
| 693 | 0x37dd, | |
| 694 | 0xb90a, | |
| 695 | 0x3769, | |
| 696 | 0xb867, | |
| 697 | 0x36f6, | |
| 698 | 0xb7c5, | |
| 699 | 0x3684, | |
| 700 | 0xb723, | |
| 701 | 0x3612, | |
| 702 | 0xb681, | |
| 703 | 0x35a0, | |
| 704 | 0xb5e1, | |
| 705 | 0x352f, | |
| 706 | 0xb541, | |
| 707 | 0x34bf, | |
| 708 | 0xb4a2, | |
| 709 | 0x344f, | |
| 710 | 0xb404, | |
| 711 | 0x33df, | |
| 712 | 0xb366, | |
| 713 | 0x3370, | |
| 714 | 0xb2c9, | |
| 715 | 0x3302, | |
| 716 | 0xb22c, | |
| 717 | 0x3293, | |
| 718 | 0xb191, | |
| 719 | 0x3226, | |
| 720 | 0xb0f5, | |
| 721 | 0x31b9, | |
| 722 | 0xb05b, | |
| 723 | 0x314c, | |
| 724 | 0xafc1, | |
| 725 | 0x30df, | |
| 726 | 0xaf28, | |
| 727 | 0x3074, | |
| 728 | 0xae8f, | |
| 729 | 0x3008, | |
| 730 | 0xadf7, | |
| 731 | 0x2f9d, | |
| 732 | 0xad60, | |
| 733 | 0x2f33, | |
| 734 | 0xacc9, | |
| 735 | 0x2ec8, | |
| 736 | 0xac33, | |
| 737 | 0x2e5f, | |
| 738 | 0xab9e, | |
| 739 | 0x2df6, | |
| 740 | 0xab09, | |
| 741 | 0x2d8d, | |
| 742 | 0xaa75, | |
| 743 | 0x2d24, | |
| 744 | 0xa9e1, | |
| 745 | 0x2cbc, | |
| 746 | 0xa94e, | |
| 747 | 0x2c55, | |
| 748 | 0xa8bc, | |
| 749 | 0x2bee, | |
| 750 | 0xa82a, | |
| 751 | 0x2b87, | |
| 752 | 0xa799, | |
| 753 | 0x2b21, | |
| 754 | 0xa708, | |
| 755 | 0x2abb, | |
| 756 | 0xa678, | |
| 757 | 0x2a55, | |
| 758 | 0xa5e8, | |
| 759 | 0x29f0, | |
| 760 | 0xa559, | |
| 761 | 0x298b, | |
| 762 | 0xa4cb, | |
| 763 | 0x2927, | |
| 764 | 0xa43d, | |
| 765 | 0x28c3, | |
| 766 | 0xa3b0, | |
| 767 | 0x2860, | |
| 768 | 0xa323, | |
| 769 | 0x27fd, | |
| 770 | 0xa297, | |
| 771 | 0x279a, | |
| 772 | 0xa20b, | |
| 773 | 0x2738, | |
| 774 | 0xa180, | |
| 775 | 0x26d6, | |
| 776 | 0xa0f6, | |
| 777 | 0x2674, | |
| 778 | 0xa06c, | |
| 779 | 0x2613, | |
| 780 | 0x9fe2, | |
| 781 | 0x25b2, | |
| 782 | 0x9f59, | |
| 783 | 0x2552, | |
| 784 | 0x9ed1, | |
| 785 | 0x24f2, | |
| 786 | 0x9e49, | |
| 787 | 0x2492, | |
| 788 | 0x9dc2, | |
| 789 | 0x2432, | |
| 790 | 0x9d3b, | |
| 791 | 0x23d3, | |
| 792 | 0x9cb4, | |
| 793 | 0x2375, | |
| 794 | 0x9c2f, | |
| 795 | 0x2317, | |
| 796 | 0x9ba9, | |
| 797 | 0x22b9, | |
| 798 | 0x9b25, | |
| 799 | 0x225b, | |
| 800 | 0x9aa0, | |
| 801 | 0x21fe, | |
| 802 | 0x9a1c, | |
| 803 | 0x21a1, | |
| 804 | 0x9999, | |
| 805 | 0x2145, | |
| 806 | 0x9916, | |
| 807 | 0x20e8, | |
| 808 | 0x9894, | |
| 809 | 0x208d, | |
| 810 | 0x9812, | |
| 811 | 0x2031, | |
| 812 | 0x9791, | |
| 813 | 0x1fd6, | |
| 814 | 0x9710, | |
| 815 | 0x1f7b, | |
| 816 | 0x968f, | |
| 817 | 0x1f21, | |
| 818 | 0x960f, | |
| 819 | 0x1ec7, | |
| 820 | 0x9590, | |
| 821 | 0x1e6d, | |
| 822 | 0x9511, | |
| 823 | 0x1e13, | |
| 824 | 0x9492, | |
| 825 | 0x1dba, | |
| 826 | 0x9414, | |
| 827 | 0x1d61, | |
| 828 | 0x9397, | |
| 829 | 0x1d09, | |
| 830 | 0x931a, | |
| 831 | 0x1cb1, | |
| 832 | 0x929d, | |
| 833 | 0x1c59, | |
| 834 | 0x9221, | |
| 835 | 0x1c01, | |
| 836 | 0x91a5, | |
| 837 | 0x1baa, | |
| 838 | 0x9129, | |
| 839 | 0x1b53, | |
| 840 | 0x90af, | |
| 841 | 0x1afc, | |
| 842 | 0x9034, | |
| 843 | 0x1aa6, | |
| 844 | 0x8fba, | |
| 845 | 0x1a50, | |
| 846 | 0x8f40, | |
| 847 | 0x19fa, | |
| 848 | 0x8ec7, | |
| 849 | 0x19a5, | |
| 850 | 0x8e4f, | |
| 851 | 0x1950, | |
| 852 | 0x8dd6, | |
| 853 | 0x18fb, | |
| 854 | 0x8d5e, | |
| 855 | 0x18a7, | |
| 856 | 0x8ce7, | |
| 857 | 0x1853, | |
| 858 | 0x8c70, | |
| 859 | 0x17ff, | |
| 860 | 0x8bf9, | |
| 861 | 0x17ab, | |
| 862 | 0x8b83, | |
| 863 | 0x1758, | |
| 864 | 0x8b0d, | |
| 865 | 0x1705, | |
| 866 | 0x8a98, | |
| 867 | 0x16b2, | |
| 868 | 0x8a23, | |
| 869 | 0x1660, | |
| 870 | 0x89ae, | |
| 871 | 0x160d, | |
| 872 | 0x893a, | |
| 873 | 0x15bc, | |
| 874 | 0x88c6, | |
| 875 | 0x156a, | |
| 876 | 0x8853, | |
| 877 | 0x1519, | |
| 878 | 0x87e0, | |
| 879 | 0x14c8, | |
| 880 | 0x876d, | |
| 881 | 0x1477, | |
| 882 | 0x86fb, | |
| 883 | 0x1426, | |
| 884 | 0x8689, | |
| 885 | 0x13d6, | |
| 886 | 0x8618, | |
| 887 | 0x1386, | |
| 888 | 0x85a7, | |
| 889 | 0x1337, | |
| 890 | 0x8536, | |
| 891 | 0x12e7, | |
| 892 | 0x84c6, | |
| 893 | 0x1298, | |
| 894 | 0x8456, | |
| 895 | 0x1249, | |
| 896 | 0x83e7, | |
| 897 | 0x11fb, | |
| 898 | 0x8377, | |
| 899 | 0x11ac, | |
| 900 | 0x8309, | |
| 901 | 0x115e, | |
| 902 | 0x829a, | |
| 903 | 0x1111, | |
| 904 | 0x822c, | |
| 905 | 0x10c3, | |
| 906 | 0x81bf, | |
| 907 | 0x1076, | |
| 908 | 0x8151, | |
| 909 | 0x1029, | |
| 910 | 0x80e4, | |
| 911 | 0x0fdc, | |
| 912 | 0x8078, | |
| 913 | 0x0f8f, | |
| 914 | 0x800c, | |
| 915 | 0x0f43, | |
| 916 | 0x7fa0, | |
| 917 | 0x0ef7, | |
| 918 | 0x7f34, | |
| 919 | 0x0eab, | |
| 920 | 0x7ec9, | |
| 921 | 0x0e60, | |
| 922 | 0x7e5e, | |
| 923 | 0x0e15, | |
| 924 | 0x7df4, | |
| 925 | 0x0dca, | |
| 926 | 0x7d8a, | |
| 927 | 0x0d7f, | |
| 928 | 0x7d20, | |
| 929 | 0x0d34, | |
| 930 | 0x7cb6, | |
| 931 | 0x0cea, | |
| 932 | 0x7c4d, | |
| 933 | 0x0ca0, | |
| 934 | 0x7be5, | |
| 935 | 0x0c56, | |
| 936 | 0x7b7c, | |
| 937 | 0x0c0c, | |
| 938 | 0x7b14, | |
| 939 | 0x0bc3, | |
| 940 | 0x7aac, | |
| 941 | 0x0b7a, | |
| 942 | 0x7a45, | |
| 943 | 0x0b31, | |
| 944 | 0x79de, | |
| 945 | 0x0ae8, | |
| 946 | 0x7977, | |
| 947 | 0x0aa0, | |
| 948 | 0x7911, | |
| 949 | 0x0a58, | |
| 950 | 0x78ab, | |
| 951 | 0x0a10, | |
| 952 | 0x7845, | |
| 953 | 0x09c8, | |
| 954 | 0x77df, | |
| 955 | 0x0981, | |
| 956 | 0x777a, | |
| 957 | 0x0939, | |
| 958 | 0x7715, | |
| 959 | 0x08f2, | |
| 960 | 0x76b1, | |
| 961 | 0x08ab, | |
| 962 | 0x764d, | |
| 963 | 0x0865, | |
| 964 | 0x75e9, | |
| 965 | 0x081e, | |
| 966 | 0x7585, | |
| 967 | 0x07d8, | |
| 968 | 0x7522, | |
| 969 | 0x0792, | |
| 970 | 0x74bf, | |
| 971 | 0x074d, | |
| 972 | 0x745d, | |
| 973 | 0x0707, | |
| 974 | 0x73fa, | |
| 975 | 0x06c2, | |
| 976 | 0x7398, | |
| 977 | 0x067d, | |
| 978 | 0x7337, | |
| 979 | 0x0638, | |
| 980 | 0x72d5, | |
| 981 | 0x05f3, | |
| 982 | 0x7274, | |
| 983 | 0x05af, | |
| 984 | 0x7213, | |
| 985 | 0x056a, | |
| 986 | 0x71b3, | |
| 987 | 0x0526, | |
| 988 | 0x7152, | |
| 989 | 0x04e2, | |
| 990 | 0x70f2, | |
| 991 | 0x049f, | |
| 992 | 0x7093, | |
| 993 | 0x045b, | |
| 994 | 0x7033, | |
| 995 | 0x0418, | |
| 996 | 0x6fd4, | |
| 997 | 0x03d5, | |
| 998 | 0x6f76, | |
| 999 | 0x0392, | |
| 1000 | 0x6f17, | |
| 1001 | 0x0350, | |
| 1002 | 0x6eb9, | |
| 1003 | 0x030d, | |
| 1004 | 0x6e5b, | |
| 1005 | 0x02cb, | |
| 1006 | 0x6dfd, | |
| 1007 | 0x0289, | |
| 1008 | 0x6da0, | |
| 1009 | 0x0247, | |
| 1010 | 0x6d43, | |
| 1011 | 0x0206, | |
| 1012 | 0x6ce6, | |
| 1013 | 0x01c4, | |
| 1014 | 0x6c8a, | |
| 1015 | 0x0183, | |
| 1016 | 0x6c2d, | |
| 1017 | 0x0142, | |
| 1018 | 0x6bd1, | |
| 1019 | 0x0101, | |
| 1020 | 0x6b76, | |
| 1021 | 0x00c0, | |
| 1022 | 0x6b1a, | |
| 1023 | 0x0080, | |
| 1024 | 0x6abf, | |
| 1025 | 0x0040, | |
| 1026 | 0x6a64 | |
| 1027 | }; |
| r9854 | r9855 | |
|---|---|---|
| 22 | 22 | #include "debugger.h" |
| 23 | 23 | #include "profiler.h" |
| 24 | 24 | #include "rsp.h" |
| 25 | #include "rspdiv.h" | |
| 25 | 26 | #include "rspfe.h" |
| 26 | 27 | #include "cpu/drcfe.h" |
| 27 | 28 | #include "cpu/drcuml.h" |
| r9854 | r9855 | |
| 43 | 44 | |
| 44 | 45 | #define SINGLE_INSTRUCTION_MODE (0) |
| 45 | 46 | |
| 46 | #define DRC_LSV (0) | |
| 47 | #define DRC_LLV (0) | |
| 48 | #define DRC_LDV (0) | |
| 49 | #define DRC_LQV (0) | |
| 50 | #define DRC_LPV (0) | |
| 51 | #define DRC_LUV (0) | |
| 52 | 47 | |
| 53 | #define DRC_SSV (0) | |
| 54 | #define DRC_SLV (0) | |
| 55 | #define DRC_SDV (0) | |
| 56 | #define DRC_SQV (0) | |
| 57 | #define DRC_SPV (0) // Todo | |
| 58 | ||
| 59 | #define DRC_VMUDL (0) | |
| 60 | #define DRC_VMUDM (0) | |
| 61 | #define DRC_VMADM (0) | |
| 62 | #define DRC_VMADN (0) | |
| 63 | #define DRC_VMADH (0) | |
| 64 | #define DRC_VADD (0) | |
| 65 | #define DRC_VAND (0) | |
| 66 | #define DRC_VNAND (0) | |
| 67 | #define DRC_VOR (0) | |
| 68 | #define DRC_VNOR (0) | |
| 69 | #define DRC_VXOR (0) | |
| 70 | #define DRC_VNXOR (0) | |
| 71 | ||
| 72 | ||
| 73 | 48 | /*************************************************************************** |
| 74 | 49 | CONSTANTS |
| 75 | 50 | ***************************************************************************/ |
| r9854 | r9855 | |
| 100 | 75 | ***************************************************************************/ |
| 101 | 76 | |
| 102 | 77 | #define R32(reg) rsp->impstate->regmap[reg].type, rsp->impstate->regmap[reg].value |
| 103 | #define VB(reg, el) rsp->impstate->regmap[16*reg+(15-el)+34].type, rsp->impstate->regmap[16*reg+(15-el)+34].value | |
| 104 | #define VS(reg, el) rsp->impstate->regmap[8*reg+(7-el)+546].type, rsp->impstate->regmap[8*reg+(7-el)+546].value | |
| 105 | #define VSX(reg, el) rsp->impstate->regmap[8*reg+el+546].type, rsp->impstate->regmap[8*reg+el+546].value | |
| 106 | #define VL(reg, el) rsp->impstate->regmap[4*reg+(3-el)+802].type, rsp->impstate->regmap[4*reg+(3-el)+802].value | |
| 107 | #define VLX(reg, el) rsp->impstate->regmap[4*reg+el+802].type, rsp->impstate->regmap[4*reg+el+802].value | |
| 108 | #define VFLAG(reg) rsp->impstate->regmap[930+reg].type, rsp->impstate->regmap[930+reg].value | |
| 109 | #define VACCUML(reg) rsp->impstate->regmap[934+reg].type, rsp->impstate->regmap[934+reg].value | |
| 110 | #define VACCUMHH(reg) rsp->impstate->regmap[942+reg].type, rsp->impstate->regmap[942+reg].value | |
| 111 | #define VACCUMHM(reg) rsp->impstate->regmap[950+reg].type, rsp->impstate->regmap[950+reg].value | |
| 112 | #define VACCUMHL(reg) rsp->impstate->regmap[958+reg].type, rsp->impstate->regmap[958+reg].value | |
| 113 | #define VACCUMHZ(reg) rsp->impstate->regmap[966+reg].type, rsp->impstate->regmap[966+reg].value | |
| 114 | #define VACCUMWMH(reg) rsp->impstate->regmap[974+reg].type, rsp->impstate->regmap[974+reg].value | |
| 115 | #define VACCUMWZL(reg) rsp->impstate->regmap[982+reg].type, rsp->impstate->regmap[982+reg].value | |
| 116 | #define VRES(reg) rsp->impstate->regmap[990+reg].type, rsp->impstate->regmap[990+reg].value | |
| 117 | 78 | |
| 118 | ||
| 119 | ||
| 120 | 79 | /*************************************************************************** |
| 121 | 80 | STRUCTURES & TYPEDEFS |
| 122 | 81 | ***************************************************************************/ |
| r9854 | r9855 | |
| 159 | 118 | const char * format; /* format string for print_debug */ |
| 160 | 119 | UINT32 arg0; /* print_debug argument 1 */ |
| 161 | 120 | UINT32 arg1; /* print_debug argument 2 */ |
| 162 | UINT64 arg64; /* print_debug 64-bit argument */ | |
| 121 | UINT32 arg2; /* print_debug argument 3 */ | |
| 122 | UINT32 arg3; /* print_debug argument 4 */ | |
| 163 | 123 | UINT32 vres[8]; /* used for temporary vector results */ |
| 164 | 124 | |
| 165 | 125 | /* register mappings */ |
| 166 | drcuml_parameter regmap[ | |
| 126 | drcuml_parameter regmap[34 | |
| 167 | 127 | |
| 168 | 128 | /* subroutines */ |
| 169 | 129 | drcuml_codehandle * entry; /* entry point */ |
| r9854 | r9855 | |
| 200 | 160 | static void cfunc_sp_set_status_cb(void *param); |
| 201 | 161 | |
| 202 | 162 | static void cfunc_rsp_lbv(void *param); |
| 203 | #if !(DRC_LSV) | |
| 204 | 163 | static void cfunc_rsp_lsv(void *param); |
| 205 | #endif | |
| 206 | #if !(DRC_LLV) | |
| 207 | 164 | static void cfunc_rsp_llv(void *param); |
| 208 | #endif | |
| 209 | #if !(DRC_LDV) | |
| 210 | 165 | static void cfunc_rsp_ldv(void *param); |
| 211 | #endif | |
| 212 | #if !(DRC_LQV) | |
| 213 | 166 | static void cfunc_rsp_lqv(void *param); |
| 214 | #endif | |
| 215 | 167 | static void cfunc_rsp_lrv(void *param); |
| 216 | #if !(DRC_LPV) | |
| 217 | 168 | static void cfunc_rsp_lpv(void *param); |
| 218 | #endif | |
| 219 | #if !(DRC_LUV) | |
| 220 | 169 | static void cfunc_rsp_luv(void *param); |
| 221 | #endif | |
| 222 | 170 | static void cfunc_rsp_lhv(void *param); |
| 223 | 171 | static void cfunc_rsp_lfv(void *param); |
| 224 | 172 | static void cfunc_rsp_lwv(void *param); |
| 225 | 173 | static void cfunc_rsp_ltv(void *param); |
| 226 | 174 | |
| 227 | 175 | static void cfunc_rsp_sbv(void *param); |
| 228 | #if !(DRC_SSV) | |
| 229 | 176 | static void cfunc_rsp_ssv(void *param); |
| 230 | #endif | |
| 231 | #if !(DRC_SLV) | |
| 232 | 177 | static void cfunc_rsp_slv(void *param); |
| 233 | #endif | |
| 234 | #if !(DRC_SDV) | |
| 235 | 178 | static void cfunc_rsp_sdv(void *param); |
| 236 | #endif | |
| 237 | #if !(DRC_SQV) | |
| 238 | 179 | static void cfunc_rsp_sqv(void *param); |
| 239 | #endif | |
| 240 | 180 | static void cfunc_rsp_srv(void *param); |
| 241 | #if !(DRC_SPV) | |
| 242 | 181 | static void cfunc_rsp_spv(void *param); |
| 243 | #endif | |
| 244 | 182 | static void cfunc_rsp_suv(void *param); |
| 245 | 183 | static void cfunc_rsp_shv(void *param); |
| 246 | 184 | static void cfunc_rsp_sfv(void *param); |
| r9854 | r9855 | |
| 252 | 190 | static void static_generate_out_of_cycles(rsp_state *rsp); |
| 253 | 191 | static void static_generate_memory_accessor(rsp_state *rsp, int size, int iswrite, const char *name, drcuml_codehandle **handleptr); |
| 254 | 192 | |
| 255 | #if (DRC_VMADN) | |
| 256 | static void generate_saturate_accum_unsigned(rsp_state *rsp, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, int accum); | |
| 257 | #endif | |
| 258 | #if (DRC_VMADH) || (DRC_VMADM) | |
| 259 | static void generate_saturate_accum_signed(rsp_state *rsp, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, int accum); | |
| 260 | #endif | |
| 261 | #if (DRC_VMUDL) | |
| 262 | static int generate_vmudl(rsp_state *rsp, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc); // vmudl | |
| 263 | #endif | |
| 264 | #if (DRC_VMADM) | |
| 265 | static int generate_vmadm(rsp_state *rsp, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc); // vmadm | |
| 266 | #endif | |
| 267 | #if (DRC_VMADN) | |
| 268 | static int generate_vmadn(rsp_state *rsp, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc); // vmadn | |
| 269 | #endif | |
| 270 | #if (DRC_VMADH) | |
| 271 | static int generate_vmadh(rsp_state *rsp, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc); // vmadh | |
| 272 | #endif | |
| 273 | #if (DRC_VADD) | |
| 274 | static int generate_vadd(rsp_state *rsp, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc); // vadd | |
| 275 | #endif | |
| 276 | #if (DRC_VAND) | |
| 277 | static int generate_vand(rsp_state *rsp, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc); // vand | |
| 278 | #endif | |
| 279 | #if (DRC_VNAND) | |
| 280 | static int generate_vnand(rsp_state *rsp, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc); // vand | |
| 281 | #endif | |
| 282 | #if (DRC_VOR) | |
| 283 | static int generate_vor(rsp_state *rsp, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc); // vand | |
| 284 | #endif | |
| 285 | #if (DRC_VNOR) | |
| 286 | static int generate_vnor(rsp_state *rsp, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc); // vand | |
| 287 | #endif | |
| 288 | #if (DRC_VXOR) | |
| 289 | static int generate_vxor(rsp_state *rsp, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc); // vand | |
| 290 | #endif | |
| 291 | #if (DRC_VNXOR) | |
| 292 | static int generate_vnxor(rsp_state *rsp, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc); // vand | |
| 293 | #endif | |
| 294 | 193 | static int generate_lwc2(rsp_state *rsp, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc); |
| 295 | 194 | static int generate_swc2(rsp_state *rsp, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc); |
| 296 | 195 | static void generate_update_cycles(rsp_state *rsp, drcuml_block *block, compiler_state *compiler, drcuml_ptype ptype, UINT64 pvalue, int allow_exception); |
| r9854 | r9855 | |
| 314 | 213 | #define VS2REG ((op >> 16) & 0x1f) |
| 315 | 214 | #define EL ((op >> 21) & 0xf) |
| 316 | 215 | |
| 317 | #define R_VREG_B(reg, offset) rsp->v[(reg)].b[15 - (offset)] | |
| 318 | #define R_VREG_S(reg, offset) (INT16)rsp->v[(reg)].s[7 - (offset)] | |
| 319 | #define R_VREG_S_X(reg, offset) (INT16)rsp->v[reg].s[offset] | |
| 320 | #define R_VREG_L(reg, offset) rsp->v[(reg)].l[3 - (offset)] | |
| 321 | #define R_VREG_D(reg, offset) rsp->v[(reg)].d[1 - (offset)] | |
| 216 | #define VREG_B(reg, offset) rsp->v[(reg)].b[BYTE4_XOR_BE(offset)] | |
| 217 | #define VREG_S(reg, offset) rsp->v[(reg)].s[(offset)^1] | |
| 322 | 218 | |
| 323 | #define W_VREG_B(reg, offset, val) (rsp->v[(reg)].b[15 - (offset)] = val) | |
| 324 | #define W_VREG_S(reg, offset, val) (rsp->v[(reg)].s[7 - (offset)] = val) | |
| 325 | #define W_VREG_S_X(reg, offset, val) (rsp->v[reg].s[offset] = val) | |
| 326 | #define W_VREG_L(reg, offset, val) (rsp->v[(reg)].l[3 - (offset)] = val) | |
| 327 | #define W_VREG_D(reg, offset, val) (rsp->v[(reg)].d[1 - (offset)] = val) | |
| 328 | ||
| 329 | #define VEC_EL_1(x,z) (vector_elements_1[(x)][(z)]) | |
| 330 | 219 | #define VEC_EL_2(x,z) (vector_elements_2[(x)][(z)]) |
| 331 | 220 | |
| 332 | #define ACCUM(x) (rsp->accum[x]) | |
| 221 | #define ACCUM(x) rsp->accum[x].q | |
| 222 | #define ACCUM_H(x) rsp->accum[((x))].w[3] | |
| 223 | #define ACCUM_M(x) rsp->accum[((x))].w[2] | |
| 224 | #define ACCUM_L(x) rsp->accum[((x))].w[1] | |
| 333 | 225 | |
| 334 | #define W_ACCUM_H(x, y) (ACCUM(x).h.high = (INT16)((INT64)(y))) | |
| 335 | #define W_ACCUM_M(x, y) (ACCUM(x).h.mid = (INT16)((INT64)(y))) | |
| 336 | #define W_ACCUM_L(x, y) (ACCUM(x).h.low = (INT16)((INT64)(y))) | |
| 337 | ||
| 338 | 226 | #define CARRY_FLAG(x) ((rsp->flag[0] & (1 << (x))) ? 1 : 0) |
| 339 | 227 | #define CLEAR_CARRY_FLAGS() { rsp->flag[0] &= ~0xff; } |
| 340 | 228 | #define SET_CARRY_FLAG(x) { rsp->flag[0] |= (1 << (x)); } |
| r9854 | r9855 | |
| 421 | 309 | INLINE UINT8 READ8(rsp_state *rsp, UINT32 address) |
| 422 | 310 | { |
| 423 | 311 | UINT8* dmem = (UINT8*)rsp->impstate->dmem; |
| 424 | return dmem[BYTE4_XOR_BE(address & 0x00000fff)]; | |
| 312 | UINT8 ret = dmem[BYTE4_XOR_BE(address & 0x00000fff)]; | |
| 313 | //printf("%04xr%02x\n", address & 0x00001fff, ret); | |
| 314 | return ret; | |
| 425 | 315 | } |
| 426 | 316 | |
| 427 | 317 | /* Legacy. Needed for vector cfuncs. */ |
| r9854 | r9855 | |
| 432 | 322 | address &= 0x00000fff; |
| 433 | 323 | ret = (UINT16)dmem[BYTE4_XOR_BE(address+0)] << 8; |
| 434 | 324 | ret |= (UINT16)dmem[BYTE4_XOR_BE(address+1)]; |
| 325 | //printf("%04xr%04x\n", address & 0x00001fff, ret); | |
| 435 | 326 | return ret; |
| 436 | 327 | } |
| 437 | 328 | |
| r9854 | r9855 | |
| 445 | 336 | ret |= (UINT32)dmem[BYTE4_XOR_BE(address+1)] << 16; |
| 446 | 337 | ret |= (UINT32)dmem[BYTE4_XOR_BE(address+2)] << 8; |
| 447 | 338 | ret |= (UINT32)dmem[BYTE4_XOR_BE(address+3)]; |
| 339 | //printf("%04xr%08x\n", address & 0x00001fff, ret); | |
| 448 | 340 | return ret; |
| 449 | 341 | } |
| 450 | 342 | |
| 451 | 343 | /* Legacy. Needed for vector cfuncs. */ |
| 452 | INLINE UINT64 READ64(rsp_state *rsp, UINT32 address) | |
| 453 | { | |
| 454 | UINT8* dmem = (UINT8*)rsp->impstate->dmem; | |
| 455 | UINT64 ret = 0; | |
| 456 | address &= 0x00000fff; | |
| 457 | ret = (UINT64)dmem[BYTE4_XOR_BE(address+0)] << 56; | |
| 458 | ret |= (UINT64)dmem[BYTE4_XOR_BE(address+1)] << 48; | |
| 459 | ret |= (UINT64)dmem[BYTE4_XOR_BE(address+2)] << 40; | |
| 460 | ret |= (UINT64)dmem[BYTE4_XOR_BE(address+3)] << 32; | |
| 461 | ret |= (UINT64)dmem[BYTE4_XOR_BE(address+4)] << 24; | |
| 462 | ret |= (UINT64)dmem[BYTE4_XOR_BE(address+5)] << 16; | |
| 463 | ret |= (UINT64)dmem[BYTE4_XOR_BE(address+6)] << 8; | |
| 464 | ret |= (UINT64)dmem[BYTE4_XOR_BE(address+7)]; | |
| 465 | return ret; | |
| 466 | } | |
| 467 | ||
| 468 | /* Legacy. Needed for vector cfuncs. */ | |
| 469 | 344 | INLINE void WRITE8(rsp_state *rsp, UINT32 address, UINT8 data) |
| 470 | 345 | { |
| 471 | 346 | UINT8* dmem = (UINT8*)rsp->impstate->dmem; |
| 472 | 347 | address &= 0x00000fff; |
| 348 | //printf("%04x:%02x\n", address & 0x00001fff, data); | |
| 473 | 349 | dmem[BYTE4_XOR_BE(address)] = data; |
| 474 | 350 | } |
| 475 | 351 | |
| r9854 | r9855 | |
| 478 | 354 | { |
| 479 | 355 | UINT8* dmem = (UINT8*)rsp->impstate->dmem; |
| 480 | 356 | address &= 0x00000fff; |
| 357 | //printf("%04x:%04x\n", address & 0x00001fff, data); | |
| 481 | 358 | dmem[BYTE4_XOR_BE(address+0)] = (UINT8)(data >> 8); |
| 482 | 359 | dmem[BYTE4_XOR_BE(address+1)] = (UINT8)(data >> 0); |
| 483 | 360 | } |
| r9854 | r9855 | |
| 487 | 364 | { |
| 488 | 365 | UINT8* dmem = (UINT8*)rsp->impstate->dmem; |
| 489 | 366 | address &= 0x00000fff; |
| 367 | //printf("%04x:%08x\n", address & 0x00001fff, data); | |
| 490 | 368 | dmem[BYTE4_XOR_BE(address+0)] = (UINT8)(data >> 24); |
| 491 | 369 | dmem[BYTE4_XOR_BE(address+1)] = (UINT8)(data >> 16); |
| 492 | 370 | dmem[BYTE4_XOR_BE(address+2)] = (UINT8)(data >> 8); |
| 493 | 371 | dmem[BYTE4_XOR_BE(address+3)] = (UINT8)(data >> 0); |
| 494 | 372 | } |
| 495 | 373 | |
| 496 | /* Legacy. Needed for vector cfuncs. */ | |
| 497 | INLINE void WRITE64(rsp_state *rsp, UINT32 address, UINT64 data) | |
| 498 | { | |
| 499 | UINT8* dmem = (UINT8*)rsp->impstate->dmem; | |
| 500 | address &= 0x00000fff; | |
| 501 | dmem[BYTE4_XOR_BE(address+0)] = (UINT8)(data >> 56); | |
| 502 | dmem[BYTE4_XOR_BE(address+1)] = (UINT8)(data >> 48); | |
| 503 | dmem[BYTE4_XOR_BE(address+2)] = (UINT8)(data >> 40); | |
| 504 | dmem[BYTE4_XOR_BE(address+3)] = (UINT8)(data >> 32); | |
| 505 | dmem[BYTE4_XOR_BE(address+4)] = (UINT8)(data >> 24); | |
| 506 | dmem[BYTE4_XOR_BE(address+5)] = (UINT8)(data >> 16); | |
| 507 | dmem[BYTE4_XOR_BE(address+6)] = (UINT8)(data >> 8); | |
| 508 | dmem[BYTE4_XOR_BE(address+7)] = (UINT8)(data >> 0); | |
| 509 | } | |
| 510 | ||
| 511 | 374 | /*****************************************************************************/ |
| 512 | 375 | |
| 513 | 376 | /*------------------------------------------------- |
| r9854 | r9855 | |
| 552 | 415 | static void cfunc_printf_debug(void *param) |
| 553 | 416 | { |
| 554 | 417 | rsp_state *rsp = (rsp_state *)param; |
| 555 | printf(rsp->impstate->format, rsp->impstate->arg0, rsp->impstate->arg1); | |
| 556 | logerror(rsp->impstate->format, rsp->impstate->arg0, rsp->impstate->arg1); | |
| 418 | switch(rsp->impstate->arg2) | |
| 419 | { | |
| 420 | case 0: // WRITE8 | |
| 421 | printf("%04x:%02x\n", rsp->impstate->arg0 & 0x0fff, (UINT8)rsp->impstate->arg1); | |
| 422 | break; | |
| 423 | case 1: // WRITE16 | |
| 424 | printf("%04x:%04x\n", rsp->impstate->arg0 & 0x0fff, (UINT16)rsp->impstate->arg1); | |
| 425 | break; | |
| 426 | case 2: // WRITE32 | |
| 427 | printf("%04x:%08x\n", rsp->impstate->arg0 & 0x0fff, rsp->impstate->arg1); | |
| 428 | break; | |
| 429 | case 3: // READ8 | |
| 430 | printf("%04xr%02x\n", rsp->impstate->arg0 & 0x0fff, (UINT8)rsp->impstate->arg1); | |
| 431 | break; | |
| 432 | case 4: // READ16 | |
| 433 | printf("%04xr%04x\n", rsp->impstate->arg0 & 0x0fff, (UINT16)rsp->impstate->arg1); | |
| 434 | break; | |
| 435 | case 5: // READ32 | |
| 436 | printf("%04xr%08x\n", rsp->impstate->arg0 & 0x0fff, rsp->impstate->arg1); | |
| 437 | break; | |
| 438 | default: // ??? | |
| 439 | printf("%08x %08x\n", rsp->impstate->arg0 & 0x0fff, rsp->impstate->arg1); | |
| 440 | break; | |
| 441 | } | |
| 557 | 442 | } |
| 558 | 443 | #endif |
| 559 | 444 | |
| 560 | ||
| 561 | /*------------------------------------------------- | |
| 562 | cfunc_printf_debug64 - generic printf for | |
| 563 | debugging 64-bit values | |
| 564 | -------------------------------------------------*/ | |
| 565 | ||
| 566 | #ifdef UNUSED_FUNCTION | |
| 567 | static void cfunc_printf_debug64(void *param) | |
| 568 | { | |
| 569 | rsp_state *rsp = (rsp_state *)param; | |
| 570 | printf(rsp->impstate->format, (UINT32)(rsp->impstate->arg64 >> 32), (UINT32)(rsp->impstate->arg64 & 0x00000000ffffffff)); | |
| 571 | logerror(rsp->impstate->format, (UINT32)(rsp->impstate->arg64 >> 32), (UINT32)(rsp->impstate->arg64 & 0x00000000ffffffff)); | |
| 572 | } | |
| 573 | #endif | |
| 574 | ||
| 575 | 445 | static void cfunc_get_cop0_reg(void *param) |
| 576 | 446 | { |
| 577 | 447 | rsp_state *rsp = (rsp_state*)param; |
| r9854 | r9855 | |
| 722 | 592 | // ...except for the accumulators. |
| 723 | 593 | for(accumIdx = 0; accumIdx < 8; accumIdx++ ) |
| 724 | 594 | { |
| 725 | rsp->accum[accumIdx]. | |
| 595 | rsp->accum[accumIdx].q = 0; | |
| 726 | 596 | } |
| 727 | 597 | |
| 728 | 598 | rsp->sr = RSP_STATUS_HALT; |
| r9854 | r9855 | |
| 742 | 612 | drccache *cache; |
| 743 | 613 | UINT32 flags = 0; |
| 744 | 614 | int regnum; |
| 745 | int elnum; | |
| 615 | //int elnum; | |
| 746 | 616 | |
| 747 | 617 | /* allocate enough space for the cache and the core */ |
| 748 | 618 | cache = (drccache *)drccache_alloc(CACHE_SIZE + sizeof(*rsp)); |
| r9854 | r9855 | |
| 792 | 662 | } |
| 793 | 663 | drcuml_symbol_add(rsp->impstate->drcuml, &rsp->impstate->arg0, sizeof(rsp->impstate->arg0), "arg0"); |
| 794 | 664 | drcuml_symbol_add(rsp->impstate->drcuml, &rsp->impstate->arg1, sizeof(rsp->impstate->arg1), "arg1"); |
| 795 | drcuml_symbol_add(rsp->impstate->drcuml, &rsp->impstate->arg64, sizeof(rsp->impstate->arg1), "arg64"); | |
| 665 | drcuml_symbol_add(rsp->impstate->drcuml, &rsp->impstate->arg2, sizeof(rsp->impstate->arg2), "arg2"); | |
| 666 | drcuml_symbol_add(rsp->impstate->drcuml, &rsp->impstate->arg3, sizeof(rsp->impstate->arg3), "arg3"); | |
| 796 | 667 | drcuml_symbol_add(rsp->impstate->drcuml, &rsp->impstate->numcycles, sizeof(rsp->impstate->numcycles), "numcycles"); |
| 797 | 668 | |
| 798 | 669 | /* initialize the front-end helper */ |
| r9854 | r9855 | |
| 808 | 679 | rsp->impstate->regmap[regnum].type = (regnum == 0) ? DRCUML_PTYPE_IMMEDIATE : DRCUML_PTYPE_MEMORY; |
| 809 | 680 | rsp->impstate->regmap[regnum].value = (regnum == 0) ? 0 : (FPTR)&rsp->r[regnum]; |
| 810 | 681 | } |
| 811 | for (regnum = 0; regnum < 32; regnum++) | |
| 812 | { | |
| 813 | for(elnum = 0; elnum < 16; elnum++) | |
| 814 | { | |
| 815 | rsp->impstate->regmap[16*regnum+elnum+34].type = DRCUML_PTYPE_MEMORY; | |
| 816 | rsp->impstate->regmap[16*regnum+elnum+34].value = (FPTR)&rsp->v[regnum].b[15-elnum]; | |
| 817 | } | |
| 818 | for(elnum = 0; elnum < 8; elnum++) | |
| 819 | { | |
| 820 | rsp->impstate->regmap[8*regnum+elnum+546].type = DRCUML_PTYPE_MEMORY; | |
| 821 | rsp->impstate->regmap[8*regnum+elnum+546].value = (FPTR)&rsp->v[regnum].s[7-elnum]; | |
| 822 | } | |
| 823 | for(elnum = 0; elnum < 4; elnum++) | |
| 824 | { | |
| 825 | rsp->impstate->regmap[4*regnum+elnum+802].type = DRCUML_PTYPE_MEMORY; | |
| 826 | rsp->impstate->regmap[4*regnum+elnum+802].value = (FPTR)&rsp->v[regnum].l[3-elnum]; | |
| 827 | } | |
| 828 | } | |
| 829 | for (regnum = 0; regnum < 4; regnum++) | |
| 830 | { | |
| 831 | rsp->impstate->regmap[930+regnum].type = DRCUML_PTYPE_MEMORY; | |
| 832 | rsp->impstate->regmap[930+regnum].value = (FPTR)&rsp->flag[regnum]; | |
| 833 | } | |
| 834 | for (regnum = 0; regnum < 8; regnum++) | |
| 835 | { | |
| 836 | rsp->impstate->regmap[934+regnum].type = DRCUML_PTYPE_MEMORY; | |
| 837 | rsp->impstate->regmap[934+regnum].value = (FPTR)&rsp->accum[regnum].l; | |
| 838 | rsp->impstate->regmap[942+regnum].type = DRCUML_PTYPE_MEMORY; | |
| 839 | rsp->impstate->regmap[942+regnum].value = (FPTR)&rsp->accum[regnum].h.high; | |
| 840 | rsp->impstate->regmap[950+regnum].type = DRCUML_PTYPE_MEMORY; | |
| 841 | rsp->impstate->regmap[950+regnum].value = (FPTR)&rsp->accum[regnum].h.mid; | |
| 842 | rsp->impstate->regmap[958+regnum].type = DRCUML_PTYPE_MEMORY; | |
| 843 | rsp->impstate->regmap[958+regnum].value = (FPTR)&rsp->accum[regnum].h.low; | |
| 844 | rsp->impstate->regmap[966+regnum].type = DRCUML_PTYPE_MEMORY; | |
| 845 | rsp->impstate->regmap[966+regnum].value = (FPTR)&rsp->accum[regnum].h.z; | |
| 846 | rsp->impstate->regmap[974+regnum].type = DRCUML_PTYPE_MEMORY; | |
| 847 | rsp->impstate->regmap[974+regnum].value = (FPTR)&rsp->accum[regnum].w.mh; | |
| 848 | rsp->impstate->regmap[982+regnum].type = DRCUML_PTYPE_MEMORY; | |
| 849 | rsp->impstate->regmap[982+regnum].value = (FPTR)&rsp->accum[regnum].w.zl; | |
| 850 | rsp->impstate->regmap[990+regnum].type = DRCUML_PTYPE_MEMORY; | |
| 851 | rsp->impstate->regmap[990+regnum].value = (FPTR)&rsp->impstate->vres[regnum]; | |
| 852 | } | |
| 853 | 682 | |
| 854 | 683 | /* mark the cache dirty so it is updated on next execute */ |
| 855 | 684 | rsp->impstate->cache_dirty = TRUE; |
| r9854 | r9855 | |
| 872 | 701 | rsp->nextpc = ~0; |
| 873 | 702 | } |
| 874 | 703 | |
| 704 | INLINE UINT32 IREAD32(rsp_state *rsp, UINT32 address) | |
| 705 | { | |
| 706 | UINT8* imem = (UINT8*)rsp->impstate->imem; | |
| 707 | UINT32 ret = 0; | |
| 708 | address &= 0x00000fff; | |
| 709 | ret = (UINT32)imem[address+0] << 24; | |
| 710 | ret |= (UINT32)imem[address+1] << 16; | |
| 711 | ret |= (UINT32)imem[address+2] << 8; | |
| 712 | ret |= (UINT32)imem[address+3]; | |
| 713 | //printf("%04xr%08x\n", address & 0x00001fff, ret); | |
| 714 | return ret; | |
| 715 | } | |
| 875 | 716 | |
| 876 | 717 | static void cfunc_rsp_lbv(void *param) |
| 877 | 718 | { |
| r9854 | r9855 | |
| 894 | 735 | // Load 1 byte to vector byte index |
| 895 | 736 | |
| 896 | 737 | ea = (base) ? rsp->r[base] + offset : offset; |
| 897 | | |
| 738 | | |
| 898 | 739 | } |
| 899 | 740 | |
| 900 | #if !(DRC_LSV) | |
| 901 | 741 | static void cfunc_rsp_lsv(void *param) |
| 902 | 742 | { |
| 903 | 743 | rsp_state *rsp = (rsp_state*)param; |
| r9854 | r9855 | |
| 920 | 760 | |
| 921 | 761 | ea = (base) ? rsp->r[base] + (offset * 2) : (offset * 2); |
| 922 | 762 | |
| 923 | W_VREG_S(dest, index >> 1, READ16(rsp, ea)); | |
| 763 | int end = index + 2; | |
| 764 | ||
| 765 | for (int i = index; i < end; i++) | |
| 766 | { | |
| 767 | VREG_B(dest, i) = READ8(rsp, ea); | |
| 768 | ea++; | |
| 769 | } | |
| 924 | 770 | } |
| 925 | #endif | |
| 926 | 771 | |
| 927 | #if !(DRC_LLV) | |
| 928 | 772 | static void cfunc_rsp_llv(void *param) |
| 929 | 773 | { |
| 930 | 774 | rsp_state *rsp = (rsp_state*)param; |
| r9854 | r9855 | |
| 947 | 791 | |
| 948 | 792 | ea = (base) ? rsp->r[base] + (offset * 4) : (offset * 4); |
| 949 | 793 | |
| 950 | W_VREG_L(dest, index >> 2, READ32(rsp, ea)); | |
| 794 | int end = index + 4; | |
| 795 | ||
| 796 | for (int i = index; i < end; i++) | |
| 797 | { | |
| 798 | VREG_B(dest, i) = READ8(rsp, ea); | |
| 799 | ea++; | |
| 800 | } | |
| 951 | 801 | } |
| 952 | #endif | |
| 953 | 802 | |
| 954 | #if !(DRC_LDV) | |
| 955 | 803 | static void cfunc_rsp_ldv(void *param) |
| 956 | 804 | { |
| 957 | 805 | rsp_state *rsp = (rsp_state*)param; |
| r9854 | r9855 | |
| 974 | 822 | |
| 975 | 823 | ea = (base) ? rsp->r[base] + (offset * 8) : (offset * 8); |
| 976 | 824 | |
| 977 | index >>= 2; | |
| 978 | W_VREG_L(dest, index, READ32(rsp, ea)); | |
| 979 | W_VREG_L(dest, index + 1, READ32(rsp, ea + 4)); | |
| 825 | int end = index + 8; | |
| 826 | ||
| 827 | for (int i = index; i < end; i++) | |
| 828 | { | |
| 829 | VREG_B(dest, i) = READ8(rsp, ea); | |
| 830 | ea++; | |
| 831 | } | |
| 980 | 832 | } |
| 981 | #endif | |
| 982 | 833 | |
| 983 | #if !(DRC_LQV) | |
| 984 | 834 | static void cfunc_rsp_lqv(void *param) |
| 985 | 835 | { |
| 986 | 836 | rsp_state *rsp = (rsp_state*)param; |
| r9854 | r9855 | |
| 1007 | 857 | |
| 1008 | 858 | end = index + (16 - (ea & 0xf)); |
| 1009 | 859 | if (end > 16) end = 16; |
| 1010 | ||
| 1011 | 860 | for (i=index; i < end; i++) |
| 1012 | 861 | { |
| 1013 | | |
| 862 | | |
| 1014 | 863 | ea++; |
| 1015 | 864 | } |
| 1016 | 865 | } |
| 1017 | #endif | |
| 1018 | 866 | |
| 1019 | 867 | static void cfunc_rsp_lrv(void *param) |
| 1020 | 868 | { |
| r9854 | r9855 | |
| 1046 | 894 | |
| 1047 | 895 | for (i=index; i < end; i++) |
| 1048 | 896 | { |
| 1049 | | |
| 897 | | |
| 1050 | 898 | ea++; |
| 1051 | 899 | } |
| 1052 | 900 | } |
| 1053 | 901 | |
| 1054 | #if !(DRC_LPV) | |
| 1055 | 902 | static void cfunc_rsp_lpv(void *param) |
| 1056 | 903 | { |
| 1057 | 904 | rsp_state *rsp = (rsp_state*)param; |
| r9854 | r9855 | |
| 1077 | 924 | |
| 1078 | 925 | for (i=0; i < 8; i++) |
| 1079 | 926 | { |
| 1080 | | |
| 927 | | |
| 1081 | 928 | } |
| 1082 | 929 | } |
| 1083 | #endif | |
| 1084 | 930 | |
| 1085 | #if !(DRC_LUV) | |
| 1086 | 931 | static void cfunc_rsp_luv(void *param) |
| 1087 | 932 | { |
| 1088 | 933 | rsp_state *rsp = (rsp_state*)param; |
| r9854 | r9855 | |
| 1108 | 953 | |
| 1109 | 954 | for (i=0; i < 8; i++) |
| 1110 | 955 | { |
| 1111 | | |
| 956 | | |
| 1112 | 957 | } |
| 1113 | 958 | } |
| 1114 | #endif | |
| 1115 | 959 | |
| 1116 | 960 | static void cfunc_rsp_lhv(void *param) |
| 1117 | 961 | { |
| r9854 | r9855 | |
| 1138 | 982 | |
| 1139 | 983 | for (i=0; i < 8; i++) |
| 1140 | 984 | { |
| 1141 | | |
| 985 | | |
| 1142 | 986 | } |
| 1143 | 987 | } |
| 1144 | 988 | |
| r9854 | r9855 | |
| 1164 | 1008 | // |
| 1165 | 1009 | // Loads a byte as the bits 14-7 of upper or lower quad, with 4-byte stride |
| 1166 | 1010 | |
| 1167 | fatalerror("RSP: LFV\n"); | |
| 1168 | 1011 | |
| 1169 | if (index & 0x7) fatalerror("RSP: LFV: index = %d at %08X\n", index, rsp->ppc); | |
| 1170 | ||
| 1171 | 1012 | ea = (base) ? rsp->r[base] + (offset * 16) : (offset * 16); |
| 1172 | 1013 | |
| 1173 | 1014 | // not sure what happens if 16-byte boundary is crossed... |
| 1174 | if ((ea & 0xf) > 0) fatalerror("RSP: LFV: 16-byte boundary crossing at %08X, recheck this!\n", rsp->ppc); | |
| 1175 | 1015 | |
| 1176 | 1016 | end = (index >> 1) + 4; |
| 1177 | 1017 | |
| 1178 | 1018 | for (i=index >> 1; i < end; i++) |
| 1179 | 1019 | { |
| 1180 | | |
| 1020 | | |
| 1181 | 1021 | ea += 4; |
| 1182 | 1022 | } |
| 1183 | 1023 | } |
| r9854 | r9855 | |
| 1207 | 1047 | |
| 1208 | 1048 | ea = (base) ? rsp->r[base] + (offset * 16) : (offset * 16); |
| 1209 | 1049 | |
| 1210 | // not sure what happens if 16-byte boundary is crossed... | |
| 1211 | if ((ea & 0xf) > 0) fatalerror("RSP: LWV: 16-byte boundary crossing at %08X, recheck this!\n", rsp->ppc); | |
| 1212 | ||
| 1213 | 1050 | end = (16 - index) + 16; |
| 1214 | 1051 | |
| 1215 | 1052 | for (i=(16 - index); i < end; i++) |
| 1216 | 1053 | { |
| 1217 | | |
| 1054 | | |
| 1218 | 1055 | ea += 4; |
| 1219 | 1056 | } |
| 1220 | 1057 | } |
| r9854 | r9855 | |
| 1243 | 1080 | int vs = dest; |
| 1244 | 1081 | int ve = dest + 8; |
| 1245 | 1082 | if (ve > 32) |
| 1246 | ve = 32; | |
| 1247 | ||
| 1248 | if (offset & 0x40) | |
| 1249 | 1083 | { |
| 1250 | | |
| 1084 | v | |
| 1251 | 1085 | } |
| 1252 | 1086 | |
| 1253 | 1087 | element = 7 - (index >> 1); |
| 1254 | 1088 | |
| 1255 | if (index & 1) fatalerror("RSP: LTV: index = %d\n", index); | |
| 1256 | ||
| 1257 | 1089 | ea = (base) ? rsp->r[base] + (offset * 16) : (offset * 16); |
| 1258 | 1090 | |
| 1259 | 1091 | ea = ((ea + 8) & ~0xf) + (index & 1); |
| 1260 | for (i=vs; i < ve; i++) | |
| 1092 | for (i = vs; i < ve; i++) | |
| 1261 | 1093 | { |
| 1262 | element = ((8 - (index >> 1) + (i-vs)) << 1); | |
| 1263 | W_VREG_B(i, (element & 0xf), READ8(rsp, ea)); | |
| 1264 | W_VREG_B(i, ((element+1) & 0xf), READ8(rsp, ea+1)); | |
| 1094 | element = ((8 - (index >> 1) + (i - vs)) << 1); | |
| 1095 | VREG_B(i, (element & 0xf)) = READ8(rsp, ea); | |
| 1096 | VREG_B(i, ((element + 1) & 0xf)) = READ8(rsp, ea + 1); | |
| 1265 | 1097 | |
| 1266 | 1098 | ea += 2; |
| 1267 | 1099 | } |
| r9854 | r9855 | |
| 1289 | 1121 | UML_CALLC(block, cfunc_rsp_lbv, rsp); |
| 1290 | 1122 | return TRUE; |
| 1291 | 1123 | case 0x01: /* LSV */ |
| 1292 | #if (DRC_LSV) | |
| 1293 | offset <<= 1; | |
| 1294 | index >>= 1; | |
| 1295 | ||
| 1296 | index = 7 - index; | |
| 1297 | UML_ADD(block, IREG(0), R32(RSREG), IMM(offset)); // add i0,<rsreg>,offset | |
| 1298 | UML_CALLH(block, rsp->impstate->read16); // callh read32 | |
| 1299 | UML_STORE(block, &rsp->v[dest].s[index], IMM(0), IREG(0), WORD); // store v[dest][index],i0,word | |
| 1300 | return TRUE; | |
| 1301 | #else | |
| 1302 | 1124 | UML_MOV(block, MEM(&rsp->impstate->arg0), IMM(desc->opptr.l[0])); // mov [arg0],desc->opptr.l |
| 1303 | 1125 | UML_CALLC(block, cfunc_rsp_lsv, rsp); |
| 1304 | 1126 | return TRUE; |
| 1305 | #endif | |
| 1306 | 1127 | case 0x02: /* LLV */ |
| 1307 | #if (DRC_LLV) | |
| 1308 | offset <<= 2; | |
| 1309 | index >>= 2; | |
| 1310 | ||
| 1311 | UML_ADD(block, IREG(0), R32(RSREG), IMM(offset)); // add i0,<rsreg>,offset | |
| 1312 | UML_CALLH(block, rsp->impstate->read32); // callh read32 | |
| 1313 | UML_MOV(block, VLX(dest, index), IREG(0)); // mov v[dest][index].i0 | |
| 1314 | return TRUE; | |
| 1315 | #else | |
| 1316 | 1128 | UML_MOV(block, MEM(&rsp->impstate->arg0), IMM(desc->opptr.l[0])); // mov [arg0],desc->opptr.l |
| 1317 | 1129 | UML_CALLC(block, cfunc_rsp_llv, rsp); |
| 1318 | 1130 | return TRUE; |
| 1319 | #endif | |
| 1320 | 1131 | case 0x03: /* LDV */ |
| 1321 | #if (DRC_LDV) | |
| 1322 | offset <<= 3; | |
| 1323 | index >>= 2; | |
| 1324 | ||
| 1325 | UML_ADD(block, IREG(0), R32(RSREG), IMM(offset)); // add i0,<rsreg>,offset | |
| 1326 | UML_CALLH(block, rsp->impstate->read32); // callh read32 | |
| 1327 | UML_MOV(block, VLX(dest, index), IREG(0)); // mov v[dest][index],i0 | |
| 1328 | ||
| 1329 | UML_ADD(block, IREG(0), R32(RSREG), IMM(offset)); // add i0,<rsreg>,offset | |
| 1330 | UML_ADD(block, IREG(0), IREG(0), IMM(4)); // add i0,i0,4 | |
| 1331 | UML_CALLH(block, rsp->impstate->read32); // callh read32 | |
| 1332 | UML_MOV(block, VLX(dest, index+1), IREG(0)); // mov v[dest][index+1],i0 | |
| 1333 | return TRUE; | |
| 1334 | #else | |
| 1335 | 1132 | UML_MOV(block, MEM(&rsp->impstate->arg0), IMM(desc->opptr.l[0])); // mov [arg0],desc->opptr.l |
| 1336 | 1133 | UML_CALLC(block, cfunc_rsp_ldv, rsp); |
| 1337 | 1134 | return TRUE; |
| 1338 | #endif | |
| 1339 | 1135 | case 0x04: /* LQV */ |
| 1340 | #if (DRC_LQV) | |
| 1341 | offset <<= 4; | |
| 1342 | ||
| 1343 | UML_ADD(block, MEM(&rsp->impstate->arg0), R32(RSREG), IMM(offset)); // mov arg0,<rsreg>,offset | |
| 1344 | UML_MOV(block, IREG(3), IMM(index)); // mov i3,index | |
| 1345 | UML_MOV(block, IREG(2), MEM(&rsp->impstate->arg0)); // mov i2,arg0 | |
| 1346 | UML_AND(block, IREG(2), IREG(2), IMM(0x0000000f)); // and i2,i2,0x0000000f | |
| 1347 | UML_SUB(block, IREG(2), IMM(16), IREG(2)); // sub i2,16,i2 | |
| 1348 | UML_ADD(block, IREG(2), IREG(2), IREG(3)); // add i2,i2,i3 | |
| 1349 | UML_CMP(block, IREG(2), IMM(16)); // cmp i2,16 | |
| 1350 | UML_TEST(block, IREG(2), IMM(0xfffffff0)); // test i2,0xfffffff0 | |
| 1351 | UML_MOVc(block, IF_NZ, IREG(2), IMM(16)); // mov NZ,i2,16 | |
| 1352 | ||
| 1353 | UML_LABEL(block, loopdest = compiler->labelnum++); // loopdest: | |
| 1354 | UML_MOV(block, IREG(0), MEM(&rsp->impstate->arg0)); // mov i0,arg0 | |
| 1355 | UML_XOR(block, IREG(0), IREG(0), IMM(BYTE4_XOR_BE(0))); // xor i0,i0,bytexor | |
| 1356 | UML_LOAD(block, IREG(0), rsp->impstate->dmem, IREG(0), BYTE); // load i0,dmem,i0,byte | |
| 1357 | UML_SUB(block, IREG(1), IMM(15), IREG(3)); // sub i1,15,i3 | |
| 1358 | UML_STORE(block, &rsp->v[dest].b[0], IREG(1), IREG(0), BYTE); // store v[dest][0]+i1,i0 | |
| 1359 | ||
| 1360 | UML_ADD(block, MEM(&rsp->impstate->arg0), MEM(&rsp->impstate->arg0), IMM(1)); | |
| 1361 | UML_AND(block, MEM(&rsp->impstate->arg0), MEM(&rsp->impstate->arg0), IMM(0x00000fff)); | |
| 1362 | UML_ADD(block, IREG(3), IREG(3), IMM(1)); // add i3,i3,1 | |
| 1363 | UML_CMP(block, IREG(3), IREG(2)); // cmp i3,i2 | |
| 1364 | UML_JMPc(block, IF_L, loopdest); // jmp L,loopdest | |
| 1365 | return TRUE; | |
| 1366 | ||
| 1367 | #else | |
| 1368 | 1136 | UML_MOV(block, MEM(&rsp->impstate->arg0), IMM(desc->opptr.l[0])); // mov [arg0],desc->opptr.l |
| 1369 | 1137 | UML_CALLC(block, cfunc_rsp_lqv, rsp); |
| 1370 | 1138 | return TRUE; |
| 1371 | #endif | |
| 1372 | 1139 | case 0x05: /* LRV */ |
| 1373 | 1140 | UML_MOV(block, MEM(&rsp->impstate->arg0), IMM(desc->opptr.l[0])); // mov [arg0],desc->opptr.l |
| 1374 | 1141 | UML_CALLC(block, cfunc_rsp_lrv, rsp); |
| 1375 | 1142 | return TRUE; |
| 1376 | 1143 | case 0x06: /* LPV */ |
| 1377 | #if (DRC_LPV) | |
| 1378 | offset <<= 3; | |
| 1379 | ||
| 1380 | UML_ADD(block, IREG(2), R32(RSREG), IMM(offset)); // add i2,<rsreg>,offset | |
| 1381 | UML_SUB(block, IREG(3), IMM(16), IMM(index)); // sub i3,16,index | |
| 1382 | ||
| 1383 | UML_AND(block, IREG(1), IREG(3), IMM(0x0000000f)); // and i1,i1,0x0000000f | |
| 1384 | UML_ADD(block, IREG(0), IREG(1), IREG(2)); // add i0,i1,i2 | |
| 1385 | UML_AND(block, IREG(0), IREG(0), IMM(0x00000fff)); // and i0,i0,0x00000fff | |
| 1386 | UML_XOR(block, IREG(0), IREG(0), IMM(BYTE4_XOR_BE(0))); // xor i0,i0,bytexor | |
| 1387 | UML_LOAD(block, IREG(0), rsp->impstate->dmem, IREG(0), BYTE); // load i0,dmem,i0,byte | |
| 1388 | UML_SHL(block, IREG(0), IREG(0), IMM(8)); // shl i0,i0,8 | |
| 1389 | UML_STORE(block, &rsp->v[dest].s[7], IMM(0), IREG(0), WORD); // store v[dest][7],i0,word | |
| 1390 | ||
| 1391 | UML_ADD(block, IREG(1), IREG(3), IMM(1)); // add i1,i3,1 | |
| 1392 | UML_AND(block, IREG(1), IREG(1), IMM(0x0000000f)); // and i1,i1,0x0000000f | |
| 1393 | UML_ADD(block, IREG(0), IREG(1), IREG(2)); // add i0,i1,i2 | |
| 1394 | UML_AND(block, IREG(0), IREG(0), IMM(0x00000fff)); // and i0,i0,0x00000fff | |
| 1395 | UML_XOR(block, IREG(0), IREG(0), IMM(BYTE4_XOR_BE(0))); // xor i0,i0,bytexor | |
| 1396 | UML_LOAD(block, IREG(0), rsp->impstate->dmem, IREG(0), BYTE); // load i0,dmem,i0,byte | |
| 1397 | UML_SHL(block, IREG(0), IREG(0), IMM(8)); // shl i0,i0,8 | |
| 1398 | UML_STORE(block, &rsp->v[dest].s[6], IMM(0), IREG(0), WORD); // store v[dest][6],i0,word | |
| 1399 | ||
| 1400 | UML_ADD(block, IREG(1), IREG(3), IMM(2)); // add i1,i3,2 | |
| 1401 | UML_AND(block, IREG(1), IREG(1), IMM(0x0000000f)); // and i1,i1,0x0000000f | |
| 1402 | UML_ADD(block, IREG(0), IREG(1), IREG(2)); // add i0,i1,i2 | |
| 1403 | UML_AND(block, IREG(0), IREG(0), IMM(0x00000fff)); // and i0,i0,0x00000fff | |
| 1404 | UML_XOR(block, IREG(0), IREG(0), IMM(BYTE4_XOR_BE(0))); // xor i0,i0,bytexor | |
| 1405 | UML_LOAD(block, IREG(0), rsp->impstate->dmem, IREG(0), BYTE); // load i0,dmem,i0,byte | |
| 1406 | UML_SHL(block, IREG(0), IREG(0), IMM(8)); // shl i0,i0,8 | |
| 1407 | UML_STORE(block, &rsp->v[dest].s[5], IMM(0), IREG(0), WORD); // store v[dest][5],i0,word | |
| 1408 | ||
| 1409 | UML_ADD(block, IREG(1), IREG(3), IMM(3)); // add i1,i3,3 | |
| 1410 | UML_AND(block, IREG(1), IREG(1), IMM(0x0000000f)); // and i1,i1,0x0000000f | |
| 1411 | UML_ADD(block, IREG(0), IREG(1), IREG(2)); // add i0,i1,i2 | |
| 1412 | UML_AND(block, IREG(0), IREG(0), IMM(0x00000fff)); // and i0,i0,0x00000fff | |
| 1413 | UML_XOR(block, IREG(0), IREG(0), IMM(BYTE4_XOR_BE(0))); // xor i0,i0,bytexor | |
| 1414 | UML_LOAD(block, IREG(0), rsp->impstate->dmem, IREG(0), BYTE); // load i0,dmem,i0,byte | |
| 1415 | UML_SHL(block, IREG(0), IREG(0), IMM(8)); // shl i0,i0,8 | |
| 1416 | UML_STORE(block, &rsp->v[dest].s[4], IMM(0), IREG(0), WORD); // store v[dest][4],i0,word | |
| 1417 | ||
| 1418 | UML_ADD(block, IREG(1), IREG(3), IMM(4)); // add i1,i3,4 | |
| 1419 | UML_AND(block, IREG(1), IREG(1), IMM(0x0000000f)); // and i1,i1,0x0000000f | |
| 1420 | UML_ADD(block, IREG(0), IREG(1), IREG(2)); // add i0,i1,i2 | |
| 1421 | UML_AND(block, IREG(0), IREG(0), IMM(0x00000fff)); // and i0,i0,0x00000fff | |
| 1422 | UML_XOR(block, IREG(0), IREG(0), IMM(BYTE4_XOR_BE(0))); // xor i0,i0,bytexor | |
| 1423 | UML_LOAD(block, IREG(0), rsp->impstate->dmem, IREG(0), BYTE); // load i0,dmem,i0,byte | |
| 1424 | UML_SHL(block, IREG(0), IREG(0), IMM(8)); // shl i0,i0,8 | |
| 1425 | UML_STORE(block, &rsp->v[dest].s[3], IMM(0), IREG(0), WORD); // store v[dest][3],i0,word | |
| 1426 | ||
| 1427 | UML_ADD(block, IREG(1), IREG(3), IMM(5)); // add i1,i3,5 | |
| 1428 | UML_AND(block, IREG(1), IREG(1), IMM(0x0000000f)); // and i1,i1,0x0000000f | |
| 1429 | UML_ADD(block, IREG(0), IREG(1), IREG(2)); // add i0,i1,i2 | |
| 1430 | UML_AND(block, IREG(0), IREG(0), IMM(0x00000fff)); // and i0,i0,0x00000fff | |
| 1431 | UML_XOR(block, IREG(0), IREG(0), IMM(BYTE4_XOR_BE(0))); // xor i0,i0,bytexor | |
| 1432 | UML_LOAD(block, IREG(0), rsp->impstate->dmem, IREG(0), BYTE); // load i0,dmem,i0,byte | |
| 1433 | UML_SHL(block, IREG(0), IREG(0), IMM(8)); // shl i0,i0,8 | |
| 1434 | UML_STORE(block, &rsp->v[dest].s[2], IMM(0), IREG(0), WORD); // store v[dest][2],i0,word | |
| 1435 | ||
| 1436 | UML_ADD(block, IREG(1), IREG(3), IMM(6)); // add i1,i3,6 | |
| 1437 | UML_AND(block, IREG(1), IREG(1), IMM(0x0000000f)); // and i1,i1,0x0000000f | |
| 1438 | UML_ADD(block, IREG(0), IREG(1), IREG(2)); // add i0,i1,i2 | |
| 1439 | UML_AND(block, IREG(0), IREG(0), IMM(0x00000fff)); // and i0,i0,0x00000fff | |
| 1440 | UML_XOR(block, IREG(0), IREG(0), IMM(BYTE4_XOR_BE(0))); // xor i0,i0,bytexor | |
| 1441 | UML_LOAD(block, IREG(0), rsp->impstate->dmem, IREG(0), BYTE); // load i0,dmem,i0,byte | |
| 1442 | UML_SHL(block, IREG(0), IREG(0), IMM(8)); // shl i0,i0,8 | |
| 1443 | UML_STORE(block, &rsp->v[dest].s[1], IMM(0), IREG(0), WORD); // store v[dest][1],i0,word | |
| 1444 | ||
| 1445 | UML_ADD(block, IREG(1), IREG(3), IMM(7)); // add i1,i3,7 | |
| 1446 | UML_AND(block, IREG(1), IREG(1), IMM(0x0000000f)); // and i1,i1,0x0000000f | |
| 1447 | UML_ADD(block, IREG(0), IREG(1), IREG(2)); // add i0,i1,i2 | |
| 1448 | UML_AND(block, IREG(0), IREG(0), IMM(0x00000fff)); // and i0,i0,0x00000fff | |
| 1449 | UML_XOR(block, IREG(0), IREG(0), IMM(BYTE4_XOR_BE(0))); // xor i0,i0,bytexor | |
| 1450 | UML_LOAD(block, IREG(0), rsp->impstate->dmem, IREG(0), BYTE); // load i0,dmem,i0,byte | |
| 1451 | UML_SHL(block, IREG(0), IREG(0), IMM(8)); // shl i0,i0,8 | |
| 1452 | UML_STORE(block, &rsp->v[dest].s[0], IMM(0), IREG(0), WORD); // store v[dest][0],i0,word | |
| 1453 | return TRUE; | |
| 1454 | #else | |
| 1455 | 1144 | UML_MOV(block, MEM(&rsp->impstate->arg0), IMM(desc->opptr.l[0])); // mov [arg0],desc->opptr.l |
| 1456 | 1145 | UML_CALLC(block, cfunc_rsp_lpv, rsp); |
| 1457 | 1146 | return TRUE; |
| 1458 | #endif | |
| 1459 | 1147 | case 0x07: /* LUV */ |
| 1460 | #if (DRC_LUV) | |
| 1461 | #ifdef UNUSED_CODE | |
| 1462 | ea = (base) ? rsp->r[base] + (offset * 8) : (offset * 8); | |
| 1463 | ||
| 1464 | for (i=0; i < 8; i++) | |
| 1465 | { | |
| 1466 | W_VREG_S(dest, i, READ8(rsp, ea + (((16-index) + i) & 0xf)) << 7); | |
| 1467 | } | |
| 1468 | #endif | |
| 1469 | offset <<= 3; | |
| 1470 | ||
| 1471 | UML_ADD(block, IREG(2), R32(RSREG), IMM(offset)); // add i2,<rsreg>,offset | |
| 1472 | UML_SUB(block, IREG(3), IMM(16), IMM(index)); // sub i3,16,index | |
| 1473 | ||
| 1474 | UML_AND(block, IREG(1), IREG(3), IMM(0x0000000f)); // and i1,i1,0x0000000f | |
| 1475 | UML_ADD(block, IREG(0), IREG(1), IREG(2)); // add i0,i1,i2 | |
| 1476 | UML_XOR(block, IREG(0), IREG(0), IMM(BYTE4_XOR_BE(0))); // xor i0,i0,bytexor | |
| 1477 | UML_LOAD(block, IREG(0), rsp->impstate->dmem, IREG(0), BYTE); // load i0,dmem,i0,byte | |
| 1478 | UML_SHL(block, IREG(0), IREG(0), IMM(7)); // shl i0,i0,8 | |
| 1479 | UML_STORE(block, &rsp->v[dest].s[7], IMM(0), IREG(0), WORD); // store v[dest][7],i0,word | |
| 1480 | ||
| 1481 | UML_ADD(block, IREG(1), IREG(3), IMM(1)); // add i1,i3,1 | |
| 1482 | UML_AND(block, IREG(1), IREG(1), IMM(0x0000000f)); // and i1,i1,0x0000000f | |
| 1483 | UML_ADD(block, IREG(0), IREG(1), IREG(2)); // add i0,i1,i2 | |
| 1484 | UML_XOR(block, IREG(0), IREG(0), IMM(BYTE4_XOR_BE(0))); // xor i0,i0,bytexor | |
| 1485 | UML_LOAD(block, IREG(0), rsp->impstate->dmem, IREG(0), BYTE); // load i0,dmem,i0,byte | |
| 1486 | UML_SHL(block, IREG(0), IREG(0), IMM(7)); // shl i0,i0,8 | |
| 1487 | UML_STORE(block, &rsp->v[dest].s[6], IMM(0), IREG(0), WORD); // store v[dest][6],i0,word | |
| 1488 | ||
| 1489 | UML_ADD(block, IREG(1), IREG(3), IMM(2)); // add i1,i3,2 | |
| 1490 | UML_AND(block, IREG(1), IREG(1), IMM(0x0000000f)); // and i1,i1,0x0000000f | |
| 1491 | UML_ADD(block, IREG(0), IREG(1), IREG(2)); // add i0,i1,i2 | |
| 1492 | UML_XOR(block, IREG(0), IREG(0), IMM(BYTE4_XOR_BE(0))); // xor i0,i0,bytexor | |
| 1493 | UML_LOAD(block, IREG(0), rsp->impstate->dmem, IREG(0), BYTE); // load i0,dmem,i0,byte | |
| 1494 | UML_SHL(block, IREG(0), IREG(0), IMM(7)); // shl i0,i0,8 | |
| 1495 | UML_STORE(block, &rsp->v[dest].s[5], IMM(0), IREG(0), WORD); // store v[dest][5],i0,word | |
| 1496 | ||
| 1497 | UML_ADD(block, IREG(1), IREG(3), IMM(3)); // add i1,i3,3 | |
| 1498 | UML_AND(block, IREG(1), IREG(1), IMM(0x0000000f)); // and i1,i1,0x0000000f | |
| 1499 | UML_ADD(block, IREG(0), IREG(1), IREG(2)); // add i0,i1,i2 | |
| 1500 | UML_XOR(block, IREG(0), IREG(0), IMM(BYTE4_XOR_BE(0))); // xor i0,i0,bytexor | |
| 1501 | UML_LOAD(block, IREG(0), rsp->impstate->dmem, IREG(0), BYTE); // load i0,dmem,i0,byte | |
| 1502 | UML_SHL(block, IREG(0), IREG(0), IMM(7)); // shl i0,i0,8 | |
| 1503 | UML_STORE(block, &rsp->v[dest].s[4], IMM(0), IREG(0), WORD); // store v[dest][4],i0,word | |
| 1504 | ||
| 1505 | UML_ADD(block, IREG(1), IREG(3), IMM(4)); // add i1,i3,4 | |
| 1506 | UML_AND(block, IREG(1), IREG(1), IMM(0x0000000f)); // and i1,i1,0x0000000f | |
| 1507 | UML_ADD(block, IREG(0), IREG(1), IREG(2)); // add i0,i1,i2 | |
| 1508 | UML_XOR(block, IREG(0), IREG(0), IMM(BYTE4_XOR_BE(0))); // xor i0,i0,bytexor | |
| 1509 | UML_LOAD(block, IREG(0), rsp->impstate->dmem, IREG(0), BYTE); // load i0,dmem,i0,byte | |
| 1510 | UML_SHL(block, IREG(0), IREG(0), IMM(7)); // shl i0,i0,8 | |
| 1511 | UML_STORE(block, &rsp->v[dest].s[3], IMM(0), IREG(0), WORD); // store v[dest][3],i0,word | |
| 1512 | ||
| 1513 | UML_ADD(block, IREG(1), IREG(3), IMM(5)); // add i1,i3,5 | |
| 1514 | UML_AND(block, IREG(1), IREG(1), IMM(0x0000000f)); // and i1,i1,0x0000000f | |
| 1515 | UML_ADD(block, IREG(0), IREG(1), IREG(2)); // add i0,i1,i2 | |
| 1516 | UML_XOR(block, IREG(0), IREG(0), IMM(BYTE4_XOR_BE(0))); // xor i0,i0,bytexor | |
| 1517 | UML_LOAD(block, IREG(0), rsp->impstate->dmem, IREG(0), BYTE); // load i0,dmem,i0,byte | |
| 1518 | UML_SHL(block, IREG(0), IREG(0), IMM(7)); // shl i0,i0,8 | |
| 1519 | UML_STORE(block, &rsp->v[dest].s[2], IMM(0), IREG(0), WORD); // store v[dest][2],i0,word | |
| 1520 | ||
| 1521 | UML_ADD(block, IREG(1), IREG(3), IMM(6)); // add i1,i3,6 | |
| 1522 | UML_AND(block, IREG(1), IREG(1), IMM(0x0000000f)); // and i1,i1,0x0000000f | |
| 1523 | UML_ADD(block, IREG(0), IREG(1), IREG(2)); // add i0,i1,i2 | |
| 1524 | UML_XOR(block, IREG(0), IREG(0), IMM(BYTE4_XOR_BE(0))); // xor i0,i0,bytexor | |
| 1525 | UML_LOAD(block, IREG(0), rsp->impstate->dmem, IREG(0), BYTE); // load i0,dmem,i0,byte | |
| 1526 | UML_SHL(block, IREG(0), IREG(0), IMM(7)); // shl i0,i0,8 | |
| 1527 | UML_STORE(block, &rsp->v[dest].s[1], IMM(0), IREG(0), WORD); // store v[dest][1],i0,word | |
| 1528 | ||
| 1529 | UML_ADD(block, IREG(1), IREG(3), IMM(7)); // add i1,i3,7 | |
| 1530 | UML_AND(block, IREG(1), IREG(1), IMM(0x0000000f)); // and i1,i1,0x0000000f | |
| 1531 | UML_ADD(block, IREG(0), IREG(1), IREG(2)); // add i0,i1,i2 | |
| 1532 | UML_XOR(block, IREG(0), IREG(0), IMM(BYTE4_XOR_BE(0))); // xor i0,i0,bytexor | |
| 1533 | UML_LOAD(block, IREG(0), rsp->impstate->dmem, IREG(0), BYTE); // load i0,dmem,i0,byte | |
| 1534 | UML_SHL(block, IREG(0), IREG(0), IMM(7)); // shl i0,i0,8 | |
| 1535 | UML_STORE(block, &rsp->v[dest].s[0], IMM(0), IREG(0), WORD); // store v[dest][0],i0,word | |
| 1536 | return TRUE; | |
| 1537 | #else | |
| 1538 | 1148 | UML_MOV(block, MEM(&rsp->impstate->arg0), IMM(desc->opptr.l[0])); // mov [arg0],desc->opptr.l |
| 1539 | 1149 | UML_CALLC(block, cfunc_rsp_luv, rsp); |
| 1540 | 1150 | return TRUE; |
| 1541 | #endif | |
| 1542 | 1151 | case 0x08: /* LHV */ |
| 1543 | 1152 | UML_MOV(block, MEM(&rsp->impstate->arg0), IMM(desc->opptr.l[0])); // mov [arg0],desc->opptr.l |
| 1544 | 1153 | UML_CALLC(block, cfunc_rsp_lhv, rsp); |
| r9854 | r9855 | |
| 1574 | 1183 | { |
| 1575 | 1184 | offset |= 0xffffffc0; |
| 1576 | 1185 | } |
| 1577 | // 31 25 20 15 10 6 0 | |
| 1578 | // -------------------------------------------------- | |
| 1579 | // | 111010 | BBBBB | TTTTT | 00000 | IIII | Offset | | |
| 1580 | // -------------------------------------------------- | |
| 1581 | // | |
| 1582 | // Stores 1 byte from vector byte index | |
| 1583 | 1186 | |
| 1584 | ea = (base) ? rsp->r[base] + offset : offset; | |
| 1585 | WRITE8(rsp, ea, R_VREG_B(dest, index)); | |
| 1187 | // 31 25 20 15 10 6 0 | |
| 1188 | // -------------------------------------------------- | |
| 1189 | // | 111010 | BBBBB | TTTTT | 00000 | IIII | Offset | | |
| 1190 | // -------------------------------------------------- | |
| 1191 | // | |
| 1192 | // Stores 1 byte from vector byte index | |
| 1193 | ||
| 1194 | ea = (base) ? rsp->r[base] + offset : offset; | |
| 1195 | WRITE8(rsp, ea, VREG_B(dest, index)); | |
| 1586 | 1196 | } |
| 1587 | 1197 | |
| 1588 | #if !(DRC_SSV) | |
| 1589 | 1198 | static void cfunc_rsp_ssv(void *param) |
| 1590 | 1199 | { |
| 1591 | 1200 | rsp_state *rsp = (rsp_state*)param; |
| r9854 | r9855 | |
| 1599 | 1208 | { |
| 1600 | 1209 | offset |= 0xffffffc0; |
| 1601 | 1210 | } |
| 1602 | // 31 25 20 15 10 6 0 | |
| 1603 | // -------------------------------------------------- | |
| 1604 | // | 111010 | BBBBB | TTTTT | 00001 | IIII | Offset | | |
| 1605 | // -------------------------------------------------- | |
| 1606 | // | |
| 1607 | // Stores 2 bytes starting from vector byte index | |
| 1608 | 1211 | |
| 1609 | ea = (base) ? rsp->r[base] + (offset * 2) : (offset * 2); | |
| 1212 | // 31 25 20 15 10 6 0 | |
| 1213 | // -------------------------------------------------- | |
| 1214 | // | 111010 | BBBBB | TTTTT | 00001 | IIII | Offset | | |
| 1215 | // -------------------------------------------------- | |
| 1216 | // | |
| 1217 | // Stores 2 bytes starting from vector byte index | |
| 1610 | 1218 | |
| 1611 | WRITE16(rsp, ea, R_VREG_S(dest, index >> 1)); | |
| 1219 | ea = (base) ? rsp->r[base] + (offset * 2) : (offset * 2); | |
| 1220 | ||
| 1221 | int end = index + 2; | |
| 1222 | ||
| 1223 | for (int i = index; i < end; i++) | |
| 1224 | { | |
| 1225 | WRITE8(rsp, ea, VREG_B(dest, i)); | |
| 1226 | ea++; | |
| 1227 | } | |
| 1612 | 1228 | } |
| 1613 | #endif | |
| 1614 | 1229 | |
| 1615 | #if !(DRC_SLV) | |
| 1616 | 1230 | static void cfunc_rsp_slv(void *param) |
| 1617 | 1231 | { |
| 1618 | 1232 | rsp_state *rsp = (rsp_state*)param; |
| r9854 | r9855 | |
| 1626 | 1240 | { |
| 1627 | 1241 | offset |= 0xffffffc0; |
| 1628 | 1242 | } |
| 1629 | // 31 25 20 15 10 6 0 | |
| 1630 | // -------------------------------------------------- | |
| 1631 | // | 111010 | BBBBB | TTTTT | 00010 | IIII | Offset | | |
| 1632 | // -------------------------------------------------- | |
| 1633 | // | |
| 1634 | // Stores 4 bytes starting from vector byte index | |
| 1243 | // 31 25 20 15 10 6 0 | |
| 1244 | // -------------------------------------------------- | |
| 1245 | // | 111010 | BBBBB | TTTTT | 00010 | IIII | Offset | | |
| 1246 | // -------------------------------------------------- | |
| 1247 | // | |
| 1248 | // Stores 4 bytes starting from vector byte index | |
| 1635 | 1249 | |
| 1636 | | |
| 1250 | | |
| 1637 | 1251 | |
| 1638 | WRITE32(rsp, ea, R_VREG_L(dest, index >> 2)); | |
| 1252 | int end = index + 4; | |
| 1253 | ||
| 1254 | for (int i = index; i < end; i++) | |
| 1255 | { | |
| 1256 | WRITE8(rsp, ea, VREG_B(dest, i)); | |
| 1257 | ea++; | |
| 1258 | } | |
| 1639 | 1259 | } |
| 1640 | #endif | |
| 1641 | 1260 | |
| 1642 | #if !(DRC_SDV) | |
| 1643 | 1261 | static void cfunc_rsp_sdv(void *param) |
| 1644 | 1262 | { |
| 1645 | 1263 | rsp_state *rsp = (rsp_state*)param; |
| r9854 | r9855 | |
| 1654 | 1272 | { |
| 1655 | 1273 | offset |= 0xffffffc0; |
| 1656 | 1274 | } |
| 1657 | // 31 25 20 15 10 6 0 | |
| 1658 | // -------------------------------------------------- | |
| 1659 | // | 111010 | BBBBB | TTTTT | 00011 | IIII | Offset | | |
| 1660 | // -------------------------------------------------- | |
| 1661 | // | |
| 1662 | // Stores 8 bytes starting from vector byte index | |
| 1663 | ea = (base) ? rsp->r[base] + (offset * 8) : (offset * 8); | |
| 1275 | // 31 25 20 15 10 6 0 | |
| 1276 | // -------------------------------------------------- | |
| 1277 | // | 111010 | BBBBB | TTTTT | 00011 | IIII | Offset | | |
| 1278 | // -------------------------------------------------- | |
| 1279 | // | |
| 1280 | // Stores 8 bytes starting from vector byte index | |
| 1281 | ea = (base) ? rsp->r[base] + (offset * 8) : (offset * 8); | |
| 1664 | 1282 | |
| 1665 | | |
| 1283 | | |
| 1666 | 1284 | |
| 1667 | index >>= 2; | |
| 1668 | WRITE32(rsp, ea, R_VREG_L(dest, index)); | |
| 1669 | WRITE32(rsp, ea + 4, R_VREG_L(dest, index + 1)); | |
| 1285 | for (int i = index; i < end; i++) | |
| 1286 | { | |
| 1287 | WRITE8(rsp, ea, VREG_B(dest, i)); | |
| 1288 | ea++; | |
| 1289 | } | |
| 1670 | 1290 | } |
| 1671 | #endif | |
| 1672 | 1291 | |
| 1673 | #if !(DRC_SQV) | |
| 1674 | 1292 | static void cfunc_rsp_sqv(void *param) |
| 1675 | 1293 | { |
| 1676 | 1294 | rsp_state *rsp = (rsp_state*)param; |
| r9854 | r9855 | |
| 1686 | 1304 | { |
| 1687 | 1305 | offset |= 0xffffffc0; |
| 1688 | 1306 | } |
| 1689 | // 31 25 20 15 10 6 0 | |
| 1690 | // -------------------------------------------------- | |
| 1691 | // | 111010 | BBBBB | TTTTT | 00100 | IIII | Offset | | |
| 1692 | // -------------------------------------------------- | |
| 1693 | // | |
| 1694 | // Stores up to 16 bytes starting from vector byte index until 16-byte boundary | |
| 1307 | // 31 25 20 15 10 6 0 | |
| 1308 | // -------------------------------------------------- | |
| 1309 | // | 111010 | BBBBB | TTTTT | 00100 | IIII | Offset | | |
| 1310 | // -------------------------------------------------- | |
| 1311 | // | |
| 1312 | // Stores up to 16 bytes starting from vector byte index until 16-byte boundary | |
| 1695 | 1313 | |
| 1696 | | |
| 1314 | | |
| 1697 | 1315 | |
| 1698 | | |
| 1316 | | |
| 1699 | 1317 | |
| 1700 | for (i=index; i < end; i++) | |
| 1701 | { | |
| 1702 | WRITE8(rsp, ea, R_VREG_B(dest, i & 0xf)); | |
| 1703 | ea++; | |
| 1704 | } | |
| 1318 | for (i=index; i < end; i++) | |
| 1319 | { | |
| 1320 | WRITE8(rsp, ea, VREG_B(dest, i & 0xf)); | |
| 1321 | ea++; | |
| 1322 | } | |
| 1705 | 1323 | } |
| 1706 | #endif | |
| 1707 | 1324 | |
| 1708 | 1325 | static void cfunc_rsp_srv(void *param) |
| 1709 | 1326 | { |
| 1710 | 1327 | rsp_state *rsp = (rsp_state*)param; |
| 1711 | 1328 | UINT32 op = rsp->impstate->arg0; |
| 1712 | UINT32 ea = 0; | |
| 1713 | int o; | |
| 1714 | int i = 0; | |
| 1715 | int end = 0; | |
| 1716 | 1329 | int dest = (op >> 16) & 0x1f; |
| 1717 | 1330 | int base = (op >> 21) & 0x1f; |
| 1718 | 1331 | int index = (op >> 7) & 0xf; |
| r9854 | r9855 | |
| 1721 | 1334 | { |
| 1722 | 1335 | offset |= 0xffffffc0; |
| 1723 | 1336 | } |
| 1724 | // 31 25 20 15 10 6 0 | |
| 1725 | // -------------------------------------------------- | |
| 1726 | // | 111010 | BBBBB | TTTTT | 00101 | IIII | Offset | | |
| 1727 | // -------------------------------------------------- | |
| 1728 | // | |
| 1729 | // Stores up to 16 bytes starting from right side until 16-byte boundary | |
| 1337 | // 31 25 20 15 10 6 0 | |
| 1338 | // -------------------------------------------------- | |
| 1339 | // | 111010 | BBBBB | TTTTT | 00101 | IIII | Offset | | |
| 1340 | // -------------------------------------------------- | |
| 1341 | // | |
| 1342 | // Stores up to 16 bytes starting from right side until 16-byte boundary | |
| 1730 | 1343 | |
| 1731 | | |
| 1344 | UINT32 ea = (base) ? rsp->r[base] + (offset * 16) : (offset * 16); | |
| 1732 | 1345 | |
| 1733 | end = index + (ea & 0xf); | |
| 1734 | o = (16 - (ea & 0xf)) & 0xf; | |
| 1735 | ea &= ~0xf; | |
| 1346 | int end = index + (ea & 0xf); | |
| 1347 | int o = (16 - (ea & 0xf)) & 0xf; | |
| 1348 | ea &= ~0xf; | |
| 1736 | 1349 | |
| 1737 | for (i=index; i < end; i++) | |
| 1738 | { | |
| 1739 | WRITE8(rsp, ea, R_VREG_B(dest, ((i + o) & 0xf))); | |
| 1740 | ea++; | |
| 1741 | } | |
| 1350 | for (int i = index; i < end; i++) | |
| 1351 | { | |
| 1352 | WRITE8(rsp, ea, VREG_B(dest, ((i + o) & 0xf))); | |
| 1353 | ea++; | |
| 1354 | } | |
| 1742 | 1355 | } |
| 1743 | 1356 | |
| 1744 | #if !(DRC_SPV) | |
| 1745 | 1357 | static void cfunc_rsp_spv(void *param) |
| 1746 | 1358 | { |
| 1747 | 1359 | rsp_state *rsp = (rsp_state*)param; |
| r9854 | r9855 | |
| 1757 | 1369 | { |
| 1758 | 1370 | offset |= 0xffffffc0; |
| 1759 | 1371 | } |
| 1760 | // 31 25 20 15 10 6 0 | |
| 1761 | // -------------------------------------------------- | |
| 1762 | // | 111010 | BBBBB | TTTTT | 00110 | IIII | Offset | | |
| 1763 | // -------------------------------------------------- | |
| 1764 | // | |
| 1765 | // Stores upper 8 bits of each element | |
| 1372 | // 31 25 20 15 10 6 0 | |
| 1373 | // -------------------------------------------------- | |
| 1374 | // | 111010 | BBBBB | TTTTT | 00110 | IIII | Offset | | |
| 1375 | // -------------------------------------------------- | |
| 1376 | // | |
| 1377 | // Stores upper 8 bits of each element | |
| 1766 | 1378 | |
| 1767 | ea = (base) ? rsp->r[base] + (offset * 8) : (offset * 8); | |
| 1768 | end = index + 8; | |
| 1379 | ea = (base) ? rsp->r[base] + (offset * 8) : (offset * 8); | |
| 1380 | end = index + 8; | |
| 1769 | 1381 | |
| 1770 | for (i=index; i < end; i++) | |
| 1771 | { | |
| 1772 | if ((i & 0xf) < 8) | |
| 1773 | { | |
| 1774 | WRITE8(rsp, ea, R_VREG_B(dest, ((i & 0xf) << 1))); | |
| 1775 | } | |
| 1776 | else | |
| 1777 | { | |
| 1778 | WRITE8(rsp, ea, R_VREG_S(dest, (i & 0x7)) >> 7); | |
| 1779 | } | |
| 1780 | ea++; | |
| 1781 | } | |
| 1382 | for (i=index; i < end; i++) | |
| 1383 | { | |
| 1384 | if ((i & 0xf) < 8) | |
| 1385 | { | |
| 1386 | WRITE8(rsp, ea, VREG_B(dest, ((i & 0xf) << 1))); | |
| 1387 | } | |
| 1388 | else | |
| 1389 | { | |
| 1390 | WRITE8(rsp, ea, VREG_S(dest, (i & 0x7)) >> 7); | |
| 1391 | } | |
| 1392 | ea++; | |
| 1393 | } | |
| 1782 | 1394 | } |
| 1783 | #endif | |
| 1784 | 1395 | |
| 1785 | 1396 | static void cfunc_rsp_suv(void *param) |
| 1786 | 1397 | { |
| r9854 | r9855 | |
| 1797 | 1408 | { |
| 1798 | 1409 | offset |= 0xffffffc0; |
| 1799 | 1410 | } |
| 1800 | // 31 25 20 15 10 6 0 | |
| 1801 | // -------------------------------------------------- | |
| 1802 | // | 111010 | BBBBB | TTTTT | 00111 | IIII | Offset | | |
| 1803 | // -------------------------------------------------- | |
| 1804 | // | |
| 1805 | // Stores bits 14-7 of each element | |
| 1411 | // 31 25 20 15 10 6 0 | |
| 1412 | // -------------------------------------------------- | |
| 1413 | // | 111010 | BBBBB | TTTTT | 00111 | IIII | Offset | | |
| 1414 | // -------------------------------------------------- | |
| 1415 | // | |
| 1416 | // Stores bits 14-7 of each element | |
| 1806 | 1417 | |
| 1807 | ea = (base) ? rsp->r[base] + (offset * 8) : (offset * 8); | |
| 1808 | end = index + 8; | |
| 1418 | ea = (base) ? rsp->r[base] + (offset * 8) : (offset * 8); | |
| 1419 | end = index + 8; | |
| 1809 | 1420 | |
| 1810 | for (i=index; i < end; i++) | |
| 1811 | { | |
| 1812 | if ((i & 0xf) < 8) | |
| 1813 | { | |
| 1814 | WRITE8(rsp, ea, R_VREG_S(dest, (i & 0x7)) >> 7); | |
| 1815 | } | |
| 1816 | else | |
| 1817 | { | |
| 1818 | WRITE8(rsp, ea, R_VREG_B(dest, ((i & 0x7) << 1))); | |
| 1819 | } | |
| 1820 | ea++; | |
| 1821 | } | |
| 1421 | for (i=index; i < end; i++) | |
| 1422 | { | |
| 1423 | if ((i & 0xf) < 8) | |
| 1424 | { | |
| 1425 | WRITE8(rsp, ea, VREG_S(dest, (i & 0x7)) >> 7); | |
| 1426 | } | |
| 1427 | else | |
| 1428 | { | |
| 1429 | WRITE8(rsp, ea, VREG_B(dest, ((i & 0x7) << 1))); | |
| 1430 | } | |
| 1431 | ea++; | |
| 1432 | } | |
| 1822 | 1433 | } |
| 1823 | 1434 | |
| 1824 | 1435 | static void cfunc_rsp_shv(void *param) |
| r9854 | r9855 | |
| 1835 | 1446 | { |
| 1836 | 1447 | offset |= 0xffffffc0; |
| 1837 | 1448 | } |
| 1838 | // 31 25 20 15 10 6 0 | |
| 1839 | // -------------------------------------------------- | |
| 1840 | // | 111010 | BBBBB | TTTTT | 01000 | IIII | Offset | | |
| 1841 | // -------------------------------------------------- | |
| 1842 | // | |
| 1843 | // Stores bits 14-7 of each element, with 2-byte stride | |
| 1449 | // 31 25 20 15 10 6 0 | |
| 1450 | // -------------------------------------------------- | |
| 1451 | // | 111010 | BBBBB | TTTTT | 01000 | IIII | Offset | | |
| 1452 | // -------------------------------------------------- | |
| 1453 | // | |
| 1454 | // Stores bits 14-7 of each element, with 2-byte stride | |
| 1844 | 1455 | |
| 1845 | | |
| 1456 | | |
| 1846 | 1457 | |
| 1847 | for (i=0; i < 8; i++) | |
| 1848 | { | |
| 1849 | UINT8 d = ((R_VREG_B(dest, ((index + (i << 1) + 0) & 0xf))) << 1) | | |
| 1850 | ((R_VREG_B(dest, ((index + (i << 1) + 1) & 0xf))) >> 7); | |
| 1458 | for (i=0; i < 8; i++) | |
| 1459 | { | |
| 1460 | UINT8 d = ((VREG_B(dest, ((index + (i << 1) + 0) & 0xf))) << 1) | | |
| 1461 | ((VREG_B(dest, ((index + (i << 1) + 1) & 0xf))) >> 7); | |
| 1851 | 1462 | |
| 1852 | WRITE8(rsp, ea, d); | |
| 1853 | ea += 2; | |
| 1854 | } | |
| 1463 | WRITE8(rsp, ea, d); | |
| 1464 | ea += 2; | |
| 1465 | } | |
| 1855 | 1466 | } |
| 1856 | 1467 | |
| 1857 | 1468 | static void cfunc_rsp_sfv(void *param) |
| r9854 | r9855 | |
| 1870 | 1481 | { |
| 1871 | 1482 | offset |= 0xffffffc0; |
| 1872 | 1483 | } |
| 1873 | // 31 25 20 15 10 6 0 | |
| 1874 | // -------------------------------------------------- | |
| 1875 | // | 111010 | BBBBB | TTTTT | 01001 | IIII | Offset | | |
| 1876 | // -------------------------------------------------- | |
| 1877 | // | |
| 1878 | // Stores bits 14-7 of upper or lower quad, with 4-byte stride | |
| 1484 | // 31 25 20 15 10 6 0 | |
| 1485 | // -------------------------------------------------- | |
| 1486 | // | 111010 | BBBBB | TTTTT | 01001 | IIII | Offset | | |
| 1487 | // -------------------------------------------------- | |
| 1488 | // | |
| 1489 | // Stores bits 14-7 of upper or lower quad, with 4-byte stride | |
| 1879 | 1490 | |
| 1880 | | |
| 1491 | if | |
| 1881 | 1492 | |
| 1882 | | |
| 1493 | | |
| 1883 | 1494 | |
| 1884 | ea = (base) ? rsp->r[base] + (offset * 16) : (offset * 16); | |
| 1495 | eaoffset = ea & 0xf; | |
| 1496 | ea &= ~0xf; | |
| 1885 | 1497 | |
| 1886 | eaoffset = ea & 0xf; | |
| 1887 | ea &= ~0xf; | |
| 1498 | end = (index >> 1) + 4; | |
| 1888 | 1499 | |
| 1889 | end = (index >> 1) + 4; | |
| 1890 | ||
| 1891 | for (i=index >> 1; i < end; i++) | |
| 1892 | { | |
| 1893 | WRITE8(rsp, ea + (eaoffset & 0xf), R_VREG_S(dest, i) >> 7); | |
| 1894 | eaoffset += 4; | |
| 1895 | } | |
| 1500 | for (i=index >> 1; i < end; i++) | |
| 1501 | { | |
| 1502 | WRITE8(rsp, ea + (eaoffset & 0xf), VREG_S(dest, i) >> 7); | |
| 1503 | eaoffset += 4; | |
| 1504 | } | |
| 1896 | 1505 | } |
| 1897 | 1506 | |
| 1898 | 1507 | static void cfunc_rsp_swv(void *param) |
| r9854 | r9855 | |
| 1911 | 1520 | { |
| 1912 | 1521 | offset |= 0xffffffc0; |
| 1913 | 1522 | } |
| 1914 | // 31 25 20 15 10 6 0 | |
| 1915 | // -------------------------------------------------- | |
| 1916 | // | 111010 | BBBBB | TTTTT | 01010 | IIII | Offset | | |
| 1917 | // -------------------------------------------------- | |
| 1918 | // | |
| 1919 | // Stores the full 128-bit vector starting from vector byte index and wrapping to index 0 | |
| 1920 | // after byte index 15 | |
| 1523 | // 31 25 20 15 10 6 0 | |
| 1524 | // -------------------------------------------------- | |
| 1525 | // | 111010 | BBBBB | TTTTT | 01010 | IIII | Offset | | |
| 1526 | // -------------------------------------------------- | |
| 1527 | // | |
| 1528 | // Stores the full 128-bit vector starting from vector byte index and wrapping to index 0 | |
| 1529 | // after byte index 15 | |
| 1921 | 1530 | |
| 1922 | | |
| 1531 | | |
| 1923 | 1532 | |
| 1924 | eaoffset = ea & 0xf; | |
| 1925 | ea &= ~0xf; | |
| 1533 | eaoffset = ea & 0xf; | |
| 1534 | ea &= ~0xf; | |
| 1926 | 1535 | |
| 1927 | | |
| 1536 | | |
| 1928 | 1537 | |
| 1929 | for (i=index; i < end; i++) | |
| 1930 | { | |
| 1931 | WRITE8(rsp, ea + (eaoffset & 0xf), R_VREG_B(dest, i & 0xf)); | |
| 1932 | eaoffset++; | |
| 1933 | } | |
| 1538 | for (i=index; i < end; i++) | |
| 1539 | { | |
| 1540 | WRITE8(rsp, ea + (eaoffset & 0xf), VREG_B(dest, i & 0xf)); | |
| 1541 | eaoffset++; | |
| 1542 | } | |
| 1934 | 1543 | } |
| 1935 | 1544 | |
| 1936 | 1545 | static void cfunc_rsp_stv(void *param) |
| r9854 | r9855 | |
| 1943 | 1552 | int base = (op >> 21) & 0x1f; |
| 1944 | 1553 | int index = (op >> 7) & 0xf; |
| 1945 | 1554 | int offset = (op & 0x7f); |
| 1946 | int element; | |
| 1947 | int eaoffset = 0; | |
| 1948 | int vs = dest; | |
| 1949 | int ve = dest + 8; | |
| 1950 | if (ve > 32) | |
| 1951 | ve = 32; | |
| 1952 | 1555 | |
| 1953 | 1556 | if (offset & 0x40) |
| 1954 | 1557 | { |
| 1955 | 1558 | offset |= 0xffffffc0; |
| 1956 | 1559 | } |
| 1957 | // 31 25 20 15 10 6 0 | |
| 1958 | // -------------------------------------------------- | |
| 1959 | // | 111010 | BBBBB | TTTTT | 01011 | IIII | Offset | | |
| 1960 | // -------------------------------------------------- | |
| 1961 | // | |
| 1962 | // Stores one element from maximum of 8 vectors, while incrementing element index | |
| 1560 | // 31 25 20 15 10 6 0 | |
| 1561 | // -------------------------------------------------- | |
| 1562 | // | 111010 | BBBBB | TTTTT | 01011 | IIII | Offset | | |
| 1563 | // -------------------------------------------------- | |
| 1564 | // | |
| 1565 | // Stores one element from maximum of 8 vectors, while incrementing element index | |
| 1963 | 1566 | |
| 1964 | element = 8 - (index >> 1); | |
| 1965 | if (index & 0x1) fatalerror("RSP: STV: index = %d at %08X\n", index, rsp->ppc); | |
| 1567 | int vs = dest; | |
| 1568 | int ve = dest + 8; | |
| 1569 | if (ve > 32) | |
| 1570 | { | |
| 1571 | ve = 32; | |
| 1572 | } | |
| 1966 | 1573 | |
| 1967 | | |
| 1574 | int | |
| 1968 | 1575 | |
| 1969 | | |
| 1576 | | |
| 1970 | 1577 | |
| 1971 | eaoffset = (ea & 0xf) + (element * 2); | |
| 1972 | ea &= ~0xf; | |
| 1578 | int eaoffset = (ea & 0xf) + (element * 2); | |
| 1579 | ea &= ~0xf; | |
| 1973 | 1580 | |
| 1974 | for (i=vs; i < ve; i++) | |
| 1975 | { | |
| 1976 | WRITE16(rsp, ea + (eaoffset & 0xf), R_VREG_S(i, element & 0x7)); | |
| 1977 | eaoffset += 2; | |
| 1978 | element++; | |
| 1979 | } | |
| 1581 | for (i=vs; i < ve; i++) | |
| 1582 | { | |
| 1583 | WRITE16(rsp, ea + (eaoffset & 0xf), VREG_S(i, element & 0x7)); | |
| 1584 | eaoffset += 2; | |
| 1585 | element++; | |
| 1586 | } | |
| 1980 | 1587 | } |
| 1981 | 1588 | |
| 1982 | 1589 | static int generate_swc2(rsp_state *rsp, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) |
| r9854 | r9855 | |
| 2000 | 1607 | UML_CALLC(block, cfunc_rsp_sbv, rsp); |
| 2001 | 1608 | return TRUE; |
| 2002 | 1609 | case 0x01: /* SSV */ |
| 2003 | #if (DRC_SSV) | |
| 2004 | offset <<= 1; | |
| 2005 | index >>= 1; | |
| 2006 | ||
| 2007 | index = 7 - index; | |
| 2008 | UML_ADD(block, IREG(0), R32(RSREG), IMM(offset)); // add i0,<rsreg>,offset | |
| 2009 | UML_LOAD(block, IREG(1), &rsp->v[dest].s[index], IMM(0), WORD); // load i1,v[dest].b[0],0,byte | |
| 2010 | UML_CALLH(block, rsp->impstate->write16); // callh read32 | |
| 2011 | return TRUE; | |
| 2012 | #else | |
| 2013 | 1610 | UML_MOV(block, MEM(&rsp->impstate->arg0), IMM(desc->opptr.l[0])); // mov [arg0],desc->opptr.l |
| 2014 | 1611 | UML_CALLC(block, cfunc_rsp_ssv, rsp); |
| 2015 | 1612 | return TRUE; |
| 2016 | #endif | |
| 2017 | 1613 | case 0x02: /* SLV */ |
| 2018 | #if (DRC_SLV) | |
| 2019 | offset <<= 2; | |
| 2020 | index >>= 2; | |
| 2021 | ||
| 2022 | UML_ADD(block, IREG(0), R32(RSREG), IMM(offset)); // add i0,<rsreg>,offset | |
| 2023 | UML_MOV(block, IREG(1), VLX(dest, index)); // mov i1,v[dest].l[index] | |
| 2024 | UML_CALLH(block, rsp->impstate->write32); // callh read32 | |
| 2025 | return TRUE; | |
| 2026 | #else | |
| 2027 | 1614 | UML_MOV(block, MEM(&rsp->impstate->arg0), IMM(desc->opptr.l[0])); // mov [arg0],desc->opptr.l |
| 2028 | 1615 | UML_CALLC(block, cfunc_rsp_slv, rsp); |
| 2029 | 1616 | return TRUE; |
| 2030 | #endif | |
| 2031 | 1617 | case 0x03: /* SDV */ |
| 2032 | #if (DRC_SDV) | |
| 2033 | offset <<= 3; | |
| 2034 | index >>= 2; | |
| 2035 | ||
| 2036 | UML_ADD(block, IREG(0), R32(RSREG), IMM(offset)); // add i0,<rsreg>,offset | |
| 2037 | UML_MOV(block, IREG(1), VLX(dest, index)); // mov i1,v[dest].l[index] | |
| 2038 | UML_CALLH(block, rsp->impstate->write32); // callh write32 | |
| 2039 | ||
| 2040 | UML_ADD(block, IREG(0), R32(RSREG), IMM(offset)); // add i0,<rsreg>,offset | |
| 2041 | UML_ADD(block, IREG(0), IREG(0), IMM(4)); // add i0,i0,4 | |
| 2042 | UML_MOV(block, IREG(1), VLX(dest, index+1)); // mov i1,v[dest].l[index+1] | |
| 2043 | UML_CALLH(block, rsp->impstate->write32); // callh write32 | |
| 2044 | return TRUE; | |
| 2045 | #else | |
| 2046 | 1618 | UML_MOV(block, MEM(&rsp->impstate->arg0), IMM(desc->opptr.l[0])); // mov [arg0],desc->opptr.l |
| 2047 | 1619 | UML_CALLC(block, cfunc_rsp_sdv, rsp); |
| 2048 | 1620 | return TRUE; |
| 2049 | #endif | |
| 2050 | 1621 | case 0x04: /* SQV */ |
| 2051 | #if (DRC_SQV) | |
| 2052 | offset <<= 4; | |
| 2053 | ||
| 2054 | UML_ADD(block, MEM(&rsp->impstate->arg0), R32(RSREG), IMM(offset)); // mov arg0,<rsreg>,offset | |
| 2055 | UML_MOV(block, IREG(3), IMM(index)); // mov i3,index | |
| 2056 | UML_MOV(block, IREG(2), MEM(&rsp->impstate->arg0)); // mov i2,arg0 | |
| 2057 | UML_AND(block, IREG(2), IREG(2), IMM(0x0000000f)); // and i2,i2,0x0000000f | |
| 2058 | UML_SUB(block, IREG(2), IMM(16), IREG(2)); // sub i2,16,i2 | |
| 2059 | UML_ADD(block, IREG(2), IREG(2), IREG(3)); // add i2,i2,i3 | |
| 2060 | UML_CMP(block, IREG(2), IMM(16)); // cmp i2,16 | |
| 2061 | UML_TEST(block, IREG(2), IMM(0xfffffff0)); // test i2,0xfffffff0 | |
| 2062 | UML_MOVc(block, IF_NZ, IREG(2), IMM(16)); // mov NZ,i2,16 | |
| 2063 | ||
| 2064 | UML_LABEL(block, loopdest = compiler->labelnum++); // loopdest: | |
| 2065 | UML_MOV(block, IREG(0), MEM(&rsp->impstate->arg0)); // mov i0,arg0 | |
| 2066 | UML_XOR(block, IREG(0), IREG(0), IMM(BYTE4_XOR_BE(0))); // xor i0,i0,byte4xor | |
| 2067 | UML_SUB(block, IREG(1), IMM(15), IREG(3)); // sub i1,15,i3 | |
| 2068 | UML_LOAD(block, IREG(1), &rsp->v[dest].b[0], IREG(1), BYTE); // load i1,v[dest].b[0],i1,byte | |
| 2069 | UML_STORE(block, rsp->impstate->dmem, IREG(0), IREG(1), BYTE); // store dmem,i0,i1,byte | |
| 2070 | ||
| 2071 | UML_ADD(block, MEM(&rsp->impstate->arg0), MEM(&rsp->impstate->arg0), IMM(1)); | |
| 2072 | UML_ADD(block, IREG(3), IREG(3), IMM(1)); // add i3,i3,1 | |
| 2073 | UML_CMP(block, IREG(3), IREG(2)); // cmp i3,i2 | |
| 2074 | UML_JMPc(block, IF_L, loopdest); // jmp L,loopdest | |
| 2075 | return TRUE; | |
| 2076 | #else | |
| 2077 | 1622 | UML_MOV(block, MEM(&rsp->impstate->arg0), IMM(desc->opptr.l[0])); // mov [arg0],desc->opptr.l |
| 2078 | 1623 | UML_CALLC(block, cfunc_rsp_sqv, rsp); |
| 2079 | #endif | |
| 2080 | 1624 | return TRUE; |
| 2081 | 1625 | case 0x05: /* SRV */ |
| 2082 | 1626 | UML_MOV(block, MEM(&rsp->impstate->arg0), IMM(desc->opptr.l[0])); // mov [arg0],desc->opptr.l |
| 2083 | 1627 | UML_CALLC(block, cfunc_rsp_srv, rsp); |
| 2084 | 1628 | return TRUE; |
| 2085 | 1629 | case 0x06: /* SPV */ |
| 2086 | #if (DRC_SPV) | |
| 2087 | #else | |
| 2088 | 1630 | UML_MOV(block, MEM(&rsp->impstate->arg0), IMM(desc->opptr.l[0])); // mov [arg0],desc->opptr.l |
| 2089 | 1631 | UML_CALLC(block, cfunc_rsp_spv, rsp); |
| 2090 | #endif | |
| 2091 | 1632 | return TRUE; |
| 2092 | 1633 | case 0x07: /* SUV */ |
| 2093 | 1634 | UML_MOV(block, MEM(&rsp->impstate->arg0), IMM(desc->opptr.l[0])); // mov [arg0],desc->opptr.l |
| r9854 | r9855 | |
| 2118 | 1659 | return TRUE; |
| 2119 | 1660 | } |
| 2120 | 1661 | |
| 2121 | #if (DRC_VMADN) | |
| 2122 | static void generate_saturate_accum_unsigned(rsp_state *rsp, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, int accum) | |
| 1662 | INLINE UINT16 SATURATE_ACCUM(rsp_state *rsp, int accum, int slice, UINT16 negative, UINT16 positive) | |
| 2123 | 1663 | { |
| 2124 | #ifdef UNUSED_CODE | |
| 2125 | int skip, skip2; | |
| 2126 | ||
| 2127 | UML_CMP(block, VACCUMWMH(accum), IMM(-32768)); | |
| 2128 | UML_JMPc(block, IF_GE, skip = compiler->labelnum++); | |
| 2129 | UML_MOV(block, IREG(0), IMM(0)); | |
| 2130 | UML_JMP(block, skip2 = compiler->labelnum++); | |
| 2131 | ||
| 2132 | UML_LABEL(block, skip); | |
| 2133 | UML_CMP(block, VACCUMWMH(accum), IMM(32767)); | |
| 2134 | UML_JMPc(block, IF_L, skip = compiler->labelnum++); | |
| 2135 | UML_MOV(block, IREG(0), IMM(0x0000ffff)); | |
| 2136 | UML_JMP(block, skip2); | |
| 2137 | ||
| 2138 | UML_LABEL(block, skip); | |
| 2139 | UML_SEXT(block, IREG(0), VACCUMHL(accum), WORD); | |
| 2140 | UML_AND(block, IREG(0), IREG(0), IMM(0x0000ffff)); | |
| 2141 | UML_LABEL(block, skip2); | |
| 2142 | #endif | |
| 2143 | UML_SEXT(block, IREG(0), VACCUMHL(accum), WORD); | |
| 2144 | UML_AND(block, IREG(0), IREG(0), IMM(0x0000ffff)); | |
| 2145 | UML_CMP(block, VACCUMWMH(accum), IMM(-32768)); | |
| 2146 | UML_MOVc(block, IF_L, IREG(0), IMM(0)); | |
| 2147 | UML_CMP(block, VACCUMWMH(accum), IMM(32767)); | |
| 2148 | UML_MOVc(block, IF_GE, IREG(0), IMM(0x0000ffff)); | |
| 2149 | } | |
| 2150 | #endif | |
| 2151 | ||
| 2152 | INLINE UINT16 SATURATE_ACCUM_UNSIGNED(rsp_state *rsp, int accum) | |
| 2153 | { | |
| 2154 | if (ACCUM(accum).w.mh < -32768) | |
| 1664 | if ((INT16)ACCUM_H(accum) < 0) | |
| 2155 | 1665 | { |
| 2156 | return 0; | |
| 1666 | if ((UINT16)(ACCUM_H(accum)) != 0xffff) | |
| 1667 | { | |
| 1668 | return negative; | |
| 1669 | } | |
| 1670 | else | |
| 1671 | { | |
| 1672 | if ((INT16)ACCUM_M(accum) >= 0) | |
| 1673 | { | |
| 1674 | return negative; | |
| 1675 | } | |
| 1676 | else | |
| 1677 | { | |
| 1678 | if (slice == 0) | |
| 1679 | { | |
| 1680 | return ACCUM_L(accum); | |
| 1681 | } | |
| 1682 | else if (slice == 1) | |
| 1683 | { | |
| 1684 | return ACCUM_M(accum); | |
| 1685 | } | |
| 1686 | } | |
| 1687 | } | |
| 2157 | 1688 | } |
| 2158 | else if(ACCUM(accum).w.mh > 32767) | |
| 2159 | { | |
| 2160 | return 0xffff; | |
| 2161 | } | |
| 2162 | 1689 | else |
| 2163 | 1690 | { |
| 2164 | return ACCUM(accum).h.low; | |
| 1691 | if ((UINT16)(ACCUM_H(accum)) != 0) | |
| 1692 | { | |
| 1693 | return positive; | |
| 1694 | } | |
| 1695 | else | |
| 1696 | { | |
| 1697 | if ((INT16)ACCUM_M(accum) < 0) | |
| 1698 | { | |
| 1699 | return positive; | |
| 1700 | } | |
| 1701 | else | |
| 1702 | { | |
| 1703 | if (slice == 0) | |
| 1704 | { | |
| 1705 | return ACCUM_L(accum); | |
| 1706 | } | |
| 1707 | else | |
| 1708 | { | |
| 1709 | return ACCUM_M(accum); | |
| 1710 | } | |
| 1711 | } | |
| 1712 | } | |
| 2165 | 1713 | } |
| 2166 | } | |
| 2167 | 1714 | |
| 2168 | #if (DRC_VMADH) || (DRC_VMADM) | |
| 2169 | static void generate_saturate_accum_signed(rsp_state *rsp, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, int accum) | |
| 2170 | { | |
| 2171 | int skip, skip2; | |
| 2172 | ||
| 2173 | UML_CMP(block, VACCUMWMH(accum), IMM(-32768)); | |
| 2174 | UML_JMPc(block, IF_GE, skip = compiler->labelnum++); | |
| 2175 | UML_MOV(block, IREG(0), IMM(0x00008000)); | |
| 2176 | UML_JMP(block, skip2 = compiler->labelnum++); | |
| 2177 | ||
| 2178 | UML_LABEL(block, skip); | |
| 2179 | UML_CMP(block, VACCUMWMH(accum), IMM(32767)); | |
| 2180 | UML_JMPc(block, IF_L, skip = compiler->labelnum++); | |
| 2181 | UML_MOV(block, IREG(0), IMM(0x00007fff)); | |
| 2182 | UML_JMP(block, skip2); | |
| 2183 | ||
| 2184 | UML_LABEL(block, skip); | |
| 2185 | UML_SEXT(block, IREG(0), VACCUMHM(accum), WORD); | |
| 2186 | UML_AND(block, IREG(0), IREG(0), IMM(0x0000ffff)); | |
| 2187 | UML_LABEL(block, skip2); | |
| 1715 | return 0; | |
| 2188 | 1716 | } |
| 2189 | #endif | |
| 2190 | 1717 | |
| 2191 | INLINE UINT16 SATURATE_ACCUM | |
| 1718 | INLINE UINT16 SATURATE_ACCUM1 | |
| 2192 | 1719 | { |
| 2193 | if (ACCUM(accum) | |
| 1720 | if ((INT16)ACCUM_H(accum) | |
| 2194 | 1721 | { |
| 2195 | return 0x8000; | |
| 1722 | if ((UINT16)(ACCUM_H(accum)) != 0xffff) | |
| 1723 | { | |
| 1724 | return negative; | |
| 1725 | } | |
| 1726 | else | |
| 1727 | { | |
| 1728 | if ((INT16)ACCUM_M(accum) >= 0) | |
| 1729 | { | |
| 1730 | return negative; | |
| 1731 | } | |
| 1732 | else | |
| 1733 | { | |
| 1734 | return ACCUM_M(accum); | |
| 1735 | } | |
| 1736 | } | |
| 2196 | 1737 | } |
| 2197 | | |
| 1738 | else | |
| 2198 | 1739 | { |
| 2199 | return 0x7fff; | |
| 1740 | if ((UINT16)(ACCUM_H(accum)) != 0) | |
| 1741 | { | |
| 1742 | return positive; | |
| 1743 | } | |
| 1744 | else | |
| 1745 | { | |
| 1746 | if ((INT16)ACCUM_M(accum) < 0) | |
| 1747 | { | |
| 1748 | return positive; | |
| 1749 | } | |
| 1750 | else | |
| 1751 | { | |
| 1752 | return ACCUM_M(accum); | |
| 1753 | } | |
| 1754 | } | |
| 2200 | 1755 | } |
| 2201 | return ACCUM(accum).h.mid; | |
| 1756 | ||
| 1757 | return 0; | |
| 2202 | 1758 | } |
| 2203 | 1759 | |
| 2204 | #define WRITEBACK_RESULT() \ | |
| 2205 | do { \ | |
| 2206 | W_VREG_S_X(VDREG, 7, vres[0]); \ | |
| 2207 | W_VREG_S_X(VDREG, 6, vres[1]); \ | |
| 2208 | W_VREG_S_X(VDREG, 5, vres[2]); \ | |
| 2209 | W_VREG_S_X(VDREG, 4, vres[3]); \ | |
| 2210 | W_VREG_S_X(VDREG, 3, vres[4]); \ | |
| 2211 | W_VREG_S_X(VDREG, 2, vres[5]); \ | |
| 2212 | W_VREG_S_X(VDREG, 1, vres[6]); \ | |
| 2213 | W_VREG_S_X(VDREG, 0, vres[7]); \ | |
| 2214 | } while(0) | |
| 2215 | ||
| 2216 | #if 0 | |
| 2217 | static float float_round(float input) | |
| 2218 | { | |
| 2219 | INT32 integer = (INT32)input; | |
| 2220 | float fraction = input - (float)integer; | |
| 2221 | float output = 0.0f; | |
| 2222 | if( fraction >= 0.5f ) | |
| 2223 | { | |
| 2224 | output = (float)( integer + 1 ); | |
| 2225 | } | |
| 2226 | else | |
| 2227 | { | |
| 2228 | output = (float)integer; | |
| 2229 | } | |
| 2230 | return output; | |
| 1760 | #define WRITEBACK_RESULT() { \ | |
| 1761 | VREG_S(VDREG, 0) = vres[0]; \ | |
| 1762 | VREG_S(VDREG, 1) = vres[1]; \ | |
| 1763 | VREG_S(VDREG, 2) = vres[2]; \ | |
| 1764 | VREG_S(VDREG, 3) = vres[3]; \ | |
| 1765 | VREG_S(VDREG, 4) = vres[4]; \ | |
| 1766 | VREG_S(VDREG, 5) = vres[5]; \ | |
| 1767 | VREG_S(VDREG, 6) = vres[6]; \ | |
| 1768 | VREG_S(VDREG, 7) = vres[7]; \ | |
| 2231 | 1769 | } |
| 2232 | #endif | |
| 2233 | 1770 | |
| 2234 | #define RSP_VMULF(E10, E11, E12, E13, E14, E15, E16, E17, E20, E21, E22, E23, E24, E25, E26, E27, I0, I1, I2, I3, I4, I5, I6, I7) \ | |
| 2235 | { \ | |
| 2236 | INT16 v1, v2; \ | |
| 2237 | v1 = R_VREG_S_X(VS1REG, I0); v2 = R_VREG_S_X(VS2REG, E20); \ | |
| 2238 | if (v1 == -32768 && v2 == -32768) { ACCUM(E10).l = 0x0000800080000000LL; vres[E10] = 0x7fff; } \ | |
| 2239 | else { ACCUM(E10).l = ((INT64)((INT32)v1 * (INT32)v2) * 0x20000 + 0x80000000); vres[E10] = ACCUM(E10).h.mid; } \ | |
| 2240 | v1 = R_VREG_S_X(VS1REG, I1); v2 = R_VREG_S_X(VS2REG, E21); \ | |
| 2241 | if (v1 == -32768 && v2 == -32768) { ACCUM(E11).l = 0x0000800080000000LL; vres[E11] = 0x7fff; } \ | |
| 2242 | else { ACCUM(E11).l = ((INT64)((INT32)v1 * (INT32)v2) * 0x20000 + 0x80000000); vres[E11] = ACCUM(E11).h.mid; } \ | |
| 2243 | v1 = R_VREG_S_X(VS1REG, I2); v2 = R_VREG_S_X(VS2REG, E22); \ | |
| 2244 | if (v1 == -32768 && v2 == -32768) { ACCUM(E12).l = 0x0000800080000000LL; vres[E12] = 0x7fff; } \ | |
| 2245 | else { ACCUM(E12).l = ((INT64)((INT32)v1 * (INT32)v2) * 0x20000 + 0x80000000); vres[E12] = ACCUM(E12).h.mid; } \ | |
| 2246 | v1 = R_VREG_S_X(VS1REG, I3); v2 = R_VREG_S_X(VS2REG, E23); \ | |
| 2247 | if (v1 == -32768 && v2 == -32768) { ACCUM(E13).l = 0x0000800080000000LL; vres[E13] = 0x7fff; } \ | |
| 2248 | else { ACCUM(E13).l = ((INT64)((INT32)v1 * (INT32)v2) * 0x20000 + 0x80000000); vres[E13] = ACCUM(E13).h.mid; } \ | |
| 2249 | v1 = R_VREG_S_X(VS1REG, I4); v2 = R_VREG_S_X(VS2REG, E24); \ | |
| 2250 | if (v1 == -32768 && v2 == -32768) { ACCUM(E14).l = 0x0000800080000000LL; vres[E14] = 0x7fff; } \ | |
| 2251 | else { ACCUM(E14).l = ((INT64)((INT32)v1 * (INT32)v2) * 0x20000 + 0x80000000); vres[E14] = ACCUM(E14).h.mid; } \ | |
| 2252 | v1 = R_VREG_S_X(VS1REG, I5); v2 = R_VREG_S_X(VS2REG, E25); \ | |
| 2253 | if (v1 == -32768 && v2 == -32768) { ACCUM(E15).l = 0x0000800080000000LL; vres[E15] = 0x7fff; } \ | |
| 2254 | else { ACCUM(E15).l = ((INT64)((INT32)v1 * (INT32)v2) * 0x20000 + 0x80000000); vres[E15] = ACCUM(E15).h.mid; } \ | |
| 2255 | v1 = R_VREG_S_X(VS1REG, I6); v2 = R_VREG_S_X(VS2REG, E26); \ | |
| 2256 | if (v1 == -32768 && v2 == -32768) { ACCUM(E16).l = 0x0000800080000000LL; vres[E16] = 0x7fff; } \ | |
| 2257 | else { ACCUM(E16).l = ((INT64)((INT32)v1 * (INT32)v2) * 0x20000 + 0x80000000); vres[E16] = ACCUM(E16).h.mid; } \ | |
| 2258 | v1 = R_VREG_S_X(VS1REG, I7); v2 = R_VREG_S_X(VS2REG, E27); \ | |
| 2259 | if (v1 == -32768 && v2 == -32768) { ACCUM(E17).l = 0x0000800080000000LL; vres[E17] = 0x7fff; } \ | |
| 2260 | else { ACCUM(E17).l = ((INT64)((INT32)v1 * (INT32)v2) * 0x20000 + 0x80000000); vres[E17] = ACCUM(E17).h.mid; } \ | |
| 2261 | } | |
| 2262 | ||
| 2263 | 1771 | INLINE void cfunc_rsp_vmulf(void *param) |
| 2264 | 1772 | { |
| 2265 | 1773 | rsp_state *rsp = (rsp_state*)param; |
| r9854 | r9855 | |
| 2273 | 1781 | // |
| 2274 | 1782 | // Multiplies signed integer by signed integer * 2 |
| 2275 | 1783 | |
| 2276 | switch(EL) | |
| 1784 | int sel; | |
| 1785 | INT32 s1, s2; | |
| 1786 | INT64 r; | |
| 1787 | for (int i = 0; i < 8; i++) | |
| 2277 | 1788 | { |
| 2278 | case 0: /* 0, 1, 2, 3, 4, 5, 6, 7 - none */ /* 0, 1, 2, 3, 4, 5, 6, 7 - none */ | |
| 2279 | RSP_VMULF(0, 1, 2, 3, 4, 5, 6, 7, 7, 6, 5, 4, 3, 2, 1, 0, 7, 6, 5, 4, 3, 2, 1, 0); | |
| 2280 | break; | |
| 2281 | case 1: /* 0, 1, 2, 3, 4, 5, 6, 7 - ??? */ /* 0, 1, 2, 3, 4, 5, 6, 7 - ??? */ | |
| 2282 | RSP_VMULF(0, 1, 2, 3, 4, 5, 6, 7, 7, 6, 5, 4, 3, 2, 1, 0, 7, 6, 5, 4, 3, 2, 1, 0); | |
| 2283 | break; | |
| 2284 | case 2: /* 1, 3, 5, 7, 0, 2, 4, 6 - 0q */ /* 0, 0, 2, 2, 4, 4, 6, 6 - 0q */ | |
| 2285 | RSP_VMULF(1, 3, 5, 7, 0, 2, 4, 6, 7, 5, 3, 1, 7, 5, 3, 1, 6, 4, 2, 0, 7, 5, 3, 1); | |
| 2286 | break; | |
| 2287 | case 3: /* 0, 2, 4, 6, 1, 3, 5, 7 - 1q */ /* 1, 1, 3, 3, 5, 5, 7, 7 - 1q */ | |
| 2288 | RSP_VMULF(0, 2, 4, 6, 1, 3, 5, 7, 6, 4, 2, 0, 6, 4, 2, 0, 7, 5, 3, 1, 6, 4, 2, 0); | |
| 2289 | break; | |
| 2290 | case 4: /* 1, 2, 3, 5, 6, 7, 0, 4 - 0h */ /* 0, 0, 0, 0, 4, 4, 4, 4 - 0h */ | |
| 2291 | RSP_VMULF(1, 2, 3, 5, 6, 7, 0, 4, 7, 7, 7, 3, 3, 3, 7, 3, 6, 5, 4, 2, 1, 0, 7, 3); | |
| 2292 | break; | |
| 2293 | case 5: /* 0, 2, 3, 4, 6, 7, 1, 5 - 1h */ /* 1, 1, 1, 1, 5, 5, 5, 5 - 1h */ | |
| 2294 | RSP_VMULF(0, 2, 3, 4, 6, 7, 1, 5, 6, 6, 6, 2, 2, 2, 6, 2, 7, 5, 4, 3, 1, 0, 6, 2); | |
| 2295 | break; | |
| 2296 | case 6: /* 0, 1, 3, 4, 5, 7, 2, 6 - 2h */ /* 2, 2, 2, 2, 6, 6, 6, 6 - 2h */ | |
| 2297 | RSP_VMULF(0, 1, 3, 4, 5, 7, 2, 6, 5, 5, 5, 1, 1, 1, 5, 1, 7, 6, 4, 3, 2, 0, 5, 1); | |
| 2298 | break; | |
| 2299 | case 7: /* 0, 1, 2, 4, 5, 6, 3, 7 - 3h */ /* 3, 3, 3, 3, 7, 7, 7, 7 - 3h */ | |
| 2300 | RSP_VMULF(0, 1, 2, 4, 5, 6, 3, 7, 4, 4, 4, 0, 0, 0, 4, 0, 7, 6, 5, 3, 2, 1, 4, 0); | |
| 2301 | break; | |
| 2302 | case 8: /* 1, 2, 3, 4, 5, 6, 7, 0 - 0 */ /* 0, 0, 0, 0, 0, 0, 0, 0 - 0 */ | |
| 2303 | RSP_VMULF(1, 2, 3, 4, 5, 6, 7, 0, 7, 7, 7, 7, 7, 7, 7, 7, 6, 5, 4, 3, 2, 1, 0, 7); | |
| 2304 | break; | |
| 2305 | case 9: /* 0, 2, 3, 4, 5, 6, 7, 1 - 1 */ /* 1, 1, 1, 1, 1, 1, 1, 1 - 0 */ | |
| 2306 | RSP_VMULF(0, 2, 3, 4, 5, 6, 7, 1, 6, 6, 6, 6, 6, 6, 6, 6, 7, 5, 4, 3, 2, 1, 0, 6); | |
| 2307 | break; | |
| 2308 | case 10: /* 0, 1, 3, 4, 5, 6, 7, 2 - 2 */ /* 2, 2, 2, 2, 2, 2, 2, 2 - 0 */ | |
| 2309 | RSP_VMULF(0, 1, 3, 4, 5, 6, 7, 2, 5, 5, 5, 5, 5, 5, 5, 5, 7, 6, 4, 3, 2, 1, 0, 5); | |
| 2310 | break; | |
| 2311 | case 11: /* 0, 1, 2, 4, 5, 6, 7, 3 - 3 */ /* 3, 3, 3, 3, 3, 3, 3, 3 - 0 */ | |
| 2312 | RSP_VMULF(0, 1, 2, 4, 5, 6, 7, 3, 4, 4, 4, 4, 4, 4, 4, 4, 7, 6, 5, 3, 2, 1, 0, 4); | |
| 2313 | break; | |
| 2314 | case 12: /* 0, 1, 2, 3, 5, 6, 7, 4 - 4 */ /* 4, 4, 4, 4, 4, 4, 4, 4 - 0 */ | |
| 2315 | RSP_VMULF(0, 1, 2, 3, 5, 6, 7, 4, 3, 3, 3, 3, 3, 3, 3, 3, 7, 6, 5, 4, 2, 1, 0, 3); | |
| 2316 | break; | |
| 2317 | case 13: /* 0, 1, 2, 3, 4, 6, 7, 5 - 5 */ /* 5, 5, 5, 5, 5, 5, 5, 5 - 0 */ | |
| 2318 | RSP_VMULF(0, 1, 2, 3, 4, 6, 7, 5, 2, 2, 2, 2, 2, 2, 2, 2, 7, 6, 5, 4, 3, 1, 0, 2); | |
| 2319 | break; | |
| 2320 | case 14: /* 0, 1, 2, 3, 4, 5, 7, 6 - 6 */ /* 6, 6, 6, 6, 6, 6, 6, 6 - 0 */ | |
| 2321 | RSP_VMULF(0, 1, 2, 3, 4, 5, 7, 6, 1, 1, 1, 1, 1, 1, 1, 1, 7, 6, 5, 4, 3, 2, 0, 1); | |
| 2322 | break; | |
| 2323 | case 15: /* 0, 1, 2, 3, 4, 5, 6, 7 - 7 */ /* 7, 7, 7, 7, 7, 7, 7, 7 - 0 */ | |
| 2324 | RSP_VMULF(0, 1, 2, 3, 4, 5, 6, 7, 0, 0, 0, 0, 0, 0, 0, 0, 7, 6, 5, 4, 3, 2, 1, 0); | |
| 2325 | break; | |
| 1789 | sel = VEC_EL_2(EL, i); | |
| 1790 | s1 = (INT32)(INT16)VREG_S(VS1REG, i); | |
| 1791 | s2 = (INT32)(INT16)VREG_S(VS2REG, sel); | |
| 1792 | if (s1 == -32768 && s2 == -32768) | |
| 1793 | { | |
| 1794 | // overflow | |
| 1795 | ACCUM_H(i) = 0; | |
| 1796 | ACCUM_M(i) = -32768; | |
| 1797 | ACCUM_L(i) = -32768; | |
| 1798 | vres[i] = 0x7fff; | |
| 1799 | } | |
| 1800 | else | |
| 1801 | { | |
| 1802 | r = s1 * s2 * 2; | |
| 1803 | r += 0x8000; // rounding ? | |
| 1804 | ACCUM_H(i) = (r < 0) ? 0xffff : 0; // sign-extend to 48-bit | |
| 1805 | ACCUM_M(i) = (INT16)(r >> 16); | |
| 1806 | ACCUM_L(i) = (UINT16)(r); | |
| 1807 | vres[i] = ACCUM_M(i); | |
| 1808 | } | |
| 2326 | 1809 | } |
| 2327 | ||
| 2328 | 1810 | WRITEBACK_RESULT(); |
| 2329 | 1811 | } |
| 2330 | 1812 | |
| r9854 | r9855 | |
| 2340 | 1822 | // ------------------------------------------------------ |
| 2341 | 1823 | // |
| 2342 | 1824 | |
| 1825 | int sel; | |
| 1826 | INT32 s1, s2; | |
| 1827 | INT64 r; | |
| 2343 | 1828 | for (i=0; i < 8; i++) |
| 2344 | 1829 | { |
| 2345 | int del = VEC_EL_1(EL, i); | |
| 2346 | int sel = VEC_EL_2(EL, del); | |
| 2347 | INT32 s1 = (INT32)(INT16)R_VREG_S(VS1REG, del); | |
| 2348 | INT32 s2 = (INT32)(INT16)R_VREG_S(VS2REG, sel); | |
| 2349 | INT64 r = s1 * s2; | |
| 2350 | r += 0x4000; // rounding ? | |
| 1830 | sel = VEC_EL_2(EL, i); | |
| 1831 | s1 = (INT32)(INT16)VREG_S(VS1REG, i); | |
| 1832 | s2 = (INT32)(INT16)VREG_S(VS2REG, sel); | |
| 1833 | r = s1 * s2 * 2; | |
| 1834 | r += 0x8000; // rounding ? | |
| 2351 | 1835 | |
| 2352 | ACCUM(del).l = r << 17; | |
| 1836 | ACCUM_H(i) = (UINT16)(r >> 32); | |
| 1837 | ACCUM_M(i) = (UINT16)(r >> 16); | |
| 1838 | ACCUM_L(i) = (UINT16)(r); | |
| 2353 | 1839 | |
| 2354 | 1840 | if (r < 0) |
| 2355 | 1841 | { |
| 2356 | vres[ | |
| 1842 | vres[i | |
| 2357 | 1843 | } |
| 2358 | else if ((ACCUM( | |
| 1844 | else if (((INT16)(ACCUM_H( | |
| 2359 | 1845 | { |
| 2360 | vres[del] = -1; | |
| 2361 | ||
| 1846 | vres[i] = -1; | |
| 2362 | 1847 | } |
| 2363 | 1848 | else |
| 2364 | 1849 | { |
| 2365 | vres[ | |
| 1850 | vres[i | |
| 2366 | 1851 | } |
| 2367 | 1852 | } |
| 2368 | 1853 | WRITEBACK_RESULT(); |
| 2369 | 1854 | } |
| 2370 | 1855 | |
| 2371 | #if (DRC_VMUDL) | |
| 2372 | /*------------------------------------------------------------------ | |
| 2373 | generate_vmudl | |
| 2374 | ------------------------------------------------------------------*/ | |
| 2375 | ||
| 2376 | #define RSP_VMUDL_DRC(E10, E11, E12, E13, E14, E15, E16, E17, E20, E21, E22, E23, E24, E25, E26, E27, I0, I1, I2, I3, I4, I5, I6, I7) \ | |
| 2377 | { \ | |
| 2378 | UML_SEXT(block, IREG(1), VS(VS1REG, I0), WORD); \ | |
| 2379 | UML_SEXT(block, IREG(0), VS(VS2REG, E20), WORD); \ | |
| 2380 | UML_AND(block, IREG(0), IREG(0), IMM(0x0000ffff)); \ | |
| 2381 | UML_AND(block, IREG(1), IREG(1), IMM(0x0000ffff)); \ | |
| 2382 | UML_MULS(block, IREG(0), IREG(1), IREG(0), IREG(1)); \ | |
| 2383 | UML_DAND(block, IREG(0), IREG(0), IMM(0x00000000ffff0000)); \ | |
| 2384 | UML_DMOV(block, VACCUML(E10), IREG(0)); \ | |
| 2385 | \ | |
| 2386 | UML_SEXT(block, IREG(1), VS(VS1REG, I1), WORD); \ | |
| 2387 | UML_SEXT(block, IREG(0), VS(VS2REG, E21), WORD); \ | |
| 2388 | UML_AND(block, IREG(0), IREG(0), IMM(0x0000ffff)); \ | |
| 2389 | UML_AND(block, IREG(1), IREG(1), IMM(0x0000ffff)); \ | |
| 2390 | UML_MULS(block, IREG(0), IREG(1), IREG(0), IREG(1)); \ | |
| 2391 | UML_DAND(block, IREG(0), IREG(0), IMM(0x00000000ffff0000)); \ | |
| 2392 | UML_DMOV(block, VACCUML(E11), IREG(0)); \ | |
| 2393 | \ | |
| 2394 | UML_SEXT(block, IREG(1), VS(VS1REG, I2), WORD); \ | |
| 2395 | UML_SEXT(block, IREG(0), VS(VS2REG, E22), WORD); \ | |
| 2396 | UML_AND(block, IREG(0), IREG(0), IMM(0x0000ffff)); \ | |
| 2397 | UML_AND(block, IREG(1), IREG(1), IMM(0x0000ffff)); \ | |
| 2398 | UML_MULS(block, IREG(0), IREG(1), IREG(0), IREG(1)); \ | |
| 2399 | UML_DAND(block, IREG(0), IREG(0), IMM(0x00000000ffff0000)); \ | |
| 2400 | UML_DMOV(block, VACCUML(E12), IREG(0)); \ | |
| 2401 | \ | |
| 2402 | UML_SEXT(block, IREG(1), VS(VS1REG, I3), WORD); \ | |
| 2403 | UML_SEXT(block, IREG(0), VS(VS2REG, E23), WORD); \ | |
| 2404 | UML_AND(block, IREG(0), IREG(0), IMM(0x0000ffff)); \ | |
| 2405 | UML_AND(block, IREG(1), IREG(1), IMM(0x0000ffff)); \ | |
| 2406 | UML_MULS(block, IREG(0), IREG(1), IREG(0), IREG(1)); \ | |
| 2407 | UML_DAND(block, IREG(0), IREG(0), IMM(0x00000000ffff0000)); \ | |
| 2408 | UML_DMOV(block, VACCUML(E13), IREG(0)); \ | |
| 2409 | \ | |
| 2410 | UML_SEXT(block, IREG(1), VS(VS1REG, I4), WORD); \ | |
| 2411 | UML_SEXT(block, IREG(0), VS(VS2REG, E24), WORD); \ | |
| 2412 | UML_AND(block, IREG(0), IREG(0), IMM(0x0000ffff)); \ | |
| 2413 | UML_AND(block, IREG(1), IREG(1), IMM(0x0000ffff)); \ | |
| 2414 | UML_MULS(block, IREG(0), IREG(1), IREG(0), IREG(1)); \ | |
| 2415 | UML_DAND(block, IREG(0), IREG(0), IMM(0x00000000ffff0000)); \ | |
| 2416 | UML_DMOV(block, VACCUML(E14), IREG(0)); \ | |
| 2417 | \ | |
| 2418 | UML_SEXT(block, IREG(1), VS(VS1REG, I5), WORD); \ | |
| 2419 | UML_SEXT(block, IREG(0), VS(VS2REG, E25), WORD); \ | |
| 2420 | UML_AND(block, IREG(0), IREG(0), IMM(0x0000ffff)); \ | |
| 2421 | UML_AND(block, IREG(1), IREG(1), IMM(0x0000ffff)); \ | |
| 2422 | UML_MULS(block, IREG(0), IREG(1), IREG(0), IREG(1)); \ | |
| 2423 | UML_DAND(block, IREG(0), IREG(0), IMM(0x00000000ffff0000)); \ | |
| 2424 | UML_DMOV(block, VACCUML(E15), IREG(0)); \ | |
| 2425 | \ | |
| 2426 | UML_SEXT(block, IREG(1), VS(VS1REG, I6), WORD); \ | |
| 2427 | UML_SEXT(block, IREG(0), VS(VS2REG, E26), WORD); \ | |
| 2428 | UML_AND(block, IREG(0), IREG(0), IMM(0x0000ffff)); \ | |
| 2429 | UML_AND(block, IREG(1), IREG(1), IMM(0x0000ffff)); \ | |
| 2430 | UML_MULS(block, IREG(0), IREG(1), IREG(0), IREG(1)); \ | |
| 2431 | UML_DAND(block, IREG(0), IREG(0), IMM(0x00000000ffff0000)); \ | |
| 2432 | UML_DMOV(block, VACCUML(E16), IREG(0)); \ | |
| 2433 | \ | |
| 2434 | UML_SEXT(block, IREG(1), VS(VS1REG, I7), WORD); \ | |
| 2435 | UML_SEXT(block, IREG(0), VS(VS2REG, E27), WORD); \ | |
| 2436 | UML_AND(block, IREG(0), IREG(0), IMM(0x0000ffff)); \ | |
| 2437 | UML_AND(block, IREG(1), IREG(1), IMM(0x0000ffff)); \ | |
| 2438 | UML_MULS(block, IREG(0), IREG(1), IREG(0), IREG(1)); \ | |
| 2439 | UML_DAND(block, IREG(0), IREG(0), IMM(0x00000000ffff0000)); \ | |
| 2440 | UML_DMOV(block, VACCUML(E17), IREG(0)); \ | |
| 2441 | \ | |
| 2442 | UML_SEXT(block, IREG(0), VACCUMHL(E10), WORD); \ | |
| 2443 | UML_STORE(block, &rsp->v[VDREG].s[I0], IMM(0), IREG(0), WORD); \ | |
| 2444 | UML_SEXT(block, IREG(0), VACCUMHL(E11), WORD); \ | |
| 2445 | UML_STORE(block, &rsp->v[VDREG].s[I1], IMM(0), IREG(0), WORD); \ | |
| 2446 | UML_SEXT(block, IREG(0), VACCUMHL(E12), WORD); \ | |
| 2447 | UML_STORE(block, &rsp->v[VDREG].s[I2], IMM(0), IREG(0), WORD); \ | |
| 2448 | UML_SEXT(block, IREG(0), VACCUMHL(E13), WORD); \ | |
| 2449 | UML_STORE(block, &rsp->v[VDREG].s[I3], IMM(0), IREG(0), WORD); \ | |
| 2450 | UML_SEXT(block, IREG(0), VACCUMHL(E14), WORD); \ | |
| 2451 | UML_STORE(block, &rsp->v[VDREG].s[I4], IMM(0), IREG(0), WORD); \ | |
| 2452 | UML_SEXT(block, IREG(0), VACCUMHL(E15), WORD); \ | |
| 2453 | UML_STORE(block, &rsp->v[VDREG].s[I5], IMM(0), IREG(0), WORD); \ | |
| 2454 | UML_SEXT(block, IREG(0), VACCUMHL(E16), WORD); \ | |
| 2455 | UML_STORE(block, &rsp->v[VDREG].s[I6], IMM(0), IREG(0), WORD); \ | |
| 2456 | UML_SEXT(block, IREG(0), VACCUMHL(E17), WORD); \ | |
| 2457 | UML_STORE(block, &rsp->v[VDREG].s[I7], IMM(0), IREG(0), WORD); \ | |
| 2458 | } | |
| 2459 | ||
| 2460 | static int generate_vmudl(rsp_state *rsp, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) // vmudl | |
| 2461 | { | |
| 2462 | UINT32 op = desc->opptr.l[0]; | |
| 2463 | ||
| 2464 | // 31 25 24 20 15 10 5 0 | |
| 2465 | // ------------------------------------------------------ | |
| 2466 | // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 001110 | | |
| 2467 | // ------------------------------------------------------ | |
| 2468 | // | |
| 2469 | // Multiplies signed integer by unsigned fraction | |
| 2470 | // The result is added into accumulator | |
| 2471 | // The middle slice of accumulator is stored into destination element | |
| 2472 | switch(EL) | |
| 2473 | { | |
| 2474 | case 0: /* 0, 1, 2, 3, 4, 5, 6, 7 - none */ /* 0, 1, 2, 3, 4, 5, 6, 7 - none */ | |
| 2475 | RSP_VMUDL_DRC(0, 1, 2, 3, 4, 5, 6, 7, 7, 6, 5, 4, 3, 2, 1, 0, 7, 6, 5, 4, 3, 2, 1, 0); | |
| 2476 | return TRUE; | |
| 2477 | case 1: /* 0, 1, 2, 3, 4, 5, 6, 7 - ??? */ /* 0, 1, 2, 3, 4, 5, 6, 7 - ??? */ | |
| 2478 | RSP_VMUDL_DRC(0, 1, 2, 3, 4, 5, 6, 7, 7, 6, 5, 4, 3, 2, 1, 0, 7, 6, 5, 4, 3, 2, 1, 0); | |
| 2479 | return TRUE; | |
| 2480 | case 2: /* 1, 3, 5, 7, 0, 2, 4, 6 - 0q */ /* 0, 0, 2, 2, 4, 4, 6, 6 - 0q */ | |
| 2481 | RSP_VMUDL_DRC(1, 3, 5, 7, 0, 2, 4, 6, 7, 5, 3, 1, 7, 5, 3, 1, 6, 4, 2, 0, 7, 5, 3, 1); | |
| 2482 | return TRUE; | |
| 2483 | case 3: /* 0, 2, 4, 6, 1, 3, 5, 7 - 1q */ /* 1, 1, 3, 3, 5, 5, 7, 7 - 1q */ | |
| 2484 | RSP_VMUDL_DRC(0, 2, 4, 6, 1, 3, 5, 7, 6, 4, 2, 0, 6, 4, 2, 0, 7, 5, 3, 1, 6, 4, 2, 0); | |
| 2485 | return TRUE; | |
| 2486 | case 4: /* 1, 2, 3, 5, 6, 7, 0, 4 - 0h */ /* 0, 0, 0, 0, 4, 4, 4, 4 - 0h */ | |
| 2487 | RSP_VMUDL_DRC(1, 2, 3, 5, 6, 7, 0, 4, 7, 7, 7, 3, 3, 3, 7, 3, 6, 5, 4, 2, 1, 0, 7, 3); | |
| 2488 | return TRUE; | |
| 2489 | case 5: /* 0, 2, 3, 4, 6, 7, 1, 5 - 1h */ /* 1, 1, 1, 1, 5, 5, 5, 5 - 1h */ | |
| 2490 | RSP_VMUDL_DRC(0, 2, 3, 4, 6, 7, 1, 5, 6, 6, 6, 2, 2, 2, 6, 2, 7, 5, 4, 3, 1, 0, 6, 2); | |
| 2491 | return TRUE; | |
| 2492 | case 6: /* 0, 1, 3, 4, 5, 7, 2, 6 - 2h */ /* 2, 2, 2, 2, 6, 6, 6, 6 - 2h */ | |
| 2493 | RSP_VMUDL_DRC(0, 1, 3, 4, 5, 7, 2, 6, 5, 5, 5, 1, 1, 1, 5, 1, 7, 6, 4, 3, 2, 0, 5, 1); | |
| 2494 | return TRUE; | |
| 2495 | case 7: /* 0, 1, 2, 4, 5, 6, 3, 7 - 3h */ /* 3, 3, 3, 3, 7, 7, 7, 7 - 3h */ | |
| 2496 | RSP_VMUDL_DRC(0, 1, 2, 4, 5, 6, 3, 7, 4, 4, 4, 0, 0, 0, 4, 0, 7, 6, 5, 3, 2, 1, 4, 0); | |
| 2497 | return TRUE; | |
| 2498 | case 8: /* 1, 2, 3, 4, 5, 6, 7, 0 - 0 */ /* 0, 0, 0, 0, 0, 0, 0, 0 - 0 */ | |
| 2499 | RSP_VMUDL_DRC(1, 2, 3, 4, 5, 6, 7, 0, 7, 7, 7, 7, 7, 7, 7, 7, 6, 5, 4, 3, 2, 1, 0, 7); | |
| 2500 | return TRUE; | |
| 2501 | case 9: /* 0, 2, 3, 4, 5, 6, 7, 1 - 1 */ /* 1, 1, 1, 1, 1, 1, 1, 1 - 0 */ | |
| 2502 | RSP_VMUDL_DRC(0, 2, 3, 4, 5, 6, 7, 1, 6, 6, 6, 6, 6, 6, 6, 6, 7, 5, 4, 3, 2, 1, 0, 6); | |
| 2503 | return TRUE; | |
| 2504 | case 10: /* 0, 1, 3, 4, 5, 6, 7, 2 - 2 */ /* 2, 2, 2, 2, 2, 2, 2, 2 - 0 */ | |
| 2505 | RSP_VMUDL_DRC(0, 1, 3, 4, 5, 6, 7, 2, 5, 5, 5, 5, 5, 5, 5, 5, 7, 6, 4, 3, 2, 1, 0, 5); | |
| 2506 | return TRUE; | |
| 2507 | case 11: /* 0, 1, 2, 4, 5, 6, 7, 3 - 3 */ /* 3, 3, 3, 3, 3, 3, 3, 3 - 0 */ | |
| 2508 | RSP_VMUDL_DRC(0, 1, 2, 4, 5, 6, 7, 3, 4, 4, 4, 4, 4, 4, 4, 4, 7, 6, 5, 3, 2, 1, 0, 4); | |
| 2509 | return TRUE; | |
| 2510 | case 12: /* 0, 1, 2, 3, 5, 6, 7, 4 - 4 */ /* 4, 4, 4, 4, 4, 4, 4, 4 - 0 */ | |
| 2511 | RSP_VMUDL_DRC(0, 1, 2, 3, 5, 6, 7, 4, 3, 3, 3, 3, 3, 3, 3, 3, 7, 6, 5, 4, 2, 1, 0, 3); | |
| 2512 | return TRUE; | |
| 2513 | case 13: /* 0, 1, 2, 3, 4, 6, 7, 5 - 5 */ /* 5, 5, 5, 5, 5, 5, 5, 5 - 0 */ | |
| 2514 | RSP_VMUDL_DRC(0, 1, 2, 3, 4, 6, 7, 5, 2, 2, 2, 2, 2, 2, 2, 2, 7, 6, 5, 4, 3, 1, 0, 2); | |
| 2515 | return TRUE; | |
| 2516 | case 14: /* 0, 1, 2, 3, 4, 5, 7, 6 - 6 */ /* 6, 6, 6, 6, 6, 6, 6, 6 - 0 */ | |
| 2517 | RSP_VMUDL_DRC(0, 1, 2, 3, 4, 5, 7, 6, 1, 1, 1, 1, 1, 1, 1, 1, 7, 6, 5, 4, 3, 2, 0, 1); | |
| 2518 | return TRUE; | |
| 2519 | case 15: /* 0, 1, 2, 3, 4, 5, 6, 7 - 7 */ /* 7, 7, 7, 7, 7, 7, 7, 7 - 0 */ | |
| 2520 | RSP_VMUDL_DRC(0, 1, 2, 3, 4, 5, 6, 7, 0, 0, 0, 0, 0, 0, 0, 0, 7, 6, 5, 4, 3, 2, 1, 0); | |
| 2521 | return TRUE; | |
| 2522 | } | |
| 2523 | ||
| 2524 | return TRUE; | |
| 2525 | } | |
| 2526 | #else | |
| 2527 | #define RSP_VMUDL(E10, E11, E12, E13, E14, E15, E16, E17, E20, E21, E22, E23, E24, E25, E26, E27) \ | |
| 2528 | { \ | |
| 2529 | ACCUM(E10).l = (((UINT32)(UINT16)R_VREG_S(VS1REG, E10) * (UINT32)(UINT16)R_VREG_S(VS2REG, E20)) & 0xffff0000); \ | |
| 2530 | ACCUM(E11).l = (((UINT32)(UINT16)R_VREG_S(VS1REG, E11) * (UINT32)(UINT16)R_VREG_S(VS2REG, E21)) & 0xffff0000); \ | |
| 2531 | ACCUM(E12).l = (((UINT32)(UINT16)R_VREG_S(VS1REG, E12) * (UINT32)(UINT16)R_VREG_S(VS2REG, E22)) & 0xffff0000); \ | |
| 2532 | ACCUM(E13).l = (((UINT32)(UINT16)R_VREG_S(VS1REG, E13) * (UINT32)(UINT16)R_VREG_S(VS2REG, E23)) & 0xffff0000); \ | |
| 2533 | ACCUM(E14).l = (((UINT32)(UINT16)R_VREG_S(VS1REG, E14) * (UINT32)(UINT16)R_VREG_S(VS2REG, E24)) & 0xffff0000); \ | |
| 2534 | ACCUM(E15).l = (((UINT32)(UINT16)R_VREG_S(VS1REG, E15) * (UINT32)(UINT16)R_VREG_S(VS2REG, E25)) & 0xffff0000); \ | |
| 2535 | ACCUM(E16).l = (((UINT32)(UINT16)R_VREG_S(VS1REG, E16) * (UINT32)(UINT16)R_VREG_S(VS2REG, E26)) & 0xffff0000); \ | |
| 2536 | ACCUM(E17).l = (((UINT32)(UINT16)R_VREG_S(VS1REG, E17) * (UINT32)(UINT16)R_VREG_S(VS2REG, E27)) & 0xffff0000); \ | |
| 2537 | vres[E10] = ACCUM(E10).h.low; \ | |
| 2538 | vres[E11] = ACCUM(E11).h.low; \ | |
| 2539 | vres[E12] = ACCUM(E12).h.low; \ | |
| 2540 | vres[E13] = ACCUM(E13).h.low; \ | |
| 2541 | vres[E14] = ACCUM(E14).h.low; \ | |
| 2542 | vres[E15] = ACCUM(E15).h.low; \ | |
| 2543 | vres[E16] = ACCUM(E16).h.low; \ | |
| 2544 | vres[E17] = ACCUM(E17).h.low; \ | |
| 2545 | W_VREG_S_X(VDREG, 7, vres[0]); \ | |
| 2546 | W_VREG_S_X(VDREG, 6, vres[1]); \ | |
| 2547 | W_VREG_S_X(VDREG, 5, vres[2]); \ | |
| 2548 | W_VREG_S_X(VDREG, 4, vres[3]); \ | |
| 2549 | W_VREG_S_X(VDREG, 3, vres[4]); \ | |
| 2550 | W_VREG_S_X(VDREG, 2, vres[5]); \ | |
| 2551 | W_VREG_S_X(VDREG, 1, vres[6]); \ | |
| 2552 | W_VREG_S_X(VDREG, 0, vres[7]); \ | |
| 2553 | } | |
| 2554 | ||
| 2555 | 1856 | INLINE void cfunc_rsp_vmudl(void *param) |
| 2556 | 1857 | { |
| 2557 | 1858 | rsp_state *rsp = (rsp_state*)param; |
| r9854 | r9855 | |
| 2566 | 1867 | // The result is added into accumulator |
| 2567 | 1868 | // The middle slice of accumulator is stored into destination element |
| 2568 | 1869 | |
| 2569 | switch(EL) | |
| 1870 | int sel; | |
| 1871 | UINT32 s1, s2; | |
| 1872 | UINT32 r; | |
| 1873 | for (int i = 0; i < 8; i++) | |
| 2570 | 1874 | { |
| 2571 | case 0: /* 0, 1, 2, 3, 4, 5, 6, 7 - none */ /* 0, 1, 2, 3, 4, 5, 6, 7 - none */ | |
| 2572 | RSP_VMUDL(0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7); | |
| 2573 | break; | |
| 2574 | case 1: /* 0, 1, 2, 3, 4, 5, 6, 7 - ??? */ /* 0, 1, 2, 3, 4, 5, 6, 7 - ??? */ | |
| 2575 | RSP_VMUDL(0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7); | |
| 2576 | break; | |
| 2577 | case 2: /* 1, 3, 5, 7, 0, 2, 4, 6 - 0q */ /* 0, 0, 2, 2, 4, 4, 6, 6 - 0q */ | |
| 2578 | RSP_VMUDL(1, 3, 5, 7, 0, 2, 4, 6, 0, 2, 4, 6, 0, 2, 4, 6); | |
| 2579 | break; | |
| 2580 | case 3: /* 0, 2, 4, 6, 1, 3, 5, 7 - 1q */ /* 1, 1, 3, 3, 5, 5, 7, 7 - 1q */ | |
| 2581 | RSP_VMUDL(0, 2, 4, 6, 1, 3, 5, 7, 1, 3, 5, 7, 1, 3, 5, 7); | |
| 2582 | break; | |
| 2583 | case 4: /* 1, 2, 3, 5, 6, 7, 0, 4 - 0h */ /* 0, 0, 0, 0, 4, 4, 4, 4 - 0h */ | |
| 2584 | RSP_VMUDL(1, 2, 3, 5, 6, 7, 0, 4, 0, 0, 0, 4, 4, 4, 0, 4); | |
| 2585 | break; | |
| 2586 | case 5: /* 0, 2, 3, 4, 6, 7, 1, 5 - 1h */ /* 1, 1, 1, 1, 5, 5, 5, 5 - 1h */ | |
| 2587 | RSP_VMUDL(0, 2, 3, 4, 6, 7, 1, 5, 1, 1, 1, 5, 5, 5, 1, 5); | |
| 2588 | break; | |
| 2589 | case 6: /* 0, 1, 3, 4, 5, 7, 2, 6 - 2h */ /* 2, 2, 2, 2, 6, 6, 6, 6 - 2h */ | |
| 2590 | RSP_VMUDL(0, 1, 3, 4, 5, 7, 2, 6, 2, 2, 2, 6, 6, 6, 2, 6); | |
| 2591 | break; | |
| 2592 | case 7: /* 0, 1, 2, 4, 5, 6, 3, 7 - 3h */ /* 3, 3, 3, 3, 7, 7, 7, 7 - 3h */ | |
| 2593 | RSP_VMUDL(0, 1, 2, 4, 5, 6, 3, 7, 3, 3, 3, 7, 7, 7, 3, 7); | |
| 2594 | break; | |
| 2595 | case 8: /* 1, 2, 3, 4, 5, 6, 7, 0 - 0 */ /* 0, 0, 0, 0, 0, 0, 0, 0 - 0 */ | |
| 2596 | RSP_VMUDL(1, 2, 3, 4, 5, 6, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0); | |
| 2597 | break; | |
| 2598 | case 9: /* 0, 2, 3, 4, 5, 6, 7, 1 - 1 */ /* 1, 1, 1, 1, 1, 1, 1, 1 - 0 */ | |
| 2599 | RSP_VMUDL(0, 2, 3, 4, 5, 6, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1); | |
| 2600 | break; | |
| 2601 | case 10: /* 0, 1, 3, 4, 5, 6, 7, 2 - 2 */ /* 2, 2, 2, 2, 2, 2, 2, 2 - 0 */ | |
| 2602 | RSP_VMUDL(0, 1, 3, 4, 5, 6, 7, 2, 2, 2, 2, 2, 2, 2, 2, 2); | |
| 2603 | break; | |
| 2604 | case 11: /* 0, 1, 2, 4, 5, 6, 7, 3 - 3 */ /* 3, 3, 3, 3, 3, 3, 3, 3 - 0 */ | |
| 2605 | RSP_VMUDL(0, 1, 2, 4, 5, 6, 7, 3, 3, 3, 3, 3, 3, 3, 3, 3); | |
| 2606 | break; | |
| 2607 | case 12: /* 0, 1, 2, 3, 5, 6, 7, 4 - 4 */ /* 4, 4, 4, 4, 4, 4, 4, 4 - 0 */ | |
| 2608 | RSP_VMUDL(0, 1, 2, 3, 5, 6, 7, 4, 4, 4, 4, 4, 4, 4, 4, 4); | |
| 2609 | break; | |
| 2610 | case 13: /* 0, 1, 2, 3, 4, 6, 7, 5 - 5 */ /* 5, 5, 5, 5, 5, 5, 5, 5 - 0 */ | |
| 2611 | RSP_VMUDL(0, 1, 2, 3, 4, 6, 7, 5, 5, 5, 5, 5, 5, 5, 5, 5); | |
| 2612 | break; | |
| 2613 | case 14: /* 0, 1, 2, 3, 4, 5, 7, 6 - 6 */ /* 6, 6, 6, 6, 6, 6, 6, 6 - 0 */ | |
| 2614 | RSP_VMUDL(0, 1, 2, 3, 4, 5, 7, 6, 6, 6, 6, 6, 6, 6, 6, 6); | |
| 2615 | break; | |
| 2616 | case 15: /* 0, 1, 2, 3, 4, 5, 6, 7 - 7 */ /* 7, 7, 7, 7, 7, 7, 7, 7 - 0 */ | |
| 2617 | RSP_VMUDL(0, 1, 2, 3, 4, 5, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7); | |
| 2618 | break; | |
| 2619 | } | |
| 2620 | } | |
| 2621 | #endif | |
| 1875 | sel = VEC_EL_2(EL, i); | |
| 1876 | s1 = (UINT32)(UINT16)VREG_S(VS1REG, i); | |
| 1877 | s2 = (UINT32)(UINT16)VREG_S(VS2REG, sel); | |
| 1878 | r = s1 * s2; | |
| 2622 | 1879 | |
| 2623 | #if (DRC_VMUDM) | |
| 2624 | /*------------------------------------------------------------------ | |
| 2625 | generate_vmudm | |
| 2626 | ------------------------------------------------------------------*/ | |
| 1880 | ACCUM_H(i) = 0; | |
| 1881 | ACCUM_M(i) = 0; | |
| 1882 | ACCUM_L(i) = (UINT16)(r >> 16); | |
| 2627 | 1883 | |
| 2628 | #define RSP_VMUDM_DRC(E10, E11, E12, E13, E14, E15, E16, E17, E20, E21, E22, E23, E24, E25, E26, E27, I0, I1, I2, I3, I4, I5, I6, I7) \ | |
| 2629 | { \ | |
| 2630 | UML_SEXT(block, IREG(1), VS(VS1REG, I0), WORD); \ | |
| 2631 | UML_SEXT(block, IREG(0), VS(VS2REG, E20), WORD); \ | |
| 2632 | UML_AND(block, IREG(0), IREG(0), IMM(0x0000ffff)); \ | |
| 2633 | UML_MULS(block, IREG(0), IREG(1), IREG(0), IREG(1)); \ | |
| 2634 | UML_DSEXT(block, IREG(0), IREG(0), DWORD); \ | |
| 2635 | UML_DSHL(block, IREG(0), IREG(0), IMM(16)); \ | |
| 2636 | UML_DMOV(block, VACCUML(E10), IREG(0)); \ | |
| 2637 | \ | |
| 2638 | UML_SEXT(block, IREG(1), VS(VS1REG, I1), WORD); \ | |
| 2639 | UML_SEXT(block, IREG(0), VS(VS2REG, E21), WORD); \ | |
| 2640 | UML_AND(block, IREG(0), IREG(0), IMM(0x0000ffff)); \ | |
| 2641 | UML_MULS(block, IREG(0), IREG(1), IREG(0), IREG(1)); \ | |
| 2642 | UML_DSEXT(block, IREG(0), IREG(0), DWORD); \ | |
| 2643 | UML_DSHL(block, IREG(0), IREG(0), IMM(16)); \ | |
| 2644 | UML_DMOV(block, VACCUML(E11), IREG(0)); \ | |
| 2645 | \ | |
| 2646 | UML_SEXT(block, IREG(1), VS(VS1REG, I2), WORD); \ | |
| 2647 | UML_SEXT(block, IREG(0), VS(VS2REG, E22), WORD); \ | |
| 2648 | UML_AND(block, IREG(0), IREG(0), IMM(0x0000ffff)); \ | |
| 2649 | UML_MULS(block, IREG(0), IREG(1), IREG(0), IREG(1)); \ | |
| 2650 | UML_DSEXT(block, IREG(0), IREG(0), DWORD); \ | |
| 2651 | UML_DSHL(block, IREG(0), IREG(0), IMM(16)); \ | |
| 2652 | UML_DMOV(block, VACCUML(E12), IREG(0)); \ | |
| 2653 | \ | |
| 2654 | UML_SEXT(block, IREG(1), VS(VS1REG, I3), WORD); \ | |
| 2655 | UML_SEXT(block, IREG(0), VS(VS2REG, E23), WORD); \ | |
| 2656 | UML_AND(block, IREG(0), IREG(0), IMM(0x0000ffff)); \ | |
| 2657 | UML_MULS(block, IREG(0), IREG(1), IREG(0), IREG(1)); \ | |
| 2658 | UML_DSEXT(block, IREG(0), IREG(0), DWORD); \ | |
| 2659 | UML_DSHL(block, IREG(0), IREG(0), IMM(16)); \ | |
| 2660 | UML_DMOV(block, VACCUML(E13), IREG(0)); \ | |
| 2661 | \ | |
| 2662 | UML_SEXT(block, IREG(1), VS(VS1REG, I4), WORD); \ | |
| 2663 | UML_SEXT(block, IREG(0), VS(VS2REG, E24), WORD); \ | |
| 2664 | UML_AND(block, IREG(0), IREG(0), IMM(0x0000ffff)); \ | |
| 2665 | UML_MULS(block, IREG(0), IREG(1), IREG(0), IREG(1)); \ | |
| 2666 | UML_DSEXT(block, IREG(0), IREG(0), DWORD); \ | |
| 2667 | UML_DSHL(block, IREG(0), IREG(0), IMM(16)); \ | |
| 2668 | UML_DMOV(block, VACCUML(E14), IREG(0)); \ | |
| 2669 | \ | |
| 2670 | UML_SEXT(block, IREG(1), VS(VS1REG, I5), WORD); \ | |
| 2671 | UML_SEXT(block, IREG(0), VS(VS2REG, E25), WORD); \ | |
| 2672 | UML_AND(block, IREG(0), IREG(0), IMM(0x0000ffff)); \ | |
| 2673 | UML_MULS(block, IREG(0), IREG(1), IREG(0), IREG(1)); \ | |
| 2674 | UML_DSEXT(block, IREG(0), IREG(0), DWORD); \ | |
| 2675 | UML_DSHL(block, IREG(0), IREG(0), IMM(16)); \ | |
| 2676 | UML_DMOV(block, VACCUML(E15), IREG(0)); \ | |
| 2677 | \ | |
| 2678 | UML_SEXT(block, IREG(1), VS(VS1REG, I6), WORD); \ | |
| 2679 | UML_SEXT(block, IREG(0), VS(VS2REG, E26), WORD); \ | |
| 2680 | UML_AND(block, IREG(0), IREG(0), IMM(0x0000ffff)); \ | |
| 2681 | UML_MULS(block, IREG(0), IREG(1), IREG(0), IREG(1)); \ | |
| 2682 | UML_DSEXT(block, IREG(0), IREG(0), DWORD); \ | |
| 2683 | UML_DSHL(block, IREG(0), IREG(0), IMM(16)); \ | |
| 2684 | UML_DMOV(block, VACCUML(E16), IREG(0)); \ | |
| 2685 | \ | |
| 2686 | UML_SEXT(block, IREG(1), VS(VS1REG, I7), WORD); \ | |
| 2687 | UML_SEXT(block, IREG(0), VS(VS2REG, E27), WORD); \ | |
| 2688 | UML_AND(block, IREG(0), IREG(0), IMM(0x0000ffff)); \ | |
| 2689 | UML_MULS(block, IREG(0), IREG(1), IREG(0), IREG(1)); \ | |
| 2690 | UML_DSEXT(block, IREG(0), IREG(0), DWORD); \ | |
| 2691 | UML_DSHL(block, IREG(0), IREG(0), IMM(16)); \ | |
| 2692 | UML_DMOV(block, VACCUML(E17), IREG(0)); \ | |
| 2693 | \ | |
| 2694 | UML_SEXT(block, IREG(0), VACCUMHM(E10), WORD); \ | |
| 2695 | UML_STORE(block, &rsp->v[VDREG].s[I0], IMM(0), IREG(0), WORD); \ | |
| 2696 | UML_SEXT(block, IREG(0), VACCUMHM(E11), WORD); \ | |
| 2697 | UML_STORE(block, &rsp->v[VDREG].s[I1], IMM(0), IREG(0), WORD); \ | |
| 2698 | UML_SEXT(block, IREG(0), VACCUMHM(E12), WORD); \ | |
| 2699 | UML_STORE(block, &rsp->v[VDREG].s[I2], IMM(0), IREG(0), WORD); \ | |
| 2700 | UML_SEXT(block, IREG(0), VACCUMHM(E13), WORD); \ | |
| 2701 | UML_STORE(block, &rsp->v[VDREG].s[I3], IMM(0), IREG(0), WORD); \ | |
| 2702 | UML_SEXT(block, IREG(0), VACCUMHM(E14), WORD); \ | |
| 2703 | UML_STORE(block, &rsp->v[VDREG].s[I4], IMM(0), IREG(0), WORD); \ | |
| 2704 | UML_SEXT(block, IREG(0), VACCUMHM(E15), WORD); \ | |
| 2705 | UML_STORE(block, &rsp->v[VDREG].s[I5], IMM(0), IREG(0), WORD); \ | |
| 2706 | UML_SEXT(block, IREG(0), VACCUMHM(E16), WORD); \ | |
| 2707 | UML_STORE(block, &rsp->v[VDREG].s[I6], IMM(0), IREG(0), WORD); \ | |
| 2708 | UML_SEXT(block, IREG(0), VACCUMHM(E17), WORD); \ | |
| 2709 | UML_STORE(block, &rsp->v[VDREG].s[I7], IMM(0), IREG(0), WORD); \ | |
| 1884 | vres[i] = ACCUM_L(i); | |
| 2710 | 1885 | } |
| 2711 | ||
| 2712 | static int generate_vmudm(rsp_state *rsp, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) // vmudl | |
| 2713 | { | |
| 2714 | UINT32 op = desc->opptr.l[0]; | |
| 2715 | ||
| 2716 | // 31 25 24 20 15 10 5 0 | |
| 2717 | // ------------------------------------------------------ | |
| 2718 | // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 001110 | | |
| 2719 | // ------------------------------------------------------ | |
| 2720 | // | |
| 2721 | // Multiplies signed integer by unsigned fraction | |
| 2722 | // The result is stored into accumulator | |
| 2723 | // The middle slice of accumulator is stored into destination element | |
| 2724 | switch(EL) | |
| 2725 | { | |
| 2726 | case 0: /* 0, 1, 2, 3, 4, 5, 6, 7 - none */ /* 0, 1, 2, 3, 4, 5, 6, 7 - none */ | |
| 2727 | RSP_VMUDM_DRC(0, 1, 2, 3, 4, 5, 6, 7, 7, 6, 5, 4, 3, 2, 1, 0, 7, 6, 5, 4, 3, 2, 1, 0); | |
| 2728 | return TRUE; | |
| 2729 | case 1: /* 0, 1, 2, 3, 4, 5, 6, 7 - ??? */ /* 0, 1, 2, 3, 4, 5, 6, 7 - ??? */ | |
| 2730 | RSP_VMUDM_DRC(0, 1, 2, 3, 4, 5, 6, 7, 7, 6, 5, 4, 3, 2, 1, 0, 7, 6, 5, 4, 3, 2, 1, 0); | |
| 2731 | return TRUE; | |
| 2732 | case 2: /* 1, 3, 5, 7, 0, 2, 4, 6 - 0q */ /* 0, 0, 2, 2, 4, 4, 6, 6 - 0q */ | |
| 2733 | RSP_VMUDM_DRC(1, 3, 5, 7, 0, 2, 4, 6, 7, 5, 3, 1, 7, 5, 3, 1, 6, 4, 2, 0, 7, 5, 3, 1); | |
| 2734 | return TRUE; | |
| 2735 | case 3: /* 0, 2, 4, 6, 1, 3, 5, 7 - 1q */ /* 1, 1, 3, 3, 5, 5, 7, 7 - 1q */ | |
| 2736 | RSP_VMUDM_DRC(0, 2, 4, 6, 1, 3, 5, 7, 6, 4, 2, 0, 6, 4, 2, 0, 7, 5, 3, 1, 6, 4, 2, 0); | |
| 2737 | return TRUE; | |
| 2738 | case 4: /* 1, 2, 3, 5, 6, 7, 0, 4 - 0h */ /* 0, 0, 0, 0, 4, 4, 4, 4 - 0h */ | |
| 2739 | RSP_VMUDM_DRC(1, 2, 3, 5, 6, 7, 0, 4, 7, 7, 7, 3, 3, 3, 7, 3, 6, 5, 4, 2, 1, 0, 7, 3); | |
| 2740 | return TRUE; | |
| 2741 | case 5: /* 0, 2, 3, 4, 6, 7, 1, 5 - 1h */ /* 1, 1, 1, 1, 5, 5, 5, 5 - 1h */ | |
| 2742 | RSP_VMUDM_DRC(0, 2, 3, 4, 6, 7, 1, 5, 6, 6, 6, 2, 2, 2, 6, 2, 7, 5, 4, 3, 1, 0, 6, 2); | |
| 2743 | return TRUE; | |
| 2744 | case 6: /* 0, 1, 3, 4, 5, 7, 2, 6 - 2h */ /* 2, 2, 2, 2, 6, 6, 6, 6 - 2h */ | |
| 2745 | RSP_VMUDM_DRC(0, 1, 3, 4, 5, 7, 2, 6, 5, 5, 5, 1, 1, 1, 5, 1, 7, 6, 4, 3, 2, 0, 5, 1); | |
| 2746 | return TRUE; | |
| 2747 | case 7: /* 0, 1, 2, 4, 5, 6, 3, 7 - 3h */ /* 3, 3, 3, 3, 7, 7, 7, 7 - 3h */ | |
| 2748 | RSP_VMUDM_DRC(0, 1, 2, 4, 5, 6, 3, 7, 4, 4, 4, 0, 0, 0, 4, 0, 7, 6, 5, 3, 2, 1, 4, 0); | |
| 2749 | return TRUE; | |
| 2750 | case 8: /* 1, 2, 3, 4, 5, 6, 7, 0 - 0 */ /* 0, 0, 0, 0, 0, 0, 0, 0 - 0 */ | |
| 2751 | RSP_VMUDM_DRC(1, 2, 3, 4, 5, 6, 7, 0, 7, 7, 7, 7, 7, 7, 7, 7, 6, 5, 4, 3, 2, 1, 0, 7); | |
| 2752 | return TRUE; | |
| 2753 | case 9: /* 0, 2, 3, 4, 5, 6, 7, 1 - 1 */ /* 1, 1, 1, 1, 1, 1, 1, 1 - 0 */ | |
| 2754 | RSP_VMUDM_DRC(0, 2, 3, 4, 5, 6, 7, 1, 6, 6, 6, 6, 6, 6, 6, 6, 7, 5, 4, 3, 2, 1, 0, 6); | |
| 2755 | return TRUE; | |
| 2756 | case 10: /* 0, 1, 3, 4, 5, 6, 7, 2 - 2 */ /* 2, 2, 2, 2, 2, 2, 2, 2 - 0 */ | |
| 2757 | RSP_VMUDM_DRC(0, 1, 3, 4, 5, 6, 7, 2, 5, 5, 5, 5, 5, 5, 5, 5, 7, 6, 4, 3, 2, 1, 0, 5); | |
| 2758 | return TRUE; | |
| 2759 | case 11: /* 0, 1, 2, 4, 5, 6, 7, 3 - 3 */ /* 3, 3, 3, 3, 3, 3, 3, 3 - 0 */ | |
| 2760 | RSP_VMUDM_DRC(0, 1, 2, 4, 5, 6, 7, 3, 4, 4, 4, 4, 4, 4, 4, 4, 7, 6, 5, 3, 2, 1, 0, 4); | |
| 2761 | return TRUE; | |
| 2762 | case 12: /* 0, 1, 2, 3, 5, 6, 7, 4 - 4 */ /* 4, 4, 4, 4, 4, 4, 4, 4 - 0 */ | |
| 2763 | RSP_VMUDM_DRC(0, 1, 2, 3, 5, 6, 7, 4, 3, 3, 3, 3, 3, 3, 3, 3, 7, 6, 5, 4, 2, 1, 0, 3); | |
| 2764 | return TRUE; | |
| 2765 | case 13: /* 0, 1, 2, 3, 4, 6, 7, 5 - 5 */ /* 5, 5, 5, 5, 5, 5, 5, 5 - 0 */ | |
| 2766 | RSP_VMUDM_DRC(0, 1, 2, 3, 4, 6, 7, 5, 2, 2, 2, 2, 2, 2, 2, 2, 7, 6, 5, 4, 3, 1, 0, 2); | |
| 2767 | return TRUE; | |
| 2768 | case 14: /* 0, 1, 2, 3, 4, 5, 7, 6 - 6 */ /* 6, 6, 6, 6, 6, 6, 6, 6 - 0 */ | |
| 2769 | RSP_VMUDM_DRC(0, 1, 2, 3, 4, 5, 7, 6, 1, 1, 1, 1, 1, 1, 1, 1, 7, 6, 5, 4, 3, 2, 0, 1); | |
| 2770 | return TRUE; | |
| 2771 | case 15: /* 0, 1, 2, 3, 4, 5, 6, 7 - 7 */ /* 7, 7, 7, 7, 7, 7, 7, 7 - 0 */ | |
| 2772 | RSP_VMUDM_DRC(0, 1, 2, 3, 4, 5, 6, 7, 0, 0, 0, 0, 0, 0, 0, 0, 7, 6, 5, 4, 3, 2, 1, 0); | |
| 2773 | return TRUE; | |
| 2774 | } | |
| 2775 | ||
| 2776 | return TRUE; | |
| 1886 | WRITEBACK_RESULT(); | |
| 2777 | 1887 | } |
| 2778 | #else | |
| 2779 | #define RSP_VMUDM(E10, E11, E12, E13, E14, E15, E16, E17, E20, E21, E22, E23, E24, E25, E26, E27, I0, I1, I2, I3, I4, I5, I6, I7) \ | |
| 2780 | { \ | |
| 2781 | ACCUM(E10).l = (INT64)((INT32)(INT16)R_VREG_S_X(VS1REG, I0) * (UINT16)R_VREG_S_X(VS2REG, E20)) << 16; \ | |
| 2782 | ACCUM(E11).l = (INT64)((INT32)(INT16)R_VREG_S_X(VS1REG, I1) * (UINT16)R_VREG_S_X(VS2REG, E21)) << 16; \ | |
| 2783 | ACCUM(E12).l = (INT64)((INT32)(INT16)R_VREG_S_X(VS1REG, I2) * (UINT16)R_VREG_S_X(VS2REG, E22)) << 16; \ | |
| 2784 | ACCUM(E13).l = (INT64)((INT32)(INT16)R_VREG_S_X(VS1REG, I3) * (UINT16)R_VREG_S_X(VS2REG, E23)) << 16; \ | |
| 2785 | ACCUM(E14).l = (INT64)((INT32)(INT16)R_VREG_S_X(VS1REG, I4) * (UINT16)R_VREG_S_X(VS2REG, E24)) << 16; \ | |
| 2786 | ACCUM(E15).l = (INT64)((INT32)(INT16)R_VREG_S_X(VS1REG, I5) * (UINT16)R_VREG_S_X(VS2REG, E25)) << 16; \ | |
| 2787 | ACCUM(E16).l = (INT64)((INT32)(INT16)R_VREG_S_X(VS1REG, I6) * (UINT16)R_VREG_S_X(VS2REG, E26)) << 16; \ | |
| 2788 | ACCUM(E17).l = (INT64)((INT32)(INT16)R_VREG_S_X(VS1REG, I7) * (UINT16)R_VREG_S_X(VS2REG, E27)) << 16; \ | |
| 2789 | vres[E10] = ACCUM(E10).h.mid; \ | |
| 2790 | vres[E11] = ACCUM(E11).h.mid; \ | |
| 2791 | vres[E12] = ACCUM(E12).h.mid; \ | |
| 2792 | vres[E13] = ACCUM(E13).h.mid; \ | |
| 2793 | vres[E14] = ACCUM(E14).h.mid; \ | |
| 2794 | vres[E15] = ACCUM(E15).h.mid; \ | |
| 2795 | vres[E16] = ACCUM(E16).h.mid; \ | |
| 2796 | vres[E17] = ACCUM(E17).h.mid; \ | |
| 2797 | W_VREG_S_X(VDREG, 7, vres[0]); \ | |
| 2798 | W_VREG_S_X(VDREG, 6, vres[1]); \ | |
| 2799 | W_VREG_S_X(VDREG, 5, vres[2]); \ | |
| 2800 | W_VREG_S_X(VDREG, 4, vres[3]); \ | |
| 2801 | W_VREG_S_X(VDREG, 3, vres[4]); \ | |
| 2802 | W_VREG_S_X(VDREG, 2, vres[5]); \ | |
| 2803 | W_VREG_S_X(VDREG, 1, vres[6]); \ | |
| 2804 | W_VREG_S_X(VDREG, 0, vres[7]); \ | |
| 2805 | } | |
| 2806 | 1888 | |
| 2807 | 1889 | INLINE void cfunc_rsp_vmudm(void *param) |
| 2808 | 1890 | { |
| r9854 | r9855 | |
| 2819 | 1901 | // The result is stored into accumulator |
| 2820 | 1902 | // The middle slice of accumulator is stored into destination element |
| 2821 | 1903 | |
| 2822 | switch(EL) | |
| 1904 | int sel; | |
| 1905 | INT32 s1, s2; | |
| 1906 | INT32 r; | |
| 1907 | for (int i = 0; i < 8; i++) | |
| 2823 | 1908 | { |
| 2824 | case 0: /* 0, 1, 2, 3, 4, 5, 6, 7 - none */ /* 0, 1, 2, 3, 4, 5, 6, 7 - none */ | |
| 2825 | RSP_VMUDM(0, 1, 2, 3, 4, 5, 6, 7, 7, 6, 5, 4, 3, 2, 1, 0, 7, 6, 5, 4, 3, 2, 1, 0); | |
| 2826 | break; | |
| 2827 | case 1: /* 0, 1, 2, 3, 4, 5, 6, 7 - ??? */ /* 0, 1, 2, 3, 4, 5, 6, 7 - ??? */ | |
| 2828 | RSP_VMUDM(0, 1, 2, 3, 4, 5, 6, 7, 7, 6, 5, 4, 3, 2, 1, 0, 7, 6, 5, 4, 3, 2, 1, 0); | |
| 2829 | break; | |
| 2830 | case 2: /* 1, 3, 5, 7, 0, 2, 4, 6 - 0q */ /* 0, 0, 2, 2, 4, 4, 6, 6 - 0q */ | |
| 2831 | RSP_VMUDM(1, 3, 5, 7, 0, 2, 4, 6, 7, 5, 3, 1, 7, 5, 3, 1, 6, 4, 2, 0, 7, 5, 3, 1); | |
| 2832 | break; | |
| 2833 | case 3: /* 0, 2, 4, 6, 1, 3, 5, 7 - 1q */ /* 1, 1, 3, 3, 5, 5, 7, 7 - 1q */ | |
| 2834 | RSP_VMUDM(0, 2, 4, 6, 1, 3, 5, 7, 6, 4, 2, 0, 6, 4, 2, 0, 7, 5, 3, 1, 6, 4, 2, 0); | |
| 2835 | break; | |
| 2836 | case 4: /* 1, 2, 3, 5, 6, 7, 0, 4 - 0h */ /* 0, 0, 0, 0, 4, 4, 4, 4 - 0h */ | |
| 2837 | RSP_VMUDM(1, 2, 3, 5, 6, 7, 0, 4, 7, 7, 7, 3, 3, 3, 7, 3, 6, 5, 4, 2, 1, 0, 7, 3); | |
| 2838 | break; | |
| 2839 | case 5: /* 0, 2, 3, 4, 6, 7, 1, 5 - 1h */ /* 1, 1, 1, 1, 5, 5, 5, 5 - 1h */ | |
| 2840 | RSP_VMUDM(0, 2, 3, 4, 6, 7, 1, 5, 6, 6, 6, 2, 2, 2, 6, 2, 7, 5, 4, 3, 1, 0, 6, 2); | |
| 2841 | break; | |
| 2842 | case 6: /* 0, 1, 3, 4, 5, 7, 2, 6 - 2h */ /* 2, 2, 2, 2, 6, 6, 6, 6 - 2h */ | |
| 2843 | RSP_VMUDM(0, 1, 3, 4, 5, 7, 2, 6, 5, 5, 5, 1, 1, 1, 5, 1, 7, 6, 4, 3, 2, 0, 5, 1); | |
| 2844 | break; | |
| 2845 | case 7: /* 0, 1, 2, 4, 5, 6, 3, 7 - 3h */ /* 3, 3, 3, 3, 7, 7, 7, 7 - 3h */ | |
| 2846 | RSP_VMUDM(0, 1, 2, 4, 5, 6, 3, 7, 4, 4, 4, 0, 0, 0, 4, 0, 7, 6, 5, 3, 2, 1, 4, 0); | |
| 2847 | break; | |
| 2848 | case 8: /* 1, 2, 3, 4, 5, 6, 7, 0 - 0 */ /* 0, 0, 0, 0, 0, 0, 0, 0 - 0 */ | |
| 2849 | RSP_VMUDM(1, 2, 3, 4, 5, 6, 7, 0, 7, 7, 7, 7, 7, 7, 7, 7, 6, 5, 4, 3, 2, 1, 0, 7); | |
| 2850 | break; | |
| 2851 | case 9: /* 0, 2, 3, 4, 5, 6, 7, 1 - 1 */ /* 1, 1, 1, 1, 1, 1, 1, 1 - 0 */ | |
| 2852 | RSP_VMUDM(0, 2, 3, 4, 5, 6, 7, 1, 6, 6, 6, 6, 6, 6, 6, 6, 7, 5, 4, 3, 2, 1, 0, 6); | |
| 2853 | break; | |
| 2854 | case 10: /* 0, 1, 3, 4, 5, 6, 7, 2 - 2 */ /* 2, 2, 2, 2, 2, 2, 2, 2 - 0 */ | |
| 2855 | RSP_VMUDM(0, 1, 3, 4, 5, 6, 7, 2, 5, 5, 5, 5, 5, 5, 5, 5, 7, 6, 4, 3, 2, 1, 0, 5); | |
| 2856 | break; | |
| 2857 | case 11: /* 0, 1, 2, 4, 5, 6, 7, 3 - 3 */ /* 3, 3, 3, 3, 3, 3, 3, 3 - 0 */ | |
| 2858 | RSP_VMUDM(0, 1, 2, 4, 5, 6, 7, 3, 4, 4, 4, 4, 4, 4, 4, 4, 7, 6, 5, 3, 2, 1, 0, 4); | |
| 2859 | break; | |
| 2860 | case 12: /* 0, 1, 2, 3, 5, 6, 7, 4 - 4 */ /* 4, 4, 4, 4, 4, 4, 4, 4 - 0 */ | |
| 2861 | RSP_VMUDM(0, 1, 2, 3, 5, 6, 7, 4, 3, 3, 3, 3, 3, 3, 3, 3, 7, 6, 5, 4, 2, 1, 0, 3); | |
| 2862 | break; | |
| 2863 | case 13: /* 0, 1, 2, 3, 4, 6, 7, 5 - 5 */ /* 5, 5, 5, 5, 5, 5, 5, 5 - 0 */ | |
| 2864 | RSP_VMUDM(0, 1, 2, 3, 4, 6, 7, 5, 2, 2, 2, 2, 2, 2, 2, 2, 7, 6, 5, 4, 3, 1, 0, 2); | |
| 2865 | break; | |
| 2866 | case 14: /* 0, 1, 2, 3, 4, 5, 7, 6 - 6 */ /* 6, 6, 6, 6, 6, 6, 6, 6 - 0 */ | |
| 2867 | RSP_VMUDM(0, 1, 2, 3, 4, 5, 7, 6, 1, 1, 1, 1, 1, 1, 1, 1, 7, 6, 5, 4, 3, 2, 0, 1); | |
| 2868 | break; | |
| 2869 | case 15: /* 0, 1, 2, 3, 4, 5, 6, 7 - 7 */ /* 7, 7, 7, 7, 7, 7, 7, 7 - 0 */ | |
| 2870 | RSP_VMUDM(0, 1, 2, 3, 4, 5, 6, 7, 0, 0, 0, 0, 0, 0, 0, 0, 7, 6, 5, 4, 3, 2, 1, 0); | |
| 2871 | break; | |
| 2872 | } | |
| 1909 | sel = VEC_EL_2(EL, i); | |
| 1910 | s1 = (INT32)(INT16)VREG_S(VS1REG, i); | |
| 1911 | s2 = (UINT16)VREG_S(VS2REG, sel); // not sign-extended | |
| 1912 | r = s1 * s2; | |
| 2873 | 1913 | |
| 2874 | #ifdef UNUSED_CODE | |
| 2875 | for (i=0; i < 8; i++) | |
| 2876 | { | |
| 2877 | int del = VEC_EL_1(EL, i); | |
| 2878 | int sel = VEC_EL_2(EL, del); | |
| 2879 | INT32 s1 = (INT32)(INT16)R_VREG_S(VS1REG, del); | |
| 2880 | INT32 s2 = (UINT16)R_VREG_S(VS2REG, sel); // not sign-extended | |
| 2881 | INT32 r = s1 * s2; | |
| 1914 | ACCUM_H(i) = (r < 0) ? 0xffff : 0; // sign-extend to 48-bit | |
| 1915 | ACCUM_M(i) = (INT16)(r >> 16); | |
| 1916 | ACCUM_L(i) = (UINT16)(r); | |
| 2882 | 1917 | |
| 2883 | W_ACCUM_H(del, (r < 0) ? 0xffff : 0); // sign-extend to 48-bit | |
| 2884 | W_ACCUM_M(del, (INT16)(r >> 16)); | |
| 2885 | W_ACCUM_L(del, (UINT16)(r)); | |
| 2886 | ||
| 2887 | vres[del] = ACCUM(del).h.mid; | |
| 1918 | vres[i] = ACCUM_M(i); | |
| 2888 | 1919 | } |
| 2889 | 1920 | WRITEBACK_RESULT(); |
| 2890 | #endif | |
| 2891 | 1921 | } |
| 2892 | #endif | |
| 2893 | 1922 | |
| 2894 | #define RSP_VMUDN(E10, E11, E12, E13, E14, E15, E16, E17, E20, E21, E22, E23, E24, E25, E26, E27) \ | |
| 2895 | { \ | |
| 2896 | ACCUM(E10).l = ((UINT16)R_VREG_S(VS1REG, E10) * (INT64)(INT16)R_VREG_S(VS2REG, E20)) << 16; \ | |
| 2897 | ACCUM(E11).l = ((UINT16)R_VREG_S(VS1REG, E11) * (INT64)(INT16)R_VREG_S(VS2REG, E21)) << 16; \ | |
| 2898 | ACCUM(E12).l = ((UINT16)R_VREG_S(VS1REG, E12) * (INT64)(INT16)R_VREG_S(VS2REG, E22)) << 16; \ | |
| 2899 | ACCUM(E13).l = ((UINT16)R_VREG_S(VS1REG, E13) * (INT64)(INT16)R_VREG_S(VS2REG, E23)) << 16; \ | |
| 2900 | ACCUM(E14).l = ((UINT16)R_VREG_S(VS1REG, E14) * (INT64)(INT16)R_VREG_S(VS2REG, E24)) << 16; \ | |
| 2901 | ACCUM(E15).l = ((UINT16)R_VREG_S(VS1REG, E15) * (INT64)(INT16)R_VREG_S(VS2REG, E25)) << 16; \ | |
| 2902 | ACCUM(E16).l = ((UINT16)R_VREG_S(VS1REG, E16) * (INT64)(INT16)R_VREG_S(VS2REG, E26)) << 16; \ | |
| 2903 | ACCUM(E17).l = ((UINT16)R_VREG_S(VS1REG, E17) * (INT64)(INT16)R_VREG_S(VS2REG, E27)) << 16; \ | |
| 2904 | W_VREG_S(VDREG, E10, ACCUM(E10).h.low); \ | |
| 2905 | W_VREG_S(VDREG, E11, ACCUM(E11).h.low); \ | |
| 2906 | W_VREG_S(VDREG, E12, ACCUM(E12).h.low); \ | |
| 2907 | W_VREG_S(VDREG, E13, ACCUM(E13).h.low); \ | |
| 2908 | W_VREG_S(VDREG, E14, ACCUM(E14).h.low); \ | |
| 2909 | W_VREG_S(VDREG, E15, ACCUM(E15).h.low); \ | |
| 2910 | W_VREG_S(VDREG, E16, ACCUM(E16).h.low); \ | |
| 2911 | W_VREG_S(VDREG, E17, ACCUM(E17).h.low); \ | |
| 2912 | } | |
| 2913 | ||
| 2914 | 1923 | INLINE void cfunc_rsp_vmudn(void *param) |
| 2915 | 1924 | { |
| 2916 | 1925 | rsp_state *rsp = (rsp_state*)param; |
| 2917 | 1926 | int op = rsp->impstate->arg0; |
| 1927 | INT16 vres[8] = { 0 }; | |
| 1928 | ||
| 2918 | 1929 | // 31 25 24 20 15 10 5 0 |
| 2919 | 1930 | // ------------------------------------------------------ |
| 2920 | 1931 | // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 000110 | |
| r9854 | r9855 | |
| 2924 | 1935 | // The result is stored into accumulator |
| 2925 | 1936 | // The low slice of accumulator is stored into destination element |
| 2926 | 1937 | |
| 2927 | switch(EL) | |
| 1938 | int sel; | |
| 1939 | INT32 s1, s2; | |
| 1940 | INT32 r; | |
| 1941 | for (int i = 0; i < 8; i++) | |
| 2928 | 1942 | { |
| 2929 | case 0: /* 0, 1, 2, 3, 4, 5, 6, 7 - none */ /* 0, 1, 2, 3, 4, 5, 6, 7 - none */ | |
| 2930 | RSP_VMUDN(0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7); | |
| 2931 | break; | |
| 2932 | case 1: /* 0, 1, 2, 3, 4, 5, 6, 7 - ??? */ /* 0, 1, 2, 3, 4, 5, 6, 7 - ??? */ | |
| 2933 | RSP_VMUDN(0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7); | |
| 2934 | break; | |
| 2935 | case 2: /* 1, 3, 5, 7, 0, 2, 4, 6 - 0q */ /* 0, 0, 2, 2, 4, 4, 6, 6 - 0q */ | |
| 2936 | RSP_VMUDN(1, 3, 5, 7, 0, 2, 4, 6, 0, 2, 4, 6, 0, 2, 4, 6); | |
| 2937 | break; | |
| 2938 | case 3: /* 0, 2, 4, 6, 1, 3, 5, 7 - 1q */ /* 1, 1, 3, 3, 5, 5, 7, 7 - 1q */ | |
| 2939 | RSP_VMUDN(0, 2, 4, 6, 1, 3, 5, 7, 1, 3, 5, 7, 1, 3, 5, 7); | |
| 2940 | break; | |
| 2941 | case 4: /* 1, 2, 3, 5, 6, 7, 0, 4 - 0h */ /* 0, 0, 0, 0, 4, 4, 4, 4 - 0h */ | |
| 2942 | RSP_VMUDN(1, 2, 3, 5, 6, 7, 0, 4, 0, 0, 0, 4, 4, 4, 0, 4); | |
| 2943 | break; | |
| 2944 | case 5: /* 0, 2, 3, 4, 6, 7, 1, 5 - 1h */ /* 1, 1, 1, 1, 5, 5, 5, 5 - 1h */ | |
| 2945 | RSP_VMUDN(0, 2, 3, 4, 6, 7, 1, 5, 1, 1, 1, 5, 5, 5, 1, 5); | |
| 2946 | break; | |
| 2947 | case 6: /* 0, 1, 3, 4, 5, 7, 2, 6 - 2h */ /* 2, 2, 2, 2, 6, 6, 6, 6 - 2h */ | |
| 2948 | RSP_VMUDN(0, 1, 3, 4, 5, 7, 2, 6, 2, 2, 2, 6, 6, 6, 2, 6); | |
| 2949 | break; | |
| 2950 | case 7: /* 0, 1, 2, 4, 5, 6, 3, 7 - 3h */ /* 3, 3, 3, 3, 7, 7, 7, 7 - 3h */ | |
| 2951 | RSP_VMUDN(0, 1, 2, 4, 5, 6, 3, 7, 3, 3, 3, 7, 7, 7, 3, 7); | |
| 2952 | break; | |
| 2953 | case 8: /* 1, 2, 3, 4, 5, 6, 7, 0 - 0 */ /* 0, 0, 0, 0, 0, 0, 0, 0 - 0 */ | |
| 2954 | RSP_VMUDN(1, 2, 3, 4, 5, 6, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0); | |
| 2955 | break; | |
| 2956 | case 9: /* 0, 2, 3, 4, 5, 6, 7, 1 - 1 */ /* 1, 1, 1, 1, 1, 1, 1, 1 - 0 */ | |
| 2957 | RSP_VMUDN(0, 2, 3, 4, 5, 6, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1); | |
| 2958 | break; | |
| 2959 | case 10: /* 0, 1, 3, 4, 5, 6, 7, 2 - 2 */ /* 2, 2, 2, 2, 2, 2, 2, 2 - 0 */ | |
| 2960 | RSP_VMUDN(0, 1, 3, 4, 5, 6, 7, 2, 2, 2, 2, 2, 2, 2, 2, 2); | |
| 2961 | break; | |
| 2962 | case 11: /* 0, 1, 2, 4, 5, 6, 7, 3 - 3 */ /* 3, 3, 3, 3, 3, 3, 3, 3 - 0 */ | |
| 2963 | RSP_VMUDN(0, 1, 2, 4, 5, 6, 7, 3, 3, 3, 3, 3, 3, 3, 3, 3); | |
| 2964 | break; | |
| 2965 | case 12: /* 0, 1, 2, 3, 5, 6, 7, 4 - 4 */ /* 4, 4, 4, 4, 4, 4, 4, 4 - 0 */ | |
| 2966 | RSP_VMUDN(0, 1, 2, 3, 5, 6, 7, 4, 4, 4, 4, 4, 4, 4, 4, 4); | |
| 2967 | break; | |
| 2968 | case 13: /* 0, 1, 2, 3, 4, 6, 7, 5 - 5 */ /* 5, 5, 5, 5, 5, 5, 5, 5 - 0 */ | |
| 2969 | RSP_VMUDN(0, 1, 2, 3, 4, 6, 7, 5, 5, 5, 5, 5, 5, 5, 5, 5); | |
| 2970 | break; | |
| 2971 | case 14: /* 0, 1, 2, 3, 4, 5, 7, 6 - 6 */ /* 6, 6, 6, 6, 6, 6, 6, 6 - 0 */ | |
| 2972 | RSP_VMUDN(0, 1, 2, 3, 4, 5, 7, 6, 6, 6, 6, 6, 6, 6, 6, 6); | |
| 2973 | break; | |
| 2974 | case 15: /* 0, 1, 2, 3, 4, 5, 6, 7 - 7 */ /* 7, 7, 7, 7, 7, 7, 7, 7 - 0 */ | |
| 2975 | RSP_VMUDN(0, 1, 2, 3, 4, 5, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7); | |
| 2976 | break; | |
| 1943 | sel = VEC_EL_2(EL, i); | |
| 1944 | s1 = (UINT16)VREG_S(VS1REG, i); // not sign-extended | |
| 1945 | s2 = (INT32)(INT16)VREG_S(VS2REG, sel); | |
| 1946 | r = s1 * s2; | |
| 1947 | ||
| 1948 | ACCUM_H(i) = (r < 0) ? 0xffff : 0; // sign-extend to 48-bit | |
| 1949 | ACCUM_M(i) = (INT16)(r >> 16); | |
| 1950 | ACCUM_L(i) = (UINT16)(r); | |
| 1951 | ||
| 1952 | vres[i] = ACCUM_L(i); | |
| 2977 | 1953 | } |
| 1954 | WRITEBACK_RESULT(); | |
| 2978 | 1955 | } |
| 2979 | 1956 | |
| 2980 | 1957 | INLINE void cfunc_rsp_vmudh(void *param) |
| r9854 | r9855 | |
| 2992 | 1969 | // The result is stored into highest 32 bits of accumulator, the low slice is zero |
| 2993 | 1970 | // The highest 32 bits of accumulator is saturated into destination element |
| 2994 | 1971 | |
| 1972 | int sel; | |
| 1973 | INT32 s1, s2; | |
| 1974 | INT32 r; | |
| 2995 | 1975 | for (i=0; i < 8; i++) |
| 2996 | 1976 | { |
| 2997 | int del = VEC_EL_1(EL, i); | |
| 2998 | int sel = VEC_EL_2(EL, del); | |
| 2999 | INT32 s1 = (INT32)(INT16)R_VREG_S(VS1REG, del); | |
| 3000 | INT32 s2 = (INT32)(INT16)R_VREG_S(VS2REG, sel); | |
| 3001 | INT32 r = s1 * s2; | |
| 1977 | sel = VEC_EL_2(EL, i); | |
| 1978 | s1 = (INT32)(INT16)VREG_S(VS1REG, i); | |
| 1979 | s2 = (INT32)(INT16)VREG_S(VS2REG, sel); | |
| 1980 | r = s1 * s2; | |
| 3002 | 1981 | |
| 3003 | W_ACCUM_H(del, (INT16)(r >> 16)); | |
| 3004 | W_ACCUM_M(del, (UINT16)(r)); | |
| 3005 | W_ACCUM_L(del, 0); | |
| 1982 | ACCUM_H(i) = (INT16)(r >> 16); | |
| 1983 | ACCUM_M(i) = (UINT16)(r); | |
| 1984 | ACCUM_L(i) = 0; | |
| 3006 | 1985 | |
| 3007 | 1986 | if (r < -32768) r = -32768; |
| 3008 | 1987 | if (r > 32767) r = 32767; |
| 3009 | vres[ | |
| 1988 | vres[i | |
| 3010 | 1989 | } |
| 3011 | 1990 | WRITEBACK_RESULT(); |
| 3012 | 1991 | } |
| 3013 | 1992 | |
| 3014 | #define RSP_VMACF(E10, E11, E12, E13, E14, E15, E16, E17, E20, E21, E22, E23, E24, E25, E26, E27) \ | |
| 3015 | { \ | |
| 3016 | ACCUM(E10).l += (INT64)((INT32)(INT16)R_VREG_S(VS1REG, E10) * (INT32)(INT16)R_VREG_S(VS2REG, E20)) << 17; \ | |
| 3017 | ACCUM(E11).l += (INT64)((INT32)(INT16)R_VREG_S(VS1REG, E11) * (INT32)(INT16)R_VREG_S(VS2REG, E21)) << 17; \ | |
| 3018 | ACCUM(E12).l += (INT64)((INT32)(INT16)R_VREG_S(VS1REG, E12) * (INT32)(INT16)R_VREG_S(VS2REG, E22)) << 17; \ | |
| 3019 | ACCUM(E13).l += (INT64)((INT32)(INT16)R_VREG_S(VS1REG, E13) * (INT32)(INT16)R_VREG_S(VS2REG, E23)) << 17; \ | |
| 3020 | ACCUM(E14).l += (INT64)((INT32)(INT16)R_VREG_S(VS1REG, E14) * (INT32)(INT16)R_VREG_S(VS2REG, E24)) << 17; \ | |
| 3021 | ACCUM(E15).l += (INT64)((INT32)(INT16)R_VREG_S(VS1REG, E15) * (INT32)(INT16)R_VREG_S(VS2REG, E25)) << 17; \ | |
| 3022 | ACCUM(E16).l += (INT64)((INT32)(INT16)R_VREG_S(VS1REG, E16) * (INT32)(INT16)R_VREG_S(VS2REG, E26)) << 17; \ | |
| 3023 | ACCUM(E17).l += (INT64)((INT32)(INT16)R_VREG_S(VS1REG, E17) * (INT32)(INT16)R_VREG_S(VS2REG, E27)) << 17; \ | |
| 3024 | vres[E10] = SATURATE_ACCUM_SIGNED(rsp, E10); \ | |
| 3025 | vres[E11] = SATURATE_ACCUM_SIGNED(rsp, E11); \ | |
| 3026 | vres[E12] = SATURATE_ACCUM_SIGNED(rsp, E12); \ | |
| 3027 | vres[E13] = SATURATE_ACCUM_SIGNED(rsp, E13); \ | |
| 3028 | vres[E14] = SATURATE_ACCUM_SIGNED(rsp, E14); \ | |
| 3029 | vres[E15] = SATURATE_ACCUM_SIGNED(rsp, E15); \ | |
| 3030 | vres[E16] = SATURATE_ACCUM_SIGNED(rsp, E16); \ | |
| 3031 | vres[E17] = SATURATE_ACCUM_SIGNED(rsp, E17); \ | |
| 3032 | W_VREG_S_X(VDREG, 7, vres[0]); \ | |
| 3033 | W_VREG_S_X(VDREG, 6, vres[1]); \ | |
| 3034 | W_VREG_S_X(VDREG, 5, vres[2]); \ | |
| 3035 | W_VREG_S_X(VDREG, 4, vres[3]); \ | |
| 3036 | W_VREG_S_X(VDREG, 3, vres[4]); \ | |
| 3037 | W_VREG_S_X(VDREG, 2, vres[5]); \ | |
| 3038 | W_VREG_S_X(VDREG, 1, vres[6]); \ | |
| 3039 | W_VREG_S_X(VDREG, 0, vres[7]); \ | |
| 3040 | } | |
| 3041 | ||
| 3042 | 1993 | INLINE void cfunc_rsp_vmacf(void *param) |
| 3043 | 1994 | { |
| 3044 | 1995 | rsp_state *rsp = (rsp_state*)param; |
| 3045 | 1996 | int op = rsp->impstate->arg0; |
| 3046 | 1997 | INT16 vres[8]; |
| 3047 | //int i; | |
| 3048 | // 31 25 24 20 15 10 5 0 | |
| 3049 | // ------------------------------------------------------ | |
| 3050 | // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 001000 | | |
| 3051 | // ------------------------------------------------------ | |
| 3052 | // | |
| 3053 | // Multiplies signed integer by signed integer * 2 | |
| 3054 | // The result is added to accumulator | |
| 3055 | 1998 | |
| 3056 | switch(EL) | |
| 1999 | int sel; | |
| 2000 | INT32 s1, s2; | |
| 2001 | INT32 r; | |
| 2002 | UINT16 res; | |
| 2003 | for (int i = 0; i < 8; i++) | |
| 3057 | 2004 | { |
| 3058 | case 0: /* 0, 1, 2, 3, 4, 5, 6, 7 - none */ /* 0, 1, 2, 3, 4, 5, 6, 7 - none */ | |
| 3059 | RSP_VMACF(0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7); | |
| 3060 | break; | |
| 3061 | case 1: /* 0, 1, 2, 3, 4, 5, 6, 7 - ??? */ /* 0, 1, 2, 3, 4, 5, 6, 7 - ??? */ | |
| 3062 | RSP_VMACF(0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7); | |
| 3063 | break; | |
| 3064 | case 2: /* 1, 3, 5, 7, 0, 2, 4, 6 - 0q */ /* 0, 0, 2, 2, 4, 4, 6, 6 - 0q */ | |
| 3065 | RSP_VMACF(1, 3, 5, 7, 0, 2, 4, 6, 0, 2, 4, 6, 0, 2, 4, 6); | |
| 3066 | break; | |
| 3067 | case 3: /* 0, 2, 4, 6, 1, 3, 5, 7 - 1q */ /* 1, 1, 3, 3, 5, 5, 7, 7 - 1q */ | |
| 3068 | RSP_VMACF(0, 2, 4, 6, 1, 3, 5, 7, 1, 3, 5, 7, 1, 3, 5, 7); | |
| 3069 | break; | |
| 3070 | case 4: /* 1, 2, 3, 5, 6, 7, 0, 4 - 0h */ /* 0, 0, 0, 0, 4, 4, 4, 4 - 0h */ | |
| 3071 | RSP_VMACF(1, 2, 3, 5, 6, 7, 0, 4, 0, 0, 0, 4, 4, 4, 0, 4); | |
| 3072 | break; | |
| 3073 | case 5: /* 0, 2, 3, 4, 6, 7, 1, 5 - 1h */ /* 1, 1, 1, 1, 5, 5, 5, 5 - 1h */ | |
| 3074 | RSP_VMACF(0, 2, 3, 4, 6, 7, 1, 5, 1, 1, 1, 5, 5, 5, 1, 5); | |
| 3075 | break; | |
| 3076 | case 6: /* 0, 1, 3, 4, 5, 7, 2, 6 - 2h */ /* 2, 2, 2, 2, 6, 6, 6, 6 - 2h */ | |
| 3077 | RSP_VMACF(0, 1, 3, 4, 5, 7, 2, 6, 2, 2, 2, 6, 6, 6, 2, 6); | |
| 3078 | break; | |
| 3079 | case 7: /* 0, 1, 2, 4, 5, 6, 3, 7 - 3h */ /* 3, 3, 3, 3, 7, 7, 7, 7 - 3h */ | |
| 3080 | RSP_VMACF(0, 1, 2, 4, 5, 6, 3, 7, 3, 3, 3, 7, 7, 7, 3, 7); | |
| 3081 | break; | |
| 3082 | case 8: /* 1, 2, 3, 4, 5, 6, 7, 0 - 0 */ /* 0, 0, 0, 0, 0, 0, 0, 0 - 0 */ | |
| 3083 | RSP_VMACF(1, 2, 3, 4, 5, 6, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0); | |
| 3084 | break; | |
| 3085 | case 9: /* 0, 2, 3, 4, 5, 6, 7, 1 - 1 */ /* 1, 1, 1, 1, 1, 1, 1, 1 - 0 */ | |
| 3086 | RSP_VMACF(0, 2, 3, 4, 5, 6, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1); | |
| 3087 | break; | |
| 3088 | case 10: /* 0, 1, 3, 4, 5, 6, 7, 2 - 2 */ /* 2, 2, 2, 2, 2, 2, 2, 2 - 0 */ | |
| 3089 | RSP_VMACF(0, 1, 3, 4, 5, 6, 7, 2, 2, 2, 2, 2, 2, 2, 2, 2); | |
| 3090 | break; | |
| 3091 | case 11: /* 0, 1, 2, 4, 5, 6, 7, 3 - 3 */ /* 3, 3, 3, 3, 3, 3, 3, 3 - 0 */ | |
| 3092 | RSP_VMACF(0, 1, 2, 4, 5, 6, 7, 3, 3, 3, 3, 3, 3, 3, 3, 3); | |
| 3093 | break; | |
| 3094 | case 12: /* 0, 1, 2, 3, 5, 6, 7, 4 - 4 */ /* 4, 4, 4, 4, 4, 4, 4, 4 - 0 */ | |
| 3095 | RSP_VMACF(0, 1, 2, 3, 5, 6, 7, 4, 4, 4, 4, 4, 4, 4, 4, 4); | |
| 3096 | break; | |
| 3097 | case 13: /* 0, 1, 2, 3, 4, 6, 7, 5 - 5 */ /* 5, 5, 5, 5, 5, 5, 5, 5 - 0 */ | |
| 3098 | RSP_VMACF(0, 1, 2, 3, 4, 6, 7, 5, 5, 5, 5, 5, 5, 5, 5, 5); | |
| 3099 | break; | |
| 3100 | case 14: /* 0, 1, 2, 3, 4, 5, 7, 6 - 6 */ /* 6, 6, 6, 6, 6, 6, 6, 6 - 0 */ | |
| 3101 | RSP_VMACF(0, 1, 2, 3, 4, 5, 7, 6, 6, 6, 6, 6, 6, 6, 6, 6); | |
| 3102 | break; | |
| 3103 | case 15: /* 0, 1, 2, 3, 4, 5, 6, 7 - 7 */ /* 7, 7, 7, 7, 7, 7, 7, 7 - 0 */ | |
| 3104 | RSP_VMACF(0, 1, 2, 3, 4, 5, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7); | |
| 3105 | break; | |
| 3106 | } | |
| 3107 | #if 0 | |
| 3108 | for (i=0; i < 8; i++) | |
| 3109 | { | |
| 3110 | UINT16 res; | |
| 3111 | int del = VEC_EL_1(EL, i); | |
| 3112 | int sel = VEC_EL_2(EL, del); | |
| 3113 | INT32 s1 = (INT32)(INT16)R_VREG_S(VS1REG, del); | |
| 3114 | INT32 s2 = (INT32)(INT16)R_VREG_S(VS2REG, sel); | |
| 3115 | INT32 r = s1 * s2; | |
| 2005 | sel = VEC_EL_2(EL, i); | |
| 2006 | s1 = (INT32)(INT16)VREG_S(VS1REG, i); | |
| 2007 | s2 = (INT32)(INT16)VREG_S(VS2REG, sel); | |
| 2008 | r = s1 * s2; | |
| 3116 | 2009 | |
| 3117 | ACCUM(del).l += (INT64)(r) << 17; | |
| 3118 | res = SATURATE_ACCUM_SIGNED(rsp, del); | |
| 2010 | ACCUM(i) += (INT64)(r) << 17; | |
| 2011 | res = SATURATE_ACCUM(rsp, i, 1, 0x8000, 0x7fff); | |
| 3119 | 2012 | |
| 3120 | vres[ | |
| 2013 | vres[i | |
| 3121 | 2014 | } |
| 3122 | 2015 | WRITEBACK_RESULT(); |
| 3123 | #endif | |
| 3124 | 2016 | } |
| 3125 | 2017 | |
| 3126 | 2018 | INLINE void cfunc_rsp_vmacu(void *param) |
| r9854 | r9855 | |
| 3135 | 2027 | // ------------------------------------------------------ |
| 3136 | 2028 | // |
| 3137 | 2029 | |
| 3138 | for (i=0; i < 8; i++) | |
| 2030 | UINT16 res; | |
| 2031 | int sel; | |
| 2032 | INT32 s1, s2, r1; | |
| 2033 | UINT32 r2, r3; | |
| 2034 | for (i = 0; i < 8; i++) | |
| 3139 | 2035 | { |
| 3140 | UINT16 res; | |
| 3141 | int del = VEC_EL_1(EL, i); | |
| 3142 | int sel = VEC_EL_2(EL, del); | |
| 3143 | INT32 s1 = (INT32)(INT16)R_VREG_S(VS1REG, del); | |
| 3144 | INT32 s2 = (INT32)(INT16)R_VREG_S(VS2REG, sel); | |
| 3145 | INT32 r1 = s1 * s2; | |
| 3146 | UINT32 r2 = (UINT16)ACCUM(del).h.low + ((UINT16)(r1) * 2); | |
| 3147 | UINT32 r3 = (UINT16)ACCUM(del).h.mid + (UINT16)((r1 >> 16) * 2) + (UINT16)(r2 >> 16); | |
| 2036 | sel = VEC_EL_2(EL, i); | |
| 2037 | s1 = (INT32)(INT16)VREG_S(VS1REG, i); | |
| 2038 | s2 = (INT32)(INT16)VREG_S(VS2REG, sel); | |
| 2039 | r1 = s1 * s2; | |
| 2040 | r2 = (UINT16)ACCUM_L(i) + ((UINT16)(r1) * 2); | |
| 2041 | r3 = (UINT16)ACCUM_M(i) + (UINT16)((r1 >> 16) * 2) + (UINT16)(r2 >> 16); | |
| 3148 | 2042 | |
| 3149 | W_ACCUM_L(del, (UINT16)(r2)); | |
| 3150 | W_ACCUM_M(del, (UINT16)(r3)); | |
| 3151 | W_ACCUM_H(del, (UINT16)ACCUM(del).h.high + (UINT16)(r3 >> 16) + (UINT16)(r1 >> 31)); | |
| 2043 | ACCUM_L(i) = (UINT16)(r2); | |
| 2044 | ACCUM_M(i) = (UINT16)(r3); | |
| 2045 | ACCUM_H(i) += (UINT16)(r3 >> 16) + (UINT16)(r1 >> 31); | |
| 3152 | 2046 | |
| 3153 | if (ACCUM(del).h.high < 0) | |
| 2047 | //res = SATURATE_ACCUM(i, 1, 0x0000, 0xffff); | |
| 2048 | if ((INT16)ACCUM_H(i) < 0) | |
| 3154 | 2049 | { |
| 3155 | 2050 | res = 0; |
| 3156 | 2051 | } |
| 3157 | 2052 | else |
| 3158 | 2053 | { |
| 3159 | if (ACCUM( | |
| 2054 | if (ACCUM_H( | |
| 3160 | 2055 | { |
| 3161 | 2056 | res = 0xffff; |
| 3162 | 2057 | } |
| 3163 | 2058 | else |
| 3164 | 2059 | { |
| 3165 | if (ACCUM( | |
| 2060 | if ((INT16)ACCUM_M( | |
| 3166 | 2061 | { |
| 3167 | 2062 | res = 0xffff; |
| 3168 | 2063 | } |
| 3169 | 2064 | else |
| 3170 | 2065 | { |
| 3171 | res = ACCUM( | |
| 2066 | res = ACCUM_M( | |
| 3172 | 2067 | } |
| 3173 | 2068 | } |
| 3174 | 2069 | } |
| 3175 | 2070 | |
| 3176 | vres[ | |
| 2071 | vres[i | |
| 3177 | 2072 | } |
| 3178 | 2073 | WRITEBACK_RESULT(); |
| 3179 | 2074 | } |
| r9854 | r9855 | |
| 3193 | 2088 | // Adds the higher 16 bits of the 32-bit result to accumulator |
| 3194 | 2089 | // The low slice of accumulator is stored into destination element |
| 3195 | 2090 | |
| 3196 | for (i=0; i < 8; i++) | |
| 2091 | UINT16 res; | |
| 2092 | int sel; | |
| 2093 | UINT32 s1, s2, r1; | |
| 2094 | UINT32 r2, r3; | |
| 2095 | for (i = 0; i < 8; i++) | |
| 3197 | 2096 | { |
| 3198 | UINT16 res; | |
| 3199 | int del = VEC_EL_1(EL, i); | |
| 3200 | int sel = VEC_EL_2(EL, del); | |
| 3201 | UINT32 s1 = (UINT32)(UINT16)R_VREG_S(VS1REG, del); | |
| 3202 | UINT32 s2 = (UINT32)(UINT16)R_VREG_S(VS2REG, sel); | |
| 3203 | UINT32 r1 = s1 * s2; | |
| 3204 | UINT32 r2 = (UINT16)ACCUM(del).h.low + (r1 >> 16); | |
| 3205 | UINT32 r3 = (UINT16)ACCUM(del).h.mid + (r2 >> 16); | |
| 2097 | sel = VEC_EL_2(EL, i); | |
| 2098 | s1 = (UINT32)(UINT16)VREG_S(VS1REG, i); | |
| 2099 | s2 = (UINT32)(UINT16)VREG_S(VS2REG, sel); | |
| 2100 | r1 = s1 * s2; | |
| 2101 | r2 = (UINT16)ACCUM_L(i) + (r1 >> 16); | |
| 2102 | r3 = (UINT16)ACCUM_M(i) + (r2 >> 16); | |
| 3206 | 2103 | |
| 3207 | W_ACCUM_L(del, (UINT16)(r2)); | |
| 3208 | W_ACCUM_M(del, (UINT16)(r3)); | |
| 3209 | W_ACCUM_H(del, ACCUM(del).h.high + (INT16)(r3 >> 16)); | |
| 2104 | ACCUM_L(i) = (UINT16)(r2); | |
| 2105 | ACCUM_M(i) = (UINT16)(r3); | |
| 2106 | ACCUM_H(i) += (INT16)(r3 >> 16); | |
| 3210 | 2107 | |
| 3211 | res = SATURATE_ACCUM | |
| 2108 | res = SATURATE_ACCUM | |
| 3212 | 2109 | |
| 3213 | vres[ | |
| 2110 | vres[i | |
| 3214 | 2111 | } |
| 3215 | 2112 | WRITEBACK_RESULT(); |
| 3216 | 2113 | } |
| 3217 | 2114 | |
| 3218 | #if (DRC_VMADM) | |
| 3219 | /*------------------------------------------------------------------ | |
| 3220 | generate_vmadm | |
| 3221 | ------------------------------------------------------------------*/ | |
| 3222 | ||
| 3223 | #define RSP_VMADM_DRC(E10, E11, E12, E13, E14, E15, E16, E17, E20, E21, E22, E23, E24, E25, E26, E27, I0, I1, I2, I3, I4, I5, I6, I7) \ | |
| 3224 | { \ | |
| 3225 | UML_SEXT(block, IREG(0), VS(VS1REG, I0), WORD); \ | |
| 3226 | UML_SEXT(block, IREG(1), VS(VS2REG, E20), WORD); \ | |
| 3227 | UML_AND(block, IREG(1), IREG(1), IMM(0x0000ffff)); \ | |
| 3228 | UML_MULS(block, IREG(0), IREG(1), IREG(0), IREG(1)); \ | |
| 3229 | UML_DSEXT(block, IREG(0), IREG(0), DWORD); \ | |
| 3230 | UML_DSHL(block, IREG(0), IREG(0), IMM(16)); \ | |
| 3231 | UML_DADD(block, VACCUML(E10), VACCUML(E10), IREG(0)); \ | |
| 3232 | \ | |
| 3233 | UML_SEXT(block, IREG(0), VS(VS1REG, I1), WORD); \ | |
| 3234 | UML_SEXT(block, IREG(1), VS(VS2REG, E21), WORD); \ | |
| 3235 | UML_AND(block, IREG(1), IREG(1), IMM(0x0000ffff)); \ | |
| 3236 | UML_MULS(block, IREG(0), IREG(1), IREG(0), IREG(1)); \ | |
| 3237 | UML_DSEXT(block, IREG(0), IREG(0), DWORD); \ | |
| 3238 | UML_DSHL(block, IREG(0), IREG(0), IMM(16)); \ | |
| 3239 | UML_DADD(block, VACCUML(E11), VACCUML(E11), IREG(0)); \ | |
| 3240 | \ | |
| 3241 | UML_SEXT(block, IREG(0), VS(VS1REG, I2), WORD); \ | |
| 3242 | UML_SEXT(block, IREG(1), VS(VS2REG, E22), WORD); \ | |
| 3243 | UML_AND(block, IREG(1), IREG(1), IMM(0x0000ffff)); \ | |
| 3244 | UML_MULS(block, IREG(0), IREG(1), IREG(0), IREG(1)); \ | |
| 3245 | UML_DSEXT(block, IREG(0), IREG(0), DWORD); \ | |
| 3246 | UML_DSHL(block, IREG(0), IREG(0), IMM(16)); \ | |
| 3247 | UML_DADD(block, VACCUML(E12), VACCUML(E12), IREG(0)); \ | |
| 3248 | \ | |
| 3249 | UML_SEXT(block, IREG(0), VS(VS1REG, I3), WORD); \ | |
| 3250 | UML_SEXT(block, IREG(1), VS(VS2REG, E23), WORD); \ | |
| 3251 | UML_AND(block, IREG(1), IREG(1), IMM(0x0000ffff)); \ | |
| 3252 | UML_MULS(block, IREG(0), IREG(1), IREG(0), IREG(1)); \ | |
| 3253 | UML_DSEXT(block, IREG(0), IREG(0), DWORD); \ | |
| 3254 | UML_DSHL(block, IREG(0), IREG(0), IMM(16)); \ | |
| 3255 | UML_DADD(block, VACCUML(E13), VACCUML(E13), IREG(0)); \ | |
| 3256 | \ | |
| 3257 | UML_SEXT(block, IREG(0), VS(VS1REG, I4), WORD); \ | |
| 3258 | UML_SEXT(block, IREG(1), VS(VS2REG, E24), WORD); \ | |
| 3259 | UML_AND(block, IREG(1), IREG(1), IMM(0x0000ffff)); \ | |
| 3260 | UML_MULS(block, IREG(0), IREG(1), IREG(0), IREG(1)); \ | |
| 3261 | UML_DSEXT(block, IREG(0), IREG(0), DWORD); \ | |
| 3262 | UML_DSHL(block, IREG(0), IREG(0), IMM(16)); \ | |
| 3263 | UML_DADD(block, VACCUML(E14), VACCUML(E14), IREG(0)); \ | |
| 3264 | \ | |
| 3265 | UML_SEXT(block, IREG(0), VS(VS1REG, I5), WORD); \ | |
| 3266 | UML_SEXT(block, IREG(1), VS(VS2REG, E25), WORD); \ | |
| 3267 | UML_AND(block, IREG(1), IREG(1), IMM(0x0000ffff)); \ | |
| 3268 | UML_MULS(block, IREG(0), IREG(1), IREG(0), IREG(1)); \ | |
| 3269 | UML_DSEXT(block, IREG(0), IREG(0), DWORD); \ | |
| 3270 | UML_DSHL(block, IREG(0), IREG(0), IMM(16)); \ | |
| 3271 | UML_DADD(block, VACCUML(E15), VACCUML(E15), IREG(0)); \ | |
| 3272 | \ | |
| 3273 | UML_SEXT(block, IREG(0), VS(VS1REG, I6), WORD); \ | |
| 3274 | UML_SEXT(block, IREG(1), VS(VS2REG, E26), WORD); \ | |
| 3275 | UML_AND(block, IREG(1), IREG(1), IMM(0x0000ffff)); \ | |
| 3276 | UML_MULS(block, IREG(0), IREG(1), IREG(0), IREG(1)); \ | |
| 3277 | UML_DSEXT(block, IREG(0), IREG(0), DWORD); \ | |
| 3278 | UML_DSHL(block, IREG(0), IREG(0), IMM(16)); \ | |
| 3279 | UML_DADD(block, VACCUML(E16), VACCUML(E16), IREG(0)); \ | |
| 3280 | \ | |
| 3281 | UML_SEXT(block, IREG(0), VS(VS1REG, I7), WORD); \ | |
| 3282 | UML_SEXT(block, IREG(1), VS(VS2REG, E27), WORD); \ | |
| 3283 | UML_AND(block, IREG(1), IREG(1), IMM(0x0000ffff)); \ | |
| 3284 | UML_MULS(block, IREG(0), IREG(1), IREG(0), IREG(1)); \ | |
| 3285 | UML_DSEXT(block, IREG(0), IREG(0), DWORD); \ | |
| 3286 | UML_DSHL(block, IREG(0), IREG(0), IMM(16)); \ | |
| 3287 | UML_DADD(block, VACCUML(E17), VACCUML(E17), IREG(0)); \ | |
| 3288 | \ | |
| 3289 | generate_saturate_accum_signed(rsp, block, compiler, desc, E10); \ | |
| 3290 | UML_STORE(block, &rsp->v[VDREG].s[I0], IMM(0), IREG(0), WORD); \ | |
| 3291 | generate_saturate_accum_signed(rsp, block, compiler, desc, E11); \ | |
| 3292 | UML_STORE(block, &rsp->v[VDREG].s[I1], IMM(0), IREG(0), WORD); \ | |
| 3293 | generate_saturate_accum_signed(rsp, block, compiler, desc, E12); \ | |
| 3294 | UML_STORE(block, &rsp->v[VDREG].s[I2], IMM(0), IREG(0), WORD); \ | |
| 3295 | generate_saturate_accum_signed(rsp, block, compiler, desc, E13); \ | |
| 3296 | UML_STORE(block, &rsp->v[VDREG].s[I3], IMM(0), IREG(0), WORD); \ | |
| 3297 | generate_saturate_accum_signed(rsp, block, compiler, desc, E14); \ | |
| 3298 | UML_STORE(block, &rsp->v[VDREG].s[I4], IMM(0), IREG(0), WORD); \ | |
| 3299 | generate_saturate_accum_signed(rsp, block, compiler, desc, E15); \ | |
| 3300 | UML_STORE(block, &rsp->v[VDREG].s[I5], IMM(0), IREG(0), WORD); \ | |
| 3301 | generate_saturate_accum_signed(rsp, block, compiler, desc, E16); \ | |
| 3302 | UML_STORE(block, &rsp->v[VDREG].s[I6], IMM(0), IREG(0), WORD); \ | |
| 3303 | generate_saturate_accum_signed(rsp, block, compiler, desc, E17); \ | |
| 3304 | UML_STORE(block, &rsp->v[VDREG].s[I7], IMM(0), IREG(0), WORD); \ | |
| 3305 | } | |
| 3306 | ||
| 3307 | static int generate_vmadm(rsp_state *rsp, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) // vmadm | |
| 3308 | { | |
| 3309 | UINT32 op = desc->opptr.l[0]; | |
| 3310 | ||
| 3311 | // 31 25 24 20 15 10 5 0 | |
| 3312 | // ------------------------------------------------------ | |
| 3313 | // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 001110 | | |
| 3314 | // ------------------------------------------------------ | |
| 3315 | // | |
| 3316 | // Multiplies signed integer by unsigned fraction | |
| 3317 | // The result is added into accumulator | |
| 3318 | // The middle slice of accumulator is stored into destination element | |
| 3319 | switch(EL) | |
| 3320 | { | |
| 3321 | case 0: /* 0, 1, 2, 3, 4, 5, 6, 7 - none */ /* 0, 1, 2, 3, 4, 5, 6, 7 - none */ | |
| 3322 | RSP_VMADM_DRC(0, 1, 2, 3, 4, 5, 6, 7, 7, 6, 5, 4, 3, 2, 1, 0, 7, 6, 5, 4, 3, 2, 1, 0); | |
| 3323 | return TRUE; | |
| 3324 | case 1: /* 0, 1, 2, 3, 4, 5, 6, 7 - ??? */ /* 0, 1, 2, 3, 4, 5, 6, 7 - ??? */ | |
| 3325 | RSP_VMADM_DRC(0, 1, 2, 3, 4, 5, 6, 7, 7, 6, 5, 4, 3, 2, 1, 0, 7, 6, 5, 4, 3, 2, 1, 0); | |
| 3326 | return TRUE; | |
| 3327 | case 2: /* 1, 3, 5, 7, 0, 2, 4, 6 - 0q */ /* 0, 0, 2, 2, 4, 4, 6, 6 - 0q */ | |
| 3328 | RSP_VMADM_DRC(1, 3, 5, 7, 0, 2, 4, 6, 7, 5, 3, 1, 7, 5, 3, 1, 6, 4, 2, 0, 7, 5, 3, 1); | |
| 3329 | return TRUE; | |
| 3330 | case 3: /* 0, 2, 4, 6, 1, 3, 5, 7 - 1q */ /* 1, 1, 3, 3, 5, 5, 7, 7 - 1q */ | |
| 3331 | RSP_VMADM_DRC(0, 2, 4, 6, 1, 3, 5, 7, 6, 4, 2, 0, 6, 4, 2, 0, 7, 5, 3, 1, 6, 4, 2, 0); | |
| 3332 | return TRUE; | |
| 3333 | case 4: /* 1, 2, 3, 5, 6, 7, 0, 4 - 0h */ /* 0, 0, 0, 0, 4, 4, 4, 4 - 0h */ | |
| 3334 | RSP_VMADM_DRC(1, 2, 3, 5, 6, 7, 0, 4, 7, 7, 7, 3, 3, 3, 7, 3, 6, 5, 4, 2, 1, 0, 7, 3); | |
| 3335 | return TRUE; | |
| 3336 | case 5: /* 0, 2, 3, 4, 6, 7, 1, 5 - 1h */ /* 1, 1, 1, 1, 5, 5, 5, 5 - 1h */ | |
| 3337 | RSP_VMADM_DRC(0, 2, 3, 4, 6, 7, 1, 5, 6, 6, 6, 2, 2, 2, 6, 2, 7, 5, 4, 3, 1, 0, 6, 2); | |
| 3338 | return TRUE; | |
| 3339 | case 6: /* 0, 1, 3, 4, 5, 7, 2, 6 - 2h */ /* 2, 2, 2, 2, 6, 6, 6, 6 - 2h */ | |
| 3340 | RSP_VMADM_DRC(0, 1, 3, 4, 5, 7, 2, 6, 5, 5, 5, 1, 1, 1, 5, 1, 7, 6, 4, 3, 2, 0, 5, 1); | |
| 3341 | return TRUE; | |
| 3342 | case 7: /* 0, 1, 2, 4, 5, 6, 3, 7 - 3h */ /* 3, 3, 3, 3, 7, 7, 7, 7 - 3h */ | |
| 3343 | RSP_VMADM_DRC(0, 1, 2, 4, 5, 6, 3, 7, 4, 4, 4, 0, 0, 0, 4, 0, 7, 6, 5, 3, 2, 1, 4, 0); | |
| 3344 | return TRUE; | |
| 3345 | case 8: /* 1, 2, 3, 4, 5, 6, 7, 0 - 0 */ /* 0, 0, 0, 0, 0, 0, 0, 0 - 0 */ | |
| 3346 | RSP_VMADM_DRC(1, 2, 3, 4, 5, 6, 7, 0, 7, 7, 7, 7, 7, 7, 7, 7, 6, 5, 4, 3, 2, 1, 0, 7); | |
| 3347 | return TRUE; | |
| 3348 | case 9: /* 0, 2, 3, 4, 5, 6, 7, 1 - 1 */ /* 1, 1, 1, 1, 1, 1, 1, 1 - 0 */ | |
| 3349 | RSP_VMADM_DRC(0, 2, 3, 4, 5, 6, 7, 1, 6, 6, 6, 6, 6, 6, 6, 6, 7, 5, 4, 3, 2, 1, 0, 6); | |
| 3350 | return TRUE; | |
| 3351 | case 10: /* 0, 1, 3, 4, 5, 6, 7, 2 - 2 */ /* 2, 2, 2, 2, 2, 2, 2, 2 - 0 */ | |
| 3352 | RSP_VMADM_DRC(0, 1, 3, 4, 5, 6, 7, 2, 5, 5, 5, 5, 5, 5, 5, 5, 7, 6, 4, 3, 2, 1, 0, 5); | |
| 3353 | return TRUE; | |
| 3354 | case 11: /* 0, 1, 2, 4, 5, 6, 7, 3 - 3 */ /* 3, 3, 3, 3, 3, 3, 3, 3 - 0 */ | |
| 3355 | RSP_VMADM_DRC(0, 1, 2, 4, 5, 6, 7, 3, 4, 4, 4, 4, 4, 4, 4, 4, 7, 6, 5, 3, 2, 1, 0, 4); | |
| 3356 | return TRUE; | |
| 3357 | case 12: /* 0, 1, 2, 3, 5, 6, 7, 4 - 4 */ /* 4, 4, 4, 4, 4, 4, 4, 4 - 0 */ | |
| 3358 | RSP_VMADM_DRC(0, 1, 2, 3, 5, 6, 7, 4, 3, 3, 3, 3, 3, 3, 3, 3, 7, 6, 5, 4, 2, 1, 0, 3); | |
| 3359 | return TRUE; | |
| 3360 | case 13: /* 0, 1, 2, 3, 4, 6, 7, 5 - 5 */ /* 5, 5, 5, 5, 5, 5, 5, 5 - 0 */ | |
| 3361 | RSP_VMADM_DRC(0, 1, 2, 3, 4, 6, 7, 5, 2, 2, 2, 2, 2, 2, 2, 2, 7, 6, 5, 4, 3, 1, 0, 2); | |
| 3362 | return TRUE; | |
| 3363 | case 14: /* 0, 1, 2, 3, 4, 5, 7, 6 - 6 */ /* 6, 6, 6, 6, 6, 6, 6, 6 - 0 */ | |
| 3364 | RSP_VMADM_DRC(0, 1, 2, 3, 4, 5, 7, 6, 1, 1, 1, 1, 1, 1, 1, 1, 7, 6, 5, 4, 3, 2, 0, 1); | |
| 3365 | return TRUE; | |
| 3366 | case 15: /* 0, 1, 2, 3, 4, 5, 6, 7 - 7 */ /* 7, 7, 7, 7, 7, 7, 7, 7 - 0 */ | |
| 3367 | RSP_VMADM_DRC(0, 1, 2, 3, 4, 5, 6, 7, 0, 0, 0, 0, 0, 0, 0, 0, 7, 6, 5, 4, 3, 2, 1, 0); | |
| 3368 | return TRUE; | |
| 3369 | } | |
| 3370 | ||
| 3371 | return TRUE; | |
| 3372 | } | |
| 3373 | #else | |
| 3374 | #define RSP_VMADM(E10, E11, E12, E13, E14, E15, E16, E17, E20, E21, E22, E23, E24, E25, E26, E27) \ | |
| 3375 | { \ | |
| 3376 | ACCUM(E10).l += ((INT64)(INT16)R_VREG_S(VS1REG, E10) * (UINT16)R_VREG_S(VS2REG, E20)) << 16; \ | |
| 3377 | ACCUM(E11).l += ((INT64)(INT16)R_VREG_S(VS1REG, E11) * (UINT16)R_VREG_S(VS2REG, E21)) << 16; \ | |
| 3378 | ACCUM(E12).l += ((INT64)(INT16)R_VREG_S(VS1REG, E12) * (UINT16)R_VREG_S(VS2REG, E22)) << 16; \ | |
| 3379 | ACCUM(E13).l += ((INT64)(INT16)R_VREG_S(VS1REG, E13) * (UINT16)R_VREG_S(VS2REG, E23)) << 16; \ | |
| 3380 | ACCUM(E14).l += ((INT64)(INT16)R_VREG_S(VS1REG, E14) * (UINT16)R_VREG_S(VS2REG, E24)) << 16; \ | |
| 3381 | ACCUM(E15).l += ((INT64)(INT16)R_VREG_S(VS1REG, E15) * (UINT16)R_VREG_S(VS2REG, E25)) << 16; \ | |
| 3382 | ACCUM(E16).l += ((INT64)(INT16)R_VREG_S(VS1REG, E16) * (UINT16)R_VREG_S(VS2REG, E26)) << 16; \ | |
| 3383 | ACCUM(E17).l += ((INT64)(INT16)R_VREG_S(VS1REG, E17) * (UINT16)R_VREG_S(VS2REG, E27)) << 16; \ | |
| 3384 | vres[E10] = SATURATE_ACCUM_SIGNED(rsp, E10); \ | |
| 3385 | vres[E11] = SATURATE_ACCUM_SIGNED(rsp, E11); \ | |
| 3386 | vres[E12] = SATURATE_ACCUM_SIGNED(rsp, E12); \ | |
| 3387 | vres[E13] = SATURATE_ACCUM_SIGNED(rsp, E13); \ | |
| 3388 | vres[E14] = SATURATE_ACCUM_SIGNED(rsp, E14); \ | |
| 3389 | vres[E15] = SATURATE_ACCUM_SIGNED(rsp, E15); \ | |
| 3390 | vres[E16] = SATURATE_ACCUM_SIGNED(rsp, E16); \ | |
| 3391 | vres[E17] = SATURATE_ACCUM_SIGNED(rsp, E17); \ | |
| 3392 | W_VREG_S_X(VDREG, 7, vres[0]); \ | |
| 3393 | W_VREG_S_X(VDREG, 6, vres[1]); \ | |
| 3394 | W_VREG_S_X(VDREG, 5, vres[2]); \ | |
| 3395 | W_VREG_S_X(VDREG, 4, vres[3]); \ | |
| 3396 | W_VREG_S_X(VDREG, 3, vres[4]); \ | |
| 3397 | W_VREG_S_X(VDREG, 2, vres[5]); \ | |
| 3398 | W_VREG_S_X(VDREG, 1, vres[6]); \ | |
| 3399 | W_VREG_S_X(VDREG, 0, vres[7]); \ | |
| 3400 | } | |
| 3401 | ||
| 3402 | 2115 | INLINE void cfunc_rsp_vmadm(void *param) |
| 3403 | 2116 | { |
| 3404 | 2117 | rsp_state *rsp = (rsp_state*)param; |
| 3405 | 2118 | int op = rsp->impstate->arg0; |
| 3406 | 2119 | INT16 vres[8]; |
| 3407 | // 31 25 24 20 15 10 5 0 | |
| 3408 | // ------------------------------------------------------ | |
| 3409 | // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 001101 | | |
| 3410 | // ------------------------------------------------------ | |
| 3411 | // | |
| 3412 | // Multiplies signed integer by unsigned fraction | |
| 3413 | // The result is added into accumulator | |
| 3414 | // The middle slice of accumulator is stored into destination element | |
| 3415 | 2120 | |
| 3416 | switch(EL) | |
| 2121 | UINT16 res; | |
| 2122 | int sel; | |
| 2123 | UINT32 s1, s2, r1; | |
| 2124 | UINT32 r2, r3; | |
| 2125 | for (int i = 0; i < 8; i++) | |
| 3417 | 2126 | { |
| 3418 | case 0: /* 0, 1, 2, 3, 4, 5, 6, 7 - none */ /* 0, 1, 2, 3, 4, 5, 6, 7 - none */ | |
| 3419 | RSP_VMADM(0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7); | |
| 3420 | break; | |
| 3421 | case 1: /* 0, 1, 2, 3, 4, 5, 6, 7 - ??? */ /* 0, 1, 2, 3, 4, 5, 6, 7 - ??? */ | |
| 3422 | RSP_VMADM(0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7); | |
| 3423 | break; | |
| 3424 | case 2: /* 1, 3, 5, 7, 0, 2, 4, 6 - 0q */ /* 0, 0, 2, 2, 4, 4, 6, 6 - 0q */ | |
| 3425 | RSP_VMADM(1, 3, 5, 7, 0, 2, 4, 6, 0, 2, 4, 6, 0, 2, 4, 6); | |
| 3426 | break; | |
| 3427 | case 3: /* 0, 2, 4, 6, 1, 3, 5, 7 - 1q */ /* 1, 1, 3, 3, 5, 5, 7, 7 - 1q */ | |
| 3428 | RSP_VMADM(0, 2, 4, 6, 1, 3, 5, 7, 1, 3, 5, 7, 1, 3, 5, 7); | |
| 3429 | break; | |
| 3430 | case 4: /* 1, 2, 3, 5, 6, 7, 0, 4 - 0h */ /* 0, 0, 0, 0, 4, 4, 4, 4 - 0h */ | |
| 3431 | RSP_VMADM(1, 2, 3, 5, 6, 7, 0, 4, 0, 0, 0, 4, 4, 4, 0, 4); | |
| 3432 | break; | |
| 3433 | case 5: /* 0, 2, 3, 4, 6, 7, 1, 5 - 1h */ /* 1, 1, 1, 1, 5, 5, 5, 5 - 1h */ | |
| 3434 | RSP_VMADM(0, 2, 3, 4, 6, 7, 1, 5, 1, 1, 1, 5, 5, 5, 1, 5); | |
| 3435 | break; | |
| 3436 | case 6: /* 0, 1, 3, 4, 5, 7, 2, 6 - 2h */ /* 2, 2, 2, 2, 6, 6, 6, 6 - 2h */ | |
| 3437 | RSP_VMADM(0, 1, 3, 4, 5, 7, 2, 6, 2, 2, 2, 6, 6, 6, 2, 6); | |
| 3438 | break; | |
| 3439 | case 7: /* 0, 1, 2, 4, 5, 6, 3, 7 - 3h */ /* 3, 3, 3, 3, 7, 7, 7, 7 - 3h */ | |
| 3440 | RSP_VMADM(0, 1, 2, 4, 5, 6, 3, 7, 3, 3, 3, 7, 7, 7, 3, 7); | |
| 3441 | break; | |
| 3442 | case 8: /* 1, 2, 3, 4, 5, 6, 7, 0 - 0 */ /* 0, 0, 0, 0, 0, 0, 0, 0 - 0 */ | |
| 3443 | RSP_VMADM(1, 2, 3, 4, 5, 6, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0); | |
| 3444 | break; | |
| 3445 | case 9: /* 0, 2, 3, 4, 5, 6, 7, 1 - 1 */ /* 1, 1, 1, 1, 1, 1, 1, 1 - 0 */ | |
| 3446 | RSP_VMADM(0, 2, 3, 4, 5, 6, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1); | |
| 3447 | break; | |
| 3448 | case 10: /* 0, 1, 3, 4, 5, 6, 7, 2 - 2 */ /* 2, 2, 2, 2, 2, 2, 2, 2 - 0 */ | |
| 3449 | RSP_VMADM(0, 1, 3, 4, 5, 6, 7, 2, 2, 2, 2, 2, 2, 2, 2, 2); | |
| 3450 | break; | |
| 3451 | case 11: /* 0, 1, 2, 4, 5, 6, 7, 3 - 3 */ /* 3, 3, 3, 3, 3, 3, 3, 3 - 0 */ | |
| 3452 | RSP_VMADM(0, 1, 2, 4, 5, 6, 7, 3, 3, 3, 3, 3, 3, 3, 3, 3); | |
| 3453 | break; | |
| 3454 | case 12: /* 0, 1, 2, 3, 5, 6, 7, 4 - 4 */ /* 4, 4, 4, 4, 4, 4, 4, 4 - 0 */ | |
| 3455 | RSP_VMADM(0, 1, 2, 3, 5, 6, 7, 4, 4, 4, 4, 4, 4, 4, 4, 4); | |
| 3456 | break; | |
| 3457 | case 13: /* 0, 1, 2, 3, 4, 6, 7, 5 - 5 */ /* 5, 5, 5, 5, 5, 5, 5, 5 - 0 */ | |
| 3458 | RSP_VMADM(0, 1, 2, 3, 4, 6, 7, 5, 5, 5, 5, 5, 5, 5, 5, 5); | |
| 3459 | break; | |
| 3460 | case 14: /* 0, 1, 2, 3, 4, 5, 7, 6 - 6 */ /* 6, 6, 6, 6, 6, 6, 6, 6 - 0 */ | |
| 3461 | RSP_VMADM(0, 1, 2, 3, 4, 5, 7, 6, 6, 6, 6, 6, 6, 6, 6, 6); | |
| 3462 | break; | |
| 3463 | case 15: /* 0, 1, 2, 3, 4, 5, 6, 7 - 7 */ /* 7, 7, 7, 7, 7, 7, 7, 7 - 0 */ | |
| 3464 | RSP_VMADM(0, 1, 2, 3, 4, 5, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7); | |
| 3465 | break; | |
| 3466 | } | |
| 3467 | } | |
| 3468 | #endif | |
| 2127 | sel = VEC_EL_2(EL, i); | |
| 2128 | s1 = (INT32)(INT16)VREG_S(VS1REG, i); | |
| 2129 | s2 = (UINT16)VREG_S(VS2REG, sel); // not sign-extended | |
| 2130 | r1 = s1 * s2; | |
| 2131 | r2 = (UINT16)ACCUM_L(i) + (UINT16)(r1); | |
| 2132 | r3 = (UINT16)ACCUM_M(i) + (r1 >> 16) + (r2 >> 16); | |
| 3469 | 2133 | |
| 3470 | #if (DRC_VMADN) | |
| 3471 | /*------------------------------------------------------------------ | |
| 3472 | generate_vmadn | |
| 3473 | ------------------------------------------------------------------*/ | |
| 2134 | ACCUM_L(i) = (UINT16)(r2); | |
| 2135 | ACCUM_M(i) = (UINT16)(r3); | |
| 2136 | ACCUM_H(i) += (UINT16)(r3 >> 16); | |
| 2137 | if ((INT32)(r1) < 0) | |
| 2138 | ACCUM_H(i) -= 1; | |
| 3474 | 2139 | |
| 3475 | #define RSP_VMADN_DRC(E10, E11, E12, E13, E14, E15, E16, E17, E20, E21, E22, E23, E24, E25, E26, E27, I0, I1, I2, I3, I4, I5, I6, I7) \ | |
| 3476 | { \ | |
| 3477 | UML_SEXT(block, IREG(1), VS(VS1REG, I0), WORD); \ | |
| 3478 | UML_SEXT(block, IREG(0), VS(VS2REG, E20), WORD); \ | |
| 3479 | UML_AND(block, IREG(1), IREG(1), IMM(0x0000ffff)); \ | |
| 3480 | UML_MULS(block, IREG(0), IREG(1), IREG(0), IREG(1)); \ | |
| 3481 | UML_DSEXT(block, IREG(0), IREG(0), DWORD); \ | |
| 3482 | UML_DSHL(block, IREG(0), IREG(0), IMM(16)); \ | |
| 3483 | UML_DADD(block, VACCUML(E10), VACCUML(E10), IREG(0)); \ | |
| 3484 | \ | |
| 3485 | UML_SEXT(block, IREG(1), VS(VS1REG, I1), WORD); \ | |
| 3486 | UML_SEXT(block, IREG(0), VS(VS2REG, E21), WORD); \ | |
| 3487 | UML_AND(block, IREG(1), IREG(1), IMM(0x0000ffff)); \ | |
| 3488 | UML_MULS(block, IREG(0), IREG(1), IREG(0), IREG(1)); \ | |
| 3489 | UML_DSEXT(block, IREG(0), IREG(0), DWORD); \ | |
| 3490 | UML_DSHL(block, IREG(0), IREG(0), IMM(16)); \ | |
| 3491 | UML_DADD(block, VACCUML(E11), VACCUML(E11), IREG(0)); \ | |
| 3492 | \ | |
| 3493 | UML_SEXT(block, IREG(1), VS(VS1REG, I2), WORD); \ | |
| 3494 | UML_SEXT(block, IREG(0), VS(VS2REG, E22), WORD); \ | |
| 3495 | UML_AND(block, IREG(1), IREG(1), IMM(0x0000ffff)); \ | |
| 3496 | UML_MULS(block, IREG(0), IREG(1), IREG(0), IREG(1)); \ | |
| 3497 | UML_DSEXT(block, IREG(0), IREG(0), DWORD); \ | |
| 3498 | UML_DSHL(block, IREG(0), IREG(0), IMM(16)); \ | |
| 3499 | UML_DADD(block, VACCUML(E12), VACCUML(E12), IREG(0)); \ | |
| 3500 | \ | |
| 3501 | UML_SEXT(block, IREG(1), VS(VS1REG, I3), WORD); \ | |
| 3502 | UML_SEXT(block, IREG(0), VS(VS2REG, E23), WORD); \ | |
| 3503 | UML_AND(block, IREG(1), IREG(1), IMM(0x0000ffff)); \ | |
| 3504 | UML_MULS(block, IREG(0), IREG(1), IREG(0), IREG(1)); \ | |
| 3505 | UML_DSEXT(block, IREG(0), IREG(0), DWORD); \ | |
| 3506 | UML_DSHL(block, IREG(0), IREG(0), IMM(16)); \ | |
| 3507 | UML_DADD(block, VACCUML(E13), VACCUML(E13), IREG(0)); \ | |
| 3508 | \ | |
| 3509 | UML_SEXT(block, IREG(1), VS(VS1REG, I4), WORD); \ | |
| 3510 | UML_SEXT(block, IREG(0), VS(VS2REG, E24), WORD); \ | |
| 3511 | UML_AND(block, IREG(1), IREG(1), IMM(0x0000ffff)); \ | |
| 3512 | UML_MULS(block, IREG(0), IREG(1), IREG(0), IREG(1)); \ | |
| 3513 | UML_DSEXT(block, IREG(0), IREG(0), DWORD); \ | |
| 3514 | UML_DSHL(block, IREG(0), IREG(0), IMM(16)); \ | |
| 3515 | UML_DADD(block, VACCUML(E14), VACCUML(E14), IREG(0)); \ | |
| 3516 | \ | |
| 3517 | UML_SEXT(block, IREG(1), VS(VS1REG, I5), WORD); \ | |
| 3518 | UML_SEXT(block, IREG(0), VS(VS2REG, E25), WORD); \ | |
| 3519 | UML_AND(block, IREG(1), IREG(1), IMM(0x0000ffff)); \ | |
| 3520 | UML_MULS(block, IREG(0), IREG(1), IREG(0), IREG(1)); \ | |
| 3521 | UML_DSEXT(block, IREG(0), IREG(0), DWORD); \ | |
| 3522 | UML_DSHL(block, IREG(0), IREG(0), IMM(16)); \ | |
| 3523 | UML_DADD(block, VACCUML(E15), VACCUML(E15), IREG(0)); \ | |
| 3524 | \ | |
| 3525 | UML_SEXT(block, IREG(1), VS(VS1REG, I6), WORD); \ | |
| 3526 | UML_SEXT(block, IREG(0), VS(VS2REG, E26), WORD); \ | |
| 3527 | UML_AND(block, IREG(1), IREG(1), IMM(0x0000ffff)); \ | |
| 3528 | UML_MULS(block, IREG(0), IREG(1), IREG(0), IREG(1)); \ | |
| 3529 | UML_DSEXT(block, IREG(0), IREG(0), DWORD); \ | |
| 3530 | UML_DSHL(block, IREG(0), IREG(0), IMM(16)); \ | |
| 3531 | UML_DADD(block, VACCUML(E16), VACCUML(E16), IREG(0)); \ | |
| 3532 | \ | |
| 3533 | UML_SEXT(block, IREG(1), VS(VS1REG, I7), WORD); \ | |
| 3534 | UML_SEXT(block, IREG(0), VS(VS2REG, E27), WORD); \ | |
| 3535 | UML_AND(block, IREG(1), IREG(1), IMM(0x0000ffff)); \ | |
| 3536 | UML_MULS(block, IREG(0), IREG(1), IREG(0), IREG(1)); \ | |
| 3537 | UML_DSEXT(block, IREG(0), IREG(0), DWORD); \ | |
| 3538 | UML_DSHL(block, IREG(0), IREG(0), IMM(16)); \ | |
| 3539 | UML_DADD(block, VACCUML(E17), VACCUML(E17), IREG(0)); \ | |
| 3540 | \ | |
| 3541 | generate_saturate_accum_unsigned(rsp, block, compiler, desc, E10); \ | |
| 3542 | UML_STORE(block, &rsp->v[VDREG].s[I0], IMM(0), IREG(0), WORD); \ | |
| 3543 | generate_saturate_accum_unsigned(rsp, block, compiler, desc, E11); \ | |
| 3544 | UML_STORE(block, &rsp->v[VDREG].s[I1], IMM(0), IREG(0), WORD); \ | |
| 3545 | generate_saturate_accum_unsigned(rsp, block, compiler, desc, E12); \ | |
| 3546 | UML_STORE(block, &rsp->v[VDREG].s[I2], IMM(0), IREG(0), WORD); \ | |
| 3547 | generate_saturate_accum_unsigned(rsp, block, compiler, desc, E13); \ | |
| 3548 | UML_STORE(block, &rsp->v[VDREG].s[I3], IMM(0), IREG(0), WORD); \ | |
| 3549 | generate_saturate_accum_unsigned(rsp, block, compiler, desc, E14); \ | |
| 3550 | UML_STORE(block, &rsp->v[VDREG].s[I4], IMM(0), IREG(0), WORD); \ | |
| 3551 | generate_saturate_accum_unsigned(rsp, block, compiler, desc, E15); \ | |
| 3552 | UML_STORE(block, &rsp->v[VDREG].s[I5], IMM(0), IREG(0), WORD); \ | |
| 3553 | generate_saturate_accum_unsigned(rsp, block, compiler, desc, E16); \ | |
| 3554 | UML_STORE(block, &rsp->v[VDREG].s[I6], IMM(0), IREG(0), WORD); \ | |
| 3555 | generate_saturate_accum_unsigned(rsp, block, compiler, desc, E17); \ | |
| 3556 | UML_STORE(block, &rsp->v[VDREG].s[I7], IMM(0), IREG(0), WORD); \ | |
| 3557 | } | |
| 2140 | res = SATURATE_ACCUM(rsp, i, 1, 0x8000, 0x7fff); | |
| 3558 | 2141 | |
| 3559 | static int generate_vmadn(rsp_state *rsp, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) // vmadn | |
| 3560 | { | |
| 3561 | UINT32 op = desc->opptr.l[0]; | |
| 3562 | ||
| 3563 | // 31 25 24 20 15 10 5 0 | |
| 3564 | // ------------------------------------------------------ | |
| 3565 | // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 001110 | | |
| 3566 | // ------------------------------------------------------ | |
| 3567 | // | |
| 3568 | // Multiplies unsigned fraction by signed integer | |
| 3569 | // The result is added into accumulator | |
| 3570 | // The low slice of accumulator is stored into destination element | |
| 3571 | switch(EL) | |
| 3572 | { | |
| 3573 | case 0: /* 0, 1, 2, 3, 4, 5, 6, 7 - none */ /* 0, 1, 2, 3, 4, 5, 6, 7 - none */ | |
| 3574 | RSP_VMADN_DRC(0, 1, 2, 3, 4, 5, 6, 7, 7, 6, 5, 4, 3, 2, 1, 0, 7, 6, 5, 4, 3, 2, 1, 0); | |
| 3575 | return TRUE; | |
| 3576 | case 1: /* 0, 1, 2, 3, 4, 5, 6, 7 - ??? */ /* 0, 1, 2, 3, 4, 5, 6, 7 - ??? */ | |
| 3577 | RSP_VMADN_DRC(0, 1, 2, 3, 4, 5, 6, 7, 7, 6, 5, 4, 3, 2, 1, 0, 7, 6, 5, 4, 3, 2, 1, 0); | |
| 3578 | return TRUE; | |
| 3579 | case 2: /* 1, 3, 5, 7, 0, 2, 4, 6 - 0q */ /* 0, 0, 2, 2, 4, 4, 6, 6 - 0q */ | |
| 3580 | RSP_VMADN_DRC(1, 3, 5, 7, 0, 2, 4, 6, 7, 5, 3, 1, 7, 5, 3, 1, 6, 4, 2, 0, 7, 5, 3, 1); | |
| 3581 | return TRUE; | |
| 3582 | case 3: /* 0, 2, 4, 6, 1, 3, 5, 7 - 1q */ /* 1, 1, 3, 3, 5, 5, 7, 7 - 1q */ | |
| 3583 | RSP_VMADN_DRC(0, 2, 4, 6, 1, 3, 5, 7, 6, 4, 2, 0, 6, 4, 2, 0, 7, 5, 3, 1, 6, 4, 2, 0); | |
| 3584 | return TRUE; | |
| 3585 | case 4: /* 1, 2, 3, 5, 6, 7, 0, 4 - 0h */ /* 0, 0, 0, 0, 4, 4, 4, 4 - 0h */ | |
| 3586 | RSP_VMADN_DRC(1, 2, 3, 5, 6, 7, 0, 4, 7, 7, 7, 3, 3, 3, 7, 3, 6, 5, 4, 2, 1, 0, 7, 3); | |
| 3587 | return TRUE; | |
| 3588 | case 5: /* 0, 2, 3, 4, 6, 7, 1, 5 - 1h */ /* 1, 1, 1, 1, 5, 5, 5, 5 - 1h */ | |
| 3589 | RSP_VMADN_DRC(0, 2, 3, 4, 6, 7, 1, 5, 6, 6, 6, 2, 2, 2, 6, 2, 7, 5, 4, 3, 1, 0, 6, 2); | |
| 3590 | return TRUE; | |
| 3591 | case 6: /* 0, 1, 3, 4, 5, 7, 2, 6 - 2h */ /* 2, 2, 2, 2, 6, 6, 6, 6 - 2h */ | |
| 3592 | RSP_VMADN_DRC(0, 1, 3, 4, 5, 7, 2, 6, 5, 5, 5, 1, 1, 1, 5, 1, 7, 6, 4, 3, 2, 0, 5, 1); | |
| 3593 | return TRUE; | |
| 3594 | case 7: /* 0, 1, 2, 4, 5, 6, 3, 7 - 3h */ /* 3, 3, 3, 3, 7, 7, 7, 7 - 3h */ | |
| 3595 | RSP_VMADN_DRC(0, 1, 2, 4, 5, 6, 3, 7, 4, 4, 4, 0, 0, 0, 4, 0, 7, 6, 5, 3, 2, 1, 4, 0); | |
| 3596 | return TRUE; | |
| 3597 | case 8: /* 1, 2, 3, 4, 5, 6, 7, 0 - 0 */ /* 0, 0, 0, 0, 0, 0, 0, 0 - 0 */ | |
| 3598 | RSP_VMADN_DRC(1, 2, 3, 4, 5, 6, 7, 0, 7, 7, 7, 7, 7, 7, 7, 7, 6, 5, 4, 3, 2, 1, 0, 7); | |
| 3599 | return TRUE; | |
| 3600 | case 9: /* 0, 2, 3, 4, 5, 6, 7, 1 - 1 */ /* 1, 1, 1, 1, 1, 1, 1, 1 - 0 */ | |
| 3601 | RSP_VMADN_DRC(0, 2, 3, 4, 5, 6, 7, 1, 6, 6, 6, 6, 6, 6, 6, 6, 7, 5, 4, 3, 2, 1, 0, 6); | |
| 3602 | return TRUE; | |
| 3603 | case 10: /* 0, 1, 3, 4, 5, 6, 7, 2 - 2 */ /* 2, 2, 2, 2, 2, 2, 2, 2 - 0 */ | |
| 3604 | RSP_VMADN_DRC(0, 1, 3, 4, 5, 6, 7, 2, 5, 5, 5, 5, 5, 5, 5, 5, 7, 6, 4, 3, 2, 1, 0, 5); | |
| 3605 | return TRUE; | |
| 3606 | case 11: /* 0, 1, 2, 4, 5, 6, 7, 3 - 3 */ /* 3, 3, 3, 3, 3, 3, 3, 3 - 0 */ | |
| 3607 | RSP_VMADN_DRC(0, 1, 2, 4, 5, 6, 7, 3, 4, 4, 4, 4, 4, 4, 4, 4, 7, 6, 5, 3, 2, 1, 0, 4); | |
| 3608 | return TRUE; | |
| 3609 | case 12: /* 0, 1, 2, 3, 5, 6, 7, 4 - 4 */ /* 4, 4, 4, 4, 4, 4, 4, 4 - 0 */ | |
| 3610 | RSP_VMADN_DRC(0, 1, 2, 3, 5, 6, 7, 4, 3, 3, 3, 3, 3, 3, 3, 3, 7, 6, 5, 4, 2, 1, 0, 3); | |
| 3611 | return TRUE; | |
| 3612 | case 13: /* 0, 1, 2, 3, 4, 6, 7, 5 - 5 */ /* 5, 5, 5, 5, 5, 5, 5, 5 - 0 */ | |
| 3613 | RSP_VMADN_DRC(0, 1, 2, 3, 4, 6, 7, 5, 2, 2, 2, 2, 2, 2, 2, 2, 7, 6, 5, 4, 3, 1, 0, 2); | |
| 3614 | return TRUE; | |
| 3615 | case 14: /* 0, 1, 2, 3, 4, 5, 7, 6 - 6 */ /* 6, 6, 6, 6, 6, 6, 6, 6 - 0 */ | |
| 3616 | RSP_VMADN_DRC(0, 1, 2, 3, 4, 5, 7, 6, 1, 1, 1, 1, 1, 1, 1, 1, 7, 6, 5, 4, 3, 2, 0, 1); | |
| 3617 | return TRUE; | |
| 3618 | case 15: /* 0, 1, 2, 3, 4, 5, 6, 7 - 7 */ /* 7, 7, 7, 7, 7, 7, 7, 7 - 0 */ | |
| 3619 | RSP_VMADN_DRC(0, 1, 2, 3, 4, 5, 6, 7, 0, 0, 0, 0, 0, 0, 0, 0, 7, 6, 5, 4, 3, 2, 1, 0); | |
| 3620 | return TRUE; | |
| 2142 | vres[i] = res; | |
| 3621 | 2143 | } |
| 3622 | ||
| 3623 | return TRUE; | |
| 2144 | WRITEBACK_RESULT(); | |
| 3624 | 2145 | } |
| 3625 | #else | |
| 3626 | #define RSP_VMADN(E10, E11, E12, E13, E14, E15, E16, E17, E20, E21, E22, E23, E24, E25, E26, E27, I0, I1, I2, I3, I4, I5, I6, I7) \ | |
| 3627 | { \ | |
| 3628 | ACCUM(E10).l += ((UINT16)R_VREG_S_X(VS1REG, I0) * (INT64)R_VREG_S_X(VS2REG, E20)) << 16; \ | |
| 3629 | ACCUM(E11).l += ((UINT16)R_VREG_S_X(VS1REG, I1) * (INT64)R_VREG_S_X(VS2REG, E21)) << 16; \ | |
| 3630 | ACCUM(E12).l += ((UINT16)R_VREG_S_X(VS1REG, I2) * (INT64)R_VREG_S_X(VS2REG, E22)) << 16; \ | |
| 3631 | ACCUM(E13).l += ((UINT16)R_VREG_S_X(VS1REG, I3) * (INT64)R_VREG_S_X(VS2REG, E23)) << 16; \ | |
| 3632 | ACCUM(E14).l += ((UINT16)R_VREG_S_X(VS1REG, I4) * (INT64)R_VREG_S_X(VS2REG, E24)) << 16; \ | |
| 3633 | ACCUM(E15).l += ((UINT16)R_VREG_S_X(VS1REG, I5) * (INT64)R_VREG_S_X(VS2REG, E25)) << 16; \ | |
| 3634 | ACCUM(E16).l += ((UINT16)R_VREG_S_X(VS1REG, I6) * (INT64)R_VREG_S_X(VS2REG, E26)) << 16; \ | |
| 3635 | ACCUM(E17).l += ((UINT16)R_VREG_S_X(VS1REG, I7) * (INT64)R_VREG_S_X(VS2REG, E27)) << 16; \ | |
| 3636 | vres[E10] = SATURATE_ACCUM_UNSIGNED(rsp, E10); \ | |
| 3637 | vres[E11] = SATURATE_ACCUM_UNSIGNED(rsp, E11); \ | |
| 3638 | vres[E12] = SATURATE_ACCUM_UNSIGNED(rsp, E12); \ | |
| 3639 | vres[E13] = SATURATE_ACCUM_UNSIGNED(rsp, E13); \ | |
| 3640 | vres[E14] = SATURATE_ACCUM_UNSIGNED(rsp, E14); \ | |
| 3641 | vres[E15] = SATURATE_ACCUM_UNSIGNED(rsp, E15); \ | |
| 3642 | vres[E16] = SATURATE_ACCUM_UNSIGNED(rsp, E16); \ | |
| 3643 | vres[E17] = SATURATE_ACCUM_UNSIGNED(rsp, E17); \ | |
| 3644 | W_VREG_S_X(VDREG, 7, vres[0]); \ | |
| 3645 | W_VREG_S_X(VDREG, 6, vres[1]); \ | |
| 3646 | W_VREG_S_X(VDREG, 5, vres[2]); \ | |
| 3647 | W_VREG_S_X(VDREG, 4, vres[3]); \ | |
| 3648 | W_VREG_S_X(VDREG, 3, vres[4]); \ | |
| 3649 | W_VREG_S_X(VDREG, 2, vres[5]); \ | |
| 3650 | W_VREG_S_X(VDREG, 1, vres[6]); \ | |
| 3651 | W_VREG_S_X(VDREG, 0, vres[7]); \ | |
| 3652 | } | |
| 3653 | 2146 | |
| 3654 | 2147 | INLINE void cfunc_rsp_vmadn(void *param) |
| 3655 | 2148 | { |
| 3656 | 2149 | rsp_state *rsp = (rsp_state*)param; |
| 3657 | 2150 | int op = rsp->impstate->arg0; |
| 3658 | 2151 | INT16 vres[8]; |
| 3659 | // 31 25 24 20 15 10 5 0 | |
| 3660 | // ------------------------------------------------------ | |
| 3661 | // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 001110 | | |
| 3662 | // ------------------------------------------------------ | |
| 3663 | // | |
| 3664 | // Multiplies unsigned fraction by signed integer | |
| 3665 | // The result is added into accumulator | |
| 3666 | // The low slice of accumulator is stored into destination element | |
| 3667 | switch(EL) | |
| 2152 | ||
| 2153 | INT32 s1, s2; | |
| 2154 | UINT16 res; | |
| 2155 | int sel; | |
| 2156 | for (int i = 0; i < 8; i++) | |
| 3668 | 2157 | { |
| 3669 | case 0: /* 0, 1, 2, 3, 4, 5, 6, 7 - none */ /* 0, 1, 2, 3, 4, 5, 6, 7 - none */ | |
| 3670 | RSP_VMADN(0, 1, 2, 3, 4, 5, 6, 7, 7, 6, 5, 4, 3, 2, 1, 0, 7, 6, 5, 4, 3, 2, 1, 0); | |
| 3671 | break; | |
| 3672 | case 1: /* 0, 1, 2, 3, 4, 5, 6, 7 - ??? */ /* 0, 1, 2, 3, 4, 5, 6, 7 - ??? */ | |
| 3673 | RSP_VMADN(0, 1, 2, 3, 4, 5, 6, 7, 7, 6, 5, 4, 3, 2, 1, 0, 7, 6, 5, 4, 3, 2, 1, 0); | |
| 3674 | break; | |
| 3675 | case 2: /* 1, 3, 5, 7, 0, 2, 4, 6 - 0q */ /* 0, 0, 2, 2, 4, 4, 6, 6 - 0q */ | |
| 3676 | RSP_VMADN(1, 3, 5, 7, 0, 2, 4, 6, 7, 5, 3, 1, 7, 5, 3, 1, 6, 4, 2, 0, 7, 5, 3, 1); | |
| 3677 | break; | |
| 3678 | case 3: /* 0, 2, 4, 6, 1, 3, 5, 7 - 1q */ /* 1, 1, 3, 3, 5, 5, 7, 7 - 1q */ | |
| 3679 | RSP_VMADN(0, 2, 4, 6, 1, 3, 5, 7, 6, 4, 2, 0, 6, 4, 2, 0, 7, 5, 3, 1, 6, 4, 2, 0); | |
| 3680 | break; | |
| 3681 | case 4: /* 1, 2, 3, 5, 6, 7, 0, 4 - 0h */ /* 0, 0, 0, 0, 4, 4, 4, 4 - 0h */ | |
| 3682 | RSP_VMADN(1, 2, 3, 5, 6, 7, 0, 4, 7, 7, 7, 3, 3, 3, 7, 3, 6, 5, 4, 2, 1, 0, 7, 3); | |
| 3683 | break; | |
| 3684 | case 5: /* 0, 2, 3, 4, 6, 7, 1, 5 - 1h */ /* 1, 1, 1, 1, 5, 5, 5, 5 - 1h */ | |
| 3685 | RSP_VMADN(0, 2, 3, 4, 6, 7, 1, 5, 6, 6, 6, 2, 2, 2, 6, 2, 7, 5, 4, 3, 1, 0, 6, 2); | |
| 3686 | break; | |
| 3687 | case 6: /* 0, 1, 3, 4, 5, 7, 2, 6 - 2h */ /* 2, 2, 2, 2, 6, 6, 6, 6 - 2h */ | |
| 3688 | RSP_VMADN(0, 1, 3, 4, 5, 7, 2, 6, 5, 5, 5, 1, 1, 1, 5, 1, 7, 6, 4, 3, 2, 0, 5, 1); | |
| 3689 | break; | |
| 3690 | case 7: /* 0, 1, 2, 4, 5, 6, 3, 7 - 3h */ /* 3, 3, 3, 3, 7, 7, 7, 7 - 3h */ | |
| 3691 | RSP_VMADN(0, 1, 2, 4, 5, 6, 3, 7, 4, 4, 4, 0, 0, 0, 4, 0, 7, 6, 5, 3, 2, 1, 4, 0); | |
| 3692 | break; | |
| 3693 | case 8: /* 1, 2, 3, 4, 5, 6, 7, 0 - 0 */ /* 0, 0, 0, 0, 0, 0, 0, 0 - 0 */ | |
| 3694 | RSP_VMADN(1, 2, 3, 4, 5, 6, 7, 0, 7, 7, 7, 7, 7, 7, 7, 7, 6, 5, 4, 3, 2, 1, 0, 7); | |
| 3695 | break; | |
| 3696 | case 9: /* 0, 2, 3, 4, 5, 6, 7, 1 - 1 */ /* 1, 1, 1, 1, 1, 1, 1, 1 - 0 */ | |
| 3697 | RSP_VMADN(0, 2, 3, 4, 5, 6, 7, 1, 6, 6, 6, 6, 6, 6, 6, 6, 7, 5, 4, 3, 2, 1, 0, 6); | |
| 3698 | break; | |
| 3699 | case 10: /* 0, 1, 3, 4, 5, 6, 7, 2 - 2 */ /* 2, 2, 2, 2, 2, 2, 2, 2 - 0 */ | |
| 3700 | RSP_VMADN(0, 1, 3, 4, 5, 6, 7, 2, 5, 5, 5, 5, 5, 5, 5, 5, 7, 6, 4, 3, 2, 1, 0, 5); | |
| 3701 | break; | |
| 3702 | case 11: /* 0, 1, 2, 4, 5, 6, 7, 3 - 3 */ /* 3, 3, 3, 3, 3, 3, 3, 3 - 0 */ | |
| 3703 | RSP_VMADN(0, 1, 2, 4, 5, 6, 7, 3, 4, 4, 4, 4, 4, 4, 4, 4, 7, 6, 5, 3, 2, 1, 0, 4); | |
| 3704 | break; | |
| 3705 | case 12: /* 0, 1, 2, 3, 5, 6, 7, 4 - 4 */ /* 4, 4, 4, 4, 4, 4, 4, 4 - 0 */ | |
| 3706 | RSP_VMADN(0, 1, 2, 3, 5, 6, 7, 4, 3, 3, 3, 3, 3, 3, 3, 3, 7, 6, 5, 4, 2, 1, 0, 3); | |
| 3707 | break; | |
| 3708 | case 13: /* 0, 1, 2, 3, 4, 6, 7, 5 - 5 */ /* 5, 5, 5, 5, 5, 5, 5, 5 - 0 */ | |
| 3709 | RSP_VMADN(0, 1, 2, 3, 4, 6, 7, 5, 2, 2, 2, 2, 2, 2, 2, 2, 7, 6, 5, 4, 3, 1, 0, 2); | |
| 3710 | break; | |
| 3711 | case 14: /* 0, 1, 2, 3, 4, 5, 7, 6 - 6 */ /* 6, 6, 6, 6, 6, 6, 6, 6 - 0 */ | |
| 3712 | RSP_VMADN(0, 1, 2, 3, 4, 5, 7, 6, 1, 1, 1, 1, 1, 1, 1, 1, 7, 6, 5, 4, 3, 2, 0, 1); | |
| 3713 | break; | |
| 3714 | case 15: /* 0, 1, 2, 3, 4, 5, 6, 7 - 7 */ /* 7, 7, 7, 7, 7, 7, 7, 7 - 0 */ | |
| 3715 | RSP_VMADN(0, 1, 2, 3, 4, 5, 6, 7, 0, 0, 0, 0, 0, 0, 0, 0, 7, 6, 5, 4, 3, 2, 1, 0); | |
| 3716 | break; | |
| 3717 | } | |
| 3718 | } | |
| 3719 | #endif | |
| 2158 | sel = VEC_EL_2(EL, i); | |
| 2159 | s1 = (UINT16)VREG_S(VS1REG, i); // not sign-extended | |
| 2160 | s2 = (INT32)(INT16)VREG_S(VS2REG, sel); | |
| 3720 | 2161 | |
| 3721 | #if (DRC_VMADH) | |
| 3722 | /*------------------------------------------------------------------ | |
| 3723 | generate_vmadh | |
| 3724 | ------------------------------------------------------------------*/ | |
| 2162 | ACCUM(i) += (INT64)(s1*s2)<<16; | |
| 3725 | 2163 | |
| 3726 | #define RSP_VMADH_DRC(E10, E11, E12, E13, E14, E15, E16, E17, E20, E21, E22, E23, E24, E25, E26, E27, I0, I1, I2, I3, I4, I5, I6, I7) \ | |
| 3727 | { \ | |
| 3728 | UML_SEXT(block, IREG(1), VS(VS1REG, I0), WORD); \ | |
| 3729 | UML_SEXT(block, IREG(0), VS(VS2REG, E20), WORD); \ | |
| 3730 | UML_MULS(block, IREG(0), IREG(1), IREG(0), IREG(1)); \ | |
| 3731 | UML_ADD(block, VACCUMWMH(E10), VACCUMWMH(E10), IREG(0)); \ | |
| 3732 | \ | |
| 3733 | UML_SEXT(block, IREG(1), VS(VS1REG, I1), WORD); \ | |
| 3734 | UML_SEXT(block, IREG(0), VS(VS2REG, E21), WORD); \ | |
| 3735 | UML_MULS(block, IREG(0), IREG(1), IREG(0), IREG(1)); \ | |
| 3736 | UML_ADD(block, VACCUMWMH(E11), VACCUMWMH(E11), IREG(0)); \ | |
| 3737 | \ | |
| 3738 | UML_SEXT(block, IREG(1), VS(VS1REG, I2), WORD); \ | |
| 3739 | UML_SEXT(block, IREG(0), VS(VS2REG, E22), WORD); \ | |
| 3740 | UML_MULS(block, IREG(0), IREG(1), IREG(0), IREG(1)); \ | |
| 3741 | UML_ADD(block, VACCUMWMH(E12), VACCUMWMH(E12), IREG(0)); \ | |
| 3742 | \ | |
| 3743 | UML_SEXT(block, IREG(1), VS(VS1REG, I3), WORD); \ | |
| 3744 | UML_SEXT(block, IREG(0), VS(VS2REG, E23), WORD); \ | |
| 3745 | UML_MULS(block, IREG(0), IREG(1), IREG(0), IREG(1)); \ | |
| 3746 | UML_ADD(block, VACCUMWMH(E13), VACCUMWMH(E13), IREG(0)); \ | |
| 3747 | \ | |
| 3748 | UML_SEXT(block, IREG(1), VS(VS1REG, I4), WORD); \ | |
| 3749 | UML_SEXT(block, IREG(0), VS(VS2REG, E24), WORD); \ | |
| 3750 | UML_MULS(block, IREG(0), IREG(1), IREG(0), IREG(1)); \ | |
| 3751 | UML_ADD(block, VACCUMWMH(E14), VACCUMWMH(E14), IREG(0)); \ | |
| 3752 | \ | |
| 3753 | UML_SEXT(block, IREG(1), VS(VS1REG, I5), WORD); \ | |
| 3754 | UML_SEXT(block, IREG(0), VS(VS2REG, E25), WORD); \ | |
| 3755 | UML_MULS(block, IREG(0), IREG(1), IREG(0), IREG(1)); \ | |
| 3756 | UML_ADD(block, VACCUMWMH(E15), VACCUMWMH(E15), IREG(0)); \ | |
| 3757 | \ | |
| 3758 | UML_SEXT(block, IREG(1), VS(VS1REG, I6), WORD); \ | |
| 3759 | UML_SEXT(block, IREG(0), VS(VS2REG, E26), WORD); \ | |
| 3760 | UML_MULS(block, IREG(0), IREG(1), IREG(0), IREG(1)); \ | |
| 3761 | UML_ADD(block, VACCUMWMH(E16), VACCUMWMH(E16), IREG(0)); \ | |
| 3762 | \ | |
| 3763 | UML_SEXT(block, IREG(1), VS(VS1REG, I7), WORD); \ | |
| 3764 | UML_SEXT(block, IREG(0), VS(VS2REG, E27), WORD); \ | |
| 3765 | UML_MULS(block, IREG(0), IREG(1), IREG(0), IREG(1)); \ | |
| 3766 | UML_ADD(block, VACCUMWMH(E17), VACCUMWMH(E17), IREG(0)); \ | |
| 3767 | \ | |
| 3768 | generate_saturate_accum_signed(rsp, block, compiler, desc, E10); \ | |
| 3769 | UML_STORE(block, &rsp->v[VDREG].s[I0], IMM(0), IREG(0), WORD); \ | |
| 3770 | generate_saturate_accum_signed(rsp, block, compiler, desc, E11); \ | |
| 3771 | UML_STORE(block, &rsp->v[VDREG].s[I1], IMM(0), IREG(0), WORD); \ | |
| 3772 | generate_saturate_accum_signed(rsp, block, compiler, desc, E12); \ | |
| 3773 | UML_STORE(block, &rsp->v[VDREG].s[I2], IMM(0), IREG(0), WORD); \ | |
| 3774 | generate_saturate_accum_signed(rsp, block, compiler, desc, E13); \ | |
| 3775 | UML_STORE(block, &rsp->v[VDREG].s[I3], IMM(0), IREG(0), WORD); \ | |
| 3776 | generate_saturate_accum_signed(rsp, block, compiler, desc, E14); \ | |
| 3777 | UML_STORE(block, &rsp->v[VDREG].s[I4], IMM(0), IREG(0), WORD); \ | |
| 3778 | generate_saturate_accum_signed(rsp, block, compiler, desc, E15); \ | |
| 3779 | UML_STORE(block, &rsp->v[VDREG].s[I5], IMM(0), IREG(0), WORD); \ | |
| 3780 | generate_saturate_accum_signed(rsp, block, compiler, desc, E16); \ | |
| 3781 | UML_STORE(block, &rsp->v[VDREG].s[I6], IMM(0), IREG(0), WORD); \ | |
| 3782 | generate_saturate_accum_signed(rsp, block, compiler, desc, E17); \ | |
| 3783 | UML_STORE(block, &rsp->v[VDREG].s[I7], IMM(0), IREG(0), WORD); \ | |
| 2164 | res = SATURATE_ACCUM(rsp, i, 0, 0x0000, 0xffff); | |
| 2165 | vres[i] = res; | |
| 3784 | 2166 | } |
| 3785 | ||
| 3786 | static int generate_vmadh(rsp_state *rsp, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) // vmadh | |
| 3787 | { | |
| 3788 | UINT32 op = desc->opptr.l[0]; | |
| 3789 | ||
| 3790 | // 31 25 24 20 15 10 5 0 | |
| 3791 | // ------------------------------------------------------ | |
| 3792 | // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 001110 | | |
| 3793 | // ------------------------------------------------------ | |
| 3794 | // | |
| 3795 | // Multiplies unsigned fraction by signed integer | |
| 3796 | // The result is added into accumulator | |
| 3797 | // The low slice of accumulator is stored into destination element | |
| 3798 | switch(EL) | |
| 3799 | { | |
| 3800 | case 0: /* 0, 1, 2, 3, 4, 5, 6, 7 - none */ /* 0, 1, 2, 3, 4, 5, 6, 7 - none */ | |
| 3801 | RSP_VMADH_DRC(0, 1, 2, 3, 4, 5, 6, 7, 7, 6, 5, 4, 3, 2, 1, 0, 7, 6, 5, 4, 3, 2, 1, 0); | |
| 3802 | return TRUE; | |
| 3803 | case 1: /* 0, 1, 2, 3, 4, 5, 6, 7 - ??? */ /* 0, 1, 2, 3, 4, 5, 6, 7 - ??? */ | |
| 3804 | RSP_VMADH_DRC(0, 1, 2, 3, 4, 5, 6, 7, 7, 6, 5, 4, 3, 2, 1, 0, 7, 6, 5, 4, 3, 2, 1, 0); | |
| 3805 | return TRUE; | |
| 3806 | case 2: /* 1, 3, 5, 7, 0, 2, 4, 6 - 0q */ /* 0, 0, 2, 2, 4, 4, 6, 6 - 0q */ | |
| 3807 | RSP_VMADH_DRC(1, 3, 5, 7, 0, 2, 4, 6, 7, 5, 3, 1, 7, 5, 3, 1, 6, 4, 2, 0, 7, 5, 3, 1); | |
| 3808 | return TRUE; | |
| 3809 | case 3: /* 0, 2, 4, 6, 1, 3, 5, 7 - 1q */ /* 1, 1, 3, 3, 5, 5, 7, 7 - 1q */ | |
| 3810 | RSP_VMADH_DRC(0, 2, 4, 6, 1, 3, 5, 7, 6, 4, 2, 0, 6, 4, 2, 0, 7, 5, 3, 1, 6, 4, 2, 0); | |
| 3811 | return TRUE; | |
| 3812 | case 4: /* 1, 2, 3, 5, 6, 7, 0, 4 - 0h */ /* 0, 0, 0, 0, 4, 4, 4, 4 - 0h */ | |
| 3813 | RSP_VMADH_DRC(1, 2, 3, 5, 6, 7, 0, 4, 7, 7, 7, 3, 3, 3, 7, 3, 6, 5, 4, 2, 1, 0, 7, 3); | |
| 3814 | return TRUE; | |
| 3815 | case 5: /* 0, 2, 3, 4, 6, 7, 1, 5 - 1h */ /* 1, 1, 1, 1, 5, 5, 5, 5 - 1h */ | |
| 3816 | RSP_VMADH_DRC(0, 2, 3, 4, 6, 7, 1, 5, 6, 6, 6, 2, 2, 2, 6, 2, 7, 5, 4, 3, 1, 0, 6, 2); | |
| 3817 | return TRUE; | |
| 3818 | case 6: /* 0, 1, 3, 4, 5, 7, 2, 6 - 2h */ /* 2, 2, 2, 2, 6, 6, 6, 6 - 2h */ | |
| 3819 | RSP_VMADH_DRC(0, 1, 3, 4, 5, 7, 2, 6, 5, 5, 5, 1, 1, 1, 5, 1, 7, 6, 4, 3, 2, 0, 5, 1); | |
| 3820 | return TRUE; | |
| 3821 | case 7: /* 0, 1, 2, 4, 5, 6, 3, 7 - 3h */ /* 3, 3, 3, 3, 7, 7, 7, 7 - 3h */ | |
| 3822 | RSP_VMADH_DRC(0, 1, 2, 4, 5, 6, 3, 7, 4, 4, 4, 0, 0, 0, 4, 0, 7, 6, 5, 3, 2, 1, 4, 0); | |
| 3823 | return TRUE; | |
| 3824 | case 8: /* 1, 2, 3, 4, 5, 6, 7, 0 - 0 */ /* 0, 0, 0, 0, 0, 0, 0, 0 - 0 */ | |
| 3825 | RSP_VMADH_DRC(1, 2, 3, 4, 5, 6, 7, 0, 7, 7, 7, 7, 7, 7, 7, 7, 6, 5, 4, 3, 2, 1, 0, 7); | |
| 3826 | return TRUE; | |
| 3827 | case 9: /* 0, 2, 3, 4, 5, 6, 7, 1 - 1 */ /* 1, 1, 1, 1, 1, 1, 1, 1 - 0 */ | |
| 3828 | RSP_VMADH_DRC(0, 2, 3, 4, 5, 6, 7, 1, 6, 6, 6, 6, 6, 6, 6, 6, 7, 5, 4, 3, 2, 1, 0, 6); | |
| 3829 | return TRUE; | |
| 3830 | case 10: /* 0, 1, 3, 4, 5, 6, 7, 2 - 2 */ /* 2, 2, 2, 2, 2, 2, 2, 2 - 0 */ | |
| 3831 | RSP_VMADH_DRC(0, 1, 3, 4, 5, 6, 7, 2, 5, 5, 5, 5, 5, 5, 5, 5, 7, 6, 4, 3, 2, 1, 0, 5); | |
| 3832 | return TRUE; | |
| 3833 | case 11: /* 0, 1, 2, 4, 5, 6, 7, 3 - 3 */ /* 3, 3, 3, 3, 3, 3, 3, 3 - 0 */ | |
| 3834 | RSP_VMADH_DRC(0, 1, 2, 4, 5, 6, 7, 3, 4, 4, 4, 4, 4, 4, 4, 4, 7, 6, 5, 3, 2, 1, 0, 4); | |
| 3835 | return TRUE; | |
| 3836 | case 12: /* 0, 1, 2, 3, 5, 6, 7, 4 - 4 */ /* 4, 4, 4, 4, 4, 4, 4, 4 - 0 */ | |
| 3837 | RSP_VMADH_DRC(0, 1, 2, 3, 5, 6, 7, 4, 3, 3, 3, 3, 3, 3, 3, 3, 7, 6, 5, 4, 2, 1, 0, 3); | |
| 3838 | return TRUE; | |
| 3839 | case 13: /* 0, 1, 2, 3, 4, 6, 7, 5 - 5 */ /* 5, 5, 5, 5, 5, 5, 5, 5 - 0 */ | |
| 3840 | RSP_VMADH_DRC(0, 1, 2, 3, 4, 6, 7, 5, 2, 2, 2, 2, 2, 2, 2, 2, 7, 6, 5, 4, 3, 1, 0, 2); | |
| 3841 | return TRUE; | |
| 3842 | case 14: /* 0, 1, 2, 3, 4, 5, 7, 6 - 6 */ /* 6, 6, 6, 6, 6, 6, 6, 6 - 0 */ | |
| 3843 | RSP_VMADH_DRC(0, 1, 2, 3, 4, 5, 7, 6, 1, 1, 1, 1, 1, 1, 1, 1, 7, 6, 5, 4, 3, 2, 0, 1); | |
| 3844 | return TRUE; | |
| 3845 | case 15: /* 0, 1, 2, 3, 4, 5, 6, 7 - 7 */ /* 7, 7, 7, 7, 7, 7, 7, 7 - 0 */ | |
| 3846 | RSP_VMADH_DRC(0, 1, 2, 3, 4, 5, 6, 7, 0, 0, 0, 0, 0, 0, 0, 0, 7, 6, 5, 4, 3, 2, 1, 0); | |
| 3847 | return TRUE; | |
| 3848 | } | |
| 3849 | ||
| 3850 | return TRUE; | |
| 2167 | WRITEBACK_RESULT(); | |
| 3851 | 2168 | } |
| 3852 | #else | |
| 3853 | #define RSP_VMADH(E10, E11, E12, E13, E14, E15, E16, E17, E20, E21, E22, E23, E24, E25, E26, E27, I0, I1, I2, I3, I4, I5, I6, I7) \ | |
| 3854 | { \ | |
| 3855 | ACCUM(E10).w.mh += (INT32)R_VREG_S_X(VS1REG, I0) * (INT32)R_VREG_S_X(VS2REG, E20); \ | |
| 3856 | ACCUM(E11).w.mh += (INT32)R_VREG_S_X(VS1REG, I1) * (INT32)R_VREG_S_X(VS2REG, E21); \ | |
| 3857 | ACCUM(E12).w.mh += (INT32)R_VREG_S_X(VS1REG, I2) * (INT32)R_VREG_S_X(VS2REG, E22); \ | |
| 3858 | ACCUM(E13).w.mh += (INT32)R_VREG_S_X(VS1REG, I3) * (INT32)R_VREG_S_X(VS2REG, E23); \ | |
| 3859 | ACCUM(E14).w.mh += (INT32)R_VREG_S_X(VS1REG, I4) * (INT32)R_VREG_S_X(VS2REG, E24); \ | |
| 3860 | ACCUM(E15).w.mh += (INT32)R_VREG_S_X(VS1REG, I5) * (INT32)R_VREG_S_X(VS2REG, E25); \ | |
| 3861 | ACCUM(E16).w.mh += (INT32)R_VREG_S_X(VS1REG, I6) * (INT32)R_VREG_S_X(VS2REG, E26); \ | |
| 3862 | ACCUM(E17).w.mh += (INT32)R_VREG_S_X(VS1REG, I7) * (INT32)R_VREG_S_X(VS2REG, E27); \ | |
| 3863 | vres[E10] = SATURATE_ACCUM_SIGNED(rsp, E10); \ | |
| 3864 | vres[E11] = SATURATE_ACCUM_SIGNED(rsp, E11); \ | |
| 3865 | vres[E12] = SATURATE_ACCUM_SIGNED(rsp, E12); \ | |
| 3866 | vres[E13] = SATURATE_ACCUM_SIGNED(rsp, E13); \ | |
| 3867 | vres[E14] = SATURATE_ACCUM_SIGNED(rsp, E14); \ | |
| 3868 | vres[E15] = SATURATE_ACCUM_SIGNED(rsp, E15); \ | |
| 3869 | vres[E16] = SATURATE_ACCUM_SIGNED(rsp, E16); \ | |
| 3870 | vres[E17] = SATURATE_ACCUM_SIGNED(rsp, E17); \ | |
| 3871 | W_VREG_S_X(VDREG, 7, vres[0]); \ | |
| 3872 | W_VREG_S_X(VDREG, 6, vres[1]); \ | |
| 3873 | W_VREG_S_X(VDREG, 5, vres[2]); \ | |
| 3874 | W_VREG_S_X(VDREG, 4, vres[3]); \ | |
| 3875 | W_VREG_S_X(VDREG, 3, vres[4]); \ | |
| 3876 | W_VREG_S_X(VDREG, 2, vres[5]); \ | |
| 3877 | W_VREG_S_X(VDREG, 1, vres[6]); \ | |
| 3878 | W_VREG_S_X(VDREG, 0, vres[7]); \ | |
| 3879 | } | |
| 3880 | 2169 | |
| 3881 | 2170 | INLINE void cfunc_rsp_vmadh(void *param) |
| 3882 | 2171 | { |
| r9854 | r9855 | |
| 3892 | 2181 | // The result is added into highest 32 bits of accumulator, the low slice is zero |
| 3893 | 2182 | // The highest 32 bits of accumulator is saturated into destination element |
| 3894 | 2183 | |
| 3895 | switch(EL) | |
| 2184 | UINT16 res; | |
| 2185 | int sel; | |
| 2186 | INT32 s1, s2; | |
| 2187 | for (int i = 0; i < 8; i++) | |
| 3896 | 2188 | { |
| 3897 | case 0: /* 0, 1, 2, 3, 4, 5, 6, 7 - none */ /* 0, 1, 2, 3, 4, 5, 6, 7 - none */ | |
| 3898 | RSP_VMADH(0, 1, 2, 3, 4, 5, 6, 7, 7, 6, 5, 4, 3, 2, 1, 0, 7, 6, 5, 4, 3, 2, 1, 0); | |
| 3899 | break; | |
| 3900 | case 1: /* 0, 1, 2, 3, 4, 5, 6, 7 - ??? */ /* 0, 1, 2, 3, 4, 5, 6, 7 - ??? */ | |
| 3901 | RSP_VMADH(0, 1, 2, 3, 4, 5, 6, 7, 7, 6, 5, 4, 3, 2, 1, 0, 7, 6, 5, 4, 3, 2, 1, 0); | |
| 3902 | break; | |
| 3903 | case 2: /* 1, 3, 5, 7, 0, 2, 4, 6 - 0q */ /* 0, 0, 2, 2, 4, 4, 6, 6 - 0q */ | |
| 3904 | RSP_VMADH(1, 3, 5, 7, 0, 2, 4, 6, 7, 5, 3, 1, 7, 5, 3, 1, 6, 4, 2, 0, 7, 5, 3, 1); | |
| 3905 | break; | |
| 3906 | case 3: /* 0, 2, 4, 6, 1, 3, 5, 7 - 1q */ /* 1, 1, 3, 3, 5, 5, 7, 7 - 1q */ | |
| 3907 | RSP_VMADH(0, 2, 4, 6, 1, 3, 5, 7, 6, 4, 2, 0, 6, 4, 2, 0, 7, 5, 3, 1, 6, 4, 2, 0); | |
| 3908 | break; | |
| 3909 | case 4: /* 1, 2, 3, 5, 6, 7, 0, 4 - 0h */ /* 0, 0, 0, 0, 4, 4, 4, 4 - 0h */ | |
| 3910 | RSP_VMADH(1, 2, 3, 5, 6, 7, 0, 4, 7, 7, 7, 3, 3, 3, 7, 3, 6, 5, 4, 2, 1, 0, 7, 3); | |
| 3911 | break; | |
| 3912 | case 5: /* 0, 2, 3, 4, 6, 7, 1, 5 - 1h */ /* 1, 1, 1, 1, 5, 5, 5, 5 - 1h */ | |
| 3913 | RSP_VMADH(0, 2, 3, 4, 6, 7, 1, 5, 6, 6, 6, 2, 2, 2, 6, 2, 7, 5, 4, 3, 1, 0, 6, 2); | |
| 3914 | break; | |
| 3915 | case 6: /* 0, 1, 3, 4, 5, 7, 2, 6 - 2h */ /* 2, 2, 2, 2, 6, 6, 6, 6 - 2h */ | |
| 3916 | RSP_VMADH(0, 1, 3, 4, 5, 7, 2, 6, 5, 5, 5, 1, 1, 1, 5, 1, 7, 6, 4, 3, 2, 0, 5, 1); | |
| 3917 | break; | |
| 3918 | case 7: /* 0, 1, 2, 4, 5, 6, 3, 7 - 3h */ /* 3, 3, 3, 3, 7, 7, 7, 7 - 3h */ | |
| 3919 | RSP_VMADH(0, 1, 2, 4, 5, 6, 3, 7, 4, 4, 4, 0, 0, 0, 4, 0, 7, 6, 5, 3, 2, 1, 4, 0); | |
| 3920 | break; | |
| 3921 | case 8: /* 1, 2, 3, 4, 5, 6, 7, 0 - 0 */ /* 0, 0, 0, 0, 0, 0, 0, 0 - 0 */ | |
| 3922 | RSP_VMADH(1, 2, 3, 4, 5, 6, 7, 0, 7, 7, 7, 7, 7, 7, 7, 7, 6, 5, 4, 3, 2, 1, 0, 7); | |
| 3923 | break; | |
| 3924 | case 9: /* 0, 2, 3, 4, 5, 6, 7, 1 - 1 */ /* 1, 1, 1, 1, 1, 1, 1, 1 - 0 */ | |
| 3925 | RSP_VMADH(0, 2, 3, 4, 5, 6, 7, 1, 6, 6, 6, 6, 6, 6, 6, 6, 7, 5, 4, 3, 2, 1, 0, 6); | |
| 3926 | break; | |
| 3927 | case 10: /* 0, 1, 3, 4, 5, 6, 7, 2 - 2 */ /* 2, 2, 2, 2, 2, 2, 2, 2 - 0 */ | |
| 3928 | RSP_VMADH(0, 1, 3, 4, 5, 6, 7, 2, 5, 5, 5, 5, 5, 5, 5, 5, 7, 6, 4, 3, 2, 1, 0, 5); | |
| 3929 | break; | |
| 3930 | case 11: /* 0, 1, 2, 4, 5, 6, 7, 3 - 3 */ /* 3, 3, 3, 3, 3, 3, 3, 3 - 0 */ | |
| 3931 | RSP_VMADH(0, 1, 2, 4, 5, 6, 7, 3, 4, 4, 4, 4, 4, 4, 4, 4, 7, 6, 5, 3, 2, 1, 0, 4); | |
| 3932 | break; | |
| 3933 | case 12: /* 0, 1, 2, 3, 5, 6, 7, 4 - 4 */ /* 4, 4, 4, 4, 4, 4, 4, 4 - 0 */ | |
| 3934 | RSP_VMADH(0, 1, 2, 3, 5, 6, 7, 4, 3, 3, 3, 3, 3, 3, 3, 3, 7, 6, 5, 4, 2, 1, 0, 3); | |
| 3935 | break; | |
| 3936 | case 13: /* 0, 1, 2, 3, 4, 6, 7, 5 - 5 */ /* 5, 5, 5, 5, 5, 5, 5, 5 - 0 */ | |
| 3937 | RSP_VMADH(0, 1, 2, 3, 4, 6, 7, 5, 2, 2, 2, 2, 2, 2, 2, 2, 7, 6, 5, 4, 3, 1, 0, 2); | |
| 3938 | break; | |
| 3939 | case 14: /* 0, 1, 2, 3, 4, 5, 7, 6 - 6 */ /* 6, 6, 6, 6, 6, 6, 6, 6 - 0 */ | |
| 3940 | RSP_VMADH(0, 1, 2, 3, 4, 5, 7, 6, 1, 1, 1, 1, 1, 1, 1, 1, 7, 6, 5, 4, 3, 2, 0, 1); | |
| 3941 | break; | |
| 3942 | case 15: /* 0, 1, 2, 3, 4, 5, 6, 7 - 7 */ /* 7, 7, 7, 7, 7, 7, 7, 7 - 0 */ | |
| 3943 | RSP_VMADH(0, 1, 2, 3, 4, 5, 6, 7, 0, 0, 0, 0, 0, 0, 0, 0, 7, 6, 5, 4, 3, 2, 1, 0); | |
| 3944 | break; | |
| 3945 | } | |
| 3946 | } | |
| 3947 | #endif | |
| 2189 | sel = VEC_EL_2(EL, i); | |
| 2190 | s1 = (INT32)(INT16)VREG_S(VS1REG, i); | |
| 2191 | s2 = (INT32)(INT16)VREG_S(VS2REG, sel); | |
| 3948 | 2192 | |
| 3949 | #if (DRC_VADD) | |
| 3950 | /*------------------------------------------------------------------ | |
| 3951 | generate_vadd | |
| 3952 | ------------------------------------------------------------------*/ | |
| 2193 | rsp->accum[i].l[1] += s1*s2; | |
| 3953 | 2194 | |
| 3954 | #define RSP_VADD_DRC(E10, E11, E12, E13, E14, E15, E16, E17, E20, E21, E22, E23, E24, E25, E26, E27, I0, I1, I2, I3, I4, I5, I6, I7) \ | |
| 3955 | { \ | |
| 3956 | int inrange, outofrange; \ | |
| 3957 | \ | |
| 3958 | UML_SEXT(block, IREG(0), VS(VS1REG, I0), WORD); \ | |
| 3959 | UML_SEXT(block, IREG(1), VS(VS2REG, E20), WORD); \ | |
| 3960 | UML_ADD(block, IREG(0), IREG(0), IREG(1)); \ | |
| 3961 | UML_SEXT(block, IREG(1), VFLAG(0), WORD); \ | |
| 3962 | UML_SHL(block, IREG(2), IMM(1), IMM(E10)); \ | |
| 3963 | UML_AND(block, IREG(1), IREG(1), IREG(2)); \ | |
| 3964 | UML_SHR(block, IREG(1), IREG(1), IMM(E10)); \ | |
| 3965 | UML_ADD(block, IREG(0), IREG(0), IREG(1)); \ | |
| 3966 | UML_STORE(block, &rsp->accum[E10].h.low, IMM(0), IREG(0), WORD); \ | |
| 3967 | UML_CMP(block, IREG(0), IMM(32767)); \ | |
| 3968 | UML_JMPc(block, IF_LE, inrange = compiler->labelnum++); \ | |
| 3969 | \ | |
| 3970 | UML_MOV(block, IREG(0), IMM(32767)); \ | |
| 3971 | UML_JMP(block, outofrange = compiler->labelnum++); \ | |
| 3972 | \ | |
| 3973 | UML_LABEL(block, inrange); \ | |
| 3974 | \ | |
| 3975 | UML_CMP(block, IREG(0), IMM(-32768)); \ | |
| 3976 | UML_JMPc(block, IF_G, inrange = compiler->labelnum++); \ | |
| 3977 | \ | |
| 3978 | UML_MOV(block, IREG(0), IMM(-32768)); \ | |
| 3979 | \ | |
| 3980 | UML_LABEL(block, inrange); \ | |
| 3981 | UML_LABEL(block, outofrange); \ | |
| 3982 | \ | |
| 3983 | UML_MOV(block, VRES(E10), IREG(0)); \ | |
| 3984 | \ | |
| 3985 | \ | |
| 3986 | UML_SEXT(block, IREG(0), VS(VS1REG, I1), WORD); \ | |
| 3987 | UML_SEXT(block, IREG(1), VS(VS2REG, E21), WORD); \ | |
| 3988 | UML_ADD(block, IREG(0), IREG(0), IREG(1)); \ | |
| 3989 | UML_SEXT(block, IREG(1), VFLAG(0), WORD); \ | |
| 3990 | UML_SHL(block, IREG(2), IMM(1), IMM(E11)); \ | |
| 3991 | UML_AND(block, IREG(1), IREG(1), IREG(2)); \ | |
| 3992 | UML_SHR(block, IREG(1), IREG(1), IMM(E11)); \ | |
| 3993 | UML_ADD(block, IREG(0), IREG(0), IREG(1)); \ | |
| 3994 | UML_STORE(block, &rsp->accum[E11].h.low, IMM(0), IREG(0), WORD); \ | |
| 3995 | UML_CMP(block, IREG(0), IMM(32767)); \ | |
| 3996 | UML_JMPc(block, IF_LE, inrange = compiler->labelnum++); \ | |
| 3997 | \ | |
| 3998 | UML_MOV(block, IREG(0), IMM(32767)); \ | |
| 3999 | UML_JMP(block, outofrange = compiler->labelnum++); \ | |
| 4000 | \ | |
| 4001 | UML_LABEL(block, inrange); \ | |
| 4002 | \ | |
| 4003 | UML_CMP(block, IREG(0), IMM(-32768)); \ | |
| 4004 | UML_JMPc(block, IF_GE, inrange = compiler->labelnum++); \ | |
| 4005 | \ | |
| 4006 | UML_MOV(block, IREG(0), IMM(-32768)); \ | |
| 4007 | \ | |
| 4008 | UML_LABEL(block, inrange); \ | |
| 4009 | UML_LABEL(block, outofrange); \ | |
| 4010 | \ | |
| 4011 | UML_MOV(block, VRES(E11), IREG(0)); \ | |
| 4012 | \ | |
| 4013 | \ | |
| 4014 | UML_SEXT(block, IREG(0), VS(VS1REG, I2), WORD); \ | |
| 4015 | UML_SEXT(block, IREG(1), VS(VS2REG, E22), WORD); \ | |
| 4016 | UML_ADD(block, IREG(0), IREG(0), IREG(1)); \ | |
| 4017 | UML_SEXT(block, IREG(1), VFLAG(0), WORD); \ | |
| 4018 | UML_SHL(block, IREG(2), IMM(1), IMM(E12)); \ | |
| 4019 | UML_AND(block, IREG(1), IREG(1), IREG(2)); \ | |
| 4020 | UML_SHR(block, IREG(1), IREG(1), IMM(E12)); \ | |
| 4021 | UML_ADD(block, IREG(0), IREG(0), IREG(1)); \ | |
| 4022 | UML_STORE(block, &rsp->accum[E12].h.low, IMM(0), IREG(0), WORD); \ | |
| 4023 | UML_CMP(block, IREG(0), IMM(32767)); \ | |
| 4024 | UML_JMPc(block, IF_LE, inrange = compiler->labelnum++); \ | |
| 4025 | \ | |
| 4026 | UML_MOV(block, IREG(0), IMM(32767)); \ | |
| 4027 | UML_JMP(block, outofrange = compiler->labelnum++); \ | |
| 4028 | \ | |
| 4029 | UML_LABEL(block, inrange); \ | |
| 4030 | \ | |
| 4031 | UML_CMP(block, IREG(0), IMM(-32768)); \ | |
| 4032 | UML_JMPc(block, IF_GE, inrange = compiler->labelnum++); \ | |
| 4033 | \ | |
| 4034 | UML_MOV(block, IREG(0), IMM(-32768)); \ | |
| 4035 | \ | |
| 4036 | UML_LABEL(block, inrange); \ | |
| 4037 | UML_LABEL(block, outofrange); \ | |
| 4038 | \ | |
| 4039 | UML_MOV(block, VRES(E12), IREG(0)); \ | |
| 4040 | \ | |
| 4041 | \ | |
| 4042 | UML_SEXT(block, IREG(0), VS(VS1REG, I3), WORD); \ | |
| 4043 | UML_SEXT(block, IREG(1), VS(VS2REG, E23), WORD); \ | |
| 4044 | UML_ADD(block, IREG(0), IREG(0), IREG(1)); \ | |
| 4045 | UML_SEXT(block, IREG(1), VFLAG(0), WORD); \ | |
| 4046 | UML_SHL(block, IREG(2), IMM(1), IMM(E13)); \ | |
| 4047 | UML_AND(block, IREG(1), IREG(1), IREG(2)); \ | |
| 4048 | UML_SHR(block, IREG(1), IREG(1), IMM(E13)); \ | |
| 4049 | UML_ADD(block, IREG(0), IREG(0), IREG(1)); \ | |
| 4050 | UML_STORE(block, &rsp->accum[E13].h.low, IMM(0), IREG(0), WORD); \ | |
| 4051 | UML_CMP(block, IREG(0), IMM(32767)); \ | |
| 4052 | UML_JMPc(block, IF_LE, inrange = compiler->labelnum++); \ | |
| 4053 | \ | |
| 4054 | UML_MOV(block, IREG(0), IMM(32767)); \ | |
| 4055 | UML_JMP(block, outofrange = compiler->labelnum++); \ | |
| 4056 | \ | |
| 4057 | UML_LABEL(block, inrange); \ | |
| 4058 | \ | |
| 4059 | UML_CMP(block, IREG(0), IMM(-32768)); \ | |
| 4060 | UML_JMPc(block, IF_GE, inrange = compiler->labelnum++); \ | |
| 4061 | \ | |
| 4062 | UML_MOV(block, IREG(0), IMM(-32768)); \ | |
| 4063 | \ | |
| 4064 | UML_LABEL(block, inrange); \ | |
| 4065 | UML_LABEL(block, outofrange); \ | |
| 4066 | \ | |
| 4067 | UML_MOV(block, VRES(E13), IREG(0)); \ | |
| 4068 | \ | |
| 4069 | \ | |
| 4070 | UML_SEXT(block, IREG(0), VS(VS1REG, I4), WORD); \ | |
| 4071 | UML_SEXT(block, IREG(1), VS(VS2REG, E24), WORD); \ | |
| 4072 | UML_ADD(block, IREG(0), IREG(0), IREG(1)); \ | |
| 4073 | UML_SEXT(block, IREG(1), VFLAG(0), WORD); \ | |
| 4074 | UML_SHL(block, IREG(2), IMM(1), IMM(E14)); \ | |
| 4075 | UML_AND(block, IREG(1), IREG(1), IREG(2)); \ | |
| 4076 | UML_SHR(block, IREG(1), IREG(1), IMM(E14)); \ | |
| 4077 | UML_ADD(block, IREG(0), IREG(0), IREG(1)); \ | |
| 4078 | UML_STORE(block, &rsp->accum[E14].h.low, IMM(0), IREG(0), WORD); \ | |
| 4079 | UML_CMP(block, IREG(0), IMM(32767)); \ | |
| 4080 | UML_JMPc(block, IF_LE, inrange = compiler->labelnum++); \ | |
| 4081 | \ | |
| 4082 | UML_MOV(block, IREG(0), IMM(32767)); \ | |
| 4083 | UML_JMP(block, outofrange = compiler->labelnum++); \ | |
| 4084 | \ | |
| 4085 | UML_LABEL(block, inrange); \ | |
| 4086 | \ | |
| 4087 | UML_CMP(block, IREG(0), IMM(-32768)); \ | |
| 4088 | UML_JMPc(block, IF_GE, inrange = compiler->labelnum++); \ | |
| 4089 | \ | |
| 4090 | UML_MOV(block, IREG(0), IMM(-32768)); \ | |
| 4091 | \ | |
| 4092 | UML_LABEL(block, inrange); \ | |
| 4093 | UML_LABEL(block, outofrange); \ | |
| 4094 | \ | |
| 4095 | UML_MOV(block, VRES(E14), IREG(0)); \ | |
| 4096 | \ | |
| 4097 | \ | |
| 4098 | UML_SEXT(block, IREG(0), VS(VS1REG, I5), WORD); \ | |
| 4099 | UML_SEXT(block, IREG(1), VS(VS2REG, E25), WORD); \ | |
| 4100 | UML_ADD(block, IREG(0), IREG(0), IREG(1)); \ | |
| 4101 | UML_SEXT(block, IREG(1), VFLAG(0), WORD); \ | |
| 4102 | UML_SHL(block, IREG(2), IMM(1), IMM(E15)); \ | |
| 4103 | UML_AND(block, IREG(1), IREG(1), IREG(2)); \ | |
| 4104 | UML_SHR(block, IREG(1), IREG(1), IMM(E15)); \ | |
| 4105 | UML_ADD(block, IREG(0), IREG(0), IREG(1)); \ | |
| 4106 | UML_STORE(block, &rsp->accum[E15].h.low, IMM(0), IREG(0), WORD); \ | |
| 4107 | UML_CMP(block, IREG(0), IMM(32767)); \ | |
| 4108 | UML_JMPc(block, IF_LE, inrange = compiler->labelnum++); \ | |
| 4109 | \ | |
| 4110 | UML_MOV(block, IREG(0), IMM(32767)); \ | |
| 4111 | UML_JMP(block, outofrange = compiler->labelnum++); \ | |
| 4112 | \ | |
| 4113 | UML_LABEL(block, inrange); \ | |
| 4114 | \ | |
| 4115 | UML_CMP(block, IREG(0), IMM(-32768)); \ | |
| 4116 | UML_JMPc(block, IF_GE, inrange = compiler->labelnum++); \ | |
| 4117 | \ | |
| 4118 | UML_MOV(block, IREG(0), IMM(-32768)); \ | |
| 4119 | \ | |
| 4120 | UML_LABEL(block, inrange); \ | |
| 4121 | UML_LABEL(block, outofrange); \ | |
| 4122 | \ | |
| 4123 | UML_MOV(block, VRES(E15), IREG(0)); \ | |
| 4124 | \ | |
| 4125 | \ | |
| 4126 | UML_SEXT(block, IREG(0), VS(VS1REG, I6), WORD); \ | |
| 4127 | UML_SEXT(block, IREG(1), VS(VS2REG, E26), WORD); \ | |
| 4128 | UML_ADD(block, IREG(0), IREG(0), IREG(1)); \ | |
| 4129 | UML_SEXT(block, IREG(1), VFLAG(0), WORD); \ | |
| 4130 | UML_SHL(block, IREG(2), IMM(1), IMM(E16)); \ | |
| 4131 | UML_AND(block, IREG(1), IREG(1), IREG(2)); \ | |
| 4132 | UML_SHR(block, IREG(1), IREG(1), IMM(E16)); \ | |
| 4133 | UML_ADD(block, IREG(0), IREG(0), IREG(1)); \ | |
| 4134 | UML_STORE(block, &rsp->accum[E16].h.low, IMM(0), IREG(0), WORD); \ | |
| 4135 | UML_CMP(block, IREG(0), IMM(32767)); \ | |
| 4136 | UML_JMPc(block, IF_LE, inrange = compiler->labelnum++); \ | |
| 4137 | \ | |
| 4138 | UML_MOV(block, IREG(0), IMM(32767)); \ | |
| 4139 | UML_JMP(block, outofrange = compiler->labelnum++); \ | |
| 4140 | \ | |
| 4141 | UML_LABEL(block, inrange); \ | |
| 4142 | \ | |
| 4143 | UML_CMP(block, IREG(0), IMM(-32768)); \ | |
| 4144 | UML_JMPc(block, IF_GE, inrange = compiler->labelnum++); \ | |
| 4145 | \ | |
| 4146 | UML_MOV(block, IREG(0), IMM(-32768)); \ | |
| 4147 | \ | |
| 4148 | UML_LABEL(block, inrange); \ | |
| 4149 | UML_LABEL(block, outofrange); \ | |
| 4150 | \ | |
| 4151 | UML_MOV(block, VRES(E16), IREG(0)); \ | |
| 4152 | \ | |
| 4153 | \ | |
| 4154 | UML_SEXT(block, IREG(0), VS(VS1REG, I7), WORD); \ | |
| 4155 | UML_SEXT(block, IREG(1), VS(VS2REG, E27), WORD); \ | |
| 4156 | UML_ADD(block, IREG(0), IREG(0), IREG(1)); \ | |
| 4157 | UML_SEXT(block, IREG(1), VFLAG(0), WORD); \ | |
| 4158 | UML_SHL(block, IREG(2), IMM(1), IMM(E17)); \ | |
| 4159 | UML_AND(block, IREG(1), IREG(1), IREG(2)); \ | |
| 4160 | UML_SHR(block, IREG(1), IREG(1), IMM(E17)); \ | |
| 4161 | UML_ADD(block, IREG(0), IREG(0), IREG(1)); \ | |
| 4162 | UML_STORE(block, &rsp->accum[E17].h.low, IMM(0), IREG(0), WORD); \ | |
| 4163 | UML_CMP(block, IREG(0), IMM(32767)); \ | |
| 4164 | UML_JMPc(block, IF_LE, inrange = compiler->labelnum++); \ | |
| 4165 | \ | |
| 4166 | UML_MOV(block, IREG(0), IMM(32767)); \ | |
| 4167 | UML_JMP(block, outofrange = compiler->labelnum++); \ | |
| 4168 | \ | |
| 4169 | UML_LABEL(block, inrange); \ | |
| 4170 | \ | |
| 4171 | UML_CMP(block, IREG(0), IMM(-32768)); \ | |
| 4172 | UML_JMPc(block, IF_GE, inrange = compiler->labelnum++); \ | |
| 4173 | \ | |
| 4174 | UML_MOV(block, IREG(0), IMM(-32768)); \ | |
| 4175 | \ | |
| 4176 | UML_LABEL(block, inrange); \ | |
| 4177 | UML_LABEL(block, outofrange); \ | |
| 4178 | \ | |
| 4179 | UML_MOV(block, VRES(E17), IREG(0)); \ | |
| 4180 | \ | |
| 4181 | \ | |
| 4182 | UML_STORE(block, &rsp->v[VDREG].s[I0], IMM(0), VRES(E10), WORD); \ | |
| 4183 | UML_STORE(block, &rsp->v[VDREG].s[I1], IMM(0), VRES(E11), WORD); \ | |
| 4184 | UML_STORE(block, &rsp->v[VDREG].s[I2], IMM(0), VRES(E12), WORD); \ | |
| 4185 | UML_STORE(block, &rsp->v[VDREG].s[I3], IMM(0), VRES(E13), WORD); \ | |
| 4186 | UML_STORE(block, &rsp->v[VDREG].s[I4], IMM(0), VRES(E14), WORD); \ | |
| 4187 | UML_STORE(block, &rsp->v[VDREG].s[I5], IMM(0), VRES(E15), WORD); \ | |
| 4188 | UML_STORE(block, &rsp->v[VDREG].s[I6], IMM(0), VRES(E16), WORD); \ | |
| 4189 | UML_STORE(block, &rsp->v[VDREG].s[I7], IMM(0), VRES(E17), WORD); \ | |
| 4190 | } | |
| 2195 | res = SATURATE_ACCUM1(rsp, i, 0x8000, 0x7fff); | |
| 4191 | 2196 | |
| 4192 | static int generate_vadd(rsp_state *rsp, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) // vadd | |
| 4193 | { | |
| 4194 | UINT32 op = desc->opptr.l[0]; | |
| 4195 | ||
| 4196 | // 31 25 24 20 15 10 5 0 | |
| 4197 | // ------------------------------------------------------ | |
| 4198 | // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 001110 | | |
| 4199 | // ------------------------------------------------------ | |
| 4200 | // | |
| 4201 | // Multiplies unsigned fraction by signed integer | |
| 4202 | // The result is added into accumulator | |
| 4203 | // The low slice of accumulator is stored into destination element | |
| 4204 | switch(EL) | |
| 4205 | { | |
| 4206 | case 0: /* 0, 1, 2, 3, 4, 5, 6, 7 - none */ /* 0, 1, 2, 3, 4, 5, 6, 7 - none */ | |
| 4207 | RSP_VADD_DRC(0, 1, 2, 3, 4, 5, 6, 7, 7, 6, 5, 4, 3, 2, 1, 0, 7, 6, 5, 4, 3, 2, 1, 0); | |
| 4208 | return TRUE; | |
| 4209 | case 1: /* 0, 1, 2, 3, 4, 5, 6, 7 - ??? */ /* 0, 1, 2, 3, 4, 5, 6, 7 - ??? */ | |
| 4210 | RSP_VADD_DRC(0, 1, 2, 3, 4, 5, 6, 7, 7, 6, 5, 4, 3, 2, 1, 0, 7, 6, 5, 4, 3, 2, 1, 0); | |
| 4211 | return TRUE; | |
| 4212 | case 2: /* 1, 3, 5, 7, 0, 2, 4, 6 - 0q */ /* 0, 0, 2, 2, 4, 4, 6, 6 - 0q */ | |
| 4213 | RSP_VADD_DRC(1, 3, 5, 7, 0, 2, 4, 6, 7, 5, 3, 1, 7, 5, 3, 1, 6, 4, 2, 0, 7, 5, 3, 1); | |
| 4214 | return TRUE; | |
| 4215 | case 3: /* 0, 2, 4, 6, 1, 3, 5, 7 - 1q */ /* 1, 1, 3, 3, 5, 5, 7, 7 - 1q */ | |
| 4216 | RSP_VADD_DRC(0, 2, 4, 6, 1, 3, 5, 7, 6, 4, 2, 0, 6, 4, 2, 0, 7, 5, 3, 1, 6, 4, 2, 0); | |
| 4217 | return TRUE; | |
| 4218 | case 4: /* 1, 2, 3, 5, 6, 7, 0, 4 - 0h */ /* 0, 0, 0, 0, 4, 4, 4, 4 - 0h */ | |
| 4219 | RSP_VADD_DRC(1, 2, 3, 5, 6, 7, 0, 4, 7, 7, 7, 3, 3, 3, 7, 3, 6, 5, 4, 2, 1, 0, 7, 3); | |
| 4220 | return TRUE; | |
| 4221 | case 5: /* 0, 2, 3, 4, 6, 7, 1, 5 - 1h */ /* 1, 1, 1, 1, 5, 5, 5, 5 - 1h */ | |
| 4222 | RSP_VADD_DRC(0, 2, 3, 4, 6, 7, 1, 5, 6, 6, 6, 2, 2, 2, 6, 2, 7, 5, 4, 3, 1, 0, 6, 2); | |
| 4223 | return TRUE; | |
| 4224 | case 6: /* 0, 1, 3, 4, 5, 7, 2, 6 - 2h */ /* 2, 2, 2, 2, 6, 6, 6, 6 - 2h */ | |
| 4225 | RSP_VADD_DRC(0, 1, 3, 4, 5, 7, 2, 6, 5, 5, 5, 1, 1, 1, 5, 1, 7, 6, 4, 3, 2, 0, 5, 1); | |
| 4226 | return TRUE; | |
| 4227 | case 7: /* 0, 1, 2, 4, 5, 6, 3, 7 - 3h */ /* 3, 3, 3, 3, 7, 7, 7, 7 - 3h */ | |
| 4228 | RSP_VADD_DRC(0, 1, 2, 4, 5, 6, 3, 7, 4, 4, 4, 0, 0, 0, 4, 0, 7, 6, 5, 3, 2, 1, 4, 0); | |
| 4229 | return TRUE; | |
| 4230 | case 8: /* 1, 2, 3, 4, 5, 6, 7, 0 - 0 */ /* 0, 0, 0, 0, 0, 0, 0, 0 - 0 */ | |
| 4231 | RSP_VADD_DRC(1, 2, 3, 4, 5, 6, 7, 0, 7, 7, 7, 7, 7, 7, 7, 7, 6, 5, 4, 3, 2, 1, 0, 7); | |
| 4232 | return TRUE; | |
| 4233 | case 9: /* 0, 2, 3, 4, 5, 6, 7, 1 - 1 */ /* 1, 1, 1, 1, 1, 1, 1, 1 - 0 */ | |
| 4234 | RSP_VADD_DRC(0, 2, 3, 4, 5, 6, 7, 1, 6, 6, 6, 6, 6, 6, 6, 6, 7, 5, 4, 3, 2, 1, 0, 6); | |
| 4235 | return TRUE; | |
| 4236 | case 10: /* 0, 1, 3, 4, 5, 6, 7, 2 - 2 */ /* 2, 2, 2, 2, 2, 2, 2, 2 - 0 */ | |
| 4237 | RSP_VADD_DRC(0, 1, 3, 4, 5, 6, 7, 2, 5, 5, 5, 5, 5, 5, 5, 5, 7, 6, 4, 3, 2, 1, 0, 5); | |
| 4238 | return TRUE; | |
| 4239 | case 11: /* 0, 1, 2, 4, 5, 6, 7, 3 - 3 */ /* 3, 3, 3, 3, 3, 3, 3, 3 - 0 */ | |
| 4240 | RSP_VADD_DRC(0, 1, 2, 4, 5, 6, 7, 3, 4, 4, 4, 4, 4, 4, 4, 4, 7, 6, 5, 3, 2, 1, 0, 4); | |
| 4241 | return TRUE; | |
| 4242 | case 12: /* 0, 1, 2, 3, 5, 6, 7, 4 - 4 */ /* 4, 4, 4, 4, 4, 4, 4, 4 - 0 */ | |
| 4243 | RSP_VADD_DRC(0, 1, 2, 3, 5, 6, 7, 4, 3, 3, 3, 3, 3, 3, 3, 3, 7, 6, 5, 4, 2, 1, 0, 3); | |
| 4244 | return TRUE; | |
| 4245 | case 13: /* 0, 1, 2, 3, 4, 6, 7, 5 - 5 */ /* 5, 5, 5, 5, 5, 5, 5, 5 - 0 */ | |
| 4246 | RSP_VADD_DRC(0, 1, 2, 3, 4, 6, 7, 5, 2, 2, 2, 2, 2, 2, 2, 2, 7, 6, 5, 4, 3, 1, 0, 2); | |
| 4247 | return TRUE; | |
| 4248 | case 14: /* 0, 1, 2, 3, 4, 5, 7, 6 - 6 */ /* 6, 6, 6, 6, 6, 6, 6, 6 - 0 */ | |
| 4249 | RSP_VADD_DRC(0, 1, 2, 3, 4, 5, 7, 6, 1, 1, 1, 1, 1, 1, 1, 1, 7, 6, 5, 4, 3, 2, 0, 1); | |
| 4250 | return TRUE; | |
| 4251 | case 15: /* 0, 1, 2, 3, 4, 5, 6, 7 - 7 */ /* 7, 7, 7, 7, 7, 7, 7, 7 - 0 */ | |
| 4252 | RSP_VADD_DRC(0, 1, 2, 3, 4, 5, 6, 7, 0, 0, 0, 0, 0, 0, 0, 0, 7, 6, 5, 4, 3, 2, 1, 0); | |
| 4253 | return TRUE; | |
| 2197 | vres[i] = res; | |
| 4254 | 2198 | } |
| 4255 | ||
| 4256 | return TRUE; | |
| 2199 | WRITEBACK_RESULT(); | |
| 4257 | 2200 | } |
| 4258 | #else | |
| 4259 | #define RSP_VADD(E10, E11, E12, E13, E14, E15, E16, E17, E20, E21, E22, E23, E24, E25, E26, E27, I0, I1, I2, I3, I4, I5, I6, I7) \ | |
| 4260 | { \ | |
| 4261 | INT32 r; \ | |
| 4262 | ACCUM(E10).h.low = (INT16)(r = (INT32)R_VREG_S_X(VS1REG, I0) + (INT32)R_VREG_S_X(VS2REG, E20) + ((rsp->flag[0] & (1 << E10)) >> E10)); \ | |
| 4263 | vres[E10] = (r > 32767) ? 32767 : ((r < -32768) ? -32768 : ACCUM(E10).h.low); \ | |
| 4264 | ACCUM(E11).h.low = (INT16)(r = (INT32)R_VREG_S_X(VS1REG, I1) + (INT32)R_VREG_S_X(VS2REG, E21) + ((rsp->flag[0] & (1 << E11)) >> E11)); \ | |
| 4265 | vres[E11] = (r > 32767) ? 32767 : ((r < -32768) ? -32768 : ACCUM(E11).h.low); \ | |
| 4266 | ACCUM(E12).h.low = (INT16)(r = (INT32)R_VREG_S_X(VS1REG, I2) + (INT32)R_VREG_S_X(VS2REG, E22) + ((rsp->flag[0] & (1 << E12)) >> E12)); \ | |
| 4267 | vres[E12] = (r > 32767) ? 32767 : ((r < -32768) ? -32768 : ACCUM(E12).h.low); \ | |
| 4268 | ACCUM(E13).h.low = (INT16)(r = (INT32)R_VREG_S_X(VS1REG, I3) + (INT32)R_VREG_S_X(VS2REG, E23) + ((rsp->flag[0] & (1 << E13)) >> E13)); \ | |
| 4269 | vres[E13] = (r > 32767) ? 32767 : ((r < -32768) ? -32768 : ACCUM(E13).h.low); \ | |
| 4270 | ACCUM(E14).h.low = (INT16)(r = (INT32)R_VREG_S_X(VS1REG, I4) + (INT32)R_VREG_S_X(VS2REG, E24) + ((rsp->flag[0] & (1 << E14)) >> E14)); \ | |
| 4271 | vres[E14] = (r > 32767) ? 32767 : ((r < -32768) ? -32768 : ACCUM(E14).h.low); \ | |
| 4272 | ACCUM(E15).h.low = (INT16)(r = (INT32)R_VREG_S_X(VS1REG, I5) + (INT32)R_VREG_S_X(VS2REG, E25) + ((rsp->flag[0] & (1 << E15)) >> E15)); \ | |
| 4273 | vres[E15] = (r > 32767) ? 32767 : ((r < -32768) ? -32768 : ACCUM(E15).h.low); \ | |
| 4274 | ACCUM(E16).h.low = (INT16)(r = (INT32)R_VREG_S_X(VS1REG, I6) + (INT32)R_VREG_S_X(VS2REG, E26) + ((rsp->flag[0] & (1 << E16)) >> E16)); \ | |
| 4275 | vres[E16] = (r > 32767) ? 32767 : ((r < -32768) ? -32768 : ACCUM(E16).h.low); \ | |
| 4276 | ACCUM(E17).h.low = (INT16)(r = (INT32)R_VREG_S_X(VS1REG, I7) + (INT32)R_VREG_S_X(VS2REG, E27) + ((rsp->flag[0] & (1 << E17)) >> E17)); \ | |
| 4277 | vres[E17] = (r > 32767) ? 32767 : ((r < -32768) ? -32768 : ACCUM(E17).h.low); \ | |
| 4278 | } | |
| 4279 | 2201 | |
| 4280 | 2202 | INLINE void cfunc_rsp_vadd(void *param) |
| 4281 | 2203 | { |
| r9854 | r9855 | |
| 4290 | 2212 | // |
| 4291 | 2213 | // Adds two vector registers and carry flag, the result is saturated to 32767 |
| 4292 | 2214 | |
| 4293 | // TODO: check VS2REG == VDREG | |
| 4294 | switch(EL) | |
| 2215 | int sel; | |
| 2216 | INT32 s1, s2, r; | |
| 2217 | for (int i = 0; i < 8; i++) | |
| 4295 | 2218 | { |
| 4296 | case 0: /* 0, 1, 2, 3, 4, 5, 6, 7 - none */ /* 0, 1, 2, 3, 4, 5, 6, 7 - none */ | |
| 4297 | RSP_VADD(0, 1, 2, 3, 4, 5, 6, 7, 7, 6, 5, 4, 3, 2, 1, 0, 7, 6, 5, 4, 3, 2, 1, 0); | |
| 4298 | break; | |
| 4299 | case 1: /* 0, 1, 2, 3, 4, 5, 6, 7 - ??? */ /* 0, 1, 2, 3, 4, 5, 6, 7 - ??? */ | |
| 4300 | RSP_VADD(0, 1, 2, 3, 4, 5, 6, 7, 7, 6, 5, 4, 3, 2, 1, 0, 7, 6, 5, 4, 3, 2, 1, 0); | |
| 4301 | break; | |
| 4302 | case 2: /* 1, 3, 5, 7, 0, 2, 4, 6 - 0q */ /* 0, 0, 2, 2, 4, 4, 6, 6 - 0q */ | |
| 4303 | RSP_VADD(1, 3, 5, 7, 0, 2, 4, 6, 7, 5, 3, 1, 7, 5, 3, 1, 6, 4, 2, 0, 7, 5, 3, 1); | |
| 4304 | break; | |
| 4305 | case 3: /* 0, 2, 4, 6, 1, 3, 5, 7 - 1q */ /* 1, 1, 3, 3, 5, 5, 7, 7 - 1q */ | |
| 4306 | RSP_VADD(0, 2, 4, 6, 1, 3, 5, 7, 6, 4, 2, 0, 6, 4, 2, 0, 7, 5, 3, 1, 6, 4, 2, 0); | |
| 4307 | break; | |
| 4308 | case 4: /* 1, 2, 3, 5, 6, 7, 0, 4 - 0h */ /* 0, 0, 0, 0, 4, 4, 4, 4 - 0h */ | |
| 4309 | RSP_VADD(1, 2, 3, 5, 6, 7, 0, 4, 7, 7, 7, 3, 3, 3, 7, 3, 6, 5, 4, 2, 1, 0, 7, 3); | |
| 4310 | break; | |
| 4311 | case 5: /* 0, 2, 3, 4, 6, 7, 1, 5 - 1h */ /* 1, 1, 1, 1, 5, 5, 5, 5 - 1h */ | |
| 4312 | RSP_VADD(0, 2, 3, 4, 6, 7, 1, 5, 6, 6, 6, 2, 2, 2, 6, 2, 7, 5, 4, 3, 1, 0, 6, 2); | |
| 4313 | break; | |
| 4314 | case 6: /* 0, 1, 3, 4, 5, 7, 2, 6 - 2h */ /* 2, 2, 2, 2, 6, 6, 6, 6 - 2h */ | |
| 4315 | RSP_VADD(0, 1, 3, 4, 5, 7, 2, 6, 5, 5, 5, 1, 1, 1, 5, 1, 7, 6, 4, 3, 2, 0, 5, 1); | |
| 4316 | break; | |
| 4317 | case 7: /* 0, 1, 2, 4, 5, 6, 3, 7 - 3h */ /* 3, 3, 3, 3, 7, 7, 7, 7 - 3h */ | |
| 4318 | RSP_VADD(0, 1, 2, 4, 5, 6, 3, 7, 4, 4, 4, 0, 0, 0, 4, 0, 7, 6, 5, 3, 2, 1, 4, 0); | |
| 4319 | break; | |
| 4320 | case 8: /* 1, 2, 3, 4, 5, 6, 7, 0 - 0 */ /* 0, 0, 0, 0, 0, 0, 0, 0 - 0 */ | |
| 4321 | RSP_VADD(1, 2, 3, 4, 5, 6, 7, 0, 7, 7, 7, 7, 7, 7, 7, 7, 6, 5, 4, 3, 2, 1, 0, 7); | |
| 4322 | break; | |
| 4323 | case 9: /* 0, 2, 3, 4, 5, 6, 7, 1 - 1 */ /* 1, 1, 1, 1, 1, 1, 1, 1 - 0 */ | |
| 4324 | RSP_VADD(0, 2, 3, 4, 5, 6, 7, 1, 6, 6, 6, 6, 6, 6, 6, 6, 7, 5, 4, 3, 2, 1, 0, 6); | |
| 4325 | break; | |
| 4326 | case 10: /* 0, 1, 3, 4, 5, 6, 7, 2 - 2 */ /* 2, 2, 2, 2, 2, 2, 2, 2 - 0 */ | |
| 4327 | RSP_VADD(0, 1, 3, 4, 5, 6, 7, 2, 5, 5, 5, 5, 5, 5, 5, 5, 7, 6, 4, 3, 2, 1, 0, 5); | |
| 4328 | break; | |
| 4329 | case 11: /* 0, 1, 2, 4, 5, 6, 7, 3 - 3 */ /* 3, 3, 3, 3, 3, 3, 3, 3 - 0 */ | |
| 4330 | RSP_VADD(0, 1, 2, 4, 5, 6, 7, 3, 4, 4, 4, 4, 4, 4, 4, 4, 7, 6, 5, 3, 2, 1, 0, 4); | |
| 4331 | break; | |
| 4332 | case 12: /* 0, 1, 2, 3, 5, 6, 7, 4 - 4 */ /* 4, 4, 4, 4, 4, 4, 4, 4 - 0 */ | |
| 4333 | RSP_VADD(0, 1, 2, 3, 5, 6, 7, 4, 3, 3, 3, 3, 3, 3, 3, 3, 7, 6, 5, 4, 2, 1, 0, 3); | |
| 4334 | break; | |
| 4335 | case 13: /* 0, 1, 2, 3, 4, 6, 7, 5 - 5 */ /* 5, 5, 5, 5, 5, 5, 5, 5 - 0 */ | |
| 4336 | RSP_VADD(0, 1, 2, 3, 4, 6, 7, 5, 2, 2, 2, 2, 2, 2, 2, 2, 7, 6, 5, 4, 3, 1, 0, 2); | |
| 4337 | break; | |
| 4338 | case 14: /* 0, 1, 2, 3, 4, 5, 7, 6 - 6 */ /* 6, 6, 6, 6, 6, 6, 6, 6 - 0 */ | |
| 4339 | RSP_VADD(0, 1, 2, 3, 4, 5, 7, 6, 1, 1, 1, 1, 1, 1, 1, 1, 7, 6, 5, 4, 3, 2, 0, 1); | |
| 4340 | break; | |
| 4341 | case 15: /* 0, 1, 2, 3, 4, 5, 6, 7 - 7 */ /* 7, 7, 7, 7, 7, 7, 7, 7 - 0 */ | |
| 4342 | RSP_VADD(0, 1, 2, 3, 4, 5, 6, 7, 0, 0, 0, 0, 0, 0, 0, 0, 7, 6, 5, 4, 3, 2, 1, 0); | |
| 4343 | break; | |
| 2219 | sel = VEC_EL_2(EL, i); | |
| 2220 | s1 = (INT32)(INT16)VREG_S(VS1REG, i); | |
| 2221 | s2 = (INT32)(INT16)VREG_S(VS2REG, sel); | |
| 2222 | r = s1 + s2 + CARRY_FLAG(i); | |
| 2223 | ||
| 2224 | ACCUM_L(i) = (INT16)(r); | |
| 2225 | ||
| 2226 | if (r > 32767) r = 32767; | |
| 2227 | if (r < -32768) r = -32768; | |
| 2228 | vres[i] = (INT16)(r); | |
| 4344 | 2229 | } |
| 4345 | rsp->flag[0] = 0; | |
| 2230 | CLEAR_ZERO_FLAGS(); | |
| 2231 | CLEAR_CARRY_FLAGS(); | |
| 4346 | 2232 | WRITEBACK_RESULT(); |
| 4347 | 2233 | } |
| 4348 | #endif | |
| 4349 | 2234 | |
| 4350 | 2235 | INLINE void cfunc_rsp_vsub(void *param) |
| 4351 | 2236 | { |
| r9854 | r9855 | |
| 4362 | 2247 | |
| 4363 | 2248 | // TODO: check VS2REG == VDREG |
| 4364 | 2249 | |
| 4365 | for (i=0; i < 8; i++) | |
| 2250 | int sel; | |
| 2251 | INT32 s1, s2, r; | |
| 2252 | for (i = 0; i < 8; i++) | |
| 4366 | 2253 | { |
| 4367 | int del = VEC_EL_1(EL, i); | |
| 4368 | int sel = VEC_EL_2(EL, del); | |
| 4369 | INT32 s1 = (INT32)(INT16)R_VREG_S(VS1REG, del); | |
| 4370 | INT32 s2 = (INT32)(INT16)R_VREG_S(VS2REG, sel); | |
| 4371 | INT32 r = s1 - s2 - CARRY_FLAG(del); | |
| 2254 | sel = VEC_EL_2(EL, i); | |
| 2255 | s1 = (INT32)(INT16)VREG_S(VS1REG, i); | |
| 2256 | s2 = (INT32)(INT16)VREG_S(VS2REG, sel); | |
| 2257 | r = s1 - s2 - CARRY_FLAG(i); | |
| 4372 | 2258 | |
| 4373 | | |
| 2259 | | |
| 4374 | 2260 | |
| 4375 | 2261 | if (r > 32767) r = 32767; |
| 4376 | 2262 | if (r < -32768) r = -32768; |
| 4377 | 2263 | |
| 4378 | vres[ | |
| 2264 | vres[i | |
| 4379 | 2265 | } |
| 4380 | rsp->flag[0] = 0; | |
| 2266 | CLEAR_ZERO_FLAGS(); | |
| 2267 | CLEAR_CARRY_FLAGS(); | |
| 4381 | 2268 | WRITEBACK_RESULT(); |
| 4382 | 2269 | } |
| 4383 | 2270 | |
| r9854 | r9855 | |
| 4395 | 2282 | // Changes the sign of source register 2 if source register 1 is negative and stores |
| 4396 | 2283 | // the result to destination register |
| 4397 | 2284 | |
| 2285 | int sel; | |
| 2286 | INT16 s1, s2; | |
| 4398 | 2287 | for (i=0; i < 8; i++) |
| 4399 | 2288 | { |
| 4400 | int del = VEC_EL_1(EL, i); | |
| 4401 | int sel = VEC_EL_2(EL, del); | |
| 4402 | INT16 s1 = (INT16)R_VREG_S(VS1REG, del); | |
| 4403 | INT16 s2 = (INT16)R_VREG_S(VS2REG, sel); | |
| 2289 | sel = VEC_EL_2(EL, i); | |
| 2290 | s1 = (INT16)VREG_S(VS1REG, i); | |
| 2291 | s2 = (INT16)VREG_S(VS2REG, sel); | |
| 4404 | 2292 | |
| 4405 | 2293 | if (s1 < 0) |
| 4406 | 2294 | { |
| 4407 | 2295 | if (s2 == -32768) |
| 4408 | 2296 | { |
| 4409 | vres[ | |
| 2297 | vres[i | |
| 4410 | 2298 | } |
| 4411 | 2299 | else |
| 4412 | 2300 | { |
| 4413 | vres[ | |
| 2301 | vres[i | |
| 4414 | 2302 | } |
| 4415 | 2303 | } |
| 4416 | 2304 | else if (s1 > 0) |
| 4417 | 2305 | { |
| 4418 | vres[ | |
| 2306 | vres[i | |
| 4419 | 2307 | } |
| 4420 | 2308 | else |
| 4421 | 2309 | { |
| 4422 | vres[ | |
| 2310 | vres[i | |
| 4423 | 2311 | } |
| 4424 | 2312 | |
| 4425 | | |
| 2313 | | |
| 4426 | 2314 | } |
| 4427 | 2315 | WRITEBACK_RESULT(); |
| 4428 | 2316 | } |
| r9854 | r9855 | |
| 4442 | 2330 | |
| 4443 | 2331 | // TODO: check VS2REG = VDREG |
| 4444 | 2332 | |
| 4445 | rsp->flag[0] = 0; | |
| 2333 | int sel; | |
| 2334 | INT32 s1, s2, r; | |
| 2335 | CLEAR_ZERO_FLAGS(); | |
| 2336 | CLEAR_CARRY_FLAGS(); | |
| 4446 | 2337 | |
| 4447 | 2338 | for (i=0; i < 8; i++) |
| 4448 | 2339 | { |
| 4449 | int del = VEC_EL_1(EL, i); | |
| 4450 | int sel = VEC_EL_2(EL, del); | |
| 4451 | INT32 s1 = (UINT32)(UINT16)R_VREG_S(VS1REG, del); | |
| 4452 | INT32 s2 = (UINT32)(UINT16)R_VREG_S(VS2REG, sel); | |
| 4453 | INT32 r = s1 + s2; | |
| 2340 | sel = VEC_EL_2(EL, i); | |
| 2341 | s1 = (UINT32)(UINT16)VREG_S(VS1REG, i); | |
| 2342 | s2 = (UINT32)(UINT16)VREG_S(VS2REG, sel); | |
| 2343 | r = s1 + s2; | |
| 4454 | 2344 | |
| 4455 | vres[del] = (INT16)(r); | |
| 4456 | W_ACCUM_L(del, (INT16)(r)); | |
| 2345 | vres[i] = (INT16)(r); | |
| 2346 | ACCUM_L(i) = (INT16)(r); | |
| 4457 | 2347 | |
| 4458 | 2348 | if (r & 0xffff0000) |
| 4459 | 2349 | { |
| 4460 | SET_CARRY_FLAG( | |
| 2350 | SET_CARRY_FLAG(i | |
| 4461 | 2351 | } |
| 4462 | 2352 | } |
| 4463 | 2353 | WRITEBACK_RESULT(); |
| r9854 | r9855 | |
| 4478 | 2368 | |
| 4479 | 2369 | // TODO: check VS2REG = VDREG |
| 4480 | 2370 | |
| 4481 | rsp->flag[0] = 0; | |
| 2371 | int sel; | |
| 2372 | INT32 s1, s2, r; | |
| 2373 | CLEAR_ZERO_FLAGS(); | |
| 2374 | CLEAR_CARRY_FLAGS(); | |
| 4482 | 2375 | |
| 4483 | 2376 | for (i=0; i < 8; i++) |
| 4484 | 2377 | { |
| 4485 | int del = VEC_EL_1(EL, i); | |
| 4486 | int sel = VEC_EL_2(EL, del); | |
| 4487 | INT32 s1 = (UINT32)(UINT16)R_VREG_S(VS1REG, del); | |
| 4488 | INT32 s2 = (UINT32)(UINT16)R_VREG_S(VS2REG, sel); | |
| 4489 | INT32 r = s1 - s2; | |
| 2378 | sel = VEC_EL_2(EL, i); | |
| 2379 | s1 = (UINT32)(UINT16)VREG_S(VS1REG, i); | |
| 2380 | s2 = (UINT32)(UINT16)VREG_S(VS2REG, sel); | |
| 2381 | r = s1 - s2; | |
| 4490 | 2382 | |
| 4491 | vres[del] = (INT16)(r); | |
| 4492 | W_ACCUM_L(del, (UINT16)(r)); | |
| 2383 | vres[i] = (INT16)(r); | |
| 2384 | ACCUM_L(i) = (UINT16)(r); | |
| 4493 | 2385 | |
| 4494 | 2386 | if ((UINT16)(r) != 0) |
| 4495 | 2387 | { |
| 4496 | SET_ZERO_FLAG( | |
| 2388 | SET_ZERO_FLAG(i | |
| 4497 | 2389 | } |
| 4498 | 2390 | if (r & 0xffff0000) |
| 4499 | 2391 | { |
| 4500 | SET_CARRY_FLAG( | |
| 2392 | SET_CARRY_FLAG(i | |
| 4501 | 2393 | } |
| 4502 | 2394 | } |
| 4503 | 2395 | WRITEBACK_RESULT(); |
| r9854 | r9855 | |
| 4518 | 2410 | { |
| 4519 | 2411 | case 0x08: // VSAWH |
| 4520 | 2412 | { |
| 4521 | W_VREG_S_X(VDREG, 7, ACCUM(0).h.high); | |
| 4522 | W_VREG_S_X(VDREG, 6, ACCUM(1).h.high); | |
| 4523 | W_VREG_S_X(VDREG, 5, ACCUM(2).h.high); | |
| 4524 | W_VREG_S_X(VDREG, 4, ACCUM(3).h.high); | |
| 4525 | W_VREG_S_X(VDREG, 3, ACCUM(4).h.high); | |
| 4526 | W_VREG_S_X(VDREG, 2, ACCUM(5).h.high); | |
| 4527 | W_VREG_S_X(VDREG, 1, ACCUM(6).h.high); | |
| 4528 | W_VREG_S_X(VDREG, 0, ACCUM(7).h.high); | |
| 2413 | for (int i = 0; i < 8; i++) | |
| 2414 | { | |
| 2415 | VREG_S(VDREG, i) = ACCUM_H(i); | |
| 2416 | } | |
| 4529 | 2417 | break; |
| 4530 | 2418 | } |
| 4531 | 2419 | case 0x09: // VSAWM |
| 4532 | 2420 | { |
| 4533 | W_VREG_S_X(VDREG, 7, ACCUM(0).h.mid); | |
| 4534 | W_VREG_S_X(VDREG, 6, ACCUM(1).h.mid); | |
| 4535 | W_VREG_S_X(VDREG, 5, ACCUM(2).h.mid); | |
| 4536 | W_VREG_S_X(VDREG, 4, ACCUM(3).h.mid); | |
| 4537 | W_VREG_S_X(VDREG, 3, ACCUM(4).h.mid); | |
| 4538 | W_VREG_S_X(VDREG, 2, ACCUM(5).h.mid); | |
| 4539 | W_VREG_S_X(VDREG, 1, ACCUM(6).h.mid); | |
| 4540 | W_VREG_S_X(VDREG, 0, ACCUM(7).h.mid); | |
| 2421 | for (int i = 0; i < 8; i++) | |
| 2422 | { | |
| 2423 | VREG_S(VDREG, i) = ACCUM_M(i); | |
| 2424 | } | |
| 4541 | 2425 | break; |
| 4542 | 2426 | } |
| 4543 | 2427 | case 0x0a: // VSAWL |
| 4544 | 2428 | { |
| 4545 | W_VREG_S_X(VDREG, 7, ACCUM(0).h.low); | |
| 4546 | W_VREG_S_X(VDREG, 6, ACCUM(1).h.low); | |
| 4547 | W_VREG_S_X(VDREG, 5, ACCUM(2).h.low); | |
| 4548 | W_VREG_S_X(VDREG, 4, ACCUM(3).h.low); | |
| 4549 | W_VREG_S_X(VDREG, 3, ACCUM(4).h.low); | |
| 4550 | W_VREG_S_X(VDREG, 2, ACCUM(5).h.low); | |
| 4551 | W_VREG_S_X(VDREG, 1, ACCUM(6).h.low); | |
| 4552 | W_VREG_S_X(VDREG, 0, ACCUM(7).h.low); | |
| 2429 | for (int i = 0; i < 8; i++) | |
| 2430 | { | |
| 2431 | VREG_S(VDREG, i) = ACCUM_L(i); | |
| 2432 | } | |
| 4553 | 2433 | break; |
| 4554 | 2434 | } |
| 4555 | 2435 | default: fatalerror("RSP: VSAW: el = %d\n", EL); |
| 4556 | 2436 | } |
| 4557 | 2437 | } |
| 4558 | 2438 | |
| 4559 | #define RSP_VLT(E10, E11, E12, E13, E14, E15, E16, E17, E20, E21, E22, E23, E24, E25, E26, E27, I0, I1, I2, I3, I4, I5, I6, I7) \ | |
| 4560 | { \ | |
| 4561 | rsp->flag[1] = 0; \ | |
| 4562 | \ | |
| 4563 | if (R_VREG_S_X(VS1REG, I0) > R_VREG_S_X(VS2REG, E20)) \ | |
| 4564 | { \ | |
| 4565 | ACCUM(E16).h.low = vres[E10] = R_VREG_S_X(VS2REG, E20); \ | |
| 4566 | } \ | |
| 4567 | else if (R_VREG_S_X(VS1REG, I0) < R_VREG_S_X(VS2REG, E20)) \ | |
| 4568 | { \ | |
| 4569 | ACCUM(E10).h.low = vres[E10] = R_VREG_S_X(VS1REG, I0); \ | |
| 4570 | SET_COMPARE_FLAG(E10); \ | |
| 4571 | } \ | |
| 4572 | else if (R_VREG_S_X(VS1REG, I0) == R_VREG_S_X(VS2REG, E20)) \ | |
| 4573 | { \ | |
| 4574 | ACCUM(E10).h.low = vres[E10] = R_VREG_S_X(VS1REG, I0); \ | |
| 4575 | if (ZERO_FLAG(E10) && CARRY_FLAG(E10)) SET_COMPARE_FLAG(E10); \ | |
| 4576 | } \ | |
| 4577 | if (R_VREG_S_X(VS1REG, I1) > R_VREG_S_X(VS2REG, E21)) \ | |
| 4578 | { \ | |
| 4579 | ACCUM(E16).h.low = vres[E11] = R_VREG_S_X(VS2REG, E21); \ | |
| 4580 | } \ | |
| 4581 | else if (R_VREG_S_X(VS1REG, I1) < R_VREG_S_X(VS2REG, E21)) \ | |
| 4582 | { \ | |
| 4583 | ACCUM(E11).h.low = vres[E11] = R_VREG_S_X(VS1REG, I1); \ | |
| 4584 | SET_COMPARE_FLAG(E11); \ | |
| 4585 | } \ | |
| 4586 | else if (R_VREG_S_X(VS1REG, I1) == R_VREG_S_X(VS2REG, E21)) \ | |
| 4587 | { \ | |
| 4588 | ACCUM(E11).h.low = vres[E11] = R_VREG_S_X(VS1REG, I1); \ | |
| 4589 | if (ZERO_FLAG(E11) && CARRY_FLAG(E11)) SET_COMPARE_FLAG(E11); \ | |
| 4590 | } \ | |
| 4591 | if (R_VREG_S_X(VS1REG, I2) > R_VREG_S_X(VS2REG, E22)) \ | |
| 4592 | { \ | |
| 4593 | ACCUM(E12).h.low = vres[E12] = R_VREG_S_X(VS2REG, E22); \ | |
| 4594 | } \ | |
| 4595 | else if (R_VREG_S_X(VS1REG, I2) < R_VREG_S_X(VS2REG, E22)) \ | |
| 4596 | { \ | |
| 4597 | ACCUM(E12).h.low = vres[E12] = R_VREG_S_X(VS1REG, I2); \ | |
| 4598 | SET_COMPARE_FLAG(E12); \ | |
| 4599 | } \ | |
| 4600 | else if (R_VREG_S_X(VS1REG, I2) == R_VREG_S_X(VS2REG, E22)) \ | |
| 4601 | { \ | |
| 4602 | ACCUM(E12).h.low = vres[E12] = R_VREG_S_X(VS1REG, I2); \ | |
| 4603 | if (ZERO_FLAG(E12) && CARRY_FLAG(E12)) SET_COMPARE_FLAG(E12); \ | |
| 4604 | } \ | |
| 4605 | if (R_VREG_S_X(VS1REG, I3) > R_VREG_S_X(VS2REG, E23)) \ | |
| 4606 | { \ | |
| 4607 | ACCUM(E13).h.low = vres[E13] = R_VREG_S_X(VS2REG, E23); \ | |
| 4608 | } \ | |
| 4609 | else if (R_VREG_S_X(VS1REG, I3) < R_VREG_S_X(VS2REG, E23)) \ | |
| 4610 | { \ | |
| 4611 | ACCUM(E13).h.low = vres[E13] = R_VREG_S_X(VS1REG, I3); \ | |
| 4612 | SET_COMPARE_FLAG(E13); \ | |
| 4613 | } \ | |
| 4614 | else if (R_VREG_S_X(VS1REG, I3) == R_VREG_S_X(VS2REG, E23)) \ | |
| 4615 | { \ | |
| 4616 | ACCUM(E13).h.low = vres[E13] = R_VREG_S_X(VS1REG, I3); \ | |
| 4617 | if (ZERO_FLAG(E10) && CARRY_FLAG(E13)) SET_COMPARE_FLAG(E13); \ | |
| 4618 | } \ | |
| 4619 | if (R_VREG_S_X(VS1REG, I4) > R_VREG_S_X(VS2REG, E24)) \ | |
| 4620 | { \ | |
| 4621 | ACCUM(E14).h.low = vres[E14] = R_VREG_S_X(VS2REG, E24); \ | |
| 4622 | } \ | |
| 4623 | else if (R_VREG_S_X(VS1REG, I4) < R_VREG_S_X(VS2REG, E24)) \ | |
| 4624 | { \ | |
| 4625 | ACCUM(E14).h.low = vres[E14] = R_VREG_S_X(VS1REG, I4); \ | |
| 4626 | SET_COMPARE_FLAG(E14); \ | |
| 4627 | } \ | |
| 4628 | else if (R_VREG_S_X(VS1REG, I4) == R_VREG_S_X(VS2REG, E24)) \ | |
| 4629 | { \ | |
| 4630 | ACCUM(E14).h.low = vres[E14] = R_VREG_S_X(VS1REG, I4); \ | |
| 4631 | if (ZERO_FLAG(E14) && CARRY_FLAG(E14)) SET_COMPARE_FLAG(E14); \ | |
| 4632 | } \ | |
| 4633 | if (R_VREG_S_X(VS1REG, I5) > R_VREG_S_X(VS2REG, E25)) \ | |
| 4634 | { \ | |
| 4635 | ACCUM(E15).h.low = vres[5] = R_VREG_S_X(VS2REG, E25); \ | |
| 4636 | } \ | |
| 4637 | else if (R_VREG_S_X(VS1REG, I5) < R_VREG_S_X(VS2REG, E25)) \ | |
| 4638 | { \ | |
| 4639 | ACCUM(E15).h.low = vres[E15] = R_VREG_S_X(VS1REG, I5); \ | |
| 4640 | SET_COMPARE_FLAG(E15); \ | |
| 4641 | } \ | |
| 4642 | else if (R_VREG_S_X(VS1REG, I5) == R_VREG_S_X(VS2REG, E25)) \ | |
| 4643 | { \ | |
| 4644 | ACCUM(E15).h.low = vres[E15] = R_VREG_S_X(VS1REG, I5); \ | |
| 4645 | if (ZERO_FLAG(E15) && CARRY_FLAG(E15)) SET_COMPARE_FLAG(E15); \ | |
| 4646 | } \ | |
| 4647 | if (R_VREG_S_X(VS1REG, I6) > R_VREG_S_X(VS2REG, E26)) \ | |
| 4648 | { \ | |
| 4649 | ACCUM(E16).h.low = vres[E16] = R_VREG_S_X(VS2REG, E26); \ | |
| 4650 | } \ | |
| 4651 | else if (R_VREG_S_X(VS1REG, I6) < R_VREG_S_X(VS2REG, E26)) \ | |
| 4652 | { \ | |
| 4653 | ACCUM(E16).h.low = vres[E16] = R_VREG_S_X(VS1REG, I6); \ | |
| 4654 | SET_COMPARE_FLAG(E16); \ | |
| 4655 | } \ | |
| 4656 | else if (R_VREG_S_X(VS1REG, I6) == R_VREG_S_X(VS2REG, E26)) \ | |
| 4657 | { \ | |
| 4658 | ACCUM(E16).h.low = vres[E16] = R_VREG_S_X(VS1REG, I6); \ | |
| 4659 | if (ZERO_FLAG(E16) && CARRY_FLAG(E16)) SET_COMPARE_FLAG(E16); \ | |
| 4660 | } \ | |
| 4661 | if (R_VREG_S_X(VS1REG, I7) > R_VREG_S_X(VS2REG, E27)) \ | |
| 4662 | { \ | |
| 4663 | ACCUM(E17).h.low = vres[E17] = R_VREG_S_X(VS2REG, E27); \ | |
| 4664 | } \ | |
| 4665 | else if (R_VREG_S_X(VS1REG, I7) < R_VREG_S_X(VS2REG, E27)) \ | |
| 4666 | { \ | |
| 4667 | ACCUM(E17).h.low = vres[E17] = R_VREG_S_X(VS1REG, I7); \ | |
| 4668 | SET_COMPARE_FLAG(E17); \ | |
| 4669 | } \ | |
| 4670 | else if (R_VREG_S_X(VS1REG, I7) == R_VREG_S_X(VS2REG, E27)) \ | |
| 4671 | { \ | |
| 4672 | ACCUM(E17).h.low = vres[E17] = R_VREG_S_X(VS1REG, I7); \ | |
| 4673 | if (ZERO_FLAG(E17) && CARRY_FLAG(E17)) SET_COMPARE_FLAG(E17); \ | |
| 4674 | } \ | |
| 4675 | rsp->flag[0] = 0; \ | |
| 4676 | W_VREG_S_X(VDREG, 7, vres[0]); \ | |
| 4677 | W_VREG_S_X(VDREG, 6, vres[1]); \ | |
| 4678 | W_VREG_S_X(VDREG, 5, vres[2]); \ | |
| 4679 | W_VREG_S_X(VDREG, 4, vres[3]); \ | |
| 4680 | W_VREG_S_X(VDREG, 3, vres[4]); \ | |
| 4681 | W_VREG_S_X(VDREG, 2, vres[5]); \ | |
| 4682 | W_VREG_S_X(VDREG, 1, vres[6]); \ | |
| 4683 | W_VREG_S_X(VDREG, 0, vres[7]); \ | |
| 4684 | } | |
| 4685 | ||
| 4686 | 2439 | INLINE void cfunc_rsp_vlt(void *param) |
| 4687 | 2440 | { |
| 4688 | 2441 | rsp_state *rsp = (rsp_state*)param; |
| r9854 | r9855 | |
| 4697 | 2450 | // Sets compare flags if elements in VS1 are less than VS2 |
| 4698 | 2451 | // Moves the element in VS2 to destination vector |
| 4699 | 2452 | |
| 4700 | switch(EL) | |
| 2453 | int sel; | |
| 2454 | rsp->flag[1] = 0; | |
| 2455 | ||
| 2456 | for (int i = 0; i < 8; i++) | |
| 4701 | 2457 | { |
| 4702 | case 0: /* 0, 1, 2, 3, 4, 5, 6, 7 - none */ /* 0, 1, 2, 3, 4, 5, 6, 7 - none */ | |
| 4703 | RSP_VLT(0, 1, 2, 3, 4, 5, 6, 7, 7, 6, 5, 4, 3, 2, 1, 0, 7, 6, 5, 4, 3, 2, 1, 0); | |
| 4704 | break; | |
| 4705 | case 1: /* 0, 1, 2, 3, 4, 5, 6, 7 - ??? */ /* 0, 1, 2, 3, 4, 5, 6, 7 - ??? */ | |
| 4706 | RSP_VLT(0, 1, 2, 3, 4, 5, 6, 7, 7, 6, 5, 4, 3, 2, 1, 0, 7, 6, 5, 4, 3, 2, 1, 0); | |
| 4707 | break; | |
| 4708 | case 2: /* 1, 3, 5, 7, 0, 2, 4, 6 - 0q */ /* 0, 0, 2, 2, 4, 4, 6, 6 - 0q */ | |
| 4709 | RSP_VLT(1, 3, 5, 7, 0, 2, 4, 6, 7, 5, 3, 1, 7, 5, 3, 1, 6, 4, 2, 0, 7, 5, 3, 1); | |
| 4710 | break; | |
| 4711 | case 3: /* 0, 2, 4, 6, 1, 3, 5, 7 - 1q */ /* 1, 1, 3, 3, 5, 5, 7, 7 - 1q */ | |
| 4712 | RSP_VLT(0, 2, 4, 6, 1, 3, 5, 7, 6, 4, 2, 0, 6, 4, 2, 0, 7, 5, 3, 1, 6, 4, 2, 0); | |
| 4713 | break; | |
| 4714 | case 4: /* 1, 2, 3, 5, 6, 7, 0, 4 - 0h */ /* 0, 0, 0, 0, 4, 4, 4, 4 - 0h */ | |
| 4715 | RSP_VLT(1, 2, 3, 5, 6, 7, 0, 4, 7, 7, 7, 3, 3, 3, 7, 3, 6, 5, 4, 2, 1, 0, 7, 3); | |
| 4716 | break; | |
| 4717 | case 5: /* 0, 2, 3, 4, 6, 7, 1, 5 - 1h */ /* 1, 1, 1, 1, 5, 5, 5, 5 - 1h */ | |
| 4718 | RSP_VLT(0, 2, 3, 4, 6, 7, 1, 5, 6, 6, 6, 2, 2, 2, 6, 2, 7, 5, 4, 3, 1, 0, 6, 2); | |
| 4719 | break; | |
| 4720 | case 6: /* 0, 1, 3, 4, 5, 7, 2, 6 - 2h */ /* 2, 2, 2, 2, 6, 6, 6, 6 - 2h */ | |
| 4721 | RSP_VLT(0, 1, 3, 4, 5, 7, 2, 6, 5, 5, 5, 1, 1, 1, 5, 1, 7, 6, 4, 3, 2, 0, 5, 1); | |
| 4722 | break; | |
| 4723 | case 7: /* 0, 1, 2, 4, 5, 6, 3, 7 - 3h */ /* 3, 3, 3, 3, 7, 7, 7, 7 - 3h */ | |
| 4724 | RSP_VLT(0, 1, 2, 4, 5, 6, 3, 7, 4, 4, 4, 0, 0, 0, 4, 0, 7, 6, 5, 3, 2, 1, 4, 0); | |
| 4725 | break; | |
| 4726 | case 8: /* 1, 2, 3, 4, 5, 6, 7, 0 - 0 */ /* 0, 0, 0, 0, 0, 0, 0, 0 - 0 */ | |
| 4727 | RSP_VLT(1, 2, 3, 4, 5, 6, 7, 0, 7, 7, 7, 7, 7, 7, 7, 7, 6, 5, 4, 3, 2, 1, 0, 7); | |
| 4728 | break; | |
| 4729 | case 9: /* 0, 2, 3, 4, 5, 6, 7, 1 - 1 */ /* 1, 1, 1, 1, 1, 1, 1, 1 - 0 */ | |
| 4730 | RSP_VLT(0, 2, 3, 4, 5, 6, 7, 1, 6, 6, 6, 6, 6, 6, 6, 6, 7, 5, 4, 3, 2, 1, 0, 6); | |
| 4731 | break; | |
| 4732 | case 10: /* 0, 1, 3, 4, 5, 6, 7, 2 - 2 */ /* 2, 2, 2, 2, 2, 2, 2, 2 - 0 */ | |
| 4733 | RSP_VLT(0, 1, 3, 4, 5, 6, 7, 2, 5, 5, 5, 5, 5, 5, 5, 5, 7, 6, 4, 3, 2, 1, 0, 5); | |
| 4734 | break; | |
| 4735 | case 11: /* 0, 1, 2, 4, 5, 6, 7, 3 - 3 */ /* 3, 3, 3, 3, 3, 3, 3, 3 - 0 */ | |
| 4736 | RSP_VLT(0, 1, 2, 4, 5, 6, 7, 3, 4, 4, 4, 4, 4, 4, 4, 4, 7, 6, 5, 3, 2, 1, 0, 4); | |
| 4737 | break; | |
| 4738 | case 12: /* 0, 1, 2, 3, 5, 6, 7, 4 - 4 */ /* 4, 4, 4, 4, 4, 4, 4, 4 - 0 */ | |
| 4739 | RSP_VLT(0, 1, 2, 3, 5, 6, 7, 4, 3, 3, 3, 3, 3, 3, 3, 3, 7, 6, 5, 4, 2, 1, 0, 3); | |
| 4740 | break; | |
| 4741 | case 13: /* 0, 1, 2, 3, 4, 6, 7, 5 - 5 */ /* 5, 5, 5, 5, 5, 5, 5, 5 - 0 */ | |
| 4742 | RSP_VLT(0, 1, 2, 3, 4, 6, 7, 5, 2, 2, 2, 2, 2, 2, 2, 2, 7, 6, 5, 4, 3, 1, 0, 2); | |
| 4743 | break; | |
| 4744 | case 14: /* 0, 1, 2, 3, 4, 5, 7, 6 - 6 */ /* 6, 6, 6, 6, 6, 6, 6, 6 - 0 */ | |
| 4745 | RSP_VLT(0, 1, 2, 3, 4, 5, 7, 6, 1, 1, 1, 1, 1, 1, 1, 1, 7, 6, 5, 4, 3, 2, 0, 1); | |
| 4746 | break; | |
| 4747 | case 15: /* 0, 1, 2, 3, 4, 5, 6, 7 - 7 */ /* 7, 7, 7, 7, 7, 7, 7, 7 - 0 */ | |
| 4748 | RSP_VLT(0, 1, 2, 3, 4, 5, 6, 7, 0, 0, 0, 0, 0, 0, 0, 0, 7, 6, 5, 4, 3, 2, 1, 0); | |
| 4749 | break; | |
| 2458 | sel = VEC_EL_2(EL, i); | |
| 2459 | ||
| 2460 | if (VREG_S(VS1REG, i) < VREG_S(VS2REG, sel)) | |
| 2461 | { | |
| 2462 | SET_COMPARE_FLAG(i); | |
| 2463 | } | |
| 2464 | else if (VREG_S(VS1REG, i) == VREG_S(VS2REG, sel)) | |
| 2465 | { | |
| 2466 | if (ZERO_FLAG(i) == 1 && CARRY_FLAG(i) != 0) | |
| 2467 | { | |
| 2468 | SET_COMPARE_FLAG(i); | |
| 2469 | } | |
| 2470 | } | |
| 2471 | ||
| 2472 | if (COMPARE_FLAG(i)) | |
| 2473 | { | |
| 2474 | vres[i] = VREG_S(VS1REG, i); | |
| 2475 | } | |
| 2476 | else | |
| 2477 | { | |
| 2478 | vres[i] = VREG_S(VS2REG, sel); | |
| 2479 | } | |
| 2480 | ||
| 2481 | ACCUM_L(i) = vres[i]; | |
| 4750 | 2482 | } |
| 4751 | 2483 | |
| 2484 | rsp->flag[0] = 0; | |
| 2485 | WRITEBACK_RESULT(); | |
| 4752 | 2486 | } |
| 4753 | 2487 | |
| 4754 | 2488 | INLINE void cfunc_rsp_veq(void *param) |
| r9854 | r9855 | |
| 4765 | 2499 | // Sets compare flags if elements in VS1 are equal with VS2 |
| 4766 | 2500 | // Moves the element in VS2 to destination vector |
| 4767 | 2501 | |
| 2502 | int sel; | |
| 4768 | 2503 | rsp->flag[1] = 0; |
| 4769 | 2504 | |
| 4770 | for (i=0; i < 8; i++) | |
| 2505 | for (i = 0; i < 8; i++) | |
| 4771 | 2506 | { |
| 4772 | int del = VEC_EL_1(EL, i); | |
| 4773 | int sel = VEC_EL_2(EL, del); | |
| 2507 | sel = VEC_EL_2(EL, i); | |
| 4774 | 2508 | |
| 4775 | vres[del] = R_VREG_S(VS2REG, sel); | |
| 4776 | W_ACCUM_L(del, vres[del]); | |
| 4777 | ||
| 4778 | if (R_VREG_S(VS1REG, del) == R_VREG_S(VS2REG, sel)) | |
| 2509 | if ((VREG_S(VS1REG, i) == VREG_S(VS2REG, sel)) && ZERO_FLAG(i) == 0) | |
| 4779 | 2510 | { |
| 4780 | if (ZERO_FLAG(del) == 0) | |
| 4781 | { | |
| 4782 | SET_COMPARE_FLAG(del); | |
| 4783 | } | |
| 2511 | SET_COMPARE_FLAG(i); | |
| 2512 | vres[i] = VREG_S(VS1REG, i); | |
| 4784 | 2513 | } |
| 2514 | else | |
| 2515 | { | |
| 2516 | vres[i] = VREG_S(VS2REG, sel); | |
| 2517 | } | |
| 2518 | ACCUM_L(i) = vres[i]; | |
| 4785 | 2519 | } |
| 4786 | 2520 | |
| 4787 | 2521 | rsp->flag[0] = 0; |
| r9854 | r9855 | |
| 4802 | 2536 | // Sets compare flags if elements in VS1 are not equal with VS2 |
| 4803 | 2537 | // Moves the element in VS2 to destination vector |
| 4804 | 2538 | |
| 2539 | int sel; | |
| 4805 | 2540 | rsp->flag[1] = 0; |
| 4806 | 2541 | |
| 4807 | for (i=0; i < 8; i++) | |
| 2542 | for (i=0; i < 8; i++)//ïåðåïèñàíî ìíîé | |
| 4808 | 2543 | { |
| 4809 | int del = VEC_EL_1(EL, i); | |
| 4810 | int sel = VEC_EL_2(EL, del); | |
| 2544 | sel = VEC_EL_2(EL, i); | |
| 4811 | 2545 | |
| 4812 | vres[del] = R_VREG_S(VS1REG, del); | |
| 4813 | W_ACCUM_L(del, vres[del]); | |
| 4814 | ||
| 4815 | if (R_VREG_S(VS1REG, del) != R_VREG_S(VS2REG, sel)) | |
| 2546 | if (VREG_S(VS1REG, i) != VREG_S(VS2REG, sel)) | |
| 4816 | 2547 | { |
| 4817 | SET_COMPARE_FLAG( | |
| 2548 | SET_COMPARE_FLAG(i | |
| 4818 | 2549 | } |
| 4819 | 2550 | else |
| 4820 | 2551 | { |
| 4821 | if (ZERO_FLAG( | |
| 2552 | if (ZERO_FLAG(i | |
| 4822 | 2553 | { |
| 4823 | SET_COMPARE_FLAG( | |
| 2554 | SET_COMPARE_FLAG(i | |
| 4824 | 2555 | } |
| 4825 | 2556 | } |
| 2557 | if (COMPARE_FLAG(i)) | |
| 2558 | { | |
| 2559 | vres[i] = VREG_S(VS1REG, i); | |
| 2560 | } | |
| 2561 | else | |
| 2562 | { | |
| 2563 | vres[i] = VREG_S(VS2REG, sel); | |
| 2564 | } | |
| 2565 | ACCUM_L(i) = vres[i]; | |
| 4826 | 2566 | } |
| 4827 | 2567 | |
| 4828 | 2568 | rsp->flag[0] = 0; |
| 4829 | 2569 | WRITEBACK_RESULT(); |
| 4830 | 2570 | } |
| 4831 | 2571 | |
| 4832 | #define RSP_VGE(E10, E11, E12, E13, E14, E15, E16, E17, E20, E21, E22, E23, E24, E25, E26, E27, I0, I1, I2, I3, I4, I5, I6, I7) \ | |
| 4833 | { \ | |
| 4834 | rsp->flag[1] = 0; \ | |
| 4835 | \ | |
| 4836 | if (R_VREG_S_X(VS1REG, I0) > R_VREG_S_X(VS2REG, E20)) \ | |
| 4837 | { \ | |
| 4838 | ACCUM(E10).h.low = vres[E10] = R_VREG_S_X(VS1REG, I0); \ | |
| 4839 | SET_COMPARE_FLAG(E10); \ | |
| 4840 | } \ | |
| 4841 | else if (R_VREG_S_X(VS1REG, I0) == R_VREG_S_X(VS2REG, E20)) \ | |
| 4842 | { \ | |
| 4843 | if (!ZERO_FLAG(E10) || !CARRY_FLAG(E10)) \ | |
| 4844 | { \ | |
| 4845 | ACCUM(E10).h.low = vres[E10] = R_VREG_S_X(VS1REG, I0); \ | |
| 4846 | SET_COMPARE_FLAG(E10); \ | |
| 4847 | } \ | |
| 4848 | else \ | |
| 4849 | { \ | |
| 4850 | ACCUM(E10).h.low = vres[E10] = R_VREG_S_X(VS2REG, E20); \ | |
| 4851 | } \ | |
| 4852 | } \ | |
| 4853 | else \ | |
| 4854 | { \ | |
| 4855 | ACCUM(E10).h.low = vres[E10] = R_VREG_S_X(VS2REG, E20); \ | |
| 4856 | } \ | |
| 4857 | if (R_VREG_S_X(VS1REG, I1) > R_VREG_S_X(VS2REG, E21)) \ | |
| 4858 | { \ | |
| 4859 | ACCUM(E11).h.low = vres[E11] = R_VREG_S_X(VS1REG, I1); \ | |
| 4860 | SET_COMPARE_FLAG(E11); \ | |
| 4861 | } \ | |
| 4862 | else if (R_VREG_S_X(VS1REG, I1) == R_VREG_S_X(VS2REG, E21)) \ | |
| 4863 | { \ | |
| 4864 | if (!ZERO_FLAG(E11) || !CARRY_FLAG(E11)) \ | |
| 4865 | { \ | |
| 4866 | ACCUM(E11).h.low = vres[E11] = R_VREG_S_X(VS1REG, I1); \ | |
| 4867 | SET_COMPARE_FLAG(E11); \ | |
| 4868 | } \ | |
| 4869 | else \ | |
| 4870 | { \ | |
| 4871 | ACCUM(E11).h.low = vres[E11] = R_VREG_S_X(VS2REG, E21); \ | |
| 4872 | } \ | |
| 4873 | } \ | |
| 4874 | else \ | |
| 4875 | { \ | |
| 4876 | ACCUM(E11).h.low = vres[E11] = R_VREG_S_X(VS2REG, E21); \ | |
| 4877 | } \ | |
| 4878 | if (R_VREG_S_X(VS1REG, I2) > R_VREG_S_X(VS2REG, E22)) \ | |
| 4879 | { \ | |
| 4880 | ACCUM(E12).h.low = vres[E12] = R_VREG_S_X(VS1REG, I2); \ | |
| 4881 | SET_COMPARE_FLAG(E12); \ | |
| 4882 | } \ | |
| 4883 | else if (R_VREG_S_X(VS1REG, I2) == R_VREG_S_X(VS2REG, E22)) \ | |
| 4884 | { \ | |
| 4885 | if (!ZERO_FLAG(E12) || !CARRY_FLAG(E12)) \ | |
| 4886 | { \ | |
| 4887 | ACCUM(E12).h.low = vres[E12] = R_VREG_S_X(VS1REG, I2); \ | |
| 4888 | SET_COMPARE_FLAG(E12); \ | |
| 4889 | } \ | |
| 4890 | else \ | |
| 4891 | { \ | |
| 4892 | ACCUM(E12).h.low = vres[E12] = R_VREG_S_X(VS2REG, E22); \ | |
| 4893 | } \ | |
| 4894 | } \ | |
| 4895 | else \ | |
| 4896 | { \ | |
| 4897 | ACCUM(E12).h.low = vres[E12] = R_VREG_S_X(VS2REG, E22); \ | |
| 4898 | } \ | |
| 4899 | if (R_VREG_S_X(VS1REG, I3) > R_VREG_S_X(VS2REG, E23)) \ | |
| 4900 | { \ | |
| 4901 | ACCUM(E13).h.low = vres[E13] = R_VREG_S_X(VS1REG, I3); \ | |
| 4902 | SET_COMPARE_FLAG(E13); \ | |
| 4903 | } \ | |
| 4904 | else if (R_VREG_S_X(VS1REG, I3) == R_VREG_S_X(VS2REG, E23)) \ | |
| 4905 | { \ | |
| 4906 | if (!ZERO_FLAG(E13) || !CARRY_FLAG(E13)) \ | |
| 4907 | { \ | |
| 4908 | ACCUM(E13).h.low = vres[E13] = R_VREG_S_X(VS1REG, I3); \ | |
| 4909 | SET_COMPARE_FLAG(E13); \ | |
| 4910 | } \ | |
| 4911 | else \ | |
| 4912 | { \ | |
| 4913 | ACCUM(E13).h.low = vres[E13] = R_VREG_S_X(VS2REG, E23); \ | |
| 4914 | } \ | |
| 4915 | } \ | |
| 4916 | else \ | |
| 4917 | { \ | |
| 4918 | ACCUM(E13).h.low = vres[E13] = R_VREG_S_X(VS2REG, E23); \ | |
| 4919 | } \ | |
| 4920 | if (R_VREG_S_X(VS1REG, I4) > R_VREG_S_X(VS2REG, E24)) \ | |
| 4921 | { \ | |
| 4922 | ACCUM(E14).h.low = vres[E14] = R_VREG_S_X(VS1REG, I4); \ | |
| 4923 | SET_COMPARE_FLAG(E14); \ | |
| 4924 | } \ | |
| 4925 | else if (R_VREG_S_X(VS1REG, I4) == R_VREG_S_X(VS2REG, E24)) \ | |
| 4926 | { \ | |
| 4927 | if (!ZERO_FLAG(E14) || !CARRY_FLAG(E14)) \ | |
| 4928 | { \ | |
| 4929 | ACCUM(E14).h.low = vres[E14] = R_VREG_S_X(VS1REG, I4); \ | |
| 4930 | SET_COMPARE_FLAG(E14); \ | |
| 4931 | } \ | |
| 4932 | else \ | |
| 4933 | { \ | |
| 4934 | ACCUM(E14).h.low = vres[E14] = R_VREG_S_X(VS2REG, E24); \ | |
| 4935 | } \ | |
| 4936 | } \ | |
| 4937 | else \ | |
| 4938 | { \ | |
| 4939 | ACCUM(E14).h.low = vres[E14] = R_VREG_S_X(VS2REG, E24); \ | |
| 4940 | } \ | |
| 4941 | if (R_VREG_S_X(VS1REG, I5) > R_VREG_S_X(VS2REG, E25)) \ | |
| 4942 | { \ | |
| 4943 | ACCUM(E15).h.low = vres[E15] = R_VREG_S_X(VS1REG, I5); \ | |
| 4944 | SET_COMPARE_FLAG(E15); \ | |
| 4945 | } \ | |
| 4946 | else if (R_VREG_S_X(VS1REG, I5) == R_VREG_S_X(VS2REG, E25)) \ | |
| 4947 | { \ | |
| 4948 | if (!ZERO_FLAG(E15) || !CARRY_FLAG(E15)) \ | |
| 4949 | { \ | |
| 4950 | ACCUM(E15).h.low = vres[E15] = R_VREG_S_X(VS1REG, I5); \ | |
| 4951 | SET_COMPARE_FLAG(E15); \ | |
| 4952 | } \ | |
| 4953 | else \ | |
| 4954 | { \ | |
| 4955 | ACCUM(E15).h.low = vres[E15] = R_VREG_S_X(VS2REG, E25); \ | |
| 4956 | } \ | |
| 4957 | } \ | |
| 4958 | else \ | |
| 4959 | { \ | |
| 4960 | ACCUM(E15).h.low = vres[E15] = R_VREG_S_X(VS2REG, E25); \ | |
| 4961 | } \ | |
| 4962 | if (R_VREG_S_X(VS1REG, I6) > R_VREG_S_X(VS2REG, E26)) \ | |
| 4963 | { \ | |
| 4964 | ACCUM(E16).h.low = vres[E16] = R_VREG_S_X(VS1REG, I6); \ | |
| 4965 | SET_COMPARE_FLAG(E16); \ | |
| 4966 | } \ | |
| 4967 | else if (R_VREG_S_X(VS1REG, I6) == R_VREG_S_X(VS2REG, E26)) \ | |
| 4968 | { \ | |
| 4969 | if (!ZERO_FLAG(E16) || !CARRY_FLAG(E16)) \ | |
| 4970 | { \ | |
| 4971 | ACCUM(E16).h.low = vres[E16] = R_VREG_S_X(VS1REG, I6); \ | |
| 4972 | SET_COMPARE_FLAG(E16); \ | |
| 4973 | } \ | |
| 4974 | else \ | |
| 4975 | { \ | |
| 4976 | ACCUM(E16).h.low = vres[E16] = R_VREG_S_X(VS2REG, E26); \ | |
| 4977 | } \ | |
| 4978 | } \ | |
| 4979 | else \ | |
| 4980 | { \ | |
| 4981 | ACCUM(E16).h.low = vres[E16] = R_VREG_S_X(VS2REG, E26); \ | |
| 4982 | } \ | |
| 4983 | if (R_VREG_S_X(VS1REG, I7) > R_VREG_S_X(VS2REG, E27)) \ | |
| 4984 | { \ | |
| 4985 | ACCUM(E17).h.low = vres[E17] = R_VREG_S_X(VS1REG, I7); \ | |
| 4986 | SET_COMPARE_FLAG(E17); \ | |
| 4987 | } \ | |
| 4988 | else if (R_VREG_S_X(VS1REG, I7) == R_VREG_S_X(VS2REG, E27)) \ | |
| 4989 | { \ | |
| 4990 | if (!ZERO_FLAG(E17) || !CARRY_FLAG(E17)) \ | |
| 4991 | { \ | |
| 4992 | ACCUM(E17).h.low = vres[E17] = R_VREG_S_X(VS1REG, I7); \ | |
| 4993 | SET_COMPARE_FLAG(E17); \ | |
| 4994 | } \ | |
| 4995 | else \ | |
| 4996 | { \ | |
| 4997 | ACCUM(E17).h.low = vres[E17] = R_VREG_S_X(VS2REG, E27); \ | |
| 4998 | } \ | |
| 4999 | } \ | |
| 5000 | else \ | |
| 5001 | { \ | |
| 5002 | ACCUM(E17).h.low = vres[E17] = R_VREG_S_X(VS2REG, E27); \ | |
| 5003 | } \ | |
| 5004 | rsp->flag[0] = 0; \ | |
| 5005 | W_VREG_S_X(VDREG, 7, vres[0]); \ | |
| 5006 | W_VREG_S_X(VDREG, 6, vres[1]); \ | |
| 5007 | W_VREG_S_X(VDREG, 5, vres[2]); \ | |
| 5008 | W_VREG_S_X(VDREG, 4, vres[3]); \ | |
| 5009 | W_VREG_S_X(VDREG, 3, vres[4]); \ | |
| 5010 | W_VREG_S_X(VDREG, 2, vres[5]); \ | |
| 5011 | W_VREG_S_X(VDREG, 1, vres[6]); \ | |
| 5012 | W_VREG_S_X(VDREG, 0, vres[7]); \ | |
| 5013 | } | |
| 5014 | ||
| 5015 | 2572 | INLINE void cfunc_rsp_vge(void *param) |
| 5016 | 2573 | { |
| 5017 | 2574 | rsp_state *rsp = (rsp_state*)param; |
| r9854 | r9855 | |
| 5026 | 2583 | // Sets compare flags if elements in VS1 are greater or equal with VS2 |
| 5027 | 2584 | // Moves the element in VS2 to destination vector |
| 5028 | 2585 | |
| 5029 | #if 1 | |
| 5030 | switch(EL) | |
| 5031 | { | |
| 5032 | case 0: /* 0, 1, 2, 3, 4, 5, 6, 7 - none */ /* 0, 1, 2, 3, 4, 5, 6, 7 - none */ | |
| 5033 | RSP_VGE(0, 1, 2, 3, 4, 5, 6, 7, 7, 6, 5, 4, 3, 2, 1, 0, 7, 6, 5, 4, 3, 2, 1, 0); | |
| 5034 | break; | |
| 5035 | case 1: /* 0, 1, 2, 3, 4, 5, 6, 7 - ??? */ /* 0, 1, 2, 3, 4, 5, 6, 7 - ??? */ | |
| 5036 | RSP_VGE(0, 1, 2, 3, 4, 5, 6, 7, 7, 6, 5, 4, 3, 2, 1, 0, 7, 6, 5, 4, 3, 2, 1, 0); | |
| 5037 | break; | |
| 5038 | case 2: /* 1, 3, 5, 7, 0, 2, 4, 6 - 0q */ /* 0, 0, 2, 2, 4, 4, 6, 6 - 0q */ | |
| 5039 | RSP_VGE(1, 3, 5, 7, 0, 2, 4, 6, 7, 5, 3, 1, 7, 5, 3, 1, 6, 4, 2, 0, 7, 5, 3, 1); | |
| 5040 | break; | |
| 5041 | case 3: /* 0, 2, 4, 6, 1, 3, 5, 7 - 1q */ /* 1, 1, 3, 3, 5, 5, 7, 7 - 1q */ | |
| 5042 | RSP_VGE(0, 2, 4, 6, 1, 3, 5, 7, 6, 4, 2, 0, 6, 4, 2, 0, 7, 5, 3, 1, 6, 4, 2, 0); | |
| 5043 | break; | |
| 5044 | case 4: /* 1, 2, 3, 5, 6, 7, 0, 4 - 0h */ /* 0, 0, 0, 0, 4, 4, 4, 4 - 0h */ | |
| 5045 | RSP_VGE(1, 2, 3, 5, 6, 7, 0, 4, 7, 7, 7, 3, 3, 3, 7, 3, 6, 5, 4, 2, 1, 0, 7, 3); | |
| 5046 | break; | |
| 5047 | case 5: /* 0, 2, 3, 4, 6, 7, 1, 5 - 1h */ /* 1, 1, 1, 1, 5, 5, 5, 5 - 1h */ | |
| 5048 | RSP_VGE(0, 2, 3, 4, 6, 7, 1, 5, 6, 6, 6, 2, 2, 2, 6, 2, 7, 5, 4, 3, 1, 0, 6, 2); | |
| 5049 | break; | |
| 5050 | case 6: /* 0, 1, 3, 4, 5, 7, 2, 6 - 2h */ /* 2, 2, 2, 2, 6, 6, 6, 6 - 2h */ | |
| 5051 | RSP_VGE(0, 1, 3, 4, 5, 7, 2, 6, 5, 5, 5, 1, 1, 1, 5, 1, 7, 6, 4, 3, 2, 0, 5, 1); | |
| 5052 | break; | |
| 5053 | case 7: /* 0, 1, 2, 4, 5, 6, 3, 7 - 3h */ /* 3, 3, 3, 3, 7, 7, 7, 7 - 3h */ | |
| 5054 | RSP_VGE(0, 1, 2, 4, 5, 6, 3, 7, 4, 4, 4, 0, 0, 0, 4, 0, 7, 6, 5, 3, 2, 1, 4, 0); | |
| 5055 | break; | |
| 5056 | case 8: /* 1, 2, 3, 4, 5, 6, 7, 0 - 0 */ /* 0, 0, 0, 0, 0, 0, 0, 0 - 0 */ | |
| 5057 | RSP_VGE(1, 2, 3, 4, 5, 6, 7, 0, 7, 7, 7, 7, 7, 7, 7, 7, 6, 5, 4, 3, 2, 1, 0, 7); | |
| 5058 | break; | |
| 5059 | case 9: /* 0, 2, 3, 4, 5, 6, 7, 1 - 1 */ /* 1, 1, 1, 1, 1, 1, 1, 1 - 0 */ | |
| 5060 | RSP_VGE(0, 2, 3, 4, 5, 6, 7, 1, 6, 6, 6, 6, 6, 6, 6, 6, 7, 5, 4, 3, 2, 1, 0, 6); | |
| 5061 | break; | |
| 5062 | case 10: /* 0, 1, 3, 4, 5, 6, 7, 2 - 2 */ /* 2, 2, 2, 2, 2, 2, 2, 2 - 0 */ | |
| 5063 | RSP_VGE(0, 1, 3, 4, 5, 6, 7, 2, 5, 5, 5, 5, 5, 5, 5, 5, 7, 6, 4, 3, 2, 1, 0, 5); | |
| 5064 | break; | |
| 5065 | case 11: /* 0, 1, 2, 4, 5, 6, 7, 3 - 3 */ /* 3, 3, 3, 3, 3, 3, 3, 3 - 0 */ | |
| 5066 | RSP_VGE(0, 1, 2, 4, 5, 6, 7, 3, 4, 4, 4, 4, 4, 4, 4, 4, 7, 6, 5, 3, 2, 1, 0, 4); | |
| 5067 | break; | |
| 5068 | case 12: /* 0, 1, 2, 3, 5, 6, 7, 4 - 4 */ /* 4, 4, 4, 4, 4, 4, 4, 4 - 0 */ | |
| 5069 | RSP_VGE(0, 1, 2, 3, 5, 6, 7, 4, 3, 3, 3, 3, 3, 3, 3, 3, 7, 6, 5, 4, 2, 1, 0, 3); | |
| 5070 | break; | |
| 5071 | case 13: /* 0, 1, 2, 3, 4, 6, 7, 5 - 5 */ /* 5, 5, 5, 5, 5, 5, 5, 5 - 0 */ | |
| 5072 | RSP_VGE(0, 1, 2, 3, 4, 6, 7, 5, 2, 2, 2, 2, 2, 2, 2, 2, 7, 6, 5, 4, 3, 1, 0, 2); | |
| 5073 | break; | |
| 5074 | case 14: /* 0, 1, 2, 3, 4, 5, 7, 6 - 6 */ /* 6, 6, 6, 6, 6, 6, 6, 6 - 0 */ | |
| 5075 | RSP_VGE(0, 1, 2, 3, 4, 5, 7, 6, 1, 1, 1, 1, 1, 1, 1, 1, 7, 6, 5, 4, 3, 2, 0, 1); | |
| 5076 | break; | |
| 5077 | case 15: /* 0, 1, 2, 3, 4, 5, 6, 7 - 7 */ /* 7, 7, 7, 7, 7, 7, 7, 7 - 0 */ | |
| 5078 | RSP_VGE(0, 1, 2, 3, 4, 5, 6, 7, 0, 0, 0, 0, 0, 0, 0, 0, 7, 6, 5, 4, 3, 2, 1, 0); | |
| 5079 | break; | |
| 5080 | } | |
| 5081 | #else | |
| 2586 | int sel; | |
| 5082 | 2587 | rsp->flag[1] = 0; |
| 5083 | 2588 | |
| 5084 | for (i=0; i < 8; i++) | |
| 2589 | for (int i = 0; i < 8; i++) | |
| 5085 | 2590 | { |
| 5086 | int del = VEC_EL_1(EL, i); | |
| 5087 | int sel = VEC_EL_2(EL, del); | |
| 2591 | sel = VEC_EL_2(EL, i); | |
| 5088 | 2592 | |
| 5089 | if ( | |
| 2593 | if ( | |
| 5090 | 2594 | { |
| 5091 | if (ZERO_FLAG( | |
| 2595 | if (ZERO_FLAG(i | |
| 5092 | 2596 | { |
| 5093 | SET_COMPARE_FLAG( | |
| 2597 | SET_COMPARE_FLAG(i | |
| 5094 | 2598 | } |
| 5095 | 2599 | } |
| 5096 | else if ( | |
| 2600 | else if ( | |
| 5097 | 2601 | { |
| 5098 | SET_COMPARE_FLAG( | |
| 2602 | SET_COMPARE_FLAG(i | |
| 5099 | 2603 | } |
| 5100 | 2604 | |
| 5101 | if (COMPARE_FLAG( | |
| 2605 | if (COMPARE_FLAG(i | |
| 5102 | 2606 | { |
| 5103 | vres[ | |
| 2607 | vres[i | |
| 5104 | 2608 | } |
| 5105 | 2609 | else |
| 5106 | 2610 | { |
| 5107 | vres[ | |
| 2611 | vres[i | |
| 5108 | 2612 | } |
| 5109 | 2613 | |
| 5110 | | |
| 2614 | | |
| 5111 | 2615 | } |
| 5112 | 2616 | |
| 5113 | 2617 | rsp->flag[0] = 0; |
| 5114 | 2618 | WRITEBACK_RESULT(); |
| 5115 | #endif | |
| 5116 | 2619 | } |
| 5117 | 2620 | |
| 5118 | 2621 | INLINE void cfunc_rsp_vcl(void *param) |
| r9854 | r9855 | |
| 5128 | 2631 | // |
| 5129 | 2632 | // Vector clip low |
| 5130 | 2633 | |
| 5131 | for (i=0; i < 8; i++) | |
| 2634 | int sel; | |
| 2635 | INT16 s1, s2; | |
| 2636 | for (i = 0; i < 8; i++) | |
| 5132 | 2637 | { |
| 5133 | int del = VEC_EL_1(EL, i); | |
| 5134 | int sel = VEC_EL_2(EL, del); | |
| 5135 | INT16 s1 = R_VREG_S(VS1REG, del); | |
| 5136 | INT16 s2 = R_VREG_S(VS2REG, sel); | |
| 2638 | sel = VEC_EL_2(EL, i); | |
| 2639 | s1 = VREG_S(VS1REG, i); | |
| 2640 | s2 = VREG_S(VS2REG, sel); | |
| 5137 | 2641 | |
| 5138 | if (CARRY_FLAG( | |
| 2642 | if (CARRY_FLAG(i | |
| 5139 | 2643 | { |
| 5140 | if (ZERO_FLAG(del) != 0) | |
| 2644 | ||
| 2645 | if (ZERO_FLAG(i) != 0) | |
| 5141 | 2646 | { |
| 5142 | if (COMPARE_FLAG(del) != 0) | |
| 2647 | ||
| 2648 | if (COMPARE_FLAG(i) != 0) | |
| 5143 | 2649 | { |
| 5144 | | |
| 2650 | | |
| 5145 | 2651 | } |
| 5146 | 2652 | else |
| 5147 | 2653 | { |
| 5148 | | |
| 2654 | | |
| 5149 | 2655 | } |
| 5150 | 2656 | } |
| 5151 | else | |
| 2657 | else//ZERO_FLAG(i)==0 | |
| 5152 | 2658 | { |
| 5153 | if (rsp->flag[2] & (1 << (del))) | |
| 2659 | ||
| 2660 | if (rsp->flag[2] & (1 << (i))) | |
| 5154 | 2661 | { |
| 2662 | ||
| 5155 | 2663 | if (((UINT32)(UINT16)(s1) + (UINT32)(UINT16)(s2)) > 0x10000) |
| 5156 | { | |
| 5157 | W_ACCUM_L(del, s1); | |
| 5158 | CLEAR_COMPARE_FLAG(del); | |
| 2664 | {//proper fix for Harvest Moon 64, r4 | |
| 2665 | ||
| 2666 | ACCUM_L(i) = s1; | |
| 2667 | CLEAR_COMPARE_FLAG(i); | |
| 5159 | 2668 | } |
| 5160 | 2669 | else |
| 5161 | 2670 | { |
| 5162 | W_ACCUM_L(del, -((UINT16)s2)); | |
| 5163 | SET_COMPARE_FLAG(del); | |
| 2671 | ||
| 2672 | ACCUM_L(i) = -((UINT16)s2); | |
| 2673 | SET_COMPARE_FLAG(i); | |
| 5164 | 2674 | } |
| 5165 | 2675 | } |
| 5166 | 2676 | else |
| 5167 | 2677 | { |
| 5168 | if (((UINT32)(INT16)(s1) + (UINT32)(INT16)(s2)) != 0) | |
| 2678 | if (((UINT32)(UINT16)(s1) + (UINT32)(UINT16)(s2)) != 0) | |
| 5169 | 2679 | { |
| 5170 | W_ACCUM_L(del, s1); | |
| 5171 | CLEAR_COMPARE_FLAG(del); | |
| 2680 | ACCUM_L(i) = s1; | |
| 2681 | CLEAR_COMPARE_FLAG(i); | |
| 5172 | 2682 | } |
| 5173 | 2683 | else |
| 5174 | 2684 | { |
| 5175 | W_ACCUM_L(del, -((UINT16)s2)); | |
| 5176 | SET_COMPARE_FLAG(del); | |
| 2685 | ACCUM_L(i) = -((UINT16)s2); | |
| 2686 | SET_COMPARE_FLAG(i); | |
| 5177 | 2687 | } |
| 5178 | 2688 | } |
| 5179 | 2689 | } |
| 5180 | } | |
| 5181 | else | |
| 2690 | }// | |
| 2691 | else//CARRY_FLAG(i)==0 | |
| 5182 | 2692 | { |
| 5183 | if (ZERO_FLAG(del) != 0) | |
| 2693 | ||
| 2694 | if (ZERO_FLAG(i) != 0) | |
| 5184 | 2695 | { |
| 5185 | if (rsp->flag[1] & (0x100 << del)) | |
| 2696 | ||
| 2697 | if (rsp->flag[1] & (1 << (8+i))) | |
| 5186 | 2698 | { |
| 5187 | | |
| 2699 | | |
| 5188 | 2700 | } |
| 5189 | 2701 | else |
| 5190 | 2702 | { |
| 5191 | | |
| 2703 | | |
| 5192 | 2704 | } |
| 5193 | 2705 | } |
| 5194 | 2706 | else |
| 5195 | 2707 | { |
| 5196 | 2708 | if (((INT32)(UINT16)s1 - (INT32)(UINT16)s2) >= 0) |
| 5197 | 2709 | { |
| 5198 | W_ACCUM_L(del, s2); | |
| 5199 | rsp->flag[1] |= (0x100 << del); | |
| 2710 | ACCUM_L(i) = s2; | |
| 2711 | rsp->flag[1] |= (1 << (8+i)); | |
| 5200 | 2712 | } |
| 5201 | 2713 | else |
| 5202 | 2714 | { |
| 5203 | W_ACCUM_L(del, s1); | |
| 5204 | rsp->flag[1] &= ~(0x100 << del); | |
| 2715 | ACCUM_L(i) = s1; | |
| 2716 | rsp->flag[1] &= ~(1 << (8+i)); | |
| 5205 | 2717 | } |
| 5206 | 2718 | } |
| 5207 | 2719 | } |
| 5208 | 2720 | |
| 5209 | vres[ | |
| 2721 | vres[i | |
| 5210 | 2722 | } |
| 5211 | 2723 | rsp->flag[0] = 0; |
| 5212 | 2724 | rsp->flag[2] = 0; |
| r9854 | r9855 | |
| 5226 | 2738 | // |
| 5227 | 2739 | // Vector clip high |
| 5228 | 2740 | |
| 2741 | int sel; | |
| 2742 | INT16 s1, s2; | |
| 5229 | 2743 | rsp->flag[0] = 0; |
| 5230 | 2744 | rsp->flag[1] = 0; |
| 5231 | 2745 | rsp->flag[2] = 0; |
| 2746 | UINT32 vce = 0; | |
| 5232 | 2747 | |
| 5233 | 2748 | for (i=0; i < 8; i++) |
| 5234 | 2749 | { |
| 5235 | int del = VEC_EL_1(EL, i); | |
| 5236 | int sel = VEC_EL_2(EL, del); | |
| 5237 | INT16 s1 = R_VREG_S(VS1REG, del); | |
| 5238 | INT16 s2 = R_VREG_S(VS2REG, sel); | |
| 2750 | sel = VEC_EL_2(EL, i); | |
| 2751 | s1 = VREG_S(VS1REG, i); | |
| 2752 | s2 = VREG_S(VS2REG, sel); | |
| 5239 | 2753 | |
| 5240 | 2754 | if ((s1 ^ s2) < 0) |
| 5241 | 2755 | { |
| 5242 | SET_CARRY_FLAG(del); | |
| 2756 | vce = (s1 + s2 == -1); | |
| 2757 | SET_CARRY_FLAG(i); | |
| 5243 | 2758 | if (s2 < 0) |
| 5244 | 2759 | { |
| 5245 | rsp->flag[1] |= ( | |
| 2760 | rsp->flag[1] |= ( | |
| 5246 | 2761 | } |
| 5247 | 2762 | |
| 5248 | 2763 | if (s1 + s2 <= 0) |
| 5249 | 2764 | { |
| 5250 | if (s1 + s2 == -1) | |
| 5251 | { | |
| 5252 | rsp->flag[2] |= (1 << (del)); | |
| 5253 | } | |
| 5254 | SET_COMPARE_FLAG(del); | |
| 5255 | vres[del] = -((UINT16)s2); | |
| 2765 | SET_COMPARE_FLAG(i); | |
| 2766 | vres[i] = -((UINT16)s2); | |
| 5256 | 2767 | } |
| 5257 | 2768 | else |
| 5258 | 2769 | { |
| 5259 | vres[ | |
| 2770 | vres[i | |
| 5260 | 2771 | } |
| 5261 | 2772 | |
| 5262 | 2773 | if (s1 + s2 != 0) |
| 5263 | 2774 | { |
| 5264 | 2775 | if (s1 != ~s2) |
| 5265 | 2776 | { |
| 5266 | SET_ZERO_FLAG( | |
| 2777 | SET_ZERO_FLAG(i | |
| 5267 | 2778 | } |
| 5268 | 2779 | } |
| 5269 | } | |
| 2780 | }//sign | |
| 5270 | 2781 | else |
| 5271 | 2782 | { |
| 2783 | vce = 0; | |
| 5272 | 2784 | if (s2 < 0) |
| 5273 | 2785 | { |
| 5274 | SET_COMPARE_FLAG( | |
| 2786 | SET_COMPARE_FLAG(i | |
| 5275 | 2787 | } |
| 5276 | 2788 | if (s1 - s2 >= 0) |
| 5277 | 2789 | { |
| 5278 | rsp->flag[1] |= (0x100 << del); | |
| 5279 | vres[del] = s2; | |
| 2790 | rsp->flag[1] |= (1 << (8+i)); | |
| 2791 | vres[i] = s2; | |
| 5280 | 2792 | } |
| 5281 | 2793 | else |
| 5282 | 2794 | { |
| 5283 | vres[ | |
| 2795 | vres[i | |
| 5284 | 2796 | } |
| 5285 | 2797 | |
| 5286 | 2798 | if ((s1 - s2) != 0) |
| 5287 | 2799 | { |
| 5288 | 2800 | if (s1 != ~s2) |
| 5289 | 2801 | { |
| 5290 | SET_ZERO_FLAG( | |
| 2802 | SET_ZERO_FLAG(i | |
| 5291 | 2803 | } |
| 5292 | 2804 | } |
| 5293 | 2805 | } |
| 5294 | ||
| 5295 | W_ACCUM_L(del, vres[del]); | |
| 2806 | rsp->flag[2] |= (vce << (i)); | |
| 2807 | ACCUM_L(i) = vres[i]; | |
| 5296 | 2808 | } |
| 5297 | 2809 | WRITEBACK_RESULT(); |
| 5298 | 2810 | } |
| r9854 | r9855 | |
| 5310 | 2822 | // |
| 5311 | 2823 | // Vector clip reverse |
| 5312 | 2824 | |
| 2825 | int sel; | |
| 2826 | INT16 s1, s2; | |
| 5313 | 2827 | rsp->flag[0] = 0; |
| 5314 | 2828 | rsp->flag[1] = 0; |
| 5315 | 2829 | rsp->flag[2] = 0; |
| 5316 | 2830 | |
| 5317 | 2831 | for (i=0; i < 8; i++) |
| 5318 | 2832 | { |
| 5319 | int del = VEC_EL_1(EL, i); | |
| 5320 | int sel = VEC_EL_2(EL, del); | |
| 5321 | INT16 s1 = R_VREG_S(VS1REG, del); | |
| 5322 | INT16 s2 = R_VREG_S(VS2REG, sel); | |
| 2833 | sel = VEC_EL_2(EL, i); | |
| 2834 | s1 = VREG_S(VS1REG, i); | |
| 2835 | s2 = VREG_S(VS2REG, sel); | |
| 5323 | 2836 | |
| 5324 | 2837 | if ((INT16)(s1 ^ s2) < 0) |
| 5325 | 2838 | { |
| 5326 | 2839 | if (s2 < 0) |
| 5327 | 2840 | { |
| 5328 | rsp->flag[1] |= ( | |
| 2841 | rsp->flag[1] |= ( | |
| 5329 | 2842 | } |
| 5330 | 2843 | if ((s1 + s2) <= 0) |
| 5331 | 2844 | { |
| 5332 | W_ACCUM_L(del, ~((UINT16)s2)); | |
| 5333 | SET_COMPARE_FLAG(del); | |
| 2845 | ACCUM_L(i) = ~((UINT16)s2); | |
| 2846 | SET_COMPARE_FLAG(i); | |
| 5334 | 2847 | } |
| 5335 | 2848 | else |
| 5336 | 2849 | { |
| 5337 | | |
| 2850 | | |
| 5338 | 2851 | } |
| 5339 | 2852 | } |
| 5340 | 2853 | else |
| 5341 | 2854 | { |
| 5342 | 2855 | if (s2 < 0) |
| 5343 | 2856 | { |
| 5344 | SET_COMPARE_FLAG( | |
| 2857 | SET_COMPARE_FLAG(i | |
| 5345 | 2858 | } |
| 5346 | 2859 | if ((s1 - s2) >= 0) |
| 5347 | 2860 | { |
| 5348 | W_ACCUM_L(del, s2); | |
| 5349 | rsp->flag[1] |= (0x100 << del); | |
| 2861 | ACCUM_L(i) = s2; | |
| 2862 | rsp->flag[1] |= (1 << (8+i)); | |
| 5350 | 2863 | } |
| 5351 | 2864 | else |
| 5352 | 2865 | { |
| 5353 | | |
| 2866 | | |
| 5354 | 2867 | } |
| 5355 | 2868 | } |
| 5356 | 2869 | |
| 5357 | vres[ | |
| 2870 | vres[i | |
| 5358 | 2871 | } |
| 5359 | 2872 | WRITEBACK_RESULT(); |
| 5360 | 2873 | } |
| 5361 | 2874 | |
| 5362 | #define RSP_VMRG(E10, E11, E12, E13, E14, E15, E16, E17, E20, E21, E22, E23, E24, E25, E26, E27) \ | |
| 5363 | if (COMPARE_FLAG(E10)) \ | |
| 5364 | { \ | |
| 5365 | vres[E10] = R_VREG_S(VS1REG, E10); \ | |
| 5366 | } \ | |
| 5367 | else \ | |
| 5368 | { \ | |
| 5369 | vres[E10] = R_VREG_S(VS2REG, E20); \ | |
| 5370 | } \ | |
| 5371 | if (COMPARE_FLAG(E11)) \ | |
| 5372 | { \ | |
| 5373 | vres[E11] = R_VREG_S(VS1REG, E11); \ | |
| 5374 | } \ | |
| 5375 | else \ | |
| 5376 | { \ | |
| 5377 | vres[E11] = R_VREG_S(VS2REG, E21); \ | |
| 5378 | } \ | |
| 5379 | if (COMPARE_FLAG(E12)) \ | |
| 5380 | { \ | |
| 5381 | vres[E12] = R_VREG_S(VS1REG, E12); \ | |
| 5382 | } \ | |
| 5383 | else \ | |
| 5384 | { \ | |
| 5385 | vres[E12] = R_VREG_S(VS2REG, E22); \ | |
| 5386 | } \ | |
| 5387 | if (COMPARE_FLAG(E13)) \ | |
| 5388 | { \ | |
| 5389 | vres[E13] = R_VREG_S(VS1REG, E13); \ | |
| 5390 | } \ | |
| 5391 | else \ | |
| 5392 | { \ | |
| 5393 | vres[E13] = R_VREG_S(VS2REG, E23); \ | |
| 5394 | } \ | |
| 5395 | if (COMPARE_FLAG(E14)) \ | |
| 5396 | { \ | |
| 5397 | vres[E14] = R_VREG_S(VS1REG, E14); \ | |
| 5398 | } \ | |
| 5399 | else \ | |
| 5400 | { \ | |
| 5401 | vres[E14] = R_VREG_S(VS2REG, E24); \ | |
| 5402 | } \ | |
| 5403 | if (COMPARE_FLAG(E15)) \ | |
| 5404 | { \ | |
| 5405 | vres[E15] = R_VREG_S(VS1REG, E15); \ | |
| 5406 | } \ | |
| 5407 | else \ | |
| 5408 | { \ | |
| 5409 | vres[E15] = R_VREG_S(VS2REG, E25); \ | |
| 5410 | } \ | |
| 5411 | if (COMPARE_FLAG(E16)) \ | |
| 5412 | { \ | |
| 5413 | vres[E16] = R_VREG_S(VS1REG, E16); \ | |
| 5414 | } \ | |
| 5415 | else \ | |
| 5416 | { \ | |
| 5417 | vres[E16] = R_VREG_S(VS2REG, E26); \ | |
| 5418 | } \ | |
| 5419 | if (COMPARE_FLAG(E17)) \ | |
| 5420 | { \ | |
| 5421 | vres[E17] = R_VREG_S(VS1REG, E17); \ | |
| 5422 | } \ | |
| 5423 | else \ | |
| 5424 | { \ | |
| 5425 | vres[E17] = R_VREG_S(VS2REG, E27); \ | |
| 5426 | } \ | |
| 5427 | W_ACCUM_L(E10, vres[E10]); \ | |
| 5428 | W_ACCUM_L(E11, vres[E11]); \ | |
| 5429 | W_ACCUM_L(E12, vres[E12]); \ | |
| 5430 | W_ACCUM_L(E13, vres[E13]); \ | |
| 5431 | W_ACCUM_L(E14, vres[E14]); \ | |
| 5432 | W_ACCUM_L(E15, vres[E15]); \ | |
| 5433 | W_ACCUM_L(E16, vres[E16]); \ | |
| 5434 | W_ACCUM_L(E17, vres[E17]); \ | |
| 5435 | ||
| 5436 | 2875 | INLINE void cfunc_rsp_vmrg(void *param) |
| 5437 | 2876 | { |
| 5438 | 2877 | rsp_state *rsp = (rsp_state*)param; |
| r9854 | r9855 | |
| 5445 | 2884 | // |
| 5446 | 2885 | // Merges two vectors according to compare flags |
| 5447 | 2886 | |
| 5448 | switch(EL) | |
| 2887 | int sel; | |
| 2888 | for (int i = 0; i < 8; i++) | |
| 5449 | 2889 | { |
| 5450 | case 0: /* 0, 1, 2, 3, 4, 5, 6, 7 - none */ /* 0, 1, 2, 3, 4, 5, 6, 7 - none */ | |
| 5451 | RSP_VMRG(0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7); | |
| 5452 | break; | |
| 5453 | case 1: /* 0, 1, 2, 3, 4, 5, 6, 7 - ??? */ /* 0, 1, 2, 3, 4, 5, 6, 7 - ??? */ | |
| 5454 | RSP_VMRG(0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7); | |
| 5455 | break; | |
| 5456 | case 2: /* 1, 3, 5, 7, 0, 2, 4, 6 - 0q */ /* 0, 0, 2, 2, 4, 4, 6, 6 - 0q */ | |
| 5457 | RSP_VMRG(1, 3, 5, 7, 0, 2, 4, 6, 0, 2, 4, 6, 0, 2, 4, 6); | |
| 5458 | break; | |
| 5459 | case 3: /* 0, 2, 4, 6, 1, 3, 5, 7 - 1q */ /* 1, 1, 3, 3, 5, 5, 7, 7 - 1q */ | |
| 5460 | RSP_VMRG(0, 2, 4, 6, 1, 3, 5, 7, 1, 3, 5, 7, 1, 3, 5, 7); | |
| 5461 | break; | |
| 5462 | case 4: /* 1, 2, 3, 5, 6, 7, 0, 4 - 0h */ /* 0, 0, 0, 0, 4, 4, 4, 4 - 0h */ | |
| 5463 | RSP_VMRG(1, 2, 3, 5, 6, 7, 0, 4, 0, 0, 0, 4, 4, 4, 0, 4); | |
| 5464 | break; | |
| 5465 | case 5: /* 0, 2, 3, 4, 6, 7, 1, 5 - 1h */ /* 1, 1, 1, 1, 5, 5, 5, 5 - 1h */ | |
| 5466 | RSP_VMRG(0, 2, 3, 4, 6, 7, 1, 5, 1, 1, 1, 5, 5, 5, 1, 5); | |
| 5467 | break; | |
| 5468 | case 6: /* 0, 1, 3, 4, 5, 7, 2, 6 - 2h */ /* 2, 2, 2, 2, 6, 6, 6, 6 - 2h */ | |
| 5469 | RSP_VMRG(0, 1, 3, 4, 5, 7, 2, 6, 2, 2, 2, 6, 6, 6, 2, 6); | |
| 5470 | break; | |
| 5471 | case 7: /* 0, 1, 2, 4, 5, 6, 3, 7 - 3h */ /* 3, 3, 3, 3, 7, 7, 7, 7 - 3h */ | |
| 5472 | RSP_VMRG(0, 1, 2, 4, 5, 6, 3, 7, 3, 3, 3, 7, 7, 7, 3, 7); | |
| 5473 | break; | |
| 5474 | case 8: /* 1, 2, 3, 4, 5, 6, 7, 0 - 0 */ /* 0, 0, 0, 0, 0, 0, 0, 0 - 0 */ | |
| 5475 | RSP_VMRG(1, 2, 3, 4, 5, 6, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0); | |
| 5476 | break; | |
| 5477 | case 9: /* 0, 2, 3, 4, 5, 6, 7, 1 - 1 */ /* 1, 1, 1, 1, 1, 1, 1, 1 - 0 */ | |
| 5478 | RSP_VMRG(0, 2, 3, 4, 5, 6, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1); | |
| 5479 | break; | |
| 5480 | case 10:/* 0, 1, 3, 4, 5, 6, 7, 2 - 2 */ /* 2, 2, 2, 2, 2, 2, 2, 2 - 0 */ | |
| 5481 | RSP_VMRG(0, 1, 3, 4, 5, 6, 7, 2, 2, 2, 2, 2, 2, 2, 2, 2); | |
| 5482 | break; | |
| 5483 | case 11:/* 0, 1, 2, 4, 5, 6, 7, 3 - 3 */ /* 3, 3, 3, 3, 3, 3, 3, 3 - 0 */ | |
| 5484 | RSP_VMRG(0, 1, 2, 4, 5, 6, 7, 3, 3, 3, 3, 3, 3, 3, 3, 3); | |
| 5485 | break; | |
| 5486 | case 12:/* 0, 1, 2, 3, 5, 6, 7, 4 - 4 */ /* 4, 4, 4, 4, 4, 4, 4, 4 - 0 */ | |
| 5487 | RSP_VMRG(0, 1, 2, 3, 5, 6, 7, 4, 4, 4, 4, 4, 4, 4, 4, 4); | |
| 5488 | break; | |
| 5489 | case 13:/* 0, 1, 2, 3, 4, 6, 7, 5 - 5 */ /* 5, 5, 5, 5, 5, 5, 5, 5 - 0 */ | |
| 5490 | RSP_VMRG(0, 1, 2, 3, 4, 6, 7, 5, 5, 5, 5, 5, 5, 5, 5, 5); | |
| 5491 | break; | |
| 5492 | case 14:/* 0, 1, 2, 3, 4, 5, 7, 6 - 6 */ /* 6, 6, 6, 6, 6, 6, 6, 6 - 0 */ | |
| 5493 | RSP_VMRG(0, 1, 2, 3, 4, 5, 7, 6, 6, 6, 6, 6, 6, 6, 6, 6); | |
| 5494 | break; | |
| 5495 | case 15:/* 0, 1, 2, 3, 4, 5, 6, 7 - 7 */ /* 7, 7, 7, 7, 7, 7, 7, 7 - 0 */ | |
| 5496 | RSP_VMRG(0, 1, 2, 3, 4, 5, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7); | |
| 5497 | break; | |
| 2890 | sel = VEC_EL_2(EL, i); | |
| 2891 | if (COMPARE_FLAG(i) != 0) | |
| 2892 | { | |
| 2893 | vres[i] = VREG_S(VS1REG, i); | |
| 2894 | } | |
| 2895 | else | |
| 2896 | { | |
| 2897 | vres[i] = VREG_S(VS2REG, sel);//ìî¸ èñïðàâëåíèå | |
| 2898 | } | |
| 2899 | ||
| 2900 | ACCUM_L(i) = vres[i]; | |
| 5498 | 2901 | } |
| 5499 | 2902 | WRITEBACK_RESULT(); |
| 5500 | 2903 | } |
| 5501 | 2904 | |
| 5502 | #if (DRC_VAND) | |
| 5503 | #define RSP_VAND_DRC(E10, E11, E12, E13, E14, E15, E16, E17, E20, E21, E22, E23, E24, E25, E26, E27, I0, I1, I2, I3, I4, I5, I6, I7) \ | |
| 5504 | { \ | |
| 5505 | UML_SEXT(block, IREG(0), VS(VS1REG, I0), WORD); \ | |
| 5506 | UML_SEXT(block, IREG(1), VS(VS2REG, E20), WORD); \ | |
| 5507 | UML_AND(block, IREG(0), IREG(0), IREG(1)); \ | |
| 5508 | UML_STORE(block, &rsp->accum[E10].h.low, IMM(0), IREG(0), WORD); \ | |
| 5509 | \ | |
| 5510 | UML_SEXT(block, IREG(0), VS(VS1REG, I1), WORD); \ | |
| 5511 | UML_SEXT(block, IREG(1), VS(VS2REG, E21), WORD); \ | |
| 5512 | UML_AND(block, IREG(0), IREG(0), IREG(1)); \ | |
| 5513 | UML_STORE(block, &rsp->accum[E11].h.low, IMM(0), IREG(0), WORD); \ | |
| 5514 | \ | |
| 5515 | UML_SEXT(block, IREG(0), VS(VS1REG, I2), WORD); \ | |
| 5516 | UML_SEXT(block, IREG(1), VS(VS2REG, E22), WORD); \ | |
| 5517 | UML_AND(block, IREG(0), IREG(0), IREG(1)); \ | |
| 5518 | UML_STORE(block, &rsp->accum[E12].h.low, IMM(0), IREG(0), WORD); \ | |
| 5519 | \ | |
| 5520 | UML_SEXT(block, IREG(0), VS(VS1REG, I3), WORD); \ | |
| 5521 | UML_SEXT(block, IREG(1), VS(VS2REG, E23), WORD); \ | |
| 5522 | UML_AND(block, IREG(0), IREG(0), IREG(1)); \ | |
| 5523 | UML_STORE(block, &rsp->accum[E13].h.low, IMM(0), IREG(0), WORD); \ | |
| 5524 | \ | |
| 5525 | UML_SEXT(block, IREG(0), VS(VS1REG, I4), WORD); \ | |
| 5526 | UML_SEXT(block, IREG(1), VS(VS2REG, E24), WORD); \ | |
| 5527 | UML_AND(block, IREG(0), IREG(0), IREG(1)); \ | |
| 5528 | UML_STORE(block, &rsp->accum[E14].h.low, IMM(0), IREG(0), WORD); \ | |
| 5529 | \ | |
| 5530 | UML_SEXT(block, IREG(0), VS(VS1REG, I5), WORD); \ | |
| 5531 | UML_SEXT(block, IREG(1), VS(VS2REG, E25), WORD); \ | |
| 5532 | UML_AND(block, IREG(0), IREG(0), IREG(1)); \ | |
| 5533 | UML_STORE(block, &rsp->accum[E15].h.low, IMM(0), IREG(0), WORD); \ | |
| 5534 | \ | |
| 5535 | UML_SEXT(block, IREG(0), VS(VS1REG, I6), WORD); \ | |
| 5536 | UML_SEXT(block, IREG(1), VS(VS2REG, E26), WORD); \ | |
| 5537 | UML_AND(block, IREG(0), IREG(0), IREG(1)); \ | |
| 5538 | UML_STORE(block, &rsp->accum[E16].h.low, IMM(0), IREG(0), WORD); \ | |
| 5539 | \ | |
| 5540 | UML_SEXT(block, IREG(0), VS(VS1REG, I7), WORD); \ | |
| 5541 | UML_SEXT(block, IREG(1), VS(VS2REG, E27), WORD); \ | |
| 5542 | UML_AND(block, IREG(0), IREG(0), IREG(1)); \ | |
| 5543 | UML_STORE(block, &rsp->accum[E17].h.low, IMM(0), IREG(0), WORD); \ | |
| 5544 | \ | |
| 5545 | UML_LOAD(block, IREG(0), &rsp->accum[E10].h.low, IMM(0), WORD); \ | |
| 5546 | UML_STORE(block, &rsp->v[VDREG].s[I0], IMM(0), IREG(0), WORD); \ | |
| 5547 | UML_LOAD(block, IREG(0), &rsp->accum[E11].h.low, IMM(0), WORD); \ | |
| 5548 | UML_STORE(block, &rsp->v[VDREG].s[I1], IMM(0), IREG(0), WORD); \ | |
| 5549 | UML_LOAD(block, IREG(0), &rsp->accum[E12].h.low, IMM(0), WORD); \ | |
| 5550 | UML_STORE(block, &rsp->v[VDREG].s[I2], IMM(0), IREG(0), WORD); \ | |
| 5551 | UML_LOAD(block, IREG(0), &rsp->accum[E13].h.low, IMM(0), WORD); \ | |
| 5552 | UML_STORE(block, &rsp->v[VDREG].s[I3], IMM(0), IREG(0), WORD); \ | |
| 5553 | UML_LOAD(block, IREG(0), &rsp->accum[E14].h.low, IMM(0), WORD); \ | |
| 5554 | UML_STORE(block, &rsp->v[VDREG].s[I4], IMM(0), IREG(0), WORD); \ | |
| 5555 | UML_LOAD(block, IREG(0), &rsp->accum[E15].h.low, IMM(0), WORD); \ | |
| 5556 | UML_STORE(block, &rsp->v[VDREG].s[I5], IMM(0), IREG(0), WORD); \ | |
| 5557 | UML_LOAD(block, IREG(0), &rsp->accum[E16].h.low, IMM(0), WORD); \ | |
| 5558 | UML_STORE(block, &rsp->v[VDREG].s[I6], IMM(0), IREG(0), WORD); \ | |
| 5559 | UML_LOAD(block, IREG(0), &rsp->accum[E17].h.low, IMM(0), WORD); \ | |
| 5560 | UML_STORE(block, &rsp->v[VDREG].s[I7], IMM(0), IREG(0), WORD); \ | |
| 5561 | } | |
| 5562 | ||
| 5563 | static int generate_vand(rsp_state *rsp, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) | |
| 5564 | { | |
| 5565 | UINT32 op = desc->opptr.l[0]; | |
| 5566 | ||
| 5567 | // 31 25 24 20 15 10 5 0 | |
| 5568 | // ------------------------------------------------------ | |
| 5569 | // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 101000 | | |
| 5570 | // ------------------------------------------------------ | |
| 5571 | // | |
| 5572 | // Bitwise AND of two vector registers | |
| 5573 | ||
| 5574 | switch(EL) | |
| 5575 | { | |
| 5576 | case 0: /* 0, 1, 2, 3, 4, 5, 6, 7 - none */ /* 0, 1, 2, 3, 4, 5, 6, 7 - none */ | |
| 5577 | RSP_VAND_DRC(0, 1, 2, 3, 4, 5, 6, 7, 7, 6, 5, 4, 3, 2, 1, 0, 7, 6, 5, 4, 3, 2, 1, 0); | |
| 5578 | return TRUE; | |
| 5579 | case 1: /* 0, 1, 2, 3, 4, 5, 6, 7 - ??? */ /* 0, 1, 2, 3, 4, 5, 6, 7 - ??? */ | |
| 5580 | RSP_VAND_DRC(0, 1, 2, 3, 4, 5, 6, 7, 7, 6, 5, 4, 3, 2, 1, 0, 7, 6, 5, 4, 3, 2, 1, 0); | |
| 5581 | return TRUE; | |
| 5582 | case 2: /* 1, 3, 5, 7, 0, 2, 4, 6 - 0q */ /* 0, 0, 2, 2, 4, 4, 6, 6 - 0q */ | |
| 5583 | RSP_VAND_DRC(1, 3, 5, 7, 0, 2, 4, 6, 7, 5, 3, 1, 7, 5, 3, 1, 6, 4, 2, 0, 7, 5, 3, 1); | |
| 5584 | return TRUE; | |
| 5585 | case 3: /* 0, 2, 4, 6, 1, 3, 5, 7 - 1q */ /* 1, 1, 3, 3, 5, 5, 7, 7 - 1q */ | |
| 5586 | RSP_VAND_DRC(0, 2, 4, 6, 1, 3, 5, 7, 6, 4, 2, 0, 6, 4, 2, 0, 7, 5, 3, 1, 6, 4, 2, 0); | |
| 5587 | return TRUE; | |
| 5588 | case 4: /* 1, 2, 3, 5, 6, 7, 0, 4 - 0h */ /* 0, 0, 0, 0, 4, 4, 4, 4 - 0h */ | |
| 5589 | RSP_VAND_DRC(1, 2, 3, 5, 6, 7, 0, 4, 7, 7, 7, 3, 3, 3, 7, 3, 6, 5, 4, 2, 1, 0, 7, 3); | |
| 5590 | return TRUE; | |
| 5591 | case 5: /* 0, 2, 3, 4, 6, 7, 1, 5 - 1h */ /* 1, 1, 1, 1, 5, 5, 5, 5 - 1h */ | |
| 5592 | RSP_VAND_DRC(0, 2, 3, 4, 6, 7, 1, 5, 6, 6, 6, 2, 2, 2, 6, 2, 7, 5, 4, 3, 1, 0, 6, 2); | |
| 5593 | return TRUE; | |
| 5594 | case 6: /* 0, 1, 3, 4, 5, 7, 2, 6 - 2h */ /* 2, 2, 2, 2, 6, 6, 6, 6 - 2h */ | |
| 5595 | RSP_VAND_DRC(0, 1, 3, 4, 5, 7, 2, 6, 5, 5, 5, 1, 1, 1, 5, 1, 7, 6, 4, 3, 2, 0, 5, 1); | |
| 5596 | return TRUE; | |
| 5597 | case 7: /* 0, 1, 2, 4, 5, 6, 3, 7 - 3h */ /* 3, 3, 3, 3, 7, 7, 7, 7 - 3h */ | |
| 5598 | RSP_VAND_DRC(0, 1, 2, 4, 5, 6, 3, 7, 4, 4, 4, 0, 0, 0, 4, 0, 7, 6, 5, 3, 2, 1, 4, 0); | |
| 5599 | return TRUE; | |
| 5600 | case 8: /* 1, 2, 3, 4, 5, 6, 7, 0 - 0 */ /* 0, 0, 0, 0, 0, 0, 0, 0 - 0 */ | |
| 5601 | RSP_VAND_DRC(1, 2, 3, 4, 5, 6, 7, 0, 7, 7, 7, 7, 7, 7, 7, 7, 6, 5, 4, 3, 2, 1, 0, 7); | |
| 5602 | return TRUE; | |
| 5603 | case 9: /* 0, 2, 3, 4, 5, 6, 7, 1 - 1 */ /* 1, 1, 1, 1, 1, 1, 1, 1 - 0 */ | |
| 5604 | RSP_VAND_DRC(0, 2, 3, 4, 5, 6, 7, 1, 6, 6, 6, 6, 6, 6, 6, 6, 7, 5, 4, 3, 2, 1, 0, 6); | |
| 5605 | return TRUE; | |
| 5606 | case 10: /* 0, 1, 3, 4, 5, 6, 7, 2 - 2 */ /* 2, 2, 2, 2, 2, 2, 2, 2 - 0 */ | |
| 5607 | RSP_VAND_DRC(0, 1, 3, 4, 5, 6, 7, 2, 5, 5, 5, 5, 5, 5, 5, 5, 7, 6, 4, 3, 2, 1, 0, 5); | |
| 5608 | return TRUE; | |
| 5609 | case 11: /* 0, 1, 2, 4, 5, 6, 7, 3 - 3 */ /* 3, 3, 3, 3, 3, 3, 3, 3 - 0 */ | |
| 5610 | RSP_VAND_DRC(0, 1, 2, 4, 5, 6, 7, 3, 4, 4, 4, 4, 4, 4, 4, 4, 7, 6, 5, 3, 2, 1, 0, 4); | |
| 5611 | return TRUE; | |
| 5612 | case 12: /* 0, 1, 2, 3, 5, 6, 7, 4 - 4 */ /* 4, 4, 4, 4, 4, 4, 4, 4 - 0 */ | |
| 5613 | RSP_VAND_DRC(0, 1, 2, 3, 5, 6, 7, 4, 3, 3, 3, 3, 3, 3, 3, 3, 7, 6, 5, 4, 2, 1, 0, 3); | |
| 5614 | return TRUE; | |
| 5615 | case 13: /* 0, 1, 2, 3, 4, 6, 7, 5 - 5 */ /* 5, 5, 5, 5, 5, 5, 5, 5 - 0 */ | |
| 5616 | RSP_VAND_DRC(0, 1, 2, 3, 4, 6, 7, 5, 2, 2, 2, 2, 2, 2, 2, 2, 7, 6, 5, 4, 3, 1, 0, 2); | |
| 5617 | return TRUE; | |
| 5618 | case 14: /* 0, 1, 2, 3, 4, 5, 7, 6 - 6 */ /* 6, 6, 6, 6, 6, 6, 6, 6 - 0 */ | |
| 5619 | RSP_VAND_DRC(0, 1, 2, 3, 4, 5, 7, 6, 1, 1, 1, 1, 1, 1, 1, 1, 7, 6, 5, 4, 3, 2, 0, 1); | |
| 5620 | return TRUE; | |
| 5621 | case 15: /* 0, 1, 2, 3, 4, 5, 6, 7 - 7 */ /* 7, 7, 7, 7, 7, 7, 7, 7 - 0 */ | |
| 5622 | RSP_VAND_DRC(0, 1, 2, 3, 4, 5, 6, 7, 0, 0, 0, 0, 0, 0, 0, 0, 7, 6, 5, 4, 3, 2, 1, 0); | |
| 5623 | return TRUE; | |
| 5624 | } | |
| 5625 | ||
| 5626 | return TRUE; | |
| 5627 | } | |
| 5628 | #else | |
| 5629 | #define RSP_VAND(E10, E11, E12, E13, E14, E15, E16, E17, E20, E21, E22, E23, E24, E25, E26, E27) \ | |
| 5630 | vres[E10] = R_VREG_S(VS1REG, E10) & R_VREG_S(VS2REG, E20); \ | |
| 5631 | vres[E11] = R_VREG_S(VS1REG, E11) & R_VREG_S(VS2REG, E21); \ | |
| 5632 | vres[E12] = R_VREG_S(VS1REG, E12) & R_VREG_S(VS2REG, E22); \ | |
| 5633 | vres[E13] = R_VREG_S(VS1REG, E13) & R_VREG_S(VS2REG, E23); \ | |
| 5634 | vres[E14] = R_VREG_S(VS1REG, E14) & R_VREG_S(VS2REG, E24); \ | |
| 5635 | vres[E15] = R_VREG_S(VS1REG, E15) & R_VREG_S(VS2REG, E25); \ | |
| 5636 | vres[E16] = R_VREG_S(VS1REG, E16) & R_VREG_S(VS2REG, E26); \ | |
| 5637 | vres[E17] = R_VREG_S(VS1REG, E17) & R_VREG_S(VS2REG, E27); \ | |
| 5638 | W_ACCUM_L(E10, vres[E10]); \ | |
| 5639 | W_ACCUM_L(E11, vres[E11]); \ | |
| 5640 | W_ACCUM_L(E12, vres[E12]); \ | |
| 5641 | W_ACCUM_L(E13, vres[E13]); \ | |
| 5642 | W_ACCUM_L(E14, vres[E14]); \ | |
| 5643 | W_ACCUM_L(E15, vres[E15]); \ | |
| 5644 | W_ACCUM_L(E16, vres[E16]); \ | |
| 5645 | W_ACCUM_L(E17, vres[E17]); \ | |
| 5646 | ||
| 5647 | 2905 | INLINE void cfunc_rsp_vand(void *param) |
| 5648 | 2906 | { |
| 5649 | 2907 | rsp_state *rsp = (rsp_state*)param; |
| r9854 | r9855 | |
| 5656 | 2914 | // |
| 5657 | 2915 | // Bitwise AND of two vector registers |
| 5658 | 2916 | |
| 5659 | switch(EL) | |
| 2917 | int sel; | |
| 2918 | for (int i = 0; i < 8; i++) | |
| 5660 | 2919 | { |
| 5661 | case 0: /* 0, 1, 2, 3, 4, 5, 6, 7 - none */ /* 0, 1, 2, 3, 4, 5, 6, 7 - none */ | |
| 5662 | RSP_VAND(0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7); | |
| 5663 | break; | |
| 5664 | case 1: /* 0, 1, 2, 3, 4, 5, 6, 7 - ??? */ /* 0, 1, 2, 3, 4, 5, 6, 7 - ??? */ | |
| 5665 | RSP_VAND(0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7); | |
| 5666 | break; | |
| 5667 | case 2: /* 1, 3, 5, 7, 0, 2, 4, 6 - 0q */ /* 0, 0, 2, 2, 4, 4, 6, 6 - 0q */ | |
| 5668 | RSP_VAND(1, 3, 5, 7, 0, 2, 4, 6, 0, 2, 4, 6, 0, 2, 4, 6); | |
| 5669 | break; | |
| 5670 | case 3: /* 0, 2, 4, 6, 1, 3, 5, 7 - 1q */ /* 1, 1, 3, 3, 5, 5, 7, 7 - 1q */ | |
| 5671 | RSP_VAND(0, 2, 4, 6, 1, 3, 5, 7, 1, 3, 5, 7, 1, 3, 5, 7); | |
| 5672 | break; | |
| 5673 | case 4: /* 1, 2, 3, 5, 6, 7, 0, 4 - 0h */ /* 0, 0, 0, 0, 4, 4, 4, 4 - 0h */ | |
| 5674 | RSP_VAND(1, 2, 3, 5, 6, 7, 0, 4, 0, 0, 0, 4, 4, 4, 0, 4); | |
| 5675 | break; | |
| 5676 | case 5: /* 0, 2, 3, 4, 6, 7, 1, 5 - 1h */ /* 1, 1, 1, 1, 5, 5, 5, 5 - 1h */ | |
| 5677 | RSP_VAND(0, 2, 3, 4, 6, 7, 1, 5, 1, 1, 1, 5, 5, 5, 1, 5); | |
| 5678 | break; | |
| 5679 | case 6: /* 0, 1, 3, 4, 5, 7, 2, 6 - 2h */ /* 2, 2, 2, 2, 6, 6, 6, 6 - 2h */ | |
| 5680 | RSP_VAND(0, 1, 3, 4, 5, 7, 2, 6, 2, 2, 2, 6, 6, 6, 2, 6); | |
| 5681 | break; | |
| 5682 | case 7: /* 0, 1, 2, 4, 5, 6, 3, 7 - 3h */ /* 3, 3, 3, 3, 7, 7, 7, 7 - 3h */ | |
| 5683 | RSP_VAND(0, 1, 2, 4, 5, 6, 3, 7, 3, 3, 3, 7, 7, 7, 3, 7); | |
| 5684 | break; | |
| 5685 | case 8: /* 1, 2, 3, 4, 5, 6, 7, 0 - 0 */ /* 0, 0, 0, 0, 0, 0, 0, 0 - 0 */ | |
| 5686 | RSP_VAND(1, 2, 3, 4, 5, 6, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0); | |
| 5687 | break; | |
| 5688 | case 9: /* 0, 2, 3, 4, 5, 6, 7, 1 - 1 */ /* 1, 1, 1, 1, 1, 1, 1, 1 - 0 */ | |
| 5689 | RSP_VAND(0, 2, 3, 4, 5, 6, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1); | |
| 5690 | break; | |
| 5691 | case 10:/* 0, 1, 3, 4, 5, 6, 7, 2 - 2 */ /* 2, 2, 2, 2, 2, 2, 2, 2 - 0 */ | |
| 5692 | RSP_VAND(0, 1, 3, 4, 5, 6, 7, 2, 2, 2, 2, 2, 2, 2, 2, 2); | |
| 5693 | break; | |
| 5694 | case 11:/* 0, 1, 2, 4, 5, 6, 7, 3 - 3 */ /* 3, 3, 3, 3, 3, 3, 3, 3 - 0 */ | |
| 5695 | RSP_VAND(0, 1, 2, 4, 5, 6, 7, 3, 3, 3, 3, 3, 3, 3, 3, 3); | |
| 5696 | break; | |
| 5697 | case 12:/* 0, 1, 2, 3, 5, 6, 7, 4 - 4 */ /* 4, 4, 4, 4, 4, 4, 4, 4 - 0 */ | |
| 5698 | RSP_VAND(0, 1, 2, 3, 5, 6, 7, 4, 4, 4, 4, 4, 4, 4, 4, 4); | |
| 5699 | break; | |
| 5700 | case 13:/* 0, 1, 2, 3, 4, 6, 7, 5 - 5 */ /* 5, 5, 5, 5, 5, 5, 5, 5 - 0 */ | |
| 5701 | RSP_VAND(0, 1, 2, 3, 4, 6, 7, 5, 5, 5, 5, 5, 5, 5, 5, 5); | |
| 5702 | break; | |
| 5703 | case 14:/* 0, 1, 2, 3, 4, 5, 7, 6 - 6 */ /* 6, 6, 6, 6, 6, 6, 6, 6 - 0 */ | |
| 5704 | RSP_VAND(0, 1, 2, 3, 4, 5, 7, 6, 6, 6, 6, 6, 6, 6, 6, 6); | |
| 5705 | break; | |
| 5706 | case 15:/* 0, 1, 2, 3, 4, 5, 6, 7 - 7 */ /* 7, 7, 7, 7, 7, 7, 7, 7 - 0 */ | |
| 5707 | RSP_VAND(0, 1, 2, 3, 4, 5, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7); | |
| 5708 | break; | |
| 2920 | sel = VEC_EL_2(EL, i); | |
| 2921 | vres[i] = VREG_S(VS1REG, i) & VREG_S(VS2REG, sel); | |
| 2922 | ACCUM_L(i) = vres[i]; | |
| 5709 | 2923 | } |
| 5710 | 2924 | WRITEBACK_RESULT(); |
| 5711 | 2925 | } |
| 5712 | #endif | |
| 5713 | 2926 | |
| 5714 | #if (DRC_VNAND) | |
| 5715 | #define RSP_VNAND_DRC(E10, E11, E12, E13, E14, E15, E16, E17, E20, E21, E22, E23, E24, E25, E26, E27, I0, I1, I2, I3, I4, I5, I6, I7) \ | |
| 5716 | { \ | |
| 5717 | UML_SEXT(block, IREG(0), VS(VS1REG, I0), WORD); \ | |
| 5718 | UML_SEXT(block, IREG(1), VS(VS2REG, E20), WORD); \ | |
| 5719 | UML_AND(block, IREG(0), IREG(0), IREG(1)); \ | |
| 5720 | UML_XOR(block, IREG(0), IREG(0), IMM(0xffffffff)); \ | |
| 5721 | UML_STORE(block, &rsp->accum[E10].h.low, IMM(0), IREG(0), WORD); \ | |
| 5722 | \ | |
| 5723 | UML_SEXT(block, IREG(0), VS(VS1REG, I1), WORD); \ | |
| 5724 | UML_SEXT(block, IREG(1), VS(VS2REG, E21), WORD); \ | |
| 5725 | UML_AND(block, IREG(0), IREG(0), IREG(1)); \ | |
| 5726 | UML_XOR(block, IREG(0), IREG(0), IMM(0xffffffff)); \ | |
| 5727 | UML_STORE(block, &rsp->accum[E11].h.low, IMM(0), IREG(0), WORD); \ | |
| 5728 | \ | |
| 5729 | UML_SEXT(block, IREG(0), VS(VS1REG, I2), WORD); \ | |
| 5730 | UML_SEXT(block, IREG(1), VS(VS2REG, E22), WORD); \ | |
| 5731 | UML_AND(block, IREG(0), IREG(0), IREG(1)); \ | |
| 5732 | UML_XOR(block, IREG(0), IREG(0), IMM(0xffffffff)); \ | |
| 5733 | UML_STORE(block, &rsp->accum[E12].h.low, IMM(0), IREG(0), WORD); \ | |
| 5734 | \ | |
| 5735 | UML_SEXT(block, IREG(0), VS(VS1REG, I3), WORD); \ | |
| 5736 | UML_SEXT(block, IREG(1), VS(VS2REG, E23), WORD); \ | |
| 5737 | UML_AND(block, IREG(0), IREG(0), IREG(1)); \ | |
| 5738 | UML_XOR(block, IREG(0), IREG(0), IMM(0xffffffff)); \ | |
| 5739 | UML_STORE(block, &rsp->accum[E13].h.low, IMM(0), IREG(0), WORD); \ | |
| 5740 | \ | |
| 5741 | UML_SEXT(block, IREG(0), VS(VS1REG, I4), WORD); \ | |
| 5742 | UML_SEXT(block, IREG(1), VS(VS2REG, E24), WORD); \ | |
| 5743 | UML_AND(block, IREG(0), IREG(0), IREG(1)); \ | |
| 5744 | UML_XOR(block, IREG(0), IREG(0), IMM(0xffffffff)); \ | |
| 5745 | UML_STORE(block, &rsp->accum[E14].h.low, IMM(0), IREG(0), WORD); \ | |
| 5746 | \ | |
| 5747 | UML_SEXT(block, IREG(0), VS(VS1REG, I5), WORD); \ | |
| 5748 | UML_SEXT(block, IREG(1), VS(VS2REG, E25), WORD); \ | |
| 5749 | UML_AND(block, IREG(0), IREG(0), IREG(1)); \ | |
| 5750 | UML_XOR(block, IREG(0), IREG(0), IMM(0xffffffff)); \ | |
| 5751 | UML_STORE(block, &rsp->accum[E15].h.low, IMM(0), IREG(0), WORD); \ | |
| 5752 | \ | |
| 5753 | UML_SEXT(block, IREG(0), VS(VS1REG, I6), WORD); \ | |
| 5754 | UML_SEXT(block, IREG(1), VS(VS2REG, E26), WORD); \ | |
| 5755 | UML_AND(block, IREG(0), IREG(0), IREG(1)); \ | |
| 5756 | UML_XOR(block, IREG(0), IREG(0), IMM(0xffffffff)); \ | |
| 5757 | UML_STORE(block, &rsp->accum[E16].h.low, IMM(0), IREG(0), WORD); \ | |
| 5758 | \ | |
| 5759 | UML_SEXT(block, IREG(0), VS(VS1REG, I7), WORD); \ | |
| 5760 | UML_SEXT(block, IREG(1), VS(VS2REG, E27), WORD); \ | |
| 5761 | UML_AND(block, IREG(0), IREG(0), IREG(1)); \ | |
| 5762 | UML_XOR(block, IREG(0), IREG(0), IMM(0xffffffff)); \ | |
| 5763 | UML_STORE(block, &rsp->accum[E17].h.low, IMM(0), IREG(0), WORD); \ | |
| 5764 | \ | |
| 5765 | UML_LOAD(block, IREG(0), &rsp->accum[E10].h.low, IMM(0), WORD); \ | |
| 5766 | UML_STORE(block, &rsp->v[VDREG].s[I0], IMM(0), IREG(0), WORD); \ | |
| 5767 | UML_LOAD(block, IREG(0), &rsp->accum[E11].h.low, IMM(0), WORD); \ | |
| 5768 | UML_STORE(block, &rsp->v[VDREG].s[I1], IMM(0), IREG(0), WORD); \ | |
| 5769 | UML_LOAD(block, IREG(0), &rsp->accum[E12].h.low, IMM(0), WORD); \ | |
| 5770 | UML_STORE(block, &rsp->v[VDREG].s[I2], IMM(0), IREG(0), WORD); \ | |
| 5771 | UML_LOAD(block, IREG(0), &rsp->accum[E13].h.low, IMM(0), WORD); \ | |
| 5772 | UML_STORE(block, &rsp->v[VDREG].s[I3], IMM(0), IREG(0), WORD); \ | |
| 5773 | UML_LOAD(block, IREG(0), &rsp->accum[E14].h.low, IMM(0), WORD); \ | |
| 5774 | UML_STORE(block, &rsp->v[VDREG].s[I4], IMM(0), IREG(0), WORD); \ | |
| 5775 | UML_LOAD(block, IREG(0), &rsp->accum[E15].h.low, IMM(0), WORD); \ | |
| 5776 | UML_STORE(block, &rsp->v[VDREG].s[I5], IMM(0), IREG(0), WORD); \ | |
| 5777 | UML_LOAD(block, IREG(0), &rsp->accum[E16].h.low, IMM(0), WORD); \ | |
| 5778 | UML_STORE(block, &rsp->v[VDREG].s[I6], IMM(0), IREG(0), WORD); \ | |
| 5779 | UML_LOAD(block, IREG(0), &rsp->accum[E17].h.low, IMM(0), WORD); \ | |
| 5780 | UML_STORE(block, &rsp->v[VDREG].s[I7], IMM(0), IREG(0), WORD); \ | |
| 5781 | } | |
| 5782 | ||
| 5783 | static int generate_vnand(rsp_state *rsp, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) | |
| 5784 | { | |
| 5785 | UINT32 op = desc->opptr.l[0]; | |
| 5786 | ||
| 5787 | // 31 25 24 20 15 10 5 0 | |
| 5788 | // ------------------------------------------------------ | |
| 5789 | // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 101000 | | |
| 5790 | // ------------------------------------------------------ | |
| 5791 | // | |
| 5792 | // Bitwise NOT AND of two vector registers | |
| 5793 | ||
| 5794 | switch(EL) | |
| 5795 | { | |
| 5796 | case 0: /* 0, 1, 2, 3, 4, 5, 6, 7 - none */ /* 0, 1, 2, 3, 4, 5, 6, 7 - none */ | |
| 5797 | RSP_VNAND_DRC(0, 1, 2, 3, 4, 5, 6, 7, 7, 6, 5, 4, 3, 2, 1, 0, 7, 6, 5, 4, 3, 2, 1, 0); | |
| 5798 | return TRUE; | |
| 5799 | case 1: /* 0, 1, 2, 3, 4, 5, 6, 7 - ??? */ /* 0, 1, 2, 3, 4, 5, 6, 7 - ??? */ | |
| 5800 | RSP_VNAND_DRC(0, 1, 2, 3, 4, 5, 6, 7, 7, 6, 5, 4, 3, 2, 1, 0, 7, 6, 5, 4, 3, 2, 1, 0); | |
| 5801 | return TRUE; | |
| 5802 | case 2: /* 1, 3, 5, 7, 0, 2, 4, 6 - 0q */ /* 0, 0, 2, 2, 4, 4, 6, 6 - 0q */ | |
| 5803 | RSP_VNAND_DRC(1, 3, 5, 7, 0, 2, 4, 6, 7, 5, 3, 1, 7, 5, 3, 1, 6, 4, 2, 0, 7, 5, 3, 1); | |
| 5804 | return TRUE; | |
| 5805 | case 3: /* 0, 2, 4, 6, 1, 3, 5, 7 - 1q */ /* 1, 1, 3, 3, 5, 5, 7, 7 - 1q */ | |
| 5806 | RSP_VNAND_DRC(0, 2, 4, 6, 1, 3, 5, 7, 6, 4, 2, 0, 6, 4, 2, 0, 7, 5, 3, 1, 6, 4, 2, 0); | |
| 5807 | return TRUE; | |
| 5808 | case 4: /* 1, 2, 3, 5, 6, 7, 0, 4 - 0h */ /* 0, 0, 0, 0, 4, 4, 4, 4 - 0h */ | |
| 5809 | RSP_VNAND_DRC(1, 2, 3, 5, 6, 7, 0, 4, 7, 7, 7, 3, 3, 3, 7, 3, 6, 5, 4, 2, 1, 0, 7, 3); | |
| 5810 | return TRUE; | |
| 5811 | case 5: /* 0, 2, 3, 4, 6, 7, 1, 5 - 1h */ /* 1, 1, 1, 1, 5, 5, 5, 5 - 1h */ | |
| 5812 | RSP_VNAND_DRC(0, 2, 3, 4, 6, 7, 1, 5, 6, 6, 6, 2, 2, 2, 6, 2, 7, 5, 4, 3, 1, 0, 6, 2); | |
| 5813 | return TRUE; | |
| 5814 | case 6: /* 0, 1, 3, 4, 5, 7, 2, 6 - 2h */ /* 2, 2, 2, 2, 6, 6, 6, 6 - 2h */ | |
| 5815 | RSP_VNAND_DRC(0, 1, 3, 4, 5, 7, 2, 6, 5, 5, 5, 1, 1, 1, 5, 1, 7, 6, 4, 3, 2, 0, 5, 1); | |
| 5816 | return TRUE; | |
| 5817 | case 7: /* 0, 1, 2, 4, 5, 6, 3, 7 - 3h */ /* 3, 3, 3, 3, 7, 7, 7, 7 - 3h */ | |
| 5818 | RSP_VNAND_DRC(0, 1, 2, 4, 5, 6, 3, 7, 4, 4, 4, 0, 0, 0, 4, 0, 7, 6, 5, 3, 2, 1, 4, 0); | |
| 5819 | return TRUE; | |
| 5820 | case 8: /* 1, 2, 3, 4, 5, 6, 7, 0 - 0 */ /* 0, 0, 0, 0, 0, 0, 0, 0 - 0 */ | |
| 5821 | RSP_VNAND_DRC(1, 2, 3, 4, 5, 6, 7, 0, 7, 7, 7, 7, 7, 7, 7, 7, 6, 5, 4, 3, 2, 1, 0, 7); | |
| 5822 | return TRUE; | |
| 5823 | case 9: /* 0, 2, 3, 4, 5, 6, 7, 1 - 1 */ /* 1, 1, 1, 1, 1, 1, 1, 1 - 0 */ | |
| 5824 | RSP_VNAND_DRC(0, 2, 3, 4, 5, 6, 7, 1, 6, 6, 6, 6, 6, 6, 6, 6, 7, 5, 4, 3, 2, 1, 0, 6); | |
| 5825 | return TRUE; | |
| 5826 | case 10: /* 0, 1, 3, 4, 5, 6, 7, 2 - 2 */ /* 2, 2, 2, 2, 2, 2, 2, 2 - 0 */ | |
| 5827 | RSP_VNAND_DRC(0, 1, 3, 4, 5, 6, 7, 2, 5, 5, 5, 5, 5, 5, 5, 5, 7, 6, 4, 3, 2, 1, 0, 5); | |
| 5828 | return TRUE; | |
| 5829 | case 11: /* 0, 1, 2, 4, 5, 6, 7, 3 - 3 */ /* 3, 3, 3, 3, 3, 3, 3, 3 - 0 */ | |
| 5830 | RSP_VNAND_DRC(0, 1, 2, 4, 5, 6, 7, 3, 4, 4, 4, 4, 4, 4, 4, 4, 7, 6, 5, 3, 2, 1, 0, 4); | |
| 5831 | return TRUE; | |
| 5832 | case 12: /* 0, 1, 2, 3, 5, 6, 7, 4 - 4 */ /* 4, 4, 4, 4, 4, 4, 4, 4 - 0 */ | |
| 5833 | RSP_VNAND_DRC(0, 1, 2, 3, 5, 6, 7, 4, 3, 3, 3, 3, 3, 3, 3, 3, 7, 6, 5, 4, 2, 1, 0, 3); | |
| 5834 | return TRUE; | |
| 5835 | case 13: /* 0, 1, 2, 3, 4, 6, 7, 5 - 5 */ /* 5, 5, 5, 5, 5, 5, 5, 5 - 0 */ | |
| 5836 | RSP_VNAND_DRC(0, 1, 2, 3, 4, 6, 7, 5, 2, 2, 2, 2, 2, 2, 2, 2, 7, 6, 5, 4, 3, 1, 0, 2); | |
| 5837 | return TRUE; | |
| 5838 | case 14: /* 0, 1, 2, 3, 4, 5, 7, 6 - 6 */ /* 6, 6, 6, 6, 6, 6, 6, 6 - 0 */ | |
| 5839 | RSP_VNAND_DRC(0, 1, 2, 3, 4, 5, 7, 6, 1, 1, 1, 1, 1, 1, 1, 1, 7, 6, 5, 4, 3, 2, 0, 1); | |
| 5840 | return TRUE; | |
| 5841 | case 15: /* 0, 1, 2, 3, 4, 5, 6, 7 - 7 */ /* 7, 7, 7, 7, 7, 7, 7, 7 - 0 */ | |
| 5842 | RSP_VNAND_DRC(0, 1, 2, 3, 4, 5, 6, 7, 0, 0, 0, 0, 0, 0, 0, 0, 7, 6, 5, 4, 3, 2, 1, 0); | |
| 5843 | return TRUE; | |
| 5844 | } | |
| 5845 | ||
| 5846 | return TRUE; | |
| 5847 | } | |
| 5848 | #else | |
| 5849 | #define RSP_VNAND(E10, E11, E12, E13, E14, E15, E16, E17, E20, E21, E22, E23, E24, E25, E26, E27) \ | |
| 5850 | vres[E10] = ~(R_VREG_S(VS1REG, E10) & R_VREG_S(VS2REG, E20)); \ | |
| 5851 | vres[E11] = ~(R_VREG_S(VS1REG, E11) & R_VREG_S(VS2REG, E21)); \ | |
| 5852 | vres[E12] = ~(R_VREG_S(VS1REG, E12) & R_VREG_S(VS2REG, E22)); \ | |
| 5853 | vres[E13] = ~(R_VREG_S(VS1REG, E13) & R_VREG_S(VS2REG, E23)); \ | |
| 5854 | vres[E14] = ~(R_VREG_S(VS1REG, E14) & R_VREG_S(VS2REG, E24)); \ | |
| 5855 | vres[E15] = ~(R_VREG_S(VS1REG, E15) & R_VREG_S(VS2REG, E25)); \ | |
| 5856 | vres[E16] = ~(R_VREG_S(VS1REG, E16) & R_VREG_S(VS2REG, E26)); \ | |
| 5857 | vres[E17] = ~(R_VREG_S(VS1REG, E17) & R_VREG_S(VS2REG, E27)); \ | |
| 5858 | W_ACCUM_L(E10, vres[E10]); \ | |
| 5859 | W_ACCUM_L(E11, vres[E11]); \ | |
| 5860 | W_ACCUM_L(E12, vres[E12]); \ | |
| 5861 | W_ACCUM_L(E13, vres[E13]); \ | |
| 5862 | W_ACCUM_L(E14, vres[E14]); \ | |
| 5863 | W_ACCUM_L(E15, vres[E15]); \ | |
| 5864 | W_ACCUM_L(E16, vres[E16]); \ | |
| 5865 | W_ACCUM_L(E17, vres[E17]); \ | |
| 5866 | ||
| 5867 | 2927 | INLINE void cfunc_rsp_vnand(void *param) |
| 5868 | 2928 | { |
| 5869 | 2929 | rsp_state *rsp = (rsp_state*)param; |
| r9854 | r9855 | |
| 5876 | 2936 | // |
| 5877 | 2937 | // Bitwise NOT AND of two vector registers |
| 5878 | 2938 | |
| 5879 | switch(EL) | |
| 2939 | int sel; | |
| 2940 | for (int i = 0; i < 8; i++) | |
| 5880 | 2941 | { |
| 5881 | case 0: /* 0, 1, 2, 3, 4, 5, 6, 7 - none */ /* 0, 1, 2, 3, 4, 5, 6, 7 - none */ | |
| 5882 | RSP_VNAND(0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7); | |
| 5883 | break; | |
| 5884 | case 1: /* 0, 1, 2, 3, 4, 5, 6, 7 - ??? */ /* 0, 1, 2, 3, 4, 5, 6, 7 - ??? */ | |
| 5885 | RSP_VNAND(0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7); | |
| 5886 | break; | |
| 5887 | case 2: /* 1, 3, 5, 7, 0, 2, 4, 6 - 0q */ /* 0, 0, 2, 2, 4, 4, 6, 6 - 0q */ | |
| 5888 | RSP_VNAND(1, 3, 5, 7, 0, 2, 4, 6, 0, 2, 4, 6, 0, 2, 4, 6); | |
| 5889 | break; | |
| 5890 | case 3: /* 0, 2, 4, 6, 1, 3, 5, 7 - 1q */ /* 1, 1, 3, 3, 5, 5, 7, 7 - 1q */ | |
| 5891 | RSP_VNAND(0, 2, 4, 6, 1, 3, 5, 7, 1, 3, 5, 7, 1, 3, 5, 7); | |
| 5892 | break; | |
| 5893 | case 4: /* 1, 2, 3, 5, 6, 7, 0, 4 - 0h */ /* 0, 0, 0, 0, 4, 4, 4, 4 - 0h */ | |
| 5894 | RSP_VNAND(1, 2, 3, 5, 6, 7, 0, 4, 0, 0, 0, 4, 4, 4, 0, 4); | |
| 5895 | break; | |
| 5896 | case 5: /* 0, 2, 3, 4, 6, 7, 1, 5 - 1h */ /* 1, 1, 1, 1, 5, 5, 5, 5 - 1h */ | |
| 5897 | RSP_VNAND(0, 2, 3, 4, 6, 7, 1, 5, 1, 1, 1, 5, 5, 5, 1, 5); | |
| 5898 | break; | |
| 5899 | case 6: /* 0, 1, 3, 4, 5, 7, 2, 6 - 2h */ /* 2, 2, 2, 2, 6, 6, 6, 6 - 2h */ | |
| 5900 | RSP_VNAND(0, 1, 3, 4, 5, 7, 2, 6, 2, 2, 2, 6, 6, 6, 2, 6); | |
| 5901 | break; | |
| 5902 | case 7: /* 0, 1, 2, 4, 5, 6, 3, 7 - 3h */ /* 3, 3, 3, 3, 7, 7, 7, 7 - 3h */ | |
| 5903 | RSP_VNAND(0, 1, 2, 4, 5, 6, 3, 7, 3, 3, 3, 7, 7, 7, 3, 7); | |
| 5904 | break; | |
| 5905 | case 8: /* 1, 2, 3, 4, 5, 6, 7, 0 - 0 */ /* 0, 0, 0, 0, 0, 0, 0, 0 - 0 */ | |
| 5906 | RSP_VNAND(1, 2, 3, 4, 5, 6, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0); | |
| 5907 | break; | |
| 5908 | case 9: /* 0, 2, 3, 4, 5, 6, 7, 1 - 1 */ /* 1, 1, 1, 1, 1, 1, 1, 1 - 0 */ | |
| 5909 | RSP_VNAND(0, 2, 3, 4, 5, 6, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1); | |
| 5910 | break; | |
| 5911 | case 10:/* 0, 1, 3, 4, 5, 6, 7, 2 - 2 */ /* 2, 2, 2, 2, 2, 2, 2, 2 - 0 */ | |
| 5912 | RSP_VNAND(0, 1, 3, 4, 5, 6, 7, 2, 2, 2, 2, 2, 2, 2, 2, 2); | |
| 5913 | break; | |
| 5914 | case 11:/* 0, 1, 2, 4, 5, 6, 7, 3 - 3 */ /* 3, 3, 3, 3, 3, 3, 3, 3 - 0 */ | |
| 5915 | RSP_VNAND(0, 1, 2, 4, 5, 6, 7, 3, 3, 3, 3, 3, 3, 3, 3, 3); | |
| 5916 | break; | |
| 5917 | case 12:/* 0, 1, 2, 3, 5, 6, 7, 4 - 4 */ /* 4, 4, 4, 4, 4, 4, 4, 4 - 0 */ | |
| 5918 | RSP_VNAND(0, 1, 2, 3, 5, 6, 7, 4, 4, 4, 4, 4, 4, 4, 4, 4); | |
| 5919 | break; | |
| 5920 | case 13:/* 0, 1, 2, 3, 4, 6, 7, 5 - 5 */ /* 5, 5, 5, 5, 5, 5, 5, 5 - 0 */ | |
| 5921 | RSP_VNAND(0, 1, 2, 3, 4, 6, 7, 5, 5, 5, 5, 5, 5, 5, 5, 5); | |
| 5922 | break; | |
| 5923 | case 14:/* 0, 1, 2, 3, 4, 5, 7, 6 - 6 */ /* 6, 6, 6, 6, 6, 6, 6, 6 - 0 */ | |
| 5924 | RSP_VNAND(0, 1, 2, 3, 4, 5, 7, 6, 6, 6, 6, 6, 6, 6, 6, 6); | |
| 5925 | break; | |
| 5926 | case 15:/* 0, 1, 2, 3, 4, 5, 6, 7 - 7 */ /* 7, 7, 7, 7, 7, 7, 7, 7 - 0 */ | |
| 5927 | RSP_VNAND(0, 1, 2, 3, 4, 5, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7); | |
| 5928 | break; | |
| 2942 | sel = VEC_EL_2(EL, i); | |
| 2943 | vres[i] = ~((VREG_S(VS1REG, i) & VREG_S(VS2REG, sel))); | |
| 2944 | ACCUM_L(i) = vres[i]; | |
| 5929 | 2945 | } |
| 5930 | 2946 | WRITEBACK_RESULT(); |
| 5931 | 2947 | } |
| 5932 | #endif | |
| 5933 | 2948 | |
| 5934 | #if (DRC_VOR) | |
| 5935 | #define RSP_VOR_DRC(E10, E11, E12, E13, E14, E15, E16, E17, E20, E21, E22, E23, E24, E25, E26, E27, I0, I1, I2, I3, I4, I5, I6, I7) \ | |
| 5936 | { \ | |
| 5937 | UML_SEXT(block, IREG(0), VS(VS1REG, I0), WORD); \ | |
| 5938 | UML_SEXT(block, IREG(1), VS(VS2REG, E20), WORD); \ | |
| 5939 | UML_OR(block, IREG(0), IREG(0), IREG(1)); \ | |
| 5940 | UML_STORE(block, &rsp->accum[E10].h.low, IMM(0), IREG(0), WORD); \ | |
| 5941 | \ | |
| 5942 | UML_SEXT(block, IREG(0), VS(VS1REG, I1), WORD); \ | |
| 5943 | UML_SEXT(block, IREG(1), VS(VS2REG, E21), WORD); \ | |
| 5944 | UML_OR(block, IREG(0), IREG(0), IREG(1)); \ | |
| 5945 | UML_STORE(block, &rsp->accum[E11].h.low, IMM(0), IREG(0), WORD); \ | |
| 5946 | \ | |
| 5947 | UML_SEXT(block, IREG(0), VS(VS1REG, I2), WORD); \ | |
| 5948 | UML_SEXT(block, IREG(1), VS(VS2REG, E22), WORD); \ | |
| 5949 | UML_OR(block, IREG(0), IREG(0), IREG(1)); \ | |
| 5950 | UML_STORE(block, &rsp->accum[E12].h.low, IMM(0), IREG(0), WORD); \ | |
| 5951 | \ | |
| 5952 | UML_SEXT(block, IREG(0), VS(VS1REG, I3), WORD); \ | |
| 5953 | UML_SEXT(block, IREG(1), VS(VS2REG, E23), WORD); \ | |
| 5954 | UML_OR(block, IREG(0), IREG(0), IREG(1)); \ | |
| 5955 | UML_STORE(block, &rsp->accum[E13].h.low, IMM(0), IREG(0), WORD); \ | |
| 5956 | \ | |
| 5957 | UML_SEXT(block, IREG(0), VS(VS1REG, I4), WORD); \ | |
| 5958 | UML_SEXT(block, IREG(1), VS(VS2REG, E24), WORD); \ | |
| 5959 | UML_OR(block, IREG(0), IREG(0), IREG(1)); \ | |
| 5960 | UML_STORE(block, &rsp->accum[E14].h.low, IMM(0), IREG(0), WORD); \ | |
| 5961 | \ | |
| 5962 | UML_SEXT(block, IREG(0), VS(VS1REG, I5), WORD); \ | |
| 5963 | UML_SEXT(block, IREG(1), VS(VS2REG, E25), WORD); \ | |
| 5964 | UML_OR(block, IREG(0), IREG(0), IREG(1)); \ | |
| 5965 | UML_STORE(block, &rsp->accum[E15].h.low, IMM(0), IREG(0), WORD); \ | |
| 5966 | \ | |
| 5967 | UML_SEXT(block, IREG(0), VS(VS1REG, I6), WORD); \ | |
| 5968 | UML_SEXT(block, IREG(1), VS(VS2REG, E26), WORD); \ | |
| 5969 | UML_OR(block, IREG(0), IREG(0), IREG(1)); \ | |
| 5970 | UML_STORE(block, &rsp->accum[E16].h.low, IMM(0), IREG(0), WORD); \ | |
| 5971 | \ | |
| 5972 | UML_SEXT(block, IREG(0), VS(VS1REG, I7), WORD); \ | |
| 5973 | UML_SEXT(block, IREG(1), VS(VS2REG, E27), WORD); \ | |
| 5974 | UML_OR(block, IREG(0), IREG(0), IREG(1)); \ | |
| 5975 | UML_STORE(block, &rsp->accum[E17].h.low, IMM(0), IREG(0), WORD); \ | |
| 5976 | \ | |
| 5977 | UML_LOAD(block, IREG(0), &rsp->accum[E10].h.low, IMM(0), WORD); \ | |
| 5978 | UML_STORE(block, &rsp->v[VDREG].s[I0], IMM(0), IREG(0), WORD); \ | |
| 5979 | UML_LOAD(block, IREG(0), &rsp->accum[E11].h.low, IMM(0), WORD); \ | |
| 5980 | UML_STORE(block, &rsp->v[VDREG].s[I1], IMM(0), IREG(0), WORD); \ | |
| 5981 | UML_LOAD(block, IREG(0), &rsp->accum[E12].h.low, IMM(0), WORD); \ | |
| 5982 | UML_STORE(block, &rsp->v[VDREG].s[I2], IMM(0), IREG(0), WORD); \ | |
| 5983 | UML_LOAD(block, IREG(0), &rsp->accum[E13].h.low, IMM(0), WORD); \ | |
| 5984 | UML_STORE(block, &rsp->v[VDREG].s[I3], IMM(0), IREG(0), WORD); \ | |
| 5985 | UML_LOAD(block, IREG(0), &rsp->accum[E14].h.low, IMM(0), WORD); \ | |
| 5986 | UML_STORE(block, &rsp->v[VDREG].s[I4], IMM(0), IREG(0), WORD); \ | |
| 5987 | UML_LOAD(block, IREG(0), &rsp->accum[E15].h.low, IMM(0), WORD); \ | |
| 5988 | UML_STORE(block, &rsp->v[VDREG].s[I5], IMM(0), IREG(0), WORD); \ | |
| 5989 | UML_LOAD(block, IREG(0), &rsp->accum[E16].h.low, IMM(0), WORD); \ | |
| 5990 | UML_STORE(block, &rsp->v[VDREG].s[I6], IMM(0), IREG(0), WORD); \ | |
| 5991 | UML_LOAD(block, IREG(0), &rsp->accum[E17].h.low, IMM(0), WORD); \ | |
| 5992 | UML_STORE(block, &rsp->v[VDREG].s[I7], IMM(0), IREG(0), WORD); \ | |
| 5993 | } | |
| 5994 | ||
| 5995 | static int generate_vor(rsp_state *rsp, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) | |
| 5996 | { | |
| 5997 | UINT32 op = desc->opptr.l[0]; | |
| 5998 | ||
| 5999 | // 31 25 24 20 15 10 5 0 | |
| 6000 | // ------------------------------------------------------ | |
| 6001 | // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 101000 | | |
| 6002 | // ------------------------------------------------------ | |
| 6003 | // | |
| 6004 | // Bitwise OR of two vector registers | |
| 6005 | ||
| 6006 | switch(EL) | |
| 6007 | { | |
| 6008 | case 0: /* 0, 1, 2, 3, 4, 5, 6, 7 - none */ /* 0, 1, 2, 3, 4, 5, 6, 7 - none */ | |
| 6009 | RSP_VOR_DRC(0, 1, 2, 3, 4, 5, 6, 7, 7, 6, 5, 4, 3, 2, 1, 0, 7, 6, 5, 4, 3, 2, 1, 0); | |
| 6010 | return TRUE; | |
| 6011 | case 1: /* 0, 1, 2, 3, 4, 5, 6, 7 - ??? */ /* 0, 1, 2, 3, 4, 5, 6, 7 - ??? */ | |
| 6012 | RSP_VOR_DRC(0, 1, 2, 3, 4, 5, 6, 7, 7, 6, 5, 4, 3, 2, 1, 0, 7, 6, 5, 4, 3, 2, 1, 0); | |
| 6013 | return TRUE; | |
| 6014 | case 2: /* 1, 3, 5, 7, 0, 2, 4, 6 - 0q */ /* 0, 0, 2, 2, 4, 4, 6, 6 - 0q */ | |
| 6015 | RSP_VOR_DRC(1, 3, 5, 7, 0, 2, 4, 6, 7, 5, 3, 1, 7, 5, 3, 1, 6, 4, 2, 0, 7, 5, 3, 1); | |
| 6016 | return TRUE; | |
| 6017 | case 3: /* 0, 2, 4, 6, 1, 3, 5, 7 - 1q */ /* 1, 1, 3, 3, 5, 5, 7, 7 - 1q */ | |
| 6018 | RSP_VOR_DRC(0, 2, 4, 6, 1, 3, 5, 7, 6, 4, 2, 0, 6, 4, 2, 0, 7, 5, 3, 1, 6, 4, 2, 0); | |
| 6019 | return TRUE; | |
| 6020 | case 4: /* 1, 2, 3, 5, 6, 7, 0, 4 - 0h */ /* 0, 0, 0, 0, 4, 4, 4, 4 - 0h */ | |
| 6021 | RSP_VOR_DRC(1, 2, 3, 5, 6, 7, 0, 4, 7, 7, 7, 3, 3, 3, 7, 3, 6, 5, 4, 2, 1, 0, 7, 3); | |
| 6022 | return TRUE; | |
| 6023 | case 5: /* 0, 2, 3, 4, 6, 7, 1, 5 - 1h */ /* 1, 1, 1, 1, 5, 5, 5, 5 - 1h */ | |
| 6024 | RSP_VOR_DRC(0, 2, 3, 4, 6, 7, 1, 5, 6, 6, 6, 2, 2, 2, 6, 2, 7, 5, 4, 3, 1, 0, 6, 2); | |
| 6025 | return TRUE; | |
| 6026 | case 6: /* 0, 1, 3, 4, 5, 7, 2, 6 - 2h */ /* 2, 2, 2, 2, 6, 6, 6, 6 - 2h */ | |
| 6027 | RSP_VOR_DRC(0, 1, 3, 4, 5, 7, 2, 6, 5, 5, 5, 1, 1, 1, 5, 1, 7, 6, 4, 3, 2, 0, 5, 1); | |
| 6028 | return TRUE; | |
| 6029 | case 7: /* 0, 1, 2, 4, 5, 6, 3, 7 - 3h */ /* 3, 3, 3, 3, 7, 7, 7, 7 - 3h */ | |
| 6030 | RSP_VOR_DRC(0, 1, 2, 4, 5, 6, 3, 7, 4, 4, 4, 0, 0, 0, 4, 0, 7, 6, 5, 3, 2, 1, 4, 0); | |
| 6031 | return TRUE; | |
| 6032 | case 8: /* 1, 2, 3, 4, 5, 6, 7, 0 - 0 */ /* 0, 0, 0, 0, 0, 0, 0, 0 - 0 */ | |
| 6033 | RSP_VOR_DRC(1, 2, 3, 4, 5, 6, 7, 0, 7, 7, 7, 7, 7, 7, 7, 7, 6, 5, 4, 3, 2, 1, 0, 7); | |
| 6034 | return TRUE; | |
| 6035 | case 9: /* 0, 2, 3, 4, 5, 6, 7, 1 - 1 */ /* 1, 1, 1, 1, 1, 1, 1, 1 - 0 */ | |
| 6036 | RSP_VOR_DRC(0, 2, 3, 4, 5, 6, 7, 1, 6, 6, 6, 6, 6, 6, 6, 6, 7, 5, 4, 3, 2, 1, 0, 6); | |
| 6037 | return TRUE; | |
| 6038 | case 10: /* 0, 1, 3, 4, 5, 6, 7, 2 - 2 */ /* 2, 2, 2, 2, 2, 2, 2, 2 - 0 */ | |
| 6039 | RSP_VOR_DRC(0, 1, 3, 4, 5, 6, 7, 2, 5, 5, 5, 5, 5, 5, 5, 5, 7, 6, 4, 3, 2, 1, 0, 5); | |
| 6040 | return TRUE; | |
| 6041 | case 11: /* 0, 1, 2, 4, 5, 6, 7, 3 - 3 */ /* 3, 3, 3, 3, 3, 3, 3, 3 - 0 */ | |
| 6042 | RSP_VOR_DRC(0, 1, 2, 4, 5, 6, 7, 3, 4, 4, 4, 4, 4, 4, 4, 4, 7, 6, 5, 3, 2, 1, 0, 4); | |
| 6043 | return TRUE; | |
| 6044 | case 12: /* 0, 1, 2, 3, 5, 6, 7, 4 - 4 */ /* 4, 4, 4, 4, 4, 4, 4, 4 - 0 */ | |
| 6045 | RSP_VOR_DRC(0, 1, 2, 3, 5, 6, 7, 4, 3, 3, 3, 3, 3, 3, 3, 3, 7, 6, 5, 4, 2, 1, 0, 3); | |
| 6046 | return TRUE; | |
| 6047 | case 13: /* 0, 1, 2, 3, 4, 6, 7, 5 - 5 */ /* 5, 5, 5, 5, 5, 5, 5, 5 - 0 */ | |
| 6048 | RSP_VOR_DRC(0, 1, 2, 3, 4, 6, 7, 5, 2, 2, 2, 2, 2, 2, 2, 2, 7, 6, 5, 4, 3, 1, 0, 2); | |
| 6049 | return TRUE; | |
| 6050 | case 14: /* 0, 1, 2, 3, 4, 5, 7, 6 - 6 */ /* 6, 6, 6, 6, 6, 6, 6, 6 - 0 */ | |
| 6051 | RSP_VOR_DRC(0, 1, 2, 3, 4, 5, 7, 6, 1, 1, 1, 1, 1, 1, 1, 1, 7, 6, 5, 4, 3, 2, 0, 1); | |
| 6052 | return TRUE; | |
| 6053 | case 15: /* 0, 1, 2, 3, 4, 5, 6, 7 - 7 */ /* 7, 7, 7, 7, 7, 7, 7, 7 - 0 */ | |
| 6054 | RSP_VOR_DRC(0, 1, 2, 3, 4, 5, 6, 7, 0, 0, 0, 0, 0, 0, 0, 0, 7, 6, 5, 4, 3, 2, 1, 0); | |
| 6055 | return TRUE; | |
| 6056 | } | |
| 6057 | ||
| 6058 | return TRUE; | |
| 6059 | } | |
| 6060 | #else | |
| 6061 | #define RSP_VOR(E10, E11, E12, E13, E14, E15, E16, E17, E20, E21, E22, E23, E24, E25, E26, E27) \ | |
| 6062 | vres[E10] = R_VREG_S(VS1REG, E10) | R_VREG_S(VS2REG, E20); \ | |
| 6063 | vres[E11] = R_VREG_S(VS1REG, E11) | R_VREG_S(VS2REG, E21); \ | |
| 6064 | vres[E12] = R_VREG_S(VS1REG, E12) | R_VREG_S(VS2REG, E22); \ | |
| 6065 | vres[E13] = R_VREG_S(VS1REG, E13) | R_VREG_S(VS2REG, E23); \ | |
| 6066 | vres[E14] = R_VREG_S(VS1REG, E14) | R_VREG_S(VS2REG, E24); \ | |
| 6067 | vres[E15] = R_VREG_S(VS1REG, E15) | R_VREG_S(VS2REG, E25); \ | |
| 6068 | vres[E16] = R_VREG_S(VS1REG, E16) | R_VREG_S(VS2REG, E26); \ | |
| 6069 | vres[E17] = R_VREG_S(VS1REG, E17) | R_VREG_S(VS2REG, E27); \ | |
| 6070 | W_ACCUM_L(E10, vres[E10]); \ | |
| 6071 | W_ACCUM_L(E11, vres[E11]); \ | |
| 6072 | W_ACCUM_L(E12, vres[E12]); \ | |
| 6073 | W_ACCUM_L(E13, vres[E13]); \ | |
| 6074 | W_ACCUM_L(E14, vres[E14]); \ | |
| 6075 | W_ACCUM_L(E15, vres[E15]); \ | |
| 6076 | W_ACCUM_L(E16, vres[E16]); \ | |
| 6077 | W_ACCUM_L(E17, vres[E17]); \ | |
| 6078 | ||
| 6079 | 2949 | INLINE void cfunc_rsp_vor(void *param) |
| 6080 | 2950 | { |
| 6081 | 2951 | rsp_state *rsp = (rsp_state*)param; |
| r9854 | r9855 | |
| 6088 | 2958 | // |
| 6089 | 2959 | // Bitwise OR of two vector registers |
| 6090 | 2960 | |
| 6091 | switch(EL) | |
| 2961 | int sel; | |
| 2962 | for (int i = 0; i < 8; i++) | |
| 6092 | 2963 | { |
| 6093 | case 0: /* 0, 1, 2, 3, 4, 5, 6, 7 - none */ /* 0, 1, 2, 3, 4, 5, 6, 7 - none */ | |
| 6094 | RSP_VOR(0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7); | |
| 6095 | break; | |
| 6096 | case 1: /* 0, 1, 2, 3, 4, 5, 6, 7 - ??? */ /* 0, 1, 2, 3, 4, 5, 6, 7 - ??? */ | |
| 6097 | RSP_VOR(0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7); | |
| 6098 | break; | |
| 6099 | case 2: /* 1, 3, 5, 7, 0, 2, 4, 6 - 0q */ /* 0, 0, 2, 2, 4, 4, 6, 6 - 0q */ | |
| 6100 | RSP_VOR(1, 3, 5, 7, 0, 2, 4, 6, 0, 2, 4, 6, 0, 2, 4, 6); | |
| 6101 | break; | |
| 6102 | case 3: /* 0, 2, 4, 6, 1, 3, 5, 7 - 1q */ /* 1, 1, 3, 3, 5, 5, 7, 7 - 1q */ | |
| 6103 | RSP_VOR(0, 2, 4, 6, 1, 3, 5, 7, 1, 3, 5, 7, 1, 3, 5, 7); | |
| 6104 | break; | |
| 6105 | case 4: /* 1, 2, 3, 5, 6, 7, 0, 4 - 0h */ /* 0, 0, 0, 0, 4, 4, 4, 4 - 0h */ | |
| 6106 | RSP_VOR(1, 2, 3, 5, 6, 7, 0, 4, 0, 0, 0, 4, 4, 4, 0, 4); | |
| 6107 | break; | |
| 6108 | case 5: /* 0, 2, 3, 4, 6, 7, 1, 5 - 1h */ /* 1, 1, 1, 1, 5, 5, 5, 5 - 1h */ | |
| 6109 | RSP_VOR(0, 2, 3, 4, 6, 7, 1, 5, 1, 1, 1, 5, 5, 5, 1, 5); | |
| 6110 | break; | |
| 6111 | case 6: /* 0, 1, 3, 4, 5, 7, 2, 6 - 2h */ /* 2, 2, 2, 2, 6, 6, 6, 6 - 2h */ | |
| 6112 | RSP_VOR(0, 1, 3, 4, 5, 7, 2, 6, 2, 2, 2, 6, 6, 6, 2, 6); | |
| 6113 | break; | |
| 6114 | case 7: /* 0, 1, 2, 4, 5, 6, 3, 7 - 3h */ /* 3, 3, 3, 3, 7, 7, 7, 7 - 3h */ | |
| 6115 | RSP_VOR(0, 1, 2, 4, 5, 6, 3, 7, 3, 3, 3, 7, 7, 7, 3, 7); | |
| 6116 | break; | |
| 6117 | case 8: /* 1, 2, 3, 4, 5, 6, 7, 0 - 0 */ /* 0, 0, 0, 0, 0, 0, 0, 0 - 0 */ | |
| 6118 | RSP_VOR(1, 2, 3, 4, 5, 6, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0); | |
| 6119 | break; | |
| 6120 | case 9: /* 0, 2, 3, 4, 5, 6, 7, 1 - 1 */ /* 1, 1, 1, 1, 1, 1, 1, 1 - 0 */ | |
| 6121 | RSP_VOR(0, 2, 3, 4, 5, 6, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1); | |
| 6122 | break; | |
| 6123 | case 10:/* 0, 1, 3, 4, 5, 6, 7, 2 - 2 */ /* 2, 2, 2, 2, 2, 2, 2, 2 - 0 */ | |
| 6124 | RSP_VOR(0, 1, 3, 4, 5, 6, 7, 2, 2, 2, 2, 2, 2, 2, 2, 2); | |
| 6125 | break; | |
| 6126 | case 11:/* 0, 1, 2, 4, 5, 6, 7, 3 - 3 */ /* 3, 3, 3, 3, 3, 3, 3, 3 - 0 */ | |
| 6127 | RSP_VOR(0, 1, 2, 4, 5, 6, 7, 3, 3, 3, 3, 3, 3, 3, 3, 3); | |
| 6128 | break; | |
| 6129 | case 12:/* 0, 1, 2, 3, 5, 6, 7, 4 - 4 */ /* 4, 4, 4, 4, 4, 4, 4, 4 - 0 */ | |
| 6130 | RSP_VOR(0, 1, 2, 3, 5, 6, 7, 4, 4, 4, 4, 4, 4, 4, 4, 4); | |
| 6131 | break; | |
| 6132 | case 13:/* 0, 1, 2, 3, 4, 6, 7, 5 - 5 */ /* 5, 5, 5, 5, 5, 5, 5, 5 - 0 */ | |
| 6133 | RSP_VOR(0, 1, 2, 3, 4, 6, 7, 5, 5, 5, 5, 5, 5, 5, 5, 5); | |
| 6134 | break; | |
| 6135 | case 14:/* 0, 1, 2, 3, 4, 5, 7, 6 - 6 */ /* 6, 6, 6, 6, 6, 6, 6, 6 - 0 */ | |
| 6136 | RSP_VOR(0, 1, 2, 3, 4, 5, 7, 6, 6, 6, 6, 6, 6, 6, 6, 6); | |
| 6137 | break; | |
| 6138 | case 15:/* 0, 1, 2, 3, 4, 5, 6, 7 - 7 */ /* 7, 7, 7, 7, 7, 7, 7, 7 - 0 */ | |
| 6139 | RSP_VOR(0, 1, 2, 3, 4, 5, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7); | |
| 6140 | break; | |
| 2964 | sel = VEC_EL_2(EL, i); | |
| 2965 | vres[i] = VREG_S(VS1REG, i) | VREG_S(VS2REG, sel); | |
| 2966 | ACCUM_L(i) = vres[i]; | |
| 6141 | 2967 | } |
| 6142 | 2968 | WRITEBACK_RESULT(); |
| 6143 | 2969 | } |
| 6144 | #endif | |
| 6145 | 2970 | |
| 6146 | #if (DRC_VNOR) | |
| 6147 | #define RSP_VNOR_DRC(E10, E11, E12, E13, E14, E15, E16, E17, E20, E21, E22, E23, E24, E25, E26, E27, I0, I1, I2, I3, I4, I5, I6, I7) \ | |
| 6148 | { \ | |
| 6149 | UML_SEXT(block, IREG(0), VS(VS1REG, I0), WORD); \ | |
| 6150 | UML_SEXT(block, IREG(1), VS(VS2REG, E20), WORD); \ | |
| 6151 | UML_OR(block, IREG(0), IREG(0), IREG(1)); \ | |
| 6152 | UML_XOR(block, IREG(0), IREG(0), IMM(0xffffffff)); \ | |
| 6153 | UML_STORE(block, &rsp->accum[E10].h.low, IMM(0), IREG(0), WORD); \ | |
| 6154 | \ | |
| 6155 | UML_SEXT(block, IREG(0), VS(VS1REG, I1), WORD); \ | |
| 6156 | UML_SEXT(block, IREG(1), VS(VS2REG, E21), WORD); \ | |
| 6157 | UML_OR(block, IREG(0), IREG(0), IREG(1)); \ | |
| 6158 | UML_XOR(block, IREG(0), IREG(0), IMM(0xffffffff)); \ | |
| 6159 | UML_STORE(block, &rsp->accum[E11].h.low, IMM(0), IREG(0), WORD); \ | |
| 6160 | \ | |
| 6161 | UML_SEXT(block, IREG(0), VS(VS1REG, I2), WORD); \ | |
| 6162 | UML_SEXT(block, IREG(1), VS(VS2REG, E22), WORD); \ | |
| 6163 | UML_OR(block, IREG(0), IREG(0), IREG(1)); \ | |
| 6164 | UML_XOR(block, IREG(0), IREG(0), IMM(0xffffffff)); \ | |
| 6165 | UML_STORE(block, &rsp->accum[E12].h.low, IMM(0), IREG(0), WORD); \ | |
| 6166 | \ | |
| 6167 | UML_SEXT(block, IREG(0), VS(VS1REG, I3), WORD); \ | |
| 6168 | UML_SEXT(block, IREG(1), VS(VS2REG, E23), WORD); \ | |
| 6169 | UML_OR(block, IREG(0), IREG(0), IREG(1)); \ | |
| 6170 | UML_XOR(block, IREG(0), IREG(0), IMM(0xffffffff)); \ | |
| 6171 | UML_STORE(block, &rsp->accum[E13].h.low, IMM(0), IREG(0), WORD); \ | |
| 6172 | \ | |
| 6173 | UML_SEXT(block, IREG(0), VS(VS1REG, I4), WORD); \ | |
| 6174 | UML_SEXT(block, IREG(1), VS(VS2REG, E24), WORD); \ | |
| 6175 | UML_OR(block, IREG(0), IREG(0), IREG(1)); \ | |
| 6176 | UML_XOR(block, IREG(0), IREG(0), IMM(0xffffffff)); \ | |
| 6177 | UML_STORE(block, &rsp->accum[E14].h.low, IMM(0), IREG(0), WORD); \ | |
| 6178 | \ | |
| 6179 | UML_SEXT(block, IREG(0), VS(VS1REG, I5), WORD); \ | |
| 6180 | UML_SEXT(block, IREG(1), VS(VS2REG, E25), WORD); \ | |
| 6181 | UML_OR(block, IREG(0), IREG(0), IREG(1)); \ | |
| 6182 | UML_XOR(block, IREG(0), IREG(0), IMM(0xffffffff)); \ | |
| 6183 | UML_STORE(block, &rsp->accum[E15].h.low, IMM(0), IREG(0), WORD); \ | |
| 6184 | \ | |
| 6185 | UML_SEXT(block, IREG(0), VS(VS1REG, I6), WORD); \ | |
| 6186 | UML_SEXT(block, IREG(1), VS(VS2REG, E26), WORD); \ | |
| 6187 | UML_OR(block, IREG(0), IREG(0), IREG(1)); \ | |
| 6188 | UML_XOR(block, IREG(0), IREG(0), IMM(0xffffffff)); \ | |
| 6189 | UML_STORE(block, &rsp->accum[E16].h.low, IMM(0), IREG(0), WORD); \ | |
| 6190 | \ | |
| 6191 | UML_SEXT(block, IREG(0), VS(VS1REG, I7), WORD); \ | |
| 6192 | UML_SEXT(block, IREG(1), VS(VS2REG, E27), WORD); \ | |
| 6193 | UML_OR(block, IREG(0), IREG(0), IREG(1)); \ | |
| 6194 | UML_XOR(block, IREG(0), IREG(0), IMM(0xffffffff)); \ | |
| 6195 | UML_STORE(block, &rsp->accum[E17].h.low, IMM(0), IREG(0), WORD); \ | |
| 6196 | \ | |
| 6197 | UML_LOAD(block, IREG(0), &rsp->accum[E10].h.low, IMM(0), WORD); \ | |
| 6198 | UML_STORE(block, &rsp->v[VDREG].s[I0], IMM(0), IREG(0), WORD); \ | |
| 6199 | UML_LOAD(block, IREG(0), &rsp->accum[E11].h.low, IMM(0), WORD); \ | |
| 6200 | UML_STORE(block, &rsp->v[VDREG].s[I1], IMM(0), IREG(0), WORD); \ | |
| 6201 | UML_LOAD(block, IREG(0), &rsp->accum[E12].h.low, IMM(0), WORD); \ | |
| 6202 | UML_STORE(block, &rsp->v[VDREG].s[I2], IMM(0), IREG(0), WORD); \ | |
| 6203 | UML_LOAD(block, IREG(0), &rsp->accum[E13].h.low, IMM(0), WORD); \ | |
| 6204 | UML_STORE(block, &rsp->v[VDREG].s[I3], IMM(0), IREG(0), WORD); \ | |
| 6205 | UML_LOAD(block, IREG(0), &rsp->accum[E14].h.low, IMM(0), WORD); \ | |
| 6206 | UML_STORE(block, &rsp->v[VDREG].s[I4], IMM(0), IREG(0), WORD); \ | |
| 6207 | UML_LOAD(block, IREG(0), &rsp->accum[E15].h.low, IMM(0), WORD); \ | |
| 6208 | UML_STORE(block, &rsp->v[VDREG].s[I5], IMM(0), IREG(0), WORD); \ | |
| 6209 | UML_LOAD(block, IREG(0), &rsp->accum[E16].h.low, IMM(0), WORD); \ | |
| 6210 | UML_STORE(block, &rsp->v[VDREG].s[I6], IMM(0), IREG(0), WORD); \ | |
| 6211 | UML_LOAD(block, IREG(0), &rsp->accum[E17].h.low, IMM(0), WORD); \ | |
| 6212 | UML_STORE(block, &rsp->v[VDREG].s[I7], IMM(0), IREG(0), WORD); \ | |
| 6213 | } | |
| 6214 | ||
| 6215 | static int generate_vnor(rsp_state *rsp, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) | |
| 6216 | { | |
| 6217 | UINT32 op = desc->opptr.l[0]; | |
| 6218 | ||
| 6219 | // 31 25 24 20 15 10 5 0 | |
| 6220 | // ------------------------------------------------------ | |
| 6221 | // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 101000 | | |
| 6222 | // ------------------------------------------------------ | |
| 6223 | // | |
| 6224 | // Bitwise NOT OR of two vector registers | |
| 6225 | ||
| 6226 | switch(EL) | |
| 6227 | { | |
| 6228 | case 0: /* 0, 1, 2, 3, 4, 5, 6, 7 - none */ /* 0, 1, 2, 3, 4, 5, 6, 7 - none */ | |
| 6229 | RSP_VNOR_DRC(0, 1, 2, 3, 4, 5, 6, 7, 7, 6, 5, 4, 3, 2, 1, 0, 7, 6, 5, 4, 3, 2, 1, 0); | |
| 6230 | return TRUE; | |
| 6231 | case 1: /* 0, 1, 2, 3, 4, 5, 6, 7 - ??? */ /* 0, 1, 2, 3, 4, 5, 6, 7 - ??? */ | |
| 6232 | RSP_VNOR_DRC(0, 1, 2, 3, 4, 5, 6, 7, 7, 6, 5, 4, 3, 2, 1, 0, 7, 6, 5, 4, 3, 2, 1, 0); | |
| 6233 | return TRUE; | |
| 6234 | case 2: /* 1, 3, 5, 7, 0, 2, 4, 6 - 0q */ /* 0, 0, 2, 2, 4, 4, 6, 6 - 0q */ | |
| 6235 | RSP_VNOR_DRC(1, 3, 5, 7, 0, 2, 4, 6, 7, 5, 3, 1, 7, 5, 3, 1, 6, 4, 2, 0, 7, 5, 3, 1); | |
| 6236 | return TRUE; | |
| 6237 | case 3: /* 0, 2, 4, 6, 1, 3, 5, 7 - 1q */ /* 1, 1, 3, 3, 5, 5, 7, 7 - 1q */ | |
| 6238 | RSP_VNOR_DRC(0, 2, 4, 6, 1, 3, 5, 7, 6, 4, 2, 0, 6, 4, 2, 0, 7, 5, 3, 1, 6, 4, 2, 0); | |
| 6239 | return TRUE; | |
| 6240 | case 4: /* 1, 2, 3, 5, 6, 7, 0, 4 - 0h */ /* 0, 0, 0, 0, 4, 4, 4, 4 - 0h */ | |
| 6241 | RSP_VNOR_DRC(1, 2, 3, 5, 6, 7, 0, 4, 7, 7, 7, 3, 3, 3, 7, 3, 6, 5, 4, 2, 1, 0, 7, 3); | |
| 6242 | return TRUE; | |
| 6243 | case 5: /* 0, 2, 3, 4, 6, 7, 1, 5 - 1h */ /* 1, 1, 1, 1, 5, 5, 5, 5 - 1h */ | |
| 6244 | RSP_VNOR_DRC(0, 2, 3, 4, 6, 7, 1, 5, 6, 6, 6, 2, 2, 2, 6, 2, 7, 5, 4, 3, 1, 0, 6, 2); | |
| 6245 | return TRUE; | |
| 6246 | case 6: /* 0, 1, 3, 4, 5, 7, 2, 6 - 2h */ /* 2, 2, 2, 2, 6, 6, 6, 6 - 2h */ | |
| 6247 | RSP_VNOR_DRC(0, 1, 3, 4, 5, 7, 2, 6, 5, 5, 5, 1, 1, 1, 5, 1, 7, 6, 4, 3, 2, 0, 5, 1); | |
| 6248 | return TRUE; | |
| 6249 | case 7: /* 0, 1, 2, 4, 5, 6, 3, 7 - 3h */ /* 3, 3, 3, 3, 7, 7, 7, 7 - 3h */ | |
| 6250 | RSP_VNOR_DRC(0, 1, 2, 4, 5, 6, 3, 7, 4, 4, 4, 0, 0, 0, 4, 0, 7, 6, 5, 3, 2, 1, 4, 0); | |
| 6251 | return TRUE; | |
| 6252 | case 8: /* 1, 2, 3, 4, 5, 6, 7, 0 - 0 */ /* 0, 0, 0, 0, 0, 0, 0, 0 - 0 */ | |
| 6253 | RSP_VNOR_DRC(1, 2, 3, 4, 5, 6, 7, 0, 7, 7, 7, 7, 7, 7, 7, 7, 6, 5, 4, 3, 2, 1, 0, 7); | |
| 6254 | return TRUE; | |
| 6255 | case 9: /* 0, 2, 3, 4, 5, 6, 7, 1 - 1 */ /* 1, 1, 1, 1, 1, 1, 1, 1 - 0 */ | |
| 6256 | RSP_VNOR_DRC(0, 2, 3, 4, 5, 6, 7, 1, 6, 6, 6, 6, 6, 6, 6, 6, 7, 5, 4, 3, 2, 1, 0, 6); | |
| 6257 | return TRUE; | |
| 6258 | case 10: /* 0, 1, 3, 4, 5, 6, 7, 2 - 2 */ /* 2, 2, 2, 2, 2, 2, 2, 2 - 0 */ | |
| 6259 | RSP_VNOR_DRC(0, 1, 3, 4, 5, 6, 7, 2, 5, 5, 5, 5, 5, 5, 5, 5, 7, 6, 4, 3, 2, 1, 0, 5); | |
| 6260 | return TRUE; | |
| 6261 | case 11: /* 0, 1, 2, 4, 5, 6, 7, 3 - 3 */ /* 3, 3, 3, 3, 3, 3, 3, 3 - 0 */ | |
| 6262 | RSP_VNOR_DRC(0, 1, 2, 4, 5, 6, 7, 3, 4, 4, 4, 4, 4, 4, 4, 4, 7, 6, 5, 3, 2, 1, 0, 4); | |
| 6263 | return TRUE; | |
| 6264 | case 12: /* 0, 1, 2, 3, 5, 6, 7, 4 - 4 */ /* 4, 4, 4, 4, 4, 4, 4, 4 - 0 */ | |
| 6265 | RSP_VNOR_DRC(0, 1, 2, 3, 5, 6, 7, 4, 3, 3, 3, 3, 3, 3, 3, 3, 7, 6, 5, 4, 2, 1, 0, 3); | |
| 6266 | return TRUE; | |
| 6267 | case 13: /* 0, 1, 2, 3, 4, 6, 7, 5 - 5 */ /* 5, 5, 5, 5, 5, 5, 5, 5 - 0 */ | |
| 6268 | RSP_VNOR_DRC(0, 1, 2, 3, 4, 6, 7, 5, 2, 2, 2, 2, 2, 2, 2, 2, 7, 6, 5, 4, 3, 1, 0, 2); | |
| 6269 | return TRUE; | |
| 6270 | case 14: /* 0, 1, 2, 3, 4, 5, 7, 6 - 6 */ /* 6, 6, 6, 6, 6, 6, 6, 6 - 0 */ | |
| 6271 | RSP_VNOR_DRC(0, 1, 2, 3, 4, 5, 7, 6, 1, 1, 1, 1, 1, 1, 1, 1, 7, 6, 5, 4, 3, 2, 0, 1); | |
| 6272 | return TRUE; | |
| 6273 | case 15: /* 0, 1, 2, 3, 4, 5, 6, 7 - 7 */ /* 7, 7, 7, 7, 7, 7, 7, 7 - 0 */ | |
| 6274 | RSP_VNOR_DRC(0, 1, 2, 3, 4, 5, 6, 7, 0, 0, 0, 0, 0, 0, 0, 0, 7, 6, 5, 4, 3, 2, 1, 0); | |
| 6275 | return TRUE; | |
| 6276 | } | |
| 6277 | ||
| 6278 | return TRUE; | |
| 6279 | } | |
| 6280 | #else | |
| 6281 | #define RSP_VNOR(E10, E11, E12, E13, E14, E15, E16, E17, E20, E21, E22, E23, E24, E25, E26, E27) \ | |
| 6282 | vres[E10] = ~(R_VREG_S(VS1REG, E10) | R_VREG_S(VS2REG, E20)); \ | |
| 6283 | vres[E11] = ~(R_VREG_S(VS1REG, E11) | R_VREG_S(VS2REG, E21)); \ | |
| 6284 | vres[E12] = ~(R_VREG_S(VS1REG, E12) | R_VREG_S(VS2REG, E22)); \ | |
| 6285 | vres[E13] = ~(R_VREG_S(VS1REG, E13) | R_VREG_S(VS2REG, E23)); \ | |
| 6286 | vres[E14] = ~(R_VREG_S(VS1REG, E14) | R_VREG_S(VS2REG, E24)); \ | |
| 6287 | vres[E15] = ~(R_VREG_S(VS1REG, E15) | R_VREG_S(VS2REG, E25)); \ | |
| 6288 | vres[E16] = ~(R_VREG_S(VS1REG, E16) | R_VREG_S(VS2REG, E26)); \ | |
| 6289 | vres[E17] = ~(R_VREG_S(VS1REG, E17) | R_VREG_S(VS2REG, E27)); \ | |
| 6290 | W_ACCUM_L(E10, vres[E10]); \ | |
| 6291 | W_ACCUM_L(E11, vres[E11]); \ | |
| 6292 | W_ACCUM_L(E12, vres[E12]); \ | |
| 6293 | W_ACCUM_L(E13, vres[E13]); \ | |
| 6294 | W_ACCUM_L(E14, vres[E14]); \ | |
| 6295 | W_ACCUM_L(E15, vres[E15]); \ | |
| 6296 | W_ACCUM_L(E16, vres[E16]); \ | |
| 6297 | W_ACCUM_L(E17, vres[E17]); \ | |
| 6298 | ||
| 6299 | 2971 | INLINE void cfunc_rsp_vnor(void *param) |
| 6300 | 2972 | { |
| 6301 | 2973 | rsp_state *rsp = (rsp_state*)param; |
| r9854 | r9855 | |
| 6308 | 2980 | // |
| 6309 | 2981 | // Bitwise NOT OR of two vector registers |
| 6310 | 2982 | |
| 6311 | switch(EL) | |
| 2983 | int sel; | |
| 2984 | for (int i = 0; i < 8; i++) | |
| 6312 | 2985 | { |
| 6313 | case 0: /* 0, 1, 2, 3, 4, 5, 6, 7 - none */ /* 0, 1, 2, 3, 4, 5, 6, 7 - none */ | |
| 6314 | RSP_VNOR(0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7); | |
| 6315 | break; | |
| 6316 | case 1: /* 0, 1, 2, 3, 4, 5, 6, 7 - ??? */ /* 0, 1, 2, 3, 4, 5, 6, 7 - ??? */ | |
| 6317 | RSP_VNOR(0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7); | |
| 6318 | break; | |
| 6319 | case 2: /* 1, 3, 5, 7, 0, 2, 4, 6 - 0q */ /* 0, 0, 2, 2, 4, 4, 6, 6 - 0q */ | |
| 6320 | RSP_VNOR(1, 3, 5, 7, 0, 2, 4, 6, 0, 2, 4, 6, 0, 2, 4, 6); | |
| 6321 | break; | |
| 6322 | case 3: /* 0, 2, 4, 6, 1, 3, 5, 7 - 1q */ /* 1, 1, 3, 3, 5, 5, 7, 7 - 1q */ | |
| 6323 | RSP_VNOR(0, 2, 4, 6, 1, 3, 5, 7, 1, 3, 5, 7, 1, 3, 5, 7); | |
| 6324 | break; | |
| 6325 | case 4: /* 1, 2, 3, 5, 6, 7, 0, 4 - 0h */ /* 0, 0, 0, 0, 4, 4, 4, 4 - 0h */ | |
| 6326 | RSP_VNOR(1, 2, 3, 5, 6, 7, 0, 4, 0, 0, 0, 4, 4, 4, 0, 4); | |
| 6327 | break; | |
| 6328 | case 5: /* 0, 2, 3, 4, 6, 7, 1, 5 - 1h */ /* 1, 1, 1, 1, 5, 5, 5, 5 - 1h */ | |
| 6329 | RSP_VNOR(0, 2, 3, 4, 6, 7, 1, 5, 1, 1, 1, 5, 5, 5, 1, 5); | |
| 6330 | break; | |
| 6331 | case 6: /* 0, 1, 3, 4, 5, 7, 2, 6 - 2h */ /* 2, 2, 2, 2, 6, 6, 6, 6 - 2h */ | |
| 6332 | RSP_VNOR(0, 1, 3, 4, 5, 7, 2, 6, 2, 2, 2, 6, 6, 6, 2, 6); | |
| 6333 | break; | |
| 6334 | case 7: /* 0, 1, 2, 4, 5, 6, 3, 7 - 3h */ /* 3, 3, 3, 3, 7, 7, 7, 7 - 3h */ | |
| 6335 | RSP_VNOR(0, 1, 2, 4, 5, 6, 3, 7, 3, 3, 3, 7, 7, 7, 3, 7); | |
| 6336 | break; | |
| 6337 | case 8: /* 1, 2, 3, 4, 5, 6, 7, 0 - 0 */ /* 0, 0, 0, 0, 0, 0, 0, 0 - 0 */ | |
| 6338 | RSP_VNOR(1, 2, 3, 4, 5, 6, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0); | |
| 6339 | break; | |
| 6340 | case 9: /* 0, 2, 3, 4, 5, 6, 7, 1 - 1 */ /* 1, 1, 1, 1, 1, 1, 1, 1 - 0 */ | |
| 6341 | RSP_VNOR(0, 2, 3, 4, 5, 6, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1); | |
| 6342 | break; | |
| 6343 | case 10:/* 0, 1, 3, 4, 5, 6, 7, 2 - 2 */ /* 2, 2, 2, 2, 2, 2, 2, 2 - 0 */ | |
| 6344 | RSP_VNOR(0, 1, 3, 4, 5, 6, 7, 2, 2, 2, 2, 2, 2, 2, 2, 2); | |
| 6345 | break; | |
| 6346 | case 11:/* 0, 1, 2, 4, 5, 6, 7, 3 - 3 */ /* 3, 3, 3, 3, 3, 3, 3, 3 - 0 */ | |
| 6347 | RSP_VNOR(0, 1, 2, 4, 5, 6, 7, 3, 3, 3, 3, 3, 3, 3, 3, 3); | |
| 6348 | break; | |
| 6349 | case 12:/* 0, 1, 2, 3, 5, 6, 7, 4 - 4 */ /* 4, 4, 4, 4, 4, 4, 4, 4 - 0 */ | |
| 6350 | RSP_VNOR(0, 1, 2, 3, 5, 6, 7, 4, 4, 4, 4, 4, 4, 4, 4, 4); | |
| 6351 | break; | |
| 6352 | case 13:/* 0, 1, 2, 3, 4, 6, 7, 5 - 5 */ /* 5, 5, 5, 5, 5, 5, 5, 5 - 0 */ | |
| 6353 | RSP_VNOR(0, 1, 2, 3, 4, 6, 7, 5, 5, 5, 5, 5, 5, 5, 5, 5); | |
| 6354 | break; | |
| 6355 | case 14:/* 0, 1, 2, 3, 4, 5, 7, 6 - 6 */ /* 6, 6, 6, 6, 6, 6, 6, 6 - 0 */ | |
| 6356 | RSP_VNOR(0, 1, 2, 3, 4, 5, 7, 6, 6, 6, 6, 6, 6, 6, 6, 6); | |
| 6357 | break; | |
| 6358 | case 15:/* 0, 1, 2, 3, 4, 5, 6, 7 - 7 */ /* 7, 7, 7, 7, 7, 7, 7, 7 - 0 */ | |
| 6359 | RSP_VNOR(0, 1, 2, 3, 4, 5, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7); | |
| 6360 | break; | |
| 2986 | sel = VEC_EL_2(EL, i); | |
| 2987 | vres[i] = ~((VREG_S(VS1REG, i) | VREG_S(VS2REG, sel))); | |
| 2988 | ACCUM_L(i) = vres[i]; | |
| 6361 | 2989 | } |
| 6362 | 2990 | WRITEBACK_RESULT(); |
| 6363 | 2991 | } |
| 6364 | #endif | |
| 6365 | 2992 | |
| 6366 | #if (DRC_VXOR) | |
| 6367 | #define RSP_VXOR_DRC(E10, E11, E12, E13, E14, E15, E16, E17, E20, E21, E22, E23, E24, E25, E26, E27, I0, I1, I2, I3, I4, I5, I6, I7) \ | |
| 6368 | { \ | |
| 6369 | UML_SEXT(block, IREG(0), VS(VS1REG, I0), WORD); \ | |
| 6370 | UML_SEXT(block, IREG(1), VS(VS2REG, E20), WORD); \ | |
| 6371 | UML_XOR(block, IREG(0), IREG(0), IREG(1)); \ | |
| 6372 | UML_STORE(block, &rsp->accum[E10].h.low, IMM(0), IREG(0), WORD); \ | |
| 6373 | \ | |
| 6374 | UML_SEXT(block, IREG(0), VS(VS1REG, I1), WORD); \ | |
| 6375 | UML_SEXT(block, IREG(1), VS(VS2REG, E21), WORD); \ | |
| 6376 | UML_XOR(block, IREG(0), IREG(0), IREG(1)); \ | |
| 6377 | UML_STORE(block, &rsp->accum[E11].h.low, IMM(0), IREG(0), WORD); \ | |
| 6378 | \ | |
| 6379 | UML_SEXT(block, IREG(0), VS(VS1REG, I2), WORD); \ | |
| 6380 | UML_SEXT(block, IREG(1), VS(VS2REG, E22), WORD); \ | |
| 6381 | UML_XOR(block, IREG(0), IREG(0), IREG(1)); \ | |
| 6382 | UML_STORE(block, &rsp->accum[E12].h.low, IMM(0), IREG(0), WORD); \ | |
| 6383 | \ | |
| 6384 | UML_SEXT(block, IREG(0), VS(VS1REG, I3), WORD); \ | |
| 6385 | UML_SEXT(block, IREG(1), VS(VS2REG, E23), WORD); \ | |
| 6386 | UML_XOR(block, IREG(0), IREG(0), IREG(1)); \ | |
| 6387 | UML_STORE(block, &rsp->accum[E13].h.low, IMM(0), IREG(0), WORD); \ | |
| 6388 | \ | |
| 6389 | UML_SEXT(block, IREG(0), VS(VS1REG, I4), WORD); \ | |
| 6390 | UML_SEXT(block, IREG(1), VS(VS2REG, E24), WORD); \ | |
| 6391 | UML_XOR(block, IREG(0), IREG(0), IREG(1)); \ | |
| 6392 | UML_STORE(block, &rsp->accum[E14].h.low, IMM(0), IREG(0), WORD); \ | |
| 6393 | \ | |
| 6394 | UML_SEXT(block, IREG(0), VS(VS1REG, I5), WORD); \ | |
| 6395 | UML_SEXT(block, IREG(1), VS(VS2REG, E25), WORD); \ | |
| 6396 | UML_XOR(block, IREG(0), IREG(0), IREG(1)); \ | |
| 6397 | UML_STORE(block, &rsp->accum[E15].h.low, IMM(0), IREG(0), WORD); \ | |
| 6398 | \ | |
| 6399 | UML_SEXT(block, IREG(0), VS(VS1REG, I6), WORD); \ | |
| 6400 | UML_SEXT(block, IREG(1), VS(VS2REG, E26), WORD); \ | |
| 6401 | UML_XOR(block, IREG(0), IREG(0), IREG(1)); \ | |
| 6402 | UML_STORE(block, &rsp->accum[E16].h.low, IMM(0), IREG(0), WORD); \ | |
| 6403 | \ | |
| 6404 | UML_SEXT(block, IREG(0), VS(VS1REG, I7), WORD); \ | |
| 6405 | UML_SEXT(block, IREG(1), VS(VS2REG, E27), WORD); \ | |
| 6406 | UML_XOR(block, IREG(0), IREG(0), IREG(1)); \ | |
| 6407 | UML_STORE(block, &rsp->accum[E17].h.low, IMM(0), IREG(0), WORD); \ | |
| 6408 | \ | |
| 6409 | UML_LOAD(block, IREG(0), &rsp->accum[E10].h.low, IMM(0), WORD); \ | |
| 6410 | UML_STORE(block, &rsp->v[VDREG].s[I0], IMM(0), IREG(0), WORD); \ | |
| 6411 | UML_LOAD(block, IREG(0), &rsp->accum[E11].h.low, IMM(0), WORD); \ | |
| 6412 | UML_STORE(block, &rsp->v[VDREG].s[I1], IMM(0), IREG(0), WORD); \ | |
| 6413 | UML_LOAD(block, IREG(0), &rsp->accum[E12].h.low, IMM(0), WORD); \ | |
| 6414 | UML_STORE(block, &rsp->v[VDREG].s[I2], IMM(0), IREG(0), WORD); \ | |
| 6415 | UML_LOAD(block, IREG(0), &rsp->accum[E13].h.low, IMM(0), WORD); \ | |
| 6416 | UML_STORE(block, &rsp->v[VDREG].s[I3], IMM(0), IREG(0), WORD); \ | |
| 6417 | UML_LOAD(block, IREG(0), &rsp->accum[E14].h.low, IMM(0), WORD); \ | |
| 6418 | UML_STORE(block, &rsp->v[VDREG].s[I4], IMM(0), IREG(0), WORD); \ | |
| 6419 | UML_LOAD(block, IREG(0), &rsp->accum[E15].h.low, IMM(0), WORD); \ | |
| 6420 | UML_STORE(block, &rsp->v[VDREG].s[I5], IMM(0), IREG(0), WORD); \ | |
| 6421 | UML_LOAD(block, IREG(0), &rsp->accum[E16].h.low, IMM(0), WORD); \ | |
| 6422 | UML_STORE(block, &rsp->v[VDREG].s[I6], IMM(0), IREG(0), WORD); \ | |
| 6423 | UML_LOAD(block, IREG(0), &rsp->accum[E17].h.low, IMM(0), WORD); \ | |
| 6424 | UML_STORE(block, &rsp->v[VDREG].s[I7], IMM(0), IREG(0), WORD); \ | |
| 6425 | } | |
| 6426 | ||
| 6427 | static int generate_vxor(rsp_state *rsp, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) | |
| 6428 | { | |
| 6429 | UINT32 op = desc->opptr.l[0]; | |
| 6430 | ||
| 6431 | // 31 25 24 20 15 10 5 0 | |
| 6432 | // ------------------------------------------------------ | |
| 6433 | // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 101000 | | |
| 6434 | // ------------------------------------------------------ | |
| 6435 | // | |
| 6436 | // Bitwise XOR of two vector registers | |
| 6437 | ||
| 6438 | switch(EL) | |
| 6439 | { | |
| 6440 | case 0: /* 0, 1, 2, 3, 4, 5, 6, 7 - none */ /* 0, 1, 2, 3, 4, 5, 6, 7 - none */ | |
| 6441 | RSP_VXOR_DRC(0, 1, 2, 3, 4, 5, 6, 7, 7, 6, 5, 4, 3, 2, 1, 0, 7, 6, 5, 4, 3, 2, 1, 0); | |
| 6442 | return TRUE; | |
| 6443 | case 1: /* 0, 1, 2, 3, 4, 5, 6, 7 - ??? */ /* 0, 1, 2, 3, 4, 5, 6, 7 - ??? */ | |
| 6444 | RSP_VXOR_DRC(0, 1, 2, 3, 4, 5, 6, 7, 7, 6, 5, 4, 3, 2, 1, 0, 7, 6, 5, 4, 3, 2, 1, 0); | |
| 6445 | return TRUE; | |
| 6446 | case 2: /* 1, 3, 5, 7, 0, 2, 4, 6 - 0q */ /* 0, 0, 2, 2, 4, 4, 6, 6 - 0q */ | |
| 6447 | RSP_VXOR_DRC(1, 3, 5, 7, 0, 2, 4, 6, 7, 5, 3, 1, 7, 5, 3, 1, 6, 4, 2, 0, 7, 5, 3, 1); | |
| 6448 | return TRUE; | |
| 6449 | case 3: /* 0, 2, 4, 6, 1, 3, 5, 7 - 1q */ /* 1, 1, 3, 3, 5, 5, 7, 7 - 1q */ | |
| 6450 | RSP_VXOR_DRC(0, 2, 4, 6, 1, 3, 5, 7, 6, 4, 2, 0, 6, 4, 2, 0, 7, 5, 3, 1, 6, 4, 2, 0); | |
| 6451 | return TRUE; | |
| 6452 | case 4: /* 1, 2, 3, 5, 6, 7, 0, 4 - 0h */ /* 0, 0, 0, 0, 4, 4, 4, 4 - 0h */ | |
| 6453 | RSP_VXOR_DRC(1, 2, 3, 5, 6, 7, 0, 4, 7, 7, 7, 3, 3, 3, 7, 3, 6, 5, 4, 2, 1, 0, 7, 3); | |
| 6454 | return TRUE; | |
| 6455 | case 5: /* 0, 2, 3, 4, 6, 7, 1, 5 - 1h */ /* 1, 1, 1, 1, 5, 5, 5, 5 - 1h */ | |
| 6456 | RSP_VXOR_DRC(0, 2, 3, 4, 6, 7, 1, 5, 6, 6, 6, 2, 2, 2, 6, 2, 7, 5, 4, 3, 1, 0, 6, 2); | |
| 6457 | return TRUE; | |
| 6458 | case 6: /* 0, 1, 3, 4, 5, 7, 2, 6 - 2h */ /* 2, 2, 2, 2, 6, 6, 6, 6 - 2h */ | |
| 6459 | RSP_VXOR_DRC(0, 1, 3, 4, 5, 7, 2, 6, 5, 5, 5, 1, 1, 1, 5, 1, 7, 6, 4, 3, 2, 0, 5, 1); | |
| 6460 | return TRUE; | |
| 6461 | case 7: /* 0, 1, 2, 4, 5, 6, 3, 7 - 3h */ /* 3, 3, 3, 3, 7, 7, 7, 7 - 3h */ | |
| 6462 | RSP_VXOR_DRC(0, 1, 2, 4, 5, 6, 3, 7, 4, 4, 4, 0, 0, 0, 4, 0, 7, 6, 5, 3, 2, 1, 4, 0); | |
| 6463 | return TRUE; | |
| 6464 | case 8: /* 1, 2, 3, 4, 5, 6, 7, 0 - 0 */ /* 0, 0, 0, 0, 0, 0, 0, 0 - 0 */ | |
| 6465 | RSP_VXOR_DRC(1, 2, 3, 4, 5, 6, 7, 0, 7, 7, 7, 7, 7, 7, 7, 7, 6, 5, 4, 3, 2, 1, 0, 7); | |
| 6466 | return TRUE; | |
| 6467 | case 9: /* 0, 2, 3, 4, 5, 6, 7, 1 - 1 */ /* 1, 1, 1, 1, 1, 1, 1, 1 - 0 */ | |
| 6468 | RSP_VXOR_DRC(0, 2, 3, 4, 5, 6, 7, 1, 6, 6, 6, 6, 6, 6, 6, 6, 7, 5, 4, 3, 2, 1, 0, 6); | |
| 6469 | return TRUE; | |
| 6470 | case 10: /* 0, 1, 3, 4, 5, 6, 7, 2 - 2 */ /* 2, 2, 2, 2, 2, 2, 2, 2 - 0 */ | |
| 6471 | RSP_VXOR_DRC(0, 1, 3, 4, 5, 6, 7, 2, 5, 5, 5, 5, 5, 5, 5, 5, 7, 6, 4, 3, 2, 1, 0, 5); | |
| 6472 | return TRUE; | |
| 6473 | case 11: /* 0, 1, 2, 4, 5, 6, 7, 3 - 3 */ /* 3, 3, 3, 3, 3, 3, 3, 3 - 0 */ | |
| 6474 | RSP_VXOR_DRC(0, 1, 2, 4, 5, 6, 7, 3, 4, 4, 4, 4, 4, 4, 4, 4, 7, 6, 5, 3, 2, 1, 0, 4); | |
| 6475 | return TRUE; | |
| 6476 | case 12: /* 0, 1, 2, 3, 5, 6, 7, 4 - 4 */ /* 4, 4, 4, 4, 4, 4, 4, 4 - 0 */ | |
| 6477 | RSP_VXOR_DRC(0, 1, 2, 3, 5, 6, 7, 4, 3, 3, 3, 3, 3, 3, 3, 3, 7, 6, 5, 4, 2, 1, 0, 3); | |
| 6478 | return TRUE; | |
| 6479 | case 13: /* 0, 1, 2, 3, 4, 6, 7, 5 - 5 */ /* 5, 5, 5, 5, 5, 5, 5, 5 - 0 */ | |
| 6480 | RSP_VXOR_DRC(0, 1, 2, 3, 4, 6, 7, 5, 2, 2, 2, 2, 2, 2, 2, 2, 7, 6, 5, 4, 3, 1, 0, 2); | |
| 6481 | return TRUE; | |
| 6482 | case 14: /* 0, 1, 2, 3, 4, 5, 7, 6 - 6 */ /* 6, 6, 6, 6, 6, 6, 6, 6 - 0 */ | |
| 6483 | RSP_VXOR_DRC(0, 1, 2, 3, 4, 5, 7, 6, 1, 1, 1, 1, 1, 1, 1, 1, 7, 6, 5, 4, 3, 2, 0, 1); | |
| 6484 | return TRUE; | |
| 6485 | case 15: /* 0, 1, 2, 3, 4, 5, 6, 7 - 7 */ /* 7, 7, 7, 7, 7, 7, 7, 7 - 0 */ | |
| 6486 | RSP_VXOR_DRC(0, 1, 2, 3, 4, 5, 6, 7, 0, 0, 0, 0, 0, 0, 0, 0, 7, 6, 5, 4, 3, 2, 1, 0); | |
| 6487 | return TRUE; | |
| 6488 | } | |
| 6489 | ||
| 6490 | return TRUE; | |
| 6491 | } | |
| 6492 | #else | |
| 6493 | #define RSP_VXOR(E10, E11, E12, E13, E14, E15, E16, E17, E20, E21, E22, E23, E24, E25, E26, E27) \ | |
| 6494 | vres[E10] = R_VREG_S(VS1REG, E10) ^ R_VREG_S(VS2REG, E20); \ | |
| 6495 | vres[E11] = R_VREG_S(VS1REG, E11) ^ R_VREG_S(VS2REG, E21); \ | |
| 6496 | vres[E12] = R_VREG_S(VS1REG, E12) ^ R_VREG_S(VS2REG, E22); \ | |
| 6497 | vres[E13] = R_VREG_S(VS1REG, E13) ^ R_VREG_S(VS2REG, E23); \ | |
| 6498 | vres[E14] = R_VREG_S(VS1REG, E14) ^ R_VREG_S(VS2REG, E24); \ | |
| 6499 | vres[E15] = R_VREG_S(VS1REG, E15) ^ R_VREG_S(VS2REG, E25); \ | |
| 6500 | vres[E16] = R_VREG_S(VS1REG, E16) ^ R_VREG_S(VS2REG, E26); \ | |
| 6501 | vres[E17] = R_VREG_S(VS1REG, E17) ^ R_VREG_S(VS2REG, E27); \ | |
| 6502 | W_ACCUM_L(E10, vres[E10]); \ | |
| 6503 | W_ACCUM_L(E11, vres[E11]); \ | |
| 6504 | W_ACCUM_L(E12, vres[E12]); \ | |
| 6505 | W_ACCUM_L(E13, vres[E13]); \ | |
| 6506 | W_ACCUM_L(E14, vres[E14]); \ | |
| 6507 | W_ACCUM_L(E15, vres[E15]); \ | |
| 6508 | W_ACCUM_L(E16, vres[E16]); \ | |
| 6509 | W_ACCUM_L(E17, vres[E17]); \ | |
| 6510 | ||
| 6511 | 2993 | INLINE void cfunc_rsp_vxor(void *param) |
| 6512 | 2994 | { |
| 6513 | 2995 | rsp_state *rsp = (rsp_state*)param; |
| r9854 | r9855 | |
| 6520 | 3002 | // |
| 6521 | 3003 | // Bitwise XOR of two vector registers |
| 6522 | 3004 | |
| 6523 | switch(EL) | |
| 3005 | int sel; | |
| 3006 | for (int i = 0; i < 8; i++) | |
| 6524 | 3007 | { |
| 6525 | case 0: /* 0, 1, 2, 3, 4, 5, 6, 7 - none */ /* 0, 1, 2, 3, 4, 5, 6, 7 - none */ | |
| 6526 | RSP_VXOR(0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7); | |
| 6527 | break; | |
| 6528 | case 1: /* 0, 1, 2, 3, 4, 5, 6, 7 - ??? */ /* 0, 1, 2, 3, 4, 5, 6, 7 - ??? */ | |
| 6529 | RSP_VXOR(0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7); | |
| 6530 | break; | |
| 6531 | case 2: /* 1, 3, 5, 7, 0, 2, 4, 6 - 0q */ /* 0, 0, 2, 2, 4, 4, 6, 6 - 0q */ | |
| 6532 | RSP_VXOR(1, 3, 5, 7, 0, 2, 4, 6, 0, 2, 4, 6, 0, 2, 4, 6); | |
| 6533 | break; | |
| 6534 | case 3: /* 0, 2, 4, 6, 1, 3, 5, 7 - 1q */ /* 1, 1, 3, 3, 5, 5, 7, 7 - 1q */ | |
| 6535 | RSP_VXOR(0, 2, 4, 6, 1, 3, 5, 7, 1, 3, 5, 7, 1, 3, 5, 7); | |
| 6536 | break; | |
| 6537 | case 4: /* 1, 2, 3, 5, 6, 7, 0, 4 - 0h */ /* 0, 0, 0, 0, 4, 4, 4, 4 - 0h */ | |
| 6538 | RSP_VXOR(1, 2, 3, 5, 6, 7, 0, 4, 0, 0, 0, 4, 4, 4, 0, 4); | |
| 6539 | break; | |
| 6540 | case 5: /* 0, 2, 3, 4, 6, 7, 1, 5 - 1h */ /* 1, 1, 1, 1, 5, 5, 5, 5 - 1h */ | |
| 6541 | RSP_VXOR(0, 2, 3, 4, 6, 7, 1, 5, 1, 1, 1, 5, 5, 5, 1, 5); | |
| 6542 | break; | |
| 6543 | case 6: /* 0, 1, 3, 4, 5, 7, 2, 6 - 2h */ /* 2, 2, 2, 2, 6, 6, 6, 6 - 2h */ | |
| 6544 | RSP_VXOR(0, 1, 3, 4, 5, 7, 2, 6, 2, 2, 2, 6, 6, 6, 2, 6); | |
| 6545 | break; | |
| 6546 | case 7: /* 0, 1, 2, 4, 5, 6, 3, 7 - 3h */ /* 3, 3, 3, 3, 7, 7, 7, 7 - 3h */ | |
| 6547 | RSP_VXOR(0, 1, 2, 4, 5, 6, 3, 7, 3, 3, 3, 7, 7, 7, 3, 7); | |
| 6548 | break; | |
| 6549 | case 8: /* 1, 2, 3, 4, 5, 6, 7, 0 - 0 */ /* 0, 0, 0, 0, 0, 0, 0, 0 - 0 */ | |
| 6550 | RSP_VXOR(1, 2, 3, 4, 5, 6, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0); | |
| 6551 | break; | |
| 6552 | case 9: /* 0, 2, 3, 4, 5, 6, 7, 1 - 1 */ /* 1, 1, 1, 1, 1, 1, 1, 1 - 0 */ | |
| 6553 | RSP_VXOR(0, 2, 3, 4, 5, 6, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1); | |
| 6554 | break; | |
| 6555 | case 10:/* 0, 1, 3, 4, 5, 6, 7, 2 - 2 */ /* 2, 2, 2, 2, 2, 2, 2, 2 - 0 */ | |
| 6556 | RSP_VXOR(0, 1, 3, 4, 5, 6, 7, 2, 2, 2, 2, 2, 2, 2, 2, 2); | |
| 6557 | break; | |
| 6558 | case 11:/* 0, 1, 2, 4, 5, 6, 7, 3 - 3 */ /* 3, 3, 3, 3, 3, 3, 3, 3 - 0 */ | |
| 6559 | RSP_VXOR(0, 1, 2, 4, 5, 6, 7, 3, 3, 3, 3, 3, 3, 3, 3, 3); | |
| 6560 | break; | |
| 6561 | case 12:/* 0, 1, 2, 3, 5, 6, 7, 4 - 4 */ /* 4, 4, 4, 4, 4, 4, 4, 4 - 0 */ | |
| 6562 | RSP_VXOR(0, 1, 2, 3, 5, 6, 7, 4, 4, 4, 4, 4, 4, 4, 4, 4); | |
| 6563 | break; | |
| 6564 | case 13:/* 0, 1, 2, 3, 4, 6, 7, 5 - 5 */ /* 5, 5, 5, 5, 5, 5, 5, 5 - 0 */ | |
| 6565 | RSP_VXOR(0, 1, 2, 3, 4, 6, 7, 5, 5, 5, 5, 5, 5, 5, 5, 5); | |
| 6566 | break; | |
| 6567 | case 14:/* 0, 1, 2, 3, 4, 5, 7, 6 - 6 */ /* 6, 6, 6, 6, 6, 6, 6, 6 - 0 */ | |
| 6568 | RSP_VXOR(0, 1, 2, 3, 4, 5, 7, 6, 6, 6, 6, 6, 6, 6, 6, 6); | |
| 6569 | break; | |
| 6570 | case 15:/* 0, 1, 2, 3, 4, 5, 6, 7 - 7 */ /* 7, 7, 7, 7, 7, 7, 7, 7 - 0 */ | |
| 6571 | RSP_VXOR(0, 1, 2, 3, 4, 5, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7); | |
| 6572 | break; | |
| 3008 | sel = VEC_EL_2(EL, i); | |
| 3009 | vres[i] = VREG_S(VS1REG, i) ^ VREG_S(VS2REG, sel); | |
| 3010 | ACCUM_L(i) = vres[i]; | |
| 6573 | 3011 | } |
| 6574 | 3012 | WRITEBACK_RESULT(); |
| 6575 | 3013 | } |
| 6576 | #endif | |
| 6577 | 3014 | |
| 6578 | #if (DRC_VNXOR) | |
| 6579 | #define RSP_VNXOR_DRC(E10, E11, E12, E13, E14, E15, E16, E17, E20, E21, E22, E23, E24, E25, E26, E27, I0, I1, I2, I3, I4, I5, I6, I7) \ | |
| 6580 | { \ | |
| 6581 | UML_SEXT(block, IREG(0), VS(VS1REG, I0), WORD); \ | |
| 6582 | UML_SEXT(block, IREG(1), VS(VS2REG, E20), WORD); \ | |
| 6583 | UML_XOR(block, IREG(0), IREG(0), IREG(1)); \ | |
| 6584 | UML_XOR(block, IREG(0), IREG(0), IMM(0xffffffff)); \ | |
| 6585 | UML_STORE(block, &rsp->accum[E10].h.low, IMM(0), IREG(0), WORD); \ | |
| 6586 | \ | |
| 6587 | UML_SEXT(block, IREG(0), VS(VS1REG, I1), WORD); \ | |
| 6588 | UML_SEXT(block, IREG(1), VS(VS2REG, E21), WORD); \ | |
| 6589 | UML_XOR(block, IREG(0), IREG(0), IREG(1)); \ | |
| 6590 | UML_XOR(block, IREG(0), IREG(0), IMM(0xffffffff)); \ | |
| 6591 | UML_STORE(block, &rsp->accum[E11].h.low, IMM(0), IREG(0), WORD); \ | |
| 6592 | \ | |
| 6593 | UML_SEXT(block, IREG(0), VS(VS1REG, I2), WORD); \ | |
| 6594 | UML_SEXT(block, IREG(1), VS(VS2REG, E22), WORD); \ | |
| 6595 | UML_XOR(block, IREG(0), IREG(0), IREG(1)); \ | |
| 6596 | UML_XOR(block, IREG(0), IREG(0), IMM(0xffffffff)); \ | |
| 6597 | UML_STORE(block, &rsp->accum[E12].h.low, IMM(0), IREG(0), WORD); \ | |
| 6598 | \ | |
| 6599 | UML_SEXT(block, IREG(0), VS(VS1REG, I3), WORD); \ | |
| 6600 | UML_SEXT(block, IREG(1), VS(VS2REG, E23), WORD); \ | |
| 6601 | UML_XOR(block, IREG(0), IREG(0), IREG(1)); \ | |
| 6602 | UML_XOR(block, IREG(0), IREG(0), IMM(0xffffffff)); \ | |
| 6603 | UML_STORE(block, &rsp->accum[E13].h.low, IMM(0), IREG(0), WORD); \ | |
| 6604 | \ | |
| 6605 | UML_SEXT(block, IREG(0), VS(VS1REG, I4), WORD); \ | |
| 6606 | UML_SEXT(block, IREG(1), VS(VS2REG, E24), WORD); \ | |
| 6607 | UML_XOR(block, IREG(0), IREG(0), IREG(1)); \ | |
| 6608 | UML_XOR(block, IREG(0), IREG(0), IMM(0xffffffff)); \ | |
| 6609 | UML_STORE(block, &rsp->accum[E14].h.low, IMM(0), IREG(0), WORD); \ | |
| 6610 | \ | |
| 6611 | UML_SEXT(block, IREG(0), VS(VS1REG, I5), WORD); \ | |
| 6612 | UML_SEXT(block, IREG(1), VS(VS2REG, E25), WORD); \ | |
| 6613 | UML_XOR(block, IREG(0), IREG(0), IREG(1)); \ | |
| 6614 | UML_XOR(block, IREG(0), IREG(0), IMM(0xffffffff)); \ | |
| 6615 | UML_STORE(block, &rsp->accum[E15].h.low, IMM(0), IREG(0), WORD); \ | |
| 6616 | \ | |
| 6617 | UML_SEXT(block, IREG(0), VS(VS1REG, I6), WORD); \ | |
| 6618 | UML_SEXT(block, IREG(1), VS(VS2REG, E26), WORD); \ | |
| 6619 | UML_XOR(block, IREG(0), IREG(0), IREG(1)); \ | |
| 6620 | UML_XOR(block, IREG(0), IREG(0), IMM(0xffffffff)); \ | |
| 6621 | UML_STORE(block, &rsp->accum[E16].h.low, IMM(0), IREG(0), WORD); \ | |
| 6622 | \ | |
| 6623 | UML_SEXT(block, IREG(0), VS(VS1REG, I7), WORD); \ | |
| 6624 | UML_SEXT(block, IREG(1), VS(VS2REG, E27), WORD); \ | |
| 6625 | UML_XOR(block, IREG(0), IREG(0), IREG(1)); \ | |
| 6626 | UML_XOR(block, IREG(0), IREG(0), IMM(0xffffffff)); \ | |
| 6627 | UML_STORE(block, &rsp->accum[E17].h.low, IMM(0), IREG(0), WORD); \ | |
| 6628 | \ | |
| 6629 | UML_LOAD(block, IREG(0), &rsp->accum[E10].h.low, IMM(0), WORD); \ | |
| 6630 | UML_STORE(block, &rsp->v[VDREG].s[I0], IMM(0), IREG(0), WORD); \ | |
| 6631 | UML_LOAD(block, IREG(0), &rsp->accum[E11].h.low, IMM(0), WORD); \ | |
| 6632 | UML_STORE(block, &rsp->v[VDREG].s[I1], IMM(0), IREG(0), WORD); \ | |
| 6633 | UML_LOAD(block, IREG(0), &rsp->accum[E12].h.low, IMM(0), WORD); \ | |
| 6634 | UML_STORE(block, &rsp->v[VDREG].s[I2], IMM(0), IREG(0), WORD); \ | |
| 6635 | UML_LOAD(block, IREG(0), &rsp->accum[E13].h.low, IMM(0), WORD); \ | |
| 6636 | UML_STORE(block, &rsp->v[VDREG].s[I3], IMM(0), IREG(0), WORD); \ | |
| 6637 | UML_LOAD(block, IREG(0), &rsp->accum[E14].h.low, IMM(0), WORD); \ | |
| 6638 | UML_STORE(block, &rsp->v[VDREG].s[I4], IMM(0), IREG(0), WORD); \ | |
| 6639 | UML_LOAD(block, IREG(0), &rsp->accum[E15].h.low, IMM(0), WORD); \ | |
| 6640 | UML_STORE(block, &rsp->v[VDREG].s[I5], IMM(0), IREG(0), WORD); \ | |
| 6641 | UML_LOAD(block, IREG(0), &rsp->accum[E16].h.low, IMM(0), WORD); \ | |
| 6642 | UML_STORE(block, &rsp->v[VDREG].s[I6], IMM(0), IREG(0), WORD); \ | |
| 6643 | UML_LOAD(block, IREG(0), &rsp->accum[E17].h.low, IMM(0), WORD); \ | |
| 6644 | UML_STORE(block, &rsp->v[VDREG].s[I7], IMM(0), IREG(0), WORD); \ | |
| 6645 | } | |
| 6646 | ||
| 6647 | static int generate_vnxor(rsp_state *rsp, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) | |
| 6648 | { | |
| 6649 | UINT32 op = desc->opptr.l[0]; | |
| 6650 | ||
| 6651 | // 31 25 24 20 15 10 5 0 | |
| 6652 | // ------------------------------------------------------ | |
| 6653 | // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 101000 | | |
| 6654 | // ------------------------------------------------------ | |
| 6655 | // | |
| 6656 | // Bitwise NOT XOR of two vector registers | |
| 6657 | ||
| 6658 | switch(EL) | |
| 6659 | { | |
| 6660 | case 0: /* 0, 1, 2, 3, 4, 5, 6, 7 - none */ /* 0, 1, 2, 3, 4, 5, 6, 7 - none */ | |
| 6661 | RSP_VNXOR_DRC(0, 1, 2, 3, 4, 5, 6, 7, 7, 6, 5, 4, 3, 2, 1, 0, 7, 6, 5, 4, 3, 2, 1, 0); | |
| 6662 | return TRUE; | |
| 6663 | case 1: /* 0, 1, 2, 3, 4, 5, 6, 7 - ??? */ /* 0, 1, 2, 3, 4, 5, 6, 7 - ??? */ | |
| 6664 | RSP_VNXOR_DRC(0, 1, 2, 3, 4, 5, 6, 7, 7, 6, 5, 4, 3, 2, 1, 0, 7, 6, 5, 4, 3, 2, 1, 0); | |
| 6665 | return TRUE; | |
| 6666 | case 2: /* 1, 3, 5, 7, 0, 2, 4, 6 - 0q */ /* 0, 0, 2, 2, 4, 4, 6, 6 - 0q */ | |
| 6667 | RSP_VNXOR_DRC(1, 3, 5, 7, 0, 2, 4, 6, 7, 5, 3, 1, 7, 5, 3, 1, 6, 4, 2, 0, 7, 5, 3, 1); | |
| 6668 | return TRUE; | |
| 6669 | case 3: /* 0, 2, 4, 6, 1, 3, 5, 7 - 1q */ /* 1, 1, 3, 3, 5, 5, 7, 7 - 1q */ | |
| 6670 | RSP_VNXOR_DRC(0, 2, 4, 6, 1, 3, 5, 7, 6, 4, 2, 0, 6, 4, 2, 0, 7, 5, 3, 1, 6, 4, 2, 0); | |
| 6671 | return TRUE; | |
| 6672 | case 4: /* 1, 2, 3, 5, 6, 7, 0, 4 - 0h */ /* 0, 0, 0, 0, 4, 4, 4, 4 - 0h */ | |
| 6673 | RSP_VNXOR_DRC(1, 2, 3, 5, 6, 7, 0, 4, 7, 7, 7, 3, 3, 3, 7, 3, 6, 5, 4, 2, 1, 0, 7, 3); | |
| 6674 | return TRUE; | |
| 6675 | case 5: /* 0, 2, 3, 4, 6, 7, 1, 5 - 1h */ /* 1, 1, 1, 1, 5, 5, 5, 5 - 1h */ | |
| 6676 | RSP_VNXOR_DRC(0, 2, 3, 4, 6, 7, 1, 5, 6, 6, 6, 2, 2, 2, 6, 2, 7, 5, 4, 3, 1, 0, 6, 2); | |
| 6677 | return TRUE; | |
| 6678 | case 6: /* 0, 1, 3, 4, 5, 7, 2, 6 - 2h */ /* 2, 2, 2, 2, 6, 6, 6, 6 - 2h */ | |
| 6679 | RSP_VNXOR_DRC(0, 1, 3, 4, 5, 7, 2, 6, 5, 5, 5, 1, 1, 1, 5, 1, 7, 6, 4, 3, 2, 0, 5, 1); | |
| 6680 | return TRUE; | |
| 6681 | case 7: /* 0, 1, 2, 4, 5, 6, 3, 7 - 3h */ /* 3, 3, 3, 3, 7, 7, 7, 7 - 3h */ | |
| 6682 | RSP_VNXOR_DRC(0, 1, 2, 4, 5, 6, 3, 7, 4, 4, 4, 0, 0, 0, 4, 0, 7, 6, 5, 3, 2, 1, 4, 0); | |
| 6683 | return TRUE; | |
| 6684 | case 8: /* 1, 2, 3, 4, 5, 6, 7, 0 - 0 */ /* 0, 0, 0, 0, 0, 0, 0, 0 - 0 */ | |
| 6685 | RSP_VNXOR_DRC(1, 2, 3, 4, 5, 6, 7, 0, 7, 7, 7, 7, 7, 7, 7, 7, 6, 5, 4, 3, 2, 1, 0, 7); | |
| 6686 | return TRUE; | |
| 6687 | case 9: /* 0, 2, 3, 4, 5, 6, 7, 1 - 1 */ /* 1, 1, 1, 1, 1, 1, 1, 1 - 0 */ | |
| 6688 | RSP_VNXOR_DRC(0, 2, 3, 4, 5, 6, 7, 1, 6, 6, 6, 6, 6, 6, 6, 6, 7, 5, 4, 3, 2, 1, 0, 6); | |
| 6689 | return TRUE; | |
| 6690 | case 10: /* 0, 1, 3, 4, 5, 6, 7, 2 - 2 */ /* 2, 2, 2, 2, 2, 2, 2, 2 - 0 */ | |
| 6691 | RSP_VNXOR_DRC(0, 1, 3, 4, 5, 6, 7, 2, 5, 5, 5, 5, 5, 5, 5, 5, 7, 6, 4, 3, 2, 1, 0, 5); | |
| 6692 | return TRUE; | |
| 6693 | case 11: /* 0, 1, 2, 4, 5, 6, 7, 3 - 3 */ /* 3, 3, 3, 3, 3, 3, 3, 3 - 0 */ | |
| 6694 | RSP_VNXOR_DRC(0, 1, 2, 4, 5, 6, 7, 3, 4, 4, 4, 4, 4, 4, 4, 4, 7, 6, 5, 3, 2, 1, 0, 4); | |
| 6695 | return TRUE; | |
| 6696 | case 12: /* 0, 1, 2, 3, 5, 6, 7, 4 - 4 */ /* 4, 4, 4, 4, 4, 4, 4, 4 - 0 */ | |
| 6697 | RSP_VNXOR_DRC(0, 1, 2, 3, 5, 6, 7, 4, 3, 3, 3, 3, 3, 3, 3, 3, 7, 6, 5, 4, 2, 1, 0, 3); | |
| 6698 | return TRUE; | |
| 6699 | case 13: /* 0, 1, 2, 3, 4, 6, 7, 5 - 5 */ /* 5, 5, 5, 5, 5, 5, 5, 5 - 0 */ | |
| 6700 | RSP_VNXOR_DRC(0, 1, 2, 3, 4, 6, 7, 5, 2, 2, 2, 2, 2, 2, 2, 2, 7, 6, 5, 4, 3, 1, 0, 2); | |
| 6701 | return TRUE; | |
| 6702 | case 14: /* 0, 1, 2, 3, 4, 5, 7, 6 - 6 */ /* 6, 6, 6, 6, 6, 6, 6, 6 - 0 */ | |
| 6703 | RSP_VNXOR_DRC(0, 1, 2, 3, 4, 5, 7, 6, 1, 1, 1, 1, 1, 1, 1, 1, 7, 6, 5, 4, 3, 2, 0, 1); | |
| 6704 | return TRUE; | |
| 6705 | case 15: /* 0, 1, 2, 3, 4, 5, 6, 7 - 7 */ /* 7, 7, 7, 7, 7, 7, 7, 7 - 0 */ | |
| 6706 | RSP_VNOR_DRC(0, 1, 2, 3, 4, 5, 6, 7, 0, 0, 0, 0, 0, 0, 0, 0, 7, 6, 5, 4, 3, 2, 1, 0); | |
| 6707 | return TRUE; | |
| 6708 | } | |
| 6709 | ||
| 6710 | return TRUE; | |
| 6711 | } | |
| 6712 | #else | |
| 6713 | #define RSP_VNXOR(E10, E11, E12, E13, E14, E15, E16, E17, E20, E21, E22, E23, E24, E25, E26, E27) \ | |
| 6714 | vres[E10] = ~(R_VREG_S(VS1REG, E10) ^ R_VREG_S(VS2REG, E20)); \ | |
| 6715 | vres[E11] = ~(R_VREG_S(VS1REG, E11) ^ R_VREG_S(VS2REG, E21)); \ | |
| 6716 | vres[E12] = ~(R_VREG_S(VS1REG, E12) ^ R_VREG_S(VS2REG, E22)); \ | |
| 6717 | vres[E13] = ~(R_VREG_S(VS1REG, E13) ^ R_VREG_S(VS2REG, E23)); \ | |
| 6718 | vres[E14] = ~(R_VREG_S(VS1REG, E14) ^ R_VREG_S(VS2REG, E24)); \ | |
| 6719 | vres[E15] = ~(R_VREG_S(VS1REG, E15) ^ R_VREG_S(VS2REG, E25)); \ | |
| 6720 | vres[E16] = ~(R_VREG_S(VS1REG, E16) ^ R_VREG_S(VS2REG, E26)); \ | |
| 6721 | vres[E17] = ~(R_VREG_S(VS1REG, E17) ^ R_VREG_S(VS2REG, E27)); \ | |
| 6722 | W_ACCUM_L(E10, vres[E10]); \ | |
| 6723 | W_ACCUM_L(E11, vres[E11]); \ | |
| 6724 | W_ACCUM_L(E12, vres[E12]); \ | |
| 6725 | W_ACCUM_L(E13, vres[E13]); \ | |
| 6726 | W_ACCUM_L(E14, vres[E14]); \ | |
| 6727 | W_ACCUM_L(E15, vres[E15]); \ | |
| 6728 | W_ACCUM_L(E16, vres[E16]); \ | |
| 6729 | W_ACCUM_L(E17, vres[E17]); \ | |
| 6730 | ||
| 6731 | 3015 | INLINE void cfunc_rsp_vnxor(void *param) |
| 6732 | 3016 | { |
| 6733 | 3017 | rsp_state *rsp = (rsp_state*)param; |
| r9854 | r9855 | |
| 6740 | 3024 | // |
| 6741 | 3025 | // Bitwise NOT XOR of two vector registers |
| 6742 | 3026 | |
| 6743 | switch(EL) | |
| 3027 | int sel; | |
| 3028 | for (int i = 0; i < 8; i++) | |
| 6744 | 3029 | { |
| 6745 | case 0: /* 0, 1, 2, 3, 4, 5, 6, 7 - none */ /* 0, 1, 2, 3, 4, 5, 6, 7 - none */ | |
| 6746 | RSP_VNXOR(0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7); | |
| 6747 | break; | |
| 6748 | case 1: /* 0, 1, 2, 3, 4, 5, 6, 7 - ??? */ /* 0, 1, 2, 3, 4, 5, 6, 7 - ??? */ | |
| 6749 | RSP_VNXOR(0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7); | |
| 6750 | break; | |
| 6751 | case 2: /* 1, 3, 5, 7, 0, 2, 4, 6 - 0q */ /* 0, 0, 2, 2, 4, 4, 6, 6 - 0q */ | |
| 6752 | RSP_VNXOR(1, 3, 5, 7, 0, 2, 4, 6, 0, 2, 4, 6, 0, 2, 4, 6); | |
| 6753 | break; | |
| 6754 | case 3: /* 0, 2, 4, 6, 1, 3, 5, 7 - 1q */ /* 1, 1, 3, 3, 5, 5, 7, 7 - 1q */ | |
| 6755 | RSP_VNXOR(0, 2, 4, 6, 1, 3, 5, 7, 1, 3, 5, 7, 1, 3, 5, 7); | |
| 6756 | break; | |
| 6757 | case 4: /* 1, 2, 3, 5, 6, 7, 0, 4 - 0h */ /* 0, 0, 0, 0, 4, 4, 4, 4 - 0h */ | |
| 6758 | RSP_VNXOR(1, 2, 3, 5, 6, 7, 0, 4, 0, 0, 0, 4, 4, 4, 0, 4); | |
| 6759 | break; | |
| 6760 | case 5: /* 0, 2, 3, 4, 6, 7, 1, 5 - 1h */ /* 1, 1, 1, 1, 5, 5, 5, 5 - 1h */ | |
| 6761 | RSP_VNXOR(0, 2, 3, 4, 6, 7, 1, 5, 1, 1, 1, 5, 5, 5, 1, 5); | |
| 6762 | break; | |
| 6763 | case 6: /* 0, 1, 3, 4, 5, 7, 2, 6 - 2h */ /* 2, 2, 2, 2, 6, 6, 6, 6 - 2h */ | |
| 6764 | RSP_VNXOR(0, 1, 3, 4, 5, 7, 2, 6, 2, 2, 2, 6, 6, 6, 2, 6); | |
| 6765 | break; | |
| 6766 | case 7: /* 0, 1, 2, 4, 5, 6, 3, 7 - 3h */ /* 3, 3, 3, 3, 7, 7, 7, 7 - 3h */ | |
| 6767 | RSP_VNXOR(0, 1, 2, 4, 5, 6, 3, 7, 3, 3, 3, 7, 7, 7, 3, 7); | |
| 6768 | break; | |
| 6769 | case 8: /* 1, 2, 3, 4, 5, 6, 7, 0 - 0 */ /* 0, 0, 0, 0, 0, 0, 0, 0 - 0 */ | |
| 6770 | RSP_VNXOR(1, 2, 3, 4, 5, 6, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0); | |
| 6771 | break; | |
| 6772 | case 9: /* 0, 2, 3, 4, 5, 6, 7, 1 - 1 */ /* 1, 1, 1, 1, 1, 1, 1, 1 - 0 */ | |
| 6773 | RSP_VNXOR(0, 2, 3, 4, 5, 6, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1); | |
| 6774 | break; | |
| 6775 | case 10:/* 0, 1, 3, 4, 5, 6, 7, 2 - 2 */ /* 2, 2, 2, 2, 2, 2, 2, 2 - 0 */ | |
| 6776 | RSP_VNXOR(0, 1, 3, 4, 5, 6, 7, 2, 2, 2, 2, 2, 2, 2, 2, 2); | |
| 6777 | break; | |
| 6778 | case 11:/* 0, 1, 2, 4, 5, 6, 7, 3 - 3 */ /* 3, 3, 3, 3, 3, 3, 3, 3 - 0 */ | |
| 6779 | RSP_VNXOR(0, 1, 2, 4, 5, 6, 7, 3, 3, 3, 3, 3, 3, 3, 3, 3); | |
| 6780 | break; | |
| 6781 | case 12:/* 0, 1, 2, 3, 5, 6, 7, 4 - 4 */ /* 4, 4, 4, 4, 4, 4, 4, 4 - 0 */ | |
| 6782 | RSP_VNXOR(0, 1, 2, 3, 5, 6, 7, 4, 4, 4, 4, 4, 4, 4, 4, 4); | |
| 6783 | break; | |
| 6784 | case 13:/* 0, 1, 2, 3, 4, 6, 7, 5 - 5 */ /* 5, 5, 5, 5, 5, 5, 5, 5 - 0 */ | |
| 6785 | RSP_VNXOR(0, 1, 2, 3, 4, 6, 7, 5, 5, 5, 5, 5, 5, 5, 5, 5); | |
| 6786 | break; | |
| 6787 | case 14:/* 0, 1, 2, 3, 4, 5, 7, 6 - 6 */ /* 6, 6, 6, 6, 6, 6, 6, 6 - 0 */ | |
| 6788 | RSP_VNXOR(0, 1, 2, 3, 4, 5, 7, 6, 6, 6, 6, 6, 6, 6, 6, 6); | |
| 6789 | break; | |
| 6790 | case 15:/* 0, 1, 2, 3, 4, 5, 6, 7 - 7 */ /* 7, 7, 7, 7, 7, 7, 7, 7 - 0 */ | |
| 6791 | RSP_VNXOR(0, 1, 2, 3, 4, 5, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7); | |
| 6792 | break; | |
| 3030 | sel = VEC_EL_2(EL, i); | |
| 3031 | vres[i] = ~((VREG_S(VS1REG, i) ^ VREG_S(VS2REG, sel))); | |
| 3032 | ACCUM_L(i) = vres[i]; | |
| 6793 | 3033 | } |
| 6794 | 3034 | WRITEBACK_RESULT(); |
| 6795 | 3035 | } |
| 6796 | #endif | |
| 6797 | 3036 | |
| 6798 | 3037 | INLINE void cfunc_rsp_vrcp(void *param) |
| 6799 | 3038 | { |
| r9854 | r9855 | |
| 6807 | 3046 | // |
| 6808 | 3047 | // Calculates reciprocal |
| 6809 | 3048 | |
| 6810 | int del = 7 - (VS1REG & 7); | |
| 6811 | int sel = 7 - (EL & 7); | |
| 6812 | INT32 rec; | |
| 3049 | int del = VS1REG & 7; | |
| 3050 | int sel = EL & 7; | |
| 3051 | INT32 shifter = 0; | |
| 6813 | 3052 | |
| 6814 | rec = (INT16)(R_VREG_S_X(VS2REG, sel)); | |
| 6815 | ||
| 6816 | if (rec == 0) | |
| 3053 | INT32 rec = (INT16)(VREG_S(VS2REG, sel)); | |
| 3054 | INT32 datainput = (rec < 0) ? (-rec) : rec; | |
| 3055 | if (datainput) | |
| 6817 | 3056 | { |
| 6818 | // divide by zero -> overflow | |
| 6819 | rec = 0x7fffffff; | |
| 6820 | } | |
| 6821 | else | |
| 6822 | { | |
| 6823 | int sign = 0; | |
| 6824 | int exp = 0; | |
| 6825 | int mantissa = 0; | |
| 6826 | ||
| 6827 | if (rec < 0) | |
| 3057 | for (i = 0; i < 32; i++) | |
| 6828 | 3058 | { |
| 6829 | rec = -rec; // rec = MINUS rec | |
| 6830 | sign = 1; | |
| 6831 | } | |
| 6832 | ||
| 6833 | // restrict to 10-bit mantissa | |
| 6834 | for (i = 15; i >= 0; i--) | |
| 6835 | { | |
| 6836 | if (rec & (1 << i)) | |
| 3059 | if (datainput & (1 << ((~i) & 0x1f)))//ò.æ.÷òî 31 - i | |
| 6837 | 3060 | { |
| 6838 | exp = i; | |
| 6839 | mantissa = (rec << (15 - i)) >> 6; | |
| 3061 | shifter = i; | |
| 6840 | 3062 | break; |
| 6841 | 3063 | } |
| 6842 | 3064 | } |
| 6843 | ||
| 6844 | if (mantissa == 0x200) | |
| 6845 | { | |
| 6846 | rec = 0x7fffffff; | |
| 6847 | } | |
| 6848 | else | |
| 6849 | { | |
| 6850 | rec = 0xffffffffU / mantissa; | |
| 6851 | ||
| 6852 | // | |
| 6853 | // simulate rounding error | |
| 6854 | // | |
| 6855 | // This has been verified on the real hardware. | |
| 6856 | // | |
| 6857 | // I was able to replicate this exact behaviour by using a five-round | |
| 6858 | // Newton reciprocal method using floorf() on intermediate results | |
| 6859 | // to force the use of IEEE 754 32bit floats. | |
| 6860 | // However, for the sake of portability, we'll use integer arithmetic. | |
| 6861 | // | |
| 6862 | if (rec & 0x800) | |
| 6863 | rec += 1; | |
| 6864 | ||
| 6865 | rec <<= 8; | |
| 6866 | } | |
| 6867 | ||
| 6868 | // restrict result to 17 significant bits | |
| 6869 | rec &= 0x7fffc000; | |
| 6870 | ||
| 6871 | rec >>= exp; | |
| 6872 | ||
| 6873 | if (sign) | |
| 6874 | { | |
| 6875 | rec = ~rec; // rec = BITWISE NOT rec | |
| 6876 | } | |
| 6877 | 3065 | } |
| 3066 | else | |
| 3067 | { | |
| 3068 | shifter = 0x10; | |
| 3069 | } | |
| 6878 | 3070 | |
| 6879 | for (i=0; i < 8; i++) | |
| 3071 | INT32 address = ((datainput << shifter) & 0x7fc00000) >> 22; | |
| 3072 | INT32 fetchval = rsp_divtable[address]; | |
| 3073 | INT32 temp = (0x40000000 | (fetchval << 14)) >> ((~shifter) & 0x1f); | |
| 3074 | if (rec < 0) | |
| 6880 | 3075 | { |
| 6881 | int element = VEC_EL_2(EL, i); | |
| 6882 | W_ACCUM_L(i, R_VREG_S_X(VS2REG, element)); | |
| 3076 | temp = ~temp; | |
| 6883 | 3077 | } |
| 3078 | if (!rec) | |
| 3079 | { | |
| 3080 | temp = 0x7fffffff; | |
| 3081 | } | |
| 3082 | else if (rec == 0xffff8000) | |
| 3083 | { | |
| 3084 | temp = 0xffff0000; | |
| 3085 | } | |
| 3086 | rec = temp; | |
| 6884 | 3087 | |
| 6885 | 3088 | rsp->reciprocal_res = rec; |
| 3089 | rsp->dp_allowed = 0; | |
| 6886 | 3090 | |
| 6887 | W_VREG_S_X(VDREG, del, (UINT16)(rsp->reciprocal_res)); // store low part | |
| 3091 | VREG_S(VDREG, del) = (UINT16)(rec & 0xffff); | |
| 3092 | ||
| 3093 | for (i = 0; i < 8; i++) | |
| 3094 | { | |
| 3095 | sel = VEC_EL_2(EL, i); | |
| 3096 | ACCUM_L(i) = VREG_S(VS2REG, sel); | |
| 3097 | } | |
| 6888 | 3098 | } |
| 6889 | 3099 | |
| 6890 | 3100 | INLINE void cfunc_rsp_vrcpl(void *param) |
| r9854 | r9855 | |
| 6899 | 3109 | // |
| 6900 | 3110 | // Calculates reciprocal low part |
| 6901 | 3111 | |
| 6902 | int del = 7 - (VS1REG & 7); | |
| 6903 | int sel = 7 - VEC_EL_2(EL, 7-del); | |
| 6904 | INT32 rec; | |
| 3112 | int del = VS1REG & 7; | |
| 3113 | int sel = EL & 7; | |
| 3114 | INT32 shifter = 0; | |
| 6905 | 3115 | |
| 6906 | rec = ((UINT16)( | |
| 3116 | INT32 rec = ((UINT16)( | |
| 6907 | 3117 | |
| 6908 | if (rec == 0) | |
| 3118 | INT32 datainput = rec; | |
| 3119 | ||
| 3120 | if (rec < 0) | |
| 6909 | 3121 | { |
| 6910 | // divide by zero -> overflow | |
| 6911 | rec = 0x7fffffff; | |
| 6912 | } | |
| 6913 | else | |
| 6914 | { | |
| 6915 | int negative = 0; | |
| 6916 | if (rec < 0) | |
| 3122 | if (rsp->dp_allowed) | |
| 6917 | 3123 | { |
| 6918 | if ( | |
| 3124 | if ( | |
| 6919 | 3125 | { |
| 6920 | | |
| 3126 | datainput = ~datainput; | |
| 6921 | 3127 | } |
| 6922 | 3128 | else |
| 6923 | 3129 | { |
| 6924 | | |
| 3130 | datainput = -datainput; | |
| 6925 | 3131 | } |
| 6926 | negative = 1; | |
| 6927 | 3132 | } |
| 6928 | | |
| 3133 | else | |
| 6929 | 3134 | { |
| 6930 | if (rec & (1 << i)) | |
| 6931 | { | |
| 6932 | rec &= ((0xffc00000) >> (31 - i)); | |
| 6933 | i = 0; | |
| 6934 | } | |
| 3135 | datainput = -datainput; | |
| 6935 | 3136 | } |
| 6936 | rec = (0x7fffffff / rec); | |
| 6937 | for (i = 31; i > 0; i--) | |
| 3137 | } | |
| 3138 | ||
| 3139 | ||
| 3140 | if (datainput) | |
| 3141 | { | |
| 3142 | for (i = 0; i < 32; i++) | |
| 6938 | 3143 | { |
| 6939 | if ( | |
| 3144 | if (datainput & (1 << ((~i) & 0x1f)))//ò.æ.÷òî 31 - i | |
| 6940 | 3145 | { |
| 6941 | rec &= ((0xffff8000) >> (31 - i)); | |
| 6942 | i = 0; | |
| 3146 | shifter = i; | |
| 3147 | break; | |
| 6943 | 3148 | } |
| 6944 | 3149 | } |
| 6945 | if (negative) | |
| 3150 | } | |
| 3151 | else | |
| 3152 | { | |
| 3153 | if (rsp->dp_allowed) | |
| 6946 | 3154 | { |
| 6947 | | |
| 3155 | shifter = 0 | |
| 6948 | 3156 | } |
| 3157 | else | |
| 3158 | { | |
| 3159 | shifter = 0x10; | |
| 3160 | } | |
| 6949 | 3161 | } |
| 6950 | 3162 | |
| 6951 | for (i=0; i < 8; i++) | |
| 3163 | INT32 address = ((datainput << shifter) & 0x7fc00000) >> 22; | |
| 3164 | INT32 fetchval = rsp_divtable[address]; | |
| 3165 | INT32 temp = (0x40000000 | (fetchval << 14)) >> ((~shifter) & 0x1f); | |
| 3166 | if (rec < 0) | |
| 6952 | 3167 | { |
| 6953 | int element = VEC_EL_2(EL, i); | |
| 6954 | W_ACCUM_L(i, R_VREG_S_X(VS2REG, element)); | |
| 3168 | temp = ~temp; | |
| 6955 | 3169 | } |
| 3170 | if (!rec) | |
| 3171 | { | |
| 3172 | temp = 0x7fffffff; | |
| 3173 | } | |
| 3174 | else if (rec == 0xffff8000) | |
| 3175 | { | |
| 3176 | temp = 0xffff0000; | |
| 3177 | } | |
| 3178 | rec = temp; | |
| 6956 | 3179 | |
| 6957 | 3180 | rsp->reciprocal_res = rec; |
| 3181 | rsp->dp_allowed = 0; | |
| 6958 | 3182 | |
| 6959 | W_VREG_S_X(VDREG, del, (UINT16)(rsp->reciprocal_res)); // store low part | |
| 3183 | VREG_S(VDREG, del) = (UINT16)(rec & 0xffff); | |
| 3184 | ||
| 3185 | for (i = 0; i < 8; i++) | |
| 3186 | { | |
| 3187 | sel = VEC_EL_2(EL, i); | |
| 3188 | ACCUM_L(i) = VREG_S(VS2REG, sel); | |
| 3189 | } | |
| 6960 | 3190 | } |
| 6961 | 3191 | |
| 6962 | 3192 | INLINE void cfunc_rsp_vrcph(void *param) |
| r9854 | r9855 | |
| 6970 | 3200 | // |
| 6971 | 3201 | // Calculates reciprocal high part |
| 6972 | 3202 | |
| 6973 | int del = 7 - (VS1REG & 7); | |
| 6974 | int sel = 7 - VEC_EL_2(EL, 7-del); | |
| 3203 | int del = VS1REG & 7; | |
| 3204 | int sel = EL & 7; | |
| 6975 | 3205 | |
| 6976 | rsp->reciprocal_high = R_VREG_S_X(VS2REG, sel); | |
| 3206 | rsp->reciprocal_high = (VREG_S(VS2REG, sel)) << 16; | |
| 3207 | rsp->dp_allowed = 1; | |
| 6977 | 3208 | |
| 6978 | W_ACCUM_L(0, R_VREG_S_X(VS2REG, VEC_EL_2(EL, 0))); | |
| 6979 | W_ACCUM_L(1, R_VREG_S_X(VS2REG, VEC_EL_2(EL, 1))); | |
| 6980 | W_ACCUM_L(2, R_VREG_S_X(VS2REG, VEC_EL_2(EL, 2))); | |
| 6981 | W_ACCUM_L(3, R_VREG_S_X(VS2REG, VEC_EL_2(EL, 3))); | |
| 6982 | W_ACCUM_L(4, R_VREG_S_X(VS2REG, VEC_EL_2(EL, 4))); | |
| 6983 | W_ACCUM_L(5, R_VREG_S_X(VS2REG, VEC_EL_2(EL, 5))); | |
| 6984 | W_ACCUM_L(6, R_VREG_S_X(VS2REG, VEC_EL_2(EL, 6))); | |
| 6985 | W_ACCUM_L(7, R_VREG_S_X(VS2REG, VEC_EL_2(EL, 7))); | |
| 3209 | for (int i = 0; i < 8; i++) | |
| 3210 | { | |
| 3211 | sel = VEC_EL_2(EL, i); | |
| 3212 | ACCUM_L(i) = VREG_S(VS2REG, sel); | |
| 3213 | } | |
| 6986 | 3214 | |
| 6987 | | |
| 3215 | | |
| 6988 | 3216 | } |
| 6989 | 3217 | |
| 6990 | 3218 | INLINE void cfunc_rsp_vmov(void *param) |
| r9854 | r9855 | |
| 6998 | 3226 | // |
| 6999 | 3227 | // Moves element from vector to destination vector |
| 7000 | 3228 | |
| 7001 | int element = 7 - (VS1REG & 7); | |
| 7002 | W_VREG_S_X(VDREG, element, R_VREG_S_X(VS2REG, 7 - VEC_EL_2(EL, element))); | |
| 3229 | int del = VS1REG & 7; | |
| 3230 | int sel = EL & 7; | |
| 3231 | ||
| 3232 | VREG_S(VDREG, del) = VREG_S(VS2REG, sel); | |
| 3233 | for (int i = 0; i < 8; i++) | |
| 3234 | { | |
| 3235 | sel = VEC_EL_2(EL, i); | |
| 3236 | ACCUM_L(i) = VREG_S(VS2REG, sel); | |
| 3237 | } | |
| 7003 | 3238 | } |
| 7004 | 3239 | |
| 7005 | 3240 | INLINE void cfunc_rsp_vrsql(void *param) |
| r9854 | r9855 | |
| 7014 | 3249 | // |
| 7015 | 3250 | // Calculates reciprocal square-root low part |
| 7016 | 3251 | |
| 7017 | int del = 7 - (VS1REG & 7); | |
| 7018 | int sel = 7 - VEC_EL_2(EL, 7 - del); | |
| 7019 | INT32 sqr; | |
| 3252 | int del = VS1REG & 7; | |
| 3253 | int sel = EL & 7; | |
| 3254 | INT32 shifter = 0; | |
| 7020 | 3255 | |
| 7021 | sqr = (UINT16)(R_VREG_S_X(VS2REG, sel)) | ((UINT32)(rsp->square_root_high) << 16); | |
| 3256 | INT32 rec = (INT16)(VREG_S(VS2REG, sel)); | |
| 3257 | INT32 datainput = (rec < 0) ? (-rec) : rec; | |
| 3258 | if (datainput) | |
| 3259 | { | |
| 3260 | for (i = 0; i < 32; i++) | |
| 3261 | { | |
| 3262 | if (datainput & (1 << ((~i) & 0x1f)))//ò.æ.÷òî 31 - i | |
| 3263 | { | |
| 3264 | shifter = i; | |
| 3265 | break; | |
| 3266 | } | |
| 3267 | } | |
| 3268 | } | |
| 3269 | else | |
| 3270 | { | |
| 3271 | shifter = 0x10; | |
| 3272 | } | |
| 7022 | 3273 | |
| 7023 | if (sqr == 0) | |
| 3274 | INT32 address = ((datainput << shifter) & 0x7fc00000) >> 22; | |
| 3275 | address = ((address | 0x200) & 0x3fe) | (shifter & 1); | |
| 3276 | ||
| 3277 | INT32 fetchval = rsp_divtable[address]; | |
| 3278 | INT32 temp = (0x40000000 | (fetchval << 14)) >> (((~shifter) & 0x1f) >> 1); | |
| 3279 | if (rec < 0) | |
| 7024 | 3280 | { |
| 7025 | // square root on 0 -> overflow | |
| 7026 | sqr = 0x7fffffff; | |
| 3281 | temp = ~temp; | |
| 7027 | 3282 | } |
| 7028 | | |
| 3283 | | |
| 7029 | 3284 | { |
| 7030 | // overflow ? | |
| 7031 | sqr = 0xffff8000; | |
| 3285 | temp = 0x7fffffff; | |
| 7032 | 3286 | } |
| 7033 | else | |
| 3287 | else if (rec == 0xffff8000) | |
| 7034 | 3288 | { |
| 7035 | int negative = 0; | |
| 7036 | if (sqr < 0) | |
| 7037 | { | |
| 7038 | if (((UINT32)(sqr & 0xffff0000) == 0xffff0000) && ((INT16)(sqr & 0xffff) < 0)) | |
| 7039 | { | |
| 7040 | sqr = ~sqr+1; | |
| 7041 | } | |
| 7042 | else | |
| 7043 | { | |
| 7044 | sqr = ~sqr; | |
| 7045 | } | |
| 7046 | negative = 1; | |
| 7047 | } | |
| 7048 | for (i = 31; i > 0; i--) | |
| 7049 | { | |
| 7050 | if (sqr & (1 << i)) | |
| 7051 | { | |
| 7052 | sqr &= (0xff800000 >> (31 - i)); | |
| 7053 | i = 0; | |
| 7054 | } | |
| 7055 | } | |
| 7056 | sqr = (INT32)(0x7fffffff / sqrt((double)sqr)); | |
| 7057 | for (i = 31; i > 0; i--) | |
| 7058 | { | |
| 7059 | if (sqr & (1 << i)) | |
| 7060 | { | |
| 7061 | sqr &= (0xffff8000 >> (31 - i)); | |
| 7062 | i = 0; | |
| 7063 | } | |
| 7064 | } | |
| 7065 | if (negative) | |
| 7066 | { | |
| 7067 | sqr = ~sqr; | |
| 7068 | } | |
| 3289 | temp = 0xffff0000; | |
| 7069 | 3290 | } |
| 3291 | rec = temp; | |
| 7070 | 3292 | |
| 7071 | W_ACCUM_L(0, R_VREG_S(VS2REG, VEC_EL_2(EL, 0))); | |
| 7072 | W_ACCUM_L(1, R_VREG_S(VS2REG, VEC_EL_2(EL, 1))); | |
| 7073 | W_ACCUM_L(2, R_VREG_S(VS2REG, VEC_EL_2(EL, 2))); | |
| 7074 | W_ACCUM_L(3, R_VREG_S(VS2REG, VEC_EL_2(EL, 3))); | |
| 7075 | W_ACCUM_L(4, R_VREG_S(VS2REG, VEC_EL_2(EL, 4))); | |
| 7076 | W_ACCUM_L(5, R_VREG_S(VS2REG, VEC_EL_2(EL, 5))); | |
| 7077 | W_ACCUM_L(6, R_VREG_S(VS2REG, VEC_EL_2(EL, 6))); | |
| 7078 | W_ACCUM_L(7, R_VREG_S(VS2REG, VEC_EL_2(EL, 7))); | |
| 3293 | rsp->reciprocal_res = rec; | |
| 3294 | rsp->dp_allowed = 0; | |
| 7079 | 3295 | |
| 7080 | | |
| 3296 | VREG | |
| 7081 | 3297 | |
| 7082 | W_VREG_S_X(VDREG, del, (UINT16)(rsp->square_root_res)); // store low part | |
| 3298 | for (i = 0; i < 8; i++) | |
| 3299 | { | |
| 3300 | sel = VEC_EL_2(EL, i); | |
| 3301 | ACCUM_L(i) = VREG_S(VS2REG, sel); | |
| 3302 | } | |
| 7083 | 3303 | } |
| 7084 | 3304 | |
| 7085 | 3305 | INLINE void cfunc_rsp_vrsqh(void *param) |
| r9854 | r9855 | |
| 7094 | 3314 | // |
| 7095 | 3315 | // Calculates reciprocal square-root high part |
| 7096 | 3316 | |
| 7097 | int del = (VS1REG & 7); | |
| 7098 | int sel = VEC_EL_2(EL, del); | |
| 3317 | int del = VS1REG & 7; | |
| 3318 | int sel = EL & 7; | |
| 7099 | 3319 | |
| 7100 | rsp->square_root_high = R_VREG_S(VS2REG, sel); | |
| 3320 | rsp->reciprocal_high = (VREG_S(VS2REG, sel)) << 16; | |
| 3321 | rsp->dp_allowed = 1; | |
| 7101 | 3322 | |
| 7102 | 3323 | for (i=0; i < 8; i++) |
| 7103 | 3324 | { |
| 7104 | int element = VEC_EL_2(EL, i); | |
| 7105 | W_ACCUM_L(i, R_VREG_S(VS2REG, element)); // perhaps accumulator is used to store the intermediate values ? | |
| 3325 | sel = VEC_EL_2(EL, i); | |
| 3326 | ACCUM_L(i) = VREG_S(VS2REG, sel); | |
| 7106 | 3327 | } |
| 7107 | 3328 | |
| 7108 | | |
| 3329 | | |
| 7109 | 3330 | } |
| 3331 | ||
| 7110 | 3332 | static void cfunc_sp_set_status_cb(void *param) |
| 7111 | 3333 | { |
| 7112 | 3334 | rsp_state *rsp = (rsp_state*)param; |
| r9854 | r9855 | |
| 7455 | 3677 | { |
| 7456 | 3678 | if (size == 1) |
| 7457 | 3679 | { |
| 3680 | //UML_MOV(block, MEM(&rsp->impstate->arg0), IREG(0)); // mov [arg0],i0 | |
| 3681 | //UML_MOV(block, MEM(&rsp->impstate->arg1), IREG(1)); // mov [arg1],i1 | |
| 3682 | //UML_MOV(block, MEM(&rsp->impstate->arg2), IMM(0)); // mov [arg2],0 | |
| 3683 | //UML_MOV(block, MEM(&rsp->impstate->arg3), MEM(&rsp->pc)); // mov [arg3],pc | |
| 3684 | //UML_CALLC(block, cfunc_printf_debug, rsp); // callc cfunc_printf_debug | |
| 7458 | 3685 | #ifdef LSB_FIRST |
| 7459 | 3686 | UML_XOR(block, IREG(0), IREG(0), IMM(3)); // xor i0,i0,3 |
| 7460 | 3687 | #endif |
| r9854 | r9855 | |
| 7463 | 3690 | } |
| 7464 | 3691 | else if (size == 2) |
| 7465 | 3692 | { |
| 3693 | //UML_MOV(block, MEM(&rsp->impstate->arg0), IREG(0)); // mov [arg0],i0 | |
| 3694 | //UML_MOV(block, MEM(&rsp->impstate->arg1), IREG(1)); // mov [arg1],i1 | |
| 3695 | //UML_MOV(block, MEM(&rsp->impstate->arg2), IMM(1)); // mov [arg2],1 | |
| 3696 | //UML_MOV(block, MEM(&rsp->impstate->arg3), MEM(&rsp->pc)); // mov [arg3],pc | |
| 3697 | //UML_CALLC(block, cfunc_printf_debug, rsp); // callc cfunc_printf_debug | |
| 7466 | 3698 | #ifdef LSB_FIRST |
| 7467 | 3699 | UML_TEST(block, IREG(0), IMM(1)); // test i0,1 |
| 7468 | 3700 | UML_JMPc(block, IF_NZ, unaligned_case); // jnz <unaligned_case> |
| r9854 | r9855 | |
| 7487 | 3719 | } |
| 7488 | 3720 | else if (size == 4) |
| 7489 | 3721 | { |
| 3722 | //UML_MOV(block, MEM(&rsp->impstate->arg0), IREG(0)); // mov [arg0],i0 | |
| 3723 | //UML_MOV(block, MEM(&rsp->impstate->arg1), IREG(1)); // mov [arg1],i1 | |
| 3724 | //UML_MOV(block, MEM(&rsp->impstate->arg2), IMM(2)); // mov [arg2],2 | |
| 3725 | //UML_MOV(block, MEM(&rsp->impstate->arg3), MEM(&rsp->pc)); // mov [arg3],pc | |
| 3726 | //UML_CALLC(block, cfunc_printf_debug, rsp); // callc cfunc_printf_debug | |
| 7490 | 3727 | #ifdef LSB_FIRST |
| 7491 | 3728 | UML_TEST(block, IREG(0), IMM(3)); // test i0,3 |
| 7492 | 3729 | UML_JMPc(block, IF_NZ, unaligned_case); // jnz <unaligned_case> |
| r9854 | r9855 | |
| 7510 | 3747 | } |
| 7511 | 3748 | else |
| 7512 | 3749 | { |
| 3750 | UML_MOV(block, MEM(&rsp->impstate->arg0), IREG(0)); // mov [arg0],i0 | |
| 7513 | 3751 | if (size == 1) |
| 7514 | 3752 | { |
| 3753 | //UML_MOV(block, MEM(&rsp->impstate->arg2), IMM(3)); // mov [arg2],3 | |
| 3754 | //UML_MOV(block, MEM(&rsp->impstate->arg3), MEM(&rsp->pc)); // mov [arg3],pc | |
| 7515 | 3755 | #ifdef LSB_FIRST |
| 7516 | 3756 | UML_XOR(block, IREG(0), IREG(0), IMM(3)); // xor i0,i0,3 |
| 7517 | 3757 | #endif |
| 7518 | 3758 | UML_AND(block, IREG(0), IREG(0), IMM(0x00000fff)); // and i0,i0,0xfff |
| 7519 | 3759 | UML_LOAD(block, IREG(0), rsp->impstate->dmem, IREG(0), BYTE); // load i0,dmem,i0,byte |
| 3760 | //UML_MOV(block, MEM(&rsp->impstate->arg1), IREG(0)); // mov [arg1],i0 | |
| 3761 | //UML_CALLC(block, cfunc_printf_debug, rsp); // callc cfunc_printf_debug | |
| 7520 | 3762 | } |
| 7521 | 3763 | else if (size == 2) |
| 7522 | 3764 | { |
| 3765 | //UML_MOV(block, MEM(&rsp->impstate->arg2), IMM(4)); // mov [arg2],4 | |
| 3766 | //UML_MOV(block, MEM(&rsp->impstate->arg3), MEM(&rsp->pc)); // mov [arg3],pc | |
| 7523 | 3767 | #ifdef LSB_FIRST |
| 7524 | 3768 | UML_TEST(block, IREG(0), IMM(1)); // test i0,1 |
| 7525 | 3769 | UML_JMPc(block, IF_NZ, unaligned_case); // jnz <unaligned_case> |
| r9854 | r9855 | |
| 7527 | 3771 | #endif |
| 7528 | 3772 | UML_AND(block, IREG(0), IREG(0), IMM(0x00000fff)); // and i0,i0,0xfff |
| 7529 | 3773 | UML_LOAD(block, IREG(0), rsp->impstate->dmem, IREG(0), WORD_x1); // load i0,dmem,i0,word_x1 |
| 3774 | //UML_MOV(block, MEM(&rsp->impstate->arg1), IREG(0)); // mov [arg1],i0 | |
| 3775 | //UML_CALLC(block, cfunc_printf_debug, rsp); // callc cfunc_printf_debug | |
| 7530 | 3776 | UML_RET(block); |
| 7531 | 3777 | #ifdef LSB_FIRST |
| 7532 | 3778 | UML_LABEL(block, unaligned_case); // unaligned_case: |
| r9854 | r9855 | |
| 7537 | 3783 | UML_ADD(block, IREG(1), IREG(1), IMM(48)); // add i1,i1,48 |
| 7538 | 3784 | UML_DROLAND(block, IREG(0), IREG(0), IREG(1), IMM(0xffff)); // droland i0,i0,i1,0xffff |
| 7539 | 3785 | #endif |
| 3786 | //UML_MOV(block, MEM(&rsp->impstate->arg1), IREG(0)); // mov [arg1],i0 | |
| 3787 | //UML_CALLC(block, cfunc_printf_debug, rsp); // callc cfunc_printf_debug | |
| 7540 | 3788 | } |
| 7541 | 3789 | else if (size == 4) |
| 7542 | 3790 | { |
| 3791 | //UML_MOV(block, MEM(&rsp->impstate->arg2), IMM(5)); // mov [arg2],5 | |
| 3792 | //UML_MOV(block, MEM(&rsp->impstate->arg3), MEM(&rsp->pc)); // mov [arg3],pc | |
| 7543 | 3793 | #ifdef LSB_FIRST |
| 7544 | 3794 | UML_TEST(block, IREG(0), IMM(3)); // test i0,3 |
| 7545 | 3795 | UML_JMPc(block, IF_NZ, unaligned_case); // jnz <unaligned_case> |
| 7546 | 3796 | #endif |
| 7547 | 3797 | UML_AND(block, IREG(0), IREG(0), IMM(0x00000fff)); // and i0,i0,0xfff |
| 7548 | 3798 | UML_LOAD(block, IREG(0), rsp->impstate->dmem, IREG(0), DWORD_x1); // load i0,dmem,i0,dword_x1 |
| 3799 | //UML_MOV(block, MEM(&rsp->impstate->arg1), IREG(0)); // mov [arg1],i0 | |
| 3800 | //UML_CALLC(block, cfunc_printf_debug, rsp); // callc cfunc_printf_debug | |
| 7549 | 3801 | UML_RET(block); |
| 7550 | 3802 | #ifdef LSB_FIRST |
| 7551 | 3803 | UML_LABEL(block, unaligned_case); // unaligned_case: |
| r9854 | r9855 | |
| 7555 | 3807 | UML_DLOAD(block, IREG(0), rsp->impstate->dmem, IREG(0), QWORD_x1); // dload i0,dmem,i0,qword_x1 |
| 7556 | 3808 | UML_DROL(block, IREG(0), IREG(0), IREG(1)); // drol i0,i0,i1 |
| 7557 | 3809 | #endif |
| 3810 | //UML_MOV(block, MEM(&rsp->impstate->arg1), IREG(0)); // mov [arg1],i0 | |
| 3811 | //UML_CALLC(block, cfunc_printf_debug, rsp); // callc cfunc_printf_debug | |
| 7558 | 3812 | } |
| 7559 | 3813 | } |
| 7560 | 3814 | UML_RET(block); |
| r9854 | r9855 | |
| 7768 | 4022 | return TRUE; |
| 7769 | 4023 | |
| 7770 | 4024 | case 0x04: /* VMUDL */ |
| 7771 | #if (DRC_VMUDL) | |
| 7772 | return generate_vmudl(rsp, block, compiler, desc); | |
| 7773 | #else | |
| 7774 | 4025 | UML_MOV(block, MEM(&rsp->impstate->arg0), IMM(desc->opptr.l[0])); // mov [arg0],desc->opptr.l |
| 7775 | 4026 | UML_CALLC(block, cfunc_rsp_vmudl, rsp); |
| 7776 | 4027 | return TRUE; |
| 7777 | #endif | |
| 7778 | 4028 | |
| 7779 | 4029 | case 0x05: /* VMUDM */ |
| 7780 | #if (DRC_VMUDM) | |
| 7781 | return generate_vmudm(rsp, block, compiler, desc); | |
| 7782 | #else | |
| 7783 | 4030 | UML_MOV(block, MEM(&rsp->impstate->arg0), IMM(desc->opptr.l[0])); // mov [arg0],desc->opptr.l |
| 7784 | 4031 | UML_CALLC(block, cfunc_rsp_vmudm, rsp); |
| 7785 | 4032 | return TRUE; |
| 7786 | #endif | |
| 7787 | 4033 | |
| 7788 | 4034 | case 0x06: /* VMUDN */ |
| 7789 | 4035 | UML_MOV(block, MEM(&rsp->impstate->arg0), IMM(desc->opptr.l[0])); // mov [arg0],desc->opptr.l |
| r9854 | r9855 | |
| 7811 | 4057 | return TRUE; |
| 7812 | 4058 | |
| 7813 | 4059 | case 0x0d: /* VMADM */ |
| 7814 | #if (DRC_VMADM) | |
| 7815 | return generate_vmadm(rsp, block, compiler, desc); | |
| 7816 | #else | |
| 7817 | 4060 | UML_MOV(block, MEM(&rsp->impstate->arg0), IMM(desc->opptr.l[0])); // mov [arg0],desc->opptr.l |
| 7818 | 4061 | UML_CALLC(block, cfunc_rsp_vmadm, rsp); |
| 7819 | 4062 | return TRUE; |
| 7820 | #endif | |
| 7821 | 4063 | |
| 7822 | 4064 | case 0x0e: /* VMADN */ |
| 7823 | #if (DRC_VMADN) | |
| 7824 | return generate_vmadn(rsp, block, compiler, desc); | |
| 7825 | #else | |
| 7826 | 4065 | UML_MOV(block, MEM(&rsp->impstate->arg0), IMM(desc->opptr.l[0])); // mov [arg0],desc->opptr.l |
| 7827 | 4066 | UML_CALLC(block, cfunc_rsp_vmadn, rsp); |
| 7828 | 4067 | return TRUE; |
| 7829 | #endif | |
| 7830 | 4068 | |
| 7831 | 4069 | case 0x0f: /* VMADH */ |
| 7832 | #if (DRC_VMADH) | |
| 7833 | return generate_vmadh(rsp, block, compiler, desc); | |
| 7834 | #else | |
| 7835 | 4070 | UML_MOV(block, MEM(&rsp->impstate->arg0), IMM(desc->opptr.l[0])); // mov [arg0],desc->opptr.l |
| 7836 | 4071 | UML_CALLC(block, cfunc_rsp_vmadh, rsp); |
| 7837 | 4072 | return TRUE; |
| 7838 | #endif | |
| 7839 | 4073 | |
| 7840 | 4074 | case 0x10: /* VADD */ |
| 7841 | #if (DRC_VADD) | |
| 7842 | return generate_vadd(rsp, block, compiler, desc); | |
| 7843 | #else | |
| 7844 | 4075 | UML_MOV(block, MEM(&rsp->impstate->arg0), IMM(desc->opptr.l[0])); // mov [arg0],desc->opptr.l |
| 7845 | 4076 | UML_CALLC(block, cfunc_rsp_vadd, rsp); |
| 7846 | 4077 | return TRUE; |
| 7847 | #endif | |
| 7848 | 4078 | |
| 7849 | 4079 | case 0x11: /* VSUB */ |
| 7850 | 4080 | UML_MOV(block, MEM(&rsp->impstate->arg0), IMM(desc->opptr.l[0])); // mov [arg0],desc->opptr.l |
| r9854 | r9855 | |
| 7912 | 4142 | return TRUE; |
| 7913 | 4143 | |
| 7914 | 4144 | case 0x28: /* VAND */ |
| 7915 | #if (DRC_VAND) | |
| 7916 | return generate_vand(rsp, block, compiler, desc); | |
| 7917 | #else | |
| 7918 | 4145 | UML_MOV(block, MEM(&rsp->impstate->arg0), IMM(desc->opptr.l[0])); // mov [arg0],desc->opptr.l |
| 7919 | 4146 | UML_CALLC(block, cfunc_rsp_vand, rsp); |
| 7920 | 4147 | return TRUE; |
| 7921 | #endif | |
| 7922 | 4148 | |
| 7923 | 4149 | case 0x29: /* VNAND */ |
| 7924 | #if (DRC_VNAND) | |
| 7925 | return generate_vnand(rsp, block, compiler, desc); | |
| 7926 | #else | |
| 7927 | 4150 | UML_MOV(block, MEM(&rsp->impstate->arg0), IMM(desc->opptr.l[0])); // mov [arg0],desc->opptr.l |
| 7928 | 4151 | UML_CALLC(block, cfunc_rsp_vnand, rsp); |
| 7929 | 4152 | return TRUE; |
| 7930 | #endif | |
| 7931 | 4153 | |
| 7932 | 4154 | case 0x2a: /* VOR */ |
| 7933 | #if (DRC_VOR) | |
| 7934 | return generate_vor(rsp, block, compiler, desc); | |
| 7935 | #else | |
| 7936 | 4155 | UML_MOV(block, MEM(&rsp->impstate->arg0), IMM(desc->opptr.l[0])); // mov [arg0],desc->opptr.l |
| 7937 | 4156 | UML_CALLC(block, cfunc_rsp_vor, rsp); |
| 7938 | 4157 | return TRUE; |
| 7939 | #endif | |
| 7940 | 4158 | |
| 7941 | 4159 | case 0x2b: /* VNOR */ |
| 7942 | #if (DRC_VNOR) | |
| 7943 | return generate_vnor(rsp, block, compiler, desc); | |
| 7944 | #else | |
| 7945 | 4160 | UML_MOV(block, MEM(&rsp->impstate->arg0), IMM(desc->opptr.l[0])); // mov [arg0],desc->opptr.l |
| 7946 | 4161 | UML_CALLC(block, cfunc_rsp_vnor, rsp); |
| 7947 | 4162 | return TRUE; |
| 7948 | #endif | |
| 7949 | 4163 | |
| 7950 | 4164 | case 0x2c: /* VXOR */ |
| 7951 | #if (DRC_VXOR) | |
| 7952 | return generate_vxor(rsp, block, compiler, desc); | |
| 7953 | #else | |
| 7954 | 4165 | UML_MOV(block, MEM(&rsp->impstate->arg0), IMM(desc->opptr.l[0])); // mov [arg0],desc->opptr.l |
| 7955 | 4166 | UML_CALLC(block, cfunc_rsp_vxor, rsp); |
| 7956 | 4167 | return TRUE; |
| 7957 | #endif | |
| 7958 | 4168 | |
| 7959 | 4169 | case 0x2d: /* VNXOR */ |
| 7960 | #if (DRC_VNXOR) | |
| 7961 | return generate_vnxor(rsp, block, compiler, desc); | |
| 7962 | #else | |
| 7963 | 4170 | UML_MOV(block, MEM(&rsp->impstate->arg0), IMM(desc->opptr.l[0])); // mov [arg0],desc->opptr.l |
| 7964 | 4171 | UML_CALLC(block, cfunc_rsp_vnxor, rsp); |
| 7965 | 4172 | return TRUE; |
| 7966 | #endif | |
| 7967 | 4173 | |
| 7968 | 4174 | case 0x30: /* VRCP */ |
| 7969 | 4175 | UML_MOV(block, MEM(&rsp->impstate->arg0), IMM(desc->opptr.l[0])); // mov [arg0],desc->opptr.l |
| r9854 | r9855 | |
| 8490 | 4696 | rsp_state *rsp = (rsp_state*)param; |
| 8491 | 4697 | UINT32 op = rsp->impstate->arg0; |
| 8492 | 4698 | int el = (op >> 7) & 0xf; |
| 8493 | UINT16 b1 = R_VREG_B(VS1REG, (el+0) & 0xf); | |
| 8494 | UINT16 b2 = R_VREG_B(VS1REG, (el+1) & 0xf); | |
| 4699 | UINT16 b1 = VREG_B(VS1REG, (el+0) & 0xf); | |
| 4700 | UINT16 b2 = VREG_B(VS1REG, (el+1) & 0xf); | |
| 8495 | 4701 | if (RTREG) RTVAL = (INT32)(INT16)((b1 << 8) | (b2)); |
| 8496 | 4702 | } |
| 8497 | 4703 | |
| r9854 | r9855 | |
| 8519 | 4725 | rsp_state *rsp = (rsp_state*)param; |
| 8520 | 4726 | UINT32 op = rsp->impstate->arg0; |
| 8521 | 4727 | int el = (op >> 7) & 0xf; |
| 8522 | W_VREG_B(VS1REG, (el+0) & 0xf, (RTVAL >> 8) & 0xff); | |
| 8523 | W_VREG_B(VS1REG, (el+1) & 0xf, (RTVAL >> 0) & 0xff); | |
| 4728 | VREG_B(VS1REG, (el+0) & 0xf) = (RTVAL >> 8) & 0xff; | |
| 4729 | VREG_B(VS1REG, (el+1) & 0xf) = (RTVAL >> 0) & 0xff; | |
| 8524 | 4730 | } |
| 8525 | 4731 | |
| 8526 | 4732 | static void cfunc_ctc2(void *param) |
| r9854 | r9855 | |
|---|---|---|
| 1184 | 1184 | $(MAME_VIDEO)/n64.o \ |
| 1185 | 1185 | $(MAME_VIDEO)/rdpblend.o \ |
| 1186 | 1186 | $(MAME_VIDEO)/rdpfb.o \ |
| 1187 | $(MAME_VIDEO)/rdpfetch.o \ | |
| 1188 | 1187 | $(MAME_VIDEO)/rdptpipe.o \ |
| 1189 | 1188 | $(MAME_VIDEO)/rdpspn16.o \ |
| 1190 | $(MAME_VIDEO)/rdptrect.o \ | |
| 1191 | $(MAME_VIDEO)/rdpfrect.o \ | |
| 1192 | 1189 | $(MESS_MACHINE)/pokemini.o \ |
| 1193 | 1190 | $(MESS_DRIVERS)/pokemini.o \ |
| 1194 | 1191 | $(MESS_DRIVERS)/vboy.o \ |
| r9854 | r9855 | |
|---|---|---|
| 210 | 210 | ROM_LOAD( "normslp.rom", 0x00, 0x80, CRC(4f2ae525) SHA1(eab43f8cc52c8551d9cff6fced18ef80eaba6f05) ) |
| 211 | 211 | ROM_END |
| 212 | 212 | |
| 213 | CONS(1996, n64, 0, 0, n64, n64, 0, "Nintendo", "Nintendo 64", GAME_ | |
| 213 | CONS(1996, n64, 0, 0, n64, n64, 0, "Nintendo", "Nintendo 64", GAME_ |
| Previous | 15994 Revisions | Next |