/[gxemul]/trunk/src/cpus/cpu_mips_instr.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Diff of /trunk/src/cpus/cpu_mips_instr.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 22 by dpavlin, Mon Oct 8 16:19:37 2007 UTC revision 28 by dpavlin, Mon Oct 8 16:20:26 2007 UTC
# Line 25  Line 25 
25   *  SUCH DAMAGE.   *  SUCH DAMAGE.
26   *   *
27   *   *
28   *  $Id: cpu_mips_instr.c,v 1.9 2006/02/17 20:27:21 debug Exp $   *  $Id: cpu_mips_instr.c,v 1.97 2006/07/20 03:20:03 debug Exp $
29   *   *
30   *  MIPS instructions.   *  MIPS instructions.
31   *   *
# Line 37  Line 37 
37    
38    
39  /*  /*
40   *  nop:  Do nothing.   *  invalid:  For catching bugs.
41   */   */
42  X(nop)  X(invalid)
43  {  {
44            fatal("FATAL ERROR: An internal error occured in the MIPS"
45                " dyntrans code. Please contact the author with detailed"
46                " repro steps on how to trigger this bug.\n");
47            exit(1);
48  }  }
49    
50    
51  /*  /*
52   *  invalid_32_64:  Attempt to execute a 64-bit instruction on an   *  reserved:  Attempt to execute a reserved instruction (e.g. a 64-bit
53   *                  emulated 32-bit processor.   *             instruction on an emulated 32-bit processor).
54   */   */
55  X(invalid_32_64)  X(reserved)
56    {
57            /*  Synchronize the PC and cause an exception:  */
58            int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
59                / sizeof(struct mips_instr_call);
60            cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
61                << MIPS_INSTR_ALIGNMENT_SHIFT);
62            cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
63            mips_cpu_exception(cpu, EXCEPTION_RI, 0, 0, 0, 0, 0, 0);
64    }
65    
66    
67    /*
68     *  cpu:  Cause a CoProcessor Unusable exception.
69     *
70     *  arg[0] = the number of the coprocessor
71     */
72    X(cpu)
73    {
74            /*  Synchronize the PC and cause an exception:  */
75            int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
76                / sizeof(struct mips_instr_call);
77            cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
78                << MIPS_INSTR_ALIGNMENT_SHIFT);
79            cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
80            mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0, ic->arg[0], 0, 0, 0);
81    }
82    
83    
84    /*
85     *  nop:  Do nothing.
86     */
87    X(nop)
88  {  {
         fatal("invalid_32_64: TODO\n");  
         exit(1);  
89  }  }
90    
91    
# Line 66  X(invalid_32_64) Line 100  X(invalid_32_64)
100   */   */
101  X(beq)  X(beq)
102  {  {
103          MODE_uint_t old_pc = cpu->pc;          MODE_int_t old_pc = cpu->pc;
104          MODE_uint_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]);          MODE_uint_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]);
105          int x = rs == rt;          int x = rs == rt;
106          cpu->cd.mips.delay_slot = TO_BE_DELAYED;          cpu->delay_slot = TO_BE_DELAYED;
107          ic[1].f(cpu, ic+1);          ic[1].f(cpu, ic+1);
108          cpu->n_translated_instrs ++;          cpu->n_translated_instrs ++;
109          if (!(cpu->cd.mips.delay_slot & EXCEPTION_IN_DELAY_SLOT)) {          if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
110                    /*  Note: Must be non-delayed when jumping to the new pc:  */
111                    cpu->delay_slot = NOT_DELAYED;
112                  if (x) {                  if (x) {
113                          old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<                          old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
114                              MIPS_INSTR_ALIGNMENT_SHIFT);                              MIPS_INSTR_ALIGNMENT_SHIFT);
# Line 80  X(beq) Line 116  X(beq)
116                          quick_pc_to_pointers(cpu);                          quick_pc_to_pointers(cpu);
117                  } else                  } else
118                          cpu->cd.mips.next_ic ++;                          cpu->cd.mips.next_ic ++;
119          }          } else
120          cpu->cd.mips.delay_slot = NOT_DELAYED;                  cpu->delay_slot = NOT_DELAYED;
121  }  }
122  X(beq_samepage)  X(beq_samepage)
123  {  {
124          MODE_uint_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]);          MODE_uint_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]);
125          int x = rs == rt;          int x = rs == rt;
126          cpu->cd.mips.delay_slot = TO_BE_DELAYED;          cpu->delay_slot = TO_BE_DELAYED;
127          ic[1].f(cpu, ic+1);          ic[1].f(cpu, ic+1);
128          cpu->n_translated_instrs ++;          cpu->n_translated_instrs ++;
129          if (!(cpu->cd.mips.delay_slot & EXCEPTION_IN_DELAY_SLOT)) {          if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
130                  if (x)                  if (x)
131                          cpu->cd.mips.next_ic = (struct mips_instr_call *)                          cpu->cd.mips.next_ic = (struct mips_instr_call *)
132                              ic->arg[2];                              ic->arg[2];
133                  else                  else
134                          cpu->cd.mips.next_ic ++;                          cpu->cd.mips.next_ic ++;
135          }          }
136          cpu->cd.mips.delay_slot = NOT_DELAYED;          cpu->delay_slot = NOT_DELAYED;
137    }
138    X(beq_samepage_addiu)
139    {
140            MODE_uint_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]);
141            cpu->n_translated_instrs ++;
142            reg(ic[1].arg[1]) = (int32_t)
143                ((int32_t)reg(ic[1].arg[0]) + (int32_t)ic[1].arg[2]);
144            if (rs == rt)
145                    cpu->cd.mips.next_ic = (struct mips_instr_call *) ic->arg[2];
146            else
147                    cpu->cd.mips.next_ic ++;
148    }
149    X(beq_samepage_nop)
150    {
151            MODE_uint_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]);
152            cpu->n_translated_instrs ++;
153            if (rs == rt)
154                    cpu->cd.mips.next_ic = (struct mips_instr_call *) ic->arg[2];
155            else
156                    cpu->cd.mips.next_ic ++;
157  }  }
158  X(bne)  X(bne)
159  {  {
160          MODE_uint_t old_pc = cpu->pc;          MODE_int_t old_pc = cpu->pc;
161          MODE_uint_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]);          MODE_uint_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]);
162          int x = rs != rt;          int x = rs != rt;
163          cpu->cd.mips.delay_slot = TO_BE_DELAYED;          cpu->delay_slot = TO_BE_DELAYED;
164          ic[1].f(cpu, ic+1);          ic[1].f(cpu, ic+1);
165          cpu->n_translated_instrs ++;          cpu->n_translated_instrs ++;
166          if (!(cpu->cd.mips.delay_slot & EXCEPTION_IN_DELAY_SLOT)) {          if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
167                    /*  Note: Must be non-delayed when jumping to the new pc:  */
168                    cpu->delay_slot = NOT_DELAYED;
169                  if (x) {                  if (x) {
170                          old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<                          old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
171                              MIPS_INSTR_ALIGNMENT_SHIFT);                              MIPS_INSTR_ALIGNMENT_SHIFT);
# Line 115  X(bne) Line 173  X(bne)
173                          quick_pc_to_pointers(cpu);                          quick_pc_to_pointers(cpu);
174                  } else                  } else
175                          cpu->cd.mips.next_ic ++;                          cpu->cd.mips.next_ic ++;
176          }          } else
177          cpu->cd.mips.delay_slot = NOT_DELAYED;                  cpu->delay_slot = NOT_DELAYED;
178  }  }
179  X(bne_samepage)  X(bne_samepage)
180  {  {
181          MODE_uint_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]);          MODE_uint_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]);
182          int x = rs != rt;          int x = rs != rt;
183          cpu->cd.mips.delay_slot = TO_BE_DELAYED;          cpu->delay_slot = TO_BE_DELAYED;
184          ic[1].f(cpu, ic+1);          ic[1].f(cpu, ic+1);
185          cpu->n_translated_instrs ++;          cpu->n_translated_instrs ++;
186          if (!(cpu->cd.mips.delay_slot & EXCEPTION_IN_DELAY_SLOT)) {          if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
187                  if (x)                  if (x)
188                          cpu->cd.mips.next_ic = (struct mips_instr_call *)                          cpu->cd.mips.next_ic = (struct mips_instr_call *)
189                              ic->arg[2];                              ic->arg[2];
190                  else                  else
191                          cpu->cd.mips.next_ic ++;                          cpu->cd.mips.next_ic ++;
192          }          }
193          cpu->cd.mips.delay_slot = NOT_DELAYED;          cpu->delay_slot = NOT_DELAYED;
194    }
195    X(bne_samepage_addiu)
196    {
197            MODE_uint_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]);
198            cpu->n_translated_instrs ++;
199            reg(ic[1].arg[1]) = (int32_t)
200                ((int32_t)reg(ic[1].arg[0]) + (int32_t)ic[1].arg[2]);
201            if (rs != rt)
202                    cpu->cd.mips.next_ic = (struct mips_instr_call *) ic->arg[2];
203            else
204                    cpu->cd.mips.next_ic ++;
205    }
206    X(bne_samepage_nop)
207    {
208            MODE_uint_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]);
209            cpu->n_translated_instrs ++;
210            if (rs != rt)
211                    cpu->cd.mips.next_ic = (struct mips_instr_call *) ic->arg[2];
212            else
213                    cpu->cd.mips.next_ic ++;
214  }  }
215  X(b)  X(b)
216  {  {
217          MODE_uint_t old_pc = cpu->pc;          MODE_int_t old_pc = cpu->pc;
218          cpu->cd.mips.delay_slot = TO_BE_DELAYED;          cpu->delay_slot = TO_BE_DELAYED;
219          ic[1].f(cpu, ic+1);          ic[1].f(cpu, ic+1);
220          cpu->n_translated_instrs ++;          cpu->n_translated_instrs ++;
221          if (!(cpu->cd.mips.delay_slot & EXCEPTION_IN_DELAY_SLOT)) {          if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
222                    /*  Note: Must be non-delayed when jumping to the new pc:  */
223                    cpu->delay_slot = NOT_DELAYED;
224                  old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<                  old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
225                      MIPS_INSTR_ALIGNMENT_SHIFT);                      MIPS_INSTR_ALIGNMENT_SHIFT);
226                  cpu->pc = old_pc + (int32_t)ic->arg[2];                  cpu->pc = old_pc + (int32_t)ic->arg[2];
227                  quick_pc_to_pointers(cpu);                  quick_pc_to_pointers(cpu);
228          }          } else
229          cpu->cd.mips.delay_slot = NOT_DELAYED;                  cpu->delay_slot = NOT_DELAYED;
230  }  }
231  X(b_samepage)  X(b_samepage)
232  {  {
233          cpu->cd.mips.delay_slot = TO_BE_DELAYED;          cpu->delay_slot = TO_BE_DELAYED;
234          ic[1].f(cpu, ic+1);          ic[1].f(cpu, ic+1);
235          cpu->n_translated_instrs ++;          cpu->n_translated_instrs ++;
236          if (!(cpu->cd.mips.delay_slot & EXCEPTION_IN_DELAY_SLOT))          if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT))
237                  cpu->cd.mips.next_ic = (struct mips_instr_call *) ic->arg[2];                  cpu->cd.mips.next_ic = (struct mips_instr_call *) ic->arg[2];
238          cpu->cd.mips.delay_slot = NOT_DELAYED;          cpu->delay_slot = NOT_DELAYED;
239    }
240    
241    
242    /*
243     *  beql:  Branch if equal likely
244     *  bnel:  Branch if not equal likely
245     *
246     *  arg[0] = pointer to rs
247     *  arg[1] = pointer to rt
248     *  arg[2] = (int32_t) relative offset from the next instruction
249     */
250    X(beql)
251    {
252            MODE_int_t old_pc = cpu->pc;
253            MODE_uint_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]);
254            int x = rs == rt;
255            cpu->delay_slot = TO_BE_DELAYED;
256            if (x)
257                    ic[1].f(cpu, ic+1);
258            cpu->n_translated_instrs ++;
259            if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
260                    /*  Note: Must be non-delayed when jumping to the new pc:  */
261                    cpu->delay_slot = NOT_DELAYED;
262                    if (x) {
263                            old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
264                                MIPS_INSTR_ALIGNMENT_SHIFT);
265                            cpu->pc = old_pc + (int32_t)ic->arg[2];
266                            quick_pc_to_pointers(cpu);
267                    } else
268                            cpu->cd.mips.next_ic ++;
269            } else
270                    cpu->delay_slot = NOT_DELAYED;
271    }
272    X(beql_samepage)
273    {
274            MODE_uint_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]);
275            int x = rs == rt;
276            cpu->delay_slot = TO_BE_DELAYED;
277            if (x)
278                    ic[1].f(cpu, ic+1);
279            cpu->n_translated_instrs ++;
280            if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
281                    if (x)
282                            cpu->cd.mips.next_ic = (struct mips_instr_call *)
283                                ic->arg[2];
284                    else
285                            cpu->cd.mips.next_ic ++;
286            }
287            cpu->delay_slot = NOT_DELAYED;
288    }
289    X(bnel)
290    {
291            MODE_int_t old_pc = cpu->pc;
292            MODE_uint_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]);
293            int x = rs != rt;
294            cpu->delay_slot = TO_BE_DELAYED;
295            if (x)
296                    ic[1].f(cpu, ic+1);
297            cpu->n_translated_instrs ++;
298            if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
299                    /*  Note: Must be non-delayed when jumping to the new pc:  */
300                    cpu->delay_slot = NOT_DELAYED;
301                    if (x) {
302                            old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
303                                MIPS_INSTR_ALIGNMENT_SHIFT);
304                            cpu->pc = old_pc + (int32_t)ic->arg[2];
305                            quick_pc_to_pointers(cpu);
306                    } else
307                            cpu->cd.mips.next_ic ++;
308            } else
309                    cpu->delay_slot = NOT_DELAYED;
310    }
311    X(bnel_samepage)
312    {
313            MODE_uint_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]);
314            int x = rs != rt;
315            cpu->delay_slot = TO_BE_DELAYED;
316            if (x)
317                    ic[1].f(cpu, ic+1);
318            cpu->n_translated_instrs ++;
319            if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
320                    if (x)
321                            cpu->cd.mips.next_ic = (struct mips_instr_call *)
322                                ic->arg[2];
323                    else
324                            cpu->cd.mips.next_ic ++;
325            }
326            cpu->delay_slot = NOT_DELAYED;
327    }
328    
329    
330    /*
331     *  blez:   Branch if less than or equal
332     *  blezl:  Branch if less than or equal likely
333     *
334     *  arg[0] = pointer to rs
335     *  arg[2] = (int32_t) relative offset from the next instruction
336     */
337    X(blez)
338    {
339            MODE_int_t old_pc = cpu->pc;
340            MODE_int_t rs = reg(ic->arg[0]);
341            int x = (rs <= 0);
342            cpu->delay_slot = TO_BE_DELAYED;
343            ic[1].f(cpu, ic+1);
344            cpu->n_translated_instrs ++;
345            if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
346                    /*  Note: Must be non-delayed when jumping to the new pc:  */
347                    cpu->delay_slot = NOT_DELAYED;
348                    if (x) {
349                            old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
350                                MIPS_INSTR_ALIGNMENT_SHIFT);
351                            cpu->pc = old_pc + (int32_t)ic->arg[2];
352                            quick_pc_to_pointers(cpu);
353                    } else
354                            cpu->cd.mips.next_ic ++;
355            } else
356                    cpu->delay_slot = NOT_DELAYED;
357    }
358    X(blez_samepage)
359    {
360            MODE_int_t rs = reg(ic->arg[0]);
361            int x = (rs <= 0);
362            cpu->delay_slot = TO_BE_DELAYED;
363            ic[1].f(cpu, ic+1);
364            cpu->n_translated_instrs ++;
365            if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
366                    if (x)
367                            cpu->cd.mips.next_ic = (struct mips_instr_call *)
368                                ic->arg[2];
369                    else
370                            cpu->cd.mips.next_ic ++;
371            }
372            cpu->delay_slot = NOT_DELAYED;
373    }
374    X(blezl)
375    {
376            MODE_int_t old_pc = cpu->pc;
377            MODE_int_t rs = reg(ic->arg[0]);
378            int x = (rs <= 0);
379            cpu->delay_slot = TO_BE_DELAYED;
380            if (x)
381                    ic[1].f(cpu, ic+1);
382            cpu->n_translated_instrs ++;
383            if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
384                    /*  Note: Must be non-delayed when jumping to the new pc:  */
385                    cpu->delay_slot = NOT_DELAYED;
386                    if (x) {
387                            old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
388                                MIPS_INSTR_ALIGNMENT_SHIFT);
389                            cpu->pc = old_pc + (int32_t)ic->arg[2];
390                            quick_pc_to_pointers(cpu);
391                    } else
392                            cpu->cd.mips.next_ic ++;
393            } else
394                    cpu->delay_slot = NOT_DELAYED;
395    }
396    X(blezl_samepage)
397    {
398            MODE_int_t rs = reg(ic->arg[0]);
399            int x = (rs <= 0);
400            cpu->delay_slot = TO_BE_DELAYED;
401            if (x)
402                    ic[1].f(cpu, ic+1);
403            cpu->n_translated_instrs ++;
404            if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
405                    if (x)
406                            cpu->cd.mips.next_ic = (struct mips_instr_call *)
407                                ic->arg[2];
408                    else
409                            cpu->cd.mips.next_ic ++;
410            }
411            cpu->delay_slot = NOT_DELAYED;
412    }
413    
414    
415    /*
416     *  bltz:   Branch if less than
417     *  bltzl:  Branch if less than likely
418     *
419     *  arg[0] = pointer to rs
420     *  arg[2] = (int32_t) relative offset from the next instruction
421     */
422    X(bltz)
423    {
424            MODE_int_t old_pc = cpu->pc;
425            MODE_int_t rs = reg(ic->arg[0]);
426            int x = (rs < 0);
427            cpu->delay_slot = TO_BE_DELAYED;
428            ic[1].f(cpu, ic+1);
429            cpu->n_translated_instrs ++;
430            if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
431                    /*  Note: Must be non-delayed when jumping to the new pc:  */
432                    cpu->delay_slot = NOT_DELAYED;
433                    if (x) {
434                            old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
435                                MIPS_INSTR_ALIGNMENT_SHIFT);
436                            cpu->pc = old_pc + (int32_t)ic->arg[2];
437                            quick_pc_to_pointers(cpu);
438                    } else
439                            cpu->cd.mips.next_ic ++;
440            } else
441                    cpu->delay_slot = NOT_DELAYED;
442    }
443    X(bltz_samepage)
444    {
445            MODE_int_t rs = reg(ic->arg[0]);
446            int x = (rs < 0);
447            cpu->delay_slot = TO_BE_DELAYED;
448            ic[1].f(cpu, ic+1);
449            cpu->n_translated_instrs ++;
450            if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
451                    if (x)
452                            cpu->cd.mips.next_ic = (struct mips_instr_call *)
453                                ic->arg[2];
454                    else
455                            cpu->cd.mips.next_ic ++;
456            }
457            cpu->delay_slot = NOT_DELAYED;
458    }
459    X(bltzl)
460    {
461            MODE_int_t old_pc = cpu->pc;
462            MODE_int_t rs = reg(ic->arg[0]);
463            int x = (rs < 0);
464            cpu->delay_slot = TO_BE_DELAYED;
465            if (x)
466                    ic[1].f(cpu, ic+1);
467            cpu->n_translated_instrs ++;
468            if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
469                    /*  Note: Must be non-delayed when jumping to the new pc:  */
470                    cpu->delay_slot = NOT_DELAYED;
471                    if (x) {
472                            old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
473                                MIPS_INSTR_ALIGNMENT_SHIFT);
474                            cpu->pc = old_pc + (int32_t)ic->arg[2];
475                            quick_pc_to_pointers(cpu);
476                    } else
477                            cpu->cd.mips.next_ic ++;
478            } else
479                    cpu->delay_slot = NOT_DELAYED;
480    }
481    X(bltzl_samepage)
482    {
483            MODE_int_t rs = reg(ic->arg[0]);
484            int x = (rs < 0);
485            cpu->delay_slot = TO_BE_DELAYED;
486            if (x)
487                    ic[1].f(cpu, ic+1);
488            cpu->n_translated_instrs ++;
489            if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
490                    if (x)
491                            cpu->cd.mips.next_ic = (struct mips_instr_call *)
492                                ic->arg[2];
493                    else
494                            cpu->cd.mips.next_ic ++;
495            }
496            cpu->delay_slot = NOT_DELAYED;
497    }
498    
499    
500    /*
501     *  bgez:   Branch if greater than or equal
502     *  bgezl:  Branch if greater than or equal likely
503     *
504     *  arg[0] = pointer to rs
505     *  arg[2] = (int32_t) relative offset from the next instruction
506     */
507    X(bgez)
508    {
509            MODE_int_t old_pc = cpu->pc;
510            MODE_int_t rs = reg(ic->arg[0]);
511            int x = (rs >= 0);
512            cpu->delay_slot = TO_BE_DELAYED;
513            ic[1].f(cpu, ic+1);
514            cpu->n_translated_instrs ++;
515            if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
516                    /*  Note: Must be non-delayed when jumping to the new pc:  */
517                    cpu->delay_slot = NOT_DELAYED;
518                    if (x) {
519                            old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
520                                MIPS_INSTR_ALIGNMENT_SHIFT);
521                            cpu->pc = old_pc + (int32_t)ic->arg[2];
522                            quick_pc_to_pointers(cpu);
523                    } else
524                            cpu->cd.mips.next_ic ++;
525            } else
526                    cpu->delay_slot = NOT_DELAYED;
527    }
528    X(bgez_samepage)
529    {
530            MODE_int_t rs = reg(ic->arg[0]);
531            int x = (rs >= 0);
532            cpu->delay_slot = TO_BE_DELAYED;
533            ic[1].f(cpu, ic+1);
534            cpu->n_translated_instrs ++;
535            if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
536                    if (x)
537                            cpu->cd.mips.next_ic = (struct mips_instr_call *)
538                                ic->arg[2];
539                    else
540                            cpu->cd.mips.next_ic ++;
541            }
542            cpu->delay_slot = NOT_DELAYED;
543    }
544    X(bgezl)
545    {
546            MODE_int_t old_pc = cpu->pc;
547            MODE_int_t rs = reg(ic->arg[0]);
548            int x = (rs >= 0);
549            cpu->delay_slot = TO_BE_DELAYED;
550            if (x)
551                    ic[1].f(cpu, ic+1);
552            cpu->n_translated_instrs ++;
553            if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
554                    /*  Note: Must be non-delayed when jumping to the new pc:  */
555                    cpu->delay_slot = NOT_DELAYED;
556                    if (x) {
557                            old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
558                                MIPS_INSTR_ALIGNMENT_SHIFT);
559                            cpu->pc = old_pc + (int32_t)ic->arg[2];
560                            quick_pc_to_pointers(cpu);
561                    } else
562                            cpu->cd.mips.next_ic ++;
563            } else
564                    cpu->delay_slot = NOT_DELAYED;
565    }
566    X(bgezl_samepage)
567    {
568            MODE_int_t rs = reg(ic->arg[0]);
569            int x = (rs >= 0);
570            cpu->delay_slot = TO_BE_DELAYED;
571            if (x)
572                    ic[1].f(cpu, ic+1);
573            cpu->n_translated_instrs ++;
574            if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
575                    if (x)
576                            cpu->cd.mips.next_ic = (struct mips_instr_call *)
577                                ic->arg[2];
578                    else
579                            cpu->cd.mips.next_ic ++;
580            }
581            cpu->delay_slot = NOT_DELAYED;
582    }
583    
584    
585    /*
586     *  bgezal:   Branch if greater than or equal (and link)
587     *  bgezall:  Branch if greater than or equal (and link) likely
588     *
589     *  arg[0] = pointer to rs
590     *  arg[2] = (int32_t) relative offset from the next instruction
591     */
592    X(bgezal)
593    {
594            MODE_int_t old_pc = cpu->pc;
595            MODE_int_t rs = reg(ic->arg[0]);
596            int x = (rs >= 0), low_pc;
597    
598            cpu->delay_slot = TO_BE_DELAYED;
599            low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
600                / sizeof(struct mips_instr_call);
601            cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
602                << MIPS_INSTR_ALIGNMENT_SHIFT);
603            cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
604            cpu->cd.mips.gpr[MIPS_GPR_RA] = cpu->pc + 8;
605    
606            ic[1].f(cpu, ic+1);
607            cpu->n_translated_instrs ++;
608            if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
609                    /*  Note: Must be non-delayed when jumping to the new pc:  */
610                    cpu->delay_slot = NOT_DELAYED;
611                    if (x) {
612                            old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
613                                MIPS_INSTR_ALIGNMENT_SHIFT);
614                            cpu->pc = old_pc + (int32_t)ic->arg[2];
615                            quick_pc_to_pointers(cpu);
616                    } else
617                            cpu->cd.mips.next_ic ++;
618            } else
619                    cpu->delay_slot = NOT_DELAYED;
620    }
621    X(bgezal_samepage)
622    {
623            MODE_int_t rs = reg(ic->arg[0]);
624            int x = (rs >= 0), low_pc;
625    
626            cpu->delay_slot = TO_BE_DELAYED;
627            low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
628                / sizeof(struct mips_instr_call);
629            cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
630                << MIPS_INSTR_ALIGNMENT_SHIFT);
631            cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
632            cpu->cd.mips.gpr[MIPS_GPR_RA] = cpu->pc + 8;
633    
634            ic[1].f(cpu, ic+1);
635            cpu->n_translated_instrs ++;
636            if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
637                    if (x)
638                            cpu->cd.mips.next_ic = (struct mips_instr_call *)
639                                ic->arg[2];
640                    else
641                            cpu->cd.mips.next_ic ++;
642            }
643            cpu->delay_slot = NOT_DELAYED;
644    }
645    X(bgezall)
646    {
647            MODE_int_t old_pc = cpu->pc;
648            MODE_int_t rs = reg(ic->arg[0]);
649            int x = (rs >= 0), low_pc;
650    
651            cpu->delay_slot = TO_BE_DELAYED;
652            low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
653                / sizeof(struct mips_instr_call);
654            cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
655                << MIPS_INSTR_ALIGNMENT_SHIFT);
656            cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
657            cpu->cd.mips.gpr[MIPS_GPR_RA] = cpu->pc + 8;
658    
659            if (x)
660                    ic[1].f(cpu, ic+1);
661            cpu->n_translated_instrs ++;
662            if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
663                    /*  Note: Must be non-delayed when jumping to the new pc:  */
664                    cpu->delay_slot = NOT_DELAYED;
665                    if (x) {
666                            old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
667                                MIPS_INSTR_ALIGNMENT_SHIFT);
668                            cpu->pc = old_pc + (int32_t)ic->arg[2];
669                            quick_pc_to_pointers(cpu);
670                    } else
671                            cpu->cd.mips.next_ic ++;
672            } else
673                    cpu->delay_slot = NOT_DELAYED;
674    }
675    X(bgezall_samepage)
676    {
677            MODE_int_t rs = reg(ic->arg[0]);
678            int x = (rs >= 0), low_pc;
679    
680            cpu->delay_slot = TO_BE_DELAYED;
681            low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
682                / sizeof(struct mips_instr_call);
683            cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
684                << MIPS_INSTR_ALIGNMENT_SHIFT);
685            cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
686            cpu->cd.mips.gpr[MIPS_GPR_RA] = cpu->pc + 8;
687    
688            if (x)
689                    ic[1].f(cpu, ic+1);
690            cpu->n_translated_instrs ++;
691            if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
692                    if (x)
693                            cpu->cd.mips.next_ic = (struct mips_instr_call *)
694                                ic->arg[2];
695                    else
696                            cpu->cd.mips.next_ic ++;
697            }
698            cpu->delay_slot = NOT_DELAYED;
699    }
700    
701    
702    /*
703     *  bltzal:   Branch if less than zero (and link)
704     *  bltzall:  Branch if less than zero (and link) likely
705     *
706     *  arg[0] = pointer to rs
707     *  arg[2] = (int32_t) relative offset from the next instruction
708     */
709    X(bltzal)
710    {
711            MODE_int_t old_pc = cpu->pc;
712            MODE_int_t rs = reg(ic->arg[0]);
713            int x = (rs < 0), low_pc;
714    
715            cpu->delay_slot = TO_BE_DELAYED;
716            low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
717                / sizeof(struct mips_instr_call);
718            cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
719                << MIPS_INSTR_ALIGNMENT_SHIFT);
720            cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
721            cpu->cd.mips.gpr[MIPS_GPR_RA] = cpu->pc + 8;
722    
723            ic[1].f(cpu, ic+1);
724            cpu->n_translated_instrs ++;
725            if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
726                    /*  Note: Must be non-delayed when jumping to the new pc:  */
727                    cpu->delay_slot = NOT_DELAYED;
728                    if (x) {
729                            old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
730                                MIPS_INSTR_ALIGNMENT_SHIFT);
731                            cpu->pc = old_pc + (int32_t)ic->arg[2];
732                            quick_pc_to_pointers(cpu);
733                    } else
734                            cpu->cd.mips.next_ic ++;
735            } else
736                    cpu->delay_slot = NOT_DELAYED;
737    }
738    X(bltzal_samepage)
739    {
740            MODE_int_t rs = reg(ic->arg[0]);
741            int x = (rs < 0), low_pc;
742    
743            cpu->delay_slot = TO_BE_DELAYED;
744            low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
745                / sizeof(struct mips_instr_call);
746            cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
747                << MIPS_INSTR_ALIGNMENT_SHIFT);
748            cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
749            cpu->cd.mips.gpr[MIPS_GPR_RA] = cpu->pc + 8;
750    
751            ic[1].f(cpu, ic+1);
752            cpu->n_translated_instrs ++;
753            if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
754                    if (x)
755                            cpu->cd.mips.next_ic = (struct mips_instr_call *)
756                                ic->arg[2];
757                    else
758                            cpu->cd.mips.next_ic ++;
759            }
760            cpu->delay_slot = NOT_DELAYED;
761    }
762    X(bltzall)
763    {
764            MODE_int_t old_pc = cpu->pc;
765            MODE_int_t rs = reg(ic->arg[0]);
766            int x = (rs < 0), low_pc;
767    
768            cpu->delay_slot = TO_BE_DELAYED;
769            low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
770                / sizeof(struct mips_instr_call);
771            cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
772                << MIPS_INSTR_ALIGNMENT_SHIFT);
773            cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
774            cpu->cd.mips.gpr[MIPS_GPR_RA] = cpu->pc + 8;
775    
776            if (x)
777                    ic[1].f(cpu, ic+1);
778            cpu->n_translated_instrs ++;
779            if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
780                    /*  Note: Must be non-delayed when jumping to the new pc:  */
781                    cpu->delay_slot = NOT_DELAYED;
782                    if (x) {
783                            old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
784                                MIPS_INSTR_ALIGNMENT_SHIFT);
785                            cpu->pc = old_pc + (int32_t)ic->arg[2];
786                            quick_pc_to_pointers(cpu);
787                    } else
788                            cpu->cd.mips.next_ic ++;
789            } else
790                    cpu->delay_slot = NOT_DELAYED;
791    }
792    X(bltzall_samepage)
793    {
794            MODE_int_t rs = reg(ic->arg[0]);
795            int x = (rs < 0), low_pc;
796    
797            cpu->delay_slot = TO_BE_DELAYED;
798            low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
799                / sizeof(struct mips_instr_call);
800            cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
801                << MIPS_INSTR_ALIGNMENT_SHIFT);
802            cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
803            cpu->cd.mips.gpr[MIPS_GPR_RA] = cpu->pc + 8;
804    
805            if (x)
806                    ic[1].f(cpu, ic+1);
807            cpu->n_translated_instrs ++;
808            if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
809                    if (x)
810                            cpu->cd.mips.next_ic = (struct mips_instr_call *)
811                                ic->arg[2];
812                    else
813                            cpu->cd.mips.next_ic ++;
814            }
815            cpu->delay_slot = NOT_DELAYED;
816    }
817    
818    
819    /*
820     *  bgtz:   Branch if greater than zero
821     *  bgtzl:  Branch if greater than zero likely
822     *
823     *  arg[0] = pointer to rs
824     *  arg[2] = (int32_t) relative offset from the next instruction
825     */
826    X(bgtz)
827    {
828            MODE_int_t old_pc = cpu->pc;
829            MODE_int_t rs = reg(ic->arg[0]);
830            int x = (rs > 0);
831            cpu->delay_slot = TO_BE_DELAYED;
832            ic[1].f(cpu, ic+1);
833            cpu->n_translated_instrs ++;
834            if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
835                    /*  Note: Must be non-delayed when jumping to the new pc:  */
836                    cpu->delay_slot = NOT_DELAYED;
837                    if (x) {
838                            old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
839                                MIPS_INSTR_ALIGNMENT_SHIFT);
840                            cpu->pc = old_pc + (int32_t)ic->arg[2];
841                            quick_pc_to_pointers(cpu);
842                    } else
843                            cpu->cd.mips.next_ic ++;
844            } else
845                    cpu->delay_slot = NOT_DELAYED;
846    }
847    X(bgtz_samepage)
848    {
849            MODE_int_t rs = reg(ic->arg[0]);
850            int x = (rs > 0);
851            cpu->delay_slot = TO_BE_DELAYED;
852            ic[1].f(cpu, ic+1);
853            cpu->n_translated_instrs ++;
854            if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
855                    if (x)
856                            cpu->cd.mips.next_ic = (struct mips_instr_call *)
857                                ic->arg[2];
858                    else
859                            cpu->cd.mips.next_ic ++;
860            }
861            cpu->delay_slot = NOT_DELAYED;
862    }
863    X(bgtzl)
864    {
865            MODE_int_t old_pc = cpu->pc;
866            MODE_int_t rs = reg(ic->arg[0]);
867            int x = (rs > 0);
868            cpu->delay_slot = TO_BE_DELAYED;
869            if (x)
870                    ic[1].f(cpu, ic+1);
871            cpu->n_translated_instrs ++;
872            if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
873                    /*  Note: Must be non-delayed when jumping to the new pc:  */
874                    cpu->delay_slot = NOT_DELAYED;
875                    if (x) {
876                            old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
877                                MIPS_INSTR_ALIGNMENT_SHIFT);
878                            cpu->pc = old_pc + (int32_t)ic->arg[2];
879                            quick_pc_to_pointers(cpu);
880                    } else
881                            cpu->cd.mips.next_ic ++;
882            } else
883                    cpu->delay_slot = NOT_DELAYED;
884    }
885    X(bgtzl_samepage)
886    {
887            MODE_int_t rs = reg(ic->arg[0]);
888            int x = (rs > 0);
889            cpu->delay_slot = TO_BE_DELAYED;
890            if (x)
891                    ic[1].f(cpu, ic+1);
892            cpu->n_translated_instrs ++;
893            if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
894                    if (x)
895                            cpu->cd.mips.next_ic = (struct mips_instr_call *)
896                                ic->arg[2];
897                    else
898                            cpu->cd.mips.next_ic ++;
899            }
900            cpu->delay_slot = NOT_DELAYED;
901  }  }
902    
903    
# Line 168  X(b_samepage) Line 910  X(b_samepage)
910   */   */
911  X(jr)  X(jr)
912  {  {
913          MODE_uint_t rs = reg(ic->arg[0]);          MODE_int_t rs = reg(ic->arg[0]);
914          cpu->cd.mips.delay_slot = TO_BE_DELAYED;          cpu->delay_slot = TO_BE_DELAYED;
915          ic[1].f(cpu, ic+1);          ic[1].f(cpu, ic+1);
916          cpu->n_translated_instrs ++;          cpu->n_translated_instrs ++;
917          if (!(cpu->cd.mips.delay_slot & EXCEPTION_IN_DELAY_SLOT)) {          if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
918                  cpu->pc = rs;                  cpu->pc = rs;
919                    /*  Note: Must be non-delayed when jumping to the new pc:  */
920                    cpu->delay_slot = NOT_DELAYED;
921                  quick_pc_to_pointers(cpu);                  quick_pc_to_pointers(cpu);
922          }          } else
923          cpu->cd.mips.delay_slot = NOT_DELAYED;                  cpu->delay_slot = NOT_DELAYED;
924  }  }
925  X(jr_ra)  X(jr_ra)
926  {  {
927          MODE_uint_t rs = cpu->cd.mips.gpr[MIPS_GPR_RA];          MODE_int_t rs = cpu->cd.mips.gpr[MIPS_GPR_RA];
928          cpu->cd.mips.delay_slot = TO_BE_DELAYED;          cpu->delay_slot = TO_BE_DELAYED;
929          ic[1].f(cpu, ic+1);          ic[1].f(cpu, ic+1);
930          cpu->n_translated_instrs ++;          cpu->n_translated_instrs ++;
931          if (!(cpu->cd.mips.delay_slot & EXCEPTION_IN_DELAY_SLOT)) {          if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
932                  cpu->pc = rs;                  cpu->pc = rs;
933                    /*  Note: Must be non-delayed when jumping to the new pc:  */
934                    cpu->delay_slot = NOT_DELAYED;
935                  quick_pc_to_pointers(cpu);                  quick_pc_to_pointers(cpu);
936          }          } else
937          cpu->cd.mips.delay_slot = NOT_DELAYED;                  cpu->delay_slot = NOT_DELAYED;
938    }
939    X(jr_ra_addiu)
940    {
941            /*  jr ra, followed by an addiu  */
942            MODE_int_t rs = cpu->cd.mips.gpr[MIPS_GPR_RA];
943            reg(ic[1].arg[1]) = (int32_t)
944                ((int32_t)reg(ic[1].arg[0]) + (int32_t)ic[1].arg[2]);
945            cpu->pc = rs;
946            quick_pc_to_pointers(cpu);
947            cpu->n_translated_instrs ++;
948  }  }
949  X(jr_ra_trace)  X(jr_ra_trace)
950  {  {
951          MODE_uint_t rs = cpu->cd.mips.gpr[MIPS_GPR_RA];          MODE_int_t rs = cpu->cd.mips.gpr[MIPS_GPR_RA];
952          cpu->cd.mips.delay_slot = TO_BE_DELAYED;          cpu->delay_slot = TO_BE_DELAYED;
953          ic[1].f(cpu, ic+1);          ic[1].f(cpu, ic+1);
954          cpu->n_translated_instrs ++;          cpu->n_translated_instrs ++;
955          if (!(cpu->cd.mips.delay_slot & EXCEPTION_IN_DELAY_SLOT)) {          if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
956                  cpu->pc = rs;                  cpu->pc = rs;
957                  cpu_functioncall_trace_return(cpu);                  cpu_functioncall_trace_return(cpu);
958                    /*  Note: Must be non-delayed when jumping to the new pc:  */
959                    cpu->delay_slot = NOT_DELAYED;
960                  quick_pc_to_pointers(cpu);                  quick_pc_to_pointers(cpu);
961          }          } else
962          cpu->cd.mips.delay_slot = NOT_DELAYED;                  cpu->delay_slot = NOT_DELAYED;
963  }  }
964  X(jalr)  X(jalr)
965  {  {
966          MODE_uint_t rs = reg(ic->arg[0]), rd;          MODE_int_t rs = reg(ic->arg[0]), rd;
967          cpu->cd.mips.delay_slot = TO_BE_DELAYED;          cpu->delay_slot = TO_BE_DELAYED;
968          rd = cpu->pc & ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<          rd = cpu->pc & ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
969              MIPS_INSTR_ALIGNMENT_SHIFT);              MIPS_INSTR_ALIGNMENT_SHIFT);
970          rd += (int32_t)ic->arg[2];          rd += (int32_t)ic->arg[2];
971          reg(ic->arg[1]) = rd;          reg(ic->arg[1]) = rd;
972          ic[1].f(cpu, ic+1);          ic[1].f(cpu, ic+1);
973          cpu->n_translated_instrs ++;          cpu->n_translated_instrs ++;
974          if (!(cpu->cd.mips.delay_slot & EXCEPTION_IN_DELAY_SLOT)) {          if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
975                  cpu->pc = rs;                  cpu->pc = rs;
976                    /*  Note: Must be non-delayed when jumping to the new pc:  */
977                    cpu->delay_slot = NOT_DELAYED;
978                  quick_pc_to_pointers(cpu);                  quick_pc_to_pointers(cpu);
979          }          } else
980          cpu->cd.mips.delay_slot = NOT_DELAYED;                  cpu->delay_slot = NOT_DELAYED;
981  }  }
982  X(jalr_trace)  X(jalr_trace)
983  {  {
984          MODE_uint_t rs = reg(ic->arg[0]), rd;          MODE_int_t rs = reg(ic->arg[0]), rd;
985          cpu->cd.mips.delay_slot = TO_BE_DELAYED;          cpu->delay_slot = TO_BE_DELAYED;
986          rd = cpu->pc & ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<          rd = cpu->pc & ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
987              MIPS_INSTR_ALIGNMENT_SHIFT);              MIPS_INSTR_ALIGNMENT_SHIFT);
988          rd += (int32_t)ic->arg[2];          rd += (int32_t)ic->arg[2];
989          reg(ic->arg[1]) = rd;          reg(ic->arg[1]) = rd;
990          ic[1].f(cpu, ic+1);          ic[1].f(cpu, ic+1);
991          cpu->n_translated_instrs ++;          cpu->n_translated_instrs ++;
992          if (!(cpu->cd.mips.delay_slot & EXCEPTION_IN_DELAY_SLOT)) {          if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
993                  cpu->pc = rs;                  cpu->pc = rs;
994                  cpu_functioncall_trace(cpu, cpu->pc);                  cpu_functioncall_trace(cpu, cpu->pc);
995                    /*  Note: Must be non-delayed when jumping to the new pc:  */
996                    cpu->delay_slot = NOT_DELAYED;
997                  quick_pc_to_pointers(cpu);                  quick_pc_to_pointers(cpu);
998          }          } else
999          cpu->cd.mips.delay_slot = NOT_DELAYED;                  cpu->delay_slot = NOT_DELAYED;
1000    }
1001    
1002    
1003    /*
1004     *  j, jal:  Jump [and link].
1005     *
1006     *  arg[0] = lowest 28 bits of new pc.
1007     *  arg[1] = offset from start of page to the jal instruction + 8
1008     */
1009    X(j)
1010    {
1011            MODE_int_t old_pc = cpu->pc;
1012            cpu->delay_slot = TO_BE_DELAYED;
1013            ic[1].f(cpu, ic+1);
1014            cpu->n_translated_instrs ++;
1015            if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
1016                    /*  Note: Must be non-delayed when jumping to the new pc:  */
1017                    cpu->delay_slot = NOT_DELAYED;
1018                    old_pc &= ~0x03ffffff;
1019                    cpu->pc = old_pc | (uint32_t)ic->arg[0];
1020                    quick_pc_to_pointers(cpu);
1021            } else
1022                    cpu->delay_slot = NOT_DELAYED;
1023    }
1024    X(jal)
1025    {
1026            MODE_int_t old_pc = cpu->pc;
1027            cpu->delay_slot = TO_BE_DELAYED;
1028            cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
1029            cpu->cd.mips.gpr[31] = (MODE_int_t)cpu->pc + (int32_t)ic->arg[1];
1030            ic[1].f(cpu, ic+1);
1031            cpu->n_translated_instrs ++;
1032            if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
1033                    /*  Note: Must be non-delayed when jumping to the new pc:  */
1034                    cpu->delay_slot = NOT_DELAYED;
1035                    old_pc &= ~0x03ffffff;
1036                    cpu->pc = old_pc | (int32_t)ic->arg[0];
1037                    quick_pc_to_pointers(cpu);
1038            } else
1039                    cpu->delay_slot = NOT_DELAYED;
1040    }
1041    X(jal_trace)
1042    {
1043            MODE_int_t old_pc = cpu->pc;
1044            cpu->delay_slot = TO_BE_DELAYED;
1045            cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
1046            cpu->cd.mips.gpr[31] = (MODE_int_t)cpu->pc + (int32_t)ic->arg[1];
1047            ic[1].f(cpu, ic+1);
1048            cpu->n_translated_instrs ++;
1049            if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
1050                    /*  Note: Must be non-delayed when jumping to the new pc:  */
1051                    cpu->delay_slot = NOT_DELAYED;
1052                    old_pc &= ~0x03ffffff;
1053                    cpu->pc = old_pc | (int32_t)ic->arg[0];
1054                    cpu_functioncall_trace(cpu, cpu->pc);
1055                    quick_pc_to_pointers(cpu);
1056            } else
1057                    cpu->delay_slot = NOT_DELAYED;
1058    }
1059    
1060    
1061    /*
1062     *  cache:  Cache operation.
1063     */
1064    X(cache)
1065    {
1066            /*  TODO: Implement cache operations.  */
1067    
1068            /*  Make sure the rmw bit is cleared:  */
1069            cpu->cd.mips.rmw = 0;
1070  }  }
1071    
1072    
# Line 245  X(jalr_trace) Line 1077  X(jalr_trace)
1077   *  arg[1] = pointer to rt   *  arg[1] = pointer to rt
1078   *  arg[2] = uint32_t immediate value   *  arg[2] = uint32_t immediate value
1079   */   */
1080  X(andi) { reg(ic->arg[1]) = reg(ic->arg[0]) & (int32_t)ic->arg[2]; }  X(andi) { reg(ic->arg[1]) = reg(ic->arg[0]) & (uint32_t)ic->arg[2]; }
1081  X(ori)  { reg(ic->arg[1]) = reg(ic->arg[0]) | (int32_t)ic->arg[2]; }  X(ori)  { reg(ic->arg[1]) = reg(ic->arg[0]) | (uint32_t)ic->arg[2]; }
1082  X(xori) { reg(ic->arg[1]) = reg(ic->arg[0]) ^ (int32_t)ic->arg[2]; }  X(xori) { reg(ic->arg[1]) = reg(ic->arg[0]) ^ (uint32_t)ic->arg[2]; }
1083    
1084    
1085  /*  /*
1086   *  2-register:   *  2-register:
1087     *
1088     *  arg[0] = ptr to rs
1089     *  arg[1] = ptr to rt
1090   */   */
1091    X(div)
1092    {
1093            int32_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1094            int32_t res, rem;
1095            if (b == 0)
1096                    res = 0, rem = a;
1097            else
1098                    res = a / b, rem = a - b*res;
1099            reg(&cpu->cd.mips.lo) = (int32_t)res;
1100            reg(&cpu->cd.mips.hi) = (int32_t)rem;
1101    }
1102    X(divu)
1103    {
1104            uint32_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1105            uint32_t res, rem;
1106            if (b == 0)
1107                    res = 0, rem = a;
1108            else
1109                    res = a / b, rem = a - b*res;
1110            reg(&cpu->cd.mips.lo) = (int32_t)res;
1111            reg(&cpu->cd.mips.hi) = (int32_t)rem;
1112    }
1113    X(ddiv)
1114    {
1115            int64_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1116            int64_t res, rem;
1117            if (b == 0)
1118                    res = 0;
1119            else
1120                    res = a / b;
1121            rem = a - b*res;
1122            reg(&cpu->cd.mips.lo) = res;
1123            reg(&cpu->cd.mips.hi) = rem;
1124    }
1125    X(ddivu)
1126    {
1127            uint64_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1128            uint64_t res, rem;
1129            if (b == 0)
1130                    res = 0;
1131            else
1132                    res = a / b;
1133            rem = a - b*res;
1134            reg(&cpu->cd.mips.lo) = res;
1135            reg(&cpu->cd.mips.hi) = rem;
1136    }
1137  X(mult)  X(mult)
1138  {  {
1139          int32_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);          int32_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
# Line 260  X(mult) Line 1141  X(mult)
1141          reg(&cpu->cd.mips.lo) = (int32_t)res;          reg(&cpu->cd.mips.lo) = (int32_t)res;
1142          reg(&cpu->cd.mips.hi) = (int32_t)(res >> 32);          reg(&cpu->cd.mips.hi) = (int32_t)(res >> 32);
1143  }  }
1144    X(mult_r5900)
1145    {
1146            /*  C790/TX79/R5900 multiplication, stores result in
1147                hi, lo, and a third register  */
1148            int32_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1149            int64_t res = (int64_t)a * (int64_t)b;
1150            reg(&cpu->cd.mips.lo) = (int32_t)res;
1151            reg(&cpu->cd.mips.hi) = (int32_t)(res >> 32);
1152            reg(ic->arg[2]) = (int32_t)res;
1153    }
1154  X(multu)  X(multu)
1155  {  {
1156          uint32_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);          uint32_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
# Line 267  X(multu) Line 1158  X(multu)
1158          reg(&cpu->cd.mips.lo) = (int32_t)res;          reg(&cpu->cd.mips.lo) = (int32_t)res;
1159          reg(&cpu->cd.mips.hi) = (int32_t)(res >> 32);          reg(&cpu->cd.mips.hi) = (int32_t)(res >> 32);
1160  }  }
1161    X(multu_r5900)
1162    {
1163            /*  C790/TX79/R5900 multiplication, stores result in
1164                hi, lo, and a third register  */
1165            uint32_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1166            uint64_t res = (uint64_t)a * (uint64_t)b;
1167            reg(&cpu->cd.mips.lo) = (int32_t)res;
1168            reg(&cpu->cd.mips.hi) = (int32_t)(res >> 32);
1169            reg(ic->arg[2]) = (int32_t)res;
1170    }
1171    X(dmult)
1172    {
1173            uint64_t a = reg(ic->arg[0]), b = reg(ic->arg[1]), c = 0;
1174            uint64_t hi = 0, lo = 0;
1175            int neg = 0;
1176            if (a >> 63)
1177                    neg = !neg, a = -a;
1178            if (b >> 63)
1179                    neg = !neg, b = -b;
1180            for (; a; a >>= 1) {
1181                    if (a & 1) {
1182                            uint64_t old_lo = lo;
1183                            hi += c;
1184                            lo += b;
1185                            if (lo < old_lo)
1186                                    hi ++;
1187                    }
1188                    c = (c << 1) | (b >> 63); b <<= 1;
1189            }
1190            if (neg) {
1191                    if (lo == 0)
1192                            hi --;
1193                    lo --;
1194                    hi ^= (int64_t) -1;
1195                    lo ^= (int64_t) -1;
1196            }
1197            reg(&cpu->cd.mips.lo) = lo;
1198            reg(&cpu->cd.mips.hi) = hi;
1199    }
1200    X(dmultu)
1201    {
1202            uint64_t a = reg(ic->arg[0]), b = reg(ic->arg[1]), c = 0;
1203            uint64_t hi = 0, lo = 0;
1204            for (; a; a >>= 1) {
1205                    if (a & 1) {
1206                            uint64_t old_lo = lo;
1207                            hi += c;
1208                            lo += b;
1209                            if (lo < old_lo)
1210                                    hi ++;
1211                    }
1212                    c = (c << 1) | (b >> 63); b <<= 1;
1213            }
1214            reg(&cpu->cd.mips.lo) = lo;
1215            reg(&cpu->cd.mips.hi) = hi;
1216    }
1217    X(tge)
1218    {
1219            MODE_int_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1220            if (a >= b) {
1221                    /*  Synch. PC and cause an exception:  */
1222                    int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1223                        / sizeof(struct mips_instr_call);
1224                    cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
1225                        << MIPS_INSTR_ALIGNMENT_SHIFT);
1226                    cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1227                    mips_cpu_exception(cpu, EXCEPTION_TR, 0, 0, 0, 0, 0, 0);
1228            }
1229    }
1230    X(tgeu)
1231    {
1232            MODE_uint_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1233            if (a >= b) {
1234                    /*  Synch. PC and cause an exception:  */
1235                    int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1236                        / sizeof(struct mips_instr_call);
1237                    cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
1238                        << MIPS_INSTR_ALIGNMENT_SHIFT);
1239                    cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1240                    mips_cpu_exception(cpu, EXCEPTION_TR, 0, 0, 0, 0, 0, 0);
1241            }
1242    }
1243    X(tlt)
1244    {
1245            MODE_int_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1246            if (a < b) {
1247                    /*  Synch. PC and cause an exception:  */
1248                    int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1249                        / sizeof(struct mips_instr_call);
1250                    cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
1251                        << MIPS_INSTR_ALIGNMENT_SHIFT);
1252                    cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1253                    mips_cpu_exception(cpu, EXCEPTION_TR, 0, 0, 0, 0, 0, 0);
1254            }
1255    }
1256    X(tltu)
1257    {
1258            MODE_uint_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1259            if (a < b) {
1260                    /*  Synch. PC and cause an exception:  */
1261                    int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1262                        / sizeof(struct mips_instr_call);
1263                    cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
1264                        << MIPS_INSTR_ALIGNMENT_SHIFT);
1265                    cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1266                    mips_cpu_exception(cpu, EXCEPTION_TR, 0, 0, 0, 0, 0, 0);
1267            }
1268    }
1269    X(teq)
1270    {
1271            MODE_uint_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1272            if (a == b) {
1273                    /*  Synch. PC and cause an exception:  */
1274                    int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1275                        / sizeof(struct mips_instr_call);
1276                    cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
1277                        << MIPS_INSTR_ALIGNMENT_SHIFT);
1278                    cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1279                    mips_cpu_exception(cpu, EXCEPTION_TR, 0, 0, 0, 0, 0, 0);
1280            }
1281    }
1282    X(tne)
1283    {
1284            MODE_uint_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1285            if (a != b) {
1286                    /*  Synch. PC and cause an exception:  */
1287                    int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1288                        / sizeof(struct mips_instr_call);
1289                    cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
1290                        << MIPS_INSTR_ALIGNMENT_SHIFT);
1291                    cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1292                    mips_cpu_exception(cpu, EXCEPTION_TR, 0, 0, 0, 0, 0, 0);
1293            }
1294    }
1295    
1296    
1297  /*  /*
1298   *  3-register:   *  3-register arithmetic instructions:
1299     *
1300     *  arg[0] = ptr to rs
1301     *  arg[1] = ptr to rt
1302     *  arg[2] = ptr to rd
1303   */   */
1304  X(addu) { reg(ic->arg[2]) = (int32_t)(reg(ic->arg[0]) + reg(ic->arg[1])); }  X(addu) { reg(ic->arg[2]) = (int32_t)(reg(ic->arg[0]) + reg(ic->arg[1])); }
1305  X(subu) { reg(ic->arg[2]) = (int32_t)(reg(ic->arg[0]) - reg(ic->arg[1])); }  X(add)
1306    {
1307            int32_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]);
1308            int32_t rd = rs + rt;
1309    
1310            if ((rs >= 0 && rt >= 0 && rd < 0) || (rs < 0 && rt < 0 && rd >= 0)) {
1311                    /*  Synch. PC and cause an exception:  */
1312                    int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1313                        / sizeof(struct mips_instr_call);
1314                    cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
1315                        << MIPS_INSTR_ALIGNMENT_SHIFT);
1316                    cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1317                    mips_cpu_exception(cpu, EXCEPTION_OV, 0, 0, 0, 0, 0, 0);
1318            } else
1319                    reg(ic->arg[2]) = rd;
1320    }
1321  X(daddu){ reg(ic->arg[2]) = reg(ic->arg[0]) + reg(ic->arg[1]); }  X(daddu){ reg(ic->arg[2]) = reg(ic->arg[0]) + reg(ic->arg[1]); }
1322  X(dsubu){ reg(ic->arg[2]) = reg(ic->arg[0]) + reg(ic->arg[1]); }  X(dadd)
1323    {
1324            int64_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]);
1325            int64_t rd = rs + rt;
1326    
1327            if ((rs >= 0 && rt >= 0 && rd < 0) || (rs < 0 && rt < 0 && rd >= 0)) {
1328                    /*  Synch. PC and cause an exception:  */
1329                    int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1330                        / sizeof(struct mips_instr_call);
1331                    cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
1332                        << MIPS_INSTR_ALIGNMENT_SHIFT);
1333                    cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1334                    mips_cpu_exception(cpu, EXCEPTION_OV, 0, 0, 0, 0, 0, 0);
1335            } else
1336                    reg(ic->arg[2]) = rd;
1337    }
1338    X(subu) { reg(ic->arg[2]) = (int32_t)(reg(ic->arg[0]) - reg(ic->arg[1])); }
1339    X(sub)
1340    {
1341            /*  NOTE: Negating rt and using addition. TODO: Is this correct?  */
1342            int32_t rs = reg(ic->arg[0]), rt = - reg(ic->arg[1]);
1343            int32_t rd = rs + rt;
1344    
1345            if ((rs >= 0 && rt >= 0 && rd < 0) || (rs < 0 && rt < 0 && rd >= 0)) {
1346                    /*  Synch. PC and cause an exception:  */
1347                    int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1348                        / sizeof(struct mips_instr_call);
1349                    cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
1350                        << MIPS_INSTR_ALIGNMENT_SHIFT);
1351                    cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1352                    mips_cpu_exception(cpu, EXCEPTION_OV, 0, 0, 0, 0, 0, 0);
1353            } else
1354                    reg(ic->arg[2]) = rd;
1355    }
1356    X(dsubu){ reg(ic->arg[2]) = reg(ic->arg[0]) - reg(ic->arg[1]); }
1357    X(dsub)
1358    {
1359            /*  NOTE: Negating rt and using addition. TODO: Is this correct?  */
1360            int64_t rs = reg(ic->arg[0]), rt = - reg(ic->arg[1]);
1361            int64_t rd = rs + rt;
1362    
1363            if ((rs >= 0 && rt >= 0 && rd < 0) || (rs < 0 && rt < 0 && rd >= 0)) {
1364                    /*  Synch. PC and cause an exception:  */
1365                    int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1366                        / sizeof(struct mips_instr_call);
1367                    cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
1368                        << MIPS_INSTR_ALIGNMENT_SHIFT);
1369                    cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1370                    mips_cpu_exception(cpu, EXCEPTION_OV, 0, 0, 0, 0, 0, 0);
1371            } else
1372                    reg(ic->arg[2]) = rd;
1373    }
1374  X(slt) {  X(slt) {
1375  #ifdef MODE32          reg(ic->arg[2]) =
1376          reg(ic->arg[2]) = (int32_t)reg(ic->arg[0]) < (int32_t)reg(ic->arg[1]);              (MODE_int_t)reg(ic->arg[0]) < (MODE_int_t)reg(ic->arg[1]);
 #else  
         reg(ic->arg[2]) = (int64_t)reg(ic->arg[0]) < (int64_t)reg(ic->arg[1]);  
 #endif  
1377  }  }
1378  X(sltu) {  X(sltu) {
1379  #ifdef MODE32          reg(ic->arg[2]) =
1380          reg(ic->arg[2]) = (uint32_t)reg(ic->arg[0]) < (uint32_t)reg(ic->arg[1]);              (MODE_uint_t)reg(ic->arg[0]) < (MODE_uint_t)reg(ic->arg[1]);
 #else  
         reg(ic->arg[2]) = (uint64_t)reg(ic->arg[0]) < (uint64_t)reg(ic->arg[1]);  
 #endif  
1381  }  }
1382  X(or) { reg(ic->arg[2]) = reg(ic->arg[0]) | reg(ic->arg[1]); }  X(and) { reg(ic->arg[2]) = reg(ic->arg[0]) & reg(ic->arg[1]); }
1383    X(or)  { reg(ic->arg[2]) = reg(ic->arg[0]) | reg(ic->arg[1]); }
1384  X(xor) { reg(ic->arg[2]) = reg(ic->arg[0]) ^ reg(ic->arg[1]); }  X(xor) { reg(ic->arg[2]) = reg(ic->arg[0]) ^ reg(ic->arg[1]); }
1385  X(nor) { reg(ic->arg[2]) = ~(reg(ic->arg[0]) | reg(ic->arg[1])); }  X(nor) { reg(ic->arg[2]) = ~(reg(ic->arg[0]) | reg(ic->arg[1])); }
1386  X(sll) { reg(ic->arg[2]) = (int32_t)(reg(ic->arg[0]) << ic->arg[1]); }  X(sll) { reg(ic->arg[2]) = (int32_t)(reg(ic->arg[0]) << (int32_t)ic->arg[1]); }
1387    X(sllv){ int32_t sa = reg(ic->arg[1]) & 31;
1388             reg(ic->arg[2]) = (int32_t)(reg(ic->arg[0]) << sa); }
1389  X(srl) { reg(ic->arg[2]) = (int32_t)((uint32_t)reg(ic->arg[0]) >> ic->arg[1]); }  X(srl) { reg(ic->arg[2]) = (int32_t)((uint32_t)reg(ic->arg[0]) >> ic->arg[1]); }
1390    X(srlv){ int32_t sa = reg(ic->arg[1]) & 31;
1391             reg(ic->arg[2]) = (int32_t)((uint32_t)reg(ic->arg[0]) >> sa); }
1392  X(sra) { reg(ic->arg[2]) = (int32_t)((int32_t)reg(ic->arg[0]) >> ic->arg[1]); }  X(sra) { reg(ic->arg[2]) = (int32_t)((int32_t)reg(ic->arg[0]) >> ic->arg[1]); }
1393    X(srav){ int32_t sa = reg(ic->arg[1]) & 31;
1394             reg(ic->arg[2]) = (int32_t)((int32_t)reg(ic->arg[0]) >> sa); }
1395    X(dsll) { reg(ic->arg[2]) = (int64_t)reg(ic->arg[0]) << (int64_t)ic->arg[1]; }
1396    X(dsllv){ int64_t sa = reg(ic->arg[1]) & 63;
1397             reg(ic->arg[2]) = reg(ic->arg[0]) << sa; }
1398    X(dsrl) { reg(ic->arg[2]) = (int64_t)((uint64_t)reg(ic->arg[0]) >>
1399            (uint64_t) ic->arg[1]);}
1400    X(dsrlv){ int64_t sa = reg(ic->arg[1]) & 63;
1401             reg(ic->arg[2]) = (uint64_t)reg(ic->arg[0]) >> sa; }
1402    X(dsra) { reg(ic->arg[2]) = (int64_t)reg(ic->arg[0]) >> (int64_t)ic->arg[1]; }
1403    X(dsrav){ int64_t sa = reg(ic->arg[1]) & 63;
1404             reg(ic->arg[2]) = (int64_t)reg(ic->arg[0]) >> sa; }
1405  X(mul) { reg(ic->arg[2]) = (int32_t)  X(mul) { reg(ic->arg[2]) = (int32_t)
1406          ( (int32_t)reg(ic->arg[0]) * (int32_t)reg(ic->arg[1]) ); }          ( (int32_t)reg(ic->arg[0]) * (int32_t)reg(ic->arg[1]) ); }
1407    X(movn) { if (reg(ic->arg[1])) reg(ic->arg[2]) = reg(ic->arg[0]); }
1408    X(movz) { if (!reg(ic->arg[1])) reg(ic->arg[2]) = reg(ic->arg[0]); }
1409    
1410    
1411    /*
1412     *  p*:  128-bit C790/TX79/R5900 stuff
1413     *
1414     *  arg[0] = rs (note: not a pointer)
1415     *  arg[1] = rt (note: not a pointer)
1416     *  arg[2] = rd (note: not a pointer)
1417     */
1418    X(por)
1419    {
1420            cpu->cd.mips.gpr[ic->arg[2]] = cpu->cd.mips.gpr[ic->arg[0]] |
1421                cpu->cd.mips.gpr[ic->arg[1]];
1422            cpu->cd.mips.gpr_quadhi[ic->arg[2]] =
1423                cpu->cd.mips.gpr_quadhi[ic->arg[0]] |
1424                cpu->cd.mips.gpr_quadhi[ic->arg[1]];
1425    }
1426    X(pextlw)
1427    {
1428            uint64_t lo, hi;
1429    
1430            lo = (uint32_t)cpu->cd.mips.gpr[ic->arg[1]] |
1431                (uint64_t)((uint64_t)cpu->cd.mips.gpr[ic->arg[0]] << 32);
1432            hi = (cpu->cd.mips.gpr[ic->arg[0]] & 0xffffffff00000000ULL) |
1433                (uint32_t)((uint64_t)cpu->cd.mips.gpr[ic->arg[1]] >> 32);
1434    
1435            cpu->cd.mips.gpr[ic->arg[2]] = lo;
1436            cpu->cd.mips.gpr_quadhi[ic->arg[2]] = hi;
1437    }
1438    
1439    
1440    /*
1441     *  madd, maddu, msub, msubu: Multiply-and-add/subtract
1442     *
1443     *  arg[0] = ptr to rs
1444     *  arg[1] = ptr to rt
1445     *  arg[2] = ptr to rd (only used on R5900/TX79)
1446     */
1447    X(madd)
1448    {
1449            int64_t rs = (int32_t)reg(ic->arg[0]), rt = (int32_t)reg(ic->arg[1]);
1450            int64_t sum = rs * rt,
1451                hilo = (cpu->cd.mips.hi << 32) | (uint32_t)(cpu->cd.mips.lo);
1452            hilo += sum;
1453            cpu->cd.mips.hi = (int32_t)(hilo>>32); cpu->cd.mips.lo = (int32_t)hilo;
1454    }
1455    X(madd_rd)
1456    {
1457            int64_t rs = (int32_t)reg(ic->arg[0]), rt = (int32_t)reg(ic->arg[1]);
1458            int64_t sum = rs * rt,
1459                hilo = (cpu->cd.mips.hi << 32) | (uint32_t)(cpu->cd.mips.lo);
1460            hilo += sum;
1461            cpu->cd.mips.hi = (int32_t)(hilo>>32); cpu->cd.mips.lo = (int32_t)hilo;
1462            reg(ic->arg[2]) = (int32_t)hilo;
1463    }
1464    X(msub)
1465    {
1466            int64_t rs = (int32_t)reg(ic->arg[0]), rt = (int32_t)reg(ic->arg[1]);
1467            int64_t sum = rs * rt,
1468                hilo = (cpu->cd.mips.hi << 32) | (uint32_t)(cpu->cd.mips.lo);
1469            hilo -= sum;
1470            cpu->cd.mips.hi = (int32_t)(hilo>>32); cpu->cd.mips.lo = (int32_t)hilo;
1471    }
1472    X(maddu)
1473    {
1474            int64_t rs = (uint32_t)reg(ic->arg[0]), rt = (uint32_t)reg(ic->arg[1]);
1475            int64_t sum = rs * rt,
1476                hilo = (cpu->cd.mips.hi << 32) | (uint32_t)(cpu->cd.mips.lo);
1477            hilo += sum;
1478            cpu->cd.mips.hi = (int32_t)(hilo>>32); cpu->cd.mips.lo = (int32_t)hilo;
1479    }
1480    X(maddu_rd)
1481    {
1482            int64_t rs = (uint32_t)reg(ic->arg[0]), rt = (uint32_t)reg(ic->arg[1]);
1483            int64_t sum = rs * rt,
1484                hilo = (cpu->cd.mips.hi << 32) | (uint32_t)(cpu->cd.mips.lo);
1485            hilo += sum;
1486            cpu->cd.mips.hi = (int32_t)(hilo>>32); cpu->cd.mips.lo = (int32_t)hilo;
1487            reg(ic->arg[2]) = (int32_t)hilo;
1488    }
1489    X(msubu)
1490    {
1491            int64_t rs = (uint32_t)reg(ic->arg[0]), rt = (uint32_t)reg(ic->arg[1]);
1492            int64_t sum = rs * rt,
1493                hilo = (cpu->cd.mips.hi << 32) | (uint32_t)(cpu->cd.mips.lo);
1494            hilo -= sum;
1495            cpu->cd.mips.hi = (int32_t)(hilo>>32); cpu->cd.mips.lo = (int32_t)hilo;
1496    }
1497    
1498    
1499  /*  /*
# Line 362  X(dclo) Line 1558  X(dclo)
1558    
1559    
1560  /*  /*
1561   *  addiu:  Add immediate (32-bit).   *  addi, daddi: Add immediate, overflow detection.
1562     *  addiu, daddiu: Add immediate.
1563     *  slti:   Set if less than immediate (signed 32-bit)
1564     *  sltiu:  Set if less than immediate (signed 32-bit, but unsigned compare)
1565   *   *
1566   *  arg[0] = pointer to rs   *  arg[0] = pointer to rs
1567   *  arg[1] = pointer to rt   *  arg[1] = pointer to rt
1568   *  arg[2] = (int32_t) immediate value   *  arg[2] = (int32_t) immediate value
1569   */   */
1570    X(addi)
1571    {
1572            int32_t rs = reg(ic->arg[0]), imm = (int32_t)ic->arg[2];
1573            int32_t rt = rs + imm;
1574    
1575            if ((rs >= 0 && imm >= 0 && rt < 0) || (rs < 0 && imm < 0 && rt >= 0)) {
1576                    /*  Synch. PC and cause an exception:  */
1577                    int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1578                        / sizeof(struct mips_instr_call);
1579                    cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
1580                        << MIPS_INSTR_ALIGNMENT_SHIFT);
1581                    cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1582                    mips_cpu_exception(cpu, EXCEPTION_OV, 0, 0, 0, 0, 0, 0);
1583            } else
1584                    reg(ic->arg[1]) = rt;
1585    }
1586  X(addiu)  X(addiu)
1587  {  {
1588          reg(ic->arg[1]) = (int32_t)          reg(ic->arg[1]) = (int32_t)
1589              ((int32_t)reg(ic->arg[0]) + (int32_t)ic->arg[2]);              ((int32_t)reg(ic->arg[0]) + (int32_t)ic->arg[2]);
1590  }  }
1591    X(daddi)
1592    {
1593            int64_t rs = reg(ic->arg[0]), imm = (int32_t)ic->arg[2];
1594            int64_t rt = rs + imm;
1595    
1596            if ((rs >= 0 && imm >= 0 && rt < 0) || (rs < 0 && imm < 0 && rt >= 0)) {
1597  /*                  /*  Synch. PC and cause an exception:  */
1598   *  daddiu:  Add immediate (64-bit).                  int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1599   *                      / sizeof(struct mips_instr_call);
1600   *  arg[0] = pointer to rs                  cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
1601   *  arg[1] = pointer to rt                      << MIPS_INSTR_ALIGNMENT_SHIFT);
1602   *  arg[2] = (int32_t) immediate value                  cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1603   */                  mips_cpu_exception(cpu, EXCEPTION_OV, 0, 0, 0, 0, 0, 0);
1604            } else
1605                    reg(ic->arg[1]) = rt;
1606    }
1607  X(daddiu)  X(daddiu)
1608  {  {
1609          reg(ic->arg[1]) = reg(ic->arg[0]) + (int32_t)ic->arg[2];          reg(ic->arg[1]) = reg(ic->arg[0]) + (int32_t)ic->arg[2];
1610  }  }
1611    X(slti)
1612    {
1613            reg(ic->arg[1]) = (MODE_int_t)reg(ic->arg[0]) < (int32_t)ic->arg[2];
1614    }
1615    X(sltiu)
1616    {
1617            reg(ic->arg[1]) = (MODE_uint_t)reg(ic->arg[0]) <
1618               ((MODE_uint_t)(int32_t)ic->arg[2]);
1619    }
1620    
1621    
1622  /*  /*
# Line 401  X(set) Line 1632  X(set)
1632    
1633    
1634  /*  /*
1635     *  cfc0:         Copy from Coprocessor 0.
1636   *  mfc0, dmfc0:  Move from Coprocessor 0.   *  mfc0, dmfc0:  Move from Coprocessor 0.
1637   *  mtc0, dmtc0:  Move to Coprocessor 0.   *  mtc0, dmtc0:  Move to Coprocessor 0.
  *  cfc1: Copy control word from Coprocessor 1.  
1638   *   *
1639   *  arg[0] = pointer to GPR (rt)   *  arg[0] = pointer to GPR (rt)
1640   *  arg[1] = coprocessor 0 register number | (select << 5)   *  arg[1] = coprocessor 0 register number | (select << 5)   (or for the
1641     *           cfc0 instruction, the coprocessor control register number)
1642   *  arg[2] = relative addr of this instruction within the page   *  arg[2] = relative addr of this instruction within the page
1643   */   */
1644    X(cfc0)
1645    {
1646            int fs = ic->arg[1] & 31;
1647            cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
1648            cpu->pc |= ic->arg[2];
1649            /*  TODO: cause exception if necessary  */
1650            reg(ic->arg[0]) = (int32_t)cpu->cd.mips.coproc[0]->fcr[fs];
1651    }
1652  X(mfc0)  X(mfc0)
1653  {  {
1654          int rd = ic->arg[1] & 31, select = ic->arg[1] >> 5;          int rd = ic->arg[1] & 31, select = ic->arg[1] >> 5;
# Line 422  X(mfc0) Line 1662  X(mfc0)
1662  X(mtc0)  X(mtc0)
1663  {  {
1664          int rd = ic->arg[1] & 31, select = ic->arg[1] >> 5;          int rd = ic->arg[1] & 31, select = ic->arg[1] >> 5;
1665            uint64_t tmp = (int32_t) reg(ic->arg[0]);
1666    
1667          cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);          cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
1668          cpu->pc |= ic->arg[2];          cpu->pc |= ic->arg[2];
1669    
1670          /*  TODO: cause exception if necessary  */          /*  TODO: cause exception if necessary  */
1671          coproc_register_write(cpu, cpu->cd.mips.coproc[0], rd,          coproc_register_write(cpu, cpu->cd.mips.coproc[0], rd, &tmp, 0, select);
1672              (uint64_t *)ic->arg[0], 0, select);  
1673            /*
1674             *  Interrupts enabled, and any interrupt pending? (Note/TODO: This
1675             *  code is duplicated in cpu_dyntrans.c. Fix this?)
1676             */
1677            if (rd == COP0_STATUS && !cpu->delay_slot) {
1678                    uint32_t status = cpu->cd.mips.coproc[0]->reg[COP0_STATUS];
1679                    uint32_t cause = cpu->cd.mips.coproc[0]->reg[COP0_CAUSE];
1680                    /*  NOTE: STATUS_IE happens to match the enable bit also
1681                        on R2000/R3000, so this is ok.  */
1682                    if (status & (STATUS_EXL | STATUS_ERL))
1683                            status &= ~STATUS_IE;
1684                    /*  Ugly R5900 special case:  (TODO: move this?)  */
1685                    if (cpu->cd.mips.cpu_type.rev == MIPS_R5900 &&
1686                        !(status & R5900_STATUS_EIE))
1687                            status &= ~STATUS_IE;
1688                    if (status & STATUS_IE && (status & cause & STATUS_IM_MASK)) {
1689                            cpu->pc += sizeof(uint32_t);
1690                            mips_cpu_exception(cpu, EXCEPTION_INT, 0, 0,0,0,0,0);
1691                    }
1692            }
1693  }  }
1694  X(dmfc0)  X(dmfc0)
1695  {  {
# Line 446  X(dmtc0) Line 1709  X(dmtc0)
1709          coproc_register_write(cpu, cpu->cd.mips.coproc[0], rd,          coproc_register_write(cpu, cpu->cd.mips.coproc[0], rd,
1710              (uint64_t *)ic->arg[0], 1, select);              (uint64_t *)ic->arg[0], 1, select);
1711  }  }
1712  X(cfc1)  
1713    
1714    /*
1715     *  cop1_bc:  Floating point conditional branch.
1716     *
1717     *  arg[0] = cc
1718     *  arg[1] = nd (=2) and tf (=1) bits
1719     *  arg[2] = offset (relative to start of this page)
1720     */
1721    X(cop1_bc)
1722    {
1723            MODE_int_t old_pc = cpu->pc;
1724            const int cpnr = 1;
1725            int x, low_pc, cc = ic->arg[0];
1726    
1727            low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1728                / sizeof(struct mips_instr_call);
1729            cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<< MIPS_INSTR_ALIGNMENT_SHIFT);
1730            cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1731            if (!(cpu->cd.mips.coproc[0]->
1732                reg[COP0_STATUS] & ((1 << cpnr) << STATUS_CU_SHIFT)) ) {
1733                    mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0, cpnr, 0, 0, 0);
1734                    return;
1735            }
1736    
1737            /*  Get the correct condition code bit:  */
1738            if (cc == 0)
1739                    x = (cpu->cd.mips.coproc[1]->fcr[MIPS_FPU_FCSR]
1740                        >> MIPS_FCSR_FCC0_SHIFT) & 1;
1741            else
1742                    x = (cpu->cd.mips.coproc[1]->fcr[MIPS_FPU_FCSR]
1743                        >> (MIPS_FCSR_FCC1_SHIFT + cc-1)) & 1;
1744    
1745            /*  Branch on false? Then invert the truth value.  */
1746            if (!(ic->arg[1] & 1))
1747                    x ^= 1;
1748    
1749            /*  Execute the delay slot (except if it is nullified):  */
1750            cpu->delay_slot = TO_BE_DELAYED;
1751            if (x || !(ic->arg[1] & 2))
1752                    ic[1].f(cpu, ic+1);
1753            cpu->n_translated_instrs ++;
1754    
1755            if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
1756                    /*  Note: Must be non-delayed when jumping to the new pc:  */
1757                    cpu->delay_slot = NOT_DELAYED;
1758                    if (x) {
1759                            old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
1760                                MIPS_INSTR_ALIGNMENT_SHIFT);
1761                            cpu->pc = old_pc + (int32_t)ic->arg[2];
1762                            quick_pc_to_pointers(cpu);
1763                    } else
1764                            cpu->cd.mips.next_ic ++;
1765            } else
1766                    cpu->delay_slot = NOT_DELAYED;
1767    }
1768    
1769    
1770    /*
1771     *  cop1_slow:  Fallback to legacy cop1 code. (Slow, but it should work.)
1772     */
1773    X(cop1_slow)
1774    {
1775            const int cpnr = 1;
1776            int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1777                / sizeof(struct mips_instr_call);
1778            cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<< MIPS_INSTR_ALIGNMENT_SHIFT);
1779            cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1780    
1781            if (!(cpu->cd.mips.coproc[0]->
1782                reg[COP0_STATUS] & ((1 << cpnr) << STATUS_CU_SHIFT)) ) {
1783                    mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0, cpnr, 0, 0, 0);
1784                    return;
1785            }
1786    
1787            coproc_function(cpu, cpu->cd.mips.coproc[1], 1, ic->arg[0], 0, 1);
1788    }
1789    
1790    
1791    /*
1792     *  syscall, break:  Synchronize the PC and cause an exception.
1793     */
1794    X(syscall)
1795    {
1796            int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1797                / sizeof(struct mips_instr_call);
1798            cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<< MIPS_INSTR_ALIGNMENT_SHIFT);
1799            cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1800            mips_cpu_exception(cpu, EXCEPTION_SYS, 0, 0, 0, 0, 0, 0);
1801    }
1802    X(break)
1803    {
1804            int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1805                / sizeof(struct mips_instr_call);
1806            cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<< MIPS_INSTR_ALIGNMENT_SHIFT);
1807            cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1808            mips_cpu_exception(cpu, EXCEPTION_BP, 0, 0, 0, 0, 0, 0);
1809    }
1810    
1811    
1812    /*
1813     *  promemul:  PROM software emulation.
1814     */
1815    X(promemul)
1816    {
1817            /*  Synchronize the PC and call the correct emulation layer:  */
1818            MODE_int_t old_pc;
1819            int res, low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1820                / sizeof(struct mips_instr_call);
1821            cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<< MIPS_INSTR_ALIGNMENT_SHIFT);
1822            cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1823            old_pc = cpu->pc;
1824    
1825            switch (cpu->machine->machine_type) {
1826            case MACHINE_PMAX:
1827                    res = decstation_prom_emul(cpu);
1828                    break;
1829            case MACHINE_PS2:
1830                    res = playstation2_sifbios_emul(cpu);
1831                    break;
1832            case MACHINE_ARC:
1833            case MACHINE_SGI:
1834                    res = arcbios_emul(cpu);
1835                    break;
1836            case MACHINE_EVBMIPS:
1837                    res = yamon_emul(cpu);
1838                    break;
1839            default:fatal("TODO: Unimplemented machine type for PROM magic trap\n");
1840                    exit(1);
1841            }
1842    
1843            if (res) {
1844                    /*  Return from the PROM call:  */
1845                    cpu->pc = (MODE_int_t)cpu->cd.mips.gpr[MIPS_GPR_RA];
1846                    cpu->delay_slot = NOT_DELAYED;
1847    
1848                    if (cpu->machine->show_trace_tree)
1849                            cpu_functioncall_trace_return(cpu);
1850            } else {
1851                    /*  The PROM call blocks.  */
1852                    cpu->n_translated_instrs += 10;
1853                    cpu->pc = old_pc;
1854            }
1855    
1856            quick_pc_to_pointers(cpu);
1857    }
1858    
1859    
1860    /*
1861     *  tlbw: TLB write indexed and random
1862     *
1863     *  arg[0] = 1 for random, 0 for indexed
1864     *  arg[2] = relative addr of this instruction within the page
1865     */
1866    X(tlbw)
1867  {  {
1868          cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);          cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
1869          cpu->pc |= ic->arg[2];          cpu->pc |= ic->arg[2];
1870          /*  TODO: cause exception if necessary  */          coproc_tlbwri(cpu, ic->arg[0]);
1871          reg(ic->arg[0]) = reg(ic->arg[1]);  }
1872    
1873    
1874    /*
1875     *  tlbp: TLB probe
1876     *  tlbr: TLB read
1877     *
1878     *  arg[2] = relative addr of this instruction within the page
1879     */
1880    X(tlbp)
1881    {
1882            cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
1883            cpu->pc |= ic->arg[2];
1884            coproc_tlbpr(cpu, 0);
1885    }
1886    X(tlbr)
1887    {
1888            cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
1889            cpu->pc |= ic->arg[2];
1890            coproc_tlbpr(cpu, 1);
1891    }
1892    
1893    
1894    /*
1895     *  rfe: Return from exception handler (R2000/R3000)
1896     */
1897    X(rfe)
1898    {
1899            /*  Just rotate the interrupt/user bits:  */
1900            cpu->cd.mips.coproc[0]->reg[COP0_STATUS] =
1901                (cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & ~0x3f) |
1902                ((cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & 0x3c) >> 2);
1903    
1904            /*
1905             *  Note: no pc to pointers conversion is necessary here. Usually the
1906             *  rfe instruction resides in the delay slot of a jr k0/k1, and
1907             *  it is up to that instruction to do the pointer conversion.
1908             */
1909    }
1910    
1911    
1912    /*
1913     *  eret: Return from exception handler (non-R3000 style)
1914     */
1915    X(eret)
1916    {
1917            if (cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & STATUS_ERL) {
1918                    cpu->pc = cpu->cd.mips.coproc[0]->reg[COP0_ERROREPC];
1919                    cpu->cd.mips.coproc[0]->reg[COP0_STATUS] &= ~STATUS_ERL;
1920            } else {
1921                    cpu->pc = cpu->cd.mips.coproc[0]->reg[COP0_EPC];
1922                    cpu->delay_slot = 0;            
1923                    cpu->cd.mips.coproc[0]->reg[COP0_STATUS] &= ~STATUS_EXL;
1924            }
1925    
1926            quick_pc_to_pointers(cpu);
1927    
1928            cpu->cd.mips.rmw = 0;   /*  the "LL bit"  */
1929    }
1930    
1931    
1932    /*
1933     *  deret: Return from debug (EJTAG) handler
1934     */
1935    X(deret)
1936    {
1937            /*
1938             *  According to the MIPS64 manual, deret loads PC from the DEPC cop0
1939             *  register, and jumps there immediately. No delay slot.
1940             *
1941             *  TODO: This instruction is only available if the processor is in
1942             *  debug mode. (What does that mean?)
1943             *
1944             *  TODO: This instruction is undefined in a delay slot.
1945             */
1946    
1947            cpu->pc = cpu->cd.mips.coproc[0]->reg[COP0_DEPC];
1948            cpu->delay_slot = 0;
1949            cpu->cd.mips.coproc[0]->reg[COP0_STATUS] &= ~STATUS_EXL;
1950            quick_pc_to_pointers(cpu);
1951    }
1952    
1953    
1954    /*
1955     *  rdhwr: Read hardware register into gpr (MIPS32/64 rev 2).
1956     *
1957     *  arg[0] = ptr to rt (destination register)
1958     */
1959    X(rdhwr_cpunum)
1960    {
1961            reg(ic->arg[0]) = cpu->cpu_id;
1962    }
1963    
1964    
1965    #include "tmp_mips_loadstore.c"
1966    
1967    
1968    /*
1969     *  Load linked / store conditional:
1970     *
1971     *  A Load-linked instruction initiates a RMW (read-modify-write) sequence.
1972     *  COP0_LLADDR is updated for diagnostic purposes, except for CPUs in the
1973     *  R10000 family.
1974     *
1975     *  A Store-conditional instruction ends the sequence.
1976     *
1977     *  arg[0] = ptr to rt
1978     *  arg[1] = ptr to rs
1979     *  arg[2] = int32_t imm
1980     */
1981    X(ll)
1982    {
1983            MODE_int_t addr = reg(ic->arg[1]) + (int32_t)ic->arg[2];
1984            int low_pc;
1985            uint8_t word[sizeof(uint32_t)];
1986    
1987            /*  Synch. PC and load using slow memory_rw():  */
1988            low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1989                / sizeof(struct mips_instr_call);
1990            cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
1991                << MIPS_INSTR_ALIGNMENT_SHIFT);
1992            cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1993    
1994            if (addr & (sizeof(word)-1)) {
1995                    fatal("TODO: load linked unaligned access: exception\n");
1996                    exit(1);
1997            }
1998    
1999            if (!cpu->memory_rw(cpu, cpu->mem, addr, word,
2000                sizeof(word), MEM_READ, CACHE_DATA)) {
2001                    /*  An exception occurred.  */
2002                    return;
2003            }
2004    
2005            cpu->cd.mips.rmw = 1;
2006            cpu->cd.mips.rmw_addr = addr;
2007            cpu->cd.mips.rmw_len = sizeof(word);
2008            if (cpu->cd.mips.cpu_type.exc_model != MMU10K)
2009                    cpu->cd.mips.coproc[0]->reg[COP0_LLADDR] =
2010                        (addr >> 4) & 0xffffffffULL;
2011    
2012            if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
2013                    reg(ic->arg[0]) = (int32_t) (word[0] + (word[1] << 8)
2014                        + (word[2] << 16) + (word[3] << 24));
2015            else
2016                    reg(ic->arg[0]) = (int32_t) (word[3] + (word[2] << 8)
2017                        + (word[1] << 16) + (word[0] << 24));
2018    }
2019    X(lld)
2020    {
2021            MODE_int_t addr = reg(ic->arg[1]) + (int32_t)ic->arg[2];
2022            int low_pc;
2023            uint8_t word[sizeof(uint64_t)];
2024    
2025            /*  Synch. PC and load using slow memory_rw():  */
2026            low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
2027                / sizeof(struct mips_instr_call);
2028            cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
2029                << MIPS_INSTR_ALIGNMENT_SHIFT);
2030            cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
2031    
2032            if (addr & (sizeof(word)-1)) {
2033                    fatal("TODO: load linked unaligned access: exception\n");
2034                    exit(1);
2035            }
2036    
2037            if (!cpu->memory_rw(cpu, cpu->mem, addr, word,
2038                sizeof(word), MEM_READ, CACHE_DATA)) {
2039                    /*  An exception occurred.  */
2040                    return;
2041            }
2042    
2043            cpu->cd.mips.rmw = 1;
2044            cpu->cd.mips.rmw_addr = addr;
2045            cpu->cd.mips.rmw_len = sizeof(word);
2046            if (cpu->cd.mips.cpu_type.exc_model != MMU10K)
2047                    cpu->cd.mips.coproc[0]->reg[COP0_LLADDR] =
2048                        (addr >> 4) & 0xffffffffULL;
2049    
2050            if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
2051                    reg(ic->arg[0]) = word[0] + (word[1] << 8)
2052                        + (word[2] << 16) + ((uint64_t)word[3] << 24) +
2053                        + ((uint64_t)word[4] << 32) + ((uint64_t)word[5] << 40)
2054                        + ((uint64_t)word[6] << 48) + ((uint64_t)word[7] << 56);
2055            else
2056                    reg(ic->arg[0]) = word[7] + (word[6] << 8)
2057                        + (word[5] << 16) + ((uint64_t)word[4] << 24) +
2058                        + ((uint64_t)word[3] << 32) + ((uint64_t)word[2] << 40)
2059                        + ((uint64_t)word[1] << 48) + ((uint64_t)word[0] << 56);
2060    }
2061    X(sc)
2062    {
2063            MODE_int_t addr = reg(ic->arg[1]) + (int32_t)ic->arg[2];
2064            uint64_t r = reg(ic->arg[0]);
2065            int low_pc, i;
2066            uint8_t word[sizeof(uint32_t)];
2067    
2068            /*  Synch. PC and store using slow memory_rw():  */
2069            low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
2070                / sizeof(struct mips_instr_call);
2071            cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
2072                << MIPS_INSTR_ALIGNMENT_SHIFT);
2073            cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
2074    
2075            if (addr & (sizeof(word)-1)) {
2076                    fatal("TODO: sc unaligned access: exception\n");
2077                    exit(1);
2078            }
2079    
2080            if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {
2081                    word[0]=r; word[1]=r>>8; word[2]=r>>16; word[3]=r>>24;
2082            } else {
2083                    word[3]=r; word[2]=r>>8; word[1]=r>>16; word[0]=r>>24;
2084            }
2085    
2086            /*  If rmw is 0, then the store failed.  (This cache-line was written
2087                to by someone else.)  */
2088            if (cpu->cd.mips.rmw == 0 || cpu->cd.mips.rmw_addr != addr
2089                || cpu->cd.mips.rmw_len != sizeof(word)) {
2090                    reg(ic->arg[0]) = 0;
2091                    cpu->cd.mips.rmw = 0;
2092                    return;
2093            }
2094    
2095            if (!cpu->memory_rw(cpu, cpu->mem, addr, word,
2096                sizeof(word), MEM_WRITE, CACHE_DATA)) {
2097                    /*  An exception occurred.  */
2098                    return;
2099            }
2100    
2101            /*  We succeeded. Let's invalidate everybody else's store to this
2102                cache line:  */
2103            for (i=0; i<cpu->machine->ncpus; i++) {
2104                    if (cpu->machine->cpus[i]->cd.mips.rmw) {
2105                            uint64_t yaddr = addr, xaddr = cpu->machine->cpus[i]->
2106                                cd.mips.rmw_addr;
2107                            uint64_t mask = ~(cpu->machine->cpus[i]->
2108                                cd.mips.cache_linesize[CACHE_DATA] - 1);
2109                            xaddr &= mask;
2110                            yaddr &= mask;
2111                            if (xaddr == yaddr)
2112                                    cpu->machine->cpus[i]->cd.mips.rmw = 0;
2113                    }
2114            }
2115    
2116            reg(ic->arg[0]) = 1;
2117            cpu->cd.mips.rmw = 0;
2118    }
2119    X(scd)
2120    {
2121            MODE_int_t addr = reg(ic->arg[1]) + (int32_t)ic->arg[2];
2122            uint64_t r = reg(ic->arg[0]);
2123            int low_pc, i;
2124            uint8_t word[sizeof(uint64_t)];
2125    
2126            /*  Synch. PC and store using slow memory_rw():  */
2127            low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
2128                / sizeof(struct mips_instr_call);
2129            cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
2130                << MIPS_INSTR_ALIGNMENT_SHIFT);
2131            cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
2132    
2133            if (addr & (sizeof(word)-1)) {
2134                    fatal("TODO: sc unaligned access: exception\n");
2135                    exit(1);
2136            }
2137    
2138            if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {
2139                    word[0]=r;     word[1]=r>>8; word[2]=r>>16; word[3]=r>>24;
2140                    word[4]=r>>32; word[5]=r>>40; word[6]=r>>48; word[7]=r>>56;
2141            } else {
2142                    word[7]=r;     word[6]=r>>8; word[5]=r>>16; word[4]=r>>24;
2143                    word[3]=r>>32; word[2]=r>>40; word[1]=r>>48; word[0]=r>>56;
2144            }
2145    
2146            /*  If rmw is 0, then the store failed.  (This cache-line was written
2147                to by someone else.)  */
2148            if (cpu->cd.mips.rmw == 0 || cpu->cd.mips.rmw_addr != addr
2149                || cpu->cd.mips.rmw_len != sizeof(word)) {
2150                    reg(ic->arg[0]) = 0;
2151                    cpu->cd.mips.rmw = 0;
2152                    return;
2153            }
2154    
2155            if (!cpu->memory_rw(cpu, cpu->mem, addr, word,
2156                sizeof(word), MEM_WRITE, CACHE_DATA)) {
2157                    /*  An exception occurred.  */
2158                    return;
2159            }
2160    
2161            /*  We succeeded. Let's invalidate everybody else's store to this
2162                cache line:  */
2163            for (i=0; i<cpu->machine->ncpus; i++) {
2164                    if (cpu->machine->cpus[i]->cd.mips.rmw) {
2165                            uint64_t yaddr = addr, xaddr = cpu->machine->cpus[i]->
2166                                cd.mips.rmw_addr;
2167                            uint64_t mask = ~(cpu->machine->cpus[i]->
2168                                cd.mips.cache_linesize[CACHE_DATA] - 1);
2169                            xaddr &= mask;
2170                            yaddr &= mask;
2171                            if (xaddr == yaddr)
2172                                    cpu->machine->cpus[i]->cd.mips.rmw = 0;
2173                    }
2174            }
2175    
2176            reg(ic->arg[0]) = 1;
2177            cpu->cd.mips.rmw = 0;
2178    }
2179    
2180    
2181    /*
2182     *  lwc1, swc1:  Coprocessor 1 load/store (32-bit)
2183     *  ldc1, sdc1:  Coprocessor 1 load/store (64-bit)
2184     *
2185     *  arg[0] = ptr to coprocessor register
2186     *  arg[1] = ptr to rs (base pointer register)
2187     *  arg[2] = int32_t imm
2188     */
2189    X(lwc1)
2190    {
2191            const int cpnr = 1;
2192    
2193            /*  Synch. PC and call the generic load/store function:  */
2194            int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
2195                / sizeof(struct mips_instr_call);
2196            cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
2197                << MIPS_INSTR_ALIGNMENT_SHIFT);
2198            cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
2199    
2200            /*  ... but first, let's see if the coprocessor is available:  */
2201            if (!(cpu->cd.mips.coproc[0]->
2202                reg[COP0_STATUS] & ((1 << cpnr) << STATUS_CU_SHIFT)) ) {
2203                    mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0, cpnr, 0, 0, 0);
2204                    return;
2205            }
2206    
2207    #ifdef MODE32
2208            mips32_loadstore
2209    #else
2210            mips_loadstore
2211    #endif
2212                [ (cpu->byte_order == EMUL_LITTLE_ENDIAN? 0 : 16) + 2 * 2 + 1]
2213                (cpu, ic);
2214    }
2215    X(swc1)
2216    {
2217            const int cpnr = 1;
2218    
2219            /*  Synch. PC and call the generic load/store function:  */
2220            int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
2221                / sizeof(struct mips_instr_call);
2222            cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
2223                << MIPS_INSTR_ALIGNMENT_SHIFT);
2224            cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
2225    
2226            /*  ... but first, let's see if the coprocessor is available:  */
2227            if (!(cpu->cd.mips.coproc[0]->
2228                reg[COP0_STATUS] & ((1 << cpnr) << STATUS_CU_SHIFT)) ) {
2229                    mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0, cpnr, 0, 0, 0);
2230                    return;
2231            }
2232    
2233    #ifdef MODE32
2234            mips32_loadstore
2235    #else
2236            mips_loadstore
2237    #endif
2238                [ (cpu->byte_order == EMUL_LITTLE_ENDIAN? 0 : 16) + 8 + 2 * 2]
2239                (cpu, ic);
2240    }
2241    X(ldc1)
2242    {
2243            const int cpnr = 1;
2244            int use_fp_pairs =
2245                !(cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & STATUS_FR);
2246            uint64_t fpr, *backup_ptr;
2247    
2248            /*  Synch. PC and call the generic load/store function:  */
2249            int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
2250                / sizeof(struct mips_instr_call);
2251            cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
2252                << MIPS_INSTR_ALIGNMENT_SHIFT);
2253            cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
2254    
2255            /*  ... but first, let's see if the coprocessor is available:  */
2256            if (!(cpu->cd.mips.coproc[0]->
2257                reg[COP0_STATUS] & ((1 << cpnr) << STATUS_CU_SHIFT)) ) {
2258                    mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0, cpnr, 0, 0, 0);
2259                    return;
2260            }
2261    
2262            backup_ptr = (uint64_t *) ic->arg[0];
2263            ic->arg[0] = (size_t) &fpr;
2264    
2265    #ifdef MODE32
2266            mips32_loadstore
2267    #else
2268            mips_loadstore
2269    #endif
2270                [ (cpu->byte_order == EMUL_LITTLE_ENDIAN? 0 : 16) + 3 * 2 + 1]
2271                (cpu, ic);
2272    
2273            if (use_fp_pairs) {
2274                    backup_ptr[0] = (int64_t)(int32_t) fpr;
2275                    backup_ptr[1] = (int64_t)(int32_t) (fpr >> 32);
2276            } else {
2277                    *backup_ptr = fpr;
2278            }
2279    
2280            ic->arg[0] = (size_t) backup_ptr;
2281    }
2282    X(sdc1)
2283    {
2284            const int cpnr = 1;
2285            int use_fp_pairs =
2286                !(cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & STATUS_FR);
2287            uint64_t fpr, *backup_ptr;
2288    
2289            /*  Synch. PC and call the generic load/store function:  */
2290            int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
2291                / sizeof(struct mips_instr_call);
2292            cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
2293                << MIPS_INSTR_ALIGNMENT_SHIFT);
2294            cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
2295    
2296            /*  ... but first, let's see if the coprocessor is available:  */
2297            if (!(cpu->cd.mips.coproc[0]->
2298                reg[COP0_STATUS] & ((1 << cpnr) << STATUS_CU_SHIFT)) ) {
2299                    mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0, cpnr, 0, 0, 0);
2300                    return;
2301            }
2302    
2303            backup_ptr = (uint64_t *) ic->arg[0];
2304            ic->arg[0] = (size_t) &fpr;
2305    
2306            if (use_fp_pairs) {
2307                    uint32_t lo = backup_ptr[0];
2308                    uint32_t hi = backup_ptr[1];
2309                    fpr = (((uint64_t)hi) << 32) | lo;
2310            } else {
2311                    fpr = *backup_ptr;
2312            }
2313    
2314    #ifdef MODE32
2315            mips32_loadstore
2316    #else
2317            mips_loadstore
2318    #endif
2319                [ (cpu->byte_order == EMUL_LITTLE_ENDIAN? 0 : 16) + 8 + 3 * 2]
2320                (cpu, ic);
2321    
2322            ic->arg[0] = (size_t) backup_ptr;
2323    }
2324    
2325    
2326    /*
2327     *  Unaligned loads/stores:
2328     *
2329     *  arg[0] = ptr to rt
2330     *  arg[1] = ptr to rs
2331     *  arg[2] = int32_t imm
2332     */
2333    X(lwl) { mips_unaligned_loadstore(cpu, ic, 1, sizeof(uint32_t), 0); }
2334    X(lwr) { mips_unaligned_loadstore(cpu, ic, 0, sizeof(uint32_t), 0); }
2335    X(ldl) { mips_unaligned_loadstore(cpu, ic, 1, sizeof(uint64_t), 0); }
2336    X(ldr) { mips_unaligned_loadstore(cpu, ic, 0, sizeof(uint64_t), 0); }
2337    X(swl) { mips_unaligned_loadstore(cpu, ic, 1, sizeof(uint32_t), 1); }
2338    X(swr) { mips_unaligned_loadstore(cpu, ic, 0, sizeof(uint32_t), 1); }
2339    X(sdl) { mips_unaligned_loadstore(cpu, ic, 1, sizeof(uint64_t), 1); }
2340    X(sdr) { mips_unaligned_loadstore(cpu, ic, 0, sizeof(uint64_t), 1); }
2341    
2342    
2343    /*
2344     *  di, ei: R5900 interrupt enable/disable.
2345     *
2346     *  TODO: check the R5900_STATUS_EDI bit in the status register. If it is
2347     *  cleared, and we are not running in kernel mode, then both the EI and DI
2348     *  instructions should be treated as NOPs!
2349     */
2350    X(di_r5900)
2351    {
2352            cpu->cd.mips.coproc[0]->reg[COP0_STATUS] &= ~R5900_STATUS_EIE;
2353    }
2354    X(ei_r5900)
2355    {
2356            cpu->cd.mips.coproc[0]->reg[COP0_STATUS] |= R5900_STATUS_EIE;
2357  }  }
2358    
2359    
# Line 459  X(cfc1) Line 2361  X(cfc1)
2361    
2362    
2363  /*  /*
2364     *  sw_loop:
2365     *
2366     *  s:  addiu   rX,rX,4                 rX = arg[0] and arg[1]
2367     *      bne     rY,rX,s  (or rX,rY,s)   rt=arg[1], rs=arg[0]
2368     *      sw      rZ,-4(rX)               rt=arg[0], rs=arg[1]
2369     */
2370    X(sw_loop)
2371    {
2372            MODE_uint_t rX = reg(ic->arg[0]), rZ = reg(ic[2].arg[0]);
2373            uint64_t *rYp = (uint64_t *) ic[1].arg[0];
2374            MODE_uint_t rY, bytes_to_write;
2375            unsigned char *page;
2376            int partial = 0;
2377    
2378            page = cpu->cd.mips.host_store[rX >> 12];
2379    
2380            /*  Fallback:  */
2381            if (cpu->delay_slot || page == NULL || (rX & 3) != 0 || rZ != 0) {
2382                    instr(addiu)(cpu, ic);
2383                    return;
2384            }
2385    
2386            if (rYp == (uint64_t *) ic->arg[0])
2387                    rYp = (uint64_t *) ic[1].arg[1];
2388    
2389            rY = reg(rYp);
2390    
2391            bytes_to_write = rY - rX;
2392            if ((rX & 0xfff) + bytes_to_write > 0x1000) {
2393                    bytes_to_write = 0x1000 - (rX & 0xfff);
2394                    partial = 1;
2395            }
2396    
2397            /*  printf("rX = %08x\n", (int)rX);
2398                printf("rY = %08x\n", (int)rY);
2399                printf("rZ = %08x\n", (int)rZ);
2400                printf("%i bytes\n", (int)bytes_to_write);  */
2401    
2402            memset(page + (rX & 0xfff), 0, bytes_to_write);
2403    
2404            reg(ic->arg[0]) = rX + bytes_to_write;
2405    
2406            cpu->n_translated_instrs += bytes_to_write / 4 * 3 - 1;
2407            cpu->cd.mips.next_ic = partial?
2408                (struct mips_instr_call *) &ic[0] :
2409                (struct mips_instr_call *) &ic[3];
2410    }
2411    
2412    
2413    /*
2414     *  multi_sw_3:
2415     *
2416     *      sw      r?,ofs(rX)              r?=arg[0], rX=arg[1], ofs=arg[2]
2417     *      sw      r?,ofs(rX)              r?=arg[0], rX=arg[1], ofs=arg[2]
2418     *      sw      r?,ofs(rX)              r?=arg[0], rX=arg[1], ofs=arg[2]
2419     */
2420    X(multi_sw_3_le)
2421    {
2422            uint32_t *page;
2423            MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2, r3;
2424            MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2];
2425            MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2];
2426            MODE_uint_t addr2 = rX + (int32_t)ic[2].arg[2];
2427            uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12,
2428                index2 = addr2 >> 12;
2429    
2430            page = (uint32_t *) cpu->cd.mips.host_store[index0];
2431    
2432            /*  Fallback:  */
2433            if (cpu->delay_slot ||
2434                page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 ||
2435                (addr2 & 3) != 0 || index0 != index1 || index0 != index2) {
2436                    /*  Normal safe sw:  */
2437                    ic[1].f(cpu, ic);
2438                    return;
2439            }
2440    
2441            addr0 = (addr0 >> 2) & 0x3ff;
2442            addr1 = (addr1 >> 2) & 0x3ff;
2443            addr2 = (addr2 >> 2) & 0x3ff;
2444    
2445            /*  printf("addr0=%x 1=%x 2=%x\n",
2446                (int)addr0, (int)addr1, (int)addr2);  */
2447    
2448            r1 = reg(ic[0].arg[0]);
2449            r2 = reg(ic[1].arg[0]);
2450            r3 = reg(ic[2].arg[0]);
2451    
2452            r1 = LE32_TO_HOST(r1);
2453            r2 = LE32_TO_HOST(r2);
2454            r3 = LE32_TO_HOST(r3);
2455    
2456            page[addr0] = r1;
2457            page[addr1] = r2;
2458            page[addr2] = r3;
2459    
2460            cpu->n_translated_instrs += 2;
2461            cpu->cd.mips.next_ic = (struct mips_instr_call *) &ic[3];
2462    }
2463    X(multi_sw_3_be)
2464    {
2465            uint32_t *page;
2466            MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2, r3;
2467            MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2];
2468            MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2];
2469            MODE_uint_t addr2 = rX + (int32_t)ic[2].arg[2];
2470            uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12,
2471                index2 = addr2 >> 12;
2472    
2473            page = (uint32_t *) cpu->cd.mips.host_store[index0];
2474    
2475            /*  Fallback:  */
2476            if (cpu->delay_slot ||
2477                page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 ||
2478                (addr2 & 3) != 0 || index0 != index1 || index0 != index2) {
2479                    /*  Normal safe sw:  */
2480                    ic[1].f(cpu, ic);
2481                    return;
2482            }
2483    
2484            addr0 = (addr0 >> 2) & 0x3ff;
2485            addr1 = (addr1 >> 2) & 0x3ff;
2486            addr2 = (addr2 >> 2) & 0x3ff;
2487    
2488            /*  printf("addr0=%x 1=%x 2=%x\n",
2489                (int)addr0, (int)addr1, (int)addr2);  */
2490    
2491            r1 = reg(ic[0].arg[0]);
2492            r2 = reg(ic[1].arg[0]);
2493            r3 = reg(ic[2].arg[0]);
2494    
2495            r1 = BE32_TO_HOST(r1);
2496            r2 = BE32_TO_HOST(r2);
2497            r3 = BE32_TO_HOST(r3);
2498    
2499            page[addr0] = r1;
2500            page[addr1] = r2;
2501            page[addr2] = r3;
2502    
2503            cpu->n_translated_instrs += 2;
2504            cpu->cd.mips.next_ic = (struct mips_instr_call *) &ic[3];
2505    }
2506    
2507    
2508    /*
2509     *  netbsd_r3k_picache_do_inv:
2510     *
2511     *  ic[0]       mtc0    rV,status
2512     *     1        nop
2513     *     2        nop
2514     *     3  s:    addiu   rX,rX,4
2515     *     4        bne     rY,rX,s
2516     *     5        sb      zr,-4(rX)
2517     *     6        nop
2518     *     7        nop
2519     *     8        mtc0    rT,status
2520     */
2521    X(netbsd_r3k_picache_do_inv)
2522    {
2523            MODE_uint_t rx = reg(ic[3].arg[0]), ry = reg(ic[4].arg[1]);
2524    
2525            /*  Fallback if the environment isn't exactly right:  */
2526            if (!(reg(ic[0].arg[0]) & MIPS1_ISOL_CACHES) ||
2527                (rx & 3) || (ry & 3) || cpu->delay_slot) {
2528                    instr(mtc0)(cpu, ic);
2529                    return;
2530            }
2531    
2532            reg(ic[3].arg[0]) = ry;
2533            cpu->n_translated_instrs += (ry - rx + 4) / 4 * 3 + 4;
2534    
2535            /*  Run the last mtc0 instruction:  */
2536            cpu->cd.mips.next_ic = (struct mips_instr_call *) &ic[8];
2537    }
2538    
2539    
2540    #ifdef MODE32
2541    /*
2542     *  netbsd_strlen():
2543     *
2544     *      lb      rV,0(rX)
2545     *   s: addiu   rX,rX,1
2546     *      bne     zr,rV,s
2547     *      nop
2548     */
2549    X(netbsd_strlen)
2550    {
2551            MODE_uint_t rx = reg(ic[0].arg[1]);
2552            MODE_int_t rv;
2553            signed char *page;
2554            uint32_t pageindex = rx >> 12;
2555            int i;
2556    
2557            page = (signed char *) cpu->cd.mips.host_load[pageindex];
2558    
2559            /*  Fallback:  */
2560            if (cpu->delay_slot || page == NULL) {
2561                    /*
2562                     *  Normal lb:  NOTE: It doesn't matter whether [1] or
2563                     *  [16+1] is called here, because endianness for 8-bit
2564                     *  loads is irrelevant. :-)
2565                     */
2566                    mips32_loadstore[1](cpu, ic);
2567                    return;
2568            }
2569    
2570            i = rx & 0xfff;
2571    
2572            /*
2573             *  TODO: This loop can be optimized further for optimal
2574             *  performance on the host, e.g. by reading full words...
2575             */
2576            do {
2577                    rv = page[i ++];
2578            } while (i < 0x1000 && rv != 0);
2579    
2580            cpu->n_translated_instrs += (i - (rx & 0xfff)) * 4 - 1;
2581    
2582            reg(ic[0].arg[1]) = (rx & ~0xfff) + i;
2583            reg(ic[2].arg[0]) = rv;
2584    
2585            /*  Done with the loop? Or continue on the next rx page?  */
2586            if (rv == 0)
2587                    cpu->cd.mips.next_ic = (struct mips_instr_call *) &ic[4];
2588            else
2589                    cpu->cd.mips.next_ic = (struct mips_instr_call *) &ic[0];
2590    }
2591    #endif
2592    
2593    
2594    /*
2595     *  lui_32bit:
2596     *
2597     *  Combination of lui and addiu.
2598     *  Note: All 32 bits of arg[2] of the lui instr_call are used.
2599     */
2600    X(lui_32bit)
2601    {
2602            reg(ic[0].arg[0]) = (int32_t) ic[0].arg[2];
2603            cpu->n_translated_instrs ++;
2604            cpu->cd.mips.next_ic ++;
2605    }
2606    
2607    
2608    /*
2609   *  b_samepage_addiu:   *  b_samepage_addiu:
2610   *   *
2611   *  Combination of branch within the same page, followed by addiu.   *  Combination of branch within the same page, followed by addiu.
2612   */   */
2613  X(b_samepage_addiu)  X(b_samepage_addiu)
2614  {  {
2615          reg(ic[1].arg[1]) = reg(ic[1].arg[0]) + (int32_t)ic[1].arg[2];          reg(ic[1].arg[1]) = (int32_t)
2616                ( (int32_t)reg(ic[1].arg[0]) + (int32_t)ic[1].arg[2] );
2617            cpu->n_translated_instrs ++;
2618            cpu->cd.mips.next_ic = (struct mips_instr_call *) ic->arg[2];
2619    }
2620    
2621    
2622    /*
2623     *  b_samepage_daddiu:
2624     *
2625     *  Combination of branch within the same page, followed by daddiu.
2626     */
2627    X(b_samepage_daddiu)
2628    {
2629            *(uint64_t *)ic[1].arg[1] = *(uint64_t *)ic[1].arg[0] +
2630                (int32_t)ic[1].arg[2];
2631          cpu->n_translated_instrs ++;          cpu->n_translated_instrs ++;
2632          cpu->cd.mips.next_ic = (struct mips_instr_call *) ic->arg[2];          cpu->cd.mips.next_ic = (struct mips_instr_call *) ic->arg[2];
2633  }  }
# Line 476  X(b_samepage_addiu) Line 2638  X(b_samepage_addiu)
2638    
2639  X(end_of_page)  X(end_of_page)
2640  {  {
         struct mips_instr_call self;  
   
2641          /*  Update the PC:  (offset 0, but on the next page)  */          /*  Update the PC:  (offset 0, but on the next page)  */
2642          cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<          cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
2643              MIPS_INSTR_ALIGNMENT_SHIFT);              MIPS_INSTR_ALIGNMENT_SHIFT);
2644          cpu->pc += (MIPS_IC_ENTRIES_PER_PAGE << MIPS_INSTR_ALIGNMENT_SHIFT);          cpu->pc += (MIPS_IC_ENTRIES_PER_PAGE << MIPS_INSTR_ALIGNMENT_SHIFT);
2645    
2646          /*  Simple jump to the next page (if we are lucky):  */          /*  end_of_page doesn't count as an executed instruction:  */
2647          if (cpu->cd.mips.delay_slot == NOT_DELAYED) {          cpu->n_translated_instrs --;
2648    
2649                  /*  Find the new physpage and update translation pointers:  */          /*
2650                  quick_pc_to_pointers(cpu);           *  Find the new physpage and update translation pointers.
2651             *
2652             *  Note: This may cause an exception, if e.g. the new page is
2653             *  not accessible.
2654             */
2655            quick_pc_to_pointers(cpu);
2656    
2657                  /*  end_of_page doesn't count as an executed instruction:  */          /*  Simple jump to the next page (if we are lucky):  */
2658                  cpu->n_translated_instrs --;          if (cpu->delay_slot == NOT_DELAYED)
2659                    return;
2660    
2661            /*
2662             *  If we were in a delay slot, and we got an exception while doing
2663             *  quick_pc_to_pointers, then return. The function which called
2664             *  end_of_page should handle this case.
2665             */
2666            if (cpu->delay_slot == EXCEPTION_IN_DELAY_SLOT)
2667                  return;                  return;
         }  
2668    
2669          /*  Tricky situation; the delay slot is on the next virtual page:  */          /*
2670             *  Tricky situation; the delay slot is on the next virtual page.
2671             *  Calling to_be_translated will translate one instruction manually,
2672             *  execute it, and then discard it.
2673             */
2674          /*  fatal("[ end_of_page: delay slot across page boundary! ]\n");  */          /*  fatal("[ end_of_page: delay slot across page boundary! ]\n");  */
2675    
2676          /*  to_be_translated will overwrite the current ic.  */          instr(to_be_translated)(cpu, cpu->cd.mips.next_ic);
         self = *ic;  
   
         instr(to_be_translated)(cpu, ic);  
2677    
2678          /*  The instruction in the delay slot has now executed.  */          /*  The instruction in the delay slot has now executed.  */
2679            /*  fatal("[ end_of_page: back from executing the delay slot, %i ]\n",
2680                cpu->delay_slot);  */
2681    
2682          /*  Find the physpage etc of the instruction in the delay slot          /*  Find the physpage etc of the instruction in the delay slot
2683              (or, if there was an exception, the exception handler):  */              (or, if there was an exception, the exception handler):  */
2684          quick_pc_to_pointers(cpu);          quick_pc_to_pointers(cpu);
   
         /*  Restore the end_of_page instr call.  */  
         *ic = self;  
   
         /*  fatal("[ end_of_page: back from delay slot ]\n");  */  
2685  }  }
2686    
2687    
2688  X(end_of_page2)  X(end_of_page2)
2689  {  {
2690  fatal("this should be removed: end of page2\n");          /*  Synchronize PC on the _second_ instruction on the next page:  */
2691  exit(1);          int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
2692                / sizeof(struct mips_instr_call);
2693          /*  Update the PC:  (offset 4, but on the next page)  */          cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
2694          cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<              << MIPS_INSTR_ALIGNMENT_SHIFT);
2695              MIPS_INSTR_ALIGNMENT_SHIFT);          cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
         cpu->pc += ((MIPS_IC_ENTRIES_PER_PAGE+1) << MIPS_INSTR_ALIGNMENT_SHIFT);  
2696    
2697          if (cpu->cd.mips.delay_slot == NOT_DELAYED) {          /*  This doesn't count as an executed instruction.  */
2698                  /*  Find the new physpage and update translation pointers:  */          cpu->n_translated_instrs --;
                 quick_pc_to_pointers(cpu);  
2699    
2700                  /*  end_of_page doesn't count as an executed instruction:  */          quick_pc_to_pointers(cpu);
                 cpu->n_translated_instrs --;  
2701    
2702            if (cpu->delay_slot == NOT_DELAYED)
2703                  return;                  return;
         }  
2704    
2705          fatal("DELAY SLOT in DELAY SLOT across a page boundary? HUH?\n");          fatal("end_of_page2: fatal error, we're in a delay slot\n");
2706          exit(1);          exit(1);
2707  }  }
2708    
# Line 545  exit(1); Line 2711  exit(1);
2711    
2712    
2713  /*  /*
2714   *  Combine: [Conditional] branch, followed by addiu.   *  Combine:  Memory fill loop (addiu, bne, sw)
2715     *
2716     *  s:  addiu   rX,rX,4
2717     *      bne     rY,rX,s
2718     *      sw      rZ,-4(rX)
2719     */
2720    void COMBINE(sw_loop)(struct cpu *cpu, struct mips_instr_call *ic, int low_addr)
2721    {
2722            int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
2723                & (MIPS_IC_ENTRIES_PER_PAGE - 1);
2724    
2725            /*  Only for 32-bit virtual address translation so far.  */
2726            if (!cpu->is_32bit)
2727                    return;
2728    
2729            if (n_back < 2)
2730                    return;
2731    
2732            if (ic[-2].f == instr(addiu) && ic[-2].arg[0] == ic[-2].arg[1] &&
2733                (int32_t)ic[-2].arg[2] == 4 &&
2734                ic[-1].f == instr(bne_samepage) &&
2735                (ic[-1].arg[0] == ic[-2].arg[0] ||
2736                    ic[-1].arg[1] == ic[-2].arg[0]) &&
2737                ic[-1].arg[0] != ic[-1].arg[1] &&
2738                ic[-1].arg[2] == (size_t) &ic[-2] &&
2739                ic[0].arg[0] != ic[0].arg[1] &&
2740                ic[0].arg[1] == ic[-2].arg[0] && (int32_t)ic[0].arg[2] == -4) {
2741                    ic[-2].f = instr(sw_loop);
2742                    combined;
2743            }
2744    }
2745    
2746    
2747    /*
2748     *  Combine:  Multiple SW in a row using the same base register
2749     *
2750     *      sw      r?,???(rX)
2751     *      sw      r?,???(rX)
2752     *      sw      r?,???(rX)
2753     *      ...
2754   */   */
2755  void COMBINE(b_addiu)(struct cpu *cpu, struct mips_instr_call *ic,  void COMBINE(multi_sw)(struct cpu *cpu, struct mips_instr_call *ic,
2756          int low_addr)          int low_addr)
2757  {  {
2758          int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)          int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
2759              & (MIPS_IC_ENTRIES_PER_PAGE - 1);              & (MIPS_IC_ENTRIES_PER_PAGE - 1);
2760    
2761            /*  Only for 32-bit virtual address translation so far.  */
2762            if (!cpu->is_32bit)
2763                    return;
2764    
2765            if (n_back < 4)
2766                    return;
2767    
2768            /*  Avoid "overlapping" instruction combinations:  */
2769            if (ic[-4].f == instr(multi_sw_3_be)||ic[-3].f == instr(multi_sw_3_be)||
2770                ic[-4].f == instr(multi_sw_3_le)||ic[-3].f == instr(multi_sw_3_le))
2771                    return;
2772    
2773            if (ic[-2].f == ic[0].f && ic[-1].f == ic[0].f &&
2774                ic[-2].arg[1] == ic[0].arg[1] &&
2775                ic[-1].arg[1] == ic[0].arg[1]) {
2776                    if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
2777                            ic[-2].f = instr(multi_sw_3_le);
2778                    else
2779                            ic[-2].f = instr(multi_sw_3_be);
2780                    combined;
2781            }
2782    }
2783    
2784    
2785    /*
2786     *  Combine:  NetBSD/pmax 3.0 R2000/R3000 physical cache invalidation loop
2787     *
2788     *  Instruction cache loop:
2789     *
2790     *  ic[-8]      mtc0    rV,status
2791     *     -7       nop
2792     *     -6       nop
2793     *     -5  s:   addiu   rX,rX,4
2794     *     -4       bne     rY,rX,s
2795     *     -3       sb      zr,-4(rX)
2796     *     -2       nop
2797     *     -1       nop
2798     *      0       mtc0    rT,status
2799     */
2800    void COMBINE(netbsd_r3k_cache_inv)(struct cpu *cpu,
2801            struct mips_instr_call *ic, int low_addr)
2802    {
2803            int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
2804                & (MIPS_IC_ENTRIES_PER_PAGE - 1);
2805    
2806            if (n_back < 8)
2807                    return;
2808    
2809            if (ic[-8].f == instr(mtc0) && ic[-8].arg[1] == COP0_STATUS &&
2810                ic[-7].f == instr(nop) && ic[-6].f == instr(nop) &&
2811                ic[-5].f == instr(addiu) && ic[-5].arg[0] == ic[-5].arg[1] &&
2812                (int32_t)ic[-5].arg[2] == 4 && ic[-4].f == instr(bne_samepage) &&
2813                ic[-4].arg[0] == ic[-5].arg[0] && ic[-4].arg[0] != ic[-4].arg[1] &&
2814                ic[-4].arg[2] == (size_t) &ic[-5] &&
2815                ic[-3].arg[1] == ic[-5].arg[0] &&
2816                ic[-2].f == instr(nop) && ic[-1].f == instr(nop)) {
2817                    ic[-8].f = instr(netbsd_r3k_picache_do_inv);
2818                    combined;
2819            }
2820    }
2821    
2822    
2823    /*
2824     *  Combine: something ending with a nop.
2825     *
2826     *      NetBSD's strlen core.
2827     *      [Conditional] branch, followed by nop.
2828     */
2829    void COMBINE(nop)(struct cpu *cpu, struct mips_instr_call *ic, int low_addr)
2830    {
2831            int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
2832                & (MIPS_IC_ENTRIES_PER_PAGE - 1);
2833    
2834    #ifdef MODE32
2835            if (n_back < 3)
2836                    return;
2837    
2838            if ((ic[-3].f == mips32_loadstore[1] ||
2839                ic[-3].f == mips32_loadstore[16 + 1]) &&
2840                ic[-3].arg[2] == 0 &&
2841                ic[-3].arg[0] == ic[-1].arg[0] && ic[-3].arg[1] == ic[-2].arg[0] &&
2842                ic[-2].arg[0] == ic[-2].arg[1] && ic[-2].arg[2] == 1 &&
2843                ic[-2].f == instr(addiu) && ic[-1].arg[2] == (size_t) &ic[-3] &&
2844                ic[-1].arg[1] == (size_t) &cpu->cd.mips.gpr[MIPS_GPR_ZERO] &&
2845                ic[-1].f == instr(bne_samepage)) {
2846                    ic[-3].f = instr(netbsd_strlen);
2847                    combined;
2848                    return;
2849            }
2850    #endif
2851    
2852            if (n_back < 1)
2853                    return;
2854    
2855            if (ic[-1].f == instr(bne_samepage)) {
2856                    ic[-1].f = instr(bne_samepage_nop);
2857                    combined;
2858                    return;
2859            }
2860    
2861            if (ic[-1].f == instr(beq_samepage)) {
2862                    ic[-1].f = instr(beq_samepage_nop);
2863                    combined;
2864                    return;
2865            }
2866    
2867            /*  TODO: other branches that are followed by nop should be here  */
2868    }
2869    
2870    
2871    /*
2872     *  Combine:
2873     *
2874     *      [Conditional] branch, followed by addiu.
2875     *      lui + addiu.
2876     */
2877    void COMBINE(addiu)(struct cpu *cpu, struct mips_instr_call *ic, int low_addr)
2878    {
2879            int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
2880                & (MIPS_IC_ENTRIES_PER_PAGE - 1);
2881    
2882          if (n_back < 1)          if (n_back < 1)
2883                  return;                  return;
2884    
2885            if (ic[-1].f == instr(set) && ic[-1].arg[0] == ic[0].arg[0] &&
2886                ic[0].arg[0] == ic[0].arg[1]) {
2887                    ic[-1].f = instr(lui_32bit);
2888                    ic[-1].arg[2] = (int32_t) (ic[-1].arg[1] + ic[0].arg[2]);
2889                    combined;
2890                    return;
2891            }
2892    
2893          if (ic[-1].f == instr(b_samepage)) {          if (ic[-1].f == instr(b_samepage)) {
2894                  ic[-1].f = instr(b_samepage_addiu);                  ic[-1].f = instr(b_samepage_addiu);
2895                  combined;                  combined;
2896                    return;
2897            }
2898    
2899            if (ic[-1].f == instr(beq_samepage)) {
2900                    ic[-1].f = instr(beq_samepage_addiu);
2901                    combined;
2902                    return;
2903            }
2904    
2905            if (ic[-1].f == instr(bne_samepage)) {
2906                    ic[-1].f = instr(bne_samepage_addiu);
2907                    combined;
2908                    return;
2909            }
2910    
2911            if (ic[-1].f == instr(jr_ra)) {
2912                    ic[-1].f = instr(jr_ra_addiu);
2913                    combined;
2914                    return;
2915          }          }
2916    
2917          /*  TODO: other branches that are followed by addiu should be here  */          /*  TODO: other branches that are followed by addiu should be here  */
2918  }  }
2919    
2920    
2921    /*
2922     *  Combine: [Conditional] branch, followed by daddiu.
2923     */
2924    void COMBINE(b_daddiu)(struct cpu *cpu, struct mips_instr_call *ic,
2925            int low_addr)
2926    {
2927            int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
2928                & (MIPS_IC_ENTRIES_PER_PAGE - 1);
2929    
2930            if (n_back < 1)
2931                    return;
2932    
2933            if (ic[-1].f == instr(b_samepage)) {
2934                    ic[-1].f = instr(b_samepage_daddiu);
2935                    combined;
2936            }
2937    
2938            /*  TODO: other branches that are followed by daddiu should be here  */
2939    }
2940    
2941    
2942  /*****************************************************************************/  /*****************************************************************************/
2943    
2944    
2945  /*  /*
2946   *  mips_instr_to_be_translated():   *  mips_instr_to_be_translated():
2947   *   *
2948   *  Translate an instruction word into an mips_instr_call. ic is filled in with   *  Translate an instruction word into a mips_instr_call. ic is filled in with
2949   *  valid data for the translated instruction, or a "nothing" instruction if   *  valid data for the translated instruction, or a "nothing" instruction if
2950   *  there was a translation failure. The newly translated instruction is then   *  there was a translation failure. The newly translated instruction is then
2951   *  executed.   *  executed.
# Line 582  X(to_be_translated) Line 2956  X(to_be_translated)
2956          uint32_t iword, imm;          uint32_t iword, imm;
2957          unsigned char *page;          unsigned char *page;
2958          unsigned char ib[4];          unsigned char ib[4];
 #ifdef DYNTRANS_BACKEND  
         int simple = 0;  
 #endif  
2959          int main_opcode, rt, rs, rd, sa, s6, x64 = 0;          int main_opcode, rt, rs, rd, sa, s6, x64 = 0;
2960          int in_crosspage_delayslot = 0;          int in_crosspage_delayslot = 0;
         int delay_slot_danger = 1;  
2961          void (*samepage_function)(struct cpu *, struct mips_instr_call *);          void (*samepage_function)(struct cpu *, struct mips_instr_call *);
2962            int store, signedness, size;
2963    
2964          /*  Figure out the (virtual) address of the instruction:  */          /*  Figure out the (virtual) address of the instruction:  */
2965          low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)          low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
2966              / sizeof(struct mips_instr_call);              / sizeof(struct mips_instr_call);
2967    
2968          /*  Special case for branch with delayslot on the next page:  */          /*  Special case for branch with delayslot on the next page:  */
2969          if (low_pc >= MIPS_IC_ENTRIES_PER_PAGE) {          if (cpu->delay_slot == TO_BE_DELAYED && low_pc == 0) {
2970                  /*  fatal("[ TEMPORARY delay-slot translation ]\n");  */                  /*  fatal("[ delay-slot translation across page "
2971                  low_pc = 0;                      "boundary ]\n");  */
2972                  in_crosspage_delayslot = 1;                  in_crosspage_delayslot = 1;
2973          }          }
2974    
2975          addr = cpu->pc & ~((MIPS_IC_ENTRIES_PER_PAGE-1)          addr = cpu->pc & ~((MIPS_IC_ENTRIES_PER_PAGE-1)
2976              << MIPS_INSTR_ALIGNMENT_SHIFT);              << MIPS_INSTR_ALIGNMENT_SHIFT);
2977          addr += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);          addr += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
2978          cpu->pc = addr;          cpu->pc = (MODE_int_t)addr;
2979          addr &= ~((1 << MIPS_INSTR_ALIGNMENT_SHIFT) - 1);          addr &= ~((1 << MIPS_INSTR_ALIGNMENT_SHIFT) - 1);
2980    
2981          /*  Read the instruction word from memory:  */          /*  Read the instruction word from memory:  */
2982    #ifdef MODE32
2983          page = cpu->cd.mips.host_load[(uint32_t)addr >> 12];          page = cpu->cd.mips.host_load[(uint32_t)addr >> 12];
2984    #else
2985            {
2986                    const uint32_t mask1 = (1 << DYNTRANS_L1N) - 1;
2987                    const uint32_t mask2 = (1 << DYNTRANS_L2N) - 1;
2988                    const uint32_t mask3 = (1 << DYNTRANS_L3N) - 1;
2989                    uint32_t x1 = (addr >> (64-DYNTRANS_L1N)) & mask1;
2990                    uint32_t x2 = (addr >> (64-DYNTRANS_L1N-DYNTRANS_L2N)) & mask2;
2991                    uint32_t x3 = (addr >> (64-DYNTRANS_L1N-DYNTRANS_L2N-
2992                        DYNTRANS_L3N)) & mask3;
2993                    struct DYNTRANS_L2_64_TABLE *l2 = cpu->cd.mips.l1_64[x1];
2994                    struct DYNTRANS_L3_64_TABLE *l3 = l2->l3[x2];
2995                    page = l3->host_load[x3];
2996            }
2997    #endif
2998    
2999          if (page != NULL) {          if (page != NULL) {
3000                  /*  fatal("TRANSLATION HIT!\n");  */                  /*  fatal("TRANSLATION HIT!\n");  */
3001                  memcpy(ib, page + (addr & 0xfff), sizeof(ib));                  memcpy(ib, page + (addr & 0xffc), sizeof(ib));
3002          } else {          } else {
3003                  /*  fatal("TRANSLATION MISS!\n");  */                  /*  fatal("TRANSLATION MISS!\n");  */
3004                  if (!cpu->memory_rw(cpu, cpu->mem, addr, ib,                  if (!cpu->memory_rw(cpu, cpu->mem, addr, ib,
3005                      sizeof(ib), MEM_READ, CACHE_INSTRUCTION)) {                      sizeof(ib), MEM_READ, CACHE_INSTRUCTION)) {
3006                          fatal("to_be_translated(): "                          fatal("to_be_translated(): read failed: TODO\n");
                             "read failed: TODO\n");  
3007                          goto bad;                          goto bad;
3008                  }                  }
3009          }          }
# Line 630  X(to_be_translated) Line 3015  X(to_be_translated)
3015          else          else
3016                  iword = BE32_TO_HOST(iword);                  iword = BE32_TO_HOST(iword);
3017    
         /*  Is the instruction in the delay slot known to be safe?  */  
         if ((addr & 0xffc) < 0xffc) {  
                 /*  TODO: check the instruction  */  
                 delay_slot_danger = 0;  
         }  
   
3018    
3019  #define DYNTRANS_TO_BE_TRANSLATED_HEAD  #define DYNTRANS_TO_BE_TRANSLATED_HEAD
3020  #include "cpu_dyntrans.c"  #include "cpu_dyntrans.c"
# Line 645  X(to_be_translated) Line 3024  X(to_be_translated)
3024          /*          /*
3025           *  Translate the instruction:           *  Translate the instruction:
3026           *           *
3027           *  NOTE: _NEVER_ allow writes to the zero register; all such           *  NOTE: _NEVER_ allow writes to the zero register; all instructions
3028           *  instructions should be made into NOPs.           *  that use the zero register as their destination should be treated
3029             *  as NOPs, except those that access memory (they should use the
3030             *  scratch register instead).
3031           */           */
3032    
3033          main_opcode = iword >> 26;          main_opcode = iword >> 26;
# Line 663  X(to_be_translated) Line 3044  X(to_be_translated)
3044                  switch (s6) {                  switch (s6) {
3045    
3046                  case SPECIAL_SLL:                  case SPECIAL_SLL:
3047                    case SPECIAL_SLLV:
3048                  case SPECIAL_SRL:                  case SPECIAL_SRL:
3049                    case SPECIAL_SRLV:
3050                  case SPECIAL_SRA:                  case SPECIAL_SRA:
3051                    case SPECIAL_SRAV:
3052                    case SPECIAL_DSRL:
3053                    case SPECIAL_DSRLV:
3054                    case SPECIAL_DSRL32:
3055                    case SPECIAL_DSLL:
3056                    case SPECIAL_DSLLV:
3057                    case SPECIAL_DSLL32:
3058                    case SPECIAL_DSRA:
3059                    case SPECIAL_DSRAV:
3060                    case SPECIAL_DSRA32:
3061                          switch (s6) {                          switch (s6) {
3062                          case SPECIAL_SLL:  ic->f = instr(sll); break;                          case SPECIAL_SLL:  ic->f = instr(sll); break;
3063                            case SPECIAL_SLLV: ic->f = instr(sllv); sa = -1; break;
3064                          case SPECIAL_SRL:  ic->f = instr(srl); break;                          case SPECIAL_SRL:  ic->f = instr(srl); break;
3065                            case SPECIAL_SRLV: ic->f = instr(srlv); sa = -1; break;
3066                          case SPECIAL_SRA:  ic->f = instr(sra); break;                          case SPECIAL_SRA:  ic->f = instr(sra); break;
3067                            case SPECIAL_SRAV: ic->f = instr(srav); sa = -1; break;
3068                            case SPECIAL_DSRL: ic->f = instr(dsrl); x64=1; break;
3069                            case SPECIAL_DSRLV:ic->f = instr(dsrlv);
3070                                               x64 = 1; sa = -1; break;
3071                            case SPECIAL_DSRL32:ic->f= instr(dsrl); x64=1;
3072                                               sa += 32; break;
3073                            case SPECIAL_DSLL: ic->f = instr(dsll); x64=1; break;
3074                            case SPECIAL_DSLLV:ic->f = instr(dsllv);
3075                                               x64 = 1; sa = -1; break;
3076                            case SPECIAL_DSLL32:ic->f= instr(dsll); x64=1;
3077                                               sa += 32; break;
3078                            case SPECIAL_DSRA: ic->f = instr(dsra); x64=1; break;
3079                            case SPECIAL_DSRAV:ic->f = instr(dsrav);
3080                                               x64 = 1; sa = -1; break;
3081                            case SPECIAL_DSRA32:ic->f = instr(dsra); x64=1;
3082                                               sa += 32; break;
3083                          }                          }
3084                          ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];                          ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
3085                          ic->arg[1] = sa;                          if (sa >= 0)
3086                                    ic->arg[1] = sa;
3087                            else
3088                                    ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rs];
3089                          ic->arg[2] = (size_t)&cpu->cd.mips.gpr[rd];                          ic->arg[2] = (size_t)&cpu->cd.mips.gpr[rd];
3090                          if (rd == MIPS_GPR_ZERO)                          if (rd == MIPS_GPR_ZERO)
3091                                  ic->f = instr(nop);                                  ic->f = instr(nop);
3092                          break;                          break;
3093    
3094                    case SPECIAL_ADD:
3095                  case SPECIAL_ADDU:                  case SPECIAL_ADDU:
3096                    case SPECIAL_SUB:
3097                  case SPECIAL_SUBU:                  case SPECIAL_SUBU:
3098                    case SPECIAL_DADD:
3099                  case SPECIAL_DADDU:                  case SPECIAL_DADDU:
3100                    case SPECIAL_DSUB:
3101                  case SPECIAL_DSUBU:                  case SPECIAL_DSUBU:
3102                  case SPECIAL_SLT:                  case SPECIAL_SLT:
3103                  case SPECIAL_SLTU:                  case SPECIAL_SLTU:
3104                    case SPECIAL_AND:
3105                  case SPECIAL_OR:                  case SPECIAL_OR:
3106                  case SPECIAL_XOR:                  case SPECIAL_XOR:
3107                  case SPECIAL_NOR:                  case SPECIAL_NOR:
3108                    case SPECIAL_MOVN:
3109                    case SPECIAL_MOVZ:
3110                  case SPECIAL_MFHI:                  case SPECIAL_MFHI:
3111                  case SPECIAL_MFLO:                  case SPECIAL_MFLO:
3112                  case SPECIAL_MTHI:                  case SPECIAL_MTHI:
3113                  case SPECIAL_MTLO:                  case SPECIAL_MTLO:
3114                    case SPECIAL_DIV:
3115                    case SPECIAL_DIVU:
3116                    case SPECIAL_DDIV:
3117                    case SPECIAL_DDIVU:
3118                    case SPECIAL_MULT:
3119                    case SPECIAL_MULTU:
3120                    case SPECIAL_DMULT:
3121                    case SPECIAL_DMULTU:
3122                    case SPECIAL_TGE:
3123                    case SPECIAL_TGEU:
3124                    case SPECIAL_TLT:
3125                    case SPECIAL_TLTU:
3126                    case SPECIAL_TEQ:
3127                    case SPECIAL_TNE:
3128                          switch (s6) {                          switch (s6) {
3129                            case SPECIAL_ADD:   ic->f = instr(add); break;
3130                          case SPECIAL_ADDU:  ic->f = instr(addu); break;                          case SPECIAL_ADDU:  ic->f = instr(addu); break;
3131                            case SPECIAL_SUB:   ic->f = instr(sub); break;
3132                          case SPECIAL_SUBU:  ic->f = instr(subu); break;                          case SPECIAL_SUBU:  ic->f = instr(subu); break;
3133                            case SPECIAL_DADD:  ic->f = instr(dadd); x64=1; break;
3134                          case SPECIAL_DADDU: ic->f = instr(daddu); x64=1; break;                          case SPECIAL_DADDU: ic->f = instr(daddu); x64=1; break;
3135                            case SPECIAL_DSUB:  ic->f = instr(dsub); x64=1; break;
3136                          case SPECIAL_DSUBU: ic->f = instr(dsubu); x64=1; break;                          case SPECIAL_DSUBU: ic->f = instr(dsubu); x64=1; break;
3137                          case SPECIAL_SLT:   ic->f = instr(slt); break;                          case SPECIAL_SLT:   ic->f = instr(slt); break;
3138                          case SPECIAL_SLTU:  ic->f = instr(sltu); break;                          case SPECIAL_SLTU:  ic->f = instr(sltu); break;
3139                            case SPECIAL_AND:   ic->f = instr(and); break;
3140                          case SPECIAL_OR:    ic->f = instr(or); break;                          case SPECIAL_OR:    ic->f = instr(or); break;
3141                          case SPECIAL_XOR:   ic->f = instr(xor); break;                          case SPECIAL_XOR:   ic->f = instr(xor); break;
3142                          case SPECIAL_NOR:   ic->f = instr(nor); break;                          case SPECIAL_NOR:   ic->f = instr(nor); break;
# Line 704  X(to_be_translated) Line 3144  X(to_be_translated)
3144                          case SPECIAL_MFLO:  ic->f = instr(mov); break;                          case SPECIAL_MFLO:  ic->f = instr(mov); break;
3145                          case SPECIAL_MTHI:  ic->f = instr(mov); break;                          case SPECIAL_MTHI:  ic->f = instr(mov); break;
3146                          case SPECIAL_MTLO:  ic->f = instr(mov); break;                          case SPECIAL_MTLO:  ic->f = instr(mov); break;
3147                            case SPECIAL_DIV:   ic->f = instr(div); break;
3148                            case SPECIAL_DIVU:  ic->f = instr(divu); break;
3149                            case SPECIAL_DDIV:  ic->f = instr(ddiv); x64=1; break;
3150                            case SPECIAL_DDIVU: ic->f = instr(ddivu); x64=1; break;
3151                            case SPECIAL_MULT : ic->f = instr(mult); break;
3152                            case SPECIAL_MULTU: ic->f = instr(multu); break;
3153                            case SPECIAL_DMULT: ic->f = instr(dmult); x64=1; break;
3154                            case SPECIAL_DMULTU:ic->f = instr(dmultu); x64=1; break;
3155                            case SPECIAL_TGE:   ic->f = instr(tge); break;
3156                            case SPECIAL_TGEU:  ic->f = instr(tgeu); break;
3157                            case SPECIAL_TLT:   ic->f = instr(tlt); break;
3158                            case SPECIAL_TLTU:  ic->f = instr(tltu); break;
3159                            case SPECIAL_TEQ:   ic->f = instr(teq); break;
3160                            case SPECIAL_TNE:   ic->f = instr(tne); break;
3161                            case SPECIAL_MOVN:  ic->f = instr(movn); break;
3162                            case SPECIAL_MOVZ:  ic->f = instr(movz); break;
3163                          }                          }
3164                          ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];                          ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];
3165                          ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rt];                          ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rt];
# Line 722  X(to_be_translated) Line 3178  X(to_be_translated)
3178                                  ic->arg[2] = (size_t)&cpu->cd.mips.lo;                                  ic->arg[2] = (size_t)&cpu->cd.mips.lo;
3179                                  break;                                  break;
3180                          }                          }
3181                          /*  rd==0 => nop:  */                          /*  Special cases for rd:  */
3182                          switch (s6) {                          switch (s6) {
3183                          case SPECIAL_MTHI:                          case SPECIAL_MTHI:
3184                          case SPECIAL_MTLO:                          case SPECIAL_MTLO:
3185                                  /*  These instructions don't use rd.  */                          case SPECIAL_DIV:
3186                                  break;                          case SPECIAL_DIVU:
3187                          default:if (rd == MIPS_GPR_ZERO)                          case SPECIAL_DDIV:
3188                                          ic->f = instr(nop);                          case SPECIAL_DDIVU:
                         }  
                         break;  
   
                 case SPECIAL_MULT:  
                 case SPECIAL_MULTU:  
                         switch (s6) {  
                         case SPECIAL_MULT : ic->f = instr(mult); break;  
                         case SPECIAL_MULTU: ic->f = instr(multu); break;  
                         }  
                         ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];  
                         ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rt];  
                         /*  rd is ignored for most of these instructions,  
                             except for multiplication:  */  
                         switch (s6) {  
3189                          case SPECIAL_MULT:                          case SPECIAL_MULT:
3190                          case SPECIAL_MULTU:                          case SPECIAL_MULTU:
3191                          case SPECIAL_DMULT:                          case SPECIAL_DMULT:
3192                          case SPECIAL_DMULTU:                          case SPECIAL_DMULTU:
3193                                  ic->arg[2] = (size_t)&cpu->cd.mips.gpr[rd];                          case SPECIAL_TGE:
3194                            case SPECIAL_TGEU:
3195                            case SPECIAL_TLT:
3196                            case SPECIAL_TLTU:
3197                            case SPECIAL_TEQ:
3198                            case SPECIAL_TNE:
3199                                    if (s6 == SPECIAL_MULT && rd != MIPS_GPR_ZERO) {
3200                                            if (cpu->cd.mips.cpu_type.rev ==
3201                                                MIPS_R5900) {
3202                                                    ic->f = instr(mult_r5900);
3203                                                    break;
3204                                            }
3205                                            break;
3206                                    }
3207                                    if (s6 == SPECIAL_MULTU && rd!=MIPS_GPR_ZERO) {
3208                                            if (cpu->cd.mips.cpu_type.rev ==
3209                                                MIPS_R5900) {
3210                                                    ic->f = instr(multu_r5900);
3211                                                    break;
3212                                            }
3213                                    }
3214                                  if (rd != MIPS_GPR_ZERO) {                                  if (rd != MIPS_GPR_ZERO) {
3215                                          fatal("TODO: mult with rd NON-zero\n");                                          fatal("TODO: rd NON-zero\n");
3216                                          goto bad;                                          goto bad;
3217                                  }                                  }
3218                                    /*  These instructions don't use rd.  */
3219                                  break;                                  break;
3220                            default:if (rd == MIPS_GPR_ZERO)
3221                                            ic->f = instr(nop);
3222                          }                          }
3223                          break;                          break;
3224    
# Line 761  X(to_be_translated) Line 3226  X(to_be_translated)
3226                  case SPECIAL_JALR:                  case SPECIAL_JALR:
3227                          ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];                          ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];
3228                          ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rd];                          ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rd];
3229                          if (main_opcode == SPECIAL_JALR && rd == MIPS_GPR_ZERO)                          if (s6 == SPECIAL_JALR && rd == MIPS_GPR_ZERO)
3230                                  main_opcode = SPECIAL_JR;                                  s6 = SPECIAL_JR;
3231                          ic->arg[2] = (addr & 0xffc) + 4;                          ic->arg[2] = (addr & 0xffc) + 8;
3232                          switch (main_opcode) {                          switch (s6) {
3233                          case SPECIAL_JR:                          case SPECIAL_JR:
3234                                  if (rs == MIPS_GPR_RA) {                                  if (rs == MIPS_GPR_RA) {
3235                                          if (cpu->machine->show_trace_tree)                                          if (cpu->machine->show_trace_tree)
# Line 782  X(to_be_translated) Line 3247  X(to_be_translated)
3247                                          ic->f = instr(jalr);                                          ic->f = instr(jalr);
3248                                  break;                                  break;
3249                          }                          }
3250                          if (in_crosspage_delayslot) {                          if (cpu->delay_slot) {
3251                                  fatal("[ WARNING: branch in delay slot? ]\n");                                  fatal("TODO: branch in delay slot? (1)\n");
3252                                  ic->f = instr(nop);                                  goto bad;
3253                            }
3254                            break;
3255    
3256                    case SPECIAL_SYSCALL:
3257                            if (((iword >> 6) & 0xfffff) == 0x30378) {
3258                                    /*  "Magic trap" for PROM emulation:  */
3259                                    ic->f = instr(promemul);
3260                            } else {
3261                                    ic->f = instr(syscall);
3262                          }                          }
3263                          break;                          break;
3264    
3265                    case SPECIAL_BREAK:
3266                            ic->f = instr(break);
3267                            break;
3268    
3269                  case SPECIAL_SYNC:                  case SPECIAL_SYNC:
3270                          ic->f = instr(nop);                          ic->f = instr(nop);
3271                          break;                          break;
# Line 798  X(to_be_translated) Line 3276  X(to_be_translated)
3276    
3277          case HI6_BEQ:          case HI6_BEQ:
3278          case HI6_BNE:          case HI6_BNE:
3279            case HI6_BEQL:
3280            case HI6_BNEL:
3281            case HI6_BLEZ:
3282            case HI6_BLEZL:
3283            case HI6_BGTZ:
3284            case HI6_BGTZL:
3285                  samepage_function = NULL;  /*  get rid of a compiler warning  */                  samepage_function = NULL;  /*  get rid of a compiler warning  */
3286                  switch (main_opcode) {                  switch (main_opcode) {
3287                  case HI6_BEQ:                  case HI6_BEQ:
# Line 812  X(to_be_translated) Line 3296  X(to_be_translated)
3296                  case HI6_BNE:                  case HI6_BNE:
3297                          ic->f = instr(bne);                          ic->f = instr(bne);
3298                          samepage_function = instr(bne_samepage);                          samepage_function = instr(bne_samepage);
3299                            break;
3300                    case HI6_BEQL:
3301                            ic->f = instr(beql);
3302                            samepage_function = instr(beql_samepage);
3303                            /*  Special case: comparing a register with itself:  */
3304                            if (rs == rt) {
3305                                    ic->f = instr(b);
3306                                    samepage_function = instr(b_samepage);
3307                            }
3308                            break;
3309                    case HI6_BNEL:
3310                            ic->f = instr(bnel);
3311                            samepage_function = instr(bnel_samepage);
3312                            break;
3313                    case HI6_BLEZ:
3314                            ic->f = instr(blez);
3315                            samepage_function = instr(blez_samepage);
3316                            break;
3317                    case HI6_BLEZL:
3318                            ic->f = instr(blezl);
3319                            samepage_function = instr(blezl_samepage);
3320                            break;
3321                    case HI6_BGTZ:
3322                            ic->f = instr(bgtz);
3323                            samepage_function = instr(bgtz_samepage);
3324                            break;
3325                    case HI6_BGTZL:
3326                            ic->f = instr(bgtzl);
3327                            samepage_function = instr(bgtzl_samepage);
3328                            break;
3329                  }                  }
3330                  ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];                  ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];
3331                  ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rt];                  ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rt];
3332                  ic->arg[2] = (imm << MIPS_INSTR_ALIGNMENT_SHIFT)                  ic->arg[2] = (int32_t) ( (imm << MIPS_INSTR_ALIGNMENT_SHIFT)
3333                      + (addr & 0xffc) + 4;                      + (addr & 0xffc) + 4 );
3334                  /*  Is the offset from the start of the current page still                  /*  Is the offset from the start of the current page still
3335                      within the same page? Then use the samepage_function:  */                      within the same page? Then use the samepage_function:  */
3336                  if ((uint32_t)ic->arg[2] < ((MIPS_IC_ENTRIES_PER_PAGE - 1)                  if ((uint32_t)ic->arg[2] < ((MIPS_IC_ENTRIES_PER_PAGE - 1)
# Line 826  X(to_be_translated) Line 3340  X(to_be_translated)
3340                              & (MIPS_IC_ENTRIES_PER_PAGE - 1)));                              & (MIPS_IC_ENTRIES_PER_PAGE - 1)));
3341                          ic->f = samepage_function;                          ic->f = samepage_function;
3342                  }                  }
3343                  if (in_crosspage_delayslot) {                  if (cpu->delay_slot) {
3344                          fatal("[ WARNING: branch in delay slot? ]\n");                          fatal("TODO: branch in delay slot? (2)\n");
3345                          ic->f = instr(nop);                          goto bad;
3346                  }                  }
3347                  break;                  break;
3348    
3349            case HI6_ADDI:
3350          case HI6_ADDIU:          case HI6_ADDIU:
3351            case HI6_SLTI:
3352            case HI6_SLTIU:
3353            case HI6_DADDI:
3354          case HI6_DADDIU:          case HI6_DADDIU:
3355          case HI6_ANDI:          case HI6_ANDI:
3356          case HI6_ORI:          case HI6_ORI:
# Line 841  X(to_be_translated) Line 3359  X(to_be_translated)
3359                  ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rt];                  ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rt];
3360                  if (main_opcode == HI6_ADDI ||                  if (main_opcode == HI6_ADDI ||
3361                      main_opcode == HI6_ADDIU ||                      main_opcode == HI6_ADDIU ||
3362                        main_opcode == HI6_SLTI ||
3363                        main_opcode == HI6_SLTIU ||
3364                      main_opcode == HI6_DADDI ||                      main_opcode == HI6_DADDI ||
3365                      main_opcode == HI6_DADDIU)                      main_opcode == HI6_DADDIU)
3366                          ic->arg[2] = (int16_t)iword;                          ic->arg[2] = (int16_t)iword;
3367                  else                  else
3368                          ic->arg[2] = (uint16_t)iword;                          ic->arg[2] = (uint16_t)iword;
3369    
3370                  switch (main_opcode) {                  switch (main_opcode) {
3371                    case HI6_ADDI:    ic->f = instr(addi); break;
3372                  case HI6_ADDIU:   ic->f = instr(addiu); break;                  case HI6_ADDIU:   ic->f = instr(addiu); break;
3373                    case HI6_SLTI:    ic->f = instr(slti); break;
3374                    case HI6_SLTIU:   ic->f = instr(sltiu); break;
3375                    case HI6_DADDI:   ic->f = instr(daddi); x64 = 1; break;
3376                  case HI6_DADDIU:  ic->f = instr(daddiu); x64 = 1; break;                  case HI6_DADDIU:  ic->f = instr(daddiu); x64 = 1; break;
3377                  case HI6_ANDI:    ic->f = instr(andi); break;                  case HI6_ANDI:    ic->f = instr(andi); break;
3378                  case HI6_ORI:     ic->f = instr(ori); break;                  case HI6_ORI:     ic->f = instr(ori); break;
3379                  case HI6_XORI:    ic->f = instr(xori); break;                  case HI6_XORI:    ic->f = instr(xori); break;
3380                  }                  }
3381    
3382                    if (ic->arg[2] == 0) {
3383                            if ((cpu->is_32bit && ic->f == instr(addiu)) ||
3384                                (!cpu->is_32bit && ic->f == instr(daddiu))) {
3385                                    ic->f = instr(mov);
3386                                    ic->arg[2] = ic->arg[1];
3387                            }
3388                    }
3389    
3390                  if (rt == MIPS_GPR_ZERO)                  if (rt == MIPS_GPR_ZERO)
3391                          ic->f = instr(nop);                          ic->f = instr(nop);
3392    
3393                  if (ic->f == instr(addiu))                  if (ic->f == instr(addiu))
3394                          cpu->cd.mips.combination_check = COMBINE(b_addiu);                          cpu->cd.mips.combination_check = COMBINE(addiu);
3395                    if (ic->f == instr(daddiu))
3396                            cpu->cd.mips.combination_check = COMBINE(b_daddiu);
3397                  break;                  break;
3398    
3399          case HI6_LUI:          case HI6_LUI:
3400                  ic->f = instr(set);                  ic->f = instr(set);
3401                  ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];                  ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
3402                  ic->arg[1] = imm << 16;                  ic->arg[1] = (int32_t) (imm << 16);
3403                    /*  NOTE: Don't use arg[2] here. It can be used with
3404                        instruction combinations, to do lui + addiu, etc.  */
3405                  if (rt == MIPS_GPR_ZERO)                  if (rt == MIPS_GPR_ZERO)
3406                          ic->f = instr(nop);                          ic->f = instr(nop);
3407                  break;                  break;
3408    
3409            case HI6_J:
3410            case HI6_JAL:
3411                    switch (main_opcode) {
3412                    case HI6_J:
3413                            ic->f = instr(j);
3414                            break;
3415                    case HI6_JAL:
3416                            if (cpu->machine->show_trace_tree)
3417                                    ic->f = instr(jal_trace);
3418                            else
3419                                    ic->f = instr(jal);
3420                            break;
3421                    }
3422                    ic->arg[0] = (iword & 0x03ffffff) << 2;
3423                    ic->arg[1] = (addr & 0xffc) + 8;
3424                    if (cpu->delay_slot) {
3425                            fatal("TODO: branch in delay slot (=%i)? (3); addr=%016"
3426                                PRIx64" iword=%08"PRIx32"\n", cpu->delay_slot,
3427                                (uint64_t)addr, iword);
3428                            goto bad;
3429                    }
3430                    break;
3431    
3432          case HI6_COP0:          case HI6_COP0:
3433                    /*  TODO: Is checking bit 25 enough, or perhaps all bits
3434                        25..21 must be checked?  */
3435                    if ((iword >> 25) & 1) {
3436                            ic->arg[2] = addr & 0xffc;
3437                            switch (iword & 0xff) {
3438                            case COP0_TLBR:
3439                                    ic->f = instr(tlbr);
3440                                    break;
3441                            case COP0_TLBWI:
3442                            case COP0_TLBWR:
3443                                    ic->f = instr(tlbw);
3444                                    ic->arg[0] = (iword & 0xff) == COP0_TLBWR;
3445                                    break;
3446                            case COP0_TLBP:
3447                                    ic->f = instr(tlbp);
3448                                    break;
3449                            case COP0_RFE:
3450                                    ic->f = instr(rfe);
3451                                    break;
3452                            case COP0_ERET:
3453                                    ic->f = instr(eret);
3454                                    break;
3455                            case COP0_DERET:
3456                                    ic->f = instr(deret);
3457                                    break;
3458                            case COP0_IDLE:
3459                            case COP0_STANDBY:
3460                            case COP0_SUSPEND:
3461                            case COP0_HIBERNATE:
3462                                    /*  TODO  */
3463                                    ic->f = instr(nop);
3464                                    break;
3465                            case COP0_EI:
3466                                    if (cpu->cd.mips.cpu_type.rev == MIPS_R5900) {
3467                                            ic->f = instr(ei_r5900);
3468                                    } else
3469                                            goto bad;
3470                                    break;
3471                            case COP0_DI:
3472                                    if (cpu->cd.mips.cpu_type.rev == MIPS_R5900) {
3473                                            ic->f = instr(di_r5900);
3474                                    } else
3475                                            goto bad;
3476                                    break;
3477                            default:fatal("UNIMPLEMENTED cop0 (func 0x%02x)\n",
3478                                        iword & 0xff);
3479                                    goto bad;
3480                            }
3481                            break;
3482                    }
3483    
3484                  /*  rs contains the coprocessor opcode!  */                  /*  rs contains the coprocessor opcode!  */
3485                  switch (rs) {                  switch (rs) {
3486                    case COPz_CFCz:
3487                            ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
3488                            ic->arg[1] = rd + ((iword & 7) << 5);
3489                            ic->arg[2] = addr & 0xffc;
3490                            ic->f = instr(cfc0);
3491                            if (rt == MIPS_GPR_ZERO)
3492                                    ic->f = instr(nop);
3493                            break;
3494                  case COPz_MFCz:                  case COPz_MFCz:
3495                  case COPz_DMFCz:                  case COPz_DMFCz:
3496                          ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];                          ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
# Line 886  X(to_be_translated) Line 3506  X(to_be_translated)
3506                          ic->arg[1] = rd + ((iword & 7) << 5);                          ic->arg[1] = rd + ((iword & 7) << 5);
3507                          ic->arg[2] = addr & 0xffc;                          ic->arg[2] = addr & 0xffc;
3508                          ic->f = rs == COPz_MTCz? instr(mtc0) : instr(dmtc0);                          ic->f = rs == COPz_MTCz? instr(mtc0) : instr(dmtc0);
3509    
3510                            if (cpu->cd.mips.cpu_type.exc_model == EXC3K &&
3511                                rs == COPz_MTCz && rd == COP0_STATUS)
3512                                    cpu->cd.mips.combination_check =
3513                                        COMBINE(netbsd_r3k_cache_inv);
3514    
3515                          break;                          break;
3516                    case 8: if (iword == 0x4100ffff) {
3517                                    /*  R2020 DECstation write-loop thingy.  */
3518                                    ic->f = instr(nop);
3519                            } else {
3520                                    fatal("Unimplemented blah blah zzzz...\n");
3521                                    goto bad;
3522                            }
3523                            break;
3524                    
3525                  default:fatal("UNIMPLEMENTED cop0 (rs = %i)\n", rs);                  default:fatal("UNIMPLEMENTED cop0 (rs = %i)\n", rs);
3526                          goto bad;                          goto bad;
3527                  }                  }
3528                  break;                  break;
3529    
3530          case HI6_COP1:          case HI6_COP1:
3531                  /*  rs contains the coprocessor opcode!  */                  /*  Always cause a coprocessor unusable exception if
3532                        there is no floating point coprocessor:  */
3533                    if (cpu->cd.mips.cpu_type.flags & NOFPU ||
3534                        cpu->cd.mips.coproc[1] == NULL) {
3535                            ic->f = instr(cpu);
3536                            ic->arg[0] = 1;
3537                            break;
3538                    }
3539    
3540                    /*  Bits 25..21 are floating point main opcode:  */
3541                  switch (rs) {                  switch (rs) {
3542    
3543                    case COPz_BCzc:
3544                            /*  Conditional branch:  */
3545                            /*  TODO: Reimplement this in a faster way.  */
3546                            ic->f = instr(cop1_bc);
3547                            ic->arg[0] = (iword >> 18) & 7; /*  cc  */
3548                            ic->arg[1] = (iword >> 16) & 3; /*  nd, tf bits  */
3549                            ic->arg[2] = (int32_t) ((imm <<
3550                                MIPS_INSTR_ALIGNMENT_SHIFT) + (addr & 0xffc) + 4);
3551                            if (cpu->delay_slot) {
3552                                    fatal("TODO: branch in delay slot? (4)\n");
3553                                    goto bad;
3554                            }
3555                            if (cpu->cd.mips.cpu_type.isa_level <= 3 &&
3556                                ic->arg[0] != 0) {
3557                                    fatal("Attempt to execute a non-cc-0 BC*"
3558                                        " instruction on an isa level %i cpu. "
3559                                        "TODO: How should this be handled?\n",
3560                                        cpu->cd.mips.cpu_type.isa_level);
3561                                    goto bad;
3562                            }
3563    
3564                            break;
3565    
3566                    case COPz_DMFCz:
3567                    case COPz_DMTCz:
3568                            x64 = 1;
3569                            /*  FALL-THROUGH  */
3570                    case COP1_FMT_S:
3571                    case COP1_FMT_D:
3572                    case COP1_FMT_W:
3573                    case COP1_FMT_L:
3574                    case COP1_FMT_PS:
3575                  case COPz_CFCz:                  case COPz_CFCz:
3576                          ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];                  case COPz_CTCz:
3577                          ic->arg[1] = (size_t)&cpu->cd.mips.coproc[1]->fcr[rd];                  case COPz_MFCz:
3578                          ic->arg[2] = addr & 0xffc;                  case COPz_MTCz:
3579                          ic->f = instr(cfc1);                          /*  Fallback to slow pre-dyntrans code, for now.  */
3580                          if (rt == MIPS_GPR_ZERO)                          /*  TODO: Fix/optimize/rewrite.  */
3581                                  ic->f = instr(nop);                          ic->f = instr(cop1_slow);
3582                            ic->arg[0] = (uint32_t)iword & ((1 << 26) - 1);
3583                          break;                          break;
3584                  default:fatal("UNIMPLEMENTED cop1 (rs = %i)\n", rs);  
3585                    default:fatal("COP1 floating point opcode = 0x%02x\n", rs);
3586                          goto bad;                          goto bad;
3587                  }                  }
3588                  break;                  break;
3589    
3590            case HI6_COP2:
3591                    /*  Always cause a coprocessor unusable exception if
3592                        there is no coprocessor 2:  */
3593                    if (cpu->cd.mips.coproc[2] == NULL) {
3594                            ic->f = instr(cpu);
3595                            ic->arg[0] = 2;
3596                            break;
3597                    }
3598                    fatal("COP2 functionality not yet implemented\n");
3599                    goto bad;
3600                    break;
3601    
3602          case HI6_SPECIAL2:          case HI6_SPECIAL2:
3603                    if (cpu->cd.mips.cpu_type.rev == MIPS_R5900) {
3604                            /*  R5900, TX79/C790, have MMI instead of SPECIAL2:  */
3605                            int mmi_subopcode = (iword >> 6) & 0x1f;
3606    
3607                            switch (s6) {
3608    
3609                            case MMI_MADD:
3610                                    ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];
3611                                    ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rt];
3612                                    ic->arg[2] = (size_t)&cpu->cd.mips.gpr[rd];
3613                                    if (rd == MIPS_GPR_ZERO)
3614                                            ic->f = instr(madd);
3615                                    else
3616                                            ic->f = instr(madd_rd);
3617                                    break;
3618    
3619                            case MMI_MADDU:
3620                                    ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];
3621                                    ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rt];
3622                                    ic->arg[2] = (size_t)&cpu->cd.mips.gpr[rd];
3623                                    if (rd == MIPS_GPR_ZERO)
3624                                            ic->f = instr(maddu);
3625                                    else
3626                                            ic->f = instr(maddu_rd);
3627                                    break;
3628    
3629                            case MMI_MMI0:
3630                                    switch (mmi_subopcode) {
3631    
3632                                    case MMI0_PEXTLW:
3633                                            ic->arg[0] = rs;
3634                                            ic->arg[1] = rt;
3635                                            ic->arg[2] = rd;
3636                                            if (rd == MIPS_GPR_ZERO)
3637                                                    ic->f = instr(nop);
3638                                            else
3639                                                    ic->f = instr(pextlw);
3640                                            break;
3641    
3642                                    default:goto bad;
3643                                    }
3644                                    break;
3645    
3646                            case MMI_MMI3:
3647                                    switch (mmi_subopcode) {
3648    
3649                                    case MMI3_POR:
3650                                            ic->arg[0] = rs;
3651                                            ic->arg[1] = rt;
3652                                            ic->arg[2] = rd;
3653                                            if (rd == MIPS_GPR_ZERO)
3654                                                    ic->f = instr(nop);
3655                                            else
3656                                                    ic->f = instr(por);
3657                                            break;
3658    
3659                                    default:goto bad;
3660                                    }
3661                                    break;
3662    
3663                            default:goto bad;
3664                            }
3665                            break;
3666                    }
3667    
3668                    /*  TODO: is this correct? Or are there other non-MIPS32/64
3669                        MIPS processors that have support for SPECIAL2 opcodes?  */
3670                    if (cpu->cd.mips.cpu_type.isa_level < 32) {
3671                            ic->f = instr(reserved);
3672                            break;
3673                    }
3674    
3675                    /*  SPECIAL2:  */
3676                  switch (s6) {                  switch (s6) {
3677    
3678                    case SPECIAL2_MADD:
3679                    case SPECIAL2_MADDU:
3680                    case SPECIAL2_MSUB:
3681                    case SPECIAL2_MSUBU:
3682                            ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];
3683                            ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rt];
3684                            switch (s6) {
3685                            case SPECIAL2_MADD: ic->f = instr(madd); break;
3686                            case SPECIAL2_MADDU:ic->f = instr(maddu); break;
3687                            case SPECIAL2_MSUB: ic->f = instr(msub); break;
3688                            case SPECIAL2_MSUBU:ic->f = instr(msubu); break;
3689                            }
3690                            break;
3691    
3692                  case SPECIAL2_MUL:                  case SPECIAL2_MUL:
3693                          ic->f = instr(mul);                          ic->f = instr(mul);
3694                          ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];                          ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];
# Line 940  X(to_be_translated) Line 3718  X(to_be_translated)
3718                  }                  }
3719                  break;                  break;
3720    
3721            case HI6_REGIMM:
3722                    switch (rt) {
3723                    case REGIMM_BGEZ:
3724                    case REGIMM_BGEZL:
3725                    case REGIMM_BLTZ:
3726                    case REGIMM_BLTZL:
3727                    case REGIMM_BGEZAL:
3728                    case REGIMM_BGEZALL:
3729                    case REGIMM_BLTZAL:
3730                    case REGIMM_BLTZALL:
3731                            samepage_function = NULL;
3732                            switch (rt) {
3733                            case REGIMM_BGEZ:
3734                                    ic->f = instr(bgez);
3735                                    samepage_function = instr(bgez_samepage);
3736                                    break;
3737                            case REGIMM_BGEZL:
3738                                    ic->f = instr(bgezl);
3739                                    samepage_function = instr(bgezl_samepage);
3740                                    break;
3741                            case REGIMM_BLTZ:
3742                                    ic->f = instr(bltz);
3743                                    samepage_function = instr(bltz_samepage);
3744                                    break;
3745                            case REGIMM_BLTZL:
3746                                    ic->f = instr(bltzl);
3747                                    samepage_function = instr(bltzl_samepage);
3748                                    break;
3749                            case REGIMM_BGEZAL:
3750                                    ic->f = instr(bgezal);
3751                                    samepage_function = instr(bgezal_samepage);
3752                                    break;
3753                            case REGIMM_BGEZALL:
3754                                    ic->f = instr(bgezall);
3755                                    samepage_function = instr(bgezall_samepage);
3756                                    break;
3757                            case REGIMM_BLTZAL:
3758                                    ic->f = instr(bltzal);
3759                                    samepage_function = instr(bltzal_samepage);
3760                                    break;
3761                            case REGIMM_BLTZALL:
3762                                    ic->f = instr(bltzall);
3763                                    samepage_function = instr(bltzall_samepage);
3764                                    break;
3765                            }
3766                            ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];
3767                            ic->arg[2] = (imm << MIPS_INSTR_ALIGNMENT_SHIFT)
3768                                + (addr & 0xffc) + 4;
3769                            /*  Is the offset from the start of the current page
3770                                still within the same page? Then use the
3771                                samepage_function:  */
3772                            if ((uint32_t)ic->arg[2] < ((MIPS_IC_ENTRIES_PER_PAGE-1)
3773                                << MIPS_INSTR_ALIGNMENT_SHIFT) && (addr & 0xffc)
3774                                < 0xffc) {
3775                                    ic->arg[2] = (size_t) (cpu->cd.mips.cur_ic_page+
3776                                        ((ic->arg[2] >> MIPS_INSTR_ALIGNMENT_SHIFT)
3777                                        & (MIPS_IC_ENTRIES_PER_PAGE - 1)));
3778                                    ic->f = samepage_function;
3779                            }
3780                            if (cpu->delay_slot) {
3781                                    fatal("TODO: branch in delay slot? (5)\n");
3782                                    goto bad;
3783                            }
3784                            break;
3785                    default:fatal("UNIMPLEMENTED regimm rt=%i\n", rt);
3786                            goto bad;
3787                    }
3788                    break;
3789    
3790            case HI6_LB:
3791            case HI6_LBU:
3792            case HI6_SB:
3793            case HI6_LH:
3794            case HI6_LHU:
3795            case HI6_SH:
3796            case HI6_LW:
3797            case HI6_LWU:
3798            case HI6_SW:
3799            case HI6_LD:
3800            case HI6_SD:
3801                    /*  TODO: LWU should probably also be x64=1?  */
3802                    size = 2; signedness = 0; store = 0;
3803                    switch (main_opcode) {
3804                    case HI6_LB:  size = 0; signedness = 1; break;
3805                    case HI6_LBU: size = 0; break;
3806                    case HI6_LH:  size = 1; signedness = 1; break;
3807                    case HI6_LHU: size = 1; break;
3808                    case HI6_LW:  signedness = 1; break;
3809                    case HI6_LWU: break;
3810                    case HI6_LD:  size = 3; x64 = 1; break;
3811                    case HI6_SB:  store = 1; size = 0; break;
3812                    case HI6_SH:  store = 1; size = 1; break;
3813                    case HI6_SW:  store = 1; break;
3814                    case HI6_SD:  store = 1; size = 3; x64 = 1; break;
3815                    }
3816    
3817                    ic->f =
3818    #ifdef MODE32
3819                        mips32_loadstore
3820    #else
3821                        mips_loadstore
3822    #endif
3823                        [ (cpu->byte_order == EMUL_LITTLE_ENDIAN? 0 : 16)
3824                        + store * 8 + size * 2 + signedness];
3825                    ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
3826                    ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rs];
3827                    ic->arg[2] = (int32_t)imm;
3828    
3829                    /*  Load into the dummy scratch register, if rt = zero  */
3830                    if (!store && rt == MIPS_GPR_ZERO)
3831                            ic->arg[0] = (size_t)&cpu->cd.mips.scratch;
3832    
3833                    /*  Check for multiple stores in a row using the same
3834                        base register:  */
3835                    if (main_opcode == HI6_SW && rs == MIPS_GPR_SP)
3836                            cpu->cd.mips.combination_check = COMBINE(multi_sw);
3837    
3838                    break;
3839    
3840            case HI6_LL:
3841            case HI6_LLD:
3842            case HI6_SC:
3843            case HI6_SCD:
3844                    /*  32-bit load-linked/store-condition for ISA II and up:  */
3845                    /*  (64-bit load-linked/store-condition for ISA III...)  */
3846                    if (cpu->cd.mips.cpu_type.isa_level < 2) {
3847                            ic->f = instr(reserved);
3848                            break;
3849                    }
3850    
3851                    store = 0;
3852                    switch (main_opcode) {
3853                    case HI6_LL:  ic->f = instr(ll); break;
3854                    case HI6_LLD: ic->f = instr(lld); x64 = 1; break;
3855                    case HI6_SC:  ic->f = instr(sc); store = 1; break;
3856                    case HI6_SCD: ic->f = instr(scd); store = 1; x64 = 1; break;
3857                    }
3858                    ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
3859                    ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rs];
3860                    ic->arg[2] = (int32_t)imm;
3861                    if (!store && rt == MIPS_GPR_ZERO) {
3862                            fatal("HM... unusual load linked\n");
3863                            goto bad;
3864                    }
3865                    break;
3866    
3867            case HI6_LWL:
3868            case HI6_LWR:
3869            case HI6_LDL:
3870            case HI6_LDR:
3871            case HI6_SWL:
3872            case HI6_SWR:
3873            case HI6_SDL:
3874            case HI6_SDR:
3875                    /*  TODO: replace these with faster versions...  */
3876                    store = 0;
3877                    switch (main_opcode) {
3878                    case HI6_LWL: ic->f = instr(lwl); break;
3879                    case HI6_LWR: ic->f = instr(lwr); break;
3880                    case HI6_LDL: ic->f = instr(ldl); x64 = 1; break;
3881                    case HI6_LDR: ic->f = instr(ldr); x64 = 1; break;
3882                    case HI6_SWL: ic->f = instr(swl); store = 1; break;
3883                    case HI6_SWR: ic->f = instr(swr); store = 1; break;
3884                    case HI6_SDL: ic->f = instr(sdl); store = 1; x64 = 1; break;
3885                    case HI6_SDR: ic->f = instr(sdr); store = 1; x64 = 1; break;
3886                    }
3887                    ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
3888                    ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rs];
3889                    ic->arg[2] = (int32_t)imm;
3890    
3891                    /*  Load into the dummy scratch register, if rt = zero  */
3892                    if (!store && rt == MIPS_GPR_ZERO)
3893                            ic->arg[0] = (size_t)&cpu->cd.mips.scratch;
3894                    break;
3895    
3896            case HI6_LWC1:
3897            case HI6_SWC1:
3898            case HI6_LDC1:
3899            case HI6_SDC1:
3900                    /*  64-bit floating-point load/store for ISA II and up...  */
3901                    if ((main_opcode == HI6_LDC1 || main_opcode == HI6_SDC1)
3902                        && cpu->cd.mips.cpu_type.isa_level < 2) {
3903                            ic->f = instr(reserved);
3904                            break;
3905                    }
3906    
3907                    ic->arg[0] = (size_t)&cpu->cd.mips.coproc[1]->reg[rt];
3908                    ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rs];
3909                    ic->arg[2] = (int32_t)imm;
3910                    switch (main_opcode) {
3911                    case HI6_LWC1: ic->f = instr(lwc1); break;
3912                    case HI6_LDC1: ic->f = instr(ldc1); break;
3913                    case HI6_SWC1: ic->f = instr(swc1); break;
3914                    case HI6_SDC1: ic->f = instr(sdc1); break;
3915                    }
3916    
3917                    /*  Cause a coprocessor unusable exception if
3918                        there is no floating point coprocessor:  */
3919                    if (cpu->cd.mips.cpu_type.flags & NOFPU ||
3920                        cpu->cd.mips.coproc[1] == NULL) {
3921                            ic->f = instr(cpu);
3922                            ic->arg[0] = 1;
3923                    }
3924                    break;
3925    
3926            case HI6_LWC3:
3927                    /*  PREF (prefetch) on ISA IV and MIPS32/64:  */
3928                    if (cpu->cd.mips.cpu_type.isa_level >= 4) {
3929                            /*  Treat as nop for now:  */
3930                            ic->f = instr(nop);
3931                    } else {
3932                            fatal("TODO: lwc3 not implemented yet\n");
3933                            goto bad;
3934                    }
3935                    break;
3936    
3937            case HI6_LQ_MDMX:
3938                    if (cpu->cd.mips.cpu_type.rev == MIPS_R5900) {
3939                            fatal("TODO: R5900 128-bit loads\n");
3940                            goto bad;
3941                    }
3942    
3943                    fatal("TODO: MDMX\n");
3944                    goto bad;
3945                    /*  break  */
3946    
3947            case HI6_SQ_SPECIAL3:
3948                    if (cpu->cd.mips.cpu_type.rev == MIPS_R5900) {
3949                            fatal("TODO: R5900 128-bit stores\n");
3950                            goto bad;
3951                    }
3952    
3953                    if (cpu->cd.mips.cpu_type.isa_level < 32 ||
3954                        cpu->cd.mips.cpu_type.isa_revision < 2) {
3955                            static int warning = 0;
3956                            if (!warning) {
3957                                    fatal("[ WARNING! SPECIAL3 opcode used, but"
3958                                        " the %s processor does not implement "
3959                                        "such instructions. Only printing this "
3960                                        "warning once. ]\n",
3961                                        cpu->cd.mips.cpu_type.name);
3962                                    warning = 1;
3963                            }
3964                            ic->f = instr(reserved);
3965                            break;
3966                    }
3967    
3968                    switch (s6) {
3969    
3970                    case SPECIAL3_RDHWR:
3971                            ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
3972    
3973                            switch (rd) {
3974    
3975                            case 0: ic->f = instr(rdhwr_cpunum);
3976                                    if (rt == MIPS_GPR_ZERO)
3977                                            ic->f = instr(nop);
3978                                    break;
3979    
3980                            default:fatal("unimplemented rdhwr register rd=%i\n",
3981                                        rd);
3982                                    goto bad;
3983                            }
3984                            break;
3985    
3986                    default:goto bad;
3987                    }
3988                    break;
3989    
3990            case HI6_CACHE:
3991                    /*  TODO: rt and op etc...  */
3992                    ic->f = instr(cache);
3993                    break;
3994    
3995          default:goto bad;          default:goto bad;
3996          }          }
3997    
3998          if (x64)  #ifdef MODE32
3999                  ic->f = instr(invalid_32_64);          if (x64) {
4000                    static int has_warned = 0;
4001                    if (!has_warned)
4002                            fatal("[ WARNING/NOTE: attempt to execute a 64-bit"
4003                                " instruction on an emulated 32-bit processor; "
4004                                "pc=0x%08"PRIx32" ]\n", (uint32_t)cpu->pc);
4005                    has_warned = 1;
4006                    ic->f = instr(reserved);
4007            }
4008    #endif
4009    
4010            if (ic->f == instr(nop) && cpu->cd.mips.combination_check == NULL)
4011                    cpu->cd.mips.combination_check = COMBINE(nop);
4012    
         if (in_crosspage_delayslot)  
                 cpu->cd.mips.combination_check = NULL;  
4013    
4014  #define DYNTRANS_TO_BE_TRANSLATED_TAIL  #define DYNTRANS_TO_BE_TRANSLATED_TAIL
4015  #include "cpu_dyntrans.c"  #include "cpu_dyntrans.c"

Legend:
Removed from v.22  
changed lines
  Added in v.28

  ViewVC Help
Powered by ViewVC 1.1.26