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 rdpfetch.c rdpfetch.h rdpfrect.c rdpfrect.h rdpspn16.c rdpspn16.h rdptpipe.c rdptpipe.h rdptrect.c rdptrect.h rdptri.h
[src/mess]mess.mak
[src/mess/drivers]n64.c

src/mame/machine/n64.c
r9854r9855
390390            src = (UINT8*)&rdram[sp_dram_addr / 4];
391391            dst = (sp_mem_addr & 0x1000) ? (UINT8*)&rsp_imem[(sp_mem_addr & 0xfff) / 4] : (UINT8*)&rsp_dmem[(sp_mem_addr & 0xfff) / 4];
392392
393         //printf("CPU %08x -> RSP %08x\n", sp_dram_addr, 0x04000000 | sp_mem_addr);
393394            for (i=0; i < sp_dma_length; i++)
394395            {
395                dst[BYTE4_XOR_BE(i)] = src[BYTE4_XOR_BE(i)];
396            //printf("%02x ", src[i]);
397            dst[i] = src[i];
396398            }
399            //printf("\n");
397400
398401            sp_mem_addr += sp_dma_length;
399402            sp_dram_addr += sp_dma_length;
r9854r9855
408411            src = (sp_mem_addr & 0x1000) ? (UINT8*)&rsp_imem[(sp_mem_addr & 0xfff) / 4] : (UINT8*)&rsp_dmem[(sp_mem_addr & 0xfff) / 4];
409412            dst = (UINT8*)&rdram[sp_dram_addr / 4];
410413
414         //printf("RSP %08x -> CPU %08x\n", 0x04000000 | sp_mem_addr, sp_dram_addr);
411415            for (i=0; i < sp_dma_length; i++)
412416            {
413                dst[BYTE4_XOR_BE(i)] = src[BYTE4_XOR_BE(i)];
417            //printf("%02x ", src[i]);
418                dst[i] = src[i];
414419            }
420            //printf("\n");
415421
416422            sp_mem_addr += sp_dma_length;
417423            sp_dram_addr += sp_dma_length;
r9854r9855
729735{
730736   _n64_state *state = device->machine->driver_data<_n64_state>();
731737
738   //printf("%08x\n", offset);
732739   switch (offset)
733740   {
734741      case 0x00/4:      // DP_START_REG
r9854r9855
755762{
756763   _n64_state *state = device->machine->driver_data<_n64_state>();
757764
765   //printf("%08x: %08x\n", offset, data);
758766   switch (offset)
759767   {
760768      case 0x00/4:      // DP_START_REG
r9854r9855
10911099    }
10921100}
10931101
1102#define N64_ATTOTIME_NORMALIZE(a)   do { while ((a).attoseconds >= ATTOSECONDS_PER_SECOND) { (a).seconds++; (a).attoseconds -= ATTOSECONDS_PER_SECOND; } } while (0)
1103
10941104static void start_audio_dma(running_machine *machine)
10951105{
10961106    INT16 *ram = (INT16*)rdram;
r9854r9855
20112021   /* configure fast RAM regions for DRC */
20122022   mips3drc_add_fastram(machine->device("maincpu"), 0x00000000, 0x007fffff, FALSE, rdram);
20132023
2014   rspdrc_set_options(machine->device("rsp"), 0);
2024   rspdrc_set_options(machine->device("rsp"), RSPDRC_STRICT_VERIFY);
20152025   rspdrc_add_imem(machine->device("rsp"), rsp_imem);
20162026   rspdrc_add_dmem(machine->device("rsp"), rsp_dmem);
20172027   rspdrc_flush_drc_cache(machine->device("rsp"));
src/mame/mame.mak
r9854r9855
12061206   $(DRIVERS)/feversoc.o \
12071207
12081208$(MAMEOBJ)/seta.a: \
1209   $(DRIVERS)/aleck64.o $(MACHINE)/n64.o $(VIDEO)/n64.o $(VIDEO)/rdpblend.o $(VIDEO)/rdpfb.o $(VIDEO)/rdpspn16.o $(VIDEO)/rdptrect.o $(VIDEO)/rdpfrect.o $(VIDEO)/rdpfetch.o $(VIDEO)/rdptpipe.o \
1209   $(DRIVERS)/aleck64.o $(MACHINE)/n64.o $(VIDEO)/n64.o $(VIDEO)/rdpblend.o $(VIDEO)/rdpfb.o $(VIDEO)/rdpspn16.o $(VIDEO)/rdptpipe.o \
12101210   $(DRIVERS)/darkhors.o \
12111211   $(DRIVERS)/hanaawas.o $(VIDEO)/hanaawas.o \
12121212   $(DRIVERS)/macs.o \
src/mame/video/rdpfrect.c
r9854r9855
1#include "emu.h"
2#include "includes/n64.h"
3#include "video/n64.h"
4
5namespace N64
6{
7
8namespace RDP
9{
10
11#define LookUpCC(A, B, C, D) m_rdp->GetCCLUT2()[(m_rdp->GetCCLUT1()[(A << 16) | (B << 8) | C] << 8) | D]
12
13void 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
24void 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
46void 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
193void 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
407void 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
src/mame/video/rdpfrect.h
r9854r9855
1#ifndef _VIDEO_RDPFILLRECT_H_
2#define _VIDEO_RDPFILLRECT_H_
3
4#include "emu.h"
5#include "video/rdpblend.h"
6
7namespace N64
8{
9
10namespace RDP
11{
12
13class OtherModes;
14class MiscState;
15class Processor;
16class Blender;
17class Color;
18
19class 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_
src/mame/video/rdpfetch.c
r9854r9855
1#include "emu.h"
2#include "includes/n64.h"
3#include "video/n64.h"
4
5namespace N64
6{
7
8namespace RDP
9{
10
11void 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
22UINT32 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
54UINT32 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
162UINT32 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
214UINT32 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
304UINT32 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
397UINT32 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
src/mame/video/rdpfetch.h
r9854r9855
1#ifndef _VIDEO_RDPFETCH_H_
2#define _VIDEO_RDPFETCH_H_
3
4#include "emu.h"
5
6namespace N64
7{
8
9namespace RDP
10{
11
12class Processor;
13class OtherModes;
14class MiscState;
15class Tile;
16
17class 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_
src/mame/video/rdptrect.c
r9854r9855
1#include "emu.h"
2#include "includes/n64.h"
3#include "video/n64.h"
4
5namespace N64
6{
7
8namespace RDP
9{
10
11#define LookUpCC(A, B, C, D) m_rdp->GetCCLUT2()[(m_rdp->GetCCLUT1()[(A << 16) | (B << 8) | C] << 8) | D]
12
13void 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
23void 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
42void 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
363void 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
src/mame/video/rdptrect.h
r9854r9855
1#ifndef _VIDEO_RDPTEXRECT_H_
2#define _VIDEO_RDPTEXRECT_H_
3
4#include "emu.h"
5
6namespace N64
7{
8
9namespace RDP
10{
11
12class OtherModes;
13class MiscState;
14class Processor;
15class Color;
16
17class 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_
src/mame/video/rdptri.h
r9854r9855
1616{
1717   public:
1818      Triangle() { fatalerror("Please don't use the default constructor for N64::RDP::Triangle\n"); }
19      Triangle(running_machine* machine, bool shade, bool texture, bool zbuffer);
19      Triangle(running_machine *machine, bool shade, bool texture, bool zbuffer, bool rect, bool flip);
2020
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);
2222      void Draw();
2323
2424   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
2528      running_machine*   m_machine;
2629      UINT32*            m_cmd_data;
2730      MiscState*         m_misc_state;
r9854r9855
2932      bool            m_shade;
3033      bool            m_texture;
3134      bool            m_zbuffer;
35      bool            m_rect;
3236};
3337
3438} // namespace RDP
src/mame/video/rdptpipe.c
r9854r9855
1717   m_machine = machine;
1818   m_rdp = &state->m_rdp;
1919   m_other_modes = m_rdp->GetOtherModes();
20   m_misc_state = m_rdp->GetMiscState();
21}
2022
21   m_tex_fetch.SetMachine(m_machine);
23void 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   }
2248}
2349
24void TexturePipe::CalculateClampDiffs(UINT32 prim_tile)
50void TexturePipe::MaskCoupled(INT32* S, INT32* S1, INT32* T, INT32* T1, INT32 num)
2551{
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)
2955   {
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;
3273   }
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
97void 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   }
33106   else
34107   {
35      start = prim_tile;
36      end = prim_tile + 1;
108      *S <<= (16 - tile[num].shift_s);
37109   }
38   for (; start <= end; start++)
110   *S = SIGN16(*S);
111   if (tile[num].shift_t < 11)
39112   {
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;
42114   }
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);
43123}
44124
45void TexturePipe::Mask(INT32* S, INT32* T, Tile* tile)
125void TexturePipe::ShiftCopy(INT32* S, INT32* T, UINT32 num)
46126{
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}
48149
49   if (tile->mask_s) // Select clamp if mask == 0
150void 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)
50157   {
51      swrap = *S >> (tile->mask_s > 10 ? 10 : tile->mask_s);
52      swrap &= 1;
53      if (tile->ms && swrap)
158      if (*S & 0x10000)
54159      {
55         *S = (~(*S)) & m_maskbits_table[tile->mask_s]; // Mirroring and masking
160         *S = 0;
161         *SFRAC = 0;
56162      }
57      else if (tile->mask_s)
163      else if (maxs)
58164      {
59         *S &= m_maskbits_table[tile->mask_s]; // Masking
165         *S = m_clamp_s_diff[num];
166         *SFRAC = 0;
60167      }
168      else
169      {
170         *S = (SIGN17(*S) >> 5) & 0x1fff;
171      }
61172   }
173   else
174   {
175      *S = (SIGN17(*S) >> 5) & 0x1fff;
176   }
62177
63   if (tile->mask_t)
178   if (dot)
64179   {
65      twrap = *T >> (tile->mask_t > 10 ? 10 : tile->mask_t);
66      twrap &= 1;
67      if (tile->mt && twrap)
180      if (*T & 0x10000)
68181      {
69         *T = (~(*T)) & m_maskbits_table[tile->mask_t]; // Mirroring and masking
182         *T = 0;
183         *TFRAC = 0;
70184      }
71      else if (tile->mask_t)
185      else if (maxt)
72186      {
73         *T &= m_maskbits_table[tile->mask_t];
187         *T = m_clamp_t_diff[num];
188         *TFRAC = 0;
74189      }
190      else
191      {
192         *T = (SIGN17(*T) >> 5) & 0x1fff;
193      }
75194   }
195   else
196   {
197      *T = (SIGN17(*T) >> 5) & 0x1fff;
198   }
76199}
77200
78void TexturePipe::TexShift(INT32* S, INT32* T, bool* maxs, bool* maxt, Tile *tile)
201void TexturePipe::ClampCycleLight(INT32* S, INT32* T, bool maxs, bool maxt, INT32 num)
79202{
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;
82206
83   if (tile->shift_s)
207   if (dos)
84208   {
85      if (tile->shift_s < 11)
209      if (*S & 0x10000)
86210      {
87         *S >>= tile->shift_s;
211         *S = 0;
88212      }
213      else if (maxs)
214      {
215         *S = m_clamp_s_diff[num];
216      }
89217      else
90218      {
91         *S <<= (16 - tile->shift_s);
219         *S = (SIGN17(*S) >> 5) & 0x1fff;
92220      }
93      *S = SIGN16(*S);
94221   }
222   else
223   {
224      *S = (SIGN17(*S) >> 5) & 0x1fff;
225   }
95226
96   if (tile->shift_s)
227   if (dot)
97228   {
98      if (tile->shift_t < 11)
229      if (*T & 0x10000)
99230      {
100         *T >>= tile->shift_t;
231         *T = 0;
101232      }
102       else
103       {
104         *T <<= (16 - tile->shift_t);
233      else if (maxt)
234      {
235         *T = m_clamp_t_diff[num];
105236      }
106      *T = SIGN16(*T);
237      else
238      {
239         *T = (SIGN17(*T) >> 5) & 0x1fff;
240      }
107241   }
108
109   *maxs = ((*S >> 3) >= tile->sh);
110   *maxt = ((*T >> 3) >= tile->th);
242   else
243   {
244      *T = (SIGN17(*T) >> 5) & 0x1fff;
245   }
111246}
112247
113void TexturePipe::Clamp(INT32* S, INT32* T, INT32* SFRAC, INT32* TFRAC, bool maxs, bool maxt, Tile* tile)
248void TexturePipe::Cycle(Color* TEX, Color* prev, INT32 SSS, INT32 SST, UINT32 tilenum, UINT32 cycle)
114249{
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)
123260   {
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      }
126363   }
127   else if (maxs && dos)
364   else
128365   {
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      }
131411   }
132   else
412}
413
414void 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
428void 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)
133435   {
134      *S = (SIGN17(*S) >> 5) & 0x1fff;
436      m_rdp->TCDiv(nexts, nextt, nextsw, &nexts, &nextt);
135437   }
136   if (overunders && dosfrac)
438   else
137439   {
138      *SFRAC = 0;
440      m_rdp->TCDivNoPersp(nexts, nextt, nextsw, &nexts, &nextt);
139441   }
140442
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)
142449   {
143      *T = 0;
144      overundert = true;
450      *sss = 0x7fff;
145451   }
146   else if (maxt && dot)
452   else if (*sss & 0x20000)
147453   {
148      *T = m_clamp_t_diff[tile->num];
149      overundert = true;
454      *sss = 0x8000;
150455   }
151456   else
152457   {
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      }
154471   }
155   if (overundert && dotfrac)
472
473   if (*sst & 0x40000)
156474   {
157      *TFRAC = 0;
475      *sst = 0x7fff;
158476   }
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   }
159497}
160498
161void TexturePipe::ClampLight(INT32* S, INT32* T, bool maxs, bool maxt, Tile* tile)
499void TexturePipe::LOD2Cycle(INT32* sss, INT32* sst, INT32 s, INT32 t, INT32 w, INT32 dsinc, INT32 dtinc, INT32 dwinc, INT32 prim_tile, INT32* t1, INT32* t2)
162500{
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;
166504
167   if (*S & 0x10000 && dos)
505   if (m_other_modes->persp_tex_en)
168506   {
169      *S = 0;
507      m_rdp->TCDiv(nexts, nextt, nextsw, &nexts, &nextt);
170508   }
171   else if (maxs && dos)
509   else
172510   {
173      *S = m_clamp_s_diff[tile->num];
511      m_rdp->TCDivNoPersp(nexts, nextt, nextsw, &nexts, &nextt);
174512   }
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   }
175542   else
176543   {
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      }
178557   }
179558
180   if (*T & 0x10000 && dot)
559   if (*sst & 0x40000)
181560   {
182      *T = 0;
561      *sst = 0x7fff;
183562   }
184   else if (maxt && dot)
563   else if (*sst & 0x20000)
185564   {
186      *T = m_clamp_t_diff[tile->num];
565      *sst = 0x8000;
187566   }
188567   else
189568   {
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      }
191582   }
192}
193583
194UINT32 TexturePipe::Fetch(INT32 SSS, INT32 SST, Tile* tile)
195{
196   Color TEX;
197   if (m_other_modes->sample_type)
584   if ((lod & 0x4000) || lodclamp)
198585   {
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   }
207592
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));
213596
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);
218598
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   }
223610
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   }
226615
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}
229656
230      Mask(&sss1, &sst1, tile);
231        Mask(&sss2, &sst2, tile);
657void 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;
232662
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)
237700      {
238         INVSF = 0x20 - SFRAC;
239         INVTF = 0x20 - TFRAC;
701         *sss = 0x7fff;
240702      }
703      else if (tempanded == 0x10000)
704      {
705         *sss = 0x8000;
706      }
707      else
708      {
709         *sss &= 0xffff;
710      }
711   }
241712
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)
245725      {
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;
248727      }
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)
252729      {
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;
255731      }
732      else
733      {
734         *sst &= 0xffff;
735      }
736   }
256737
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)
258754      {
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)
260764         {
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);
269766         }
270767         else
271768         {
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);
280770         }
771         *t1 &= 7;
281772      }
282      else // Is this accurate?
773   }
774}
775
776void 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)
283782      {
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         }
288790      }
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      }
289800   }
290   else
801   else//1-cycle or copy
291802   {
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}
294807
295      bool maxs = false;
296      bool maxt = false;
297      TexShift(&sss1, &sst1, &maxs, &maxt, tile);
808UINT32 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;
298817
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   }
301826
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   }
304831
305      INT32 SFRAC = sss1 & 0x1f;
306      INT32 TFRAC = sst1 & 0x1f;
832   UINT16 *tc16 = m_rdp->GetTMEM16();
307833
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;
309849
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);
311882
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      }
3141253   }
3151254
316   return TEX.c;
1255   return color.c;
3171256}
3181257
3191258} // namespace RDP
src/mame/video/rdptpipe.h
r9854r9855
2525         {
2626            m_maskbits_table[i] = ((UINT16)(0xffff) >> (16 - i)) & 0x3ff;
2727         }
28         m_start_span = false;
29         m_precomp_s = 0;
30         m_precomp_t = 0;
2831      }
2932
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);
3136      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);
3240
3341      void            SetMachine(running_machine* machine);
3442
43      bool            m_start_span;
44      INT32            m_precomp_s;
45      INT32            m_precomp_t;
46
3547   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);
4050
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
4157      running_machine*   m_machine;
4258      OtherModes*         m_other_modes;
59      MiscState*         m_misc_state;
4360      Processor*         m_rdp;
44      TexFetch         m_tex_fetch;
4561
4662      INT32            m_maskbits_table[16];
4763      INT32            m_clamp_t_diff[8];
src/mame/video/rdpblend.c
r9854r9855
55namespace N64
66{
77
8bool RDP::Blender::Blend(void* in_fb, UINT8* hb, RDP::Color c1, RDP::Color c2, int dith)
8namespace RDP
99{
10   switch(m_misc_state->m_fb_size)
11   {
12      case PIXEL_SIZE_16BIT:
13         return Blend16Bit((UINT16*)in_fb, hb, c1, c2, dith);
1410
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
26bool RDP::Blender::Blend16Bit(UINT16* fb, UINT8* hb, RDP::Color c1, RDP::Color c2, int dith)
11bool Blender::Blend1Cycle(UINT32* fr, UINT32* fg, UINT32* fb, int dith, int adseed, int partialreject, int special_bsel)
2712{
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;
3215
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);
3919   }
4020
41   return false;
42}
21   DitherA(&m_rdp->GetShadeColor()->i.a, adseed);
4322
44bool 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))
4924   {
50      memory_cvg = ((mem & 1) << 2) + (*hb & 3);
25      //return false;
5126   }
5227
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))
5529   {
5630      return false;
5731   }
5832
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)
6035   {
61      return false;
36      r = *ci->blender1a_r[0];
37      g = *ci->blender1a_g[0];
38      b = *ci->blender1a_b[0];
6239   }
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   }
10740   else
10841   {
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);
12144   }
12245
123   if(!(m_other_modes->rgb_dither_sel & 2))
46   if (m_other_modes->rgb_dither_sel < 3)
12447   {
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);
13049   }
131
132    return m_rdp->GetFramebuffer()->Write(fb, hb, r, g, b);
50   *fr = r;
51   *fg = g;
52   *fb = b;
53   return true;
13354}
13455
135bool RDP::Blender::Blend16Bit2Cycle(UINT16* fb, UINT8* hb, RDP::Color c1, RDP::Color c2, int dith)
56bool Blender::Blend2Cycle(UINT32* fr, UINT32* fg, UINT32* fb, int dith, int adseed, int partialreject, int special_bsel0, int special_bsel1)
13657{
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)
14060   {
141      memory_cvg = ((mem & 1) << 2) + (*hb & 3);
61      DitherA(&m_rdp->GetPixelColor()->i.a, adseed);
14262   }
14363
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))
14667   {
147      return false;
68      //return false;
14869   }
14970
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))
15172   {
15273      return false;
15374   }
15475
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];
16077
161   m_rdp->GetPixelColor()->c = c2.c;
78   INT32 r, g, b;
79   BlendEquationCycle0(&r, &g, &b, special_bsel0);
16280
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
18381   m_rdp->GetBlendedColor()->i.r = r;
18482   m_rdp->GetBlendedColor()->i.g = g;
18583   m_rdp->GetBlendedColor()->i.b = b;
18684   m_rdp->GetBlendedColor()->i.a = m_rdp->GetPixelColor()->i.a;
18785
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)
19588   {
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];
20692   }
20793   else
20894   {
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);
22897   }
22998
230   if(!(m_other_modes->rgb_dither_sel & 2))
99   if (m_other_modes->rgb_dither_sel < 3)
231100   {
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);
237102   }
238103
239    return m_rdp->GetFramebuffer()->Write(fb, hb, r, g, b);
240}
104   *fr = r;
105   *fg = g;
106   *fb = b;
241107
242bool 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;
258109}
259110
260bool RDP::Blender::Blend32Bit1Cycle(UINT32* fb, RDP::Color c)
111void Blender::BlendEquationCycle0(int* r, int* g, int* b, int bsel_special)
261112{
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;
264116
265   // Alpha compare
266   if (!AlphaCompare(c.i.a))
117   if (bsel_special)
267118   {
268      return 0;
119      blend1a = (blend1a >> m_shift_a) & 0x1C;
120      blend2a = (blend2a >> m_shift_b) & 0x1C;
269121   }
270122
271   if (!m_misc_state->m_curpixel_cvg)
272   {
273      return 0;
274   }
123   UINT32 sum = ((blend1a >> 2) + (blend2a >> 2) + 1) & 0xf;
275124
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)));
281127
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)));
285130
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)
287135   {
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);
289139   }
290140   else
291141   {
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];
293145   }
294146
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)
296152   {
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;
300156   }
301157   else
302158   {
303      m_rdp->GetInvPixelColor()->i.a = 0xff - *m_rdp->GetColorInputs()->blender1b_a[0];
304
305      if(m_other_modes->force_blend)
159      if (sum)
306160      {
307         BlendEquation0Force(&r, &g, &b, m_misc_state->m_special_bsel0);
161         *r /= sum;
162         *g /= sum;
163         *b /= sum;
308164      }
309165      else
310166      {
311         BlendEquation0NoForce(&r, &g, &b, m_misc_state->m_special_bsel0);
167         *r = *g = *b = 0xff;
312168      }
313169   }
314170
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;
316174}
317175
318bool RDP::Blender::Blend32Bit2Cycle(UINT32* fb, RDP::Color c1, RDP::Color c2)
176void Blender::BlendEquationCycle1(INT32* r, INT32* g, INT32* b, int bsel_special)
319177{
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;
322181
323   // Alpha compare
324   if (!AlphaCompare(c2.i.a))
182   if (bsel_special)
325183   {
326      return 0;
184      blend1a = (blend1a >> m_shift_a) & 0x1C;
185      blend2a = (blend2a >> m_shift_b) & 0x1C;
327186   }
328187
329   if (!m_misc_state->m_curpixel_cvg)
330   {
331      return 0;
332   }
188   UINT32 sum = ((blend1a >> 2) + (blend2a >> 2) + 1) & 0xf;
333189
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)));
339192
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)));
343195
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)));
352198
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)
356200   {
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);
358204   }
359205   else
360206   {
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];
362210   }
363211
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;
367215
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)
373217   {
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;
377221   }
378222   else
379223   {
380      m_rdp->GetInvPixelColor()->i.a = 0xff - *m_rdp->GetColorInputs()->blender1b_a[1];
381
382      if(m_other_modes->force_blend)
224      if (sum)
383225      {
384         BlendEquation1Force(&r, &g, &b, m_misc_state->m_special_bsel1);
226         *r /= sum;
227         *g /= sum;
228         *b /= sum;
385229      }
386230      else
387231      {
388         BlendEquation1NoForce(&r, &g, &b, m_misc_state->m_special_bsel1);
232         *r = *g = *b = 0xff;
389233      }
390234   }
391235
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;
393239}
394240
395void RDP::Blender::BlendEquation0Force(INT32* r, INT32* g, INT32* b, int bsel_special)
241bool Blender::AlphaCompare(UINT8 alpha)
396242{
397   int blend1a = *m_rdp->GetColorInputs()->blender1b_a[0];
398   if (bsel_special)
243   INT32 threshold;
244   if (m_other_modes->alpha_compare_en)
399245   {
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;
401252   }
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;
410254}
411255
412void RDP::Blender::BlendEquation0NoForce(INT32* r, INT32* g, INT32* b, int bsel_special)
256void Blender::DitherA(UINT8 *a, int dith)
413257{
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)
417260   {
418      blend1a &= 0xe0;
261      new_a = 0xff;
419262   }
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;
450264}
451265
452void RDP::Blender::BlendEquation1Force(INT32* r, INT32* g, INT32* b, int bsel_special)
266void Blender::DitherRGB(INT32 *r, INT32 *g, INT32 *b, int dith)
453267{
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
482void 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
522bool 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
538void RDP::Blender::DitherRGB(INT32 *r, INT32 *g, INT32 *b, int dith)
539{
540268   if ((*r & 7) > dith)
541269   {
542270      *r = (*r & 0xf8) + 8;
r9854r9855
563291   }
564292}
565293
294} // namespace RDP
295
566296} // namespace N64
src/mame/video/rdpblend.h
r9854r9855
1717class Blender
1818{
1919   public:
20      Blender() { }
20      Blender()
21      {
22         m_blend_enable = false;
23      }
2124
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);
2327
2428      void            SetOtherModes(OtherModes* other_modes) { m_other_modes = other_modes; }
2529      void            SetMiscState(MiscState* misc_state) { m_misc_state = misc_state; }
2630      void            SetMachine(running_machine* machine) { m_machine = machine; }
2731      void            SetProcessor(Processor* rdp) { m_rdp = rdp; }
2832
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
2939   private:
3040      running_machine*   m_machine;
3141      OtherModes*         m_other_modes;
3242      MiscState*         m_misc_state;
3343      Processor*         m_rdp;
3444
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
4152      bool            AlphaCompare(UINT8 alpha);
4253
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
4854      void            DitherRGB(INT32* r, INT32* g, INT32* b, int dith);
55      void            DitherA(UINT8* a, int dith);
4956};
5057
5158} // namespace RDP
src/mame/video/rdpspn16.c
r9854r9855
1010
1111#define LookUpCC(A, B, C, D) m_rdp->GetCCLUT2()[(m_rdp->GetCCLUT1()[(A << 16) | (B << 8) | C] << 8) | D]
1212
13void Processor::RenderSpans(int start, int end, int tilenum, bool shade, bool texture, bool zbuffer, bool flip)
13void Processor::RenderSpans(int start, int end, int tilenum, bool flip)
1414{
15   m_tex_pipe.CalculateClampDiffs(tilenum);
16
1715   int clipy1 = GetScissor()->m_yh;
1816   int clipy2 = GetScissor()->m_yl;
1917
r9854r9855
3735   for(int i = start; i <= end; i++)
3836   {
3937      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
4146   }
4247}
4348
r9854r9855
6065      printf("%d", m_cvg[index]);
6166   }
6267   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);
7468}
7569
7670void Span::SetMachine(running_machine *machine)
r9854r9855
8377   m_misc_state = m_rdp->GetMiscState();
8478}
8579
86void Span::Draw(int index, int tilenum, bool shade, bool texture, bool zbuffer, bool flip)
80void Span::RGBAZClip(int sr, int sg, int sb, int sa, int *sz)
8781{
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
99void 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
131void Span::Draw1Cycle(int index, int tilenum, bool flip)
132{
88133   int clipx1 = m_rdp->GetScissor()->m_xh;
89134   int clipx2 = m_rdp->GetScissor()->m_xl;
90135
r9854r9855
97142   SpanParam t = m_t;
98143   SpanParam w = m_w;
99144
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;
104148
105   UINT32 prim_tile = tilenum;
106   UINT32 tilenum2 = 0;
149   INT32 tile1 = tilenum;
107150
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;
117166   int xinc = flip ? 1 : -1;
118167
119   int nexts;
120   int nextt;
121   int nextsw;
122
123168   int fb_index = m_misc_state->m_fb_width * index;
124169
125   int x = m_rx;
170   int cdith = 0;
171   int adith = 0;
126172
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;
128176
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;
134178
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;
139182
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
150183   for (int j = 0; j <= length; j++)
151184   {
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;
164195
165      if(shade)
196      if (m_other_modes->z_source_sel)
166197      {
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;
171201      }
172202
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);
179204
180      if(zbuffer)
205      if (x >= clipx1 && x < clipx2 && valid_x)
181206      {
182         sz = z.w >> 13;
207         m_rdp->lookup_cvmask_derivatives(m_cvg[x], &offx, &offy);
183208
184         if (m_other_modes->z_source_sel)
209         if (m_rdp->GetTexPipe()->m_start_span)
185210         {
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            }
188219         }
189      }
220         else
221         {
222            sss = m_rdp->GetTexPipe()->m_precomp_s;
223            sst = m_rdp->GetTexPipe()->m_precomp_t;
224         }
190225
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);
194227
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);
196230
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))
198242         {
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);
204244
205            if(texture)
245            bool rendered = m_rdp->GetBlender()->Blend1Cycle(&fir, &fig, &fib, cdith, adith, partialreject, bsel0);
246
247                if (rendered)
206248            {
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)
208251               {
209                  m_rdp->TCDiv(ss, st, sw, &sss, &sst);
252                  m_rdp->ZStore(zbcur, zhbcur, sz);
210253               }
211               else // Hack for Bust-a-Move 2
212               {
213                  sss = ss;
214                  sst = st;
215               }
254            }
255         }
256      }
216257
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;
231266
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}
242270
243                  int LOD = (horstep >= vertstep) ? horstep : vertstep;
244                  LOD = (LOD >= m_dymax) ? LOD : m_dymax;
271void 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;
245275
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;
254284
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;
258288
259                  m_rdp->SetLODFrac(((LOD << 3) >> l_tile) & 0xff);
289   INT32 tile2 = (tilenum + 1) & 7;
290   INT32 tile1 = tilenum;
291   UINT32 prim_tile = tilenum;
260292
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;
277296
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);
306298
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);
317303
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;
328314
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;
344316
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)
346363            {
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);
364365            }
365            else if (m_other_modes->cycle_type == CYCLE_TYPE_2)
366            else
366367            {
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);
404369            }
370         }
371         else
372         {
373            sss = m_rdp->GetTexPipe()->m_precomp_s;
374            sst = m_rdp->GetTexPipe()->m_precomp_t;
375         }
405376
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);
410378
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);
423382
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);
425385
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)
427409               {
428                  m_rdp->ZStore(zbcur, zhbcur, sz, dzpix);
410                  m_rdp->ZStore(zbcur, zhbcur, sz);
429411               }
430412            }
431413         }
432414      }
433415
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
429void 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)
435458      {
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         }
440469      }
441      if (texture)
470
471      s.w += dsinc;
472      t.w += dtinc;
473      x += xinc;
474   }
475}
476
477void 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)
442496      {
443         s.w += dsinc;
444         t.w += dtinc;
445         w.w += dwinc;
497         UINT32 curpixel = fb_index + x;
498         m_rdp->GetFramebuffer()->Fill(curpixel);
446499      }
447      if (zbuffer)
448      {
449         z.w += dzinc;
450      }
451500
452501      x += xinc;
453502   }
src/mame/video/rdpspn16.h
r9854r9855
3434   public:
3535      Span() { }
3636
37      void   Draw(int index, int tilenum, bool shade, bool texture, bool zbuffer, bool flip);
3837      void   Dump();
3938      void   SetMachine(running_machine* machine);
4039
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
4145   public:
4246      int m_lx;
4347      int m_rx;
48      int m_unscissored_rx;
4449
4550      SpanParam m_s;
4651      SpanParam m_t;
r9854r9855
5156      SpanParam m_a;
5257      SpanParam m_z;
5358
54      UINT8 m_cvg[RDP_CVG_SPAN_MAX];
59      UINT16 m_cvg[RDP_CVG_SPAN_MAX];
5560
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
6961   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
7065      running_machine* m_machine;
7166      Processor* m_rdp;
7267      MiscState* m_misc_state;
src/mame/video/rdpfb.c
r9854r9855
55namespace N64
66{
77
8bool RDP::Framebuffer::Write(void *fb, UINT8* hb, UINT32 r, UINT32 g, UINT32 b)
8namespace RDP
99{
10
11void Framebuffer::Write(UINT32 curpixel, UINT32 r, UINT32 g, UINT32 b)
12{
1013   switch(m_misc_state->m_fb_size)
1114   {
1215      case PIXEL_SIZE_16BIT:
13         return Write16Bit((UINT16*)fb, hb, r, g, b);
16         Write16Bit(curpixel, r, g, b);
17         break;
1418
1519      case PIXEL_SIZE_32BIT:
16         return Write32Bit((UINT32*)fb, r, g, b);
20         Write32Bit(curpixel, r, g, b);
21         break;
1722
1823      default:
1924         fatalerror("Unsupported bit depth: %d\n", m_misc_state->m_fb_size);
2025         break;
2126   }
22
23   return false;
2427}
2528
26bool RDP::Framebuffer::Write16Bit(UINT16 *fb, UINT8* hb, UINT32 r, UINT32 g, UINT32 b)
29void Framebuffer::Write16Bit(UINT32 curpixel, UINT32 r, UINT32 g, UINT32 b)
2730{
2831#undef CVG_DRAW
29//#define CVG_DRAW
3032#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;
4034   r = covdraw;
4135   g = covdraw;
4236   b = covdraw;
4337#endif
4438
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)
4644   {
47      m_misc_state->m_curpixel_overlap = 0;
45      stricterror("FBWRITE_16: curpixel_cvg %d", m_misc_state->m_curpixel_cvg);
4846   }
47#endif
4948
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)
5253   {
53      memory_cvg = ((*fb & 1) << 2) + (*hb & 3) + 1;
54      finalcolor = RREADIDX16(fb) & 0xfffe;
5455   }
5556
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}
5892
59   UINT16 finalcolor = ((r >> 3) << 11) | ((g >> 3) << 6) | ((b >> 3) << 1);
93void 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;
6098
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
63105
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)
70107   {
71      *fb &= 0xfffe;
72      *fb |= ((newcvg >> 2) & 1);
73      *hb = (newcvg & 3);
74      return false;
108      finalcolor = RREADIDX32(fb) & 0xffffff00;
75109   }
76110
77111   switch(m_other_modes->cvg_dest)
78112   {
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)
81124         {
82            *fb = finalcolor | ((m_misc_state->m_curpixel_cvg >> 2) & 1);
83            *hb = (m_misc_state->m_curpixel_cvg & 3);
125            finalcvg = 7;
84126         }
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}
91145
92      case 1:
93         *fb = finalcolor | ((newcvg >> 2) & 1);
94         *hb = (newcvg & 3);
146void Framebuffer::Read(UINT32 curpixel)
147{
148   switch(m_misc_state->m_fb_size)
149   {
150      case PIXEL_SIZE_16BIT:
151         Read16Bit(curpixel);
95152         break;
96153
97      case 2:
98         *fb = finalcolor | 1;
99         *hb = 3;
154      case PIXEL_SIZE_32BIT:
155         Read32Bit(curpixel);
100156         break;
101157
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);
105160         break;
106161   }
162}
107163
108   return true;
164void 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   }
109181}
110182
111bool RDP::Framebuffer::Write32Bit(UINT32 *fb, UINT32 r, UINT32 g, UINT32 b)
183void Framebuffer::Read32Bit(UINT32 curpixel)
112184{
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;
117189   if (m_other_modes->image_read_en)
118190   {
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;
120193   }
194   else
195   {
196      m_misc_state->m_curpixel_memcvg = 7;
197      m_rdp->GetMemoryColor()->i.a = 0xff;
198   }
199}
121200
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;
201void 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;
126208
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;
131212
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;
137216   }
217}
138218
139   switch(m_other_modes->cvg_dest)
219void 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
226void 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
232void Framebuffer::Fill(UINT32 curpixel)
233{
234   switch(m_misc_state->m_fb_size)
140235   {
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);
150238         break;
151      case 1:
152         *fb = finalcolor | (newcvg << 5);
239
240      case PIXEL_SIZE_32BIT:
241         Fill32Bit(curpixel);
153242         break;
154      case 2:
155         *fb = finalcolor | 0xE0;
243
244      default:
245         fatalerror("Unsupported bit depth: %d\n", m_misc_state->m_fb_size);
156246         break;
157      case 3:
158         *fb = finalcolor | memory_alphachannel;
159         break;
160247   }
248}
161249
162   return true;
250void 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));
163263}
164264
265void 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
165275} // namespace N64
src/mame/video/rdpfb.h
r9854r9855
1515class Framebuffer
1616{
1717   public:
18      Framebuffer() { }
18      Framebuffer()
19      {
20         m_pre_wrap = false;
21      }
1922
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);
2127
28      void            SetProcessor(Processor* rdp) { m_rdp = rdp; }
2229      void            SetOtherModes(OtherModes* other_modes) { m_other_modes = other_modes; }
2330      void            SetMiscState(MiscState* misc_state) { m_misc_state = misc_state; }
31      void            SetPreWrap(bool prewrap) { m_pre_wrap = prewrap; }
2432
2533   private:
34      Processor*         m_rdp;
2635      OtherModes*         m_other_modes;
2736      MiscState*         m_misc_state;
37      bool            m_pre_wrap;
2838
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);
3147};
3248
3349} // namespace RDP
src/mame/video/n64.c
r9854r9855
2727#include "includes/n64.h"
2828#include "video/n64.h"
2929
30#define LOG_RDP_EXECUTION     
30#define LOG_RDP_EXECUTION      1
3131
3232static FILE *rdp_exec;
3333
3434/*****************************************************************************/
3535
36#define LookUpCC(A, B, C, D) state->m_rdp.GetCCLUT2()[(state->m_rdp.GetCCLUT1()[(A << 16) | (B << 8) | C] << 8) | D]
37
3836// The functions in this file should be moved into the parent Processor class.
3937#include "rdpfiltr.c"
4038
r9854r9855
4644
4745void Processor::GetAlphaCvg(UINT8 *comb_alpha)
4846{
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)
5052   {
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;
8755   }
88   else
56   if (m_other_modes.alpha_cvg_select)
8957   {
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);
10459   }
60   if (temp > 0xff)
61   {
62      temp = 0xff;
63   }
64   *comb_alpha = temp;
10565}
10666
10767/*****************************************************************************/
r9854r9855
11979         break;
12080
12181      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);
12383         break;
12484   }
12585}
r9854r9855
182142                  next_cvg = ((frame_buffer[(pixels + 1)^WORD_ADDR_XOR] & 1) << 2) | (hidden_buffer[(pixels + 1)^BYTE_ADDR_XOR] & 3);
183143               }
184144            }
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);
189148
190149            if(fsaa)
191150            {
r9854r9855
342301
343302/*****************************************************************************/
344303
304void 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
345310void Processor::TCDiv(INT32 ss, INT32 st, INT32 sw, INT32* sss, INT32* sst)
346311{
347   int shift;
312   int w_carry = 0;
313   if ((sw & 0x8000) || !(sw & 0x7fff))
314   {
315      w_carry = 1;
316   }
348317
349318   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++);
351322   shift -= 1;
352323
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;
355327
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];
357330
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
359341   {
360      *sss = (SIGN16(ss) * tlu_rcp) << 1;
361      *sst = (SIGN16(st) * tlu_rcp) << 1;
342      *sss = sprod << 1;//sw, tw çäåñü íå èçìåíèëèñü
343      *sst = tprod << 1;
362344   }
363345   else
364346   {
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);
368349   }
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);
369385}
370386
387INT32 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
399INT32 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
411void 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
427void 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
371450void Processor::SetSubAInputRGB(UINT8 **input_r, UINT8 **input_g, UINT8 **input_b, int code)
372451{
373452   switch (code & 0xf)
r9854r9855
468547{
469548   switch (code & 0x7)
470549   {
471      case 0:      *input = &m_lod_frac; break; //HACK
550      case 0:      *input = &m_lod_frac; break;
472551      case 1:      *input = &m_texel0_color.i.a; break;
473552      case 2:      *input = &m_texel1_color.i.a; break;
474553      case 3:      *input = &m_prim_color.i.a; break;
475554      case 4:      *input = &m_shade_color.i.a; break;
476555      case 5:      *input = &m_env_color.i.a; break;
477      case 6:      *input = &m_prim_lod_frac; break; //HACK
556      case 6:      *input = &m_prim_lod_frac; break;
478557      case 7:      *input = &m_zero_color.i.a; break;
479558   }
480559}
r9854r9855
563642    7,  1,  6, 0
564643};
565644
566const Processor::ZDecompressEntry Processor::m_z_decompress_table[8] =
645const Processor::ZDecompressEntry Processor::z_dec_table[8] =
567646{
568647   { 6, 0x00000 },
569648   { 5, 0x20000 },
r9854r9855
577656
578657/*****************************************************************************/
579658
580void Processor::BuildCompressedZTable()
659void Processor::z_build_com_table(void)
581660{
582   for(int j = 0; j < 0x40000; j++)
661   UINT16 altmem = 0;
662   for(int z = 0; z < 0x40000; z++)
583663   {
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   }
592811
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    }
596815}
597816
598void Processor::ZStore(UINT16* zb, UINT8* zhb, UINT32 z, UINT32 deltaz)
817void Processor::precalc_cvmask_derivatives(void)
599818{
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++)
604823   {
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++)
606834      {
607         break;
835         cvarray[i].cvg += ((i >> k) & 1);
608836      }
609      else
837
838      UINT16 masky = 0;
839      for (int k = 0; k < 4; k++)
610840      {
611         deltazmem--;
841         masky |= ((mask & (0xf000 >> (k << 2))) > 0) << k;
612842      }
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;
613850   }
614   if (deltazmem>15)
615   {
616      deltazmem=0;
617   }
618   *zb = m_z_compress_table[z] | (deltazmem>>2);
619   *zhb = (deltazmem & 3);
620851}
621852
622UINT32 Processor::DecompressZ(UINT16 *zb)
853UINT16 Processor::decompress_cvmask_frombyte(UINT8 x)
623854{
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;
627858}
628859
629UINT16 Processor::DecompressDZ(UINT16* zb, UINT8* zhb)
860void Processor::lookup_cvmask_derivatives(UINT32 mask, UINT8* offx, UINT8* offy)
630861{
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;
633872}
634873
874void 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
635887INT32 Processor::NormalizeDZPix(INT32 sum)
636888{
637889   if (sum & 0xc000)
r9854r9855
652904    return 0;
653905}
654906
655bool Processor::ZCompare(void* fb, UINT8* hb, UINT16* zb, UINT8* zhb, UINT32 sz, UINT16 dzpix)
907UINT32 Processor::ZDecompress(UINT32 zcurpixel)
656908{
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}
666912
667   sz &= 0x3ffff;
668   if (dzmem == 0x8000 && precision_factor < 3)
913UINT32 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
921UINT32 Processor::DZCompress(UINT32 value)
922{
923   INT32 j = 0;
924   for (; value > 1; j++, value >>= 1);
925   return j;
926}
927
928void 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)
669932   {
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;
671994   }
672   if (!precision_factor)
995}
996
997INT32 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
1004bool 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)
6731015   {
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);
6751020   }
676   else if (precision_factor == 1)
1021   else
6771022   {
678      dzmem = ((dzmem << 1) > 8) ? (dzmem << 1) : 8;
1023      oz = 0;
1024      dzmem = 1 << 0xf;
1025      zval = 0x3;
1026      rawdzmem = 0xf;
6791027   }
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)
6811038   {
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      }
6831053   }
684   if (dzmem == 0 && precision_factor < 3)
685   {
686      dzmem = 0xffff;
687   }
6881054   if (dzmem > 0x8000)
6891055   {
6901056      dzmem = 0xffff;
6911057   }
692   dznew =((dzmem > dzpix) ? dzmem : (UINT32)dzpix) << 3;
693   dznew &= 0x3ffff;
6941058
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;
7001062
1063   bool farther = (sz + dznew) >= oz;
1064   bool infront = sz < oz;
1065
7011066   if (force_coplanar)
7021067   {
703      farther = nearer = true;
1068      farther = true;
7041069   }
7051070
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);
7071074
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)
7091079   {
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;
7241083   }
7251084
726   if (!m_other_modes.image_read_en)
1085   if (!m_other_modes.z_compare_en)
7271086   {
728      memory_cvg = 7;
1087      return true;
7291088   }
7301089
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)
7351094   {
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;
7381096   }
739   if (m_misc_state.m_curpixel_cvg > 8)
740   {
741      m_misc_state.m_curpixel_cvg = 8;
742   }
7431097
7441098   switch(m_other_modes.z_mode)
7451099   {
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;
7571112   }
1113
1114   return false;
7581115}
7591116
7601117UINT32 Processor::GetLog2(UINT32 lod_clamp)
r9854r9855
9421299               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);
9431300         break;
9441301      }
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      }
9451332      case 0x0a:      // Tri_Tex
9461333      {
9471334         int lft = (command >> 23) & 0x1;
r9854r9855
9921379         buffer+=sprintf(buffer, "                       DSDY: %s, DTDY: %s, DWDY: %s\n", dsdy, dtdy, dwdy);
9931380         break;
9941381      }
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      }
9951432      case 0x0c:      // Tri_Shade
9961433      {
9971434         int lft = (command >> 23) & 0x1;
r9854r9855
10441481         buffer+=sprintf(buffer, "                       DRDY: %s, DGDY: %s, DBDY: %s, DADY: %s\n", drdy, dgdy, dbdy, dady);
10451482         break;
10461483      }
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      }
10471536      case 0x0e:      // Tri_TexShade
10481537      {
10491538         int lft = (command >> 23) & 0x1;
r9854r9855
11191608         buffer+=sprintf(buffer, "                       DSDY: %s, DTDY: %s, DWDY: %s\n", dsdy, dtdy, dwdy);
11201609         break;
11211610      }
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      }
11221686      case 0x24:
11231687      case 0x25:
11241688      {
r9854r9855
11691733
11701734/*****************************************************************************/
11711735
1172N64::RDP::Triangle::Triangle(running_machine *machine, bool shade, bool texture, bool zbuffer)
1736N64::RDP::Triangle::Triangle(running_machine *machine, bool shade, bool texture, bool zbuffer, bool rect, bool flip)
11731737{
1174   InitFromData(machine, shade, texture, zbuffer);
1738   InitFromData(machine, shade, texture, zbuffer, rect, flip);
11751739}
11761740
1177void N64::RDP::Triangle::InitFromData(running_machine *machine, bool shade, bool texture, bool zbuffer)
1741void N64::RDP::Triangle::InitFromData(running_machine *machine, bool shade, bool texture, bool zbuffer, bool rect, bool flip)
11781742{
11791743   m_machine = machine;
11801744   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();
11821746   m_misc_state = m_rdp->GetMiscState();
11831747   m_shade = shade;
11841748   m_texture = texture;
11851749   m_zbuffer = zbuffer;
1750   m_rect = rect;
11861751}
11871752
1753static 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
1761static 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
1769static 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
1785void 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
1857void 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
11881930void N64::RDP::Triangle::Draw()
11891931{
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];
11921935
11931936   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;
11961939
11971940   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;
11991941   int dsdeh = 0, dtdeh = 0, dwdeh = 0, drdeh = 0, dgdeh = 0, dbdeh = 0, dadeh = 0, dzdeh = 0;
12001942   int dsdxh = 0, dtdxh = 0, dwdxh = 0, drdxh = 0, dgdxh = 0, dbdxh = 0, dadxh = 0, dzdxh = 0;
12011943   int dsdyh = 0, dtdyh = 0, dwdyh = 0, drdyh = 0, dgdyh = 0, dbdyh = 0, dadyh = 0, dzdyh = 0;
1202   int xfrac = 0;
12031944
12041945   INT32 maxxmx = 0;
12051946   INT32 minxmx = 0;
12061947   INT32 maxxhx = 0;
12071948   INT32 minxhx = 0;
12081949
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)
12131954   {
12141955      texture_base += 16;
12151956      zbuffer_base += 16;
12161957   }
1217   if(m_zbuffer)
1958   if(m_texture)
12181959   {
12191960      zbuffer_base += 16;
12201961   }
12211962
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];
12281969
12291970   INT32 yl = (w1 & 0x3fff);
12301971   INT32 ym = ((w2 >> 16) & 0x3fff);
r9854r9855
12371978   INT32 dxhdy = (INT32)(w6);
12381979   INT32 dxmdy = (INT32)(w8);
12391980
1240   m_misc_state->m_max_level = ((w1 >> 19) & 7);
1241   int tilenum = (w1 >> 16) & 0x7;
1242
12431981   if (yl & 0x2000)  yl |= 0xffffc000;
12441982   if (ym & 0x2000)  ym |= 0xffffc000;
12451983   if (yh & 0x2000)  yh |= 0xffffc000;
r9854r9855
12812019   int dzde = m_cmd_data[zbuffer_base+2];
12822020   int dzdy = m_cmd_data[zbuffer_base+3];
12832021
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
12842035   int dzdy_dz = (dzdy >> 16) & 0xffff;
12852036   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   }
12962037
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                  );
12992051
1300   int xright = xh;
1301   int xleft = xm;
2052   int xleft_inc = (dxmdy >> 2) & ~1;
2053   int xright_inc = (dxhdy >> 2) & ~1;
13022054
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;
13082057
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
13152058   int sign_dxhdy = (dxhdy & 0x80000000) ? 1 : 0;
13162059   int do_offset = !(sign_dxhdy ^ (flip));
13172060
r9854r9855
13262069      dadeh = dade >> 9;   dadyh = dady >> 9;
13272070      dzdeh = dzde >> 9;   dzdyh = dzdy >> 9;
13282071
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);
13462080   }
13472081   else
13482082   {
13492083      dsdiff = dtdiff = dwdiff = drdiff = dgdiff = dbdiff = dadiff = dzdiff = 0;
1350      dseoff = dteoff = dweoff = dreoff = dgeoff = dbeoff = daeoff = dzeoff = 0;
13512084   }
13522085
13532086   dsdxh = dsdx >> 8;
r9854r9855
13592092   dadxh = dadx >> 8;
13602093   dzdxh = dzdx >> 8;
13612094
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;
13672103
1368   if(ylfar >= 0x1000)
1369   {
1370      ylfar = 0x0fff;
1371   }
2104   int xfrac = ((xright >> 8) & 0xff);
13722105
13732106   if(flip)
13742107   {
r9854r9855
13762109      {
13772110         if (k == ym)
13782111         {
1379            xleft = xl;
1380            xleft_inc = dxldy >> 2;
2112            xleft = xl & ~1;
2113            xleft_inc = (dxldy >> 2) & ~1;
13812114         }
13822115
13832116         int xstart = xleft >> 16;
13842117         int xend = xright >> 16;
13852118         int j = k >> 2;
13862119         int spix = k & 3;
2120         valid_y = !(k < yh || k >= yl);
13872121
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)
13932123         {
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)
14032130            {
1404               minxmx = maxxmx = xstart;
1405               minxhx = maxxhx = xend;
2131               maxxmx = 0;
2132               minxhx = 0xfff;
14062133            }
1407            else
2134
2135            if (valid_y)
14082136            {
1409               minxmx = (xstart < minxmx) ? xstart : minxmx;
14102137               maxxmx = (xstart > maxxmx) ? xstart : maxxmx;
14112138               minxhx = (xend < minxhx) ? xend : minxhx;
1412               maxxhx = (xend > maxxhx) ? xend : maxxhx;
14132139            }
1414         }
14152140
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)
14212142            {
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);
14262146            }
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         }
14612147
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)
14682149            {
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);
14732161            }
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            }
14962162         }
14972163
1498         m = xend + 1;
1499
1500         if (k >= yh && length >= 0 && k <= yl)
2164         if (spix == 3)
15012165         {
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;
15262174         }
15272175
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         }
15482176         xleft += xleft_inc;
15492177         xright += xright_inc;
15502178      }
r9854r9855
15552183      {
15562184         if (k == ym)
15572185         {
1558            xleft = xl;
1559            xleft_inc = dxldy >> 2;
2186            xleft = xl & ~1;
2187            xleft_inc = (dxldy >> 2) & ~1;
15602188         }
15612189
15622190         int xstart = xleft >> 16;
15632191         int xend = xright >> 16;
15642192         int j = k >> 2;
15652193         int spix = k & 3;
2194         valid_y = !(k < yh || k >= yl);
15662195
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)
15722197         {
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)
15822204            {
1583               minxmx = maxxmx = xstart;
1584               minxhx = maxxhx = xend;
2205               maxxhx = 0;
2206               minxmx = 0xfff;
15852207            }
1586            else
2208
2209            if (valid_y)
15872210            {
15882211               minxmx = (xstart < minxmx) ? xstart : minxmx;
1589               maxxmx = (xstart > maxxmx) ? xstart : maxxmx;
1590               minxhx = (xend < minxhx) ? xend : minxhx;
15912212               maxxhx = (xend > maxxhx) ? xend : maxxhx;
15922213            }
1593         }
15942214
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)
16012216            {
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);
16062220            }
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         }
16202221
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)
16272223            {
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);
16312234            }
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            }
16432235         }
16442236
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
16792237         if (spix == 3)
16802238         {
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;
16982247         }
16992248         xleft += xleft_inc;
17002249         xright += xright_inc;
17012250      }
17022251   }
17032252
1704   m_rdp->RenderSpans(yh >> 2, yl >> 2, tilenum, m_shade, m_texture, m_zbuffer, flip);
2253   m_rdp->RenderSpans(yh >> 2, yl >> 2, tilenum, flip);
17052254}
17062255
17072256/*****************************************************************************/
r9854r9855
17122261
17132262void N64::RDP::Processor::Triangle(bool shade, bool texture, bool zbuffer)
17142263{
1715   N64::RDP::Triangle tri(m_machine, shade, texture, zbuffer);
2264   N64::RDP::Triangle tri(m_machine, shade, texture, zbuffer, false, false);
17162265   tri.Draw();
17172266}
17182267
r9854r9855
17562305   Triangle(true, true, true);
17572306}
17582307
1759void N64::RDP::Rectangle::InitFromBuffer(UINT32 *data)
2308void N64::RDP::Processor::CmdTexRect(UINT32 w1, UINT32 w2)
17602309{
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;
17662311
1767void 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];
17792314
1780void 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();
17842366}
17852367
17862368void N64::RDP::Processor::CmdTexRectFlip(UINT32 w1, UINT32 w2)
17872369{
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();
17902426}
17912427
17922428void N64::RDP::Processor::CmdSyncLoad(UINT32 w1, UINT32 w2)
r9854r9855
18612497
18622498void N64::RDP::Processor::CmdSetOtherModes(UINT32 w1, UINT32 w2)
18632499{
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
19002536
19012537   // These should belong to the Blender class
19022538   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);
19032539   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);
19042540   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);
19052541   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;
19082542}
19092543
19102544void N64::RDP::Processor::CmdLoadTLUT(UINT32 w1, UINT32 w2)
19112545{
1912   const int tilenum = (w2 >> 24) & 7;
1913   N64::RDP::Tile* tex_tile = &m_tiles[tilenum];
2546   Tile* tile = GetTiles();
19142547
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;
19182553
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
19192562   switch (m_misc_state.m_ti_size)
19202563   {
19212564      case PIXEL_SIZE_16BIT:
19222565      {
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         }
19242570         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;
19272573
1928         for (int i = 0; i < count; i++)
2574         for (int i = 0; i < count; i += 4)
19292575         {
1930            if((i*4) < 0x400)
2576            if (dststart < 2048)
19312577            {
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;
19362584            }
19372585         }
19382586         break;
19392587      }
1940      default:   fatalerror("RDP::LoadTLUT: size = %d\n", m_misc_state.m_ti_size);
2588      default:   fatalerror("RDP: load_tlut: size = %d\n", m_misc_state.m_ti_size);
19412589   }
19422590}
19432591
r9854r9855
19532601
19542602void N64::RDP::Processor::CmdLoadBlock(UINT32 w1, UINT32 w2)
19552603{
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();
19612605
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();
19662608
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);
19682614
1969   if (width > 2048) // Hack for Magical Tetris Challenge
2615   if (sh < sl)
19702616   {
1971      width = 2048;
2617      fatalerror("load_block: sh < sl");
19722618   }
19732619
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)
19752624   {
1976      fatalerror( "load block: unaligned ti_address 0x%x",m_misc_state.m_ti_address ); // Rat Attack, Frogger 2 prototype
2625      width = (width & ~7) + 8;
19772626   }
2627   width >>= 3;
19782628
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;
19822630
1983   slindwords = sl;
2631   int tiwinwords = m_misc_state.m_ti_width;
2632   UINT32 slinwords = sl;
19842633
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;
19922636
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;
19972640
1998   if (width & 7)   // Sigh... another Rat Attack-specific thing.
1999   {
2000      width = (width & (~7)) + 8;
2001   }
2002
20032641   if (dxt != 0)
20042642   {
20052643      int j = 0;
20062644      int t = 0;
20072645      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)
20142648      {
2015         oldt = t;
2016         t = ((j >> 11) & 1) ? xorval : 0;
2017         if (t > oldt)
2649         for (int i = 0; i < width; i ++)
20182650         {
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;
20202666         }
2021         ptr = tb + i;
2022         tc[ptr & 0x3ff] = src[i ^ t];
2023         tc[(ptr + 1) & 0x3ff] = src[(i + 1) ^ t];
2024         j += dxt;
20252667      }
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);
20272718   }
2028   else // Needed by Pilotwings 64 intro, Top Gear Rally intro
2719   else
20292720   {
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;
20332766   }
20342767}
20352768
20362769void N64::RDP::Processor::CmdLoadTile(UINT32 w1, UINT32 w2)
20372770{
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;
20422773
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);
20472778
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;
20522783
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;
20572786
2058   int width = (sh - sl) + 1;
2059   int height = (th - tl) + 1;
2060
2787   int topad;
20612788   if (m_misc_state.m_ti_size < 3)
20622789   {
2063      toppad = (width * m_misc_state.m_ti_size) & 0x7;
2790      topad = (width * m_misc_state.m_ti_size) & 0x7;
20642791   }
20652792   else
20662793   {
2067      toppad = (width << 2) & 0x7;
2794      topad = (width << 2) & 0x7;
20682795   }
2069   toppad = 0; // Currently disabled
2796   topad = 0; // ????
20702797
20712798   switch (m_misc_state.m_ti_size)
20722799   {
20732800      case PIXEL_SIZE_8BIT:
20742801      {
2075         UINT8 *src = (UINT8*)rdram;
2802         UINT32 src = m_misc_state.m_ti_address;
20762803         UINT8 *tc = GetTMEM();
2077         int tb = m_tiles[tilenum].tmem;
2804         int tb = tile[tilenum].tmem << 3;
20782805
2079         if (tb + (width * height) > 4096)
2080         {
2081            height = (4096 - tb) / line; // Per Ziggy
2082         }
2083
20842806         for (int j = 0; j < height; j++)
20852807         {
2086            int tline = tb + (tex_tile->line * j);
2808            int tline = tb + ((tile[tilenum].line << 3) * j);
20872809            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
20902810
2811            int xorval8 = ((j & 1) ? BYTE_XOR_DWORD_SWAP : BYTE_ADDR_XOR);//ïîïðîùå,÷åì ó Ziggy
20912812            for (int i = 0; i < width; i++)
20922813            {
2093               tc[(tline + i) ^ xorval8] = src[(m_misc_state.m_ti_address + s + i) ^ BYTE_ADDR_XOR];
2814               tc[((tline + i) ^ xorval8) & 0xfff] = RREADADDR8(src + s + i);
20942815            }
20952816         }
20962817         break;
20972818      }
20982819      case PIXEL_SIZE_16BIT:
20992820      {
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;
21022822         UINT16 *tc = GetTMEM16();
2103         int tb = (tex_tile->tmem / 2);
2104         int taddr;
2823         UINT16 yuvword;
21052824
2106         if ((tb + (width * height)) > 2048)
2825         if (tile[tilenum].format != FORMAT_YUV)
21072826         {
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            }
21092840         }
2110
2111         for (int j = 0; j < height; j++)
2841         else
21122842         {
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++)
21172844            {
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;
21232849
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++)
21282851               {
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;
21302856               }
21312857            }
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            //}
21362858         }
21372859         break;
21382860      }
21392861      case PIXEL_SIZE_32BIT:
21402862      {
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);
21452866
2146         if (tb + (width * height) > 1024)
2867         for (int j = 0; j < height; j++)
21472868         {
2148            height = (1024 - tb) / (line/4); // Per Ziggy
2149         }
2869            int tline = tb + ((tile[tilenum].line << 2) * j);
21502870
2151         for (int j = 0; j < height; j++)
2152         {
2153            int tline = tb + ((tex_tile->line / 2) * j);
21542871            int s = ((j + tl) * m_misc_state.m_ti_width) + sl;
2155            int xorval32cur = (j & 1) ? xorval32 : 0;
2872            int xorval32cur = (j & 1) ? WORD_XOR_DWORD_SWAP : WORD_ADDR_XOR;
21562873            for (int i = 0; i < width; i++)
21572874            {
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;
21592879            }
21602880         }
21612881         break;
r9854r9855
21722892
21732893   tex_tile->format   = (w1 >> 21) & 0x7;
21742894   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;
21772897   tex_tile->palette   = (w2 >> 20) & 0xf;
21782898   tex_tile->ct      = (w2 >> 19) & 0x1;
21792899   tex_tile->mt      = (w2 >> 18) & 0x1;
r9854r9855
21832903   tex_tile->ms      = (w2 >>  8) & 0x1;
21842904   tex_tile->mask_s   = (w2 >>  4) & 0xf;
21852905   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;
21892906}
21902907
21912908void N64::RDP::Processor::CmdFillRect(UINT32 w1, UINT32 w2)
21922909{
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;
21942914
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();
21962936}
21972937
21982938void N64::RDP::Processor::CmdSetFogColor(UINT32 w1, UINT32 w2)
r9854r9855
24083148   UINT32 cmd = (m_cmd_data[0] >> 24) & 0x3f;
24093149   UINT32 cmd_length = (m_cmd_ptr + 1) * 4;
24103150
3151   SetStatusReg(GetStatusReg() &~ DP_STATUS_FREEZE);
3152
24113153   // check if more data is needed
24123154   if (cmd_length < rdp_command_length[cmd])
24133155   {
r9854r9855
25153257
25163258   state->m_rdp.GetFramebuffer()->SetOtherModes(state->m_rdp.GetOtherModes());
25173259   state->m_rdp.GetFramebuffer()->SetMiscState(state->m_rdp.GetMiscState());
3260   state->m_rdp.GetFramebuffer()->SetProcessor(&state->m_rdp);
25183261
25193262   state->m_rdp.GetTexPipe()->SetMachine(machine);
25203263
src/mame/video/n64.h
r9854r9855
55#include "video/rdpblend.h"
66#include "video/rdptri.h"
77#include "video/rdpfb.h"
8#include "video/rdpfrect.h"
9#include "video/rdptrect.h"
108#include "video/rdptpipe.h"
119#include "video/rdpspn16.h"
12#include "video/rdpfetch.h"
1310
1411/*****************************************************************************/
1512
r9854r9855
3734#define XOR_SWAP_WORD   2
3835#define XOR_SWAP_DWORD   1
3936
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
4075//sign-extension macros
76#define SIGN22(x)   (((x) & 0x200000) ? ((x) | ~0x3fffff) : ((x) & 0x3fffff))
4177#define SIGN17(x)   (((x) & 0x10000) ? ((x) | ~0x1ffff) : ((x) & 0x1ffff))
4278#define SIGN16(x)   (((x) & 0x8000) ? ((x) | ~0xffff) : ((x) & 0xffff))
79#define SIGN13(x)   (((x) & 0x1000) ? ((x) | ~0x1fff) : ((x) & 0x1fff))
4380#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))
4483
84#define KURT_AKELEY_SIGN9(x)   ((((x) & 0x180) == 0x180) ? ((x) | ~0x1ff) : ((x) & 0x1ff))
85
4586/*****************************************************************************/
4687
4788namespace N64
r9854r9855
86127   public:
87128      int format;   // Image data format: RGBA, YUV, CI, IA, I
88129      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
91132      int palette; // Palette number for 4b CI texels
92133      int ct, mt, cs, ms; // Clamp / mirror enable bits for S / T direction
93134      int mask_t, shift_t, mask_s, shift_s; // Mask values / LOD shifts
r9854r9855
101142      MiscState()
102143      {
103144         m_curpixel_cvg = 0;
145         m_curpixel_memcvg = 0;
146         m_curpixel_cvbit = 0;
104147         m_curpixel_overlap = 0;
105148
106149         m_max_level = 0;
r9854r9855
121164      UINT32 m_ti_address;
122165
123166      UINT32 m_curpixel_cvg;
167      UINT32 m_curpixel_memcvg;
168      UINT32 m_curpixel_cvbit;
124169      UINT32 m_curpixel_overlap;
125170
126171      UINT8 m_random_seed;
r9854r9855
232277      UINT8 *blender2b_a[2];
233278};
234279
280struct 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
235288class Processor
236289{
237290   public:
r9854r9855
245298         m_current = 0;
246299         m_status = 0x88;
247300
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
289301         for (int i = 0; i < 8; i++)
290302         {
291303            m_tiles[i].num = i;
r9854r9855
325337
326338         m_machine = NULL;
327339
328         memset(m_hidden_bits, 3, 4194304); // Hack / fix for letters in Rayman 2
340         //memset(m_hidden_bits, 3, 8388608);
329341
330342         m_prim_lod_frac = 0;
331343         m_lod_frac = 0;
r9854r9855
342354            m_gamma_dither_table[i] <<= 1;
343355         }
344356
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         }
346389      }
347390
348391      ~Processor() { }
349392
393      UINT8*   ReplicatedRGBA() { return m_replicated_rgba; }
394
350395      void   Dasm(char *buffer);
351396
352397      void   ProcessList();
353398      UINT32   ReadData(UINT32 address);
354399
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
355423      void   InitInternalState()
356424      {
357425         if(m_machine)
r9854r9855
362430            UINT8 *normpoint = memory_region(m_machine, "normpoint");
363431            UINT8 *normslope = memory_region(m_machine, "normslope");
364432
365            for(int i = 0; i < 64; i++)
433            for(INT32 i = 0; i < 64; i++)
366434            {
367435               m_norm_point_rom[i] = (normpoint[(i << 1) + 1] << 8) | normpoint[i << 1];
368436               m_norm_slope_rom[i] = (normslope[(i << 1) + 1] << 8) | normslope[i << 1];
r9854r9855
430498      Color*      GetTexel1Color() { return &m_texel1_color; }
431499      void      SetTexel1Color(UINT32 color) { m_texel1_color.c = color; }
432500
501      Color*      GetNextTexelColor() { return &m_next_texel_color; }
502      void      SetNextTexelColor(UINT32 color) { m_next_texel_color.c = color; }
503
433504      Color*      GetShadeColor() { return &m_shade_color; }
434505      void      SetShadeColor(UINT32 color) { m_shade_color.c = color; }
435506
r9854r9855
442513      Color*      GetOne() { return &m_one_color; }
443514      Color*      GetZero() { return &m_zero_color; }
444515
445      UINT8*      GetLODFrac() { return &m_lod_frac; }
516      UINT8      GetLODFrac() { return m_lod_frac; }
446517      void      SetLODFrac(UINT8 lod_frac) { m_lod_frac = lod_frac; }
447518
448      UINT8*      GetPrimLODFrac() { return &m_prim_lod_frac; }
519      UINT8      GetPrimLODFrac() { return m_prim_lod_frac; }
449520      void      SetPrimLODFrac(UINT8 prim_lod_frac) { m_prim_lod_frac = prim_lod_frac; }
450521
451522      // 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);
452527      void      SetSubAInputRGB(UINT8 **input_r, UINT8 **input_g, UINT8 **input_b, int code);
453528      void      SetSubBInputRGB(UINT8 **input_r, UINT8 **input_g, UINT8 **input_b, int code);
454529      void      SetMulInputRGB(UINT8 **input_r, UINT8 **input_g, UINT8 **input_b, int code);
r9854r9855
464539      Tile*      GetTiles(){ return m_tiles; }
465540
466541      // 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; }
471542      UINT8      GetRandom() { return m_misc_state.m_random_seed += 0x13; }
472543
473544      // YUV Factors
r9854r9855
485556      // Render-related (move into eventual drawing-related classes?)
486557      Rectangle*      GetScissor() { return &m_scissor; }
487558      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);
488560      UINT32         GetLog2(UINT32 lod_clamp);
489      void         RenderSpans(int start, int end, int tilenum, bool shade, bool texture, bool zbuffer, bool flip);
561      void         RenderSpans(int start, int end, int tilenum, bool flip);
490562      UINT8*         GetHiddenBits() { return m_hidden_bits; }
491563      void         GetAlphaCvg(UINT8 *comb_alpha);
492564      const UINT8*   GetBayerMatrix() const { return s_bayer_matrix; }
r9854r9855
495567      int            GetCurrFIFOIndex() const { return m_cmd_cur; }
496568      UINT32         GetFillColor32() const { return m_fill_color; }
497569
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);
501574      INT32         NormalizeDZPix(INT32 sum);
502      bool         ZCompare(void* fb, UINT8* hb, UINT16* zb, UINT8* zhb, UINT32 sz, UINT16 dzpix);
575      bool         ZCompare(UINT32 zcurpixel, UINT32 dzcurpixel, UINT32 sz, UINT16 dzpix);
503576
504577      // Fullscreen update-related
505578      void         VideoUpdate(bitmap_t *bitmap);
r9854r9855
548621      UINT32      AddLeftCvg(UINT32 x, UINT32 k);
549622
550623      UINT32*      GetCommandData() { return m_cmd_data; }
624      UINT32*      GetTempRectData() { return m_temp_rect_data; }
551625
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
552650   protected:
553651      Blender         m_blender;
554652      Framebuffer      m_framebuffer;
r9854r9855
571669      Color      m_combined_color;
572670      Color      m_texel0_color;
573671      Color      m_texel1_color;
672      Color      m_next_texel_color;
574673      Color      m_shade_color;
575674      Color      m_key_scale;
576675      Color      m_noise_color;
r9854r9855
582681
583682      UINT32      m_fill_color;
584683
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)];
589692
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
590697      UINT32      m_cmd_data[0x1000];
698      UINT32      m_temp_rect_data[0x1000];
699
591700      int       m_cmd_ptr;
592701      int       m_cmd_cur;
593702
r9854r9855
627736      INT32 m_gamma_table[256];
628737      INT32 m_gamma_dither_table[0x4000];
629738
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
630746      class ZDecompressEntry
631747      {
632748         public:
r9854r9855
634750            UINT32 add;
635751      };
636752
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];
640756
641757      // Internal screen-update functions
642758      void         VideoUpdate16(bitmap_t *bitmap);
src/emu/cpu/rsp/rsp.c
r9854r9855
77#include "emu.h"
88#include "debugger.h"
99#include "rsp.h"
10#include "rspdiv.h"
1011
1112CPU_DISASSEMBLE( rsp );
1213
r9854r9855
1819#define RSP_TEST_SYNC                   0
1920
2021#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))
2526
2627#define PRINT_ACCUM(x)     mame_printf_debug("A%d: %08X|%08X\n", (x), \
2728                            (UINT32)( ( ACCUM(x) >> 32 ) & 0x00000000ffffffff ),    \
r9854r9855
4647#define JUMP_REL_L(offset,l)   { rsp->nextpc = 0x04001000 | ((rsp->pc + ((offset) << 2)) & 0xfff); rsp->r[l] = rsp->pc + 4; }
4748#define JUMP_PC(addr)         { rsp->nextpc = 0x04001000 | ((addr) & 0xfff); }
4849#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; }
4951
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)]
5455
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)]
5859
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)
6263
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)])
6665
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]
7070
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
9271#define CARRY_FLAG(x)         ((rsp->flag[0] & (1 << ((x)))) ? 1 : 0)
9372#define CLEAR_CARRY_FLAGS()      { rsp->flag[0] &= ~0xff; }
9473#define SET_CARRY_FLAG(x)      { rsp->flag[0] |= (1 << ((x))); }
r9854r9855
10483#define SET_ZERO_FLAG(x)      { rsp->flag[0] |= (1 << (8+(x))); }
10584#define CLEAR_ZERO_FLAG(x)      { rsp->flag[0] &= ~(1 << (8+(x))); }
10685
107#define ROPCODE(pc)      memory_decrypted_read_dword(rsp->program, pc)
86#define EXTENSION_FLAG(x)      ((rsp.flag[2] & (1 << ((x)))) ? 1 : 0)
10887
88#define ROPCODE(pc)      rsp->program->read_dword(pc)
89
10990INLINE UINT8 READ8(rsp_state *rsp, UINT32 address)
11091{
92   UINT8 ret;
11193   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;
11397}
11498
11599INLINE UINT16 READ16(rsp_state *rsp, UINT32 address)
116100{
101   UINT16 ret;
117102   address = 0x04000000 | (address & 0xfff);
118103
119   if (address & 1)
104   if(address & 1)
120105   {
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);
123107   }
108   else
109   {
110      ret = rsp->program->read_word(address);
111   }
124112
125   return rsp->program->read_word(address);
113   printf("%04xr%04x\n", address & 0x0000ffff, ret);
114
115   return ret;
126116}
127117
128118INLINE UINT32 READ32(rsp_state *rsp, UINT32 address)
129119{
120   UINT32 ret;
130121   address = 0x04000000 | (address & 0xfff);
131122
132   if (address & 3)
123   if(address & 3)
133124   {
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) |
136126            ((rsp->program->read_byte(address + 1) & 0xff) << 16) |
137127            ((rsp->program->read_byte(address + 2) & 0xff) << 8) |
138128            ((rsp->program->read_byte(address + 3) & 0xff) << 0);
139129   }
130   else
131   {
132      ret = rsp->program->read_dword(address);
133   }
140134
141   return rsp->program->read_dword(address);
135   printf("%04xr%08x\n", address & 0x0000ffff, ret);
136   return ret;
142137}
143138
144139INLINE void WRITE8(rsp_state *rsp, UINT32 address, UINT8 data)
145140{
146141   address = 0x04000000 | (address & 0xfff);
142   printf("%04x:%02x\n", address & 0x0000ffff, data);
147143   rsp->program->write_byte(address, data);
148144}
149145
150146INLINE void WRITE16(rsp_state *rsp, UINT32 address, UINT16 data)
151147{
152148   address = 0x04000000 | (address & 0xfff);
149   printf("%04x:%04x\n", address & 0x0000ffff, data);
153150
154   if (address & 1)
151   if(address & 1)
155152   {
156      //fatalerror("RSP: WRITE16: unaligned %08X, %04X at %08X\n", address, data, rsp->ppc);
157153      rsp->program->write_byte(address + 0, (data >> 8) & 0xff);
158154      rsp->program->write_byte(address + 1, (data >> 0) & 0xff);
159155      return;
r9854r9855
165161INLINE void WRITE32(rsp_state *rsp, UINT32 address, UINT32 data)
166162{
167163   address = 0x04000000 | (address & 0xfff);
164   printf("%04x:%08x\n", address & 0x0000ffff, data);
168165
169   if (address & 3)
166   if(address & 3)
170167   {
171      //osd_die("RSP: WRITE32: unaligned %08X, %08X at %08X\n", address, data, rsp->ppc);
172168      rsp->program->write_byte(address + 0, (data >> 24) & 0xff);
173169      rsp->program->write_byte(address + 1, (data >> 16) & 0xff);
174170      rsp->program->write_byte(address + 2, (data >> 8) & 0xff);
r9854r9855
183179
184180static UINT32 get_cop0_reg(rsp_state *rsp, int reg)
185181{
186   if (reg >= 0 && reg < 8)
182   reg &= 0xf;
183   if (reg < 8)
187184   {
188185      return (rsp->config->sp_reg_r)(rsp->device, reg, 0x00000000);
189186   }
r9854r9855
191188   {
192189      return (rsp->config->dp_reg_r)(rsp->device, reg - 8, 0x00000000);
193190   }
194   else
195   {
196      fatalerror("RSP: get_cop0_reg: %d", reg);
197   }
191
192   return 0;
198193}
199194
200195static void set_cop0_reg(rsp_state *rsp, int reg, UINT32 data)
201196{
202   if (reg >= 0 && reg < 8)
197   reg &= 0xf;
198   if (reg < 8)
203199   {
204200      (rsp->config->sp_reg_w)(rsp->device, reg, data, 0x00000000);
205201   }
r9854r9855
207203   {
208204      (rsp->config->dp_reg_w)(rsp->device, reg - 8, data, 0x00000000);
209205   }
210   else
211   {
212      fatalerror("RSP: set_cop0_reg: %d, %08X\n", reg, data);
213   }
214206}
215207
216208static void unimplemented_opcode(rsp_state *rsp, UINT32 op)
r9854r9855
257249
258250/*****************************************************************************/
259251
260static const int vector_elements_1[16][8] =
252static const int vector_elements[16][8] =
261253{
262254   { 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
280static const int vector_elements_2[16][8] =
281{
282   { 0, 1, 2, 3, 4, 5, 6, 7 },      // none
283255   { 0, 1, 2, 3, 4, 5, 6, 7 },      // ???
284256   { 0, 0, 2, 2, 4, 4, 6, 6 },      // 0q
285257   { 1, 1, 3, 3, 5, 5, 7, 7 },      // 1q
r9854r9855
335307   //   makes me retch uncontrollably.
336308   for(accumIdx = 0; accumIdx < 8; accumIdx++ )
337309   {
338      rsp->accum[accumIdx].l = 0;
310      rsp->accum[accumIdx].q = 0;
339311   }
340312
341313   rsp->sr = RSP_STATUS_HALT;
r9854r9855
419391         // Load 1 byte to vector byte index
420392
421393         ea = (base) ? rsp->r[base] + offset : offset;
422         W_VREG_B(dest, index, READ8(rsp, ea));
394         VREG_B(dest, index) = READ8(rsp, ea);
423395         break;
424396      }
425397      case 0x01:      /* LSV */
r9854r9855
437409
438410         for (i=index; i < end; i++)
439411         {
440            W_VREG_B(dest, i, READ8(rsp, ea));
412            VREG_B(dest, i) = READ8(rsp, ea);
441413            ea++;
442414         }
443415         break;
r9854r9855
457429
458430         for (i=index; i < end; i++)
459431         {
460            W_VREG_B(dest, i, READ8(rsp, ea));
432            VREG_B(dest, i) = READ8(rsp, ea);
461433            ea++;
462434         }
463435         break;
r9854r9855
477449
478450         for (i=index; i < end; i++)
479451         {
480            W_VREG_B(dest, i, READ8(rsp, ea));
452            VREG_B(dest, i) = READ8(rsp, ea);
481453            ea++;
482454         }
483455         break;
r9854r9855
498470
499471         for (i=index; i < end; i++)
500472         {
501            W_VREG_B(dest, i, READ8(rsp, ea));
473            VREG_B(dest, i) = READ8(rsp, ea);
502474            ea++;
503475         }
504476         break;
r9854r9855
520492
521493         for (i=index; i < end; i++)
522494         {
523            W_VREG_B(dest, i, READ8(rsp, ea));
495            VREG_B(dest, i) = READ8(rsp, ea);
524496            ea++;
525497         }
526498         break;
r9854r9855
538510
539511         for (i=0; i < 8; i++)
540512         {
541            W_VREG_S(dest, i, READ8(rsp, ea + (((16-index) + i) & 0xf)) << 8);
513            VREG_S(dest, i) = READ8(rsp, ea + (((16-index) + i) & 0xf)) << 8;
542514         }
543515         break;
544516      }
r9854r9855
555527
556528         for (i=0; i < 8; i++)
557529         {
558            W_VREG_S(dest, i, READ8(rsp, ea + (((16-index) + i) & 0xf)) << 7);
530            VREG_S(dest, i) = READ8(rsp, ea + (((16-index) + i) & 0xf)) << 7;
559531         }
560532         break;
561533      }
r9854r9855
572544
573545         for (i=0; i < 8; i++)
574546         {
575            W_VREG_S(dest, i, READ8(rsp, ea + (((16-index) + (i<<1)) & 0xf)) << 7);
547            VREG_S(dest, i) = READ8(rsp, ea + (((16-index) + (i<<1)) & 0xf)) << 7;
576548         }
577549         break;
578550      }
r9854r9855
585557         //
586558         // Loads a byte as the bits 14-7 of upper or lower quad, with 4-byte stride
587559
588         fatalerror("RSP: LFV\n");
589
590         if (index & 0x7)   fatalerror("RSP: LFV: index = %d at %08X\n", index, rsp->ppc);
591
592560         ea = (base) ? rsp->r[base] + (offset * 16) : (offset * 16);
593561
594562         // 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);
596563
597564         end = (index >> 1) + 4;
598565
599566         for (i=index >> 1; i < end; i++)
600567         {
601            W_VREG_S(dest, i, READ8(rsp, ea) << 7);
568            VREG_S(dest, i) = READ8(rsp, ea) << 7;
602569            ea += 4;
603570         }
604571         break;
r9854r9855
622589
623590         for (i=(16 - index); i < end; i++)
624591         {
625            W_VREG_B(dest, i & 0xf, READ8(rsp, ea));
592            VREG_B(dest, i & 0xf) = READ8(rsp, ea);
626593            ea += 4;
627594         }
628595         break;
r9854r9855
654621         for (i=vs; i < ve; i++)
655622         {
656623            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);
659626
660627            ea += 2;
661628         }
r9854r9855
694661         // Stores 1 byte from vector byte index
695662
696663         ea = (base) ? rsp->r[base] + offset : offset;
697         WRITE8(rsp, ea, R_VREG_B(dest, index));
664         WRITE8(rsp, ea, VREG_B(dest, index));
698665         break;
699666      }
700667      case 0x01:      /* SSV */
r9854r9855
712679
713680         for (i=index; i < end; i++)
714681         {
715            WRITE8(rsp, ea, R_VREG_B(dest, i));
682            WRITE8(rsp, ea, VREG_B(dest, i));
716683            ea++;
717684         }
718685         break;
r9854r9855
732699
733700         for (i=index; i < end; i++)
734701         {
735            WRITE8(rsp, ea, R_VREG_B(dest, i));
702            WRITE8(rsp, ea, VREG_B(dest, i));
736703            ea++;
737704         }
738705         break;
r9854r9855
752719
753720         for (i=index; i < end; i++)
754721         {
755            WRITE8(rsp, ea, R_VREG_B(dest, i));
722            WRITE8(rsp, ea, VREG_B(dest, i));
756723            ea++;
757724         }
758725         break;
r9854r9855
772739
773740         for (i=index; i < end; i++)
774741         {
775            WRITE8(rsp, ea, R_VREG_B(dest, i & 0xf));
742            WRITE8(rsp, ea, VREG_B(dest, i & 0xf));
776743            ea++;
777744         }
778745         break;
r9854r9855
795762
796763         for (i=index; i < end; i++)
797764         {
798            WRITE8(rsp, ea, R_VREG_B(dest, ((i + o) & 0xf)));
765            WRITE8(rsp, ea, VREG_B(dest, ((i + o) & 0xf)));
799766            ea++;
800767         }
801768         break;
r9854r9855
816783         {
817784            if ((i & 0xf) < 8)
818785            {
819               WRITE8(rsp, ea, R_VREG_B(dest, ((i & 0xf) << 1)));
786               WRITE8(rsp, ea, VREG_B(dest, ((i & 0xf) << 1)));
820787            }
821788            else
822789            {
823               WRITE8(rsp, ea, R_VREG_S(dest, (i & 0x7)) >> 7);
790               WRITE8(rsp, ea, VREG_S(dest, (i & 0x7)) >> 7);
824791            }
825792            ea++;
826793         }
r9854r9855
842809         {
843810            if ((i & 0xf) < 8)
844811            {
845               WRITE8(rsp, ea, R_VREG_S(dest, (i & 0x7)) >> 7);
812               WRITE8(rsp, ea, VREG_S(dest, (i & 0x7)) >> 7);
846813            }
847814            else
848815            {
849               WRITE8(rsp, ea, R_VREG_B(dest, ((i & 0x7) << 1)));
816               WRITE8(rsp, ea, VREG_B(dest, ((i & 0x7) << 1)));
850817            }
851818            ea++;
852819         }
r9854r9855
865832
866833         for (i=0; i < 8; i++)
867834         {
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);
870837
871838            WRITE8(rsp, ea, d);
872839            ea += 2;
r9854r9855
895862
896863         for (i=index >> 1; i < end; i++)
897864         {
898            WRITE8(rsp, ea + (eaoffset & 0xf), R_VREG_S(dest, i) >> 7);
865            WRITE8(rsp, ea + (eaoffset & 0xf), VREG_S(dest, i) >> 7);
899866            eaoffset += 4;
900867         }
901868         break;
r9854r9855
919886
920887         for (i=index; i < end; i++)
921888         {
922            WRITE8(rsp, ea + (eaoffset & 0xf), R_VREG_B(dest, i & 0xf));
889            WRITE8(rsp, ea + (eaoffset & 0xf), VREG_B(dest, i & 0xf));
923890            eaoffset++;
924891         }
925892         break;
r9854r9855
940907            ve = 32;
941908
942909         element = 8 - (index >> 1);
943         if (index & 0x1)   fatalerror("RSP: STV: index = %d at %08X\n", index, rsp->ppc);
944910
945911         ea = (base) ? rsp->r[base] + (offset * 16) : (offset * 16);
946912
947         if (ea & 0x1)      fatalerror("RSP: STV: ea = %08X at %08X\n", ea, rsp->ppc);
948
949913         eaoffset = (ea & 0xf) + (element * 2);
950914         ea &= ~0xf;
951915
952916         for (i=vs; i < ve; i++)
953917         {
954            WRITE16(rsp, ea + (eaoffset & 0xf), R_VREG_S(i, element & 0x7));
918            WRITE16(rsp, ea + (eaoffset & 0xf), VREG_S(i, element & 0x7));
955919            eaoffset += 2;
956920            element++;
957921         }
r9854r9855
968932
969933INLINE UINT16 SATURATE_ACCUM(rsp_state *rsp, int accum, int slice, UINT16 negative, UINT16 positive)
970934{
971   if ((INT16)R_ACCUM_H(accum) < 0)
935   if ((INT16)ACCUM_H(accum) < 0)
972936   {
973      if ((UINT16)(R_ACCUM_H(accum)) != 0xffff)
937      if ((UINT16)(ACCUM_H(accum)) != 0xffff)
974938      {
975939         return negative;
976940      }
977941      else
978942      {
979         if ((INT16)R_ACCUM_M(accum) >= 0)
943         if ((INT16)ACCUM_M(accum) >= 0)
980944         {
981945            return negative;
982946         }
r9854r9855
984948         {
985949            if (slice == 0)
986950            {
987               return R_ACCUM_L(accum);
951               return ACCUM_L(accum);
988952            }
989953            else if (slice == 1)
990954            {
991               return R_ACCUM_M(accum);
955               return ACCUM_M(accum);
992956            }
993957         }
994958      }
995959   }
996960   else
997961   {
998      if ((UINT16)(R_ACCUM_H(accum)) != 0)
962      if ((UINT16)(ACCUM_H(accum)) != 0)
999963      {
1000964         return positive;
1001965      }
1002966      else
1003967      {
1004         if ((INT16)R_ACCUM_M(accum) < 0)
968         if ((INT16)ACCUM_M(accum) < 0)
1005969         {
1006970            return positive;
1007971         }
r9854r9855
1009973         {
1010974            if (slice == 0)
1011975            {
1012               return R_ACCUM_L(accum);
976               return ACCUM_L(accum);
1013977            }
1014978            else
1015979            {
1016               return R_ACCUM_M(accum);
980               return ACCUM_M(accum);
1017981            }
1018982         }
1019983      }
r9854r9855
1022986   return 0;
1023987}
1024988
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)
989INLINE 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   }
10361027
1028   return 0;
1029}
1030
1031#define WRITEBACK_RESULT() {memcpy(&rsp->v[VDREG].s[0], &vres[0], 16);}
1032
10371033#if 0
10381034static float float_round(float input)
10391035{
r9854r9855
10551051static void handle_vector_ops(rsp_state *rsp, UINT32 op)
10561052{
10571053   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;
10581058   INT16 vres[8];
10591059
10601060   // Opcode legend:
r9854r9855
10741074         //
10751075         // Multiplies signed integer by signed integer * 2
10761076
1077         int sel;
1078         INT32 s1, s2;
1079         INT64 r;
10771080         for (i=0; i < 8; i++)
10781081         {
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);
10831085            if (s1 == -32768 && s2 == -32768)
10841086            {
10851087               // 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;
10901092            }
10911093            else
10921094            {
1093               INT64 r =  s1 * s2 * 2;
1095               r =  s1 * s2 * 2;
10941096               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);
10991101            }
11001102         }
11011103         WRITEBACK_RESULT();
r9854r9855
11111113         // ------------------------------------------------------
11121114         //
11131115
1116         int sel;
1117         INT32 s1, s2;
1118         INT64 r;
11141119         for (i=0; i < 8; i++)
11151120         {
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;
11211125            r += 0x8000;   // rounding ?
11221126
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);
11261130
11271131            if (r < 0)
11281132            {
1129               vres[del] = 0;
1133               vres[i] = 0;
11301134            }
1131            else if (((INT16)(R_ACCUM_H(del)) ^ (INT16)(R_ACCUM_M(del))) < 0)
1135            else if (((INT16)(ACCUM_H(i)) ^ (INT16)(ACCUM_M(i))) < 0)
11321136            {
1133               vres[del] = -1;
1137               vres[i] = -1;
11341138            }
11351139            else
11361140            {
1137               vres[del] = R_ACCUM_M(del);
1141               vres[i] = ACCUM_M(i);
11381142            }
11391143         }
11401144         WRITEBACK_RESULT();
r9854r9855
11521156         // Stores the higher 16 bits of the 32-bit result to accumulator
11531157         // The low slice of accumulator is stored into destination element
11541158
1159         int sel;
1160         UINT32 s1, s2;
1161         UINT32 r;
11551162         for (i=0; i < 8; i++)
11561163         {
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;
11621168
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);
11661172
1167            vres[del] = R_ACCUM_L(del);
1173            vres[i] = ACCUM_L(i);
11681174         }
11691175         WRITEBACK_RESULT();
11701176         break;
r9854r9855
11811187         // The result is stored into accumulator
11821188         // The middle slice of accumulator is stored into destination element
11831189
1190         int sel;
1191         INT32 s1, s2;
1192         INT32 r;
11841193         for (i=0; i < 8; i++)
11851194         {
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;
11911199
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);
11951203
1196            vres[del] = R_ACCUM_M(del);
1204            vres[i] = ACCUM_M(i);
11971205         }
11981206         WRITEBACK_RESULT();
11991207         break;
r9854r9855
12111219         // The result is stored into accumulator
12121220         // The low slice of accumulator is stored into destination element
12131221
1222         int sel;
1223         INT32 s1, s2;
1224         INT32 r;
12141225         for (i=0; i < 8; i++)
12151226         {
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;
12211231
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);
12251235
1226            vres[del] = R_ACCUM_L(del);
1236            vres[i] = ACCUM_L(i);
12271237         }
12281238         WRITEBACK_RESULT();
12291239         break;
r9854r9855
12401250         // The result is stored into highest 32 bits of accumulator, the low slice is zero
12411251         // The highest 32 bits of accumulator is saturated into destination element
12421252
1253         int sel;
1254         INT32 s1, s2;
1255         INT32 r;
12431256         for (i=0; i < 8; i++)
12441257         {
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;
12501262
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;
12541266
12551267            if (r < -32768) r = -32768;
12561268            if (r >  32767)   r = 32767;
1257            vres[del] = (INT16)(r);
1269            vres[i] = (INT16)(r);
12581270         }
12591271         WRITEBACK_RESULT();
12601272         break;
r9854r9855
12701282         // Multiplies signed integer by signed integer * 2
12711283         // The result is added to accumulator
12721284
1285         int sel;
1286         INT32 s1, s2;
1287         INT32 r;
1288         UINT16 res;
12731289         for (i=0; i < 8; i++)
12741290         {
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;
12811295
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);
12841298
1285            vres[del] = res;
1299            vres[i] = res;
12861300         }
12871301         WRITEBACK_RESULT();
12881302         break;
r9854r9855
12961310         // ------------------------------------------------------
12971311         //
12981312
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++)
13001318         {
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);
13091325
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);
13131329
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)
13161332            {
13171333               res = 0;
13181334            }
13191335            else
13201336            {
1321               if (R_ACCUM_H(del) != 0)
1337               if (ACCUM_H(i) != 0)
13221338               {
13231339                  res = 0xffff;
13241340               }
13251341               else
13261342               {
1327                  if ((INT16)R_ACCUM_M(del) < 0)
1343                  if ((INT16)ACCUM_M(i) < 0)
13281344                  {
13291345                     res = 0xffff;
13301346                  }
13311347                  else
13321348                  {
1333                     res = R_ACCUM_M(del);
1349                     res = ACCUM_M(i);
13341350                  }
13351351               }
13361352            }
13371353
1338            vres[del] = res;
1354            vres[i] = res;
13391355         }
13401356         WRITEBACK_RESULT();
13411357         break;
r9854r9855
13521368         // Adds the higher 16 bits of the 32-bit result to accumulator
13531369         // The low slice of accumulator is stored into destination element
13541370
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++)
13561376         {
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);
13651383
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);
13691387
1370            res = SATURATE_ACCUM(rsp, del, 0, 0x0000, 0xffff);
1388            res = SATURATE_ACCUM(rsp, i, 0, 0x0000, 0xffff);
13711389
1372            vres[del] = res;
1390            vres[i] = res;
13731391         }
13741392         WRITEBACK_RESULT();
13751393         break;
r9854r9855
13861404         // The result is added into accumulator
13871405         // The middle slice of accumulator is stored into destination element
13881406
1407         UINT16 res;
1408         int sel;
1409         UINT32 s1, s2, r1;
1410         UINT32 r2, r3;
13891411         for (i=0; i < 8; i++)
13901412         {
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);
13991419
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);
14031423            if ((INT32)(r1) < 0)
1404               W_ACCUM_H(del, (UINT16)R_ACCUM_H(del) - 1);
1424               ACCUM_H(i) -= 1;
14051425
1406            res = SATURATE_ACCUM(rsp, del, 1, 0x8000, 0x7fff);
1426            res = SATURATE_ACCUM(rsp, i, 1, 0x8000, 0x7fff);
14071427
1408            vres[del] = res;
1428            vres[i] = res;
14091429         }
14101430         WRITEBACK_RESULT();
14111431         break;
r9854r9855
14221442         // The result is added into accumulator
14231443         // The low slice of accumulator is stored into destination element
14241444
1445         INT32 s1, s2;
1446         UINT16 res;
1447         int sel;
14251448         for (i=0; i < 8; i++)
14261449         {
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);
14351453
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;
14411455
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;
14451458         }
14461459         WRITEBACK_RESULT();
1460
14471461         break;
14481462      }
14491463
r9854r9855
14581472         // The result is added into highest 32 bits of accumulator, the low slice is zero
14591473         // The highest 32 bits of accumulator is saturated into destination element
14601474
1461         for (i=0; i < 8; i++)
1475         UINT16 res;
1476         int sel;
1477         INT32 s1, s2;
1478         for (i = 0; i < 8; i++)
14621479         {
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);
14691483
1470            ACCUM(del) += (INT64)(r) << 32;
1484            rsp->accum[i].l[1] += s1*s2;
14711485
1472            res = SATURATE_ACCUM(rsp, del, 1, 0x8000, 0x7fff);
1486            res = SATURATE_ACCUM1(rsp, i, 0x8000, 0x7fff);
14731487
1474            vres[del] = res;
1488            vres[i] = res;
14751489         }
14761490         WRITEBACK_RESULT();
1491
14771492         break;
14781493      }
14791494
r9854r9855
14881503
14891504         // TODO: check VS2REG == VDREG
14901505
1506         int sel;
1507         INT32 s1, s2, r;
14911508         for (i=0; i < 8; i++)
14921509         {
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);
14981514
1499            W_ACCUM_L(del, (INT16)(r));
1515            ACCUM_L(i) = (INT16)(r);
15001516
15011517            if (r > 32767) r = 32767;
15021518            if (r < -32768) r = -32768;
1503            vres[del] = (INT16)(r);
1519            vres[i] = (INT16)(r);
15041520         }
15051521         CLEAR_ZERO_FLAGS();
15061522         CLEAR_CARRY_FLAGS();
r9854r9855
15191535
15201536         // TODO: check VS2REG == VDREG
15211537
1522         for (i=0; i < 8; i++)
1538         int sel;
1539         INT32 s1, s2, r;
1540         for (i = 0; i < 8; i++)
15231541         {
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);
15291546
1530            W_ACCUM_L(del, (INT16)(r));
1547            ACCUM_L(i) = (INT16)(r);
15311548
15321549            if (r > 32767) r = 32767;
15331550            if (r < -32768) r = -32768;
15341551
1535            vres[del] = (INT16)(r);
1552            vres[i] = (INT16)(r);
15361553         }
15371554         CLEAR_ZERO_FLAGS();
15381555         CLEAR_CARRY_FLAGS();
r9854r9855
15501567         // Changes the sign of source register 2 if source register 1 is negative and stores
15511568         // the result to destination register
15521569
1570         int sel;
1571         INT16 s1, s2;
15531572         for (i=0; i < 8; i++)
15541573         {
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);
15591577
15601578            if (s1 < 0)
15611579            {
15621580               if (s2 == -32768)
15631581               {
1564                  vres[del] = 32767;
1582                  vres[i] = 32767;
15651583               }
15661584               else
15671585               {
1568                  vres[del] = -s2;
1586                  vres[i] = -s2;
15691587               }
15701588            }
15711589            else if (s1 > 0)
15721590            {
1573               vres[del] = s2;
1591               vres[i] = s2;
15741592            }
15751593            else
15761594            {
1577               vres[del] = 0;
1595               vres[i] = 0;
15781596            }
15791597
1580            W_ACCUM_L(del, vres[del]);
1598            ACCUM_L(i) = vres[i];
15811599         }
15821600         WRITEBACK_RESULT();
15831601         break;
r9854r9855
15941612
15951613         // TODO: check VS2REG = VDREG
15961614
1615         int sel;
1616         INT32 s1, s2, r;
15971617         CLEAR_ZERO_FLAGS();
15981618         CLEAR_CARRY_FLAGS();
15991619
16001620         for (i=0; i < 8; i++)
16011621         {
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;
16071626
1608            vres[del] = (INT16)(r);
1609            W_ACCUM_L(del, (INT16)(r));
1627            vres[i] = (INT16)(r);
1628            ACCUM_L(i) = (INT16)(r);
16101629
16111630            if (r & 0xffff0000)
16121631            {
1613               SET_CARRY_FLAG(del);
1632               SET_CARRY_FLAG(i);
16141633            }
16151634         }
16161635         WRITEBACK_RESULT();
r9854r9855
16281647
16291648         // TODO: check VS2REG = VDREG
16301649
1650         int sel;
1651         INT32 s1, s2, r;
16311652         CLEAR_ZERO_FLAGS();
16321653         CLEAR_CARRY_FLAGS();
16331654
16341655         for (i=0; i < 8; i++)
16351656         {
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;
16411661
1642            vres[del] = (INT16)(r);
1643            W_ACCUM_L(del, (UINT16)(r));
1662            vres[i] = (INT16)(r);
1663            ACCUM_L(i) = (UINT16)(r);
16441664
16451665            if ((UINT16)(r) != 0)
16461666            {
1647               SET_ZERO_FLAG(del);
1667               SET_ZERO_FLAG(i);
16481668            }
16491669            if (r & 0xffff0000)
16501670            {
1651               SET_CARRY_FLAG(del);
1671               SET_CARRY_FLAG(i);
16521672            }
16531673         }
16541674         WRITEBACK_RESULT();
r9854r9855
16701690            {
16711691               for (i=0; i < 8; i++)
16721692               {
1673                  W_VREG_S(VDREG, i, R_ACCUM_H(i));
1693                  VREG_S(VDREG, i) = ACCUM_H(i);
16741694               }
16751695               break;
16761696            }
r9854r9855
16781698            {
16791699               for (i=0; i < 8; i++)
16801700               {
1681                  W_VREG_S(VDREG, i, R_ACCUM_M(i));
1701                  VREG_S(VDREG, i) = ACCUM_M(i);
16821702               }
16831703               break;
16841704            }
r9854r9855
16861706            {
16871707               for (i=0; i < 8; i++)
16881708               {
1689                  W_VREG_S(VDREG, i, R_ACCUM_L(i));
1709                  VREG_S(VDREG, i) = ACCUM_L(i);
16901710               }
16911711               break;
16921712            }
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);
16941716         }
16951717         break;
16961718      }
r9854r9855
17051727         // Sets compare flags if elements in VS1 are less than VS2
17061728         // Moves the element in VS2 to destination vector
17071729
1730         int sel;
17081731         rsp->flag[1] = 0;
17091732
17101733         for (i=0; i < 8; i++)
17111734         {
1712            int del = VEC_EL_1(EL, i);
1713            int sel = VEC_EL_2(EL, del);
1735            sel = VEC_EL_2(EL, i);
17141736
1715            if (R_VREG_S(VS1REG, del) < R_VREG_S(VS2REG, sel))
1737            if (VREG_S(VS1REG, i) < VREG_S(VS2REG, sel))
17161738            {
1717               vres[del] = R_VREG_S(VS1REG, del);
1718               SET_COMPARE_FLAG(del);
1739               SET_COMPARE_FLAG(i);
17191740            }
1720            else if (R_VREG_S(VS1REG, del) == R_VREG_S(VS2REG, sel))
1741            else if (VREG_S(VS1REG, i) == VREG_S(VS2REG, sel))
17211742            {
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)
17241744               {
1725                  SET_COMPARE_FLAG(del);
1745                  SET_COMPARE_FLAG(i);
17261746               }
17271747            }
1748
1749            if (COMPARE_FLAG(i))
1750            {
1751               vres[i] = VREG_S(VS1REG, i);
1752            }
17281753            else
17291754            {
1730               vres[del] = R_VREG_S(VS2REG, sel);
1755               vres[i] = VREG_S(VS2REG, sel);
17311756            }
17321757
1733            W_ACCUM_L(del, vres[del]);
1758            ACCUM_L(i) = vres[i];
17341759         }
17351760
1736         CLEAR_ZERO_FLAGS();
1737         CLEAR_CARRY_FLAGS();
1761         rsp->flag[0] = 0;
17381762         WRITEBACK_RESULT();
17391763         break;
17401764      }
r9854r9855
17491773         // Sets compare flags if elements in VS1 are equal with VS2
17501774         // Moves the element in VS2 to destination vector
17511775
1776         int sel;
17521777         rsp->flag[1] = 0;
17531778
1754         for (i=0; i < 8; i++)
1779         for (i = 0; i < 8; i++)
17551780         {
1756            int del = VEC_EL_1(EL, i);
1757            int sel = VEC_EL_2(EL, del);
1781            sel = VEC_EL_2(EL, i);
17581782
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)
17631784            {
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);
17681787            }
1788            else
1789            {
1790               vres[i] = VREG_S(VS2REG, sel);
1791            }
1792            ACCUM_L(i) = vres[i];
17691793         }
17701794
1771         CLEAR_ZERO_FLAGS();
1772         CLEAR_CARRY_FLAGS();
1795         rsp->flag[0] = 0;
17731796         WRITEBACK_RESULT();
17741797         break;
17751798      }
r9854r9855
17841807         // Sets compare flags if elements in VS1 are not equal with VS2
17851808         // Moves the element in VS2 to destination vector
17861809
1810         int sel;
17871811         rsp->flag[1] = 0;
17881812
1789         for (i=0; i < 8; i++)
1813         for (i=0; i < 8; i++)//ïåðåïèñàíî ìíîé
17901814         {
1791            int del = VEC_EL_1(EL, i);
1792            int sel = VEC_EL_2(EL, del);
1815            sel = VEC_EL_2(EL, i);
17931816
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))
17981818            {
1799               SET_COMPARE_FLAG(del);
1819               SET_COMPARE_FLAG(i);
18001820            }
18011821            else
18021822            {
1803               if (ZERO_FLAG(del) != 0)
1823               if (ZERO_FLAG(i) == 1)
18041824               {
1805                  SET_COMPARE_FLAG(del);
1825                  SET_COMPARE_FLAG(i);
18061826               }
18071827            }
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];
18081837         }
18091838
1810         CLEAR_ZERO_FLAGS();
1811         CLEAR_CARRY_FLAGS();
1839         rsp->flag[0] = 0;
18121840         WRITEBACK_RESULT();
18131841         break;
18141842      }
r9854r9855
18231851         // Sets compare flags if elements in VS1 are greater or equal with VS2
18241852         // Moves the element in VS2 to destination vector
18251853
1854         int sel;
18261855         rsp->flag[1] = 0;
18271856
18281857         for (i=0; i < 8; i++)
18291858         {
1830            int del = VEC_EL_1(EL, i);
1831            int sel = VEC_EL_2(EL, del);
1859            sel = VEC_EL_2(EL, i);
18321860
1833            if (R_VREG_S(VS1REG, del) == R_VREG_S(VS2REG, sel))
1861            if (VREG_S(VS1REG, i) == VREG_S(VS2REG, sel))
18341862            {
1835               if (ZERO_FLAG(del) == 0 || CARRY_FLAG(del) == 0)
1863               if (ZERO_FLAG(i) == 0 || CARRY_FLAG(i) == 0)
18361864               {
1837                  SET_COMPARE_FLAG(del);
1865                  SET_COMPARE_FLAG(i);
18381866               }
18391867            }
1840            else if (R_VREG_S(VS1REG, del) > R_VREG_S(VS2REG, sel))
1868            else if (VREG_S(VS1REG, i) > VREG_S(VS2REG, sel))
18411869            {
1842               SET_COMPARE_FLAG(del);
1870               SET_COMPARE_FLAG(i);
18431871            }
18441872
1845            if (COMPARE_FLAG(del) != 0)
1873            if (COMPARE_FLAG(i) != 0)
18461874            {
1847               vres[del] = R_VREG_S(VS1REG, del);
1875               vres[i] = VREG_S(VS1REG, i);
18481876            }
18491877            else
18501878            {
1851               vres[del] = R_VREG_S(VS2REG, sel);
1879               vres[i] = VREG_S(VS2REG, sel);
18521880            }
18531881
1854            W_ACCUM_L(del, vres[del]);
1882            ACCUM_L(i) = vres[i];
18551883         }
18561884
1857         CLEAR_ZERO_FLAGS();
1858         CLEAR_CARRY_FLAGS();
1885         rsp->flag[0] = 0;
18591886         WRITEBACK_RESULT();
18601887         break;
18611888      }
r9854r9855
18691896         //
18701897         // Vector clip low
18711898
1872         for (i=0; i < 8; i++)
1899         int sel;
1900         INT16 s1, s2;
1901         for (i = 0; i < 8; i++)
18731902         {
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);
18781906
1879            if (CARRY_FLAG(del) != 0)
1907            if (CARRY_FLAG(i) != 0)
18801908            {
1881               if (ZERO_FLAG(del) != 0)
1909
1910               if (ZERO_FLAG(i) != 0)
18821911               {
1883                  if (COMPARE_FLAG(del) != 0)
1912
1913                  if (COMPARE_FLAG(i) != 0)
18841914                  {
1885                     W_ACCUM_L(del, -(UINT16)s2);
1915                     ACCUM_L(i) = -(UINT16)s2;
18861916                  }
18871917                  else
18881918                  {
1889                     W_ACCUM_L(del, s1);
1919                     ACCUM_L(i) = s1;
18901920                  }
18911921               }
1892               else
1922               else//ZERO_FLAG(i)==0
18931923               {
1894                  if (rsp->flag[2] & (1 << (del)))
1924
1925                  if (rsp->flag[2] & (1 << (i)))
18951926                  {
1927
18961928                     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);
19001933                     }
19011934                     else
19021935                     {
1903                        W_ACCUM_L(del, -((UINT16)s2));
1904                        SET_COMPARE_FLAG(del);
1936
1937                        ACCUM_L(i) = -((UINT16)s2);
1938                        SET_COMPARE_FLAG(i);
19051939                     }
19061940                  }
19071941                  else
19081942                  {
1909                     if (((UINT32)(INT16)(s1) + (UINT32)(INT16)(s2)) != 0)
1943                     if (((UINT32)(UINT16)(s1) + (UINT32)(UINT16)(s2)) != 0)
19101944                     {
1911                        W_ACCUM_L(del, s1);
1912                        CLEAR_COMPARE_FLAG(del);
1945                        ACCUM_L(i) = s1;
1946                        CLEAR_COMPARE_FLAG(i);
19131947                     }
19141948                     else
19151949                     {
1916                        W_ACCUM_L(del, -((UINT16)s2));
1917                        SET_COMPARE_FLAG(del);
1950                        ACCUM_L(i) = -((UINT16)s2);
1951                        SET_COMPARE_FLAG(i);
19181952                     }
19191953                  }
19201954               }
1921            }
1922            else
1955            }//
1956            else//CARRY_FLAG(i)==0
19231957            {
1924               if (ZERO_FLAG(del) != 0)
1958
1959               if (ZERO_FLAG(i) != 0)
19251960               {
1926                  if (rsp->flag[1] & (1 << (8+del)))
1961
1962                  if (rsp->flag[1] & (1 << (8+i)))
19271963                  {
1928                     W_ACCUM_L(del, s2);
1964                     ACCUM_L(i) = s2;
19291965                  }
19301966                  else
19311967                  {
1932                     W_ACCUM_L(del, s1);
1968                     ACCUM_L(i) = s1;
19331969                  }
19341970               }
19351971               else
19361972               {
19371973                  if (((INT32)(UINT16)s1 - (INT32)(UINT16)s2) >= 0)
19381974                  {
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));
19411977                  }
19421978                  else
19431979                  {
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));
19461982                  }
19471983               }
19481984            }
19491985
1950            vres[del] = R_ACCUM_L(del);
1986            vres[i] = ACCUM_L(i);
19511987         }
1952         CLEAR_ZERO_FLAGS();
1953         CLEAR_CARRY_FLAGS();
1988         rsp->flag[0] = 0;
19541989         rsp->flag[2] = 0;
19551990         WRITEBACK_RESULT();
19561991         break;
r9854r9855
19652000         //
19662001         // Vector clip high
19672002
1968         CLEAR_ZERO_FLAGS();
1969         CLEAR_CARRY_FLAGS();
2003         int sel;
2004         INT16 s1, s2;
2005         rsp->flag[0] = 0;
19702006         rsp->flag[1] = 0;
19712007         rsp->flag[2] = 0;
2008         UINT32 vce = 0;
19722009
19732010         for (i=0; i < 8; i++)
19742011         {
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);
19792015
19802016            if ((s1 ^ s2) < 0)
19812017            {
1982               SET_CARRY_FLAG(del);
2018               vce = (s1 + s2 == -1);
2019               SET_CARRY_FLAG(i);
19832020               if (s2 < 0)
19842021               {
1985                  rsp->flag[1] |= (1 << (8+del));
2022                  rsp->flag[1] |= (1 << (8+i));
19862023               }
19872024
19882025               if (s1 + s2 <= 0)
19892026               {
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);
19962029               }
19972030               else
19982031               {
1999                  vres[del] = s1;
2032                  vres[i] = s1;
20002033               }
20012034
20022035               if (s1 + s2 != 0)
20032036               {
20042037                  if (s1 != ~s2)
20052038                  {
2006                     SET_ZERO_FLAG(del);
2039                     SET_ZERO_FLAG(i);
20072040                  }
20082041               }
2009            }
2042            }//sign
20102043            else
20112044            {
2045               vce = 0;
20122046               if (s2 < 0)
20132047               {
2014                  SET_COMPARE_FLAG(del);
2048                  SET_COMPARE_FLAG(i);
20152049               }
20162050               if (s1 - s2 >= 0)
20172051               {
2018                  rsp->flag[1] |= (1 << (8+del));
2019                  vres[del] = s2;
2052                  rsp->flag[1] |= (1 << (8+i));
2053                  vres[i] = s2;
20202054               }
20212055               else
20222056               {
2023                  vres[del] = s1;
2057                  vres[i] = s1;
20242058               }
20252059
20262060               if ((s1 - s2) != 0)
20272061               {
20282062                  if (s1 != ~s2)
20292063                  {
2030                     SET_ZERO_FLAG(del);
2064                     SET_ZERO_FLAG(i);
20312065                  }
20322066               }
20332067            }
2034
2035            W_ACCUM_L(del, vres[del]);
2068            rsp->flag[2] |= (vce << (i));
2069            ACCUM_L(i) = vres[i];
20362070         }
20372071         WRITEBACK_RESULT();
20382072         break;
r9854r9855
20472081         //
20482082         // Vector clip reverse
20492083
2084         int sel;
2085         INT16 s1, s2;
20502086         rsp->flag[0] = 0;
20512087         rsp->flag[1] = 0;
20522088         rsp->flag[2] = 0;
20532089
20542090         for (i=0; i < 8; i++)
20552091         {
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);
20602095
20612096            if ((INT16)(s1 ^ s2) < 0)
20622097            {
20632098               if (s2 < 0)
20642099               {
2065                  rsp->flag[1] |= (1 << (8+del));
2100                  rsp->flag[1] |= (1 << (8+i));
20662101               }
20672102               if ((s1 + s2) <= 0)
20682103               {
2069                  W_ACCUM_L(del, ~((UINT16)s2));
2070                  SET_COMPARE_FLAG(del);
2104                  ACCUM_L(i) = ~((UINT16)s2);
2105                  SET_COMPARE_FLAG(i);
20712106               }
20722107               else
20732108               {
2074                  W_ACCUM_L(del, s1);
2109                  ACCUM_L(i) = s1;
20752110               }
20762111            }
20772112            else
20782113            {
20792114               if (s2 < 0)
20802115               {
2081                  SET_COMPARE_FLAG(del);
2116                  SET_COMPARE_FLAG(i);
20822117               }
20832118               if ((s1 - s2) >= 0)
20842119               {
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));
20872122               }
20882123               else
20892124               {
2090                  W_ACCUM_L(del, s1);
2125                  ACCUM_L(i) = s1;
20912126               }
20922127            }
20932128
2094            vres[del] = R_ACCUM_L(del);
2129            vres[i] = ACCUM_L(i);
20952130         }
20962131         WRITEBACK_RESULT();
20972132         break;
r9854r9855
21062141         //
21072142         // Merges two vectors according to compare flags
21082143
2109         for (i=0; i < 8; i++)
2144         int sel;
2145         for (i = 0; i < 8; i++)
21102146         {
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)
21142149            {
2115               vres[del] = R_VREG_S(VS1REG, del);
2150               vres[i] = VREG_S(VS1REG, i);
21162151            }
21172152            else
21182153            {
2119               vres[del] = R_VREG_S(VS2REG, VEC_EL_2(EL, sel));
2154               vres[i] = VREG_S(VS2REG, sel);//ìî¸ èñïðàâëåíèå
21202155            }
21212156
2122            W_ACCUM_L(del, vres[del]);
2157            ACCUM_L(i) = vres[i];
21232158         }
21242159         WRITEBACK_RESULT();
21252160         break;
r9854r9855
21332168         //
21342169         // Bitwise AND of two vector registers
21352170
2136         for (i=0; i < 8; i++)
2171         int sel;
2172         for (i = 0; i < 8; i++)
21372173         {
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];
21422177         }
21432178         WRITEBACK_RESULT();
21442179         break;
r9854r9855
21522187         //
21532188         // Bitwise NOT AND of two vector registers
21542189
2155         for (i=0; i < 8; i++)
2190         int sel;
2191         for (i = 0; i < 8; i++)
21562192         {
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];
21612196         }
21622197         WRITEBACK_RESULT();
21632198         break;
r9854r9855
21712206         //
21722207         // Bitwise OR of two vector registers
21732208
2174         for (i=0; i < 8; i++)
2209         int sel;
2210         for (i = 0; i < 8; i++)
21752211         {
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];
21802215         }
21812216         WRITEBACK_RESULT();
21822217         break;
r9854r9855
21902225         //
21912226         // Bitwise NOT OR of two vector registers
21922227
2228         int sel;
21932229         for (i=0; i < 8; i++)
21942230         {
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];
21992234         }
22002235         WRITEBACK_RESULT();
22012236         break;
r9854r9855
22092244         //
22102245         // Bitwise XOR of two vector registers
22112246
2247         int sel;
22122248         for (i=0; i < 8; i++)
22132249         {
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];
22182253         }
22192254         WRITEBACK_RESULT();
22202255         break;
r9854r9855
22282263         //
22292264         // Bitwise NOT XOR of two vector registers
22302265
2266         int sel;
22312267         for (i=0; i < 8; i++)
22322268         {
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];
22372272         }
22382273         WRITEBACK_RESULT();
22392274         break;
r9854r9855
22472282         // ------------------------------------------------------
22482283         //
22492284         // Calculates reciprocal
2250
2251         int del = (VS1REG & 7);
2285         int del = VS1REG & 7;
22522286         int sel = EL & 7;
2253         INT32 rec;
2287         INT32 shifter = 0;
22542288
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)
22582292         {
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++)
22692294            {
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
22782296               {
2279                  exp = i;
2280                  mantissa = (rec << (15 - i)) >> 6;
2297                  shifter = i;
22812298                  break;
22822299               }
22832300            }
2301         }
2302         else
2303         {
2304            shifter = 0x10;
2305         }
22842306
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;
22922323
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;
23052326
2306               rec <<= 8;
2307            }
2327         VREG_S(VDREG, del) = (UINT16)(rec & 0xffff);
23082328
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++)
23212330         {
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);
23242333         }
23252334
2326         rsp->reciprocal_res = rec;
23272335
2328         W_VREG_S(VDREG, del, (UINT16)(rsp->reciprocal_res));         // store low part
23292336         break;
23302337      }
23312338
r9854r9855
23382345         //
23392346         // Calculates reciprocal low part
23402347
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;
23442351
2345         rec = ((UINT16)(R_VREG_S(VS2REG, sel)) | ((UINT32)(rsp->reciprocal_high) << 16));
2352         INT32 rec = ((UINT16)(VREG_S(VS2REG, sel)) | ((UINT32)(rsp->reciprocal_high) & 0xffff0000));
23462353
2347         if (rec == 0)
2354         INT32 datainput = rec;
2355
2356         if (rec < 0)
23482357         {
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)
23562359            {
2357               if (((UINT32)(rec & 0xffff0000) == 0xffff0000) && ((INT16)(rec & 0xffff) < 0))
2360               if (rec < -32768)
23582361               {
2359                  rec = ~rec+1;
2362                  datainput = ~datainput;
23602363               }
23612364               else
23622365               {
2363                  rec = ~rec;
2366                  datainput = -datainput;
23642367               }
2365               negative = 1;
23662368            }
2367            for (i = 31; i > 0; i--)
2369            else
23682370            {
2369               if (rec & (1 << i))
2370               {
2371                  rec &= ((0xffc00000) >> (31 - i));
2372                  i = 0;
2373               }
2371               datainput = -datainput;
23742372            }
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++)
23772379            {
2378               if (rec & (1 << i))
2380               if (datainput & (1 << ((~i) & 0x1f)))//ò.æ.÷òî 31 - i
23792381               {
2380                  rec &= ((0xffff8000) >> (31 - i));
2381                  i = 0;
2382                  shifter = i;
2383                  break;
23822384               }
23832385            }
2384            if (negative)
2386         }
2387         else
2388         {
2389            if (rsp->dp_allowed)
23852390            {
2386               rec = ~rec;
2391               shifter = 0;
23872392            }
2393            else
2394            {
2395               shifter = 0x10;
2396            }
23882397         }
23892398
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)
23912403         {
2392            int element = VEC_EL_2(EL, i);
2393            W_ACCUM_L(i, R_VREG_S(VS2REG, element));
2404            temp = ~temp;
23942405         }
2406         if (!rec)
2407         {
2408            temp = 0x7fffffff;
2409         }
2410         else if (rec == 0xffff8000)
2411         {
2412            temp = 0xffff0000;
2413         }
2414         rec = temp;
23952415
23962416         rsp->reciprocal_res = rec;
2417         rsp->dp_allowed = 0;
23972418
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
23992427         break;
24002428      }
24012429
r9854r9855
24082436         //
24092437         // Calculates reciprocal high part
24102438
2411         int del = (VS1REG & 7);
2412         int sel = VEC_EL_2(EL, del);
2439         int del = VS1REG & 7;
2440         int sel = EL & 7;
24132441
2414         rsp->reciprocal_high = R_VREG_S(VS2REG, sel);
2442         rsp->reciprocal_high = (VREG_S(VS2REG, sel)) << 16;
2443         rsp->dp_allowed = 1;
24152444
2416         for (i=0; i < 8; i++)
2445         for (i = 0; i < 8; i++)
24172446         {
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);
24202449         }
24212450
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
24232453         break;
24242454      }
24252455
r9854r9855
24322462         //
24332463         // Moves element from vector to destination vector
24342464
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         }
24372474         break;
24382475      }
24392476
2440      case 0x35:      /* VRSQL */
2477      case 0x34:      /* VRSQ */
24412478      {
24422479         // 31       25  24     20      15      10      5        0
24432480         // ------------------------------------------------------
2444         // | 010010 | 1 | EEEE | SSSSS | ?FFFF | DDDDD | 110101 |
2481         // | 010010 | 1 | EEEE | SSSSS | ?FFFF | DDDDD | 110100 |
24452482         // ------------------------------------------------------
24462483         //
2447         // Calculates reciprocal square-root low part
2484         // Calculates reciprocal square-root
24482485
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;
24522489
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         }
24542507
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)
24562514         {
2457            // square root on 0 -> overflow
2458            sqr = 0x7fffffff;
2515            temp = ~temp;
24592516         }
2460         else if (sqr == 0xffff8000)
2517         if (!rec)
24612518         {
2462            // overflow ?
2463            sqr = 0xffff8000;
2519            temp = 0x7fffffff;
24642520         }
2465         else
2521         else if (rec == 0xffff8000)
24662522         {
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)
24692561            {
2470               if (((UINT32)(sqr & 0xffff0000) == 0xffff0000) && ((INT16)(sqr & 0xffff) < 0))
2562               if (rec < -32768)//VDIV.C,208
24712563               {
2472                  sqr = ~sqr+1;
2564                  datainput = ~datainput;
24732565               }
24742566               else
24752567               {
2476                  sqr = ~sqr;
2568                  datainput = -datainput;
24772569               }
2478               negative = 1;
24792570            }
2480            for (i = 31; i > 0; i--)
2571            else
24812572            {
2482               if (sqr & (1 << i))
2483               {
2484                  sqr &= (0xff800000 >> (31 - i));
2485                  i = 0;
2486               }
2573               datainput = -datainput;
24872574            }
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++)
24902580            {
2491               if (sqr & (1 << i))
2581               if (datainput & (1 << ((~i) & 0x1f)))
24922582               {
2493                  sqr &= (0xffff8000 >> (31 - i));
2494                  i = 0;
2583                  shifter = i;
2584                  break;
24952585               }
24962586            }
2497            if (negative)
2587         }
2588         else
2589         {
2590            if (rsp->dp_allowed)
24982591            {
2499               sqr = ~sqr;
2592               shifter = 0;
25002593            }
2594            else
2595            {
2596               shifter = 0x10;
2597            }
25012598         }
25022599
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)
25042606         {
2505            int element = VEC_EL_2(EL, i);
2506            W_ACCUM_L(i, R_VREG_S(VS2REG, element));
2607            temp = ~temp;
25072608         }
2609         if (!rec)
2610         {
2611            temp = 0x7fffffff;
2612         }
2613         else if (rec == 0xffff8000)
2614         {
2615            temp = 0xffff0000;
2616         }
2617         rec = temp;
25082618
2509         rsp->square_root_res = sqr;
2619         rsp->reciprocal_res = rec;
2620         rsp->dp_allowed = 0;
25102621
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
25122630         break;
25132631      }
25142632
r9854r9855
25212639         //
25222640         // Calculates reciprocal square-root high part
25232641
2524         int del = (VS1REG & 7);
2525         int sel = VEC_EL_2(EL, del);
2642         int del = VS1REG & 7;
2643         int sel = EL & 7;
25262644
2527         rsp->square_root_high = R_VREG_S(VS2REG, sel);
2645         rsp->reciprocal_high = (VREG_S(VS2REG, sel)) << 16;
2646         rsp->dp_allowed = 1;
25282647
25292648         for (i=0; i < 8; i++)
25302649         {
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);
25332652         }
25342653
2535         W_VREG_S(VDREG, del, (INT16)(rsp->square_root_res >> 16));   // store high part
2654         VREG_S(VDREG, del) = (INT16)(rsp->reciprocal_res >> 16);   // store high part
25362655         break;
25372656      }
25382657
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
25392670      default:   unimplemented_opcode(rsp, op); break;
25402671   }
25412672}
r9854r9855
26582789                  //
26592790
26602791                  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);
26632794                  if (RTREG) RTVAL = (INT32)(INT16)((b1 << 8) | (b2));
26642795                  break;
26652796               }
r9854r9855
26952826                  //
26962827
26972828                  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);
27002831                  break;
27012832               }
27022833               case 0x06:   /* CTC2 */
r9854r9855
27762907            if (rsp->v[i].d[0] != prev_vecs[i].d[0] || rsp->v[i].d[1] != prev_vecs[i].d[1])
27772908            {
27782909               fprintf(rsp->exec_output, "V%d: %04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X ", i,
2779               (UINT16)R_VREG_S(i,0), (UINT16)R_VREG_S(i,1), (UINT16)R_VREG_S(i,2), (UINT16)R_VREG_S(i,3), (UINT16)R_VREG_S(i,4), (UINT16)R_VREG_S(i,5), (UINT16)R_VREG_S(i,6), (UINT16)R_VREG_S(i,7));
2910               (UINT16)VREG_S(i,0), (UINT16)VREG_S(i,1), (UINT16)VREG_S(i,2), (UINT16)VREG_S(i,3), (UINT16)VREG_S(i,4), (UINT16)VREG_S(i,5), (UINT16)VREG_S(i,6), (UINT16)VREG_S(i,7));
27802911            }
27812912            prev_vecs[i].d[0] = rsp->v[i].d[0];
27822913            prev_vecs[i].d[1] = rsp->v[i].d[1];
r9854r9855
28682999   switch(state)
28693000   {
28703001      /* --- the following bits of info are returned as 64-bit signed integers --- */
2871      case CPUINFO_INT_CONTEXT_SIZE:               info->i = sizeof(rsp_state);               break;
3002      case CPUINFO_INT_CONTEXT_SIZE:               info->i = sizeof(rsp_state);         break;
28723003      case CPUINFO_INT_INPUT_LINES:               info->i = 1;                     break;
28733004      case CPUINFO_INT_DEFAULT_IRQ_VECTOR:         info->i = 0;                     break;
2874      case DEVINFO_INT_ENDIANNESS:               info->i = ENDIANNESS_LITTLE;               break;
3005      case DEVINFO_INT_ENDIANNESS:               info->i = ENDIANNESS_BIG;            break;
28753006      case CPUINFO_INT_CLOCK_MULTIPLIER:            info->i = 1;                     break;
28763007      case CPUINFO_INT_CLOCK_DIVIDER:               info->i = 1;                     break;
28773008      case CPUINFO_INT_MIN_INSTRUCTION_BYTES:         info->i = 4;                     break;
src/emu/cpu/rsp/rsp.h
r9854r9855
139139
140140#define RSPDRC_STRICT_VERIFY   0x0001         /* verify all instructions */
141141
142typedef struct
142typedef union
143143{
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];
151148} VECTOR_REG;
152149
153typedef struct
150typedef union
154151{
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;
187156
188157typedef struct _rspimp_state rspimp_state;
189158typedef struct _rsp_state rsp_state;
r9854r9855
199168   UINT32 sr;
200169   UINT32 step_count;
201170
202   ACCUMULATOR accum[8];
171   ACCUMULATOR_REG accum[8];
203172   INT32 square_root_res;
204173   INT32 square_root_high;
205174   INT32 reciprocal_res;
206175   INT32 reciprocal_high;
176   INT32 dp_allowed;
207177
208178   UINT32 ppc;
209179   UINT32 nextpc;
src/emu/cpu/rsp/rspdiv.h
r0r9855
1static 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};
src/emu/cpu/rsp/rspdrc.c
r9854r9855
2222#include "debugger.h"
2323#include "profiler.h"
2424#include "rsp.h"
25#include "rspdiv.h"
2526#include "rspfe.h"
2627#include "cpu/drcfe.h"
2728#include "cpu/drcuml.h"
r9854r9855
4344
4445#define SINGLE_INSTRUCTION_MODE         (0)
4546
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)
5247
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
7348/***************************************************************************
7449    CONSTANTS
7550***************************************************************************/
r9854r9855
10075***************************************************************************/
10176
10277#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
11778
118
119
12079/***************************************************************************
12180    STRUCTURES & TYPEDEFS
12281***************************************************************************/
r9854r9855
159118   const char *      format;                  /* format string for print_debug */
160119   UINT32            arg0;                  /* print_debug argument 1 */
161120   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 */
163123   UINT32            vres[8];               /* used for temporary vector results */
164124
165125   /* register mappings */
166   drcuml_parameter   regmap[998];            /* parameter to register mappings for all 32 integer registers, vector registers, flags, accumulators and temps */
126   drcuml_parameter   regmap[34];               /* parameter to register mappings for all 32 integer registers */
167127
168128   /* subroutines */
169129   drcuml_codehandle *   entry;                  /* entry point */
r9854r9855
200160static void cfunc_sp_set_status_cb(void *param);
201161
202162static void cfunc_rsp_lbv(void *param);
203#if !(DRC_LSV)
204163static void cfunc_rsp_lsv(void *param);
205#endif
206#if !(DRC_LLV)
207164static void cfunc_rsp_llv(void *param);
208#endif
209#if !(DRC_LDV)
210165static void cfunc_rsp_ldv(void *param);
211#endif
212#if !(DRC_LQV)
213166static void cfunc_rsp_lqv(void *param);
214#endif
215167static void cfunc_rsp_lrv(void *param);
216#if !(DRC_LPV)
217168static void cfunc_rsp_lpv(void *param);
218#endif
219#if !(DRC_LUV)
220169static void cfunc_rsp_luv(void *param);
221#endif
222170static void cfunc_rsp_lhv(void *param);
223171static void cfunc_rsp_lfv(void *param);
224172static void cfunc_rsp_lwv(void *param);
225173static void cfunc_rsp_ltv(void *param);
226174
227175static void cfunc_rsp_sbv(void *param);
228#if !(DRC_SSV)
229176static void cfunc_rsp_ssv(void *param);
230#endif
231#if !(DRC_SLV)
232177static void cfunc_rsp_slv(void *param);
233#endif
234#if !(DRC_SDV)
235178static void cfunc_rsp_sdv(void *param);
236#endif
237#if !(DRC_SQV)
238179static void cfunc_rsp_sqv(void *param);
239#endif
240180static void cfunc_rsp_srv(void *param);
241#if !(DRC_SPV)
242181static void cfunc_rsp_spv(void *param);
243#endif
244182static void cfunc_rsp_suv(void *param);
245183static void cfunc_rsp_shv(void *param);
246184static void cfunc_rsp_sfv(void *param);
r9854r9855
252190static void static_generate_out_of_cycles(rsp_state *rsp);
253191static void static_generate_memory_accessor(rsp_state *rsp, int size, int iswrite, const char *name, drcuml_codehandle **handleptr);
254192
255#if (DRC_VMADN)
256static 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)
259static 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)
262static int generate_vmudl(rsp_state *rsp, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);   // vmudl
263#endif
264#if (DRC_VMADM)
265static int generate_vmadm(rsp_state *rsp, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);   // vmadm
266#endif
267#if (DRC_VMADN)
268static int generate_vmadn(rsp_state *rsp, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);   // vmadn
269#endif
270#if (DRC_VMADH)
271static int generate_vmadh(rsp_state *rsp, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);   // vmadh
272#endif
273#if (DRC_VADD)
274static int generate_vadd(rsp_state *rsp, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);   // vadd
275#endif
276#if (DRC_VAND)
277static int generate_vand(rsp_state *rsp, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);   // vand
278#endif
279#if (DRC_VNAND)
280static int generate_vnand(rsp_state *rsp, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);   // vand
281#endif
282#if (DRC_VOR)
283static int generate_vor(rsp_state *rsp, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);   // vand
284#endif
285#if (DRC_VNOR)
286static int generate_vnor(rsp_state *rsp, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);   // vand
287#endif
288#if (DRC_VXOR)
289static int generate_vxor(rsp_state *rsp, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);   // vand
290#endif
291#if (DRC_VNXOR)
292static int generate_vnxor(rsp_state *rsp, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);   // vand
293#endif
294193static int generate_lwc2(rsp_state *rsp, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
295194static int generate_swc2(rsp_state *rsp, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
296195static void generate_update_cycles(rsp_state *rsp, drcuml_block *block, compiler_state *compiler, drcuml_ptype ptype, UINT64 pvalue, int allow_exception);
r9854r9855
314213#define VS2REG                  ((op >> 16) & 0x1f)
315214#define EL                     ((op >> 21) & 0xf)
316215
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]
322218
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)])
330219#define VEC_EL_2(x,z)            (vector_elements_2[(x)][(z)])
331220
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]
333225
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
338226#define CARRY_FLAG(x)            ((rsp->flag[0] & (1 << (x))) ? 1 : 0)
339227#define CLEAR_CARRY_FLAGS()         { rsp->flag[0] &= ~0xff; }
340228#define SET_CARRY_FLAG(x)         { rsp->flag[0] |= (1 << (x)); }
r9854r9855
421309INLINE UINT8 READ8(rsp_state *rsp, UINT32 address)
422310{
423311   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;
425315}
426316
427317/* Legacy.  Needed for vector cfuncs. */
r9854r9855
432322   address &= 0x00000fff;
433323   ret  = (UINT16)dmem[BYTE4_XOR_BE(address+0)] << 8;
434324   ret |= (UINT16)dmem[BYTE4_XOR_BE(address+1)];
325   //printf("%04xr%04x\n", address & 0x00001fff, ret);
435326   return ret;
436327}
437328
r9854r9855
445336   ret |= (UINT32)dmem[BYTE4_XOR_BE(address+1)] << 16;
446337   ret |= (UINT32)dmem[BYTE4_XOR_BE(address+2)] <<  8;
447338   ret |= (UINT32)dmem[BYTE4_XOR_BE(address+3)];
339   //printf("%04xr%08x\n", address & 0x00001fff, ret);
448340   return ret;
449341}
450342
451343/* Legacy.  Needed for vector cfuncs. */
452INLINE 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. */
469344INLINE void WRITE8(rsp_state *rsp, UINT32 address, UINT8 data)
470345{
471346   UINT8* dmem = (UINT8*)rsp->impstate->dmem;
472347   address &= 0x00000fff;
348   //printf("%04x:%02x\n", address & 0x00001fff, data);
473349   dmem[BYTE4_XOR_BE(address)] = data;
474350}
475351
r9854r9855
478354{
479355   UINT8* dmem = (UINT8*)rsp->impstate->dmem;
480356   address &= 0x00000fff;
357   //printf("%04x:%04x\n", address & 0x00001fff, data);
481358   dmem[BYTE4_XOR_BE(address+0)] = (UINT8)(data >> 8);
482359   dmem[BYTE4_XOR_BE(address+1)] = (UINT8)(data >> 0);
483360}
r9854r9855
487364{
488365   UINT8* dmem = (UINT8*)rsp->impstate->dmem;
489366   address &= 0x00000fff;
367   //printf("%04x:%08x\n", address & 0x00001fff, data);
490368   dmem[BYTE4_XOR_BE(address+0)] = (UINT8)(data >> 24);
491369   dmem[BYTE4_XOR_BE(address+1)] = (UINT8)(data >> 16);
492370   dmem[BYTE4_XOR_BE(address+2)] = (UINT8)(data >>  8);
493371   dmem[BYTE4_XOR_BE(address+3)] = (UINT8)(data >>  0);
494372}
495373
496/* Legacy.  Needed for vector cfuncs. */
497INLINE 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
511374/*****************************************************************************/
512375
513376/*-------------------------------------------------
r9854r9855
552415static void cfunc_printf_debug(void *param)
553416{
554417   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   }
557442}
558443#endif
559444
560
561/*-------------------------------------------------
562    cfunc_printf_debug64 - generic printf for
563    debugging 64-bit values
564-------------------------------------------------*/
565
566#ifdef UNUSED_FUNCTION
567static 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
575445static void cfunc_get_cop0_reg(void *param)
576446{
577447   rsp_state *rsp = (rsp_state*)param;
r9854r9855
722592   // ...except for the accumulators.
723593   for(accumIdx = 0; accumIdx < 8; accumIdx++ )
724594   {
725      rsp->accum[accumIdx].l = 0;
595      rsp->accum[accumIdx].q = 0;
726596   }
727597
728598   rsp->sr = RSP_STATUS_HALT;
r9854r9855
742612   drccache *cache;
743613   UINT32 flags = 0;
744614   int regnum;
745   int elnum;
615   //int elnum;
746616
747617   /* allocate enough space for the cache and the core */
748618   cache = (drccache *)drccache_alloc(CACHE_SIZE + sizeof(*rsp));
r9854r9855
792662   }
793663   drcuml_symbol_add(rsp->impstate->drcuml, &rsp->impstate->arg0, sizeof(rsp->impstate->arg0), "arg0");
794664   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");
796667   drcuml_symbol_add(rsp->impstate->drcuml, &rsp->impstate->numcycles, sizeof(rsp->impstate->numcycles), "numcycles");
797668
798669   /* initialize the front-end helper */
r9854r9855
808679      rsp->impstate->regmap[regnum].type = (regnum == 0) ? DRCUML_PTYPE_IMMEDIATE : DRCUML_PTYPE_MEMORY;
809680      rsp->impstate->regmap[regnum].value = (regnum == 0) ? 0 : (FPTR)&rsp->r[regnum];
810681   }
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   }
853682
854683   /* mark the cache dirty so it is updated on next execute */
855684   rsp->impstate->cache_dirty = TRUE;
r9854r9855
872701   rsp->nextpc = ~0;
873702}
874703
704INLINE 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}
875716
876717static void cfunc_rsp_lbv(void *param)
877718{
r9854r9855
894735   // Load 1 byte to vector byte index
895736
896737   ea = (base) ? rsp->r[base] + offset : offset;
897   W_VREG_B(dest, index, READ8(rsp, ea));
738   VREG_B(dest, index) = READ8(rsp, ea);
898739}
899740
900#if !(DRC_LSV)
901741static void cfunc_rsp_lsv(void *param)
902742{
903743   rsp_state *rsp = (rsp_state*)param;
r9854r9855
920760
921761   ea = (base) ? rsp->r[base] + (offset * 2) : (offset * 2);
922762
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   }
924770}
925#endif
926771
927#if !(DRC_LLV)
928772static void cfunc_rsp_llv(void *param)
929773{
930774   rsp_state *rsp = (rsp_state*)param;
r9854r9855
947791
948792   ea = (base) ? rsp->r[base] + (offset * 4) : (offset * 4);
949793
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   }
951801}
952#endif
953802
954#if !(DRC_LDV)
955803static void cfunc_rsp_ldv(void *param)
956804{
957805   rsp_state *rsp = (rsp_state*)param;
r9854r9855
974822
975823   ea = (base) ? rsp->r[base] + (offset * 8) : (offset * 8);
976824
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   }
980832}
981#endif
982833
983#if !(DRC_LQV)
984834static void cfunc_rsp_lqv(void *param)
985835{
986836   rsp_state *rsp = (rsp_state*)param;
r9854r9855
1007857
1008858   end = index + (16 - (ea & 0xf));
1009859   if (end > 16) end = 16;
1010
1011860   for (i=index; i < end; i++)
1012861   {
1013      W_VREG_B(dest, i, READ8(rsp, ea));
862      VREG_B(dest, i) = READ8(rsp, ea);
1014863      ea++;
1015864   }
1016865}
1017#endif
1018866
1019867static void cfunc_rsp_lrv(void *param)
1020868{
r9854r9855
1046894
1047895   for (i=index; i < end; i++)
1048896   {
1049      W_VREG_B(dest, i, READ8(rsp, ea));
897      VREG_B(dest, i) = READ8(rsp, ea);
1050898      ea++;
1051899   }
1052900}
1053901
1054#if !(DRC_LPV)
1055902static void cfunc_rsp_lpv(void *param)
1056903{
1057904   rsp_state *rsp = (rsp_state*)param;
r9854r9855
1077924
1078925   for (i=0; i < 8; i++)
1079926   {
1080      W_VREG_S(dest, i, READ8(rsp, ea + (((16-index) + i) & 0xf)) << 8);
927      VREG_S(dest, i) = READ8(rsp, ea + (((16-index) + i) & 0xf)) << 8;
1081928   }
1082929}
1083#endif
1084930
1085#if !(DRC_LUV)
1086931static void cfunc_rsp_luv(void *param)
1087932{
1088933   rsp_state *rsp = (rsp_state*)param;
r9854r9855
1108953
1109954   for (i=0; i < 8; i++)
1110955   {
1111      W_VREG_S(dest, i, READ8(rsp, ea + (((16-index) + i) & 0xf)) << 7);
956      VREG_S(dest, i) = READ8(rsp, ea + (((16-index) + i) & 0xf)) << 7;
1112957   }
1113958}
1114#endif
1115959
1116960static void cfunc_rsp_lhv(void *param)
1117961{
r9854r9855
1138982
1139983   for (i=0; i < 8; i++)
1140984   {
1141      W_VREG_S(dest, i, READ8(rsp, ea + (((16-index) + (i<<1)) & 0xf)) << 7);
985      VREG_S(dest, i) = READ8(rsp, ea + (((16-index) + (i<<1)) & 0xf)) << 7;
1142986   }
1143987}
1144988
r9854r9855
11641008   //
11651009   // Loads a byte as the bits 14-7 of upper or lower quad, with 4-byte stride
11661010
1167   fatalerror("RSP: LFV\n");
11681011
1169   if (index & 0x7)   fatalerror("RSP: LFV: index = %d at %08X\n", index, rsp->ppc);
1170
11711012   ea = (base) ? rsp->r[base] + (offset * 16) : (offset * 16);
11721013
11731014   // 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);
11751015
11761016   end = (index >> 1) + 4;
11771017
11781018   for (i=index >> 1; i < end; i++)
11791019   {
1180      W_VREG_S(dest, i, READ8(rsp, ea) << 7);
1020      VREG_S(dest, i) = READ8(rsp, ea) << 7;
11811021      ea += 4;
11821022   }
11831023}
r9854r9855
12071047
12081048   ea = (base) ? rsp->r[base] + (offset * 16) : (offset * 16);
12091049
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
12131050   end = (16 - index) + 16;
12141051
12151052   for (i=(16 - index); i < end; i++)
12161053   {
1217      W_VREG_B(dest, i & 0xf, READ8(rsp, ea));
1054      VREG_B(dest, i & 0xf) = READ8(rsp, ea);
12181055      ea += 4;
12191056   }
12201057}
r9854r9855
12431080   int vs = dest;
12441081   int ve = dest + 8;
12451082   if (ve > 32)
1246      ve = 32;
1247
1248   if (offset & 0x40)
12491083   {
1250      offset |= 0xffffffc0;
1084      ve = 32;
12511085   }
12521086
12531087   element = 7 - (index >> 1);
12541088
1255   if (index & 1)   fatalerror("RSP: LTV: index = %d\n", index);
1256
12571089   ea = (base) ? rsp->r[base] + (offset * 16) : (offset * 16);
12581090
12591091   ea = ((ea + 8) & ~0xf) + (index & 1);
1260   for (i=vs; i < ve; i++)
1092   for (i = vs; i < ve; i++)
12611093   {
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);
12651097
12661098      ea += 2;
12671099   }
r9854r9855
12891121         UML_CALLC(block, cfunc_rsp_lbv, rsp);
12901122         return TRUE;
12911123      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
13021124         UML_MOV(block, MEM(&rsp->impstate->arg0), IMM(desc->opptr.l[0]));      // mov     [arg0],desc->opptr.l
13031125         UML_CALLC(block, cfunc_rsp_lsv, rsp);
13041126         return TRUE;
1305#endif
13061127      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
13161128         UML_MOV(block, MEM(&rsp->impstate->arg0), IMM(desc->opptr.l[0]));      // mov     [arg0],desc->opptr.l
13171129         UML_CALLC(block, cfunc_rsp_llv, rsp);
13181130         return TRUE;
1319#endif
13201131      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
13351132         UML_MOV(block, MEM(&rsp->impstate->arg0), IMM(desc->opptr.l[0]));      // mov     [arg0],desc->opptr.l
13361133         UML_CALLC(block, cfunc_rsp_ldv, rsp);
13371134         return TRUE;
1338#endif
13391135      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
13681136         UML_MOV(block, MEM(&rsp->impstate->arg0), IMM(desc->opptr.l[0]));      // mov     [arg0],desc->opptr.l
13691137         UML_CALLC(block, cfunc_rsp_lqv, rsp);
13701138         return TRUE;
1371#endif
13721139      case 0x05:      /* LRV */
13731140         UML_MOV(block, MEM(&rsp->impstate->arg0), IMM(desc->opptr.l[0]));      // mov     [arg0],desc->opptr.l
13741141         UML_CALLC(block, cfunc_rsp_lrv, rsp);
13751142         return TRUE;
13761143      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
14551144         UML_MOV(block, MEM(&rsp->impstate->arg0), IMM(desc->opptr.l[0]));      // mov     [arg0],desc->opptr.l
14561145         UML_CALLC(block, cfunc_rsp_lpv, rsp);
14571146         return TRUE;
1458#endif
14591147      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
15381148         UML_MOV(block, MEM(&rsp->impstate->arg0), IMM(desc->opptr.l[0]));      // mov     [arg0],desc->opptr.l
15391149         UML_CALLC(block, cfunc_rsp_luv, rsp);
15401150         return TRUE;
1541#endif
15421151      case 0x08:      /* LHV */
15431152         UML_MOV(block, MEM(&rsp->impstate->arg0), IMM(desc->opptr.l[0]));      // mov     [arg0],desc->opptr.l
15441153         UML_CALLC(block, cfunc_rsp_lhv, rsp);
r9854r9855
15741183   {
15751184      offset |= 0xffffffc0;
15761185   }
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
15831186
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));
15861196}
15871197
1588#if !(DRC_SSV)
15891198static void cfunc_rsp_ssv(void *param)
15901199{
15911200   rsp_state *rsp = (rsp_state*)param;
r9854r9855
15991208   {
16001209      offset |= 0xffffffc0;
16011210   }
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
16081211
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
16101218
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   }
16121228}
1613#endif
16141229
1615#if !(DRC_SLV)
16161230static void cfunc_rsp_slv(void *param)
16171231{
16181232   rsp_state *rsp = (rsp_state*)param;
r9854r9855
16261240   {
16271241      offset |= 0xffffffc0;
16281242   }
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
16351249
1636         ea = (base) ? rsp->r[base] + (offset * 4) : (offset * 4);
1250   ea = (base) ? rsp->r[base] + (offset * 4) : (offset * 4);
16371251
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   }
16391259}
1640#endif
16411260
1642#if !(DRC_SDV)
16431261static void cfunc_rsp_sdv(void *param)
16441262{
16451263   rsp_state *rsp = (rsp_state*)param;
r9854r9855
16541272   {
16551273      offset |= 0xffffffc0;
16561274   }
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);
16641282
1665         end = index + 8;
1283   end = index + 8;
16661284
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   }
16701290}
1671#endif
16721291
1673#if !(DRC_SQV)
16741292static void cfunc_rsp_sqv(void *param)
16751293{
16761294   rsp_state *rsp = (rsp_state*)param;
r9854r9855
16861304   {
16871305      offset |= 0xffffffc0;
16881306   }
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
16951313
1696         ea = (base) ? rsp->r[base] + (offset * 16) : (offset * 16);
1314   ea = (base) ? rsp->r[base] + (offset * 16) : (offset * 16);
16971315
1698         end = index + (16 - (ea & 0xf));
1316   end = index + (16 - (ea & 0xf));
16991317
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   }
17051323}
1706#endif
17071324
17081325static void cfunc_rsp_srv(void *param)
17091326{
17101327   rsp_state *rsp = (rsp_state*)param;
17111328   UINT32 op = rsp->impstate->arg0;
1712   UINT32 ea = 0;
1713   int o;
1714   int i = 0;
1715   int end = 0;
17161329   int dest = (op >> 16) & 0x1f;
17171330   int base = (op >> 21) & 0x1f;
17181331   int index = (op >> 7) & 0xf;
r9854r9855
17211334   {
17221335      offset |= 0xffffffc0;
17231336   }
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
17301343
1731         ea = (base) ? rsp->r[base] + (offset * 16) : (offset * 16);
1344   UINT32 ea = (base) ? rsp->r[base] + (offset * 16) : (offset * 16);
17321345
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;
17361349
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   }
17421355}
17431356
1744#if !(DRC_SPV)
17451357static void cfunc_rsp_spv(void *param)
17461358{
17471359   rsp_state *rsp = (rsp_state*)param;
r9854r9855
17571369   {
17581370      offset |= 0xffffffc0;
17591371   }
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
17661378
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;
17691381
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   }
17821394}
1783#endif
17841395
17851396static void cfunc_rsp_suv(void *param)
17861397{
r9854r9855
17971408   {
17981409      offset |= 0xffffffc0;
17991410   }
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
18061417
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;
18091420
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   }
18221433}
18231434
18241435static void cfunc_rsp_shv(void *param)
r9854r9855
18351446   {
18361447      offset |= 0xffffffc0;
18371448   }
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
18441455
1845         ea = (base) ? rsp->r[base] + (offset * 16) : (offset * 16);
1456   ea = (base) ? rsp->r[base] + (offset * 16) : (offset * 16);
18461457
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);
18511462
1852            WRITE8(rsp, ea, d);
1853            ea += 2;
1854         }
1463      WRITE8(rsp, ea, d);
1464      ea += 2;
1465   }
18551466}
18561467
18571468static void cfunc_rsp_sfv(void *param)
r9854r9855
18701481   {
18711482      offset |= 0xffffffc0;
18721483   }
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
18791490
1880         // FIXME: only works for index 0 and index 8
1491   if (index & 0x7)   printf("RSP: SFV: index = %d at %08X\n", index, rsp->ppc);
18811492
1882         if (index & 0x7)   mame_printf_debug("RSP: SFV: index = %d at %08X\n", index, rsp->ppc);
1493   ea = (base) ? rsp->r[base] + (offset * 16) : (offset * 16);
18831494
1884         ea = (base) ? rsp->r[base] + (offset * 16) : (offset * 16);
1495   eaoffset = ea & 0xf;
1496   ea &= ~0xf;
18851497
1886         eaoffset = ea & 0xf;
1887         ea &= ~0xf;
1498   end = (index >> 1) + 4;
18881499
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   }
18961505}
18971506
18981507static void cfunc_rsp_swv(void *param)
r9854r9855
19111520   {
19121521      offset |= 0xffffffc0;
19131522   }
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
19211530
1922         ea = (base) ? rsp->r[base] + (offset * 16) : (offset * 16);
1531   ea = (base) ? rsp->r[base] + (offset * 16) : (offset * 16);
19231532
1924         eaoffset = ea & 0xf;
1925         ea &= ~0xf;
1533   eaoffset = ea & 0xf;
1534   ea &= ~0xf;
19261535
1927         end = index + 16;
1536   end = index + 16;
19281537
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   }
19341543}
19351544
19361545static void cfunc_rsp_stv(void *param)
r9854r9855
19431552   int base = (op >> 21) & 0x1f;
19441553   int index = (op >> 7) & 0xf;
19451554   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;
19521555
19531556   if (offset & 0x40)
19541557   {
19551558      offset |= 0xffffffc0;
19561559   }
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
19631566
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   }
19661573
1967         ea = (base) ? rsp->r[base] + (offset * 16) : (offset * 16);
1574   int element = 8 - (index >> 1);
19681575
1969         if (ea & 0x1)      fatalerror("RSP: STV: ea = %08X at %08X\n", ea, rsp->ppc);
1576   ea = (base) ? rsp->r[base] + (offset * 16) : (offset * 16);
19701577
1971         eaoffset = (ea & 0xf) + (element * 2);
1972         ea &= ~0xf;
1578   int eaoffset = (ea & 0xf) + (element * 2);
1579   ea &= ~0xf;
19731580
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   }
19801587}
19811588
19821589static int generate_swc2(rsp_state *rsp, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc)
r9854r9855
20001607         UML_CALLC(block, cfunc_rsp_sbv, rsp);
20011608         return TRUE;
20021609      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
20131610         UML_MOV(block, MEM(&rsp->impstate->arg0), IMM(desc->opptr.l[0]));      // mov     [arg0],desc->opptr.l
20141611         UML_CALLC(block, cfunc_rsp_ssv, rsp);
20151612         return TRUE;
2016#endif
20171613      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
20271614         UML_MOV(block, MEM(&rsp->impstate->arg0), IMM(desc->opptr.l[0]));      // mov     [arg0],desc->opptr.l
20281615         UML_CALLC(block, cfunc_rsp_slv, rsp);
20291616         return TRUE;
2030#endif
20311617      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
20461618         UML_MOV(block, MEM(&rsp->impstate->arg0), IMM(desc->opptr.l[0]));      // mov     [arg0],desc->opptr.l
20471619         UML_CALLC(block, cfunc_rsp_sdv, rsp);
20481620         return TRUE;
2049#endif
20501621      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
20771622         UML_MOV(block, MEM(&rsp->impstate->arg0), IMM(desc->opptr.l[0]));      // mov     [arg0],desc->opptr.l
20781623         UML_CALLC(block, cfunc_rsp_sqv, rsp);
2079#endif
20801624         return TRUE;
20811625      case 0x05:      /* SRV */
20821626         UML_MOV(block, MEM(&rsp->impstate->arg0), IMM(desc->opptr.l[0]));      // mov     [arg0],desc->opptr.l
20831627         UML_CALLC(block, cfunc_rsp_srv, rsp);
20841628         return TRUE;
20851629      case 0x06:      /* SPV */
2086#if (DRC_SPV)
2087#else
20881630         UML_MOV(block, MEM(&rsp->impstate->arg0), IMM(desc->opptr.l[0]));      // mov     [arg0],desc->opptr.l
20891631         UML_CALLC(block, cfunc_rsp_spv, rsp);
2090#endif
20911632         return TRUE;
20921633      case 0x07:      /* SUV */
20931634         UML_MOV(block, MEM(&rsp->impstate->arg0), IMM(desc->opptr.l[0]));      // mov     [arg0],desc->opptr.l
r9854r9855
21181659   return TRUE;
21191660}
21201661
2121#if (DRC_VMADN)
2122static void generate_saturate_accum_unsigned(rsp_state *rsp, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, int accum)
1662INLINE UINT16 SATURATE_ACCUM(rsp_state *rsp, int accum, int slice, UINT16 negative, UINT16 positive)
21231663{
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
2152INLINE UINT16 SATURATE_ACCUM_UNSIGNED(rsp_state *rsp, int accum)
2153{
2154   if (ACCUM(accum).w.mh < -32768)
1664   if ((INT16)ACCUM_H(accum) < 0)
21551665   {
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      }
21571688   }
2158   else if(ACCUM(accum).w.mh > 32767)
2159   {
2160      return 0xffff;
2161   }
21621689   else
21631690   {
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      }
21651713   }
2166}
21671714
2168#if (DRC_VMADH) || (DRC_VMADM)
2169static 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;
21881716}
2189#endif
21901717
2191INLINE UINT16 SATURATE_ACCUM_SIGNED(rsp_state *rsp, int accum)
1718INLINE UINT16 SATURATE_ACCUM1(rsp_state *rsp, int accum, UINT16 negative, UINT16 positive)
21921719{
2193   if (ACCUM(accum).w.mh < -32768)
1720   if ((INT16)ACCUM_H(accum) < 0)
21941721   {
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      }
21961737   }
2197   if(ACCUM(accum).w.mh > 32767)
1738   else
21981739   {
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      }
22001755   }
2201   return ACCUM(accum).h.mid;
1756
1757   return 0;
22021758}
22031759
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
2217static 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];   \
22311769}
2232#endif
22331770
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
22631771INLINE void cfunc_rsp_vmulf(void *param)
22641772{
22651773   rsp_state *rsp = (rsp_state*)param;
r9854r9855
22731781   //
22741782   // Multiplies signed integer by signed integer * 2
22751783
2276   switch(EL)
1784   int sel;
1785   INT32 s1, s2;
1786   INT64 r;
1787   for (int i = 0; i < 8; i++)
22771788   {
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      }
23261809   }
2327
23281810   WRITEBACK_RESULT();
23291811}
23301812
r9854r9855
23401822   // ------------------------------------------------------
23411823   //
23421824
1825   int sel;
1826   INT32 s1, s2;
1827   INT64 r;
23431828   for (i=0; i < 8; i++)
23441829   {
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 ?
23511835
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);
23531839
23541840      if (r < 0)
23551841      {
2356         vres[del] = 0;
1842         vres[i] = 0;
23571843      }
2358      else if ((ACCUM(del).h.high ^ ACCUM(del).h.mid) < 0)
1844      else if (((INT16)(ACCUM_H(i)) ^ (INT16)(ACCUM_M(i))) < 0)
23591845      {
2360         vres[del] = -1;
2361
1846         vres[i] = -1;
23621847      }
23631848      else
23641849      {
2365         vres[del] = ACCUM(del).h.mid;
1850         vres[i] = ACCUM_M(i);
23661851      }
23671852   }
23681853   WRITEBACK_RESULT();
23691854}
23701855
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
2460static 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
25551856INLINE void cfunc_rsp_vmudl(void *param)
25561857{
25571858   rsp_state *rsp = (rsp_state*)param;
r9854r9855
25661867   // The result is added into accumulator
25671868   // The middle slice of accumulator is stored into destination element
25681869
2569   switch(EL)
1870   int sel;
1871   UINT32 s1, s2;
1872   UINT32 r;
1873   for (int i = 0; i < 8; i++)
25701874   {
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;
26221879
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);
26271883
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);
27101885   }
2711
2712static 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();
27771887}
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   }
28061888
28071889INLINE void cfunc_rsp_vmudm(void *param)
28081890{
r9854r9855
28191901   // The result is stored into accumulator
28201902   // The middle slice of accumulator is stored into destination element
28211903
2822   switch(EL)
1904   int sel;
1905   INT32 s1, s2;
1906   INT32 r;
1907   for (int i = 0; i < 8; i++)
28231908   {
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;
28731913
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);
28821917
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);
28881919   }
28891920   WRITEBACK_RESULT();
2890#endif
28911921}
2892#endif
28931922
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
29141923INLINE void cfunc_rsp_vmudn(void *param)
29151924{
29161925   rsp_state *rsp = (rsp_state*)param;
29171926   int op = rsp->impstate->arg0;
1927   INT16 vres[8] = { 0 };
1928
29181929   // 31       25  24     20      15      10      5        0
29191930   // ------------------------------------------------------
29201931   // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 000110 |
r9854r9855
29241935   // The result is stored into accumulator
29251936   // The low slice of accumulator is stored into destination element
29261937
2927   switch(EL)
1938   int sel;
1939   INT32 s1, s2;
1940   INT32 r;
1941   for (int i = 0; i < 8; i++)
29281942   {
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);
29771953   }
1954   WRITEBACK_RESULT();
29781955}
29791956
29801957INLINE void cfunc_rsp_vmudh(void *param)
r9854r9855
29921969   // The result is stored into highest 32 bits of accumulator, the low slice is zero
29931970   // The highest 32 bits of accumulator is saturated into destination element
29941971
1972   int sel;
1973   INT32 s1, s2;
1974   INT32 r;
29951975   for (i=0; i < 8; i++)
29961976   {
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;
30021981
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;
30061985
30071986      if (r < -32768) r = -32768;
30081987      if (r >  32767)   r = 32767;
3009      vres[del] = (INT16)(r);
1988      vres[i] = (INT16)(r);
30101989   }
30111990   WRITEBACK_RESULT();
30121991}
30131992
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
30421993INLINE void cfunc_rsp_vmacf(void *param)
30431994{
30441995   rsp_state *rsp = (rsp_state*)param;
30451996   int op = rsp->impstate->arg0;
30461997   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
30551998
3056   switch(EL)
1999   int sel;
2000   INT32 s1, s2;
2001   INT32 r;
2002   UINT16 res;
2003   for (int i = 0; i < 8; i++)
30572004   {
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;
31162009
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);
31192012
3120      vres[del] = res;
2013      vres[i] = res;
31212014   }
31222015   WRITEBACK_RESULT();
3123#endif
31242016}
31252017
31262018INLINE void cfunc_rsp_vmacu(void *param)
r9854r9855
31352027   // ------------------------------------------------------
31362028   //
31372029
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++)
31392035   {
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);
31482042
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);
31522046
3153      if (ACCUM(del).h.high < 0)
2047      //res = SATURATE_ACCUM(i, 1, 0x0000, 0xffff);
2048      if ((INT16)ACCUM_H(i) < 0)
31542049      {
31552050         res = 0;
31562051      }
31572052      else
31582053      {
3159         if (ACCUM(del).h.high != 0)
2054         if (ACCUM_H(i) != 0)
31602055         {
31612056            res = 0xffff;
31622057         }
31632058         else
31642059         {
3165            if (ACCUM(del).h.mid < 0)
2060            if ((INT16)ACCUM_M(i) < 0)
31662061            {
31672062               res = 0xffff;
31682063            }
31692064            else
31702065            {
3171               res = ACCUM(del).h.mid;
2066               res = ACCUM_M(i);
31722067            }
31732068         }
31742069      }
31752070
3176      vres[del] = res;
2071      vres[i] = res;
31772072   }
31782073   WRITEBACK_RESULT();
31792074}
r9854r9855
31932088   // Adds the higher 16 bits of the 32-bit result to accumulator
31942089   // The low slice of accumulator is stored into destination element
31952090
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++)
31972096   {
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);
32062103
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);
32102107
3211      res = SATURATE_ACCUM_UNSIGNED(rsp, del);
2108      res = SATURATE_ACCUM(rsp, i, 0, 0x0000, 0xffff);
32122109
3213      vres[del] = res;
2110      vres[i] = res;
32142111   }
32152112   WRITEBACK_RESULT();
32162113}
32172114
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
3307static 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
34022115INLINE void cfunc_rsp_vmadm(void *param)
34032116{
34042117   rsp_state *rsp = (rsp_state*)param;
34052118   int op = rsp->impstate->arg0;
34062119   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
34152120
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++)
34172126   {
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);
34692133
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;
34742139
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);
35582141
3559static 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;
36212143   }
3622
3623   return TRUE;
2144   WRITEBACK_RESULT();
36242145}
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   }
36532146
36542147INLINE void cfunc_rsp_vmadn(void *param)
36552148{
36562149   rsp_state *rsp = (rsp_state*)param;
36572150   int op = rsp->impstate->arg0;
36582151   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++)
36682157   {
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);
37202161
3721#if (DRC_VMADH)
3722/*------------------------------------------------------------------
3723    generate_vmadh
3724------------------------------------------------------------------*/
2162      ACCUM(i) += (INT64)(s1*s2)<<16;
37252163
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;
37842166   }
3785
3786static 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();
38512168}
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   }
38802169
38812170INLINE void cfunc_rsp_vmadh(void *param)
38822171{
r9854r9855
38922181   // The result is added into highest 32 bits of accumulator, the low slice is zero
38932182   // The highest 32 bits of accumulator is saturated into destination element
38942183
3895   switch(EL)
2184   UINT16 res;
2185   int sel;
2186   INT32 s1, s2;
2187   for (int i = 0; i < 8; i++)
38962188   {
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);
39482192
3949#if (DRC_VADD)
3950/*------------------------------------------------------------------
3951    generate_vadd
3952------------------------------------------------------------------*/
2193      rsp->accum[i].l[1] += s1*s2;
39532194
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);
41912196
4192static 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;
42542198   }
4255
4256   return TRUE;
2199   WRITEBACK_RESULT();
42572200}
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   }
42792201
42802202INLINE void cfunc_rsp_vadd(void *param)
42812203{
r9854r9855
42902212   //
42912213   // Adds two vector registers and carry flag, the result is saturated to 32767
42922214
4293   // TODO: check VS2REG == VDREG
4294   switch(EL)
2215   int sel;
2216   INT32 s1, s2, r;
2217   for (int i = 0; i < 8; i++)
42952218   {
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);
43442229   }
4345   rsp->flag[0] = 0;
2230   CLEAR_ZERO_FLAGS();
2231   CLEAR_CARRY_FLAGS();
43462232   WRITEBACK_RESULT();
43472233}
4348#endif
43492234
43502235INLINE void cfunc_rsp_vsub(void *param)
43512236{
r9854r9855
43622247
43632248   // TODO: check VS2REG == VDREG
43642249
4365   for (i=0; i < 8; i++)
2250   int sel;
2251   INT32 s1, s2, r;
2252   for (i = 0; i < 8; i++)
43662253   {
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);
43722258
4373      W_ACCUM_L(del, (INT16)(r));
2259      ACCUM_L(i) = (INT16)(r);
43742260
43752261      if (r > 32767) r = 32767;
43762262      if (r < -32768) r = -32768;
43772263
4378      vres[del] = (INT16)(r);
2264      vres[i] = (INT16)(r);
43792265   }
4380   rsp->flag[0] = 0;
2266   CLEAR_ZERO_FLAGS();
2267   CLEAR_CARRY_FLAGS();
43812268   WRITEBACK_RESULT();
43822269}
43832270
r9854r9855
43952282   // Changes the sign of source register 2 if source register 1 is negative and stores
43962283   // the result to destination register
43972284
2285   int sel;
2286   INT16 s1, s2;
43982287   for (i=0; i < 8; i++)
43992288   {
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);
44042292
44052293      if (s1 < 0)
44062294      {
44072295         if (s2 == -32768)
44082296         {
4409            vres[del] = 32767;
2297            vres[i] = 32767;
44102298         }
44112299         else
44122300         {
4413            vres[del] = -s2;
2301            vres[i] = -s2;
44142302         }
44152303      }
44162304      else if (s1 > 0)
44172305      {
4418         vres[del] = s2;
2306         vres[i] = s2;
44192307      }
44202308      else
44212309      {
4422         vres[del] = 0;
2310         vres[i] = 0;
44232311      }
44242312
4425      W_ACCUM_L(del, vres[del]);
2313      ACCUM_L(i) = vres[i];
44262314   }
44272315   WRITEBACK_RESULT();
44282316}
r9854r9855
44422330
44432331   // TODO: check VS2REG = VDREG
44442332
4445   rsp->flag[0] = 0;
2333   int sel;
2334   INT32 s1, s2, r;
2335   CLEAR_ZERO_FLAGS();
2336   CLEAR_CARRY_FLAGS();
44462337
44472338   for (i=0; i < 8; i++)
44482339   {
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;
44542344
4455      vres[del] = (INT16)(r);
4456      W_ACCUM_L(del, (INT16)(r));
2345      vres[i] = (INT16)(r);
2346      ACCUM_L(i) = (INT16)(r);
44572347
44582348      if (r & 0xffff0000)
44592349      {
4460         SET_CARRY_FLAG(del);
2350         SET_CARRY_FLAG(i);
44612351      }
44622352   }
44632353   WRITEBACK_RESULT();
r9854r9855
44782368
44792369   // TODO: check VS2REG = VDREG
44802370
4481   rsp->flag[0] = 0;
2371   int sel;
2372   INT32 s1, s2, r;
2373   CLEAR_ZERO_FLAGS();
2374   CLEAR_CARRY_FLAGS();
44822375
44832376   for (i=0; i < 8; i++)
44842377   {
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;
44902382
4491      vres[del] = (INT16)(r);
4492      W_ACCUM_L(del, (UINT16)(r));
2383      vres[i] = (INT16)(r);
2384      ACCUM_L(i) = (UINT16)(r);
44932385
44942386      if ((UINT16)(r) != 0)
44952387      {
4496         SET_ZERO_FLAG(del);
2388         SET_ZERO_FLAG(i);
44972389      }
44982390      if (r & 0xffff0000)
44992391      {
4500         SET_CARRY_FLAG(del);
2392         SET_CARRY_FLAG(i);
45012393      }
45022394   }
45032395   WRITEBACK_RESULT();
r9854r9855
45182410   {
45192411      case 0x08:      // VSAWH
45202412      {
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         }
45292417         break;
45302418      }
45312419      case 0x09:      // VSAWM
45322420      {
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         }
45412425         break;
45422426      }
45432427      case 0x0a:      // VSAWL
45442428      {
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         }
45532433         break;
45542434      }
45552435      default:   fatalerror("RSP: VSAW: el = %d\n", EL);
45562436   }
45572437}
45582438
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
46862439INLINE void cfunc_rsp_vlt(void *param)
46872440{
46882441   rsp_state *rsp = (rsp_state*)param;
r9854r9855
46972450   // Sets compare flags if elements in VS1 are less than VS2
46982451   // Moves the element in VS2 to destination vector
46992452
4700   switch(EL)
2453   int sel;
2454   rsp->flag[1] = 0;
2455
2456   for (int i = 0; i < 8; i++)
47012457   {
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];
47502482   }
47512483
2484   rsp->flag[0] = 0;
2485   WRITEBACK_RESULT();
47522486}
47532487
47542488INLINE void cfunc_rsp_veq(void *param)
r9854r9855
47652499   // Sets compare flags if elements in VS1 are equal with VS2
47662500   // Moves the element in VS2 to destination vector
47672501
2502   int sel;
47682503   rsp->flag[1] = 0;
47692504
4770   for (i=0; i < 8; i++)
2505   for (i = 0; i < 8; i++)
47712506   {
4772      int del = VEC_EL_1(EL, i);
4773      int sel = VEC_EL_2(EL, del);
2507      sel = VEC_EL_2(EL, i);
47742508
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)
47792510      {
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);
47842513      }
2514      else
2515      {
2516         vres[i] = VREG_S(VS2REG, sel);
2517      }
2518      ACCUM_L(i) = vres[i];
47852519   }
47862520
47872521   rsp->flag[0] = 0;
r9854r9855
48022536   // Sets compare flags if elements in VS1 are not equal with VS2
48032537   // Moves the element in VS2 to destination vector
48042538
2539   int sel;
48052540   rsp->flag[1] = 0;
48062541
4807   for (i=0; i < 8; i++)
2542   for (i=0; i < 8; i++)//ïåðåïèñàíî ìíîé
48082543   {
4809      int del = VEC_EL_1(EL, i);
4810      int sel = VEC_EL_2(EL, del);
2544      sel = VEC_EL_2(EL, i);
48112545
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))
48162547      {
4817         SET_COMPARE_FLAG(del);
2548         SET_COMPARE_FLAG(i);
48182549      }
48192550      else
48202551      {
4821         if (ZERO_FLAG(del) != 0)
2552         if (ZERO_FLAG(i) == 1)
48222553         {
4823            SET_COMPARE_FLAG(del);
2554            SET_COMPARE_FLAG(i);
48242555         }
48252556      }
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];
48262566   }
48272567
48282568   rsp->flag[0] = 0;
48292569   WRITEBACK_RESULT();
48302570}
48312571
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
50152572INLINE void cfunc_rsp_vge(void *param)
50162573{
50172574   rsp_state *rsp = (rsp_state*)param;
r9854r9855
50262583   // Sets compare flags if elements in VS1 are greater or equal with VS2
50272584   // Moves the element in VS2 to destination vector
50282585
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;
50822587   rsp->flag[1] = 0;
50832588
5084   for (i=0; i < 8; i++)
2589   for (int i = 0; i < 8; i++)
50852590   {
5086      int del = VEC_EL_1(EL, i);
5087      int sel = VEC_EL_2(EL, del);
2591      sel = VEC_EL_2(EL, i);
50882592
5089      if (R_VREG_S(VS1REG, del) == R_VREG_S(VS2REG, sel))
2593      if (VREG_S(VS1REG, i) == VREG_S(VS2REG, sel))
50902594      {
5091         if (ZERO_FLAG(del) == 0 || CARRY_FLAG(del) == 0)
2595         if (ZERO_FLAG(i) == 0 || CARRY_FLAG(i) == 0)
50922596         {
5093            SET_COMPARE_FLAG(del);
2597            SET_COMPARE_FLAG(i);
50942598         }
50952599      }
5096      else if (R_VREG_S(VS1REG, del) > R_VREG_S(VS2REG, sel))
2600      else if (VREG_S(VS1REG, i) > VREG_S(VS2REG, sel))
50972601      {
5098         SET_COMPARE_FLAG(del);
2602         SET_COMPARE_FLAG(i);
50992603      }
51002604
5101      if (COMPARE_FLAG(del))
2605      if (COMPARE_FLAG(i) != 0)
51022606      {
5103         vres[del] = R_VREG_S(VS1REG, del);
2607         vres[i] = VREG_S(VS1REG, i);
51042608      }
51052609      else
51062610      {
5107         vres[del] = R_VREG_S(VS2REG, sel);
2611         vres[i] = VREG_S(VS2REG, sel);
51082612      }
51092613
5110      W_ACCUM_L(del, vres[del]);
2614      ACCUM_L(i) = vres[i];
51112615   }
51122616
51132617   rsp->flag[0] = 0;
51142618   WRITEBACK_RESULT();
5115#endif
51162619}
51172620
51182621INLINE void cfunc_rsp_vcl(void *param)
r9854r9855
51282631   //
51292632   // Vector clip low
51302633
5131   for (i=0; i < 8; i++)
2634   int sel;
2635   INT16 s1, s2;
2636   for (i = 0; i < 8; i++)
51322637   {
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);
51372641
5138      if (CARRY_FLAG(del) != 0)
2642      if (CARRY_FLAG(i) != 0)
51392643      {
5140         if (ZERO_FLAG(del) != 0)
2644
2645         if (ZERO_FLAG(i) != 0)
51412646         {
5142            if (COMPARE_FLAG(del) != 0)
2647
2648            if (COMPARE_FLAG(i) != 0)
51432649            {
5144               W_ACCUM_L(del, -(UINT16)s2);
2650               ACCUM_L(i) = -(UINT16)s2;
51452651            }
51462652            else
51472653            {
5148               W_ACCUM_L(del, s1);
2654               ACCUM_L(i) = s1;
51492655            }
51502656         }
5151         else
2657         else//ZERO_FLAG(i)==0
51522658         {
5153            if (rsp->flag[2] & (1 << (del)))
2659
2660            if (rsp->flag[2] & (1 << (i)))
51542661            {
2662
51552663               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);
51592668               }
51602669               else
51612670               {
5162                  W_ACCUM_L(del, -((UINT16)s2));
5163                  SET_COMPARE_FLAG(del);
2671
2672                  ACCUM_L(i) = -((UINT16)s2);
2673                  SET_COMPARE_FLAG(i);
51642674               }
51652675            }
51662676            else
51672677            {
5168               if (((UINT32)(INT16)(s1) + (UINT32)(INT16)(s2)) != 0)
2678               if (((UINT32)(UINT16)(s1) + (UINT32)(UINT16)(s2)) != 0)
51692679               {
5170                  W_ACCUM_L(del, s1);
5171                  CLEAR_COMPARE_FLAG(del);
2680                  ACCUM_L(i) = s1;
2681                  CLEAR_COMPARE_FLAG(i);
51722682               }
51732683               else
51742684               {
5175                  W_ACCUM_L(del, -((UINT16)s2));
5176                  SET_COMPARE_FLAG(del);
2685                  ACCUM_L(i) = -((UINT16)s2);
2686                  SET_COMPARE_FLAG(i);
51772687               }
51782688            }
51792689         }
5180      }
5181      else
2690      }//
2691      else//CARRY_FLAG(i)==0
51822692      {
5183         if (ZERO_FLAG(del) != 0)
2693
2694         if (ZERO_FLAG(i) != 0)
51842695         {
5185            if (rsp->flag[1] & (0x100 << del))
2696
2697            if (rsp->flag[1] & (1 << (8+i)))
51862698            {
5187               W_ACCUM_L(del, s2);
2699               ACCUM_L(i) = s2;
51882700            }
51892701            else
51902702            {
5191               W_ACCUM_L(del, s1);
2703               ACCUM_L(i) = s1;
51922704            }
51932705         }
51942706         else
51952707         {
51962708            if (((INT32)(UINT16)s1 - (INT32)(UINT16)s2) >= 0)
51972709            {
5198               W_ACCUM_L(del, s2);
5199               rsp->flag[1] |= (0x100 << del);
2710               ACCUM_L(i) = s2;
2711               rsp->flag[1] |= (1 << (8+i));
52002712            }
52012713            else
52022714            {
5203               W_ACCUM_L(del, s1);
5204               rsp->flag[1] &= ~(0x100 << del);
2715               ACCUM_L(i) = s1;
2716               rsp->flag[1] &= ~(1 << (8+i));
52052717            }
52062718         }
52072719      }
52082720
5209      vres[del] = ACCUM(del).h.low;
2721      vres[i] = ACCUM_L(i);
52102722   }
52112723   rsp->flag[0] = 0;
52122724   rsp->flag[2] = 0;
r9854r9855
52262738   //
52272739   // Vector clip high
52282740
2741   int sel;
2742   INT16 s1, s2;
52292743   rsp->flag[0] = 0;
52302744   rsp->flag[1] = 0;
52312745   rsp->flag[2] = 0;
2746   UINT32 vce = 0;
52322747
52332748   for (i=0; i < 8; i++)
52342749   {
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);
52392753
52402754      if ((s1 ^ s2) < 0)
52412755      {
5242         SET_CARRY_FLAG(del);
2756         vce = (s1 + s2 == -1);
2757         SET_CARRY_FLAG(i);
52432758         if (s2 < 0)
52442759         {
5245            rsp->flag[1] |= (0x100 << del);
2760            rsp->flag[1] |= (1 << (8+i));
52462761         }
52472762
52482763         if (s1 + s2 <= 0)
52492764         {
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);
52562767         }
52572768         else
52582769         {
5259            vres[del] = s1;
2770            vres[i] = s1;
52602771         }
52612772
52622773         if (s1 + s2 != 0)
52632774         {
52642775            if (s1 != ~s2)
52652776            {
5266               SET_ZERO_FLAG(del);
2777               SET_ZERO_FLAG(i);
52672778            }
52682779         }
5269      }
2780      }//sign
52702781      else
52712782      {
2783         vce = 0;
52722784         if (s2 < 0)
52732785         {
5274            SET_COMPARE_FLAG(del);
2786            SET_COMPARE_FLAG(i);
52752787         }
52762788         if (s1 - s2 >= 0)
52772789         {
5278            rsp->flag[1] |= (0x100 << del);
5279            vres[del] = s2;
2790            rsp->flag[1] |= (1 << (8+i));
2791            vres[i] = s2;
52802792         }
52812793         else
52822794         {
5283            vres[del] = s1;
2795            vres[i] = s1;
52842796         }
52852797
52862798         if ((s1 - s2) != 0)
52872799         {
52882800            if (s1 != ~s2)
52892801            {
5290               SET_ZERO_FLAG(del);
2802               SET_ZERO_FLAG(i);
52912803            }
52922804         }
52932805      }
5294
5295      W_ACCUM_L(del, vres[del]);
2806      rsp->flag[2] |= (vce << (i));
2807      ACCUM_L(i) = vres[i];
52962808   }
52972809   WRITEBACK_RESULT();
52982810}
r9854r9855
53102822   //
53112823   // Vector clip reverse
53122824
2825   int sel;
2826   INT16 s1, s2;
53132827   rsp->flag[0] = 0;
53142828   rsp->flag[1] = 0;
53152829   rsp->flag[2] = 0;
53162830
53172831   for (i=0; i < 8; i++)
53182832   {
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);
53232836
53242837      if ((INT16)(s1 ^ s2) < 0)
53252838      {
53262839         if (s2 < 0)
53272840         {
5328            rsp->flag[1] |= (0x100 << del);
2841            rsp->flag[1] |= (1 << (8+i));
53292842         }
53302843         if ((s1 + s2) <= 0)
53312844         {
5332            W_ACCUM_L(del, ~((UINT16)s2));
5333            SET_COMPARE_FLAG(del);
2845            ACCUM_L(i) = ~((UINT16)s2);
2846            SET_COMPARE_FLAG(i);
53342847         }
53352848         else
53362849         {
5337            W_ACCUM_L(del, s1);
2850            ACCUM_L(i) = s1;
53382851         }
53392852      }
53402853      else
53412854      {
53422855         if (s2 < 0)
53432856         {
5344            SET_COMPARE_FLAG(del);
2857            SET_COMPARE_FLAG(i);
53452858         }
53462859         if ((s1 - s2) >= 0)
53472860         {
5348            W_ACCUM_L(del, s2);
5349            rsp->flag[1] |= (0x100 << del);
2861            ACCUM_L(i) = s2;
2862            rsp->flag[1] |= (1 << (8+i));
53502863         }
53512864         else
53522865         {
5353            W_ACCUM_L(del, s1);
2866            ACCUM_L(i) = s1;
53542867         }
53552868      }
53562869
5357      vres[del] = ACCUM(del).h.low;
2870      vres[i] = ACCUM_L(i);
53582871   }
53592872   WRITEBACK_RESULT();
53602873}
53612874
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
54362875INLINE void cfunc_rsp_vmrg(void *param)
54372876{
54382877   rsp_state *rsp = (rsp_state*)param;
r9854r9855
54452884   //
54462885   // Merges two vectors according to compare flags
54472886
5448   switch(EL)
2887   int sel;
2888   for (int i = 0; i < 8; i++)
54492889   {
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];
54982901   }
54992902   WRITEBACK_RESULT();
55002903}
55012904
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
5563static 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
56472905INLINE void cfunc_rsp_vand(void *param)
56482906{
56492907   rsp_state *rsp = (rsp_state*)param;
r9854r9855
56562914   //
56572915   // Bitwise AND of two vector registers
56582916
5659   switch(EL)
2917   int sel;
2918   for (int i = 0; i < 8; i++)
56602919   {
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];
57092923   }
57102924   WRITEBACK_RESULT();
57112925}
5712#endif
57132926
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
5783static 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
58672927INLINE void cfunc_rsp_vnand(void *param)
58682928{
58692929   rsp_state *rsp = (rsp_state*)param;
r9854r9855
58762936   //
58772937   // Bitwise NOT AND of two vector registers
58782938
5879   switch(EL)
2939   int sel;
2940   for (int i = 0; i < 8; i++)
58802941   {
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];
59292945   }
59302946   WRITEBACK_RESULT();
59312947}
5932#endif
59332948
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
5995static 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
60792949INLINE void cfunc_rsp_vor(void *param)
60802950{
60812951   rsp_state *rsp = (rsp_state*)param;
r9854r9855
60882958   //
60892959   // Bitwise OR of two vector registers
60902960
6091   switch(EL)
2961   int sel;
2962   for (int i = 0; i < 8; i++)
60922963   {
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];
61412967   }
61422968   WRITEBACK_RESULT();
61432969}
6144#endif
61452970
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
6215static 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
62992971INLINE void cfunc_rsp_vnor(void *param)
63002972{
63012973   rsp_state *rsp = (rsp_state*)param;
r9854r9855
63082980   //
63092981   // Bitwise NOT OR of two vector registers
63102982
6311   switch(EL)
2983   int sel;
2984   for (int i = 0; i < 8; i++)
63122985   {
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];
63612989   }
63622990   WRITEBACK_RESULT();
63632991}
6364#endif
63652992
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
6427static 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
65112993INLINE void cfunc_rsp_vxor(void *param)
65122994{
65132995   rsp_state *rsp = (rsp_state*)param;
r9854r9855
65203002   //
65213003   // Bitwise XOR of two vector registers
65223004
6523   switch(EL)
3005   int sel;
3006   for (int i = 0; i < 8; i++)
65243007   {
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];
65733011   }
65743012   WRITEBACK_RESULT();
65753013}
6576#endif
65773014
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
6647static 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
67313015INLINE void cfunc_rsp_vnxor(void *param)
67323016{
67333017   rsp_state *rsp = (rsp_state*)param;
r9854r9855
67403024   //
67413025   // Bitwise NOT XOR of two vector registers
67423026
6743   switch(EL)
3027   int sel;
3028   for (int i = 0; i < 8; i++)
67443029   {
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];
67933033   }
67943034   WRITEBACK_RESULT();
67953035}
6796#endif
67973036
67983037INLINE void cfunc_rsp_vrcp(void *param)
67993038{
r9854r9855
68073046   //
68083047   // Calculates reciprocal
68093048
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;
68133052
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)
68173056   {
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++)
68283058      {
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
68373060         {
6838            exp = i;
6839            mantissa = (rec << (15 - i)) >> 6;
3061            shifter = i;
68403062            break;
68413063         }
68423064      }
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      }
68773065   }
3066   else
3067   {
3068      shifter = 0x10;
3069   }
68783070
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)
68803075   {
6881      int element = VEC_EL_2(EL, i);
6882      W_ACCUM_L(i, R_VREG_S_X(VS2REG, element));
3076      temp = ~temp;
68833077   }
3078   if (!rec)
3079   {
3080      temp = 0x7fffffff;
3081   }
3082   else if (rec == 0xffff8000)
3083   {
3084      temp = 0xffff0000;
3085   }
3086   rec = temp;
68843087
68853088   rsp->reciprocal_res = rec;
3089   rsp->dp_allowed = 0;
68863090
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   }
68883098}
68893099
68903100INLINE void cfunc_rsp_vrcpl(void *param)
r9854r9855
68993109   //
69003110   // Calculates reciprocal low part
69013111
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;
69053115
6906   rec = ((UINT16)(R_VREG_S_X(VS2REG, sel)) | ((UINT32)(rsp->reciprocal_high) << 16));
3116   INT32 rec = ((UINT16)(VREG_S(VS2REG, sel)) | ((UINT32)(rsp->reciprocal_high) & 0xffff0000));
69073117
6908   if (rec == 0)
3118   INT32 datainput = rec;
3119
3120   if (rec < 0)
69093121   {
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)
69173123      {
6918         if (((UINT32)(rec & 0xffff0000) == 0xffff0000) && ((INT16)(rec & 0xffff) < 0))
3124         if (rec < -32768)
69193125         {
6920            rec = ~rec+1;
3126            datainput = ~datainput;
69213127         }
69223128         else
69233129         {
6924            rec = ~rec;
3130            datainput = -datainput;
69253131         }
6926         negative = 1;
69273132      }
6928      for (i = 31; i > 0; i--)
3133      else
69293134      {
6930         if (rec & (1 << i))
6931         {
6932            rec &= ((0xffc00000) >> (31 - i));
6933            i = 0;
6934         }
3135         datainput = -datainput;
69353136      }
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++)
69383143      {
6939         if (rec & (1 << i))
3144         if (datainput & (1 << ((~i) & 0x1f)))//ò.æ.÷òî 31 - i
69403145         {
6941            rec &= ((0xffff8000) >> (31 - i));
6942            i = 0;
3146            shifter = i;
3147            break;
69433148         }
69443149      }
6945      if (negative)
3150   }
3151   else
3152   {
3153      if (rsp->dp_allowed)
69463154      {
6947         rec = ~rec;
3155         shifter = 0;
69483156      }
3157      else
3158      {
3159         shifter = 0x10;
3160      }
69493161   }
69503162
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)
69523167   {
6953      int element = VEC_EL_2(EL, i);
6954      W_ACCUM_L(i, R_VREG_S_X(VS2REG, element));
3168      temp = ~temp;
69553169   }
3170   if (!rec)
3171   {
3172      temp = 0x7fffffff;
3173   }
3174   else if (rec == 0xffff8000)
3175   {
3176      temp = 0xffff0000;
3177   }
3178   rec = temp;
69563179
69573180   rsp->reciprocal_res = rec;
3181   rsp->dp_allowed = 0;
69583182
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   }
69603190}
69613191
69623192INLINE void cfunc_rsp_vrcph(void *param)
r9854r9855
69703200   //
69713201   // Calculates reciprocal high part
69723202
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;
69753205
6976   rsp->reciprocal_high = R_VREG_S_X(VS2REG, sel);
3206   rsp->reciprocal_high = (VREG_S(VS2REG, sel)) << 16;
3207   rsp->dp_allowed = 1;
69773208
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   }
69863214
6987   W_VREG_S_X(VDREG, del, (INT16)(rsp->reciprocal_res >> 16));   // store high part
3215   VREG_S(VDREG, del) = (INT16)(rsp->reciprocal_res >> 16);
69883216}
69893217
69903218INLINE void cfunc_rsp_vmov(void *param)
r9854r9855
69983226   //
69993227   // Moves element from vector to destination vector
70003228
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   }
70033238}
70043239
70053240INLINE void cfunc_rsp_vrsql(void *param)
r9854r9855
70143249   //
70153250   // Calculates reciprocal square-root low part
70163251
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;
70203255
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   }
70223273
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)
70243280   {
7025      // square root on 0 -> overflow
7026      sqr = 0x7fffffff;
3281      temp = ~temp;
70273282   }
7028   else if (sqr == 0xffff8000)
3283   if (!rec)
70293284   {
7030      // overflow ?
7031      sqr = 0xffff8000;
3285      temp = 0x7fffffff;
70323286   }
7033   else
3287   else if (rec == 0xffff8000)
70343288   {
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;
70693290   }
3291   rec = temp;
70703292
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;
70793295
7080   rsp->square_root_res = sqr;
3296   VREG_S(VDREG, del) = (UINT16)(rec & 0xffff);
70813297
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   }
70833303}
70843304
70853305INLINE void cfunc_rsp_vrsqh(void *param)
r9854r9855
70943314   //
70953315   // Calculates reciprocal square-root high part
70963316
7097   int del = (VS1REG & 7);
7098   int sel = VEC_EL_2(EL, del);
3317   int del = VS1REG & 7;
3318   int sel = EL & 7;
70993319
7100   rsp->square_root_high = R_VREG_S(VS2REG, sel);
3320   rsp->reciprocal_high = (VREG_S(VS2REG, sel)) << 16;
3321   rsp->dp_allowed = 1;
71013322
71023323   for (i=0; i < 8; i++)
71033324   {
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);
71063327   }
71073328
7108   W_VREG_S(VDREG, del, (INT16)(rsp->square_root_res >> 16));   // store high part
3329   VREG_S(VDREG, del) = (INT16)(rsp->reciprocal_res >> 16);   // store high part
71093330}
3331
71103332static void cfunc_sp_set_status_cb(void *param)
71113333{
71123334   rsp_state *rsp = (rsp_state*)param;
r9854r9855
74553677   {
74563678      if (size == 1)
74573679      {
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
74583685#ifdef LSB_FIRST
74593686         UML_XOR(block, IREG(0), IREG(0), IMM(3));                           // xor     i0,i0,3
74603687#endif
r9854r9855
74633690      }
74643691      else if (size == 2)
74653692      {
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
74663698#ifdef LSB_FIRST
74673699         UML_TEST(block, IREG(0), IMM(1));                                 // test    i0,1
74683700         UML_JMPc(block, IF_NZ, unaligned_case);                              // jnz     <unaligned_case>
r9854r9855
74873719      }
74883720      else if (size == 4)
74893721      {
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
74903727#ifdef LSB_FIRST
74913728         UML_TEST(block, IREG(0), IMM(3));                                 // test    i0,3
74923729         UML_JMPc(block, IF_NZ, unaligned_case);                              // jnz     <unaligned_case>
r9854r9855
75103747   }
75113748   else
75123749   {
3750      UML_MOV(block, MEM(&rsp->impstate->arg0), IREG(0));               // mov     [arg0],i0
75133751      if (size == 1)
75143752      {
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
75153755#ifdef LSB_FIRST
75163756         UML_XOR(block, IREG(0), IREG(0), IMM(3));                           // xor     i0,i0,3
75173757#endif
75183758         UML_AND(block, IREG(0), IREG(0), IMM(0x00000fff));                     // and     i0,i0,0xfff
75193759         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
75203762      }
75213763      else if (size == 2)
75223764      {
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
75233767#ifdef LSB_FIRST
75243768         UML_TEST(block, IREG(0), IMM(1));                                 // test    i0,1
75253769         UML_JMPc(block, IF_NZ, unaligned_case);                              // jnz     <unaligned_case>
r9854r9855
75273771#endif
75283772         UML_AND(block, IREG(0), IREG(0), IMM(0x00000fff));                     // and     i0,i0,0xfff
75293773         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
75303776         UML_RET(block);
75313777#ifdef LSB_FIRST
75323778         UML_LABEL(block, unaligned_case);                              // unaligned_case:
r9854r9855
75373783         UML_ADD(block, IREG(1), IREG(1), IMM(48));                           // add     i1,i1,48
75383784         UML_DROLAND(block, IREG(0), IREG(0), IREG(1), IMM(0xffff));               // droland i0,i0,i1,0xffff
75393785#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
75403788      }
75413789      else if (size == 4)
75423790      {
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
75433793#ifdef LSB_FIRST
75443794         UML_TEST(block, IREG(0), IMM(3));                                 // test    i0,3
75453795         UML_JMPc(block, IF_NZ, unaligned_case);                              // jnz     <unaligned_case>
75463796#endif
75473797         UML_AND(block, IREG(0), IREG(0), IMM(0x00000fff));                     // and     i0,i0,0xfff
75483798         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
75493801         UML_RET(block);
75503802#ifdef LSB_FIRST
75513803         UML_LABEL(block, unaligned_case);                              // unaligned_case:
r9854r9855
75553807         UML_DLOAD(block, IREG(0), rsp->impstate->dmem, IREG(0), QWORD_x1);         // dload   i0,dmem,i0,qword_x1
75563808         UML_DROL(block, IREG(0), IREG(0), IREG(1));                           // drol    i0,i0,i1
75573809#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
75583812      }
75593813   }
75603814   UML_RET(block);
r9854r9855
77684022         return TRUE;
77694023
77704024      case 0x04:      /* VMUDL */
7771#if (DRC_VMUDL)
7772         return generate_vmudl(rsp, block, compiler, desc);
7773#else
77744025         UML_MOV(block, MEM(&rsp->impstate->arg0), IMM(desc->opptr.l[0]));      // mov     [arg0],desc->opptr.l
77754026         UML_CALLC(block, cfunc_rsp_vmudl, rsp);
77764027         return TRUE;
7777#endif
77784028
77794029      case 0x05:      /* VMUDM */
7780#if (DRC_VMUDM)
7781         return generate_vmudm(rsp, block, compiler, desc);
7782#else
77834030         UML_MOV(block, MEM(&rsp->impstate->arg0), IMM(desc->opptr.l[0]));      // mov     [arg0],desc->opptr.l
77844031         UML_CALLC(block, cfunc_rsp_vmudm, rsp);
77854032         return TRUE;
7786#endif
77874033
77884034      case 0x06:      /* VMUDN */
77894035         UML_MOV(block, MEM(&rsp->impstate->arg0), IMM(desc->opptr.l[0]));      // mov     [arg0],desc->opptr.l
r9854r9855
78114057         return TRUE;
78124058
78134059      case 0x0d:      /* VMADM */
7814#if (DRC_VMADM)
7815         return generate_vmadm(rsp, block, compiler, desc);
7816#else
78174060         UML_MOV(block, MEM(&rsp->impstate->arg0), IMM(desc->opptr.l[0]));      // mov     [arg0],desc->opptr.l
78184061         UML_CALLC(block, cfunc_rsp_vmadm, rsp);
78194062         return TRUE;
7820#endif
78214063
78224064      case 0x0e:      /* VMADN */
7823#if (DRC_VMADN)
7824         return generate_vmadn(rsp, block, compiler, desc);
7825#else
78264065         UML_MOV(block, MEM(&rsp->impstate->arg0), IMM(desc->opptr.l[0]));      // mov     [arg0],desc->opptr.l
78274066         UML_CALLC(block, cfunc_rsp_vmadn, rsp);
78284067         return TRUE;
7829#endif
78304068
78314069      case 0x0f:      /* VMADH */
7832#if (DRC_VMADH)
7833         return generate_vmadh(rsp, block, compiler, desc);
7834#else
78354070         UML_MOV(block, MEM(&rsp->impstate->arg0), IMM(desc->opptr.l[0]));      // mov     [arg0],desc->opptr.l
78364071         UML_CALLC(block, cfunc_rsp_vmadh, rsp);
78374072         return TRUE;
7838#endif
78394073
78404074      case 0x10:      /* VADD */
7841#if (DRC_VADD)
7842         return generate_vadd(rsp, block, compiler, desc);
7843#else
78444075         UML_MOV(block, MEM(&rsp->impstate->arg0), IMM(desc->opptr.l[0]));      // mov     [arg0],desc->opptr.l
78454076         UML_CALLC(block, cfunc_rsp_vadd, rsp);
78464077         return TRUE;
7847#endif
78484078
78494079      case 0x11:      /* VSUB */
78504080         UML_MOV(block, MEM(&rsp->impstate->arg0), IMM(desc->opptr.l[0]));      // mov     [arg0],desc->opptr.l
r9854r9855
79124142         return TRUE;
79134143
79144144      case 0x28:      /* VAND */
7915#if (DRC_VAND)
7916         return generate_vand(rsp, block, compiler, desc);
7917#else
79184145         UML_MOV(block, MEM(&rsp->impstate->arg0), IMM(desc->opptr.l[0]));      // mov     [arg0],desc->opptr.l
79194146         UML_CALLC(block, cfunc_rsp_vand, rsp);
79204147         return TRUE;
7921#endif
79224148
79234149      case 0x29:      /* VNAND */
7924#if (DRC_VNAND)
7925         return generate_vnand(rsp, block, compiler, desc);
7926#else
79274150         UML_MOV(block, MEM(&rsp->impstate->arg0), IMM(desc->opptr.l[0]));      // mov     [arg0],desc->opptr.l
79284151         UML_CALLC(block, cfunc_rsp_vnand, rsp);
79294152         return TRUE;
7930#endif
79314153
79324154      case 0x2a:      /* VOR */
7933#if (DRC_VOR)
7934         return generate_vor(rsp, block, compiler, desc);
7935#else
79364155         UML_MOV(block, MEM(&rsp->impstate->arg0), IMM(desc->opptr.l[0]));      // mov     [arg0],desc->opptr.l
79374156         UML_CALLC(block, cfunc_rsp_vor, rsp);
79384157         return TRUE;
7939#endif
79404158
79414159      case 0x2b:      /* VNOR */
7942#if (DRC_VNOR)
7943         return generate_vnor(rsp, block, compiler, desc);
7944#else
79454160         UML_MOV(block, MEM(&rsp->impstate->arg0), IMM(desc->opptr.l[0]));      // mov     [arg0],desc->opptr.l
79464161         UML_CALLC(block, cfunc_rsp_vnor, rsp);
79474162         return TRUE;
7948#endif
79494163
79504164      case 0x2c:      /* VXOR */
7951#if (DRC_VXOR)
7952         return generate_vxor(rsp, block, compiler, desc);
7953#else
79544165         UML_MOV(block, MEM(&rsp->impstate->arg0), IMM(desc->opptr.l[0]));      // mov     [arg0],desc->opptr.l
79554166         UML_CALLC(block, cfunc_rsp_vxor, rsp);
79564167         return TRUE;
7957#endif
79584168
79594169      case 0x2d:      /* VNXOR */
7960#if (DRC_VNXOR)
7961         return generate_vnxor(rsp, block, compiler, desc);
7962#else
79634170         UML_MOV(block, MEM(&rsp->impstate->arg0), IMM(desc->opptr.l[0]));      // mov     [arg0],desc->opptr.l
79644171         UML_CALLC(block, cfunc_rsp_vnxor, rsp);
79654172         return TRUE;
7966#endif
79674173
79684174      case 0x30:      /* VRCP */
79694175         UML_MOV(block, MEM(&rsp->impstate->arg0), IMM(desc->opptr.l[0]));      // mov     [arg0],desc->opptr.l
r9854r9855
84904696   rsp_state *rsp = (rsp_state*)param;
84914697   UINT32 op = rsp->impstate->arg0;
84924698   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);
84954701   if (RTREG) RTVAL = (INT32)(INT16)((b1 << 8) | (b2));
84964702}
84974703
r9854r9855
85194725   rsp_state *rsp = (rsp_state*)param;
85204726   UINT32 op = rsp->impstate->arg0;
85214727   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;
85244730}
85254731
85264732static void cfunc_ctc2(void *param)
src/mess/mess.mak
r9854r9855
11841184   $(MAME_VIDEO)/n64.o      \
11851185   $(MAME_VIDEO)/rdpblend.o   \
11861186   $(MAME_VIDEO)/rdpfb.o      \
1187   $(MAME_VIDEO)/rdpfetch.o   \
11881187   $(MAME_VIDEO)/rdptpipe.o   \
11891188   $(MAME_VIDEO)/rdpspn16.o   \
1190   $(MAME_VIDEO)/rdptrect.o   \
1191   $(MAME_VIDEO)/rdpfrect.o   \
11921189   $(MESS_MACHINE)/pokemini.o   \
11931190   $(MESS_DRIVERS)/pokemini.o   \
11941191   $(MESS_DRIVERS)/vboy.o      \
src/mess/drivers/n64.c
r9854r9855
210210   ROM_LOAD( "normslp.rom", 0x00, 0x80, CRC(4f2ae525) SHA1(eab43f8cc52c8551d9cff6fced18ef80eaba6f05) )
211211ROM_END
212212
213CONS(1996, n64,    0,      0,      n64,   n64,   0,   "Nintendo", "Nintendo 64", GAME_NOT_WORKING | GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_SOUND )
213CONS(1996, n64,    0,      0,      n64,   n64,   0,   "Nintendo", "Nintendo 64", GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_SOUND )

Previous 15994 Revisions Next


© 1998-2018 The MESS Team