/[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 30 by dpavlin, Mon Oct 8 16:20:40 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.104 2006/08/14 17:45:47 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 (cpu->cd.mips.cpu_type.exc_model != EXC3K) {
1683                            if (status & (STATUS_EXL | STATUS_ERL))
1684                                    status &= ~STATUS_IE;
1685                    }
1686                    /*  Ugly R5900 special case:  (TODO: move this?)  */
1687                    if (cpu->cd.mips.cpu_type.rev == MIPS_R5900 &&
1688                        !(status & R5900_STATUS_EIE))
1689                            status &= ~STATUS_IE;
1690                    if (status & STATUS_IE && (status & cause & STATUS_IM_MASK)) {
1691                            cpu->pc += sizeof(uint32_t);
1692                            mips_cpu_exception(cpu, EXCEPTION_INT, 0, 0,0,0,0,0);
1693                    }
1694            }
1695  }  }
1696  X(dmfc0)  X(dmfc0)
1697  {  {
# Line 446  X(dmtc0) Line 1711  X(dmtc0)
1711          coproc_register_write(cpu, cpu->cd.mips.coproc[0], rd,          coproc_register_write(cpu, cpu->cd.mips.coproc[0], rd,
1712              (uint64_t *)ic->arg[0], 1, select);              (uint64_t *)ic->arg[0], 1, select);
1713  }  }
1714  X(cfc1)  
1715    
1716    /*
1717     *  cop1_bc:  Floating point conditional branch.
1718     *
1719     *  arg[0] = cc
1720     *  arg[1] = nd (=2) and tf (=1) bits
1721     *  arg[2] = offset (relative to start of this page)
1722     */
1723    X(cop1_bc)
1724    {
1725            MODE_int_t old_pc = cpu->pc;
1726            const int cpnr = 1;
1727            int x, low_pc, cc = ic->arg[0];
1728    
1729            low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1730                / sizeof(struct mips_instr_call);
1731            cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<< MIPS_INSTR_ALIGNMENT_SHIFT);
1732            cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1733            if (!(cpu->cd.mips.coproc[0]->
1734                reg[COP0_STATUS] & ((1 << cpnr) << STATUS_CU_SHIFT)) ) {
1735                    mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0, cpnr, 0, 0, 0);
1736                    return;
1737            }
1738    
1739            /*  Get the correct condition code bit:  */
1740            if (cc == 0)
1741                    x = (cpu->cd.mips.coproc[1]->fcr[MIPS_FPU_FCSR]
1742                        >> MIPS_FCSR_FCC0_SHIFT) & 1;
1743            else
1744                    x = (cpu->cd.mips.coproc[1]->fcr[MIPS_FPU_FCSR]
1745                        >> (MIPS_FCSR_FCC1_SHIFT + cc-1)) & 1;
1746    
1747            /*  Branch on false? Then invert the truth value.  */
1748            if (!(ic->arg[1] & 1))
1749                    x ^= 1;
1750    
1751            /*  Execute the delay slot (except if it is nullified):  */
1752            cpu->delay_slot = TO_BE_DELAYED;
1753            if (x || !(ic->arg[1] & 2))
1754                    ic[1].f(cpu, ic+1);
1755            cpu->n_translated_instrs ++;
1756    
1757            if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
1758                    /*  Note: Must be non-delayed when jumping to the new pc:  */
1759                    cpu->delay_slot = NOT_DELAYED;
1760                    if (x) {
1761                            old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
1762                                MIPS_INSTR_ALIGNMENT_SHIFT);
1763                            cpu->pc = old_pc + (int32_t)ic->arg[2];
1764                            quick_pc_to_pointers(cpu);
1765                    } else
1766                            cpu->cd.mips.next_ic ++;
1767            } else
1768                    cpu->delay_slot = NOT_DELAYED;
1769    }
1770    
1771    
1772    /*
1773     *  cop1_slow:  Fallback to legacy cop1 code. (Slow, but it should work.)
1774     */
1775    X(cop1_slow)
1776    {
1777            const int cpnr = 1;
1778            int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1779                / sizeof(struct mips_instr_call);
1780            cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<< MIPS_INSTR_ALIGNMENT_SHIFT);
1781            cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1782    
1783            if (!(cpu->cd.mips.coproc[0]->
1784                reg[COP0_STATUS] & ((1 << cpnr) << STATUS_CU_SHIFT)) ) {
1785                    mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0, cpnr, 0, 0, 0);
1786                    return;
1787            }
1788    
1789            coproc_function(cpu, cpu->cd.mips.coproc[1], 1, ic->arg[0], 0, 1);
1790    }
1791    
1792    
1793    /*
1794     *  syscall, break:  Synchronize the PC and cause an exception.
1795     */
1796    X(syscall)
1797    {
1798            int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1799                / sizeof(struct mips_instr_call);
1800            cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<< MIPS_INSTR_ALIGNMENT_SHIFT);
1801            cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1802            mips_cpu_exception(cpu, EXCEPTION_SYS, 0, 0, 0, 0, 0, 0);
1803    }
1804    X(break)
1805    {
1806            int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1807                / sizeof(struct mips_instr_call);
1808            cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<< MIPS_INSTR_ALIGNMENT_SHIFT);
1809            cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1810            mips_cpu_exception(cpu, EXCEPTION_BP, 0, 0, 0, 0, 0, 0);
1811    }
1812    X(reboot)
1813    {
1814            cpu->running = 0;
1815            debugger_n_steps_left_before_interaction = 0;
1816            cpu->cd.mips.next_ic = &nothing_call;
1817    }
1818    
1819    
1820    /*
1821     *  promemul:  PROM software emulation.
1822     */
1823    X(promemul)
1824    {
1825            /*  Synchronize the PC and call the correct emulation layer:  */
1826            MODE_int_t old_pc;
1827            int res, low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1828                / sizeof(struct mips_instr_call);
1829            cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<< MIPS_INSTR_ALIGNMENT_SHIFT);
1830            cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1831            old_pc = cpu->pc;
1832    
1833            switch (cpu->machine->machine_type) {
1834            case MACHINE_PMAX:
1835                    res = decstation_prom_emul(cpu);
1836                    break;
1837            case MACHINE_PS2:
1838                    res = playstation2_sifbios_emul(cpu);
1839                    break;
1840            case MACHINE_ARC:
1841            case MACHINE_SGI:
1842                    res = arcbios_emul(cpu);
1843                    break;
1844            case MACHINE_EVBMIPS:
1845                    res = yamon_emul(cpu);
1846                    break;
1847            default:fatal("TODO: Unimplemented machine type for PROM magic trap\n");
1848                    exit(1);
1849            }
1850    
1851            if (res) {
1852                    /*  Return from the PROM call:  */
1853                    cpu->pc = (MODE_int_t)cpu->cd.mips.gpr[MIPS_GPR_RA];
1854                    cpu->delay_slot = NOT_DELAYED;
1855    
1856                    if (cpu->machine->show_trace_tree)
1857                            cpu_functioncall_trace_return(cpu);
1858            } else {
1859                    /*  The PROM call blocks.  */
1860                    cpu->n_translated_instrs += 10;
1861                    cpu->pc = old_pc;
1862            }
1863    
1864            quick_pc_to_pointers(cpu);
1865    }
1866    
1867    
1868    /*
1869     *  tlbw: TLB write indexed and random
1870     *
1871     *  arg[0] = 1 for random, 0 for indexed
1872     *  arg[2] = relative addr of this instruction within the page
1873     */
1874    X(tlbw)
1875  {  {
1876          cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);          cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
1877          cpu->pc |= ic->arg[2];          cpu->pc |= ic->arg[2];
1878          /*  TODO: cause exception if necessary  */          coproc_tlbwri(cpu, ic->arg[0]);
1879          reg(ic->arg[0]) = reg(ic->arg[1]);  }
1880    
1881    
1882    /*
1883     *  tlbp: TLB probe
1884     *  tlbr: TLB read
1885     *
1886     *  arg[2] = relative addr of this instruction within the page
1887     */
1888    X(tlbp)
1889    {
1890            cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
1891            cpu->pc |= ic->arg[2];
1892            coproc_tlbpr(cpu, 0);
1893    }
1894    X(tlbr)
1895    {
1896            cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
1897            cpu->pc |= ic->arg[2];
1898            coproc_tlbpr(cpu, 1);
1899    }
1900    
1901    
1902    /*
1903     *  rfe: Return from exception handler (R2000/R3000)
1904     */
1905    X(rfe)
1906    {
1907            /*  Just rotate the interrupt/user bits:  */
1908            cpu->cd.mips.coproc[0]->reg[COP0_STATUS] =
1909                (cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & ~0x3f) |
1910                ((cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & 0x3c) >> 2);
1911    
1912            /*
1913             *  Note: no pc to pointers conversion is necessary here. Usually the
1914             *  rfe instruction resides in the delay slot of a jr k0/k1, and
1915             *  it is up to that instruction to do the pointer conversion.
1916             */
1917    }
1918    
1919    
1920    /*
1921     *  eret: Return from exception handler (non-R3000 style)
1922     */
1923    X(eret)
1924    {
1925            if (cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & STATUS_ERL) {
1926                    cpu->pc = cpu->cd.mips.coproc[0]->reg[COP0_ERROREPC];
1927                    cpu->cd.mips.coproc[0]->reg[COP0_STATUS] &= ~STATUS_ERL;
1928            } else {
1929                    cpu->pc = cpu->cd.mips.coproc[0]->reg[COP0_EPC];
1930                    cpu->delay_slot = 0;            
1931                    cpu->cd.mips.coproc[0]->reg[COP0_STATUS] &= ~STATUS_EXL;
1932            }
1933    
1934            quick_pc_to_pointers(cpu);
1935    
1936            cpu->cd.mips.rmw = 0;   /*  the "LL bit"  */
1937    }
1938    
1939    
1940    /*
1941     *  deret: Return from debug (EJTAG) handler
1942     */
1943    X(deret)
1944    {
1945            /*
1946             *  According to the MIPS64 manual, deret loads PC from the DEPC cop0
1947             *  register, and jumps there immediately. No delay slot.
1948             *
1949             *  TODO: This instruction is only available if the processor is in
1950             *  debug mode. (What does that mean?)
1951             *
1952             *  TODO: This instruction is undefined in a delay slot.
1953             */
1954    
1955            cpu->pc = cpu->cd.mips.coproc[0]->reg[COP0_DEPC];
1956            cpu->delay_slot = 0;
1957            cpu->cd.mips.coproc[0]->reg[COP0_STATUS] &= ~STATUS_EXL;
1958            quick_pc_to_pointers(cpu);
1959    }
1960    
1961    
1962    /*
1963     *  wait: Wait for external interrupt.
1964     */
1965    X(wait)
1966    {
1967            /*
1968             *  If there is an interrupt, then just return. Otherwise
1969             *  re-run the wait instruction (after a delay).
1970             */
1971            uint32_t status = cpu->cd.mips.coproc[0]->reg[COP0_STATUS];
1972            uint32_t cause = cpu->cd.mips.coproc[0]->reg[COP0_CAUSE];
1973    
1974            /*  NOTE: STATUS_IE happens to match the enable bit also
1975                on R2000/R3000, so this is ok.  */
1976            if (cpu->cd.mips.cpu_type.exc_model != EXC3K) {
1977                    if (status & (STATUS_EXL | STATUS_ERL))
1978                            status &= ~STATUS_IE;
1979            }
1980            /*  Ugly R5900 special case:  (TODO: move this?)  */
1981            if (cpu->cd.mips.cpu_type.rev == MIPS_R5900 &&
1982                !(status & R5900_STATUS_EIE))
1983                    status &= ~STATUS_IE;
1984            if (status & STATUS_IE && (status & cause & STATUS_IM_MASK))
1985                    return;
1986    
1987            cpu->cd.mips.next_ic = ic;
1988            cpu->is_halted = 1;
1989    
1990            /*
1991             *  There was no interrupt. Go to sleep.
1992             *
1993             *  TODO:
1994             *
1995             *  Think about how to actually implement this usleep stuff,
1996             *  in an SMP and/or timing accurate environment.
1997             */
1998    
1999            if (cpu->machine->ncpus == 1) {
2000                    static int x = 0;
2001                    if ((++x) == 600) {
2002                            usleep(1);
2003                            x = 0;
2004                    }
2005                    cpu->n_translated_instrs += N_SAFE_DYNTRANS_LIMIT / 6;
2006            }
2007    }
2008    
2009    
2010    /*
2011     *  rdhwr: Read hardware register into gpr (MIPS32/64 rev 2).
2012     *
2013     *  arg[0] = ptr to rt (destination register)
2014     */
2015    X(rdhwr_cpunum)
2016    {
2017            reg(ic->arg[0]) = cpu->cpu_id;
2018    }
2019    
2020    
2021    #include "tmp_mips_loadstore.c"
2022    
2023    
2024    /*
2025     *  Load linked / store conditional:
2026     *
2027     *  A Load-linked instruction initiates a RMW (read-modify-write) sequence.
2028     *  COP0_LLADDR is updated for diagnostic purposes, except for CPUs in the
2029     *  R10000 family.
2030     *
2031     *  A Store-conditional instruction ends the sequence.
2032     *
2033     *  arg[0] = ptr to rt
2034     *  arg[1] = ptr to rs
2035     *  arg[2] = int32_t imm
2036     */
2037    X(ll)
2038    {
2039            MODE_int_t addr = reg(ic->arg[1]) + (int32_t)ic->arg[2];
2040            int low_pc;
2041            uint8_t word[sizeof(uint32_t)];
2042    
2043            /*  Synch. PC and load using slow memory_rw():  */
2044            low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
2045                / sizeof(struct mips_instr_call);
2046            cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
2047                << MIPS_INSTR_ALIGNMENT_SHIFT);
2048            cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
2049    
2050            if (addr & (sizeof(word)-1)) {
2051                    fatal("TODO: load linked unaligned access: exception\n");
2052                    exit(1);
2053            }
2054    
2055            if (!cpu->memory_rw(cpu, cpu->mem, addr, word,
2056                sizeof(word), MEM_READ, CACHE_DATA)) {
2057                    /*  An exception occurred.  */
2058                    return;
2059            }
2060    
2061            cpu->cd.mips.rmw = 1;
2062            cpu->cd.mips.rmw_addr = addr;
2063            cpu->cd.mips.rmw_len = sizeof(word);
2064            if (cpu->cd.mips.cpu_type.exc_model != MMU10K)
2065                    cpu->cd.mips.coproc[0]->reg[COP0_LLADDR] =
2066                        (addr >> 4) & 0xffffffffULL;
2067    
2068            if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
2069                    reg(ic->arg[0]) = (int32_t) (word[0] + (word[1] << 8)
2070                        + (word[2] << 16) + (word[3] << 24));
2071            else
2072                    reg(ic->arg[0]) = (int32_t) (word[3] + (word[2] << 8)
2073                        + (word[1] << 16) + (word[0] << 24));
2074    }
2075    X(lld)
2076    {
2077            MODE_int_t addr = reg(ic->arg[1]) + (int32_t)ic->arg[2];
2078            int low_pc;
2079            uint8_t word[sizeof(uint64_t)];
2080    
2081            /*  Synch. PC and load using slow memory_rw():  */
2082            low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
2083                / sizeof(struct mips_instr_call);
2084            cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
2085                << MIPS_INSTR_ALIGNMENT_SHIFT);
2086            cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
2087    
2088            if (addr & (sizeof(word)-1)) {
2089                    fatal("TODO: load linked unaligned access: exception\n");
2090                    exit(1);
2091            }
2092    
2093            if (!cpu->memory_rw(cpu, cpu->mem, addr, word,
2094                sizeof(word), MEM_READ, CACHE_DATA)) {
2095                    /*  An exception occurred.  */
2096                    return;
2097            }
2098    
2099            cpu->cd.mips.rmw = 1;
2100            cpu->cd.mips.rmw_addr = addr;
2101            cpu->cd.mips.rmw_len = sizeof(word);
2102            if (cpu->cd.mips.cpu_type.exc_model != MMU10K)
2103                    cpu->cd.mips.coproc[0]->reg[COP0_LLADDR] =
2104                        (addr >> 4) & 0xffffffffULL;
2105    
2106            if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
2107                    reg(ic->arg[0]) = word[0] + (word[1] << 8)
2108                        + (word[2] << 16) + ((uint64_t)word[3] << 24) +
2109                        + ((uint64_t)word[4] << 32) + ((uint64_t)word[5] << 40)
2110                        + ((uint64_t)word[6] << 48) + ((uint64_t)word[7] << 56);
2111            else
2112                    reg(ic->arg[0]) = word[7] + (word[6] << 8)
2113                        + (word[5] << 16) + ((uint64_t)word[4] << 24) +
2114                        + ((uint64_t)word[3] << 32) + ((uint64_t)word[2] << 40)
2115                        + ((uint64_t)word[1] << 48) + ((uint64_t)word[0] << 56);
2116    }
2117    X(sc)
2118    {
2119            MODE_int_t addr = reg(ic->arg[1]) + (int32_t)ic->arg[2];
2120            uint64_t r = reg(ic->arg[0]);
2121            int low_pc, i;
2122            uint8_t word[sizeof(uint32_t)];
2123    
2124            /*  Synch. PC and store using slow memory_rw():  */
2125            low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
2126                / sizeof(struct mips_instr_call);
2127            cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
2128                << MIPS_INSTR_ALIGNMENT_SHIFT);
2129            cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
2130    
2131            if (addr & (sizeof(word)-1)) {
2132                    fatal("TODO: sc unaligned access: exception\n");
2133                    exit(1);
2134            }
2135    
2136            if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {
2137                    word[0]=r; word[1]=r>>8; word[2]=r>>16; word[3]=r>>24;
2138            } else {
2139                    word[3]=r; word[2]=r>>8; word[1]=r>>16; word[0]=r>>24;
2140            }
2141    
2142            /*  If rmw is 0, then the store failed.  (This cache-line was written
2143                to by someone else.)  */
2144            if (cpu->cd.mips.rmw == 0 || cpu->cd.mips.rmw_addr != addr
2145                || cpu->cd.mips.rmw_len != sizeof(word)) {
2146                    reg(ic->arg[0]) = 0;
2147                    cpu->cd.mips.rmw = 0;
2148                    return;
2149            }
2150    
2151            if (!cpu->memory_rw(cpu, cpu->mem, addr, word,
2152                sizeof(word), MEM_WRITE, CACHE_DATA)) {
2153                    /*  An exception occurred.  */
2154                    return;
2155            }
2156    
2157            /*  We succeeded. Let's invalidate everybody else's store to this
2158                cache line:  */
2159            for (i=0; i<cpu->machine->ncpus; i++) {
2160                    if (cpu->machine->cpus[i]->cd.mips.rmw) {
2161                            uint64_t yaddr = addr, xaddr = cpu->machine->cpus[i]->
2162                                cd.mips.rmw_addr;
2163                            uint64_t mask = ~(cpu->machine->cpus[i]->
2164                                cd.mips.cache_linesize[CACHE_DATA] - 1);
2165                            xaddr &= mask;
2166                            yaddr &= mask;
2167                            if (xaddr == yaddr)
2168                                    cpu->machine->cpus[i]->cd.mips.rmw = 0;
2169                    }
2170            }
2171    
2172            reg(ic->arg[0]) = 1;
2173            cpu->cd.mips.rmw = 0;
2174    }
2175    X(scd)
2176    {
2177            MODE_int_t addr = reg(ic->arg[1]) + (int32_t)ic->arg[2];
2178            uint64_t r = reg(ic->arg[0]);
2179            int low_pc, i;
2180            uint8_t word[sizeof(uint64_t)];
2181    
2182            /*  Synch. PC and store using slow memory_rw():  */
2183            low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
2184                / sizeof(struct mips_instr_call);
2185            cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
2186                << MIPS_INSTR_ALIGNMENT_SHIFT);
2187            cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
2188    
2189            if (addr & (sizeof(word)-1)) {
2190                    fatal("TODO: sc unaligned access: exception\n");
2191                    exit(1);
2192            }
2193    
2194            if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {
2195                    word[0]=r;     word[1]=r>>8; word[2]=r>>16; word[3]=r>>24;
2196                    word[4]=r>>32; word[5]=r>>40; word[6]=r>>48; word[7]=r>>56;
2197            } else {
2198                    word[7]=r;     word[6]=r>>8; word[5]=r>>16; word[4]=r>>24;
2199                    word[3]=r>>32; word[2]=r>>40; word[1]=r>>48; word[0]=r>>56;
2200            }
2201    
2202            /*  If rmw is 0, then the store failed.  (This cache-line was written
2203                to by someone else.)  */
2204            if (cpu->cd.mips.rmw == 0 || cpu->cd.mips.rmw_addr != addr
2205                || cpu->cd.mips.rmw_len != sizeof(word)) {
2206                    reg(ic->arg[0]) = 0;
2207                    cpu->cd.mips.rmw = 0;
2208                    return;
2209            }
2210    
2211            if (!cpu->memory_rw(cpu, cpu->mem, addr, word,
2212                sizeof(word), MEM_WRITE, CACHE_DATA)) {
2213                    /*  An exception occurred.  */
2214                    return;
2215            }
2216    
2217            /*  We succeeded. Let's invalidate everybody else's store to this
2218                cache line:  */
2219            for (i=0; i<cpu->machine->ncpus; i++) {
2220                    if (cpu->machine->cpus[i]->cd.mips.rmw) {
2221                            uint64_t yaddr = addr, xaddr = cpu->machine->cpus[i]->
2222                                cd.mips.rmw_addr;
2223                            uint64_t mask = ~(cpu->machine->cpus[i]->
2224                                cd.mips.cache_linesize[CACHE_DATA] - 1);
2225                            xaddr &= mask;
2226                            yaddr &= mask;
2227                            if (xaddr == yaddr)
2228                                    cpu->machine->cpus[i]->cd.mips.rmw = 0;
2229                    }
2230            }
2231    
2232            reg(ic->arg[0]) = 1;
2233            cpu->cd.mips.rmw = 0;
2234    }
2235    
2236    
2237    /*
2238     *  lwc1, swc1:  Coprocessor 1 load/store (32-bit)
2239     *  ldc1, sdc1:  Coprocessor 1 load/store (64-bit)
2240     *
2241     *  arg[0] = ptr to coprocessor register
2242     *  arg[1] = ptr to rs (base pointer register)
2243     *  arg[2] = int32_t imm
2244     */
2245    X(lwc1)
2246    {
2247            const int cpnr = 1;
2248    
2249            /*  Synch. PC and call the generic load/store function:  */
2250            int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
2251                / sizeof(struct mips_instr_call);
2252            cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
2253                << MIPS_INSTR_ALIGNMENT_SHIFT);
2254            cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
2255    
2256            /*  ... but first, let's see if the coprocessor is available:  */
2257            if (!(cpu->cd.mips.coproc[0]->
2258                reg[COP0_STATUS] & ((1 << cpnr) << STATUS_CU_SHIFT)) ) {
2259                    mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0, cpnr, 0, 0, 0);
2260                    return;
2261            }
2262    
2263    #ifdef MODE32
2264            mips32_loadstore
2265    #else
2266            mips_loadstore
2267    #endif
2268                [ (cpu->byte_order == EMUL_LITTLE_ENDIAN? 0 : 16) + 2 * 2 + 1]
2269                (cpu, ic);
2270    }
2271    X(swc1)
2272    {
2273            const int cpnr = 1;
2274    
2275            /*  Synch. PC and call the generic load/store function:  */
2276            int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
2277                / sizeof(struct mips_instr_call);
2278            cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
2279                << MIPS_INSTR_ALIGNMENT_SHIFT);
2280            cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
2281    
2282            /*  ... but first, let's see if the coprocessor is available:  */
2283            if (!(cpu->cd.mips.coproc[0]->
2284                reg[COP0_STATUS] & ((1 << cpnr) << STATUS_CU_SHIFT)) ) {
2285                    mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0, cpnr, 0, 0, 0);
2286                    return;
2287            }
2288    
2289    #ifdef MODE32
2290            mips32_loadstore
2291    #else
2292            mips_loadstore
2293    #endif
2294                [ (cpu->byte_order == EMUL_LITTLE_ENDIAN? 0 : 16) + 8 + 2 * 2]
2295                (cpu, ic);
2296    }
2297    X(ldc1)
2298    {
2299            const int cpnr = 1;
2300            int use_fp_pairs =
2301                !(cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & STATUS_FR);
2302            uint64_t fpr, *backup_ptr;
2303    
2304            /*  Synch. PC and call the generic load/store function:  */
2305            int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
2306                / sizeof(struct mips_instr_call);
2307            cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
2308                << MIPS_INSTR_ALIGNMENT_SHIFT);
2309            cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
2310    
2311            /*  ... but first, let's see if the coprocessor is available:  */
2312            if (!(cpu->cd.mips.coproc[0]->
2313                reg[COP0_STATUS] & ((1 << cpnr) << STATUS_CU_SHIFT)) ) {
2314                    mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0, cpnr, 0, 0, 0);
2315                    return;
2316            }
2317    
2318            backup_ptr = (uint64_t *) ic->arg[0];
2319            ic->arg[0] = (size_t) &fpr;
2320    
2321    #ifdef MODE32
2322            mips32_loadstore
2323    #else
2324            mips_loadstore
2325    #endif
2326                [ (cpu->byte_order == EMUL_LITTLE_ENDIAN? 0 : 16) + 3 * 2 + 1]
2327                (cpu, ic);
2328    
2329            if (use_fp_pairs) {
2330                    backup_ptr[0] = (int64_t)(int32_t) fpr;
2331                    backup_ptr[1] = (int64_t)(int32_t) (fpr >> 32);
2332            } else {
2333                    *backup_ptr = fpr;
2334            }
2335    
2336            ic->arg[0] = (size_t) backup_ptr;
2337    }
2338    X(sdc1)
2339    {
2340            const int cpnr = 1;
2341            int use_fp_pairs =
2342                !(cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & STATUS_FR);
2343            uint64_t fpr, *backup_ptr;
2344    
2345            /*  Synch. PC and call the generic load/store function:  */
2346            int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
2347                / sizeof(struct mips_instr_call);
2348            cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
2349                << MIPS_INSTR_ALIGNMENT_SHIFT);
2350            cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
2351    
2352            /*  ... but first, let's see if the coprocessor is available:  */
2353            if (!(cpu->cd.mips.coproc[0]->
2354                reg[COP0_STATUS] & ((1 << cpnr) << STATUS_CU_SHIFT)) ) {
2355                    mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0, cpnr, 0, 0, 0);
2356                    return;
2357            }
2358    
2359            backup_ptr = (uint64_t *) ic->arg[0];
2360            ic->arg[0] = (size_t) &fpr;
2361    
2362            if (use_fp_pairs) {
2363                    uint32_t lo = backup_ptr[0];
2364                    uint32_t hi = backup_ptr[1];
2365                    fpr = (((uint64_t)hi) << 32) | lo;
2366            } else {
2367                    fpr = *backup_ptr;
2368            }
2369    
2370    #ifdef MODE32
2371            mips32_loadstore
2372    #else
2373            mips_loadstore
2374    #endif
2375                [ (cpu->byte_order == EMUL_LITTLE_ENDIAN? 0 : 16) + 8 + 3 * 2]
2376                (cpu, ic);
2377    
2378            ic->arg[0] = (size_t) backup_ptr;
2379    }
2380    
2381    
2382    /*
2383     *  Unaligned loads/stores:
2384     *
2385     *  arg[0] = ptr to rt
2386     *  arg[1] = ptr to rs
2387     *  arg[2] = int32_t imm
2388     */
2389    X(lwl) { mips_unaligned_loadstore(cpu, ic, 1, sizeof(uint32_t), 0); }
2390    X(lwr) { mips_unaligned_loadstore(cpu, ic, 0, sizeof(uint32_t), 0); }
2391    X(ldl) { mips_unaligned_loadstore(cpu, ic, 1, sizeof(uint64_t), 0); }
2392    X(ldr) { mips_unaligned_loadstore(cpu, ic, 0, sizeof(uint64_t), 0); }
2393    X(swl) { mips_unaligned_loadstore(cpu, ic, 1, sizeof(uint32_t), 1); }
2394    X(swr) { mips_unaligned_loadstore(cpu, ic, 0, sizeof(uint32_t), 1); }
2395    X(sdl) { mips_unaligned_loadstore(cpu, ic, 1, sizeof(uint64_t), 1); }
2396    X(sdr) { mips_unaligned_loadstore(cpu, ic, 0, sizeof(uint64_t), 1); }
2397    
2398    
2399    /*
2400     *  di, ei: R5900 interrupt enable/disable.
2401     *
2402     *  TODO: check the R5900_STATUS_EDI bit in the status register. If it is
2403     *  cleared, and we are not running in kernel mode, then both the EI and DI
2404     *  instructions should be treated as NOPs!
2405     */
2406    X(di_r5900)
2407    {
2408            cpu->cd.mips.coproc[0]->reg[COP0_STATUS] &= ~R5900_STATUS_EIE;
2409    }
2410    X(ei_r5900)
2411    {
2412            cpu->cd.mips.coproc[0]->reg[COP0_STATUS] |= R5900_STATUS_EIE;
2413  }  }
2414    
2415    
# Line 459  X(cfc1) Line 2417  X(cfc1)
2417    
2418    
2419  /*  /*
2420     *  sw_loop:
2421     *
2422     *  s:  addiu   rX,rX,4                 rX = arg[0] and arg[1]
2423     *      bne     rY,rX,s  (or rX,rY,s)   rt=arg[1], rs=arg[0]
2424     *      sw      rZ,-4(rX)               rt=arg[0], rs=arg[1]
2425     */
2426    X(sw_loop)
2427    {
2428            MODE_uint_t rX = reg(ic->arg[0]), rZ = reg(ic[2].arg[0]);
2429            uint64_t *rYp = (uint64_t *) ic[1].arg[0];
2430            MODE_uint_t rY, bytes_to_write;
2431            unsigned char *page;
2432            int partial = 0;
2433    
2434            page = cpu->cd.mips.host_store[rX >> 12];
2435    
2436            /*  Fallback:  */
2437            if (cpu->delay_slot || page == NULL || (rX & 3) != 0 || rZ != 0) {
2438                    instr(addiu)(cpu, ic);
2439                    return;
2440            }
2441    
2442            if (rYp == (uint64_t *) ic->arg[0])
2443                    rYp = (uint64_t *) ic[1].arg[1];
2444    
2445            rY = reg(rYp);
2446    
2447            bytes_to_write = rY - rX;
2448            if ((rX & 0xfff) + bytes_to_write > 0x1000) {
2449                    bytes_to_write = 0x1000 - (rX & 0xfff);
2450                    partial = 1;
2451            }
2452    
2453            /*  printf("rX = %08x\n", (int)rX);
2454                printf("rY = %08x\n", (int)rY);
2455                printf("rZ = %08x\n", (int)rZ);
2456                printf("%i bytes\n", (int)bytes_to_write);  */
2457    
2458            memset(page + (rX & 0xfff), 0, bytes_to_write);
2459    
2460            reg(ic->arg[0]) = rX + bytes_to_write;
2461    
2462            cpu->n_translated_instrs += bytes_to_write / 4 * 3 - 1;
2463            cpu->cd.mips.next_ic = partial?
2464                (struct mips_instr_call *) &ic[0] :
2465                (struct mips_instr_call *) &ic[3];
2466    }
2467    
2468    
2469    #ifdef MODE32
2470    /*
2471     *  multi_sw_2, _3, _4:
2472     *
2473     *      sw      r?,ofs(rX)              r?=arg[0], rX=arg[1], ofs=arg[2]
2474     */
2475    X(multi_sw_2_le)
2476    {
2477            uint32_t *page;
2478            MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2;
2479            MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2];
2480            MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2];
2481            uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12;
2482    
2483            page = (uint32_t *) cpu->cd.mips.host_store[index0];
2484    
2485            /*  Fallback:  */
2486            if (cpu->delay_slot ||
2487                page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 ||
2488                index0 != index1) {
2489                    /*  Normal safe sw:  */
2490                    mips32_loadstore[8 + 2 * 2](cpu, ic);
2491                    return;
2492            }
2493    
2494            addr0 = (addr0 >> 2) & 0x3ff;
2495            addr1 = (addr1 >> 2) & 0x3ff;
2496    
2497            r1 = reg(ic[0].arg[0]);
2498            r2 = reg(ic[1].arg[0]);
2499    
2500            r1 = LE32_TO_HOST(r1);
2501            r2 = LE32_TO_HOST(r2);
2502    
2503            page[addr0] = r1;
2504            page[addr1] = r2;
2505    
2506            cpu->n_translated_instrs ++;
2507            cpu->cd.mips.next_ic ++;
2508    }
2509    X(multi_sw_2_be)
2510    {
2511            uint32_t *page;
2512            MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2;
2513            MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2];
2514            MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2];
2515            uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12;
2516    
2517            page = (uint32_t *) cpu->cd.mips.host_store[index0];
2518    
2519            /*  Fallback:  */
2520            if (cpu->delay_slot ||
2521                page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 ||
2522                index0 != index1) {
2523                    /*  Normal safe sw:  */
2524                    mips32_loadstore[16 + 8 + 2 * 2](cpu, ic);
2525                    return;
2526            }
2527    
2528            addr0 = (addr0 >> 2) & 0x3ff;
2529            addr1 = (addr1 >> 2) & 0x3ff;
2530    
2531            r1 = reg(ic[0].arg[0]);
2532            r2 = reg(ic[1].arg[0]);
2533    
2534            r1 = BE32_TO_HOST(r1);
2535            r2 = BE32_TO_HOST(r2);
2536    
2537            page[addr0] = r1;
2538            page[addr1] = r2;
2539    
2540            cpu->n_translated_instrs ++;
2541            cpu->cd.mips.next_ic ++;
2542    }
2543    X(multi_sw_3_le)
2544    {
2545            uint32_t *page;
2546            MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2, r3;
2547            MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2];
2548            MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2];
2549            MODE_uint_t addr2 = rX + (int32_t)ic[2].arg[2];
2550            uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12,
2551                index2 = addr2 >> 12;
2552    
2553            page = (uint32_t *) cpu->cd.mips.host_store[index0];
2554    
2555            /*  Fallback:  */
2556            if (cpu->delay_slot ||
2557                page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 ||
2558                (addr2 & 3) != 0 || index0 != index1 || index0 != index2) {
2559                    /*  Normal safe sw:  */
2560                    mips32_loadstore[8 + 2 * 2](cpu, ic);
2561                    return;
2562            }
2563    
2564            addr0 = (addr0 >> 2) & 0x3ff;
2565            addr1 = (addr1 >> 2) & 0x3ff;
2566            addr2 = (addr2 >> 2) & 0x3ff;
2567    
2568            /*  printf("addr0=%x 1=%x 2=%x\n",
2569                (int)addr0, (int)addr1, (int)addr2);  */
2570    
2571            r1 = reg(ic[0].arg[0]);
2572            r2 = reg(ic[1].arg[0]);
2573            r3 = reg(ic[2].arg[0]);
2574    
2575            r1 = LE32_TO_HOST(r1);
2576            r2 = LE32_TO_HOST(r2);
2577            r3 = LE32_TO_HOST(r3);
2578    
2579            page[addr0] = r1;
2580            page[addr1] = r2;
2581            page[addr2] = r3;
2582    
2583            cpu->n_translated_instrs += 2;
2584            cpu->cd.mips.next_ic += 2;
2585    }
2586    X(multi_sw_3_be)
2587    {
2588            uint32_t *page;
2589            MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2, r3;
2590            MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2];
2591            MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2];
2592            MODE_uint_t addr2 = rX + (int32_t)ic[2].arg[2];
2593            uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12,
2594                index2 = addr2 >> 12;
2595    
2596            page = (uint32_t *) cpu->cd.mips.host_store[index0];
2597    
2598            /*  Fallback:  */
2599            if (cpu->delay_slot ||
2600                page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 ||
2601                (addr2 & 3) != 0 || index0 != index1 || index0 != index2) {
2602                    /*  Normal safe sw:  */
2603                    mips32_loadstore[16 + 8 + 2 * 2](cpu, ic);
2604                    return;
2605            }
2606    
2607            addr0 = (addr0 >> 2) & 0x3ff;
2608            addr1 = (addr1 >> 2) & 0x3ff;
2609            addr2 = (addr2 >> 2) & 0x3ff;
2610    
2611            /*  printf("addr0=%x 1=%x 2=%x\n",
2612                (int)addr0, (int)addr1, (int)addr2);  */
2613    
2614            r1 = reg(ic[0].arg[0]);
2615            r2 = reg(ic[1].arg[0]);
2616            r3 = reg(ic[2].arg[0]);
2617    
2618            r1 = BE32_TO_HOST(r1);
2619            r2 = BE32_TO_HOST(r2);
2620            r3 = BE32_TO_HOST(r3);
2621    
2622            page[addr0] = r1;
2623            page[addr1] = r2;
2624            page[addr2] = r3;
2625    
2626            cpu->n_translated_instrs += 2;
2627            cpu->cd.mips.next_ic += 2;
2628    }
2629    X(multi_sw_4_le)
2630    {
2631            uint32_t *page;
2632            MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2, r3, r4;
2633            MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2];
2634            MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2];
2635            MODE_uint_t addr2 = rX + (int32_t)ic[2].arg[2];
2636            MODE_uint_t addr3 = rX + (int32_t)ic[3].arg[2];
2637            uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12,
2638                index2 = addr2 >> 12, index3 = addr3 >> 12;
2639    
2640            page = (uint32_t *) cpu->cd.mips.host_store[index0];
2641    
2642            /*  Fallback:  */
2643            if (cpu->delay_slot ||
2644                page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 ||
2645                (addr2 & 3) != 0 || (addr3 & 3) != 0 || index0 != index1 ||
2646                index0 != index2 || index0 != index3) {
2647                    /*  Normal safe sw:  */
2648                    mips32_loadstore[8 + 2 * 2](cpu, ic);
2649                    return;
2650            }
2651    
2652            addr0 = (addr0 >> 2) & 0x3ff;
2653            addr1 = (addr1 >> 2) & 0x3ff;
2654            addr2 = (addr2 >> 2) & 0x3ff;
2655            addr3 = (addr3 >> 2) & 0x3ff;
2656    
2657            r1 = reg(ic[0].arg[0]);
2658            r2 = reg(ic[1].arg[0]);
2659            r3 = reg(ic[2].arg[0]);
2660            r4 = reg(ic[3].arg[0]);
2661    
2662            r1 = LE32_TO_HOST(r1);
2663            r2 = LE32_TO_HOST(r2);
2664            r3 = LE32_TO_HOST(r3);
2665            r4 = LE32_TO_HOST(r4);
2666    
2667            page[addr0] = r1;
2668            page[addr1] = r2;
2669            page[addr2] = r3;
2670            page[addr3] = r4;
2671    
2672            cpu->n_translated_instrs += 3;
2673            cpu->cd.mips.next_ic += 3;
2674    }
2675    X(multi_sw_4_be)
2676    {
2677            uint32_t *page;
2678            MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2, r3, r4;
2679            MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2];
2680            MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2];
2681            MODE_uint_t addr2 = rX + (int32_t)ic[2].arg[2];
2682            MODE_uint_t addr3 = rX + (int32_t)ic[3].arg[2];
2683            uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12,
2684                index2 = addr2 >> 12, index3 = addr3 >> 12;
2685    
2686            page = (uint32_t *) cpu->cd.mips.host_store[index0];
2687    
2688            /*  Fallback:  */
2689            if (cpu->delay_slot ||
2690                page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 ||
2691                (addr2 & 3) != 0 || (addr3 & 3) != 0 || index0 != index1 ||
2692                index0 != index2 || index0 != index3) {
2693                    /*  Normal safe sw:  */
2694                    mips32_loadstore[16 + 8 + 2 * 2](cpu, ic);
2695                    return;
2696            }
2697    
2698            addr0 = (addr0 >> 2) & 0x3ff;
2699            addr1 = (addr1 >> 2) & 0x3ff;
2700            addr2 = (addr2 >> 2) & 0x3ff;
2701            addr3 = (addr3 >> 2) & 0x3ff;
2702    
2703            r1 = reg(ic[0].arg[0]);
2704            r2 = reg(ic[1].arg[0]);
2705            r3 = reg(ic[2].arg[0]);
2706            r4 = reg(ic[3].arg[0]);
2707    
2708            r1 = BE32_TO_HOST(r1);
2709            r2 = BE32_TO_HOST(r2);
2710            r3 = BE32_TO_HOST(r3);
2711            r4 = BE32_TO_HOST(r4);
2712    
2713            page[addr0] = r1;
2714            page[addr1] = r2;
2715            page[addr2] = r3;
2716            page[addr3] = r4;
2717    
2718            cpu->n_translated_instrs += 3;
2719            cpu->cd.mips.next_ic += 3;
2720    }
2721    #endif
2722    
2723    
2724    #ifdef MODE32
2725    /*
2726     *  multi_lw_2, _3, _4:
2727     *
2728     *      lw      r?,ofs(rX)              r?=arg[0], rX=arg[1], ofs=arg[2]
2729     */
2730    X(multi_lw_2_le)
2731    {
2732            uint32_t *page;
2733            MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2;
2734            MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2];
2735            MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2];
2736            uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12;
2737    
2738            page = (uint32_t *) cpu->cd.mips.host_load[index0];
2739    
2740            /*  Fallback:  */
2741            if (cpu->delay_slot ||
2742                page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 ||
2743                index0 != index1) {
2744                    /*  Normal safe lw:  */
2745                    mips32_loadstore[2 * 2 + 1](cpu, ic);
2746                    return;
2747            }
2748    
2749            addr0 = (addr0 >> 2) & 0x3ff;
2750            addr1 = (addr1 >> 2) & 0x3ff;
2751    
2752            r1 = page[addr0];
2753            r2 = page[addr1];
2754    
2755            r1 = LE32_TO_HOST(r1);
2756            r2 = LE32_TO_HOST(r2);
2757    
2758            reg(ic[0].arg[0]) = r1;
2759            reg(ic[1].arg[0]) = r2;
2760    
2761            cpu->n_translated_instrs ++;
2762            cpu->cd.mips.next_ic ++;
2763    }
2764    X(multi_lw_2_be)
2765    {
2766            uint32_t *page;
2767            MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2;
2768            MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2];
2769            MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2];
2770            uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12;
2771    
2772            page = (uint32_t *) cpu->cd.mips.host_load[index0];
2773    
2774            /*  Fallback:  */
2775            if (cpu->delay_slot ||
2776                page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 ||
2777                index0 != index1) {
2778                    /*  Normal safe lw:  */
2779                    mips32_loadstore[16 + 2 * 2 + 1](cpu, ic);
2780                    return;
2781            }
2782    
2783            addr0 = (addr0 >> 2) & 0x3ff;
2784            addr1 = (addr1 >> 2) & 0x3ff;
2785    
2786            r1 = page[addr0];
2787            r2 = page[addr1];
2788    
2789            r1 = BE32_TO_HOST(r1);
2790            r2 = BE32_TO_HOST(r2);
2791    
2792            reg(ic[0].arg[0]) = r1;
2793            reg(ic[1].arg[0]) = r2;
2794    
2795            cpu->n_translated_instrs ++;
2796            cpu->cd.mips.next_ic ++;
2797    }
2798    X(multi_lw_3_le)
2799    {
2800            uint32_t *page;
2801            MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2, r3;
2802            MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2];
2803            MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2];
2804            MODE_uint_t addr2 = rX + (int32_t)ic[2].arg[2];
2805            uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12,
2806                index2 = addr2 >> 12;
2807    
2808            page = (uint32_t *) cpu->cd.mips.host_load[index0];
2809    
2810            /*  Fallback:  */
2811            if (cpu->delay_slot ||
2812                page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 ||
2813                (addr2 & 3) != 0 || index0 != index1 || index0 != index2) {
2814                    /*  Normal safe lw:  */
2815                    mips32_loadstore[2 * 2 + 1](cpu, ic);
2816                    return;
2817            }
2818    
2819            addr0 = (addr0 >> 2) & 0x3ff;
2820            addr1 = (addr1 >> 2) & 0x3ff;
2821            addr2 = (addr2 >> 2) & 0x3ff;
2822    
2823            /*  printf("addr0=%x 1=%x 2=%x\n",
2824                (int)addr0, (int)addr1, (int)addr2);  */
2825    
2826            r1 = page[addr0];
2827            r2 = page[addr1];
2828            r3 = page[addr2];
2829    
2830            r1 = LE32_TO_HOST(r1);
2831            r2 = LE32_TO_HOST(r2);
2832            r3 = LE32_TO_HOST(r3);
2833    
2834            reg(ic[0].arg[0]) = r1;
2835            reg(ic[1].arg[0]) = r2;
2836            reg(ic[2].arg[0]) = r3;
2837    
2838            cpu->n_translated_instrs += 2;
2839            cpu->cd.mips.next_ic += 2;
2840    }
2841    X(multi_lw_3_be)
2842    {
2843            uint32_t *page;
2844            MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2, r3;
2845            MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2];
2846            MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2];
2847            MODE_uint_t addr2 = rX + (int32_t)ic[2].arg[2];
2848            uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12,
2849                index2 = addr2 >> 12;
2850    
2851            page = (uint32_t *) cpu->cd.mips.host_load[index0];
2852    
2853            /*  Fallback:  */
2854            if (cpu->delay_slot ||
2855                page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 ||
2856                (addr2 & 3) != 0 || index0 != index1 || index0 != index2) {
2857                    /*  Normal safe lw:  */
2858                    mips32_loadstore[16 + 2 * 2 + 1](cpu, ic);
2859                    return;
2860            }
2861    
2862            addr0 = (addr0 >> 2) & 0x3ff;
2863            addr1 = (addr1 >> 2) & 0x3ff;
2864            addr2 = (addr2 >> 2) & 0x3ff;
2865    
2866            /*  printf("addr0=%x 1=%x 2=%x\n",
2867                (int)addr0, (int)addr1, (int)addr2);  */
2868    
2869            r1 = page[addr0];
2870            r2 = page[addr1];
2871            r3 = page[addr2];
2872    
2873            r1 = BE32_TO_HOST(r1);
2874            r2 = BE32_TO_HOST(r2);
2875            r3 = BE32_TO_HOST(r3);
2876    
2877            reg(ic[0].arg[0]) = r1;
2878            reg(ic[1].arg[0]) = r2;
2879            reg(ic[2].arg[0]) = r3;
2880    
2881            cpu->n_translated_instrs += 2;
2882            cpu->cd.mips.next_ic += 2;
2883    }
2884    X(multi_lw_4_le)
2885    {
2886            uint32_t *page;
2887            MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2, r3, r4;
2888            MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2];
2889            MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2];
2890            MODE_uint_t addr2 = rX + (int32_t)ic[2].arg[2];
2891            MODE_uint_t addr3 = rX + (int32_t)ic[3].arg[2];
2892            uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12,
2893                index2 = addr2 >> 12, index3 = addr3 >> 12;
2894    
2895            page = (uint32_t *) cpu->cd.mips.host_load[index0];
2896    
2897            /*  Fallback:  */
2898            if (cpu->delay_slot ||
2899                page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 ||
2900                (addr2 & 3) != 0 || (addr3 & 3) != 0 ||
2901                index0 != index1 || index0 != index2 || index0 != index3) {
2902                    /*  Normal safe lw:  */
2903                    mips32_loadstore[2 * 2 + 1](cpu, ic);
2904                    return;
2905            }
2906    
2907            addr0 = (addr0 >> 2) & 0x3ff;
2908            addr1 = (addr1 >> 2) & 0x3ff;
2909            addr2 = (addr2 >> 2) & 0x3ff;
2910            addr3 = (addr3 >> 2) & 0x3ff;
2911    
2912            r1 = page[addr0];
2913            r2 = page[addr1];
2914            r3 = page[addr2];
2915            r4 = page[addr3];
2916    
2917            r1 = LE32_TO_HOST(r1);
2918            r2 = LE32_TO_HOST(r2);
2919            r3 = LE32_TO_HOST(r3);
2920            r4 = LE32_TO_HOST(r4);
2921    
2922            reg(ic[0].arg[0]) = r1;
2923            reg(ic[1].arg[0]) = r2;
2924            reg(ic[2].arg[0]) = r3;
2925            reg(ic[3].arg[0]) = r4;
2926    
2927            cpu->n_translated_instrs += 3;
2928            cpu->cd.mips.next_ic += 3;
2929    }
2930    X(multi_lw_4_be)
2931    {
2932            uint32_t *page;
2933            MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2, r3, r4;
2934            MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2];
2935            MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2];
2936            MODE_uint_t addr2 = rX + (int32_t)ic[2].arg[2];
2937            MODE_uint_t addr3 = rX + (int32_t)ic[3].arg[2];
2938            uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12,
2939                index2 = addr2 >> 12, index3 = addr3 >> 12;
2940    
2941            page = (uint32_t *) cpu->cd.mips.host_load[index0];
2942    
2943            /*  Fallback:  */
2944            if (cpu->delay_slot ||
2945                page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 ||
2946                (addr2 & 3) != 0 || (addr3 & 3) != 0 ||
2947                index0 != index1 || index0 != index2 || index0 != index3) {
2948                    /*  Normal safe lw:  */
2949                    mips32_loadstore[16 + 2 * 2 + 1](cpu, ic);
2950                    return;
2951            }
2952    
2953            addr0 = (addr0 >> 2) & 0x3ff;
2954            addr1 = (addr1 >> 2) & 0x3ff;
2955            addr2 = (addr2 >> 2) & 0x3ff;
2956            addr3 = (addr3 >> 2) & 0x3ff;
2957    
2958            r1 = page[addr0];
2959            r2 = page[addr1];
2960            r3 = page[addr2];
2961            r4 = page[addr3];
2962    
2963            r1 = BE32_TO_HOST(r1);
2964            r2 = BE32_TO_HOST(r2);
2965            r3 = BE32_TO_HOST(r3);
2966            r4 = BE32_TO_HOST(r4);
2967    
2968            reg(ic[0].arg[0]) = r1;
2969            reg(ic[1].arg[0]) = r2;
2970            reg(ic[2].arg[0]) = r3;
2971            reg(ic[3].arg[0]) = r4;
2972    
2973            cpu->n_translated_instrs += 3;
2974            cpu->cd.mips.next_ic += 3;
2975    }
2976    #endif
2977    
2978    
2979    /*
2980     *  multi_addu_3:
2981     */
2982    X(multi_addu_3)
2983    {
2984            /*  Fallback:  */
2985            if (cpu->delay_slot) {
2986                    instr(addu)(cpu, ic);
2987                    return;
2988            }
2989    
2990            reg(ic[0].arg[2]) = (int32_t)(reg(ic[0].arg[0]) + reg(ic[0].arg[1]));
2991            reg(ic[1].arg[2]) = (int32_t)(reg(ic[1].arg[0]) + reg(ic[1].arg[1]));
2992            reg(ic[2].arg[2]) = (int32_t)(reg(ic[2].arg[0]) + reg(ic[2].arg[1]));
2993            cpu->n_translated_instrs += 2;
2994            cpu->cd.mips.next_ic += 2;
2995    }
2996    
2997    
2998    /*
2999     *  netbsd_r3k_picache_do_inv:
3000     *
3001     *  ic[0]       mtc0    rV,status
3002     *     1        nop
3003     *     2        nop
3004     *     3  s:    addiu   rX,rX,4
3005     *     4        bne     rY,rX,s
3006     *     5        sb      zr,-4(rX)
3007     *     6        nop
3008     *     7        nop
3009     *     8        mtc0    rT,status
3010     */
3011    X(netbsd_r3k_picache_do_inv)
3012    {
3013            MODE_uint_t rx = reg(ic[3].arg[0]), ry = reg(ic[4].arg[1]);
3014    
3015            /*  Fallback if the environment isn't exactly right:  */
3016            if (!(reg(ic[0].arg[0]) & MIPS1_ISOL_CACHES) ||
3017                (rx & 3) || (ry & 3) || cpu->delay_slot) {
3018                    instr(mtc0)(cpu, ic);
3019                    return;
3020            }
3021    
3022            reg(ic[3].arg[0]) = ry;
3023            cpu->n_translated_instrs += (ry - rx + 4) / 4 * 3 + 4;
3024    
3025            /*  Run the last mtc0 instruction:  */
3026            cpu->cd.mips.next_ic = (struct mips_instr_call *) &ic[8];
3027    }
3028    
3029    
3030    #ifdef MODE32
3031    /*
3032     *  netbsd_strlen():
3033     *
3034     *      lb      rV,0(rX)
3035     *   s: addiu   rX,rX,1
3036     *      bne     zr,rV,s
3037     *      nop
3038     */
3039    X(netbsd_strlen)
3040    {
3041            MODE_uint_t rx = reg(ic[0].arg[1]);
3042            MODE_int_t rv;
3043            signed char *page;
3044            uint32_t pageindex = rx >> 12;
3045            int i;
3046    
3047            page = (signed char *) cpu->cd.mips.host_load[pageindex];
3048    
3049            /*  Fallback:  */
3050            if (cpu->delay_slot || page == NULL) {
3051                    /*
3052                     *  Normal lb:  NOTE: It doesn't matter whether [1] or
3053                     *  [16+1] is called here, because endianness for 8-bit
3054                     *  loads is irrelevant. :-)
3055                     */
3056                    mips32_loadstore[1](cpu, ic);
3057                    return;
3058            }
3059    
3060            i = rx & 0xfff;
3061    
3062            /*
3063             *  TODO: This loop can be optimized further for optimal
3064             *  performance on the host, e.g. by reading full words...
3065             */
3066            do {
3067                    rv = page[i ++];
3068            } while (i < 0x1000 && rv != 0);
3069    
3070            cpu->n_translated_instrs += (i - (rx & 0xfff)) * 4 - 1;
3071    
3072            reg(ic[0].arg[1]) = (rx & ~0xfff) + i;
3073            reg(ic[2].arg[0]) = rv;
3074    
3075            /*  Done with the loop? Or continue on the next rx page?  */
3076            if (rv == 0)
3077                    cpu->cd.mips.next_ic = (struct mips_instr_call *) &ic[4];
3078            else
3079                    cpu->cd.mips.next_ic = (struct mips_instr_call *) &ic[0];
3080    }
3081    #endif
3082    
3083    
3084    /*
3085     *  addiu_bne_samepage_addiu:
3086     */
3087    X(addiu_bne_samepage_addiu)
3088    {
3089            MODE_uint_t rs, rt;
3090    
3091            if (cpu->delay_slot) {
3092                    instr(addiu)(cpu, ic);
3093                    return;
3094            }
3095    
3096            cpu->n_translated_instrs += 2;
3097            reg(ic[0].arg[1]) = (int32_t)
3098                ((int32_t)reg(ic[0].arg[0]) + (int32_t)ic[0].arg[2]);
3099            rs = reg(ic[1].arg[0]);
3100            rt = reg(ic[1].arg[1]);
3101            reg(ic[2].arg[1]) = (int32_t)
3102                ((int32_t)reg(ic[2].arg[0]) + (int32_t)ic[2].arg[2]);
3103            if (rs != rt)
3104                    cpu->cd.mips.next_ic = (struct mips_instr_call *) ic[1].arg[2];
3105            else
3106                    cpu->cd.mips.next_ic += 2;
3107    }
3108    
3109    
3110    /*
3111     *  xor_andi_sll:
3112     */
3113    X(xor_andi_sll)
3114    {
3115            /*  Fallback:  */
3116            if (cpu->delay_slot) {
3117                    instr(xor)(cpu, ic);
3118                    return;
3119            }
3120    
3121            reg(ic[0].arg[2]) = reg(ic[0].arg[0]) ^ reg(ic[0].arg[1]);
3122            reg(ic[1].arg[1]) = reg(ic[1].arg[0]) & (uint32_t)ic[1].arg[2];
3123            reg(ic[2].arg[2]) = (int32_t)(reg(ic[2].arg[0])<<(int32_t)ic[2].arg[1]);
3124    
3125            cpu->n_translated_instrs += 2;
3126            cpu->cd.mips.next_ic += 2;
3127    }
3128    
3129    
3130    /*
3131     *  andi_sll:
3132     */
3133    X(andi_sll)
3134    {
3135            /*  Fallback:  */
3136            if (cpu->delay_slot) {
3137                    instr(andi)(cpu, ic);
3138                    return;
3139            }
3140    
3141            reg(ic[0].arg[1]) = reg(ic[0].arg[0]) & (uint32_t)ic[0].arg[2];
3142            reg(ic[1].arg[2]) = (int32_t)(reg(ic[1].arg[0])<<(int32_t)ic[1].arg[1]);
3143    
3144            cpu->n_translated_instrs ++;
3145            cpu->cd.mips.next_ic ++;
3146    }
3147    
3148    
3149    /*
3150     *  lui_ori:
3151     */
3152    X(lui_ori)
3153    {
3154            /*  Fallback:  */
3155            if (cpu->delay_slot) {
3156                    instr(set)(cpu, ic);
3157                    return;
3158            }
3159    
3160            reg(ic[0].arg[0]) = (int32_t)ic[0].arg[1];
3161            reg(ic[1].arg[1]) = reg(ic[1].arg[0]) | (uint32_t)ic[1].arg[2];
3162    
3163            cpu->n_translated_instrs ++;
3164            cpu->cd.mips.next_ic ++;
3165    }
3166    
3167    
3168    /*
3169     *  lui_addiu:
3170     */
3171    X(lui_addiu)
3172    {
3173            /*  Fallback:  */
3174            if (cpu->delay_slot) {
3175                    instr(set)(cpu, ic);
3176                    return;
3177            }
3178    
3179            reg(ic[0].arg[0]) = (int32_t)ic[0].arg[1];
3180            reg(ic[1].arg[1]) = (int32_t)
3181                ((int32_t)reg(ic[1].arg[0]) + (int32_t)ic[1].arg[2]);
3182    
3183            cpu->n_translated_instrs ++;
3184            cpu->cd.mips.next_ic ++;
3185    }
3186    
3187    
3188    /*
3189   *  b_samepage_addiu:   *  b_samepage_addiu:
3190   *   *
3191   *  Combination of branch within the same page, followed by addiu.   *  Combination of branch within the same page, followed by addiu.
3192   */   */
3193  X(b_samepage_addiu)  X(b_samepage_addiu)
3194  {  {
3195          reg(ic[1].arg[1]) = reg(ic[1].arg[0]) + (int32_t)ic[1].arg[2];          reg(ic[1].arg[1]) = (int32_t)
3196                ( (int32_t)reg(ic[1].arg[0]) + (int32_t)ic[1].arg[2] );
3197            cpu->n_translated_instrs ++;
3198            cpu->cd.mips.next_ic = (struct mips_instr_call *) ic->arg[2];
3199    }
3200    
3201    
3202    /*
3203     *  b_samepage_daddiu:
3204     *
3205     *  Combination of branch within the same page, followed by daddiu.
3206     */
3207    X(b_samepage_daddiu)
3208    {
3209            *(uint64_t *)ic[1].arg[1] = *(uint64_t *)ic[1].arg[0] +
3210                (int32_t)ic[1].arg[2];
3211          cpu->n_translated_instrs ++;          cpu->n_translated_instrs ++;
3212          cpu->cd.mips.next_ic = (struct mips_instr_call *) ic->arg[2];          cpu->cd.mips.next_ic = (struct mips_instr_call *) ic->arg[2];
3213  }  }
# Line 476  X(b_samepage_addiu) Line 3218  X(b_samepage_addiu)
3218    
3219  X(end_of_page)  X(end_of_page)
3220  {  {
         struct mips_instr_call self;  
   
3221          /*  Update the PC:  (offset 0, but on the next page)  */          /*  Update the PC:  (offset 0, but on the next page)  */
3222          cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<          cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
3223              MIPS_INSTR_ALIGNMENT_SHIFT);              MIPS_INSTR_ALIGNMENT_SHIFT);
3224          cpu->pc += (MIPS_IC_ENTRIES_PER_PAGE << MIPS_INSTR_ALIGNMENT_SHIFT);          cpu->pc += (MIPS_IC_ENTRIES_PER_PAGE << MIPS_INSTR_ALIGNMENT_SHIFT);
3225    
3226          /*  Simple jump to the next page (if we are lucky):  */          /*  end_of_page doesn't count as an executed instruction:  */
3227          if (cpu->cd.mips.delay_slot == NOT_DELAYED) {          cpu->n_translated_instrs --;
3228    
3229                  /*  Find the new physpage and update translation pointers:  */          /*
3230                  quick_pc_to_pointers(cpu);           *  Find the new physpage and update translation pointers.
3231             *
3232             *  Note: This may cause an exception, if e.g. the new page is
3233             *  not accessible.
3234             */
3235            quick_pc_to_pointers(cpu);
3236    
3237                  /*  end_of_page doesn't count as an executed instruction:  */          /*  Simple jump to the next page (if we are lucky):  */
3238                  cpu->n_translated_instrs --;          if (cpu->delay_slot == NOT_DELAYED)
3239                    return;
3240    
3241            /*
3242             *  If we were in a delay slot, and we got an exception while doing
3243             *  quick_pc_to_pointers, then return. The function which called
3244             *  end_of_page should handle this case.
3245             */
3246            if (cpu->delay_slot == EXCEPTION_IN_DELAY_SLOT)
3247                  return;                  return;
         }  
3248    
3249          /*  Tricky situation; the delay slot is on the next virtual page:  */          /*
3250             *  Tricky situation; the delay slot is on the next virtual page.
3251             *  Calling to_be_translated will translate one instruction manually,
3252             *  execute it, and then discard it.
3253             */
3254          /*  fatal("[ end_of_page: delay slot across page boundary! ]\n");  */          /*  fatal("[ end_of_page: delay slot across page boundary! ]\n");  */
3255    
3256          /*  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);  
3257    
3258          /*  The instruction in the delay slot has now executed.  */          /*  The instruction in the delay slot has now executed.  */
3259            /*  fatal("[ end_of_page: back from executing the delay slot, %i ]\n",
3260                cpu->delay_slot);  */
3261    
3262          /*  Find the physpage etc of the instruction in the delay slot          /*  Find the physpage etc of the instruction in the delay slot
3263              (or, if there was an exception, the exception handler):  */              (or, if there was an exception, the exception handler):  */
3264          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");  */  
3265  }  }
3266    
3267    
3268  X(end_of_page2)  X(end_of_page2)
3269  {  {
3270  fatal("this should be removed: end of page2\n");          /*  Synchronize PC on the _second_ instruction on the next page:  */
3271  exit(1);          int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
3272                / sizeof(struct mips_instr_call);
3273          /*  Update the PC:  (offset 4, but on the next page)  */          cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
3274          cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<              << MIPS_INSTR_ALIGNMENT_SHIFT);
3275              MIPS_INSTR_ALIGNMENT_SHIFT);          cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
         cpu->pc += ((MIPS_IC_ENTRIES_PER_PAGE+1) << MIPS_INSTR_ALIGNMENT_SHIFT);  
3276    
3277          if (cpu->cd.mips.delay_slot == NOT_DELAYED) {          /*  This doesn't count as an executed instruction.  */
3278                  /*  Find the new physpage and update translation pointers:  */          cpu->n_translated_instrs --;
                 quick_pc_to_pointers(cpu);  
3279    
3280                  /*  end_of_page doesn't count as an executed instruction:  */          quick_pc_to_pointers(cpu);
                 cpu->n_translated_instrs --;  
3281    
3282            if (cpu->delay_slot == NOT_DELAYED)
3283                  return;                  return;
         }  
3284    
3285          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");
3286          exit(1);          exit(1);
3287  }  }
3288    
# Line 545  exit(1); Line 3291  exit(1);
3291    
3292    
3293  /*  /*
3294   *  Combine: [Conditional] branch, followed by addiu.   *  Combine:  Memory fill loop (addiu, bne, sw)
3295     *
3296     *  s:  addiu   rX,rX,4
3297     *      bne     rY,rX,s
3298     *      sw      rZ,-4(rX)
3299   */   */
3300  void COMBINE(b_addiu)(struct cpu *cpu, struct mips_instr_call *ic,  void COMBINE(sw_loop)(struct cpu *cpu, struct mips_instr_call *ic, int low_addr)
3301    {
3302            int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
3303                & (MIPS_IC_ENTRIES_PER_PAGE - 1);
3304    
3305            /*  Only for 32-bit virtual address translation so far.  */
3306            if (!cpu->is_32bit)
3307                    return;
3308    
3309            if (n_back < 2)
3310                    return;
3311    
3312            if (ic[-2].f == instr(addiu) && ic[-2].arg[0] == ic[-2].arg[1] &&
3313                (int32_t)ic[-2].arg[2] == 4 &&
3314                ic[-1].f == instr(bne_samepage) &&
3315                (ic[-1].arg[0] == ic[-2].arg[0] ||
3316                    ic[-1].arg[1] == ic[-2].arg[0]) &&
3317                ic[-1].arg[0] != ic[-1].arg[1] &&
3318                ic[-1].arg[2] == (size_t) &ic[-2] &&
3319                ic[0].arg[0] != ic[0].arg[1] &&
3320                ic[0].arg[1] == ic[-2].arg[0] && (int32_t)ic[0].arg[2] == -4) {
3321                    ic[-2].f = instr(sw_loop);
3322            }
3323    }
3324    
3325    
3326    /*  Only for 32-bit virtual address translation so far.  */
3327    #ifdef MODE32
3328    /*
3329     *  Combine:  Multiple SW in a row using the same base register
3330     *
3331     *      sw      r?,???(rX)
3332     *      sw      r?,???(rX)
3333     *      sw      r?,???(rX)
3334     *      ...
3335     */
3336    void COMBINE(multi_sw)(struct cpu *cpu, struct mips_instr_call *ic,
3337          int low_addr)          int low_addr)
3338  {  {
3339          int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)          int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
3340              & (MIPS_IC_ENTRIES_PER_PAGE - 1);              & (MIPS_IC_ENTRIES_PER_PAGE - 1);
3341    
3342            if (n_back < 3)
3343                    return;
3344    
3345            /*  Convert a multi_sw_3 to a multi_sw_4:  */
3346            if ((ic[-3].f == instr(multi_sw_3_be) ||
3347                ic[-3].f == instr(multi_sw_3_le)) &&
3348                ic[-3].arg[1] == ic[0].arg[1]) {
3349                    if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
3350                            ic[-3].f = instr(multi_sw_4_le);
3351                    else
3352                            ic[-3].f = instr(multi_sw_4_be);
3353            }
3354    
3355            /*  Convert a multi_sw_2 to a multi_sw_3:  */
3356            if ((ic[-2].f == instr(multi_sw_2_be) ||
3357                ic[-2].f == instr(multi_sw_2_le)) &&
3358                ic[-2].arg[1] == ic[0].arg[1]) {
3359                    if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
3360                            ic[-2].f = instr(multi_sw_3_le);
3361                    else
3362                            ic[-2].f = instr(multi_sw_3_be);
3363            }
3364    
3365            if (ic[-1].f == ic[0].f && ic[-1].arg[1] == ic[0].arg[1]) {
3366                    if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
3367                            ic[-1].f = instr(multi_sw_2_le);
3368                    else
3369                            ic[-1].f = instr(multi_sw_2_be);
3370            }
3371    }
3372    #endif
3373    
3374    
3375    /*  Only for 32-bit virtual address translation so far.  */
3376    #ifdef MODE32
3377    /*
3378     *  Combine:  Multiple LW in a row using the same base register
3379     *
3380     *      lw      r?,???(rX)
3381     *      lw      r?,???(rX)
3382     *      lw      r?,???(rX)
3383     *      ...
3384     */
3385    void COMBINE(multi_lw)(struct cpu *cpu, struct mips_instr_call *ic,
3386            int low_addr)
3387    {
3388            int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
3389                & (MIPS_IC_ENTRIES_PER_PAGE - 1);
3390    
3391            if (n_back < 3)
3392                    return;
3393    
3394            /*  Convert a multi_lw_3 to a multi_lw_4:  */
3395            if ((ic[-3].f == instr(multi_lw_3_be) ||
3396                ic[-3].f == instr(multi_lw_3_le)) &&
3397                ic[-3].arg[1] == ic[0].arg[1] &&
3398                ic[-1].arg[0] != ic[0].arg[1]) {
3399                    if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
3400                            ic[-3].f = instr(multi_lw_4_le);
3401                    else
3402                            ic[-3].f = instr(multi_lw_4_be);
3403            }
3404    
3405            /*  Convert a multi_lw_2 to a multi_lw_3:  */
3406            if ((ic[-2].f == instr(multi_lw_2_be) ||
3407                ic[-2].f == instr(multi_lw_2_le)) &&
3408                ic[-2].arg[1] == ic[0].arg[1] &&
3409                ic[-1].arg[0] != ic[0].arg[1]) {
3410                    if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
3411                            ic[-2].f = instr(multi_lw_3_le);
3412                    else
3413                            ic[-2].f = instr(multi_lw_3_be);
3414            }
3415    
3416            /*  Note: Loads to the base register are not allowed in slot -1.  */
3417            if (ic[-1].f == ic[0].f &&
3418                ic[-1].arg[1] == ic[0].arg[1] &&
3419                ic[-1].arg[0] != ic[0].arg[1]) {
3420                    if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
3421                            ic[-1].f = instr(multi_lw_2_le);
3422                    else
3423                            ic[-1].f = instr(multi_lw_2_be);
3424            }
3425    }
3426    #endif
3427    
3428    
3429    /*
3430     *  Combine:  NetBSD/pmax 3.0 R2000/R3000 physical cache invalidation loop
3431     *
3432     *  Instruction cache loop:
3433     *
3434     *  ic[-8]      mtc0    rV,status
3435     *     -7       nop
3436     *     -6       nop
3437     *     -5  s:   addiu   rX,rX,4
3438     *     -4       bne     rY,rX,s
3439     *     -3       sb      zr,-4(rX)
3440     *     -2       nop
3441     *     -1       nop
3442     *      0       mtc0    rT,status
3443     */
3444    void COMBINE(netbsd_r3k_cache_inv)(struct cpu *cpu,
3445            struct mips_instr_call *ic, int low_addr)
3446    {
3447            int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
3448                & (MIPS_IC_ENTRIES_PER_PAGE - 1);
3449    
3450            if (n_back < 8)
3451                    return;
3452    
3453            if (ic[-8].f == instr(mtc0) && ic[-8].arg[1] == COP0_STATUS &&
3454                ic[-7].f == instr(nop) && ic[-6].f == instr(nop) &&
3455                ic[-5].f == instr(addiu) && ic[-5].arg[0] == ic[-5].arg[1] &&
3456                (int32_t)ic[-5].arg[2] == 4 && ic[-4].f == instr(bne_samepage) &&
3457                ic[-4].arg[0] == ic[-5].arg[0] && ic[-4].arg[0] != ic[-4].arg[1] &&
3458                ic[-4].arg[2] == (size_t) &ic[-5] &&
3459                ic[-3].arg[1] == ic[-5].arg[0] &&
3460                ic[-2].f == instr(nop) && ic[-1].f == instr(nop)) {
3461                    ic[-8].f = instr(netbsd_r3k_picache_do_inv);
3462            }
3463    }
3464    
3465    
3466    /*
3467     *  Combine: something ending with a nop.
3468     *
3469     *      NetBSD's strlen core.
3470     *      [Conditional] branch, followed by nop.
3471     */
3472    void COMBINE(nop)(struct cpu *cpu, struct mips_instr_call *ic, int low_addr)
3473    {
3474            int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
3475                & (MIPS_IC_ENTRIES_PER_PAGE - 1);
3476    
3477    #ifdef MODE32
3478            if (n_back < 3)
3479                    return;
3480    
3481            if ((ic[-3].f == mips32_loadstore[1] ||
3482                ic[-3].f == mips32_loadstore[16 + 1]) &&
3483                ic[-3].arg[2] == 0 &&
3484                ic[-3].arg[0] == ic[-1].arg[0] && ic[-3].arg[1] == ic[-2].arg[0] &&
3485                ic[-2].arg[0] == ic[-2].arg[1] && ic[-2].arg[2] == 1 &&
3486                ic[-2].f == instr(addiu) && ic[-1].arg[2] == (size_t) &ic[-3] &&
3487                ic[-1].arg[1] == (size_t) &cpu->cd.mips.gpr[MIPS_GPR_ZERO] &&
3488                ic[-1].f == instr(bne_samepage)) {
3489                    ic[-3].f = instr(netbsd_strlen);
3490                    return;
3491            }
3492    #endif
3493    
3494          if (n_back < 1)          if (n_back < 1)
3495                  return;                  return;
3496    
3497            if (ic[-1].f == instr(bne_samepage)) {
3498                    ic[-1].f = instr(bne_samepage_nop);
3499                    return;
3500            }
3501    
3502            if (ic[-1].f == instr(beq_samepage)) {
3503                    ic[-1].f = instr(beq_samepage_nop);
3504                    return;
3505            }
3506    
3507            /*  TODO: other branches that are followed by nop should be here  */
3508    }
3509    
3510    
3511    /*
3512     *  Combine:
3513     *
3514     *      xor + andi + sll
3515     *      andi + sll
3516     */
3517    void COMBINE(sll)(struct cpu *cpu, struct mips_instr_call *ic, int low_addr)
3518    {
3519            int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
3520                & (MIPS_IC_ENTRIES_PER_PAGE - 1);
3521    
3522            if (n_back < 2)
3523                    return;
3524    
3525            if (ic[-2].f == instr(xor) && ic[-1].f == instr(andi)) {
3526                    ic[-2].f = instr(xor_andi_sll);
3527                    return;
3528            }
3529    
3530            if (ic[-1].f == instr(andi)) {
3531                    ic[-1].f = instr(andi_sll);
3532                    return;
3533            }
3534    }
3535    
3536    
3537    /*
3538     *  lui + ori
3539     */
3540    void COMBINE(ori)(struct cpu *cpu, struct mips_instr_call *ic, int low_addr)
3541    {
3542            int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
3543                & (MIPS_IC_ENTRIES_PER_PAGE - 1);
3544    
3545            if (n_back < 1)
3546                    return;
3547    
3548            if (ic[-1].f == instr(set)) {
3549                    ic[-1].f = instr(lui_ori);
3550                    return;
3551            }
3552    }
3553    
3554    
3555    /*
3556     *  addu + addu + addu
3557     */
3558    void COMBINE(addu)(struct cpu *cpu, struct mips_instr_call *ic, int low_addr)
3559    {
3560            int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
3561                & (MIPS_IC_ENTRIES_PER_PAGE - 1);
3562    
3563            if (n_back < 4)
3564                    return;
3565    
3566            /*  Avoid "overlapping" instruction combinations:  */
3567            if (ic[-4].f == instr(multi_addu_3) ||
3568                ic[-3].f == instr(multi_addu_3))
3569                    return;
3570    
3571            if (ic[-2].f == instr(addu) && ic[-1].f == instr(addu)) {
3572                    ic[-2].f = instr(multi_addu_3);
3573                    return;
3574            }
3575    }
3576    
3577    
3578    /*
3579     *  Combine:
3580     *
3581     *      [Conditional] branch, followed by addiu.
3582     */
3583    void COMBINE(addiu)(struct cpu *cpu, struct mips_instr_call *ic, int low_addr)
3584    {
3585            int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
3586                & (MIPS_IC_ENTRIES_PER_PAGE - 1);
3587    
3588            if (n_back < 2)
3589                    return;
3590    
3591            if (ic[-2].f == instr(addiu) &&
3592                ic[-1].f == instr(bne_samepage)) {
3593                    ic[-2].f = instr(addiu_bne_samepage_addiu);
3594                    return;
3595            }
3596    
3597            if (ic[-1].f == instr(set)) {
3598                    ic[-1].f = instr(lui_addiu);
3599                    return;
3600            }
3601    
3602          if (ic[-1].f == instr(b_samepage)) {          if (ic[-1].f == instr(b_samepage)) {
3603                  ic[-1].f = instr(b_samepage_addiu);                  ic[-1].f = instr(b_samepage_addiu);
3604                  combined;                  return;
3605            }
3606    
3607            if (ic[-1].f == instr(beq_samepage)) {
3608                    ic[-1].f = instr(beq_samepage_addiu);
3609                    return;
3610            }
3611    
3612            if (ic[-1].f == instr(bne_samepage)) {
3613                    ic[-1].f = instr(bne_samepage_addiu);
3614                    return;
3615            }
3616    
3617            if (ic[-1].f == instr(jr_ra)) {
3618                    ic[-1].f = instr(jr_ra_addiu);
3619                    return;
3620          }          }
3621    
3622          /*  TODO: other branches that are followed by addiu should be here  */          /*  TODO: other branches that are followed by addiu should be here  */
3623  }  }
3624    
3625    
3626    /*
3627     *  Combine: [Conditional] branch, followed by daddiu.
3628     */
3629    void COMBINE(b_daddiu)(struct cpu *cpu, struct mips_instr_call *ic,
3630            int low_addr)
3631    {
3632            int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
3633                & (MIPS_IC_ENTRIES_PER_PAGE - 1);
3634    
3635            if (n_back < 1)
3636                    return;
3637    
3638            if (ic[-1].f == instr(b_samepage)) {
3639                    ic[-1].f = instr(b_samepage_daddiu);
3640            }
3641    
3642            /*  TODO: other branches that are followed by daddiu should be here  */
3643    }
3644    
3645    
3646  /*****************************************************************************/  /*****************************************************************************/
3647    
3648    
3649  /*  /*
3650   *  mips_instr_to_be_translated():   *  mips_instr_to_be_translated():
3651   *   *
3652   *  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
3653   *  valid data for the translated instruction, or a "nothing" instruction if   *  valid data for the translated instruction, or a "nothing" instruction if
3654   *  there was a translation failure. The newly translated instruction is then   *  there was a translation failure. The newly translated instruction is then
3655   *  executed.   *  executed.
# Line 582  X(to_be_translated) Line 3660  X(to_be_translated)
3660          uint32_t iword, imm;          uint32_t iword, imm;
3661          unsigned char *page;          unsigned char *page;
3662          unsigned char ib[4];          unsigned char ib[4];
 #ifdef DYNTRANS_BACKEND  
         int simple = 0;  
 #endif  
3663          int main_opcode, rt, rs, rd, sa, s6, x64 = 0;          int main_opcode, rt, rs, rd, sa, s6, x64 = 0;
3664          int in_crosspage_delayslot = 0;          int in_crosspage_delayslot = 0;
         int delay_slot_danger = 1;  
3665          void (*samepage_function)(struct cpu *, struct mips_instr_call *);          void (*samepage_function)(struct cpu *, struct mips_instr_call *);
3666            int store, signedness, size;
3667    
3668          /*  Figure out the (virtual) address of the instruction:  */          /*  Figure out the (virtual) address of the instruction:  */
3669          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)
3670              / sizeof(struct mips_instr_call);              / sizeof(struct mips_instr_call);
3671    
3672          /*  Special case for branch with delayslot on the next page:  */          /*  Special case for branch with delayslot on the next page:  */
3673          if (low_pc >= MIPS_IC_ENTRIES_PER_PAGE) {          if (cpu->delay_slot == TO_BE_DELAYED && low_pc == 0) {
3674                  /*  fatal("[ TEMPORARY delay-slot translation ]\n");  */                  /*  fatal("[ delay-slot translation across page "
3675                  low_pc = 0;                      "boundary ]\n");  */
3676                  in_crosspage_delayslot = 1;                  in_crosspage_delayslot = 1;
3677          }          }
3678    
3679          addr = cpu->pc & ~((MIPS_IC_ENTRIES_PER_PAGE-1)          addr = cpu->pc & ~((MIPS_IC_ENTRIES_PER_PAGE-1)
3680              << MIPS_INSTR_ALIGNMENT_SHIFT);              << MIPS_INSTR_ALIGNMENT_SHIFT);
3681          addr += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);          addr += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
3682          cpu->pc = addr;          cpu->pc = (MODE_int_t)addr;
3683          addr &= ~((1 << MIPS_INSTR_ALIGNMENT_SHIFT) - 1);          addr &= ~((1 << MIPS_INSTR_ALIGNMENT_SHIFT) - 1);
3684    
3685          /*  Read the instruction word from memory:  */          /*  Read the instruction word from memory:  */
3686    #ifdef MODE32
3687          page = cpu->cd.mips.host_load[(uint32_t)addr >> 12];          page = cpu->cd.mips.host_load[(uint32_t)addr >> 12];
3688    #else
3689            {
3690                    const uint32_t mask1 = (1 << DYNTRANS_L1N) - 1;
3691                    const uint32_t mask2 = (1 << DYNTRANS_L2N) - 1;
3692                    const uint32_t mask3 = (1 << DYNTRANS_L3N) - 1;
3693                    uint32_t x1 = (addr >> (64-DYNTRANS_L1N)) & mask1;
3694                    uint32_t x2 = (addr >> (64-DYNTRANS_L1N-DYNTRANS_L2N)) & mask2;
3695                    uint32_t x3 = (addr >> (64-DYNTRANS_L1N-DYNTRANS_L2N-
3696                        DYNTRANS_L3N)) & mask3;
3697                    struct DYNTRANS_L2_64_TABLE *l2 = cpu->cd.mips.l1_64[x1];
3698                    struct DYNTRANS_L3_64_TABLE *l3 = l2->l3[x2];
3699                    page = l3->host_load[x3];
3700            }
3701    #endif
3702    
3703          if (page != NULL) {          if (page != NULL) {
3704                  /*  fatal("TRANSLATION HIT!\n");  */                  /*  fatal("TRANSLATION HIT!\n");  */
3705                  memcpy(ib, page + (addr & 0xfff), sizeof(ib));                  memcpy(ib, page + (addr & 0xffc), sizeof(ib));
3706          } else {          } else {
3707                  /*  fatal("TRANSLATION MISS!\n");  */                  /*  fatal("TRANSLATION MISS!\n");  */
3708                  if (!cpu->memory_rw(cpu, cpu->mem, addr, ib,                  if (!cpu->memory_rw(cpu, cpu->mem, addr, ib,
3709                      sizeof(ib), MEM_READ, CACHE_INSTRUCTION)) {                      sizeof(ib), MEM_READ, CACHE_INSTRUCTION)) {
3710                          fatal("to_be_translated(): "                          fatal("to_be_translated(): read failed: TODO\n");
                             "read failed: TODO\n");  
3711                          goto bad;                          goto bad;
3712                  }                  }
3713          }          }
# Line 630  X(to_be_translated) Line 3719  X(to_be_translated)
3719          else          else
3720                  iword = BE32_TO_HOST(iword);                  iword = BE32_TO_HOST(iword);
3721    
         /*  Is the instruction in the delay slot known to be safe?  */  
         if ((addr & 0xffc) < 0xffc) {  
                 /*  TODO: check the instruction  */  
                 delay_slot_danger = 0;  
         }  
   
3722    
3723  #define DYNTRANS_TO_BE_TRANSLATED_HEAD  #define DYNTRANS_TO_BE_TRANSLATED_HEAD
3724  #include "cpu_dyntrans.c"  #include "cpu_dyntrans.c"
# Line 645  X(to_be_translated) Line 3728  X(to_be_translated)
3728          /*          /*
3729           *  Translate the instruction:           *  Translate the instruction:
3730           *           *
3731           *  NOTE: _NEVER_ allow writes to the zero register; all such           *  NOTE: _NEVER_ allow writes to the zero register; all instructions
3732           *  instructions should be made into NOPs.           *  that use the zero register as their destination should be treated
3733             *  as NOPs, except those that access memory (they should use the
3734             *  scratch register instead).
3735           */           */
3736    
3737          main_opcode = iword >> 26;          main_opcode = iword >> 26;
# Line 663  X(to_be_translated) Line 3748  X(to_be_translated)
3748                  switch (s6) {                  switch (s6) {
3749    
3750                  case SPECIAL_SLL:                  case SPECIAL_SLL:
3751                    case SPECIAL_SLLV:
3752                  case SPECIAL_SRL:                  case SPECIAL_SRL:
3753                    case SPECIAL_SRLV:
3754                  case SPECIAL_SRA:                  case SPECIAL_SRA:
3755                    case SPECIAL_SRAV:
3756                    case SPECIAL_DSRL:
3757                    case SPECIAL_DSRLV:
3758                    case SPECIAL_DSRL32:
3759                    case SPECIAL_DSLL:
3760                    case SPECIAL_DSLLV:
3761                    case SPECIAL_DSLL32:
3762                    case SPECIAL_DSRA:
3763                    case SPECIAL_DSRAV:
3764                    case SPECIAL_DSRA32:
3765                          switch (s6) {                          switch (s6) {
3766                          case SPECIAL_SLL:  ic->f = instr(sll); break;                          case SPECIAL_SLL:  ic->f = instr(sll); break;
3767                            case SPECIAL_SLLV: ic->f = instr(sllv); sa = -1; break;
3768                          case SPECIAL_SRL:  ic->f = instr(srl); break;                          case SPECIAL_SRL:  ic->f = instr(srl); break;
3769                            case SPECIAL_SRLV: ic->f = instr(srlv); sa = -1; break;
3770                          case SPECIAL_SRA:  ic->f = instr(sra); break;                          case SPECIAL_SRA:  ic->f = instr(sra); break;
3771                            case SPECIAL_SRAV: ic->f = instr(srav); sa = -1; break;
3772                            case SPECIAL_DSRL: ic->f = instr(dsrl); x64=1; break;
3773                            case SPECIAL_DSRLV:ic->f = instr(dsrlv);
3774                                               x64 = 1; sa = -1; break;
3775                            case SPECIAL_DSRL32:ic->f= instr(dsrl); x64=1;
3776                                               sa += 32; break;
3777                            case SPECIAL_DSLL: ic->f = instr(dsll); x64=1; break;
3778                            case SPECIAL_DSLLV:ic->f = instr(dsllv);
3779                                               x64 = 1; sa = -1; break;
3780                            case SPECIAL_DSLL32:ic->f= instr(dsll); x64=1;
3781                                               sa += 32; break;
3782                            case SPECIAL_DSRA: ic->f = instr(dsra); x64=1; break;
3783                            case SPECIAL_DSRAV:ic->f = instr(dsrav);
3784                                               x64 = 1; sa = -1; break;
3785                            case SPECIAL_DSRA32:ic->f = instr(dsra); x64=1;
3786                                               sa += 32; break;
3787                          }                          }
3788                          ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];                          ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
3789                          ic->arg[1] = sa;                          if (sa >= 0)
3790                                    ic->arg[1] = sa;
3791                            else
3792                                    ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rs];
3793                          ic->arg[2] = (size_t)&cpu->cd.mips.gpr[rd];                          ic->arg[2] = (size_t)&cpu->cd.mips.gpr[rd];
3794                          if (rd == MIPS_GPR_ZERO)                          if (rd == MIPS_GPR_ZERO)
3795                                  ic->f = instr(nop);                                  ic->f = instr(nop);
3796                            if (ic->f == instr(sll))
3797                                    cpu->cd.mips.combination_check = COMBINE(sll);
3798                          break;                          break;
3799    
3800                    case SPECIAL_ADD:
3801                  case SPECIAL_ADDU:                  case SPECIAL_ADDU:
3802                    case SPECIAL_SUB:
3803                  case SPECIAL_SUBU:                  case SPECIAL_SUBU:
3804                    case SPECIAL_DADD:
3805                  case SPECIAL_DADDU:                  case SPECIAL_DADDU:
3806                    case SPECIAL_DSUB:
3807                  case SPECIAL_DSUBU:                  case SPECIAL_DSUBU:
3808                  case SPECIAL_SLT:                  case SPECIAL_SLT:
3809                  case SPECIAL_SLTU:                  case SPECIAL_SLTU:
3810                    case SPECIAL_AND:
3811                  case SPECIAL_OR:                  case SPECIAL_OR:
3812                  case SPECIAL_XOR:                  case SPECIAL_XOR:
3813                  case SPECIAL_NOR:                  case SPECIAL_NOR:
3814                    case SPECIAL_MOVN:
3815                    case SPECIAL_MOVZ:
3816                  case SPECIAL_MFHI:                  case SPECIAL_MFHI:
3817                  case SPECIAL_MFLO:                  case SPECIAL_MFLO:
3818                  case SPECIAL_MTHI:                  case SPECIAL_MTHI:
3819                  case SPECIAL_MTLO:                  case SPECIAL_MTLO:
3820                    case SPECIAL_DIV:
3821                    case SPECIAL_DIVU:
3822                    case SPECIAL_DDIV:
3823                    case SPECIAL_DDIVU:
3824                    case SPECIAL_MULT:
3825                    case SPECIAL_MULTU:
3826                    case SPECIAL_DMULT:
3827                    case SPECIAL_DMULTU:
3828                    case SPECIAL_TGE:
3829                    case SPECIAL_TGEU:
3830                    case SPECIAL_TLT:
3831                    case SPECIAL_TLTU:
3832                    case SPECIAL_TEQ:
3833                    case SPECIAL_TNE:
3834                          switch (s6) {                          switch (s6) {
3835                            case SPECIAL_ADD:   ic->f = instr(add); break;
3836                          case SPECIAL_ADDU:  ic->f = instr(addu); break;                          case SPECIAL_ADDU:  ic->f = instr(addu); break;
3837                            case SPECIAL_SUB:   ic->f = instr(sub); break;
3838                          case SPECIAL_SUBU:  ic->f = instr(subu); break;                          case SPECIAL_SUBU:  ic->f = instr(subu); break;
3839                            case SPECIAL_DADD:  ic->f = instr(dadd); x64=1; break;
3840                          case SPECIAL_DADDU: ic->f = instr(daddu); x64=1; break;                          case SPECIAL_DADDU: ic->f = instr(daddu); x64=1; break;
3841                            case SPECIAL_DSUB:  ic->f = instr(dsub); x64=1; break;
3842                          case SPECIAL_DSUBU: ic->f = instr(dsubu); x64=1; break;                          case SPECIAL_DSUBU: ic->f = instr(dsubu); x64=1; break;
3843                          case SPECIAL_SLT:   ic->f = instr(slt); break;                          case SPECIAL_SLT:   ic->f = instr(slt); break;
3844                          case SPECIAL_SLTU:  ic->f = instr(sltu); break;                          case SPECIAL_SLTU:  ic->f = instr(sltu); break;
3845                            case SPECIAL_AND:   ic->f = instr(and); break;
3846                          case SPECIAL_OR:    ic->f = instr(or); break;                          case SPECIAL_OR:    ic->f = instr(or); break;
3847                          case SPECIAL_XOR:   ic->f = instr(xor); break;                          case SPECIAL_XOR:   ic->f = instr(xor); break;
3848                          case SPECIAL_NOR:   ic->f = instr(nor); break;                          case SPECIAL_NOR:   ic->f = instr(nor); break;
# Line 704  X(to_be_translated) Line 3850  X(to_be_translated)
3850                          case SPECIAL_MFLO:  ic->f = instr(mov); break;                          case SPECIAL_MFLO:  ic->f = instr(mov); break;
3851                          case SPECIAL_MTHI:  ic->f = instr(mov); break;                          case SPECIAL_MTHI:  ic->f = instr(mov); break;
3852                          case SPECIAL_MTLO:  ic->f = instr(mov); break;                          case SPECIAL_MTLO:  ic->f = instr(mov); break;
3853                            case SPECIAL_DIV:   ic->f = instr(div); break;
3854                            case SPECIAL_DIVU:  ic->f = instr(divu); break;
3855                            case SPECIAL_DDIV:  ic->f = instr(ddiv); x64=1; break;
3856                            case SPECIAL_DDIVU: ic->f = instr(ddivu); x64=1; break;
3857                            case SPECIAL_MULT : ic->f = instr(mult); break;
3858                            case SPECIAL_MULTU: ic->f = instr(multu); break;
3859                            case SPECIAL_DMULT: ic->f = instr(dmult); x64=1; break;
3860                            case SPECIAL_DMULTU:ic->f = instr(dmultu); x64=1; break;
3861                            case SPECIAL_TGE:   ic->f = instr(tge); break;
3862                            case SPECIAL_TGEU:  ic->f = instr(tgeu); break;
3863                            case SPECIAL_TLT:   ic->f = instr(tlt); break;
3864                            case SPECIAL_TLTU:  ic->f = instr(tltu); break;
3865                            case SPECIAL_TEQ:   ic->f = instr(teq); break;
3866                            case SPECIAL_TNE:   ic->f = instr(tne); break;
3867                            case SPECIAL_MOVN:  ic->f = instr(movn); break;
3868                            case SPECIAL_MOVZ:  ic->f = instr(movz); break;
3869                          }                          }
3870                          ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];                          ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];
3871                          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 3884  X(to_be_translated)
3884                                  ic->arg[2] = (size_t)&cpu->cd.mips.lo;                                  ic->arg[2] = (size_t)&cpu->cd.mips.lo;
3885                                  break;                                  break;
3886                          }                          }
3887                          /*  rd==0 => nop:  */                          /*  Special cases for rd:  */
3888                          switch (s6) {                          switch (s6) {
3889                          case SPECIAL_MTHI:                          case SPECIAL_MTHI:
3890                          case SPECIAL_MTLO:                          case SPECIAL_MTLO:
3891                                  /*  These instructions don't use rd.  */                          case SPECIAL_DIV:
3892                                  break;                          case SPECIAL_DIVU:
3893                          default:if (rd == MIPS_GPR_ZERO)                          case SPECIAL_DDIV:
3894                                          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) {  
3895                          case SPECIAL_MULT:                          case SPECIAL_MULT:
3896                          case SPECIAL_MULTU:                          case SPECIAL_MULTU:
3897                          case SPECIAL_DMULT:                          case SPECIAL_DMULT:
3898                          case SPECIAL_DMULTU:                          case SPECIAL_DMULTU:
3899                                  ic->arg[2] = (size_t)&cpu->cd.mips.gpr[rd];                          case SPECIAL_TGE:
3900                            case SPECIAL_TGEU:
3901                            case SPECIAL_TLT:
3902                            case SPECIAL_TLTU:
3903                            case SPECIAL_TEQ:
3904                            case SPECIAL_TNE:
3905                                    if (s6 == SPECIAL_MULT && rd != MIPS_GPR_ZERO) {
3906                                            if (cpu->cd.mips.cpu_type.rev ==
3907                                                MIPS_R5900) {
3908                                                    ic->f = instr(mult_r5900);
3909                                                    break;
3910                                            }
3911                                            break;
3912                                    }
3913                                    if (s6 == SPECIAL_MULTU && rd!=MIPS_GPR_ZERO) {
3914                                            if (cpu->cd.mips.cpu_type.rev ==
3915                                                MIPS_R5900) {
3916                                                    ic->f = instr(multu_r5900);
3917                                                    break;
3918                                            }
3919                                    }
3920                                  if (rd != MIPS_GPR_ZERO) {                                  if (rd != MIPS_GPR_ZERO) {
3921                                          fatal("TODO: mult with rd NON-zero\n");                                          fatal("TODO: rd NON-zero\n");
3922                                          goto bad;                                          goto bad;
3923                                  }                                  }
3924                                    /*  These instructions don't use rd.  */
3925                                  break;                                  break;
3926                            default:if (rd == MIPS_GPR_ZERO)
3927                                            ic->f = instr(nop);
3928                          }                          }
3929    
3930                            if (ic->f == instr(addu))
3931                                    cpu->cd.mips.combination_check = COMBINE(addu);
3932                          break;                          break;
3933    
3934                  case SPECIAL_JR:                  case SPECIAL_JR:
3935                  case SPECIAL_JALR:                  case SPECIAL_JALR:
3936                          ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];                          ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];
3937                          ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rd];                          ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rd];
3938                          if (main_opcode == SPECIAL_JALR && rd == MIPS_GPR_ZERO)                          if (s6 == SPECIAL_JALR && rd == MIPS_GPR_ZERO)
3939                                  main_opcode = SPECIAL_JR;                                  s6 = SPECIAL_JR;
3940                          ic->arg[2] = (addr & 0xffc) + 4;                          ic->arg[2] = (addr & 0xffc) + 8;
3941                          switch (main_opcode) {                          switch (s6) {
3942                          case SPECIAL_JR:                          case SPECIAL_JR:
3943                                  if (rs == MIPS_GPR_RA) {                                  if (rs == MIPS_GPR_RA) {
3944                                          if (cpu->machine->show_trace_tree)                                          if (cpu->machine->show_trace_tree)
# Line 782  X(to_be_translated) Line 3956  X(to_be_translated)
3956                                          ic->f = instr(jalr);                                          ic->f = instr(jalr);
3957                                  break;                                  break;
3958                          }                          }
3959                          if (in_crosspage_delayslot) {                          if (cpu->delay_slot) {
3960                                  fatal("[ WARNING: branch in delay slot? ]\n");                                  fatal("TODO: branch in delay slot? (1)\n");
3961                                  ic->f = instr(nop);                                  goto bad;
3962                            }
3963                            break;
3964    
3965                    case SPECIAL_SYSCALL:
3966                            if (((iword >> 6) & 0xfffff) == 0x30378) {
3967                                    /*  "Magic trap" for PROM emulation:  */
3968                                    ic->f = instr(promemul);
3969                            } else {
3970                                    ic->f = instr(syscall);
3971                            }
3972                            break;
3973    
3974                    case SPECIAL_BREAK:
3975                            if (((iword >> 6) & 0xfffff) == 0x30378) {
3976                                    /*  "Magic trap" for REBOOT:  */
3977                                    ic->f = instr(reboot);
3978                            } else {
3979                                    ic->f = instr(break);
3980                          }                          }
3981                          break;                          break;
3982    
# Line 798  X(to_be_translated) Line 3990  X(to_be_translated)
3990    
3991          case HI6_BEQ:          case HI6_BEQ:
3992          case HI6_BNE:          case HI6_BNE:
3993            case HI6_BEQL:
3994            case HI6_BNEL:
3995            case HI6_BLEZ:
3996            case HI6_BLEZL:
3997            case HI6_BGTZ:
3998            case HI6_BGTZL:
3999                  samepage_function = NULL;  /*  get rid of a compiler warning  */                  samepage_function = NULL;  /*  get rid of a compiler warning  */
4000                  switch (main_opcode) {                  switch (main_opcode) {
4001                  case HI6_BEQ:                  case HI6_BEQ:
# Line 812  X(to_be_translated) Line 4010  X(to_be_translated)
4010                  case HI6_BNE:                  case HI6_BNE:
4011                          ic->f = instr(bne);                          ic->f = instr(bne);
4012                          samepage_function = instr(bne_samepage);                          samepage_function = instr(bne_samepage);
4013                            break;
4014                    case HI6_BEQL:
4015                            ic->f = instr(beql);
4016                            samepage_function = instr(beql_samepage);
4017                            /*  Special case: comparing a register with itself:  */
4018                            if (rs == rt) {
4019                                    ic->f = instr(b);
4020                                    samepage_function = instr(b_samepage);
4021                            }
4022                            break;
4023                    case HI6_BNEL:
4024                            ic->f = instr(bnel);
4025                            samepage_function = instr(bnel_samepage);
4026                            break;
4027                    case HI6_BLEZ:
4028                            ic->f = instr(blez);
4029                            samepage_function = instr(blez_samepage);
4030                            break;
4031                    case HI6_BLEZL:
4032                            ic->f = instr(blezl);
4033                            samepage_function = instr(blezl_samepage);
4034                            break;
4035                    case HI6_BGTZ:
4036                            ic->f = instr(bgtz);
4037                            samepage_function = instr(bgtz_samepage);
4038                            break;
4039                    case HI6_BGTZL:
4040                            ic->f = instr(bgtzl);
4041                            samepage_function = instr(bgtzl_samepage);
4042                            break;
4043                  }                  }
4044                  ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];                  ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];
4045                  ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rt];                  ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rt];
4046                  ic->arg[2] = (imm << MIPS_INSTR_ALIGNMENT_SHIFT)                  ic->arg[2] = (int32_t) ( (imm << MIPS_INSTR_ALIGNMENT_SHIFT)
4047                      + (addr & 0xffc) + 4;                      + (addr & 0xffc) + 4 );
4048                  /*  Is the offset from the start of the current page still                  /*  Is the offset from the start of the current page still
4049                      within the same page? Then use the samepage_function:  */                      within the same page? Then use the samepage_function:  */
4050                  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 4054  X(to_be_translated)
4054                              & (MIPS_IC_ENTRIES_PER_PAGE - 1)));                              & (MIPS_IC_ENTRIES_PER_PAGE - 1)));
4055                          ic->f = samepage_function;                          ic->f = samepage_function;
4056                  }                  }
4057                  if (in_crosspage_delayslot) {                  if (cpu->delay_slot) {
4058                          fatal("[ WARNING: branch in delay slot? ]\n");                          fatal("TODO: branch in delay slot? (2)\n");
4059                          ic->f = instr(nop);                          goto bad;
4060                  }                  }
4061                  break;                  break;
4062    
4063            case HI6_ADDI:
4064          case HI6_ADDIU:          case HI6_ADDIU:
4065            case HI6_SLTI:
4066            case HI6_SLTIU:
4067            case HI6_DADDI:
4068          case HI6_DADDIU:          case HI6_DADDIU:
4069          case HI6_ANDI:          case HI6_ANDI:
4070          case HI6_ORI:          case HI6_ORI:
# Line 841  X(to_be_translated) Line 4073  X(to_be_translated)
4073                  ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rt];                  ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rt];
4074                  if (main_opcode == HI6_ADDI ||                  if (main_opcode == HI6_ADDI ||
4075                      main_opcode == HI6_ADDIU ||                      main_opcode == HI6_ADDIU ||
4076                        main_opcode == HI6_SLTI ||
4077                        main_opcode == HI6_SLTIU ||
4078                      main_opcode == HI6_DADDI ||                      main_opcode == HI6_DADDI ||
4079                      main_opcode == HI6_DADDIU)                      main_opcode == HI6_DADDIU)
4080                          ic->arg[2] = (int16_t)iword;                          ic->arg[2] = (int16_t)iword;
4081                  else                  else
4082                          ic->arg[2] = (uint16_t)iword;                          ic->arg[2] = (uint16_t)iword;
4083    
4084                  switch (main_opcode) {                  switch (main_opcode) {
4085                    case HI6_ADDI:    ic->f = instr(addi); break;
4086                  case HI6_ADDIU:   ic->f = instr(addiu); break;                  case HI6_ADDIU:   ic->f = instr(addiu); break;
4087                    case HI6_SLTI:    ic->f = instr(slti); break;
4088                    case HI6_SLTIU:   ic->f = instr(sltiu); break;
4089                    case HI6_DADDI:   ic->f = instr(daddi); x64 = 1; break;
4090                  case HI6_DADDIU:  ic->f = instr(daddiu); x64 = 1; break;                  case HI6_DADDIU:  ic->f = instr(daddiu); x64 = 1; break;
4091                  case HI6_ANDI:    ic->f = instr(andi); break;                  case HI6_ANDI:    ic->f = instr(andi); break;
4092                  case HI6_ORI:     ic->f = instr(ori); break;                  case HI6_ORI:     ic->f = instr(ori); break;
4093                  case HI6_XORI:    ic->f = instr(xori); break;                  case HI6_XORI:    ic->f = instr(xori); break;
4094                  }                  }
4095    
4096                    if (ic->arg[2] == 0) {
4097                            if ((cpu->is_32bit && ic->f == instr(addiu)) ||
4098                                (!cpu->is_32bit && ic->f == instr(daddiu))) {
4099                                    ic->f = instr(mov);
4100                                    ic->arg[2] = ic->arg[1];
4101                            }
4102                    }
4103    
4104                  if (rt == MIPS_GPR_ZERO)                  if (rt == MIPS_GPR_ZERO)
4105                          ic->f = instr(nop);                          ic->f = instr(nop);
4106    
4107                    if (ic->f == instr(ori))
4108                            cpu->cd.mips.combination_check = COMBINE(ori);
4109                  if (ic->f == instr(addiu))                  if (ic->f == instr(addiu))
4110                          cpu->cd.mips.combination_check = COMBINE(b_addiu);                          cpu->cd.mips.combination_check = COMBINE(addiu);
4111                    if (ic->f == instr(daddiu))
4112                            cpu->cd.mips.combination_check = COMBINE(b_daddiu);
4113                  break;                  break;
4114    
4115          case HI6_LUI:          case HI6_LUI:
4116                  ic->f = instr(set);                  ic->f = instr(set);
4117                  ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];                  ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
4118                  ic->arg[1] = imm << 16;                  ic->arg[1] = (int32_t) (imm << 16);
4119                    /*  NOTE: Don't use arg[2] here. It can be used with
4120                        instruction combinations, to do lui + addiu, etc.  */
4121                  if (rt == MIPS_GPR_ZERO)                  if (rt == MIPS_GPR_ZERO)
4122                          ic->f = instr(nop);                          ic->f = instr(nop);
4123                  break;                  break;
4124    
4125            case HI6_J:
4126            case HI6_JAL:
4127                    switch (main_opcode) {
4128                    case HI6_J:
4129                            ic->f = instr(j);
4130                            break;
4131                    case HI6_JAL:
4132                            if (cpu->machine->show_trace_tree)
4133                                    ic->f = instr(jal_trace);
4134                            else
4135                                    ic->f = instr(jal);
4136                            break;
4137                    }
4138                    ic->arg[0] = (iword & 0x03ffffff) << 2;
4139                    ic->arg[1] = (addr & 0xffc) + 8;
4140                    if (cpu->delay_slot) {
4141                            fatal("TODO: branch in delay slot (=%i)? (3); addr=%016"
4142                                PRIx64" iword=%08"PRIx32"\n", cpu->delay_slot,
4143                                (uint64_t)addr, iword);
4144                            goto bad;
4145                    }
4146                    break;
4147    
4148          case HI6_COP0:          case HI6_COP0:
4149                    /*  TODO: Is checking bit 25 enough, or perhaps all bits
4150                        25..21 must be checked?  */
4151                    if ((iword >> 25) & 1) {
4152                            ic->arg[2] = addr & 0xffc;
4153                            switch (iword & 0xff) {
4154                            case COP0_TLBR:
4155                                    ic->f = instr(tlbr);
4156                                    break;
4157                            case COP0_TLBWI:
4158                            case COP0_TLBWR:
4159                                    ic->f = instr(tlbw);
4160                                    ic->arg[0] = (iword & 0xff) == COP0_TLBWR;
4161                                    break;
4162                            case COP0_TLBP:
4163                                    ic->f = instr(tlbp);
4164                                    break;
4165                            case COP0_RFE:
4166                                    ic->f = instr(rfe);
4167                                    break;
4168                            case COP0_ERET:
4169                                    ic->f = instr(eret);
4170                                    break;
4171                            case COP0_DERET:
4172                                    ic->f = instr(deret);
4173                                    break;
4174                            case COP0_WAIT:
4175                                    ic->f = instr(wait);
4176                                    if (cpu->cd.mips.cpu_type.rev != MIPS_RM5200 &&
4177                                        cpu->cd.mips.cpu_type.isa_level < 32) {
4178                                            static int warned = 0;
4179                                            ic->f = instr(reserved);
4180                                            if (!warned) {
4181                                                    fatal("{ WARNING: Attempt to "
4182                                                        "execute the WAIT instruct"
4183                                                        "ion, but the emulated CPU "
4184                                                        "is neither RM52xx, nor "
4185                                                        "MIPS32/64! }\n");
4186                                                    warned = 1;
4187                                            }
4188                                    }
4189                                    break;
4190                            case COP0_STANDBY:
4191                            case COP0_SUSPEND:
4192                            case COP0_HIBERNATE:
4193                                    /*  TODO  */
4194                                    ic->f = instr(nop);
4195                                    break;
4196                            case COP0_EI:
4197                                    if (cpu->cd.mips.cpu_type.rev == MIPS_R5900) {
4198                                            ic->f = instr(ei_r5900);
4199                                    } else
4200                                            goto bad;
4201                                    break;
4202                            case COP0_DI:
4203                                    if (cpu->cd.mips.cpu_type.rev == MIPS_R5900) {
4204                                            ic->f = instr(di_r5900);
4205                                    } else
4206                                            goto bad;
4207                                    break;
4208                            default:fatal("UNIMPLEMENTED cop0 (func 0x%02x)\n",
4209                                        iword & 0xff);
4210                                    goto bad;
4211                            }
4212                            break;
4213                    }
4214    
4215                  /*  rs contains the coprocessor opcode!  */                  /*  rs contains the coprocessor opcode!  */
4216                  switch (rs) {                  switch (rs) {
4217                    case COPz_CFCz:
4218                            ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
4219                            ic->arg[1] = rd + ((iword & 7) << 5);
4220                            ic->arg[2] = addr & 0xffc;
4221                            ic->f = instr(cfc0);
4222                            if (rt == MIPS_GPR_ZERO)
4223                                    ic->f = instr(nop);
4224                            break;
4225                  case COPz_MFCz:                  case COPz_MFCz:
4226                  case COPz_DMFCz:                  case COPz_DMFCz:
4227                          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 4237  X(to_be_translated)
4237                          ic->arg[1] = rd + ((iword & 7) << 5);                          ic->arg[1] = rd + ((iword & 7) << 5);
4238                          ic->arg[2] = addr & 0xffc;                          ic->arg[2] = addr & 0xffc;
4239                          ic->f = rs == COPz_MTCz? instr(mtc0) : instr(dmtc0);                          ic->f = rs == COPz_MTCz? instr(mtc0) : instr(dmtc0);
4240    
4241                            if (cpu->cd.mips.cpu_type.exc_model == EXC3K &&
4242                                rs == COPz_MTCz && rd == COP0_STATUS)
4243                                    cpu->cd.mips.combination_check =
4244                                        COMBINE(netbsd_r3k_cache_inv);
4245    
4246                          break;                          break;
4247                    case 8: if (iword == 0x4100ffff) {
4248                                    /*  R2020 DECstation write-loop thingy.  */
4249                                    ic->f = instr(nop);
4250                            } else {
4251                                    fatal("Unimplemented blah blah zzzz...\n");
4252                                    goto bad;
4253                            }
4254                            break;
4255                    
4256                  default:fatal("UNIMPLEMENTED cop0 (rs = %i)\n", rs);                  default:fatal("UNIMPLEMENTED cop0 (rs = %i)\n", rs);
4257                          goto bad;                          goto bad;
4258                  }                  }
4259                  break;                  break;
4260    
4261          case HI6_COP1:          case HI6_COP1:
4262                  /*  rs contains the coprocessor opcode!  */                  /*  Always cause a coprocessor unusable exception if
4263                        there is no floating point coprocessor:  */
4264                    if (cpu->cd.mips.cpu_type.flags & NOFPU ||
4265                        cpu->cd.mips.coproc[1] == NULL) {
4266                            ic->f = instr(cpu);
4267                            ic->arg[0] = 1;
4268                            break;
4269                    }
4270    
4271                    /*  Bits 25..21 are floating point main opcode:  */
4272                  switch (rs) {                  switch (rs) {
4273    
4274                    case COPz_BCzc:
4275                            /*  Conditional branch:  */
4276                            /*  TODO: Reimplement this in a faster way.  */
4277                            ic->f = instr(cop1_bc);
4278                            ic->arg[0] = (iword >> 18) & 7; /*  cc  */
4279                            ic->arg[1] = (iword >> 16) & 3; /*  nd, tf bits  */
4280                            ic->arg[2] = (int32_t) ((imm <<
4281                                MIPS_INSTR_ALIGNMENT_SHIFT) + (addr & 0xffc) + 4);
4282                            if (cpu->delay_slot) {
4283                                    fatal("TODO: branch in delay slot? (4)\n");
4284                                    goto bad;
4285                            }
4286                            if (cpu->cd.mips.cpu_type.isa_level <= 3 &&
4287                                ic->arg[0] != 0) {
4288                                    fatal("Attempt to execute a non-cc-0 BC*"
4289                                        " instruction on an isa level %i cpu. "
4290                                        "TODO: How should this be handled?\n",
4291                                        cpu->cd.mips.cpu_type.isa_level);
4292                                    goto bad;
4293                            }
4294    
4295                            break;
4296    
4297                    case COPz_DMFCz:
4298                    case COPz_DMTCz:
4299                            x64 = 1;
4300                            /*  FALL-THROUGH  */
4301                    case COP1_FMT_S:
4302                    case COP1_FMT_D:
4303                    case COP1_FMT_W:
4304                    case COP1_FMT_L:
4305                    case COP1_FMT_PS:
4306                  case COPz_CFCz:                  case COPz_CFCz:
4307                          ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];                  case COPz_CTCz:
4308                          ic->arg[1] = (size_t)&cpu->cd.mips.coproc[1]->fcr[rd];                  case COPz_MFCz:
4309                          ic->arg[2] = addr & 0xffc;                  case COPz_MTCz:
4310                          ic->f = instr(cfc1);                          /*  Fallback to slow pre-dyntrans code, for now.  */
4311                          if (rt == MIPS_GPR_ZERO)                          /*  TODO: Fix/optimize/rewrite.  */
4312                                  ic->f = instr(nop);                          ic->f = instr(cop1_slow);
4313                            ic->arg[0] = (uint32_t)iword & ((1 << 26) - 1);
4314                          break;                          break;
4315                  default:fatal("UNIMPLEMENTED cop1 (rs = %i)\n", rs);  
4316                    default:fatal("COP1 floating point opcode = 0x%02x\n", rs);
4317                          goto bad;                          goto bad;
4318                  }                  }
4319                  break;                  break;
4320    
4321            case HI6_COP2:
4322                    /*  Always cause a coprocessor unusable exception if
4323                        there is no coprocessor 2:  */
4324                    if (cpu->cd.mips.coproc[2] == NULL) {
4325                            ic->f = instr(cpu);
4326                            ic->arg[0] = 2;
4327                            break;
4328                    }
4329                    fatal("COP2 functionality not yet implemented\n");
4330                    goto bad;
4331                    break;
4332    
4333          case HI6_SPECIAL2:          case HI6_SPECIAL2:
4334                    if (cpu->cd.mips.cpu_type.rev == MIPS_R5900) {
4335                            /*  R5900, TX79/C790, have MMI instead of SPECIAL2:  */
4336                            int mmi_subopcode = (iword >> 6) & 0x1f;
4337    
4338                            switch (s6) {
4339    
4340                            case MMI_MADD:
4341                                    ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];
4342                                    ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rt];
4343                                    ic->arg[2] = (size_t)&cpu->cd.mips.gpr[rd];
4344                                    if (rd == MIPS_GPR_ZERO)
4345                                            ic->f = instr(madd);
4346                                    else
4347                                            ic->f = instr(madd_rd);
4348                                    break;
4349    
4350                            case MMI_MADDU:
4351                                    ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];
4352                                    ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rt];
4353                                    ic->arg[2] = (size_t)&cpu->cd.mips.gpr[rd];
4354                                    if (rd == MIPS_GPR_ZERO)
4355                                            ic->f = instr(maddu);
4356                                    else
4357                                            ic->f = instr(maddu_rd);
4358                                    break;
4359    
4360                            case MMI_MMI0:
4361                                    switch (mmi_subopcode) {
4362    
4363                                    case MMI0_PEXTLW:
4364                                            ic->arg[0] = rs;
4365                                            ic->arg[1] = rt;
4366                                            ic->arg[2] = rd;
4367                                            if (rd == MIPS_GPR_ZERO)
4368                                                    ic->f = instr(nop);
4369                                            else
4370                                                    ic->f = instr(pextlw);
4371                                            break;
4372    
4373                                    default:goto bad;
4374                                    }
4375                                    break;
4376    
4377                            case MMI_MMI3:
4378                                    switch (mmi_subopcode) {
4379    
4380                                    case MMI3_POR:
4381                                            ic->arg[0] = rs;
4382                                            ic->arg[1] = rt;
4383                                            ic->arg[2] = rd;
4384                                            if (rd == MIPS_GPR_ZERO)
4385                                                    ic->f = instr(nop);
4386                                            else
4387                                                    ic->f = instr(por);
4388                                            break;
4389    
4390                                    default:goto bad;
4391                                    }
4392                                    break;
4393    
4394                            default:goto bad;
4395                            }
4396                            break;
4397                    }
4398    
4399                    /*  TODO: is this correct? Or are there other non-MIPS32/64
4400                        MIPS processors that have support for SPECIAL2 opcodes?  */
4401                    if (cpu->cd.mips.cpu_type.isa_level < 32) {
4402                            ic->f = instr(reserved);
4403                            break;
4404                    }
4405    
4406                    /*  SPECIAL2:  */
4407                  switch (s6) {                  switch (s6) {
4408    
4409                    case SPECIAL2_MADD:
4410                    case SPECIAL2_MADDU:
4411                    case SPECIAL2_MSUB:
4412                    case SPECIAL2_MSUBU:
4413                            ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];
4414                            ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rt];
4415                            switch (s6) {
4416                            case SPECIAL2_MADD: ic->f = instr(madd); break;
4417                            case SPECIAL2_MADDU:ic->f = instr(maddu); break;
4418                            case SPECIAL2_MSUB: ic->f = instr(msub); break;
4419                            case SPECIAL2_MSUBU:ic->f = instr(msubu); break;
4420                            }
4421                            break;
4422    
4423                  case SPECIAL2_MUL:                  case SPECIAL2_MUL:
4424                          ic->f = instr(mul);                          ic->f = instr(mul);
4425                          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 4449  X(to_be_translated)
4449                  }                  }
4450                  break;                  break;
4451    
4452            case HI6_REGIMM:
4453                    switch (rt) {
4454                    case REGIMM_BGEZ:
4455                    case REGIMM_BGEZL:
4456                    case REGIMM_BLTZ:
4457                    case REGIMM_BLTZL:
4458                    case REGIMM_BGEZAL:
4459                    case REGIMM_BGEZALL:
4460                    case REGIMM_BLTZAL:
4461                    case REGIMM_BLTZALL:
4462                            samepage_function = NULL;
4463                            switch (rt) {
4464                            case REGIMM_BGEZ:
4465                                    ic->f = instr(bgez);
4466                                    samepage_function = instr(bgez_samepage);
4467                                    break;
4468                            case REGIMM_BGEZL:
4469                                    ic->f = instr(bgezl);
4470                                    samepage_function = instr(bgezl_samepage);
4471                                    break;
4472                            case REGIMM_BLTZ:
4473                                    ic->f = instr(bltz);
4474                                    samepage_function = instr(bltz_samepage);
4475                                    break;
4476                            case REGIMM_BLTZL:
4477                                    ic->f = instr(bltzl);
4478                                    samepage_function = instr(bltzl_samepage);
4479                                    break;
4480                            case REGIMM_BGEZAL:
4481                                    ic->f = instr(bgezal);
4482                                    samepage_function = instr(bgezal_samepage);
4483                                    break;
4484                            case REGIMM_BGEZALL:
4485                                    ic->f = instr(bgezall);
4486                                    samepage_function = instr(bgezall_samepage);
4487                                    break;
4488                            case REGIMM_BLTZAL:
4489                                    ic->f = instr(bltzal);
4490                                    samepage_function = instr(bltzal_samepage);
4491                                    break;
4492                            case REGIMM_BLTZALL:
4493                                    ic->f = instr(bltzall);
4494                                    samepage_function = instr(bltzall_samepage);
4495                                    break;
4496                            }
4497                            ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];
4498                            ic->arg[2] = (imm << MIPS_INSTR_ALIGNMENT_SHIFT)
4499                                + (addr & 0xffc) + 4;
4500                            /*  Is the offset from the start of the current page
4501                                still within the same page? Then use the
4502                                samepage_function:  */
4503                            if ((uint32_t)ic->arg[2] < ((MIPS_IC_ENTRIES_PER_PAGE-1)
4504                                << MIPS_INSTR_ALIGNMENT_SHIFT) && (addr & 0xffc)
4505                                < 0xffc) {
4506                                    ic->arg[2] = (size_t) (cpu->cd.mips.cur_ic_page+
4507                                        ((ic->arg[2] >> MIPS_INSTR_ALIGNMENT_SHIFT)
4508                                        & (MIPS_IC_ENTRIES_PER_PAGE - 1)));
4509                                    ic->f = samepage_function;
4510                            }
4511                            if (cpu->delay_slot) {
4512                                    fatal("TODO: branch in delay slot? (5)\n");
4513                                    goto bad;
4514                            }
4515                            break;
4516                    default:fatal("UNIMPLEMENTED regimm rt=%i\n", rt);
4517                            goto bad;
4518                    }
4519                    break;
4520    
4521            case HI6_LB:
4522            case HI6_LBU:
4523            case HI6_SB:
4524            case HI6_LH:
4525            case HI6_LHU:
4526            case HI6_SH:
4527            case HI6_LW:
4528            case HI6_LWU:
4529            case HI6_SW:
4530            case HI6_LD:
4531            case HI6_SD:
4532                    /*  TODO: LWU should probably also be x64=1?  */
4533                    size = 2; signedness = 0; store = 0;
4534                    switch (main_opcode) {
4535                    case HI6_LB:  size = 0; signedness = 1; break;
4536                    case HI6_LBU: size = 0; break;
4537                    case HI6_LH:  size = 1; signedness = 1; break;
4538                    case HI6_LHU: size = 1; break;
4539                    case HI6_LW:  signedness = 1; break;
4540                    case HI6_LWU: break;
4541                    case HI6_LD:  size = 3; x64 = 1; break;
4542                    case HI6_SB:  store = 1; size = 0; break;
4543                    case HI6_SH:  store = 1; size = 1; break;
4544                    case HI6_SW:  store = 1; break;
4545                    case HI6_SD:  store = 1; size = 3; x64 = 1; break;
4546                    }
4547    
4548                    ic->f =
4549    #ifdef MODE32
4550                        mips32_loadstore
4551    #else
4552                        mips_loadstore
4553    #endif
4554                        [ (cpu->byte_order == EMUL_LITTLE_ENDIAN? 0 : 16)
4555                        + store * 8 + size * 2 + signedness];
4556                    ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
4557                    ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rs];
4558                    ic->arg[2] = (int32_t)imm;
4559    
4560                    /*  Load into the dummy scratch register, if rt = zero  */
4561                    if (!store && rt == MIPS_GPR_ZERO)
4562                            ic->arg[0] = (size_t)&cpu->cd.mips.scratch;
4563    
4564                    /*  Check for multiple loads or stores in a row using the same
4565                        base register:  */
4566    #ifdef MODE32
4567                    if (main_opcode == HI6_LW)
4568                            cpu->cd.mips.combination_check = COMBINE(multi_lw);
4569                    if (main_opcode == HI6_SW)
4570                            cpu->cd.mips.combination_check = COMBINE(multi_sw);
4571    #endif
4572                    break;
4573    
4574            case HI6_LL:
4575            case HI6_LLD:
4576            case HI6_SC:
4577            case HI6_SCD:
4578                    /*  32-bit load-linked/store-condition for ISA II and up:  */
4579                    /*  (64-bit load-linked/store-condition for ISA III...)  */
4580                    if (cpu->cd.mips.cpu_type.isa_level < 2) {
4581                            ic->f = instr(reserved);
4582                            break;
4583                    }
4584    
4585                    store = 0;
4586                    switch (main_opcode) {
4587                    case HI6_LL:  ic->f = instr(ll); break;
4588                    case HI6_LLD: ic->f = instr(lld); x64 = 1; break;
4589                    case HI6_SC:  ic->f = instr(sc); store = 1; break;
4590                    case HI6_SCD: ic->f = instr(scd); store = 1; x64 = 1; break;
4591                    }
4592                    ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
4593                    ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rs];
4594                    ic->arg[2] = (int32_t)imm;
4595                    if (!store && rt == MIPS_GPR_ZERO) {
4596                            fatal("HM... unusual load linked\n");
4597                            goto bad;
4598                    }
4599                    break;
4600    
4601            case HI6_LWL:
4602            case HI6_LWR:
4603            case HI6_LDL:
4604            case HI6_LDR:
4605            case HI6_SWL:
4606            case HI6_SWR:
4607            case HI6_SDL:
4608            case HI6_SDR:
4609                    /*  TODO: replace these with faster versions...  */
4610                    store = 0;
4611                    switch (main_opcode) {
4612                    case HI6_LWL: ic->f = instr(lwl); break;
4613                    case HI6_LWR: ic->f = instr(lwr); break;
4614                    case HI6_LDL: ic->f = instr(ldl); x64 = 1; break;
4615                    case HI6_LDR: ic->f = instr(ldr); x64 = 1; break;
4616                    case HI6_SWL: ic->f = instr(swl); store = 1; break;
4617                    case HI6_SWR: ic->f = instr(swr); store = 1; break;
4618                    case HI6_SDL: ic->f = instr(sdl); store = 1; x64 = 1; break;
4619                    case HI6_SDR: ic->f = instr(sdr); store = 1; x64 = 1; break;
4620                    }
4621                    ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
4622                    ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rs];
4623                    ic->arg[2] = (int32_t)imm;
4624    
4625                    /*  Load into the dummy scratch register, if rt = zero  */
4626                    if (!store && rt == MIPS_GPR_ZERO)
4627                            ic->arg[0] = (size_t)&cpu->cd.mips.scratch;
4628                    break;
4629    
4630            case HI6_LWC1:
4631            case HI6_SWC1:
4632            case HI6_LDC1:
4633            case HI6_SDC1:
4634                    /*  64-bit floating-point load/store for ISA II and up...  */
4635                    if ((main_opcode == HI6_LDC1 || main_opcode == HI6_SDC1)
4636                        && cpu->cd.mips.cpu_type.isa_level < 2) {
4637                            ic->f = instr(reserved);
4638                            break;
4639                    }
4640    
4641                    ic->arg[0] = (size_t)&cpu->cd.mips.coproc[1]->reg[rt];
4642                    ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rs];
4643                    ic->arg[2] = (int32_t)imm;
4644                    switch (main_opcode) {
4645                    case HI6_LWC1: ic->f = instr(lwc1); break;
4646                    case HI6_LDC1: ic->f = instr(ldc1); break;
4647                    case HI6_SWC1: ic->f = instr(swc1); break;
4648                    case HI6_SDC1: ic->f = instr(sdc1); break;
4649                    }
4650    
4651                    /*  Cause a coprocessor unusable exception if
4652                        there is no floating point coprocessor:  */
4653                    if (cpu->cd.mips.cpu_type.flags & NOFPU ||
4654                        cpu->cd.mips.coproc[1] == NULL) {
4655                            ic->f = instr(cpu);
4656                            ic->arg[0] = 1;
4657                    }
4658                    break;
4659    
4660            case HI6_LWC3:
4661                    /*  PREF (prefetch) on ISA IV and MIPS32/64:  */
4662                    if (cpu->cd.mips.cpu_type.isa_level >= 4) {
4663                            /*  Treat as nop for now:  */
4664                            ic->f = instr(nop);
4665                    } else {
4666                            fatal("TODO: lwc3 not implemented yet\n");
4667                            goto bad;
4668                    }
4669                    break;
4670    
4671            case HI6_LQ_MDMX:
4672                    if (cpu->cd.mips.cpu_type.rev == MIPS_R5900) {
4673                            fatal("TODO: R5900 128-bit loads\n");
4674                            goto bad;
4675                    }
4676    
4677                    fatal("TODO: MDMX\n");
4678                    goto bad;
4679                    /*  break  */
4680    
4681            case HI6_SQ_SPECIAL3:
4682                    if (cpu->cd.mips.cpu_type.rev == MIPS_R5900) {
4683                            fatal("TODO: R5900 128-bit stores\n");
4684                            goto bad;
4685                    }
4686    
4687                    if (cpu->cd.mips.cpu_type.isa_level < 32 ||
4688                        cpu->cd.mips.cpu_type.isa_revision < 2) {
4689                            static int warning = 0;
4690                            if (!warning) {
4691                                    fatal("[ WARNING! SPECIAL3 opcode used, but"
4692                                        " the %s processor does not implement "
4693                                        "such instructions. Only printing this "
4694                                        "warning once. ]\n",
4695                                        cpu->cd.mips.cpu_type.name);
4696                                    warning = 1;
4697                            }
4698                            ic->f = instr(reserved);
4699                            break;
4700                    }
4701    
4702                    switch (s6) {
4703    
4704                    case SPECIAL3_RDHWR:
4705                            ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
4706    
4707                            switch (rd) {
4708    
4709                            case 0: ic->f = instr(rdhwr_cpunum);
4710                                    if (rt == MIPS_GPR_ZERO)
4711                                            ic->f = instr(nop);
4712                                    break;
4713    
4714                            default:fatal("unimplemented rdhwr register rd=%i\n",
4715                                        rd);
4716                                    goto bad;
4717                            }
4718                            break;
4719    
4720                    default:goto bad;
4721                    }
4722                    break;
4723    
4724            case HI6_CACHE:
4725                    /*  TODO: rt and op etc...  */
4726                    ic->f = instr(cache);
4727                    break;
4728    
4729          default:goto bad;          default:goto bad;
4730          }          }
4731    
4732          if (x64)  #ifdef MODE32
4733                  ic->f = instr(invalid_32_64);          if (x64) {
4734                    static int has_warned = 0;
4735                    if (!has_warned)
4736                            fatal("[ WARNING/NOTE: attempt to execute a 64-bit"
4737                                " instruction on an emulated 32-bit processor; "
4738                                "pc=0x%08"PRIx32" ]\n", (uint32_t)cpu->pc);
4739                    has_warned = 1;
4740                    ic->f = instr(reserved);
4741            }
4742    #endif
4743    
4744            if (ic->f == instr(nop) && cpu->cd.mips.combination_check == NULL)
4745                    cpu->cd.mips.combination_check = COMBINE(nop);
4746    
         if (in_crosspage_delayslot)  
                 cpu->cd.mips.combination_check = NULL;  
4747    
4748  #define DYNTRANS_TO_BE_TRANSLATED_TAIL  #define DYNTRANS_TO_BE_TRANSLATED_TAIL
4749  #include "cpu_dyntrans.c"  #include "cpu_dyntrans.c"

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

  ViewVC Help
Powered by ViewVC 1.1.26