/[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 24 by dpavlin, Mon Oct 8 16:19:56 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.85 2006/06/22 13:22:41 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(bne)  X(bne)
139  {  {
140          MODE_uint_t old_pc = cpu->pc;          MODE_int_t old_pc = cpu->pc;
141          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]);
142          int x = rs != rt;          int x = rs != rt;
143          cpu->cd.mips.delay_slot = TO_BE_DELAYED;          cpu->delay_slot = TO_BE_DELAYED;
144          ic[1].f(cpu, ic+1);          ic[1].f(cpu, ic+1);
145          cpu->n_translated_instrs ++;          cpu->n_translated_instrs ++;
146          if (!(cpu->cd.mips.delay_slot & EXCEPTION_IN_DELAY_SLOT)) {          if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
147                    /*  Note: Must be non-delayed when jumping to the new pc:  */
148                    cpu->delay_slot = NOT_DELAYED;
149                  if (x) {                  if (x) {
150                          old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<                          old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
151                              MIPS_INSTR_ALIGNMENT_SHIFT);                              MIPS_INSTR_ALIGNMENT_SHIFT);
# Line 115  X(bne) Line 153  X(bne)
153                          quick_pc_to_pointers(cpu);                          quick_pc_to_pointers(cpu);
154                  } else                  } else
155                          cpu->cd.mips.next_ic ++;                          cpu->cd.mips.next_ic ++;
156          }          } else
157          cpu->cd.mips.delay_slot = NOT_DELAYED;                  cpu->delay_slot = NOT_DELAYED;
158  }  }
159  X(bne_samepage)  X(bne_samepage)
160  {  {
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                  if (x)                  if (x)
168                          cpu->cd.mips.next_ic = (struct mips_instr_call *)                          cpu->cd.mips.next_ic = (struct mips_instr_call *)
169                              ic->arg[2];                              ic->arg[2];
170                  else                  else
171                          cpu->cd.mips.next_ic ++;                          cpu->cd.mips.next_ic ++;
172          }          }
173          cpu->cd.mips.delay_slot = NOT_DELAYED;          cpu->delay_slot = NOT_DELAYED;
174  }  }
175  X(b)  X(b)
176  {  {
177          MODE_uint_t old_pc = cpu->pc;          MODE_int_t old_pc = cpu->pc;
178          cpu->cd.mips.delay_slot = TO_BE_DELAYED;          cpu->delay_slot = TO_BE_DELAYED;
179          ic[1].f(cpu, ic+1);          ic[1].f(cpu, ic+1);
180          cpu->n_translated_instrs ++;          cpu->n_translated_instrs ++;
181          if (!(cpu->cd.mips.delay_slot & EXCEPTION_IN_DELAY_SLOT)) {          if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
182                    /*  Note: Must be non-delayed when jumping to the new pc:  */
183                    cpu->delay_slot = NOT_DELAYED;
184                  old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<                  old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
185                      MIPS_INSTR_ALIGNMENT_SHIFT);                      MIPS_INSTR_ALIGNMENT_SHIFT);
186                  cpu->pc = old_pc + (int32_t)ic->arg[2];                  cpu->pc = old_pc + (int32_t)ic->arg[2];
187                  quick_pc_to_pointers(cpu);                  quick_pc_to_pointers(cpu);
188          }          } else
189          cpu->cd.mips.delay_slot = NOT_DELAYED;                  cpu->delay_slot = NOT_DELAYED;
190  }  }
191  X(b_samepage)  X(b_samepage)
192  {  {
193          cpu->cd.mips.delay_slot = TO_BE_DELAYED;          cpu->delay_slot = TO_BE_DELAYED;
194          ic[1].f(cpu, ic+1);          ic[1].f(cpu, ic+1);
195          cpu->n_translated_instrs ++;          cpu->n_translated_instrs ++;
196          if (!(cpu->cd.mips.delay_slot & EXCEPTION_IN_DELAY_SLOT))          if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT))
197                  cpu->cd.mips.next_ic = (struct mips_instr_call *) ic->arg[2];                  cpu->cd.mips.next_ic = (struct mips_instr_call *) ic->arg[2];
198          cpu->cd.mips.delay_slot = NOT_DELAYED;          cpu->delay_slot = NOT_DELAYED;
199    }
200    
201    
202    /*
203     *  beql:  Branch if equal likely
204     *  bnel:  Branch if not equal likely
205     *
206     *  arg[0] = pointer to rs
207     *  arg[1] = pointer to rt
208     *  arg[2] = (int32_t) relative offset from the next instruction
209     */
210    X(beql)
211    {
212            MODE_int_t old_pc = cpu->pc;
213            MODE_uint_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]);
214            int x = rs == rt;
215            cpu->delay_slot = TO_BE_DELAYED;
216            if (x)
217                    ic[1].f(cpu, ic+1);
218            cpu->n_translated_instrs ++;
219            if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
220                    /*  Note: Must be non-delayed when jumping to the new pc:  */
221                    cpu->delay_slot = NOT_DELAYED;
222                    if (x) {
223                            old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
224                                MIPS_INSTR_ALIGNMENT_SHIFT);
225                            cpu->pc = old_pc + (int32_t)ic->arg[2];
226                            quick_pc_to_pointers(cpu);
227                    } else
228                            cpu->cd.mips.next_ic ++;
229            } else
230                    cpu->delay_slot = NOT_DELAYED;
231    }
232    X(beql_samepage)
233    {
234            MODE_uint_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]);
235            int x = rs == rt;
236            cpu->delay_slot = TO_BE_DELAYED;
237            if (x)
238                    ic[1].f(cpu, ic+1);
239            cpu->n_translated_instrs ++;
240            if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
241                    if (x)
242                            cpu->cd.mips.next_ic = (struct mips_instr_call *)
243                                ic->arg[2];
244                    else
245                            cpu->cd.mips.next_ic ++;
246            }
247            cpu->delay_slot = NOT_DELAYED;
248    }
249    X(bnel)
250    {
251            MODE_int_t old_pc = cpu->pc;
252            MODE_uint_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]);
253            int x = rs != rt;
254            cpu->delay_slot = TO_BE_DELAYED;
255            if (x)
256                    ic[1].f(cpu, ic+1);
257            cpu->n_translated_instrs ++;
258            if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
259                    /*  Note: Must be non-delayed when jumping to the new pc:  */
260                    cpu->delay_slot = NOT_DELAYED;
261                    if (x) {
262                            old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
263                                MIPS_INSTR_ALIGNMENT_SHIFT);
264                            cpu->pc = old_pc + (int32_t)ic->arg[2];
265                            quick_pc_to_pointers(cpu);
266                    } else
267                            cpu->cd.mips.next_ic ++;
268            } else
269                    cpu->delay_slot = NOT_DELAYED;
270    }
271    X(bnel_samepage)
272    {
273            MODE_uint_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]);
274            int x = rs != rt;
275            cpu->delay_slot = TO_BE_DELAYED;
276            if (x)
277                    ic[1].f(cpu, ic+1);
278            cpu->n_translated_instrs ++;
279            if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
280                    if (x)
281                            cpu->cd.mips.next_ic = (struct mips_instr_call *)
282                                ic->arg[2];
283                    else
284                            cpu->cd.mips.next_ic ++;
285            }
286            cpu->delay_slot = NOT_DELAYED;
287    }
288    
289    
290    /*
291     *  blez:   Branch if less than or equal
292     *  blezl:  Branch if less than or equal likely
293     *
294     *  arg[0] = pointer to rs
295     *  arg[2] = (int32_t) relative offset from the next instruction
296     */
297    X(blez)
298    {
299            MODE_int_t old_pc = cpu->pc;
300            MODE_int_t rs = reg(ic->arg[0]);
301            int x = (rs <= 0);
302            cpu->delay_slot = TO_BE_DELAYED;
303            ic[1].f(cpu, ic+1);
304            cpu->n_translated_instrs ++;
305            if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
306                    /*  Note: Must be non-delayed when jumping to the new pc:  */
307                    cpu->delay_slot = NOT_DELAYED;
308                    if (x) {
309                            old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
310                                MIPS_INSTR_ALIGNMENT_SHIFT);
311                            cpu->pc = old_pc + (int32_t)ic->arg[2];
312                            quick_pc_to_pointers(cpu);
313                    } else
314                            cpu->cd.mips.next_ic ++;
315            } else
316                    cpu->delay_slot = NOT_DELAYED;
317    }
318    X(blez_samepage)
319    {
320            MODE_int_t rs = reg(ic->arg[0]);
321            int x = (rs <= 0);
322            cpu->delay_slot = TO_BE_DELAYED;
323            ic[1].f(cpu, ic+1);
324            cpu->n_translated_instrs ++;
325            if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
326                    if (x)
327                            cpu->cd.mips.next_ic = (struct mips_instr_call *)
328                                ic->arg[2];
329                    else
330                            cpu->cd.mips.next_ic ++;
331            }
332            cpu->delay_slot = NOT_DELAYED;
333    }
334    X(blezl)
335    {
336            MODE_int_t old_pc = cpu->pc;
337            MODE_int_t rs = reg(ic->arg[0]);
338            int x = (rs <= 0);
339            cpu->delay_slot = TO_BE_DELAYED;
340            if (x)
341                    ic[1].f(cpu, ic+1);
342            cpu->n_translated_instrs ++;
343            if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
344                    /*  Note: Must be non-delayed when jumping to the new pc:  */
345                    cpu->delay_slot = NOT_DELAYED;
346                    if (x) {
347                            old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
348                                MIPS_INSTR_ALIGNMENT_SHIFT);
349                            cpu->pc = old_pc + (int32_t)ic->arg[2];
350                            quick_pc_to_pointers(cpu);
351                    } else
352                            cpu->cd.mips.next_ic ++;
353            } else
354                    cpu->delay_slot = NOT_DELAYED;
355    }
356    X(blezl_samepage)
357    {
358            MODE_int_t rs = reg(ic->arg[0]);
359            int x = (rs <= 0);
360            cpu->delay_slot = TO_BE_DELAYED;
361            if (x)
362                    ic[1].f(cpu, ic+1);
363            cpu->n_translated_instrs ++;
364            if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
365                    if (x)
366                            cpu->cd.mips.next_ic = (struct mips_instr_call *)
367                                ic->arg[2];
368                    else
369                            cpu->cd.mips.next_ic ++;
370            }
371            cpu->delay_slot = NOT_DELAYED;
372    }
373    
374    
375    /*
376     *  bltz:   Branch if less than
377     *  bltzl:  Branch if less than likely
378     *
379     *  arg[0] = pointer to rs
380     *  arg[2] = (int32_t) relative offset from the next instruction
381     */
382    X(bltz)
383    {
384            MODE_int_t old_pc = cpu->pc;
385            MODE_int_t rs = reg(ic->arg[0]);
386            int x = (rs < 0);
387            cpu->delay_slot = TO_BE_DELAYED;
388            ic[1].f(cpu, ic+1);
389            cpu->n_translated_instrs ++;
390            if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
391                    /*  Note: Must be non-delayed when jumping to the new pc:  */
392                    cpu->delay_slot = NOT_DELAYED;
393                    if (x) {
394                            old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
395                                MIPS_INSTR_ALIGNMENT_SHIFT);
396                            cpu->pc = old_pc + (int32_t)ic->arg[2];
397                            quick_pc_to_pointers(cpu);
398                    } else
399                            cpu->cd.mips.next_ic ++;
400            } else
401                    cpu->delay_slot = NOT_DELAYED;
402    }
403    X(bltz_samepage)
404    {
405            MODE_int_t rs = reg(ic->arg[0]);
406            int x = (rs < 0);
407            cpu->delay_slot = TO_BE_DELAYED;
408            ic[1].f(cpu, ic+1);
409            cpu->n_translated_instrs ++;
410            if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
411                    if (x)
412                            cpu->cd.mips.next_ic = (struct mips_instr_call *)
413                                ic->arg[2];
414                    else
415                            cpu->cd.mips.next_ic ++;
416            }
417            cpu->delay_slot = NOT_DELAYED;
418    }
419    X(bltzl)
420    {
421            MODE_int_t old_pc = cpu->pc;
422            MODE_int_t rs = reg(ic->arg[0]);
423            int x = (rs < 0);
424            cpu->delay_slot = TO_BE_DELAYED;
425            if (x)
426                    ic[1].f(cpu, ic+1);
427            cpu->n_translated_instrs ++;
428            if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
429                    /*  Note: Must be non-delayed when jumping to the new pc:  */
430                    cpu->delay_slot = NOT_DELAYED;
431                    if (x) {
432                            old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
433                                MIPS_INSTR_ALIGNMENT_SHIFT);
434                            cpu->pc = old_pc + (int32_t)ic->arg[2];
435                            quick_pc_to_pointers(cpu);
436                    } else
437                            cpu->cd.mips.next_ic ++;
438            } else
439                    cpu->delay_slot = NOT_DELAYED;
440    }
441    X(bltzl_samepage)
442    {
443            MODE_int_t rs = reg(ic->arg[0]);
444            int x = (rs < 0);
445            cpu->delay_slot = TO_BE_DELAYED;
446            if (x)
447                    ic[1].f(cpu, ic+1);
448            cpu->n_translated_instrs ++;
449            if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
450                    if (x)
451                            cpu->cd.mips.next_ic = (struct mips_instr_call *)
452                                ic->arg[2];
453                    else
454                            cpu->cd.mips.next_ic ++;
455            }
456            cpu->delay_slot = NOT_DELAYED;
457    }
458    
459    
460    /*
461     *  bgez:   Branch if greater than or equal
462     *  bgezl:  Branch if greater than or equal likely
463     *
464     *  arg[0] = pointer to rs
465     *  arg[2] = (int32_t) relative offset from the next instruction
466     */
467    X(bgez)
468    {
469            MODE_int_t old_pc = cpu->pc;
470            MODE_int_t rs = reg(ic->arg[0]);
471            int x = (rs >= 0);
472            cpu->delay_slot = TO_BE_DELAYED;
473            ic[1].f(cpu, ic+1);
474            cpu->n_translated_instrs ++;
475            if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
476                    /*  Note: Must be non-delayed when jumping to the new pc:  */
477                    cpu->delay_slot = NOT_DELAYED;
478                    if (x) {
479                            old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
480                                MIPS_INSTR_ALIGNMENT_SHIFT);
481                            cpu->pc = old_pc + (int32_t)ic->arg[2];
482                            quick_pc_to_pointers(cpu);
483                    } else
484                            cpu->cd.mips.next_ic ++;
485            } else
486                    cpu->delay_slot = NOT_DELAYED;
487    }
488    X(bgez_samepage)
489    {
490            MODE_int_t rs = reg(ic->arg[0]);
491            int x = (rs >= 0);
492            cpu->delay_slot = TO_BE_DELAYED;
493            ic[1].f(cpu, ic+1);
494            cpu->n_translated_instrs ++;
495            if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
496                    if (x)
497                            cpu->cd.mips.next_ic = (struct mips_instr_call *)
498                                ic->arg[2];
499                    else
500                            cpu->cd.mips.next_ic ++;
501            }
502            cpu->delay_slot = NOT_DELAYED;
503    }
504    X(bgezl)
505    {
506            MODE_int_t old_pc = cpu->pc;
507            MODE_int_t rs = reg(ic->arg[0]);
508            int x = (rs >= 0);
509            cpu->delay_slot = TO_BE_DELAYED;
510            if (x)
511                    ic[1].f(cpu, ic+1);
512            cpu->n_translated_instrs ++;
513            if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
514                    /*  Note: Must be non-delayed when jumping to the new pc:  */
515                    cpu->delay_slot = NOT_DELAYED;
516                    if (x) {
517                            old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
518                                MIPS_INSTR_ALIGNMENT_SHIFT);
519                            cpu->pc = old_pc + (int32_t)ic->arg[2];
520                            quick_pc_to_pointers(cpu);
521                    } else
522                            cpu->cd.mips.next_ic ++;
523            } else
524                    cpu->delay_slot = NOT_DELAYED;
525    }
526    X(bgezl_samepage)
527    {
528            MODE_int_t rs = reg(ic->arg[0]);
529            int x = (rs >= 0);
530            cpu->delay_slot = TO_BE_DELAYED;
531            if (x)
532                    ic[1].f(cpu, ic+1);
533            cpu->n_translated_instrs ++;
534            if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
535                    if (x)
536                            cpu->cd.mips.next_ic = (struct mips_instr_call *)
537                                ic->arg[2];
538                    else
539                            cpu->cd.mips.next_ic ++;
540            }
541            cpu->delay_slot = NOT_DELAYED;
542    }
543    
544    
545    /*
546     *  bgezal:   Branch if greater than or equal (and link)
547     *  bgezall:  Branch if greater than or equal (and link) likely
548     *
549     *  arg[0] = pointer to rs
550     *  arg[2] = (int32_t) relative offset from the next instruction
551     */
552    X(bgezal)
553    {
554            MODE_int_t old_pc = cpu->pc;
555            MODE_int_t rs = reg(ic->arg[0]);
556            int x = (rs >= 0), low_pc;
557    
558            cpu->delay_slot = TO_BE_DELAYED;
559            low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
560                / sizeof(struct mips_instr_call);
561            cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
562                << MIPS_INSTR_ALIGNMENT_SHIFT);
563            cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
564            cpu->cd.mips.gpr[MIPS_GPR_RA] = cpu->pc + 8;
565    
566            ic[1].f(cpu, ic+1);
567            cpu->n_translated_instrs ++;
568            if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
569                    /*  Note: Must be non-delayed when jumping to the new pc:  */
570                    cpu->delay_slot = NOT_DELAYED;
571                    if (x) {
572                            old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
573                                MIPS_INSTR_ALIGNMENT_SHIFT);
574                            cpu->pc = old_pc + (int32_t)ic->arg[2];
575                            quick_pc_to_pointers(cpu);
576                    } else
577                            cpu->cd.mips.next_ic ++;
578            } else
579                    cpu->delay_slot = NOT_DELAYED;
580    }
581    X(bgezal_samepage)
582    {
583            MODE_int_t rs = reg(ic->arg[0]);
584            int x = (rs >= 0), low_pc;
585    
586            cpu->delay_slot = TO_BE_DELAYED;
587            low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
588                / sizeof(struct mips_instr_call);
589            cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
590                << MIPS_INSTR_ALIGNMENT_SHIFT);
591            cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
592            cpu->cd.mips.gpr[MIPS_GPR_RA] = cpu->pc + 8;
593    
594            ic[1].f(cpu, ic+1);
595            cpu->n_translated_instrs ++;
596            if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
597                    if (x)
598                            cpu->cd.mips.next_ic = (struct mips_instr_call *)
599                                ic->arg[2];
600                    else
601                            cpu->cd.mips.next_ic ++;
602            }
603            cpu->delay_slot = NOT_DELAYED;
604    }
605    X(bgezall)
606    {
607            MODE_int_t old_pc = cpu->pc;
608            MODE_int_t rs = reg(ic->arg[0]);
609            int x = (rs >= 0), low_pc;
610    
611            cpu->delay_slot = TO_BE_DELAYED;
612            low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
613                / sizeof(struct mips_instr_call);
614            cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
615                << MIPS_INSTR_ALIGNMENT_SHIFT);
616            cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
617            cpu->cd.mips.gpr[MIPS_GPR_RA] = cpu->pc + 8;
618    
619            if (x)
620                    ic[1].f(cpu, ic+1);
621            cpu->n_translated_instrs ++;
622            if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
623                    /*  Note: Must be non-delayed when jumping to the new pc:  */
624                    cpu->delay_slot = NOT_DELAYED;
625                    if (x) {
626                            old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
627                                MIPS_INSTR_ALIGNMENT_SHIFT);
628                            cpu->pc = old_pc + (int32_t)ic->arg[2];
629                            quick_pc_to_pointers(cpu);
630                    } else
631                            cpu->cd.mips.next_ic ++;
632            } else
633                    cpu->delay_slot = NOT_DELAYED;
634    }
635    X(bgezall_samepage)
636    {
637            MODE_int_t rs = reg(ic->arg[0]);
638            int x = (rs >= 0), low_pc;
639    
640            cpu->delay_slot = TO_BE_DELAYED;
641            low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
642                / sizeof(struct mips_instr_call);
643            cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
644                << MIPS_INSTR_ALIGNMENT_SHIFT);
645            cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
646            cpu->cd.mips.gpr[MIPS_GPR_RA] = cpu->pc + 8;
647    
648            if (x)
649                    ic[1].f(cpu, ic+1);
650            cpu->n_translated_instrs ++;
651            if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
652                    if (x)
653                            cpu->cd.mips.next_ic = (struct mips_instr_call *)
654                                ic->arg[2];
655                    else
656                            cpu->cd.mips.next_ic ++;
657            }
658            cpu->delay_slot = NOT_DELAYED;
659    }
660    
661    
662    /*
663     *  bltzal:   Branch if less than zero (and link)
664     *  bltzall:  Branch if less than zero (and link) likely
665     *
666     *  arg[0] = pointer to rs
667     *  arg[2] = (int32_t) relative offset from the next instruction
668     */
669    X(bltzal)
670    {
671            MODE_int_t old_pc = cpu->pc;
672            MODE_int_t rs = reg(ic->arg[0]);
673            int x = (rs < 0), low_pc;
674    
675            cpu->delay_slot = TO_BE_DELAYED;
676            low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
677                / sizeof(struct mips_instr_call);
678            cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
679                << MIPS_INSTR_ALIGNMENT_SHIFT);
680            cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
681            cpu->cd.mips.gpr[MIPS_GPR_RA] = cpu->pc + 8;
682    
683            ic[1].f(cpu, ic+1);
684            cpu->n_translated_instrs ++;
685            if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
686                    /*  Note: Must be non-delayed when jumping to the new pc:  */
687                    cpu->delay_slot = NOT_DELAYED;
688                    if (x) {
689                            old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
690                                MIPS_INSTR_ALIGNMENT_SHIFT);
691                            cpu->pc = old_pc + (int32_t)ic->arg[2];
692                            quick_pc_to_pointers(cpu);
693                    } else
694                            cpu->cd.mips.next_ic ++;
695            } else
696                    cpu->delay_slot = NOT_DELAYED;
697    }
698    X(bltzal_samepage)
699    {
700            MODE_int_t rs = reg(ic->arg[0]);
701            int x = (rs < 0), low_pc;
702    
703            cpu->delay_slot = TO_BE_DELAYED;
704            low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
705                / sizeof(struct mips_instr_call);
706            cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
707                << MIPS_INSTR_ALIGNMENT_SHIFT);
708            cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
709            cpu->cd.mips.gpr[MIPS_GPR_RA] = cpu->pc + 8;
710    
711            ic[1].f(cpu, ic+1);
712            cpu->n_translated_instrs ++;
713            if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
714                    if (x)
715                            cpu->cd.mips.next_ic = (struct mips_instr_call *)
716                                ic->arg[2];
717                    else
718                            cpu->cd.mips.next_ic ++;
719            }
720            cpu->delay_slot = NOT_DELAYED;
721    }
722    X(bltzall)
723    {
724            MODE_int_t old_pc = cpu->pc;
725            MODE_int_t rs = reg(ic->arg[0]);
726            int x = (rs < 0), low_pc;
727    
728            cpu->delay_slot = TO_BE_DELAYED;
729            low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
730                / sizeof(struct mips_instr_call);
731            cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
732                << MIPS_INSTR_ALIGNMENT_SHIFT);
733            cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
734            cpu->cd.mips.gpr[MIPS_GPR_RA] = cpu->pc + 8;
735    
736            if (x)
737                    ic[1].f(cpu, ic+1);
738            cpu->n_translated_instrs ++;
739            if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
740                    /*  Note: Must be non-delayed when jumping to the new pc:  */
741                    cpu->delay_slot = NOT_DELAYED;
742                    if (x) {
743                            old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
744                                MIPS_INSTR_ALIGNMENT_SHIFT);
745                            cpu->pc = old_pc + (int32_t)ic->arg[2];
746                            quick_pc_to_pointers(cpu);
747                    } else
748                            cpu->cd.mips.next_ic ++;
749            } else
750                    cpu->delay_slot = NOT_DELAYED;
751    }
752    X(bltzall_samepage)
753    {
754            MODE_int_t rs = reg(ic->arg[0]);
755            int x = (rs < 0), low_pc;
756    
757            cpu->delay_slot = TO_BE_DELAYED;
758            low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
759                / sizeof(struct mips_instr_call);
760            cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
761                << MIPS_INSTR_ALIGNMENT_SHIFT);
762            cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
763            cpu->cd.mips.gpr[MIPS_GPR_RA] = cpu->pc + 8;
764    
765            if (x)
766                    ic[1].f(cpu, ic+1);
767            cpu->n_translated_instrs ++;
768            if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
769                    if (x)
770                            cpu->cd.mips.next_ic = (struct mips_instr_call *)
771                                ic->arg[2];
772                    else
773                            cpu->cd.mips.next_ic ++;
774            }
775            cpu->delay_slot = NOT_DELAYED;
776    }
777    
778    
779    /*
780     *  bgtz:   Branch if greater than zero
781     *  bgtzl:  Branch if greater than zero likely
782     *
783     *  arg[0] = pointer to rs
784     *  arg[2] = (int32_t) relative offset from the next instruction
785     */
786    X(bgtz)
787    {
788            MODE_int_t old_pc = cpu->pc;
789            MODE_int_t rs = reg(ic->arg[0]);
790            int x = (rs > 0);
791            cpu->delay_slot = TO_BE_DELAYED;
792            ic[1].f(cpu, ic+1);
793            cpu->n_translated_instrs ++;
794            if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
795                    /*  Note: Must be non-delayed when jumping to the new pc:  */
796                    cpu->delay_slot = NOT_DELAYED;
797                    if (x) {
798                            old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
799                                MIPS_INSTR_ALIGNMENT_SHIFT);
800                            cpu->pc = old_pc + (int32_t)ic->arg[2];
801                            quick_pc_to_pointers(cpu);
802                    } else
803                            cpu->cd.mips.next_ic ++;
804            } else
805                    cpu->delay_slot = NOT_DELAYED;
806    }
807    X(bgtz_samepage)
808    {
809            MODE_int_t rs = reg(ic->arg[0]);
810            int x = (rs > 0);
811            cpu->delay_slot = TO_BE_DELAYED;
812            ic[1].f(cpu, ic+1);
813            cpu->n_translated_instrs ++;
814            if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
815                    if (x)
816                            cpu->cd.mips.next_ic = (struct mips_instr_call *)
817                                ic->arg[2];
818                    else
819                            cpu->cd.mips.next_ic ++;
820            }
821            cpu->delay_slot = NOT_DELAYED;
822    }
823    X(bgtzl)
824    {
825            MODE_int_t old_pc = cpu->pc;
826            MODE_int_t rs = reg(ic->arg[0]);
827            int x = (rs > 0);
828            cpu->delay_slot = TO_BE_DELAYED;
829            if (x)
830                    ic[1].f(cpu, ic+1);
831            cpu->n_translated_instrs ++;
832            if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
833                    /*  Note: Must be non-delayed when jumping to the new pc:  */
834                    cpu->delay_slot = NOT_DELAYED;
835                    if (x) {
836                            old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
837                                MIPS_INSTR_ALIGNMENT_SHIFT);
838                            cpu->pc = old_pc + (int32_t)ic->arg[2];
839                            quick_pc_to_pointers(cpu);
840                    } else
841                            cpu->cd.mips.next_ic ++;
842            } else
843                    cpu->delay_slot = NOT_DELAYED;
844    }
845    X(bgtzl_samepage)
846    {
847            MODE_int_t rs = reg(ic->arg[0]);
848            int x = (rs > 0);
849            cpu->delay_slot = TO_BE_DELAYED;
850            if (x)
851                    ic[1].f(cpu, ic+1);
852            cpu->n_translated_instrs ++;
853            if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
854                    if (x)
855                            cpu->cd.mips.next_ic = (struct mips_instr_call *)
856                                ic->arg[2];
857                    else
858                            cpu->cd.mips.next_ic ++;
859            }
860            cpu->delay_slot = NOT_DELAYED;
861  }  }
862    
863    
# Line 168  X(b_samepage) Line 870  X(b_samepage)
870   */   */
871  X(jr)  X(jr)
872  {  {
873          MODE_uint_t rs = reg(ic->arg[0]);          MODE_int_t rs = reg(ic->arg[0]);
874          cpu->cd.mips.delay_slot = TO_BE_DELAYED;          cpu->delay_slot = TO_BE_DELAYED;
875          ic[1].f(cpu, ic+1);          ic[1].f(cpu, ic+1);
876          cpu->n_translated_instrs ++;          cpu->n_translated_instrs ++;
877          if (!(cpu->cd.mips.delay_slot & EXCEPTION_IN_DELAY_SLOT)) {          if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
878                  cpu->pc = rs;                  cpu->pc = rs;
879                    /*  Note: Must be non-delayed when jumping to the new pc:  */
880                    cpu->delay_slot = NOT_DELAYED;
881                  quick_pc_to_pointers(cpu);                  quick_pc_to_pointers(cpu);
882          }          } else
883          cpu->cd.mips.delay_slot = NOT_DELAYED;                  cpu->delay_slot = NOT_DELAYED;
884  }  }
885  X(jr_ra)  X(jr_ra)
886  {  {
887          MODE_uint_t rs = cpu->cd.mips.gpr[MIPS_GPR_RA];          MODE_int_t rs = cpu->cd.mips.gpr[MIPS_GPR_RA];
888          cpu->cd.mips.delay_slot = TO_BE_DELAYED;          cpu->delay_slot = TO_BE_DELAYED;
889          ic[1].f(cpu, ic+1);          ic[1].f(cpu, ic+1);
890          cpu->n_translated_instrs ++;          cpu->n_translated_instrs ++;
891          if (!(cpu->cd.mips.delay_slot & EXCEPTION_IN_DELAY_SLOT)) {          if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
892                  cpu->pc = rs;                  cpu->pc = rs;
893                    /*  Note: Must be non-delayed when jumping to the new pc:  */
894                    cpu->delay_slot = NOT_DELAYED;
895                  quick_pc_to_pointers(cpu);                  quick_pc_to_pointers(cpu);
896          }          } else
897          cpu->cd.mips.delay_slot = NOT_DELAYED;                  cpu->delay_slot = NOT_DELAYED;
898  }  }
899  X(jr_ra_trace)  X(jr_ra_trace)
900  {  {
901          MODE_uint_t rs = cpu->cd.mips.gpr[MIPS_GPR_RA];          MODE_int_t rs = cpu->cd.mips.gpr[MIPS_GPR_RA];
902          cpu->cd.mips.delay_slot = TO_BE_DELAYED;          cpu->delay_slot = TO_BE_DELAYED;
903          ic[1].f(cpu, ic+1);          ic[1].f(cpu, ic+1);
904          cpu->n_translated_instrs ++;          cpu->n_translated_instrs ++;
905          if (!(cpu->cd.mips.delay_slot & EXCEPTION_IN_DELAY_SLOT)) {          if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
906                  cpu->pc = rs;                  cpu->pc = rs;
907                  cpu_functioncall_trace_return(cpu);                  cpu_functioncall_trace_return(cpu);
908                    /*  Note: Must be non-delayed when jumping to the new pc:  */
909                    cpu->delay_slot = NOT_DELAYED;
910                  quick_pc_to_pointers(cpu);                  quick_pc_to_pointers(cpu);
911          }          } else
912          cpu->cd.mips.delay_slot = NOT_DELAYED;                  cpu->delay_slot = NOT_DELAYED;
913  }  }
914  X(jalr)  X(jalr)
915  {  {
916          MODE_uint_t rs = reg(ic->arg[0]), rd;          MODE_int_t rs = reg(ic->arg[0]), rd;
917          cpu->cd.mips.delay_slot = TO_BE_DELAYED;          cpu->delay_slot = TO_BE_DELAYED;
918          rd = cpu->pc & ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<          rd = cpu->pc & ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
919              MIPS_INSTR_ALIGNMENT_SHIFT);              MIPS_INSTR_ALIGNMENT_SHIFT);
920          rd += (int32_t)ic->arg[2];          rd += (int32_t)ic->arg[2];
921          reg(ic->arg[1]) = rd;          reg(ic->arg[1]) = rd;
922          ic[1].f(cpu, ic+1);          ic[1].f(cpu, ic+1);
923          cpu->n_translated_instrs ++;          cpu->n_translated_instrs ++;
924          if (!(cpu->cd.mips.delay_slot & EXCEPTION_IN_DELAY_SLOT)) {          if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
925                  cpu->pc = rs;                  cpu->pc = rs;
926                    /*  Note: Must be non-delayed when jumping to the new pc:  */
927                    cpu->delay_slot = NOT_DELAYED;
928                  quick_pc_to_pointers(cpu);                  quick_pc_to_pointers(cpu);
929          }          } else
930          cpu->cd.mips.delay_slot = NOT_DELAYED;                  cpu->delay_slot = NOT_DELAYED;
931  }  }
932  X(jalr_trace)  X(jalr_trace)
933  {  {
934          MODE_uint_t rs = reg(ic->arg[0]), rd;          MODE_int_t rs = reg(ic->arg[0]), rd;
935          cpu->cd.mips.delay_slot = TO_BE_DELAYED;          cpu->delay_slot = TO_BE_DELAYED;
936          rd = cpu->pc & ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<          rd = cpu->pc & ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
937              MIPS_INSTR_ALIGNMENT_SHIFT);              MIPS_INSTR_ALIGNMENT_SHIFT);
938          rd += (int32_t)ic->arg[2];          rd += (int32_t)ic->arg[2];
939          reg(ic->arg[1]) = rd;          reg(ic->arg[1]) = rd;
940          ic[1].f(cpu, ic+1);          ic[1].f(cpu, ic+1);
941          cpu->n_translated_instrs ++;          cpu->n_translated_instrs ++;
942          if (!(cpu->cd.mips.delay_slot & EXCEPTION_IN_DELAY_SLOT)) {          if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
943                  cpu->pc = rs;                  cpu->pc = rs;
944                  cpu_functioncall_trace(cpu, cpu->pc);                  cpu_functioncall_trace(cpu, cpu->pc);
945                    /*  Note: Must be non-delayed when jumping to the new pc:  */
946                    cpu->delay_slot = NOT_DELAYED;
947                  quick_pc_to_pointers(cpu);                  quick_pc_to_pointers(cpu);
948          }          } else
949          cpu->cd.mips.delay_slot = NOT_DELAYED;                  cpu->delay_slot = NOT_DELAYED;
950    }
951    
952    
953    /*
954     *  j, jal:  Jump [and link].
955     *
956     *  arg[0] = lowest 28 bits of new pc.
957     *  arg[1] = offset from start of page to the jal instruction + 8
958     */
959    X(j)
960    {
961            MODE_int_t old_pc = cpu->pc;
962            cpu->delay_slot = TO_BE_DELAYED;
963            ic[1].f(cpu, ic+1);
964            cpu->n_translated_instrs ++;
965            if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
966                    /*  Note: Must be non-delayed when jumping to the new pc:  */
967                    cpu->delay_slot = NOT_DELAYED;
968                    old_pc &= ~0x03ffffff;
969                    cpu->pc = old_pc | (uint32_t)ic->arg[0];
970                    quick_pc_to_pointers(cpu);
971            } else
972                    cpu->delay_slot = NOT_DELAYED;
973    }
974    X(jal)
975    {
976            MODE_int_t old_pc = cpu->pc;
977            cpu->delay_slot = TO_BE_DELAYED;
978            cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
979            cpu->cd.mips.gpr[31] = (MODE_int_t)cpu->pc + (int32_t)ic->arg[1];
980            ic[1].f(cpu, ic+1);
981            cpu->n_translated_instrs ++;
982            if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
983                    /*  Note: Must be non-delayed when jumping to the new pc:  */
984                    cpu->delay_slot = NOT_DELAYED;
985                    old_pc &= ~0x03ffffff;
986                    cpu->pc = old_pc | (int32_t)ic->arg[0];
987                    quick_pc_to_pointers(cpu);
988            } else
989                    cpu->delay_slot = NOT_DELAYED;
990    }
991    X(jal_trace)
992    {
993            MODE_int_t old_pc = cpu->pc;
994            cpu->delay_slot = TO_BE_DELAYED;
995            cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
996            cpu->cd.mips.gpr[31] = (MODE_int_t)cpu->pc + (int32_t)ic->arg[1];
997            ic[1].f(cpu, ic+1);
998            cpu->n_translated_instrs ++;
999            if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
1000                    /*  Note: Must be non-delayed when jumping to the new pc:  */
1001                    cpu->delay_slot = NOT_DELAYED;
1002                    old_pc &= ~0x03ffffff;
1003                    cpu->pc = old_pc | (int32_t)ic->arg[0];
1004                    cpu_functioncall_trace(cpu, cpu->pc);
1005                    quick_pc_to_pointers(cpu);
1006            } else
1007                    cpu->delay_slot = NOT_DELAYED;
1008    }
1009    
1010    
1011    /*
1012     *  cache:  Cache operation.
1013     */
1014    X(cache)
1015    {
1016            /*  TODO. For now, just clear the rmw bit:  */
1017            cpu->cd.mips.rmw = 0;
1018    
1019    /*  TODO: fix  */
1020    cpu->invalidate_code_translation(cpu, 0, INVALIDATE_ALL);
1021    cpu->invalidate_translation_caches(cpu, 0, INVALIDATE_ALL);
1022    /* cpu_create_or_reset_tc(cpu); */
1023  }  }
1024    
1025    
# Line 245  X(jalr_trace) Line 1030  X(jalr_trace)
1030   *  arg[1] = pointer to rt   *  arg[1] = pointer to rt
1031   *  arg[2] = uint32_t immediate value   *  arg[2] = uint32_t immediate value
1032   */   */
1033  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]; }
1034  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]; }
1035  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]; }
1036    
1037    
1038  /*  /*
1039   *  2-register:   *  2-register:
1040     *
1041     *  arg[0] = ptr to rs
1042     *  arg[1] = ptr to rt
1043   */   */
1044    X(div)
1045    {
1046            int32_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1047            int32_t res, rem;
1048            if (b == 0)
1049                    res = 0, rem = a;
1050            else
1051                    res = a / b, rem = a - b*res;
1052            reg(&cpu->cd.mips.lo) = (int32_t)res;
1053            reg(&cpu->cd.mips.hi) = (int32_t)rem;
1054    }
1055    X(divu)
1056    {
1057            uint32_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1058            uint32_t res, rem;
1059            if (b == 0)
1060                    res = 0, rem = a;
1061            else
1062                    res = a / b, rem = a - b*res;
1063            reg(&cpu->cd.mips.lo) = (int32_t)res;
1064            reg(&cpu->cd.mips.hi) = (int32_t)rem;
1065    }
1066    X(ddiv)
1067    {
1068            int64_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1069            int64_t res, rem;
1070            if (b == 0)
1071                    res = 0;
1072            else
1073                    res = a / b;
1074            rem = a - b*res;
1075            reg(&cpu->cd.mips.lo) = res;
1076            reg(&cpu->cd.mips.hi) = rem;
1077    }
1078    X(ddivu)
1079    {
1080            uint64_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1081            uint64_t res, rem;
1082            if (b == 0)
1083                    res = 0;
1084            else
1085                    res = a / b;
1086            rem = a - b*res;
1087            reg(&cpu->cd.mips.lo) = res;
1088            reg(&cpu->cd.mips.hi) = rem;
1089    }
1090  X(mult)  X(mult)
1091  {  {
1092          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 1094  X(mult)
1094          reg(&cpu->cd.mips.lo) = (int32_t)res;          reg(&cpu->cd.mips.lo) = (int32_t)res;
1095          reg(&cpu->cd.mips.hi) = (int32_t)(res >> 32);          reg(&cpu->cd.mips.hi) = (int32_t)(res >> 32);
1096  }  }
1097    X(mult_r5900)
1098    {
1099            /*  C790/TX79/R5900 multiplication, stores result in
1100                hi, lo, and a third register  */
1101            int32_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1102            int64_t res = (int64_t)a * (int64_t)b;
1103            reg(&cpu->cd.mips.lo) = (int32_t)res;
1104            reg(&cpu->cd.mips.hi) = (int32_t)(res >> 32);
1105            reg(ic->arg[2]) = (int32_t)res;
1106    }
1107  X(multu)  X(multu)
1108  {  {
1109          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 1111  X(multu)
1111          reg(&cpu->cd.mips.lo) = (int32_t)res;          reg(&cpu->cd.mips.lo) = (int32_t)res;
1112          reg(&cpu->cd.mips.hi) = (int32_t)(res >> 32);          reg(&cpu->cd.mips.hi) = (int32_t)(res >> 32);
1113  }  }
1114    X(multu_r5900)
1115    {
1116            /*  C790/TX79/R5900 multiplication, stores result in
1117                hi, lo, and a third register  */
1118            uint32_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1119            uint64_t res = (uint64_t)a * (uint64_t)b;
1120            reg(&cpu->cd.mips.lo) = (int32_t)res;
1121            reg(&cpu->cd.mips.hi) = (int32_t)(res >> 32);
1122            reg(ic->arg[2]) = (int32_t)res;
1123    }
1124    X(dmult)
1125    {
1126            uint64_t a = reg(ic->arg[0]), b = reg(ic->arg[1]), c = 0;
1127            uint64_t hi = 0, lo = 0;
1128            int neg = 0;
1129            if (a >> 63)
1130                    neg = !neg, a = -a;
1131            if (b >> 63)
1132                    neg = !neg, b = -b;
1133            for (; a; a >>= 1) {
1134                    if (a & 1) {
1135                            uint64_t old_lo = lo;
1136                            hi += c;
1137                            lo += b;
1138                            if (lo < old_lo)
1139                                    hi ++;
1140                    }
1141                    c = (c << 1) | (b >> 63); b <<= 1;
1142            }
1143            if (neg) {
1144                    if (lo == 0)
1145                            hi --;
1146                    lo --;
1147                    hi ^= (int64_t) -1;
1148                    lo ^= (int64_t) -1;
1149            }
1150            reg(&cpu->cd.mips.lo) = lo;
1151            reg(&cpu->cd.mips.hi) = hi;
1152    }
1153    X(dmultu)
1154    {
1155            uint64_t a = reg(ic->arg[0]), b = reg(ic->arg[1]), c = 0;
1156            uint64_t hi = 0, lo = 0;
1157            for (; a; a >>= 1) {
1158                    if (a & 1) {
1159                            uint64_t old_lo = lo;
1160                            hi += c;
1161                            lo += b;
1162                            if (lo < old_lo)
1163                                    hi ++;
1164                    }
1165                    c = (c << 1) | (b >> 63); b <<= 1;
1166            }
1167            reg(&cpu->cd.mips.lo) = lo;
1168            reg(&cpu->cd.mips.hi) = hi;
1169    }
1170    X(tge)
1171    {
1172            MODE_int_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1173            if (a >= b) {
1174                    /*  Synch. PC and cause an exception:  */
1175                    int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1176                        / sizeof(struct mips_instr_call);
1177                    cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
1178                        << MIPS_INSTR_ALIGNMENT_SHIFT);
1179                    cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1180                    mips_cpu_exception(cpu, EXCEPTION_TR, 0, 0, 0, 0, 0, 0);
1181            }
1182    }
1183    X(tgeu)
1184    {
1185            MODE_uint_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1186            if (a >= b) {
1187                    /*  Synch. PC and cause an exception:  */
1188                    int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1189                        / sizeof(struct mips_instr_call);
1190                    cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
1191                        << MIPS_INSTR_ALIGNMENT_SHIFT);
1192                    cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1193                    mips_cpu_exception(cpu, EXCEPTION_TR, 0, 0, 0, 0, 0, 0);
1194            }
1195    }
1196    X(tlt)
1197    {
1198            MODE_int_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1199            if (a < b) {
1200                    /*  Synch. PC and cause an exception:  */
1201                    int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1202                        / sizeof(struct mips_instr_call);
1203                    cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
1204                        << MIPS_INSTR_ALIGNMENT_SHIFT);
1205                    cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1206                    mips_cpu_exception(cpu, EXCEPTION_TR, 0, 0, 0, 0, 0, 0);
1207            }
1208    }
1209    X(tltu)
1210    {
1211            MODE_uint_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1212            if (a < b) {
1213                    /*  Synch. PC and cause an exception:  */
1214                    int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1215                        / sizeof(struct mips_instr_call);
1216                    cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
1217                        << MIPS_INSTR_ALIGNMENT_SHIFT);
1218                    cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1219                    mips_cpu_exception(cpu, EXCEPTION_TR, 0, 0, 0, 0, 0, 0);
1220            }
1221    }
1222    X(teq)
1223    {
1224            MODE_uint_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1225            if (a == b) {
1226                    /*  Synch. PC and cause an exception:  */
1227                    int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1228                        / sizeof(struct mips_instr_call);
1229                    cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
1230                        << MIPS_INSTR_ALIGNMENT_SHIFT);
1231                    cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1232                    mips_cpu_exception(cpu, EXCEPTION_TR, 0, 0, 0, 0, 0, 0);
1233            }
1234    }
1235    X(tne)
1236    {
1237            MODE_uint_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1238            if (a != b) {
1239                    /*  Synch. PC and cause an exception:  */
1240                    int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1241                        / sizeof(struct mips_instr_call);
1242                    cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
1243                        << MIPS_INSTR_ALIGNMENT_SHIFT);
1244                    cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1245                    mips_cpu_exception(cpu, EXCEPTION_TR, 0, 0, 0, 0, 0, 0);
1246            }
1247    }
1248    
1249    
1250  /*  /*
1251   *  3-register:   *  3-register arithmetic instructions:
1252     *
1253     *  arg[0] = ptr to rs
1254     *  arg[1] = ptr to rt
1255     *  arg[2] = ptr to rd
1256   */   */
1257  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])); }
1258  X(subu) { reg(ic->arg[2]) = (int32_t)(reg(ic->arg[0]) - reg(ic->arg[1])); }  X(add)
1259    {
1260            int32_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]);
1261            int32_t rd = rs + rt;
1262    
1263            if ((rs >= 0 && rt >= 0 && rd < 0) || (rs < 0 && rt < 0 && rd >= 0)) {
1264                    /*  Synch. PC and cause an exception:  */
1265                    int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1266                        / sizeof(struct mips_instr_call);
1267                    cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
1268                        << MIPS_INSTR_ALIGNMENT_SHIFT);
1269                    cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1270                    mips_cpu_exception(cpu, EXCEPTION_OV, 0, 0, 0, 0, 0, 0);
1271            } else
1272                    reg(ic->arg[2]) = rd;
1273    }
1274  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]); }
1275  X(dsubu){ reg(ic->arg[2]) = reg(ic->arg[0]) + reg(ic->arg[1]); }  X(dadd)
1276    {
1277            int64_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]);
1278            int64_t rd = rs + rt;
1279    
1280            if ((rs >= 0 && rt >= 0 && rd < 0) || (rs < 0 && rt < 0 && rd >= 0)) {
1281                    /*  Synch. PC and cause an exception:  */
1282                    int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1283                        / sizeof(struct mips_instr_call);
1284                    cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
1285                        << MIPS_INSTR_ALIGNMENT_SHIFT);
1286                    cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1287                    mips_cpu_exception(cpu, EXCEPTION_OV, 0, 0, 0, 0, 0, 0);
1288            } else
1289                    reg(ic->arg[2]) = rd;
1290    }
1291    X(subu) { reg(ic->arg[2]) = (int32_t)(reg(ic->arg[0]) - reg(ic->arg[1])); }
1292    X(sub)
1293    {
1294            /*  NOTE: Negating rt and using addition. TODO: Is this correct?  */
1295            int32_t rs = reg(ic->arg[0]), rt = - reg(ic->arg[1]);
1296            int32_t rd = rs + rt;
1297    
1298            if ((rs >= 0 && rt >= 0 && rd < 0) || (rs < 0 && rt < 0 && rd >= 0)) {
1299                    /*  Synch. PC and cause an exception:  */
1300                    int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1301                        / sizeof(struct mips_instr_call);
1302                    cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
1303                        << MIPS_INSTR_ALIGNMENT_SHIFT);
1304                    cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1305                    mips_cpu_exception(cpu, EXCEPTION_OV, 0, 0, 0, 0, 0, 0);
1306            } else
1307                    reg(ic->arg[2]) = rd;
1308    }
1309    X(dsubu){ reg(ic->arg[2]) = reg(ic->arg[0]) - reg(ic->arg[1]); }
1310    X(dsub)
1311    {
1312            /*  NOTE: Negating rt and using addition. TODO: Is this correct?  */
1313            int64_t rs = reg(ic->arg[0]), rt = - reg(ic->arg[1]);
1314            int64_t rd = rs + rt;
1315    
1316            if ((rs >= 0 && rt >= 0 && rd < 0) || (rs < 0 && rt < 0 && rd >= 0)) {
1317                    /*  Synch. PC and cause an exception:  */
1318                    int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1319                        / sizeof(struct mips_instr_call);
1320                    cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
1321                        << MIPS_INSTR_ALIGNMENT_SHIFT);
1322                    cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1323                    mips_cpu_exception(cpu, EXCEPTION_OV, 0, 0, 0, 0, 0, 0);
1324            } else
1325                    reg(ic->arg[2]) = rd;
1326    }
1327  X(slt) {  X(slt) {
1328  #ifdef MODE32          reg(ic->arg[2]) =
1329          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  
1330  }  }
1331  X(sltu) {  X(sltu) {
1332  #ifdef MODE32          reg(ic->arg[2]) =
1333          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  
1334  }  }
1335  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]); }
1336    X(or)  { reg(ic->arg[2]) = reg(ic->arg[0]) | reg(ic->arg[1]); }
1337  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]); }
1338  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])); }
1339  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]); }
1340    X(sllv){ int32_t sa = reg(ic->arg[1]) & 31;
1341             reg(ic->arg[2]) = (int32_t)(reg(ic->arg[0]) << sa); }
1342  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]); }
1343    X(srlv){ int32_t sa = reg(ic->arg[1]) & 31;
1344             reg(ic->arg[2]) = (int32_t)((uint32_t)reg(ic->arg[0]) >> sa); }
1345  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]); }
1346    X(srav){ int32_t sa = reg(ic->arg[1]) & 31;
1347             reg(ic->arg[2]) = (int32_t)((int32_t)reg(ic->arg[0]) >> sa); }
1348    X(dsll) { reg(ic->arg[2]) = (int64_t)reg(ic->arg[0]) << (int64_t)ic->arg[1]; }
1349    X(dsllv){ int64_t sa = reg(ic->arg[1]) & 63;
1350             reg(ic->arg[2]) = reg(ic->arg[0]) << sa; }
1351    X(dsrl) { reg(ic->arg[2]) = (int64_t)((uint64_t)reg(ic->arg[0]) >>
1352            (uint64_t) ic->arg[1]);}
1353    X(dsrlv){ int64_t sa = reg(ic->arg[1]) & 63;
1354             reg(ic->arg[2]) = (uint64_t)reg(ic->arg[0]) >> sa; }
1355    X(dsra) { reg(ic->arg[2]) = (int64_t)reg(ic->arg[0]) >> (int64_t)ic->arg[1]; }
1356    X(dsrav){ int64_t sa = reg(ic->arg[1]) & 63;
1357             reg(ic->arg[2]) = (int64_t)reg(ic->arg[0]) >> sa; }
1358  X(mul) { reg(ic->arg[2]) = (int32_t)  X(mul) { reg(ic->arg[2]) = (int32_t)
1359          ( (int32_t)reg(ic->arg[0]) * (int32_t)reg(ic->arg[1]) ); }          ( (int32_t)reg(ic->arg[0]) * (int32_t)reg(ic->arg[1]) ); }
1360    X(movn) { if (reg(ic->arg[1])) reg(ic->arg[2]) = reg(ic->arg[0]); }
1361    X(movz) { if (!reg(ic->arg[1])) reg(ic->arg[2]) = reg(ic->arg[0]); }
1362    
1363    
1364    /*
1365     *  p*:  128-bit C790/TX79/R5900 stuff
1366     *
1367     *  arg[0] = rs (note: not a pointer)
1368     *  arg[1] = rt (note: not a pointer)
1369     *  arg[2] = rd (note: not a pointer)
1370     */
1371    X(por)
1372    {
1373            cpu->cd.mips.gpr[ic->arg[2]] = cpu->cd.mips.gpr[ic->arg[0]] |
1374                cpu->cd.mips.gpr[ic->arg[1]];
1375            cpu->cd.mips.gpr_quadhi[ic->arg[2]] =
1376                cpu->cd.mips.gpr_quadhi[ic->arg[0]] |
1377                cpu->cd.mips.gpr_quadhi[ic->arg[1]];
1378    }
1379    X(pextlw)
1380    {
1381            uint64_t lo, hi;
1382    
1383            lo = (uint32_t)cpu->cd.mips.gpr[ic->arg[1]] |
1384                (uint64_t)((uint64_t)cpu->cd.mips.gpr[ic->arg[0]] << 32);
1385            hi = (cpu->cd.mips.gpr[ic->arg[0]] & 0xffffffff00000000ULL) |
1386                (uint32_t)((uint64_t)cpu->cd.mips.gpr[ic->arg[1]] >> 32);
1387    
1388            cpu->cd.mips.gpr[ic->arg[2]] = lo;
1389            cpu->cd.mips.gpr_quadhi[ic->arg[2]] = hi;
1390    }
1391    
1392    
1393    /*
1394     *  madd, maddu, msub, msubu: Multiply-and-add/subtract
1395     *
1396     *  arg[0] = ptr to rs
1397     *  arg[1] = ptr to rt
1398     *  arg[2] = ptr to rd (only used on R5900/TX79)
1399     */
1400    X(madd)
1401    {
1402            int64_t rs = (int32_t)reg(ic->arg[0]), rt = (int32_t)reg(ic->arg[1]);
1403            int64_t sum = rs * rt,
1404                hilo = (cpu->cd.mips.hi << 32) | (uint32_t)(cpu->cd.mips.lo);
1405            hilo += sum;
1406            cpu->cd.mips.hi = (int32_t)(hilo>>32); cpu->cd.mips.lo = (int32_t)hilo;
1407    }
1408    X(madd_rd)
1409    {
1410            int64_t rs = (int32_t)reg(ic->arg[0]), rt = (int32_t)reg(ic->arg[1]);
1411            int64_t sum = rs * rt,
1412                hilo = (cpu->cd.mips.hi << 32) | (uint32_t)(cpu->cd.mips.lo);
1413            hilo += sum;
1414            cpu->cd.mips.hi = (int32_t)(hilo>>32); cpu->cd.mips.lo = (int32_t)hilo;
1415            reg(ic->arg[2]) = (int32_t)hilo;
1416    }
1417    X(msub)
1418    {
1419            int64_t rs = (int32_t)reg(ic->arg[0]), rt = (int32_t)reg(ic->arg[1]);
1420            int64_t sum = rs * rt,
1421                hilo = (cpu->cd.mips.hi << 32) | (uint32_t)(cpu->cd.mips.lo);
1422            hilo -= sum;
1423            cpu->cd.mips.hi = (int32_t)(hilo>>32); cpu->cd.mips.lo = (int32_t)hilo;
1424    }
1425    X(maddu)
1426    {
1427            int64_t rs = (uint32_t)reg(ic->arg[0]), rt = (uint32_t)reg(ic->arg[1]);
1428            int64_t sum = rs * rt,
1429                hilo = (cpu->cd.mips.hi << 32) | (uint32_t)(cpu->cd.mips.lo);
1430            hilo += sum;
1431            cpu->cd.mips.hi = (int32_t)(hilo>>32); cpu->cd.mips.lo = (int32_t)hilo;
1432    }
1433    X(maddu_rd)
1434    {
1435            int64_t rs = (uint32_t)reg(ic->arg[0]), rt = (uint32_t)reg(ic->arg[1]);
1436            int64_t sum = rs * rt,
1437                hilo = (cpu->cd.mips.hi << 32) | (uint32_t)(cpu->cd.mips.lo);
1438            hilo += sum;
1439            cpu->cd.mips.hi = (int32_t)(hilo>>32); cpu->cd.mips.lo = (int32_t)hilo;
1440            reg(ic->arg[2]) = (int32_t)hilo;
1441    }
1442    X(msubu)
1443    {
1444            int64_t rs = (uint32_t)reg(ic->arg[0]), rt = (uint32_t)reg(ic->arg[1]);
1445            int64_t sum = rs * rt,
1446                hilo = (cpu->cd.mips.hi << 32) | (uint32_t)(cpu->cd.mips.lo);
1447            hilo -= sum;
1448            cpu->cd.mips.hi = (int32_t)(hilo>>32); cpu->cd.mips.lo = (int32_t)hilo;
1449    }
1450    
1451    
1452  /*  /*
# Line 362  X(dclo) Line 1511  X(dclo)
1511    
1512    
1513  /*  /*
1514   *  addiu:  Add immediate (32-bit).   *  addi, daddi: Add immediate, overflow detection.
1515     *  addiu, daddiu: Add immediate.
1516     *  slti:   Set if less than immediate (signed 32-bit)
1517     *  sltiu:  Set if less than immediate (signed 32-bit, but unsigned compare)
1518   *   *
1519   *  arg[0] = pointer to rs   *  arg[0] = pointer to rs
1520   *  arg[1] = pointer to rt   *  arg[1] = pointer to rt
1521   *  arg[2] = (int32_t) immediate value   *  arg[2] = (int32_t) immediate value
1522   */   */
1523    X(addi)
1524    {
1525            int32_t rs = reg(ic->arg[0]), imm = (int32_t)ic->arg[2];
1526            int32_t rt = rs + imm;
1527    
1528            if ((rs >= 0 && imm >= 0 && rt < 0) || (rs < 0 && imm < 0 && rt >= 0)) {
1529                    /*  Synch. PC and cause an exception:  */
1530                    int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1531                        / sizeof(struct mips_instr_call);
1532                    cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
1533                        << MIPS_INSTR_ALIGNMENT_SHIFT);
1534                    cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1535                    mips_cpu_exception(cpu, EXCEPTION_OV, 0, 0, 0, 0, 0, 0);
1536            } else
1537                    reg(ic->arg[1]) = rt;
1538    }
1539  X(addiu)  X(addiu)
1540  {  {
1541          reg(ic->arg[1]) = (int32_t)          reg(ic->arg[1]) = (int32_t)
1542              ((int32_t)reg(ic->arg[0]) + (int32_t)ic->arg[2]);              ((int32_t)reg(ic->arg[0]) + (int32_t)ic->arg[2]);
1543  }  }
1544    X(daddi)
1545    {
1546            int64_t rs = reg(ic->arg[0]), imm = (int32_t)ic->arg[2];
1547            int64_t rt = rs + imm;
1548    
1549            if ((rs >= 0 && imm >= 0 && rt < 0) || (rs < 0 && imm < 0 && rt >= 0)) {
1550  /*                  /*  Synch. PC and cause an exception:  */
1551   *  daddiu:  Add immediate (64-bit).                  int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1552   *                      / sizeof(struct mips_instr_call);
1553   *  arg[0] = pointer to rs                  cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
1554   *  arg[1] = pointer to rt                      << MIPS_INSTR_ALIGNMENT_SHIFT);
1555   *  arg[2] = (int32_t) immediate value                  cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1556   */                  mips_cpu_exception(cpu, EXCEPTION_OV, 0, 0, 0, 0, 0, 0);
1557            } else
1558                    reg(ic->arg[1]) = rt;
1559    }
1560  X(daddiu)  X(daddiu)
1561  {  {
1562          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];
1563  }  }
1564    X(slti)
1565    {
1566            reg(ic->arg[1]) = (MODE_int_t)reg(ic->arg[0]) < (int32_t)ic->arg[2];
1567    }
1568    X(sltiu)
1569    {
1570            reg(ic->arg[1]) = (MODE_uint_t)reg(ic->arg[0]) <
1571               ((MODE_uint_t)(int32_t)ic->arg[2]);
1572    }
1573    
1574    
1575  /*  /*
# Line 401  X(set) Line 1585  X(set)
1585    
1586    
1587  /*  /*
1588     *  cfc0:         Copy from Coprocessor 0.
1589   *  mfc0, dmfc0:  Move from Coprocessor 0.   *  mfc0, dmfc0:  Move from Coprocessor 0.
1590   *  mtc0, dmtc0:  Move to Coprocessor 0.   *  mtc0, dmtc0:  Move to Coprocessor 0.
  *  cfc1: Copy control word from Coprocessor 1.  
1591   *   *
1592   *  arg[0] = pointer to GPR (rt)   *  arg[0] = pointer to GPR (rt)
1593   *  arg[1] = coprocessor 0 register number | (select << 5)   *  arg[1] = coprocessor 0 register number | (select << 5)   (or for the
1594     *           cfc0 instruction, the coprocessor control register number)
1595   *  arg[2] = relative addr of this instruction within the page   *  arg[2] = relative addr of this instruction within the page
1596   */   */
1597    X(cfc0)
1598    {
1599            int fs = ic->arg[1] & 31;
1600            cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
1601            cpu->pc |= ic->arg[2];
1602            /*  TODO: cause exception if necessary  */
1603            reg(ic->arg[0]) = (int32_t)cpu->cd.mips.coproc[0]->fcr[fs];
1604    }
1605  X(mfc0)  X(mfc0)
1606  {  {
1607          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 1615  X(mfc0)
1615  X(mtc0)  X(mtc0)
1616  {  {
1617          int rd = ic->arg[1] & 31, select = ic->arg[1] >> 5;          int rd = ic->arg[1] & 31, select = ic->arg[1] >> 5;
1618            uint64_t tmp = (int32_t) reg(ic->arg[0]);
1619    #if 0
1620            uint32_t oldstatus = cpu->cd.mips.coproc[0]->reg[COP0_STATUS];
1621    #endif
1622          cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);          cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
1623          cpu->pc |= ic->arg[2];          cpu->pc |= ic->arg[2];
1624    
1625          /*  TODO: cause exception if necessary  */          /*  TODO: cause exception if necessary  */
1626          coproc_register_write(cpu, cpu->cd.mips.coproc[0], rd,          coproc_register_write(cpu, cpu->cd.mips.coproc[0], rd, &tmp, 0, select);
1627              (uint64_t *)ic->arg[0], 0, select);  
1628    #if 0
1629            /*  Interrupts enabled, and any interrupt pending?  */
1630            if (rd == COP0_STATUS && !(oldstatus & STATUS_IE)) {
1631                    uint32_t status = cpu->cd.mips.coproc[0]->reg[COP0_STATUS];
1632                    uint32_t cause = cpu->cd.mips.coproc[0]->reg[COP0_CAUSE];
1633                    /*  NOTE: STATUS_IE happens to match the enable bit also
1634                        on R2000/R3000, so this is ok.  */
1635                    if (status & STATUS_IE && (status & cause & STATUS_IM_MASK))
1636                            cpu->running_translated = 0;
1637            }
1638    #endif
1639  }  }
1640  X(dmfc0)  X(dmfc0)
1641  {  {
# Line 445  X(dmtc0) Line 1654  X(dmtc0)
1654          /*  TODO: cause exception if necessary  */          /*  TODO: cause exception if necessary  */
1655          coproc_register_write(cpu, cpu->cd.mips.coproc[0], rd,          coproc_register_write(cpu, cpu->cd.mips.coproc[0], rd,
1656              (uint64_t *)ic->arg[0], 1, select);              (uint64_t *)ic->arg[0], 1, select);
1657    
1658    /*  TODO: fix/remove these!  */
1659    cpu->invalidate_translation_caches(cpu, 0, INVALIDATE_ALL);
1660  }  }
1661  X(cfc1)  
1662    
1663    /*
1664     *  cop1_bc:  Floating point conditional branch.
1665     *
1666     *  arg[0] = cc
1667     *  arg[1] = nd (=2) and tf (=1) bits
1668     *  arg[2] = offset (relative to start of this page)
1669     */
1670    X(cop1_bc)
1671    {
1672            MODE_int_t old_pc = cpu->pc;
1673            const int cpnr = 1;
1674            int x, low_pc, cc = ic->arg[0];
1675    
1676            low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1677                / sizeof(struct mips_instr_call);
1678            cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<< MIPS_INSTR_ALIGNMENT_SHIFT);
1679            cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1680            if (!(cpu->cd.mips.coproc[0]->
1681                reg[COP0_STATUS] & ((1 << cpnr) << STATUS_CU_SHIFT)) ) {
1682                    mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0, cpnr, 0, 0, 0);
1683                    return;
1684            }
1685    
1686            /*  Get the correct condition code bit:  */
1687            if (cc == 0)
1688                    x = (cpu->cd.mips.coproc[1]->fcr[MIPS_FPU_FCSR]
1689                        >> MIPS_FCSR_FCC0_SHIFT) & 1;
1690            else
1691                    x = (cpu->cd.mips.coproc[1]->fcr[MIPS_FPU_FCSR]
1692                        >> (MIPS_FCSR_FCC1_SHIFT + cc-1)) & 1;
1693    
1694            /*  Branch on false? Then invert the truth value.  */
1695            if (!(ic->arg[1] & 1))
1696                    x ^= 1;
1697    
1698            /*  Execute the delay slot (except if it is nullified):  */
1699            cpu->delay_slot = TO_BE_DELAYED;
1700            if (x || !(ic->arg[1] & 2))
1701                    ic[1].f(cpu, ic+1);
1702            cpu->n_translated_instrs ++;
1703    
1704            if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
1705                    /*  Note: Must be non-delayed when jumping to the new pc:  */
1706                    cpu->delay_slot = NOT_DELAYED;
1707                    if (x) {
1708                            old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
1709                                MIPS_INSTR_ALIGNMENT_SHIFT);
1710                            cpu->pc = old_pc + (int32_t)ic->arg[2];
1711                            quick_pc_to_pointers(cpu);
1712                    } else
1713                            cpu->cd.mips.next_ic ++;
1714            } else
1715                    cpu->delay_slot = NOT_DELAYED;
1716    }
1717    
1718    
1719    /*
1720     *  cop1_slow:  Fallback to legacy cop1 code. (Slow, but it should work.)
1721     */
1722    X(cop1_slow)
1723    {
1724            const int cpnr = 1;
1725            int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1726                / sizeof(struct mips_instr_call);
1727            cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<< MIPS_INSTR_ALIGNMENT_SHIFT);
1728            cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1729    
1730            if (!(cpu->cd.mips.coproc[0]->
1731                reg[COP0_STATUS] & ((1 << cpnr) << STATUS_CU_SHIFT)) ) {
1732                    mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0, cpnr, 0, 0, 0);
1733                    return;
1734            }
1735    
1736            coproc_function(cpu, cpu->cd.mips.coproc[1], 1, ic->arg[0], 0, 1);
1737    }
1738    
1739    
1740    /*
1741     *  syscall, break:  Synchronize the PC and cause an exception.
1742     */
1743    X(syscall)
1744    {
1745            int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1746                / sizeof(struct mips_instr_call);
1747            cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<< MIPS_INSTR_ALIGNMENT_SHIFT);
1748            cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1749            mips_cpu_exception(cpu, EXCEPTION_SYS, 0, 0, 0, 0, 0, 0);
1750    }
1751    X(break)
1752    {
1753            int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1754                / sizeof(struct mips_instr_call);
1755            cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<< MIPS_INSTR_ALIGNMENT_SHIFT);
1756            cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1757            mips_cpu_exception(cpu, EXCEPTION_BP, 0, 0, 0, 0, 0, 0);
1758    }
1759    
1760    
1761    /*
1762     *  promemul:  PROM software emulation.
1763     */
1764    X(promemul)
1765    {
1766            /*  Synchronize the PC and call the correct emulation layer:  */
1767            MODE_int_t old_pc;
1768            int res, low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1769                / sizeof(struct mips_instr_call);
1770            cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<< MIPS_INSTR_ALIGNMENT_SHIFT);
1771            cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1772            old_pc = cpu->pc;
1773    
1774            switch (cpu->machine->machine_type) {
1775            case MACHINE_PMAX:
1776                    res = decstation_prom_emul(cpu);
1777                    break;
1778            case MACHINE_PS2:
1779                    res = playstation2_sifbios_emul(cpu);
1780                    break;
1781            case MACHINE_ARC:
1782            case MACHINE_SGI:
1783                    res = arcbios_emul(cpu);
1784                    break;
1785            case MACHINE_EVBMIPS:
1786                    res = yamon_emul(cpu);
1787                    break;
1788            default:fatal("TODO: Unimplemented machine type for PROM magic trap\n");
1789                    exit(1);
1790            }
1791    
1792            if (res) {
1793                    /*  Return from the PROM call:  */
1794                    cpu->pc = (MODE_int_t)cpu->cd.mips.gpr[MIPS_GPR_RA];
1795                    cpu->delay_slot = NOT_DELAYED;
1796    
1797                    if (cpu->machine->show_trace_tree)
1798                            cpu_functioncall_trace_return(cpu);
1799            } else {
1800                    /*  The PROM call blocks.  */
1801                    cpu->n_translated_instrs += 10;
1802                    cpu->pc = old_pc;
1803            }
1804    
1805            quick_pc_to_pointers(cpu);
1806    }
1807    
1808    
1809    /*
1810     *  tlbw: TLB write indexed and random
1811     *
1812     *  arg[0] = 1 for random, 0 for indexed
1813     *  arg[2] = relative addr of this instruction within the page
1814     */
1815    X(tlbw)
1816  {  {
1817          cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);          cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
1818          cpu->pc |= ic->arg[2];          cpu->pc |= ic->arg[2];
1819          /*  TODO: cause exception if necessary  */          coproc_tlbwri(cpu, ic->arg[0]);
1820          reg(ic->arg[0]) = reg(ic->arg[1]);  }
1821    
1822    
1823    /*
1824     *  tlbp: TLB probe
1825     *  tlbr: TLB read
1826     *
1827     *  arg[2] = relative addr of this instruction within the page
1828     */
1829    X(tlbp)
1830    {
1831            cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
1832            cpu->pc |= ic->arg[2];
1833            coproc_tlbpr(cpu, 0);
1834    }
1835    X(tlbr)
1836    {
1837            cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
1838            cpu->pc |= ic->arg[2];
1839            coproc_tlbpr(cpu, 1);
1840    }
1841    
1842    
1843    /*
1844     *  rfe: Return from exception handler (R2000/R3000)
1845     */
1846    X(rfe)
1847    {
1848            coproc_rfe(cpu);
1849    
1850            /*  Note: no pc to pointers conversion is necessary here.  */
1851    }
1852    
1853    
1854    /*
1855     *  eret: Return from exception handler
1856     */
1857    X(eret)
1858    {
1859            coproc_eret(cpu);
1860            quick_pc_to_pointers(cpu);
1861    }
1862    
1863    
1864    /*
1865     *  deret: Return from debug (EJTAG) handler
1866     */
1867    X(deret)
1868    {
1869            /*
1870             *  According to the MIPS64 manual, deret loads PC from the DEPC cop0
1871             *  register, and jumps there immediately. No delay slot.
1872             *
1873             *  TODO: This instruction is only available if the processor is in
1874             *  debug mode. (What does that mean?)
1875             *
1876             *  TODO: This instruction is undefined in a delay slot.
1877             */
1878    
1879            cpu->pc = cpu->cd.mips.coproc[0]->reg[COP0_DEPC];
1880            cpu->delay_slot = 0;
1881            cpu->cd.mips.coproc[0]->reg[COP0_STATUS] &= ~STATUS_EXL;
1882            quick_pc_to_pointers(cpu);
1883    }
1884    
1885    
1886    /*
1887     *  rdhwr: Read hardware register into gpr (MIPS32/64 rev 2).
1888     *
1889     *  arg[0] = ptr to rt (destination register)
1890     */
1891    X(rdhwr_cpunum)
1892    {
1893            reg(ic->arg[0]) = cpu->cpu_id;
1894    }
1895    
1896    
1897    #include "tmp_mips_loadstore.c"
1898    
1899    
1900    /*
1901     *  Load linked / store conditional:
1902     *
1903     *  A Load-linked instruction initiates a RMW (read-modify-write) sequence.
1904     *  COP0_LLADDR is updated for diagnostic purposes, except for CPUs in the
1905     *  R10000 family.
1906     *
1907     *  A Store-conditional instruction ends the sequence.
1908     *
1909     *  arg[0] = ptr to rt
1910     *  arg[1] = ptr to rs
1911     *  arg[2] = int32_t imm
1912     */
1913    X(ll)
1914    {
1915            MODE_int_t addr = reg(ic->arg[1]) + (int32_t)ic->arg[2];
1916            int low_pc;
1917            uint8_t word[sizeof(uint32_t)];
1918    
1919            /*  Synch. PC and load using slow memory_rw():  */
1920            low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1921                / sizeof(struct mips_instr_call);
1922            cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
1923                << MIPS_INSTR_ALIGNMENT_SHIFT);
1924            cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1925    
1926            if (addr & (sizeof(word)-1)) {
1927                    fatal("TODO: load linked unaligned access: exception\n");
1928                    exit(1);
1929            }
1930    
1931            if (!cpu->memory_rw(cpu, cpu->mem, addr, word,
1932                sizeof(word), MEM_READ, CACHE_DATA)) {
1933                    /*  An exception occurred.  */
1934                    return;
1935            }
1936    
1937            cpu->cd.mips.rmw = 1;
1938            cpu->cd.mips.rmw_addr = addr;
1939            cpu->cd.mips.rmw_len = sizeof(word);
1940            if (cpu->cd.mips.cpu_type.exc_model != MMU10K)
1941                    cpu->cd.mips.coproc[0]->reg[COP0_LLADDR] =
1942                        (addr >> 4) & 0xffffffffULL;
1943    
1944            if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
1945                    reg(ic->arg[0]) = (int32_t) (word[0] + (word[1] << 8)
1946                        + (word[2] << 16) + (word[3] << 24));
1947            else
1948                    reg(ic->arg[0]) = (int32_t) (word[3] + (word[2] << 8)
1949                        + (word[1] << 16) + (word[0] << 24));
1950    }
1951    X(lld)
1952    {
1953            MODE_int_t addr = reg(ic->arg[1]) + (int32_t)ic->arg[2];
1954            int low_pc;
1955            uint8_t word[sizeof(uint64_t)];
1956    
1957            /*  Synch. PC and load using slow memory_rw():  */
1958            low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1959                / sizeof(struct mips_instr_call);
1960            cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
1961                << MIPS_INSTR_ALIGNMENT_SHIFT);
1962            cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1963    
1964            if (addr & (sizeof(word)-1)) {
1965                    fatal("TODO: load linked unaligned access: exception\n");
1966                    exit(1);
1967            }
1968    
1969            if (!cpu->memory_rw(cpu, cpu->mem, addr, word,
1970                sizeof(word), MEM_READ, CACHE_DATA)) {
1971                    /*  An exception occurred.  */
1972                    return;
1973            }
1974    
1975            cpu->cd.mips.rmw = 1;
1976            cpu->cd.mips.rmw_addr = addr;
1977            cpu->cd.mips.rmw_len = sizeof(word);
1978            if (cpu->cd.mips.cpu_type.exc_model != MMU10K)
1979                    cpu->cd.mips.coproc[0]->reg[COP0_LLADDR] =
1980                        (addr >> 4) & 0xffffffffULL;
1981    
1982            if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
1983                    reg(ic->arg[0]) = word[0] + (word[1] << 8)
1984                        + (word[2] << 16) + ((uint64_t)word[3] << 24) +
1985                        + ((uint64_t)word[4] << 32) + ((uint64_t)word[5] << 40)
1986                        + ((uint64_t)word[6] << 48) + ((uint64_t)word[7] << 56);
1987            else
1988                    reg(ic->arg[0]) = word[7] + (word[6] << 8)
1989                        + (word[5] << 16) + ((uint64_t)word[4] << 24) +
1990                        + ((uint64_t)word[3] << 32) + ((uint64_t)word[2] << 40)
1991                        + ((uint64_t)word[1] << 48) + ((uint64_t)word[0] << 56);
1992    }
1993    X(sc)
1994    {
1995            MODE_int_t addr = reg(ic->arg[1]) + (int32_t)ic->arg[2];
1996            uint64_t r = reg(ic->arg[0]);
1997            int low_pc, i;
1998            uint8_t word[sizeof(uint32_t)];
1999    
2000            /*  Synch. PC and store using slow memory_rw():  */
2001            low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
2002                / sizeof(struct mips_instr_call);
2003            cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
2004                << MIPS_INSTR_ALIGNMENT_SHIFT);
2005            cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
2006    
2007            if (addr & (sizeof(word)-1)) {
2008                    fatal("TODO: sc unaligned access: exception\n");
2009                    exit(1);
2010            }
2011    
2012            if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {
2013                    word[0]=r; word[1]=r>>8; word[2]=r>>16; word[3]=r>>24;
2014            } else {
2015                    word[3]=r; word[2]=r>>8; word[1]=r>>16; word[0]=r>>24;
2016            }
2017    
2018            /*  If rmw is 0, then the store failed.  (This cache-line was written
2019                to by someone else.)  */
2020            if (cpu->cd.mips.rmw == 0 || cpu->cd.mips.rmw_addr != addr
2021                || cpu->cd.mips.rmw_len != sizeof(word)) {
2022                    reg(ic->arg[0]) = 0;
2023                    cpu->cd.mips.rmw = 0;
2024                    return;
2025            }
2026    
2027            if (!cpu->memory_rw(cpu, cpu->mem, addr, word,
2028                sizeof(word), MEM_WRITE, CACHE_DATA)) {
2029                    /*  An exception occurred.  */
2030                    return;
2031            }
2032    
2033            /*  We succeeded. Let's invalidate everybody else's store to this
2034                cache line:  */
2035            for (i=0; i<cpu->machine->ncpus; i++) {
2036                    if (cpu->machine->cpus[i]->cd.mips.rmw) {
2037                            uint64_t yaddr = addr, xaddr = cpu->machine->cpus[i]->
2038                                cd.mips.rmw_addr;
2039                            uint64_t mask = ~(cpu->machine->cpus[i]->
2040                                cd.mips.cache_linesize[CACHE_DATA] - 1);
2041                            xaddr &= mask;
2042                            yaddr &= mask;
2043                            if (xaddr == yaddr)
2044                                    cpu->machine->cpus[i]->cd.mips.rmw = 0;
2045                    }
2046            }
2047    
2048            reg(ic->arg[0]) = 1;
2049            cpu->cd.mips.rmw = 0;
2050    }
2051    X(scd)
2052    {
2053            MODE_int_t addr = reg(ic->arg[1]) + (int32_t)ic->arg[2];
2054            uint64_t r = reg(ic->arg[0]);
2055            int low_pc, i;
2056            uint8_t word[sizeof(uint64_t)];
2057    
2058            /*  Synch. PC and store using slow memory_rw():  */
2059            low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
2060                / sizeof(struct mips_instr_call);
2061            cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
2062                << MIPS_INSTR_ALIGNMENT_SHIFT);
2063            cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
2064    
2065            if (addr & (sizeof(word)-1)) {
2066                    fatal("TODO: sc unaligned access: exception\n");
2067                    exit(1);
2068            }
2069    
2070            if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {
2071                    word[0]=r;     word[1]=r>>8; word[2]=r>>16; word[3]=r>>24;
2072                    word[4]=r>>32; word[5]=r>>40; word[6]=r>>48; word[7]=r>>56;
2073            } else {
2074                    word[7]=r;     word[6]=r>>8; word[5]=r>>16; word[4]=r>>24;
2075                    word[3]=r>>32; word[2]=r>>40; word[1]=r>>48; word[0]=r>>56;
2076            }
2077    
2078            /*  If rmw is 0, then the store failed.  (This cache-line was written
2079                to by someone else.)  */
2080            if (cpu->cd.mips.rmw == 0 || cpu->cd.mips.rmw_addr != addr
2081                || cpu->cd.mips.rmw_len != sizeof(word)) {
2082                    reg(ic->arg[0]) = 0;
2083                    cpu->cd.mips.rmw = 0;
2084                    return;
2085            }
2086    
2087            if (!cpu->memory_rw(cpu, cpu->mem, addr, word,
2088                sizeof(word), MEM_WRITE, CACHE_DATA)) {
2089                    /*  An exception occurred.  */
2090                    return;
2091            }
2092    
2093            /*  We succeeded. Let's invalidate everybody else's store to this
2094                cache line:  */
2095            for (i=0; i<cpu->machine->ncpus; i++) {
2096                    if (cpu->machine->cpus[i]->cd.mips.rmw) {
2097                            uint64_t yaddr = addr, xaddr = cpu->machine->cpus[i]->
2098                                cd.mips.rmw_addr;
2099                            uint64_t mask = ~(cpu->machine->cpus[i]->
2100                                cd.mips.cache_linesize[CACHE_DATA] - 1);
2101                            xaddr &= mask;
2102                            yaddr &= mask;
2103                            if (xaddr == yaddr)
2104                                    cpu->machine->cpus[i]->cd.mips.rmw = 0;
2105                    }
2106            }
2107    
2108            reg(ic->arg[0]) = 1;
2109            cpu->cd.mips.rmw = 0;
2110    }
2111    
2112    
2113    /*
2114     *  lwc1, swc1:  Coprocessor 1 load/store (32-bit)
2115     *  ldc1, sdc1:  Coprocessor 1 load/store (64-bit)
2116     *
2117     *  arg[0] = ptr to coprocessor register
2118     *  arg[1] = ptr to rs (base pointer register)
2119     *  arg[2] = int32_t imm
2120     */
2121    X(lwc1)
2122    {
2123            const int cpnr = 1;
2124    
2125            /*  Synch. PC and call the generic load/store function:  */
2126            int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
2127                / sizeof(struct mips_instr_call);
2128            cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
2129                << MIPS_INSTR_ALIGNMENT_SHIFT);
2130            cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
2131    
2132            /*  ... but first, let's see if the coprocessor is available:  */
2133            if (!(cpu->cd.mips.coproc[0]->
2134                reg[COP0_STATUS] & ((1 << cpnr) << STATUS_CU_SHIFT)) ) {
2135                    mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0, cpnr, 0, 0, 0);
2136                    return;
2137            }
2138    
2139    #ifdef MODE32
2140            mips32_loadstore
2141    #else
2142            mips_loadstore
2143    #endif
2144                [ (cpu->byte_order == EMUL_LITTLE_ENDIAN? 0 : 16) + 2 * 2 + 1]
2145                (cpu, ic);
2146    }
2147    X(swc1)
2148    {
2149            const int cpnr = 1;
2150    
2151            /*  Synch. PC and call the generic load/store function:  */
2152            int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
2153                / sizeof(struct mips_instr_call);
2154            cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
2155                << MIPS_INSTR_ALIGNMENT_SHIFT);
2156            cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
2157    
2158            /*  ... but first, let's see if the coprocessor is available:  */
2159            if (!(cpu->cd.mips.coproc[0]->
2160                reg[COP0_STATUS] & ((1 << cpnr) << STATUS_CU_SHIFT)) ) {
2161                    mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0, cpnr, 0, 0, 0);
2162                    return;
2163            }
2164    
2165    #ifdef MODE32
2166            mips32_loadstore
2167    #else
2168            mips_loadstore
2169    #endif
2170                [ (cpu->byte_order == EMUL_LITTLE_ENDIAN? 0 : 16) + 8 + 2 * 2]
2171                (cpu, ic);
2172    }
2173    X(ldc1)
2174    {
2175            const int cpnr = 1;
2176            int use_fp_pairs =
2177                !(cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & STATUS_FR);
2178            uint64_t fpr, *backup_ptr;
2179    
2180            /*  Synch. PC and call the generic load/store function:  */
2181            int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
2182                / sizeof(struct mips_instr_call);
2183            cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
2184                << MIPS_INSTR_ALIGNMENT_SHIFT);
2185            cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
2186    
2187            /*  ... but first, let's see if the coprocessor is available:  */
2188            if (!(cpu->cd.mips.coproc[0]->
2189                reg[COP0_STATUS] & ((1 << cpnr) << STATUS_CU_SHIFT)) ) {
2190                    mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0, cpnr, 0, 0, 0);
2191                    return;
2192            }
2193    
2194            backup_ptr = (uint64_t *) ic->arg[0];
2195            ic->arg[0] = (size_t) &fpr;
2196    
2197    #ifdef MODE32
2198            mips32_loadstore
2199    #else
2200            mips_loadstore
2201    #endif
2202                [ (cpu->byte_order == EMUL_LITTLE_ENDIAN? 0 : 16) + 3 * 2 + 1]
2203                (cpu, ic);
2204    
2205            if (use_fp_pairs) {
2206                    backup_ptr[0] = (int64_t)(int32_t) fpr;
2207                    backup_ptr[1] = (int64_t)(int32_t) (fpr >> 32);
2208            } else {
2209                    *backup_ptr = fpr;
2210            }
2211    
2212            ic->arg[0] = (size_t) backup_ptr;
2213    }
2214    X(sdc1)
2215    {
2216            const int cpnr = 1;
2217            int use_fp_pairs =
2218                !(cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & STATUS_FR);
2219            uint64_t fpr, *backup_ptr;
2220    
2221            /*  Synch. PC and call the generic load/store function:  */
2222            int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
2223                / sizeof(struct mips_instr_call);
2224            cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
2225                << MIPS_INSTR_ALIGNMENT_SHIFT);
2226            cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
2227    
2228            /*  ... but first, let's see if the coprocessor is available:  */
2229            if (!(cpu->cd.mips.coproc[0]->
2230                reg[COP0_STATUS] & ((1 << cpnr) << STATUS_CU_SHIFT)) ) {
2231                    mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0, cpnr, 0, 0, 0);
2232                    return;
2233            }
2234    
2235            backup_ptr = (uint64_t *) ic->arg[0];
2236            ic->arg[0] = (size_t) &fpr;
2237    
2238            if (use_fp_pairs) {
2239                    uint32_t lo = backup_ptr[0];
2240                    uint32_t hi = backup_ptr[1];
2241                    fpr = (((uint64_t)hi) << 32) | lo;
2242            } else {
2243                    fpr = *backup_ptr;
2244            }
2245    
2246    #ifdef MODE32
2247            mips32_loadstore
2248    #else
2249            mips_loadstore
2250    #endif
2251                [ (cpu->byte_order == EMUL_LITTLE_ENDIAN? 0 : 16) + 8 + 3 * 2]
2252                (cpu, ic);
2253    
2254            ic->arg[0] = (size_t) backup_ptr;
2255    }
2256    
2257    
2258    /*
2259     *  Unaligned loads/stores:
2260     *
2261     *  arg[0] = ptr to rt
2262     *  arg[1] = ptr to rs
2263     *  arg[2] = int32_t imm
2264     */
2265    X(lwl) { mips_unaligned_loadstore(cpu, ic, 1, sizeof(uint32_t), 0); }
2266    X(lwr) { mips_unaligned_loadstore(cpu, ic, 0, sizeof(uint32_t), 0); }
2267    X(ldl) { mips_unaligned_loadstore(cpu, ic, 1, sizeof(uint64_t), 0); }
2268    X(ldr) { mips_unaligned_loadstore(cpu, ic, 0, sizeof(uint64_t), 0); }
2269    X(swl) { mips_unaligned_loadstore(cpu, ic, 1, sizeof(uint32_t), 1); }
2270    X(swr) { mips_unaligned_loadstore(cpu, ic, 0, sizeof(uint32_t), 1); }
2271    X(sdl) { mips_unaligned_loadstore(cpu, ic, 1, sizeof(uint64_t), 1); }
2272    X(sdr) { mips_unaligned_loadstore(cpu, ic, 0, sizeof(uint64_t), 1); }
2273    
2274    
2275    /*
2276     *  di, ei: R5900 interrupt enable/disable.
2277     *
2278     *  TODO: check the R5900_STATUS_EDI bit in the status register. If it is
2279     *  cleared, and we are not running in kernel mode, then both the EI and DI
2280     *  instructions should be treated as NOPs!
2281     */
2282    X(di_r5900)
2283    {
2284            cpu->cd.mips.coproc[0]->reg[COP0_STATUS] &= ~R5900_STATUS_EIE;
2285    }
2286    X(ei_r5900)
2287    {
2288            cpu->cd.mips.coproc[0]->reg[COP0_STATUS] |= R5900_STATUS_EIE;
2289  }  }
2290    
2291    
# Line 465  X(cfc1) Line 2299  X(cfc1)
2299   */   */
2300  X(b_samepage_addiu)  X(b_samepage_addiu)
2301  {  {
2302          reg(ic[1].arg[1]) = reg(ic[1].arg[0]) + (int32_t)ic[1].arg[2];          reg(ic[1].arg[1]) = (int32_t)
2303                ( (int32_t)reg(ic[1].arg[0]) + (int32_t)ic[1].arg[2] );
2304            cpu->n_translated_instrs ++;
2305            cpu->cd.mips.next_ic = (struct mips_instr_call *) ic->arg[2];
2306    }
2307    
2308    
2309    /*
2310     *  b_samepage_daddiu:
2311     *
2312     *  Combination of branch within the same page, followed by daddiu.
2313     */
2314    X(b_samepage_daddiu)
2315    {
2316            *(uint64_t *)ic[1].arg[1] = *(uint64_t *)ic[1].arg[0] +
2317                (int32_t)ic[1].arg[2];
2318          cpu->n_translated_instrs ++;          cpu->n_translated_instrs ++;
2319          cpu->cd.mips.next_ic = (struct mips_instr_call *) ic->arg[2];          cpu->cd.mips.next_ic = (struct mips_instr_call *) ic->arg[2];
2320  }  }
# Line 476  X(b_samepage_addiu) Line 2325  X(b_samepage_addiu)
2325    
2326  X(end_of_page)  X(end_of_page)
2327  {  {
         struct mips_instr_call self;  
   
2328          /*  Update the PC:  (offset 0, but on the next page)  */          /*  Update the PC:  (offset 0, but on the next page)  */
2329          cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<          cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
2330              MIPS_INSTR_ALIGNMENT_SHIFT);              MIPS_INSTR_ALIGNMENT_SHIFT);
2331          cpu->pc += (MIPS_IC_ENTRIES_PER_PAGE << MIPS_INSTR_ALIGNMENT_SHIFT);          cpu->pc += (MIPS_IC_ENTRIES_PER_PAGE << MIPS_INSTR_ALIGNMENT_SHIFT);
2332    
2333          /*  Simple jump to the next page (if we are lucky):  */          /*  end_of_page doesn't count as an executed instruction:  */
2334          if (cpu->cd.mips.delay_slot == NOT_DELAYED) {          cpu->n_translated_instrs --;
2335    
2336                  /*  Find the new physpage and update translation pointers:  */          /*
2337                  quick_pc_to_pointers(cpu);           *  Find the new physpage and update translation pointers.
2338             *
2339             *  Note: This may cause an exception, if e.g. the new page is
2340             *  not accessible.
2341             */
2342            quick_pc_to_pointers(cpu);
2343    
2344                  /*  end_of_page doesn't count as an executed instruction:  */          /*  Simple jump to the next page (if we are lucky):  */
2345                  cpu->n_translated_instrs --;          if (cpu->delay_slot == NOT_DELAYED)
2346                    return;
2347    
2348            /*
2349             *  If we were in a delay slot, and we got an exception while doing
2350             *  quick_pc_to_pointers, then return. The function which called
2351             *  end_of_page should handle this case.
2352             */
2353            if (cpu->delay_slot == EXCEPTION_IN_DELAY_SLOT)
2354                  return;                  return;
         }  
2355    
2356          /*  Tricky situation; the delay slot is on the next virtual page:  */          /*
2357             *  Tricky situation; the delay slot is on the next virtual page.
2358             *  Calling to_be_translated will translate one instruction manually,
2359             *  execute it, and then discard it.
2360             */
2361          /*  fatal("[ end_of_page: delay slot across page boundary! ]\n");  */          /*  fatal("[ end_of_page: delay slot across page boundary! ]\n");  */
2362    
2363          /*  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);  
2364    
2365          /*  The instruction in the delay slot has now executed.  */          /*  The instruction in the delay slot has now executed.  */
2366            /*  fatal("[ end_of_page: back from executing the delay slot, %i ]\n",
2367                cpu->delay_slot);  */
2368    
2369          /*  Find the physpage etc of the instruction in the delay slot          /*  Find the physpage etc of the instruction in the delay slot
2370              (or, if there was an exception, the exception handler):  */              (or, if there was an exception, the exception handler):  */
2371          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");  */  
2372  }  }
2373    
2374    
2375  X(end_of_page2)  X(end_of_page2)
2376  {  {
2377  fatal("this should be removed: end of page2\n");          /*  Synchronize PC on the _second_ instruction on the next page:  */
2378  exit(1);          int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
2379                / sizeof(struct mips_instr_call);
2380          /*  Update the PC:  (offset 4, but on the next page)  */          cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
2381          cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<              << MIPS_INSTR_ALIGNMENT_SHIFT);
2382              MIPS_INSTR_ALIGNMENT_SHIFT);          cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
         cpu->pc += ((MIPS_IC_ENTRIES_PER_PAGE+1) << MIPS_INSTR_ALIGNMENT_SHIFT);  
2383    
2384          if (cpu->cd.mips.delay_slot == NOT_DELAYED) {          /*  This doesn't count as an executed instruction.  */
2385                  /*  Find the new physpage and update translation pointers:  */          cpu->n_translated_instrs --;
                 quick_pc_to_pointers(cpu);  
2386    
2387                  /*  end_of_page doesn't count as an executed instruction:  */          quick_pc_to_pointers(cpu);
                 cpu->n_translated_instrs --;  
2388    
2389            if (cpu->delay_slot == NOT_DELAYED)
2390                  return;                  return;
         }  
2391    
2392          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");
2393          exit(1);          exit(1);
2394  }  }
2395    
# Line 565  void COMBINE(b_addiu)(struct cpu *cpu, s Line 2418  void COMBINE(b_addiu)(struct cpu *cpu, s
2418  }  }
2419    
2420    
2421    /*
2422     *  Combine: [Conditional] branch, followed by daddiu.
2423     */
2424    void COMBINE(b_daddiu)(struct cpu *cpu, struct mips_instr_call *ic,
2425            int low_addr)
2426    {
2427            int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
2428                & (MIPS_IC_ENTRIES_PER_PAGE - 1);
2429    
2430            if (n_back < 1)
2431                    return;
2432    
2433            if (ic[-1].f == instr(b_samepage)) {
2434                    ic[-1].f = instr(b_samepage_daddiu);
2435                    combined;
2436            }
2437    
2438            /*  TODO: other branches that are followed by daddiu should be here  */
2439    }
2440    
2441    
2442  /*****************************************************************************/  /*****************************************************************************/
2443    
2444    
2445  /*  /*
2446   *  mips_instr_to_be_translated():   *  mips_instr_to_be_translated():
2447   *   *
2448   *  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
2449   *  valid data for the translated instruction, or a "nothing" instruction if   *  valid data for the translated instruction, or a "nothing" instruction if
2450   *  there was a translation failure. The newly translated instruction is then   *  there was a translation failure. The newly translated instruction is then
2451   *  executed.   *  executed.
# Line 582  X(to_be_translated) Line 2456  X(to_be_translated)
2456          uint32_t iword, imm;          uint32_t iword, imm;
2457          unsigned char *page;          unsigned char *page;
2458          unsigned char ib[4];          unsigned char ib[4];
 #ifdef DYNTRANS_BACKEND  
         int simple = 0;  
 #endif  
2459          int main_opcode, rt, rs, rd, sa, s6, x64 = 0;          int main_opcode, rt, rs, rd, sa, s6, x64 = 0;
2460          int in_crosspage_delayslot = 0;          int in_crosspage_delayslot = 0;
         int delay_slot_danger = 1;  
2461          void (*samepage_function)(struct cpu *, struct mips_instr_call *);          void (*samepage_function)(struct cpu *, struct mips_instr_call *);
2462            int store, signedness, size;
2463    
2464          /*  Figure out the (virtual) address of the instruction:  */          /*  Figure out the (virtual) address of the instruction:  */
2465          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)
2466              / sizeof(struct mips_instr_call);              / sizeof(struct mips_instr_call);
2467    
2468          /*  Special case for branch with delayslot on the next page:  */          /*  Special case for branch with delayslot on the next page:  */
2469          if (low_pc >= MIPS_IC_ENTRIES_PER_PAGE) {          if (cpu->delay_slot == TO_BE_DELAYED && low_pc == 0) {
2470                  /*  fatal("[ TEMPORARY delay-slot translation ]\n");  */                  /*  fatal("[ delay-slot translation across page "
2471                  low_pc = 0;                      "boundary ]\n");  */
2472                  in_crosspage_delayslot = 1;                  in_crosspage_delayslot = 1;
2473          }          }
2474    
2475          addr = cpu->pc & ~((MIPS_IC_ENTRIES_PER_PAGE-1)          addr = cpu->pc & ~((MIPS_IC_ENTRIES_PER_PAGE-1)
2476              << MIPS_INSTR_ALIGNMENT_SHIFT);              << MIPS_INSTR_ALIGNMENT_SHIFT);
2477          addr += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);          addr += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
2478          cpu->pc = addr;          cpu->pc = (MODE_int_t)addr;
2479          addr &= ~((1 << MIPS_INSTR_ALIGNMENT_SHIFT) - 1);          addr &= ~((1 << MIPS_INSTR_ALIGNMENT_SHIFT) - 1);
2480    
2481          /*  Read the instruction word from memory:  */          /*  Read the instruction word from memory:  */
2482    #ifdef MODE32
2483          page = cpu->cd.mips.host_load[(uint32_t)addr >> 12];          page = cpu->cd.mips.host_load[(uint32_t)addr >> 12];
2484    #else
2485            {
2486                    const uint32_t mask1 = (1 << DYNTRANS_L1N) - 1;
2487                    const uint32_t mask2 = (1 << DYNTRANS_L2N) - 1;
2488                    const uint32_t mask3 = (1 << DYNTRANS_L3N) - 1;
2489                    uint32_t x1 = (addr >> (64-DYNTRANS_L1N)) & mask1;
2490                    uint32_t x2 = (addr >> (64-DYNTRANS_L1N-DYNTRANS_L2N)) & mask2;
2491                    uint32_t x3 = (addr >> (64-DYNTRANS_L1N-DYNTRANS_L2N-
2492                        DYNTRANS_L3N)) & mask3;
2493                    struct DYNTRANS_L2_64_TABLE *l2 = cpu->cd.mips.l1_64[x1];
2494                    struct DYNTRANS_L3_64_TABLE *l3 = l2->l3[x2];
2495                    page = l3->host_load[x3];
2496            }
2497    #endif
2498    
2499          if (page != NULL) {          if (page != NULL) {
2500                  /*  fatal("TRANSLATION HIT!\n");  */                  /*  fatal("TRANSLATION HIT!\n");  */
2501                  memcpy(ib, page + (addr & 0xfff), sizeof(ib));                  memcpy(ib, page + (addr & 0xffc), sizeof(ib));
2502          } else {          } else {
2503                  /*  fatal("TRANSLATION MISS!\n");  */                  /*  fatal("TRANSLATION MISS!\n");  */
2504                  if (!cpu->memory_rw(cpu, cpu->mem, addr, ib,                  if (!cpu->memory_rw(cpu, cpu->mem, addr, ib,
2505                      sizeof(ib), MEM_READ, CACHE_INSTRUCTION)) {                      sizeof(ib), MEM_READ, CACHE_INSTRUCTION)) {
2506                          fatal("to_be_translated(): "                          fatal("to_be_translated(): read failed: TODO\n");
                             "read failed: TODO\n");  
2507                          goto bad;                          goto bad;
2508                  }                  }
2509          }          }
# Line 630  X(to_be_translated) Line 2515  X(to_be_translated)
2515          else          else
2516                  iword = BE32_TO_HOST(iword);                  iword = BE32_TO_HOST(iword);
2517    
         /*  Is the instruction in the delay slot known to be safe?  */  
         if ((addr & 0xffc) < 0xffc) {  
                 /*  TODO: check the instruction  */  
                 delay_slot_danger = 0;  
         }  
   
2518    
2519  #define DYNTRANS_TO_BE_TRANSLATED_HEAD  #define DYNTRANS_TO_BE_TRANSLATED_HEAD
2520  #include "cpu_dyntrans.c"  #include "cpu_dyntrans.c"
# Line 645  X(to_be_translated) Line 2524  X(to_be_translated)
2524          /*          /*
2525           *  Translate the instruction:           *  Translate the instruction:
2526           *           *
2527           *  NOTE: _NEVER_ allow writes to the zero register; all such           *  NOTE: _NEVER_ allow writes to the zero register; all instructions
2528           *  instructions should be made into NOPs.           *  that use the zero register as their destination should be treated
2529             *  as NOPs, except those that access memory (they should use the
2530             *  scratch register instead).
2531           */           */
2532    
2533          main_opcode = iword >> 26;          main_opcode = iword >> 26;
# Line 663  X(to_be_translated) Line 2544  X(to_be_translated)
2544                  switch (s6) {                  switch (s6) {
2545    
2546                  case SPECIAL_SLL:                  case SPECIAL_SLL:
2547                    case SPECIAL_SLLV:
2548                  case SPECIAL_SRL:                  case SPECIAL_SRL:
2549                    case SPECIAL_SRLV:
2550                  case SPECIAL_SRA:                  case SPECIAL_SRA:
2551                    case SPECIAL_SRAV:
2552                    case SPECIAL_DSRL:
2553                    case SPECIAL_DSRLV:
2554                    case SPECIAL_DSRL32:
2555                    case SPECIAL_DSLL:
2556                    case SPECIAL_DSLLV:
2557                    case SPECIAL_DSLL32:
2558                    case SPECIAL_DSRA:
2559                    case SPECIAL_DSRAV:
2560                    case SPECIAL_DSRA32:
2561                          switch (s6) {                          switch (s6) {
2562                          case SPECIAL_SLL:  ic->f = instr(sll); break;                          case SPECIAL_SLL:  ic->f = instr(sll); break;
2563                            case SPECIAL_SLLV: ic->f = instr(sllv); sa = -1; break;
2564                          case SPECIAL_SRL:  ic->f = instr(srl); break;                          case SPECIAL_SRL:  ic->f = instr(srl); break;
2565                            case SPECIAL_SRLV: ic->f = instr(srlv); sa = -1; break;
2566                          case SPECIAL_SRA:  ic->f = instr(sra); break;                          case SPECIAL_SRA:  ic->f = instr(sra); break;
2567                            case SPECIAL_SRAV: ic->f = instr(srav); sa = -1; break;
2568                            case SPECIAL_DSRL: ic->f = instr(dsrl); x64=1; break;
2569                            case SPECIAL_DSRLV:ic->f = instr(dsrlv);
2570                                               x64 = 1; sa = -1; break;
2571                            case SPECIAL_DSRL32:ic->f= instr(dsrl); x64=1;
2572                                               sa += 32; break;
2573                            case SPECIAL_DSLL: ic->f = instr(dsll); x64=1; break;
2574                            case SPECIAL_DSLLV:ic->f = instr(dsllv);
2575                                               x64 = 1; sa = -1; break;
2576                            case SPECIAL_DSLL32:ic->f= instr(dsll); x64=1;
2577                                               sa += 32; break;
2578                            case SPECIAL_DSRA: ic->f = instr(dsra); x64=1; break;
2579                            case SPECIAL_DSRAV:ic->f = instr(dsrav);
2580                                               x64 = 1; sa = -1; break;
2581                            case SPECIAL_DSRA32:ic->f = instr(dsra); x64=1;
2582                                               sa += 32; break;
2583                          }                          }
2584                          ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];                          ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
2585                          ic->arg[1] = sa;                          if (sa >= 0)
2586                                    ic->arg[1] = sa;
2587                            else
2588                                    ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rs];
2589                          ic->arg[2] = (size_t)&cpu->cd.mips.gpr[rd];                          ic->arg[2] = (size_t)&cpu->cd.mips.gpr[rd];
2590                          if (rd == MIPS_GPR_ZERO)                          if (rd == MIPS_GPR_ZERO)
2591                                  ic->f = instr(nop);                                  ic->f = instr(nop);
2592                          break;                          break;
2593    
2594                    case SPECIAL_ADD:
2595                  case SPECIAL_ADDU:                  case SPECIAL_ADDU:
2596                    case SPECIAL_SUB:
2597                  case SPECIAL_SUBU:                  case SPECIAL_SUBU:
2598                    case SPECIAL_DADD:
2599                  case SPECIAL_DADDU:                  case SPECIAL_DADDU:
2600                    case SPECIAL_DSUB:
2601                  case SPECIAL_DSUBU:                  case SPECIAL_DSUBU:
2602                  case SPECIAL_SLT:                  case SPECIAL_SLT:
2603                  case SPECIAL_SLTU:                  case SPECIAL_SLTU:
2604                    case SPECIAL_AND:
2605                  case SPECIAL_OR:                  case SPECIAL_OR:
2606                  case SPECIAL_XOR:                  case SPECIAL_XOR:
2607                  case SPECIAL_NOR:                  case SPECIAL_NOR:
2608                    case SPECIAL_MOVN:
2609                    case SPECIAL_MOVZ:
2610                  case SPECIAL_MFHI:                  case SPECIAL_MFHI:
2611                  case SPECIAL_MFLO:                  case SPECIAL_MFLO:
2612                  case SPECIAL_MTHI:                  case SPECIAL_MTHI:
2613                  case SPECIAL_MTLO:                  case SPECIAL_MTLO:
2614                    case SPECIAL_DIV:
2615                    case SPECIAL_DIVU:
2616                    case SPECIAL_DDIV:
2617                    case SPECIAL_DDIVU:
2618                    case SPECIAL_MULT:
2619                    case SPECIAL_MULTU:
2620                    case SPECIAL_DMULT:
2621                    case SPECIAL_DMULTU:
2622                    case SPECIAL_TGE:
2623                    case SPECIAL_TGEU:
2624                    case SPECIAL_TLT:
2625                    case SPECIAL_TLTU:
2626                    case SPECIAL_TEQ:
2627                    case SPECIAL_TNE:
2628                          switch (s6) {                          switch (s6) {
2629                            case SPECIAL_ADD:   ic->f = instr(add); break;
2630                          case SPECIAL_ADDU:  ic->f = instr(addu); break;                          case SPECIAL_ADDU:  ic->f = instr(addu); break;
2631                            case SPECIAL_SUB:   ic->f = instr(sub); break;
2632                          case SPECIAL_SUBU:  ic->f = instr(subu); break;                          case SPECIAL_SUBU:  ic->f = instr(subu); break;
2633                            case SPECIAL_DADD:  ic->f = instr(dadd); x64=1; break;
2634                          case SPECIAL_DADDU: ic->f = instr(daddu); x64=1; break;                          case SPECIAL_DADDU: ic->f = instr(daddu); x64=1; break;
2635                            case SPECIAL_DSUB:  ic->f = instr(dsub); x64=1; break;
2636                          case SPECIAL_DSUBU: ic->f = instr(dsubu); x64=1; break;                          case SPECIAL_DSUBU: ic->f = instr(dsubu); x64=1; break;
2637                          case SPECIAL_SLT:   ic->f = instr(slt); break;                          case SPECIAL_SLT:   ic->f = instr(slt); break;
2638                          case SPECIAL_SLTU:  ic->f = instr(sltu); break;                          case SPECIAL_SLTU:  ic->f = instr(sltu); break;
2639                            case SPECIAL_AND:   ic->f = instr(and); break;
2640                          case SPECIAL_OR:    ic->f = instr(or); break;                          case SPECIAL_OR:    ic->f = instr(or); break;
2641                          case SPECIAL_XOR:   ic->f = instr(xor); break;                          case SPECIAL_XOR:   ic->f = instr(xor); break;
2642                          case SPECIAL_NOR:   ic->f = instr(nor); break;                          case SPECIAL_NOR:   ic->f = instr(nor); break;
# Line 704  X(to_be_translated) Line 2644  X(to_be_translated)
2644                          case SPECIAL_MFLO:  ic->f = instr(mov); break;                          case SPECIAL_MFLO:  ic->f = instr(mov); break;
2645                          case SPECIAL_MTHI:  ic->f = instr(mov); break;                          case SPECIAL_MTHI:  ic->f = instr(mov); break;
2646                          case SPECIAL_MTLO:  ic->f = instr(mov); break;                          case SPECIAL_MTLO:  ic->f = instr(mov); break;
2647                            case SPECIAL_DIV:   ic->f = instr(div); break;
2648                            case SPECIAL_DIVU:  ic->f = instr(divu); break;
2649                            case SPECIAL_DDIV:  ic->f = instr(ddiv); x64=1; break;
2650                            case SPECIAL_DDIVU: ic->f = instr(ddivu); x64=1; break;
2651                            case SPECIAL_MULT : ic->f = instr(mult); break;
2652                            case SPECIAL_MULTU: ic->f = instr(multu); break;
2653                            case SPECIAL_DMULT: ic->f = instr(dmult); x64=1; break;
2654                            case SPECIAL_DMULTU:ic->f = instr(dmultu); x64=1; break;
2655                            case SPECIAL_TGE:   ic->f = instr(tge); break;
2656                            case SPECIAL_TGEU:  ic->f = instr(tgeu); break;
2657                            case SPECIAL_TLT:   ic->f = instr(tlt); break;
2658                            case SPECIAL_TLTU:  ic->f = instr(tltu); break;
2659                            case SPECIAL_TEQ:   ic->f = instr(teq); break;
2660                            case SPECIAL_TNE:   ic->f = instr(tne); break;
2661                            case SPECIAL_MOVN:  ic->f = instr(movn); break;
2662                            case SPECIAL_MOVZ:  ic->f = instr(movz); break;
2663                          }                          }
2664                          ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];                          ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];
2665                          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 2678  X(to_be_translated)
2678                                  ic->arg[2] = (size_t)&cpu->cd.mips.lo;                                  ic->arg[2] = (size_t)&cpu->cd.mips.lo;
2679                                  break;                                  break;
2680                          }                          }
2681                          /*  rd==0 => nop:  */                          /*  Special cases for rd:  */
2682                          switch (s6) {                          switch (s6) {
2683                          case SPECIAL_MTHI:                          case SPECIAL_MTHI:
2684                          case SPECIAL_MTLO:                          case SPECIAL_MTLO:
2685                                  /*  These instructions don't use rd.  */                          case SPECIAL_DIV:
2686                                  break;                          case SPECIAL_DIVU:
2687                          default:if (rd == MIPS_GPR_ZERO)                          case SPECIAL_DDIV:
2688                                          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) {  
2689                          case SPECIAL_MULT:                          case SPECIAL_MULT:
2690                          case SPECIAL_MULTU:                          case SPECIAL_MULTU:
2691                          case SPECIAL_DMULT:                          case SPECIAL_DMULT:
2692                          case SPECIAL_DMULTU:                          case SPECIAL_DMULTU:
2693                                  ic->arg[2] = (size_t)&cpu->cd.mips.gpr[rd];                          case SPECIAL_TGE:
2694                            case SPECIAL_TGEU:
2695                            case SPECIAL_TLT:
2696                            case SPECIAL_TLTU:
2697                            case SPECIAL_TEQ:
2698                            case SPECIAL_TNE:
2699                                    if (s6 == SPECIAL_MULT && rd != MIPS_GPR_ZERO) {
2700                                            if (cpu->cd.mips.cpu_type.rev ==
2701                                                MIPS_R5900) {
2702                                                    ic->f = instr(mult_r5900);
2703                                                    break;
2704                                            }
2705                                            break;
2706                                    }
2707                                    if (s6 == SPECIAL_MULTU && rd!=MIPS_GPR_ZERO) {
2708                                            if (cpu->cd.mips.cpu_type.rev ==
2709                                                MIPS_R5900) {
2710                                                    ic->f = instr(multu_r5900);
2711                                                    break;
2712                                            }
2713                                    }
2714                                  if (rd != MIPS_GPR_ZERO) {                                  if (rd != MIPS_GPR_ZERO) {
2715                                          fatal("TODO: mult with rd NON-zero\n");                                          fatal("TODO: rd NON-zero\n");
2716                                          goto bad;                                          goto bad;
2717                                  }                                  }
2718                                    /*  These instructions don't use rd.  */
2719                                  break;                                  break;
2720                            default:if (rd == MIPS_GPR_ZERO)
2721                                            ic->f = instr(nop);
2722                          }                          }
2723                          break;                          break;
2724    
# Line 761  X(to_be_translated) Line 2726  X(to_be_translated)
2726                  case SPECIAL_JALR:                  case SPECIAL_JALR:
2727                          ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];                          ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];
2728                          ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rd];                          ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rd];
2729                          if (main_opcode == SPECIAL_JALR && rd == MIPS_GPR_ZERO)                          if (s6 == SPECIAL_JALR && rd == MIPS_GPR_ZERO)
2730                                  main_opcode = SPECIAL_JR;                                  s6 = SPECIAL_JR;
2731                          ic->arg[2] = (addr & 0xffc) + 4;                          ic->arg[2] = (addr & 0xffc) + 8;
2732                          switch (main_opcode) {                          switch (s6) {
2733                          case SPECIAL_JR:                          case SPECIAL_JR:
2734                                  if (rs == MIPS_GPR_RA) {                                  if (rs == MIPS_GPR_RA) {
2735                                          if (cpu->machine->show_trace_tree)                                          if (cpu->machine->show_trace_tree)
# Line 782  X(to_be_translated) Line 2747  X(to_be_translated)
2747                                          ic->f = instr(jalr);                                          ic->f = instr(jalr);
2748                                  break;                                  break;
2749                          }                          }
2750                          if (in_crosspage_delayslot) {                          if (cpu->delay_slot) {
2751                                  fatal("[ WARNING: branch in delay slot? ]\n");                                  fatal("TODO: branch in delay slot? (1)\n");
2752                                  ic->f = instr(nop);                                  goto bad;
2753                          }                          }
2754                          break;                          break;
2755    
2756                    case SPECIAL_SYSCALL:
2757                            if (((iword >> 6) & 0xfffff) == 0x30378) {
2758                                    /*  "Magic trap" for PROM emulation:  */
2759                                    ic->f = instr(promemul);
2760                            } else {
2761                                    ic->f = instr(syscall);
2762                            }
2763                            break;
2764    
2765                    case SPECIAL_BREAK:
2766                            ic->f = instr(break);
2767                            break;
2768    
2769                  case SPECIAL_SYNC:                  case SPECIAL_SYNC:
2770                          ic->f = instr(nop);                          ic->f = instr(nop);
2771                          break;                          break;
# Line 798  X(to_be_translated) Line 2776  X(to_be_translated)
2776    
2777          case HI6_BEQ:          case HI6_BEQ:
2778          case HI6_BNE:          case HI6_BNE:
2779            case HI6_BEQL:
2780            case HI6_BNEL:
2781            case HI6_BLEZ:
2782            case HI6_BLEZL:
2783            case HI6_BGTZ:
2784            case HI6_BGTZL:
2785                  samepage_function = NULL;  /*  get rid of a compiler warning  */                  samepage_function = NULL;  /*  get rid of a compiler warning  */
2786                  switch (main_opcode) {                  switch (main_opcode) {
2787                  case HI6_BEQ:                  case HI6_BEQ:
# Line 812  X(to_be_translated) Line 2796  X(to_be_translated)
2796                  case HI6_BNE:                  case HI6_BNE:
2797                          ic->f = instr(bne);                          ic->f = instr(bne);
2798                          samepage_function = instr(bne_samepage);                          samepage_function = instr(bne_samepage);
2799                            break;
2800                    case HI6_BEQL:
2801                            ic->f = instr(beql);
2802                            samepage_function = instr(beql_samepage);
2803                            /*  Special case: comparing a register with itself:  */
2804                            if (rs == rt) {
2805                                    ic->f = instr(b);
2806                                    samepage_function = instr(b_samepage);
2807                            }
2808                            break;
2809                    case HI6_BNEL:
2810                            ic->f = instr(bnel);
2811                            samepage_function = instr(bnel_samepage);
2812                            break;
2813                    case HI6_BLEZ:
2814                            ic->f = instr(blez);
2815                            samepage_function = instr(blez_samepage);
2816                            break;
2817                    case HI6_BLEZL:
2818                            ic->f = instr(blezl);
2819                            samepage_function = instr(blezl_samepage);
2820                            break;
2821                    case HI6_BGTZ:
2822                            ic->f = instr(bgtz);
2823                            samepage_function = instr(bgtz_samepage);
2824                            break;
2825                    case HI6_BGTZL:
2826                            ic->f = instr(bgtzl);
2827                            samepage_function = instr(bgtzl_samepage);
2828                            break;
2829                  }                  }
2830                  ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];                  ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];
2831                  ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rt];                  ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rt];
2832                  ic->arg[2] = (imm << MIPS_INSTR_ALIGNMENT_SHIFT)                  ic->arg[2] = (int32_t) ( (imm << MIPS_INSTR_ALIGNMENT_SHIFT)
2833                      + (addr & 0xffc) + 4;                      + (addr & 0xffc) + 4 );
2834                  /*  Is the offset from the start of the current page still                  /*  Is the offset from the start of the current page still
2835                      within the same page? Then use the samepage_function:  */                      within the same page? Then use the samepage_function:  */
2836                  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 2840  X(to_be_translated)
2840                              & (MIPS_IC_ENTRIES_PER_PAGE - 1)));                              & (MIPS_IC_ENTRIES_PER_PAGE - 1)));
2841                          ic->f = samepage_function;                          ic->f = samepage_function;
2842                  }                  }
2843                  if (in_crosspage_delayslot) {                  if (cpu->delay_slot) {
2844                          fatal("[ WARNING: branch in delay slot? ]\n");                          fatal("TODO: branch in delay slot? (2)\n");
2845                          ic->f = instr(nop);                          goto bad;
2846                  }                  }
2847                  break;                  break;
2848    
2849            case HI6_ADDI:
2850          case HI6_ADDIU:          case HI6_ADDIU:
2851            case HI6_SLTI:
2852            case HI6_SLTIU:
2853            case HI6_DADDI:
2854          case HI6_DADDIU:          case HI6_DADDIU:
2855          case HI6_ANDI:          case HI6_ANDI:
2856          case HI6_ORI:          case HI6_ORI:
# Line 841  X(to_be_translated) Line 2859  X(to_be_translated)
2859                  ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rt];                  ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rt];
2860                  if (main_opcode == HI6_ADDI ||                  if (main_opcode == HI6_ADDI ||
2861                      main_opcode == HI6_ADDIU ||                      main_opcode == HI6_ADDIU ||
2862                        main_opcode == HI6_SLTI ||
2863                        main_opcode == HI6_SLTIU ||
2864                      main_opcode == HI6_DADDI ||                      main_opcode == HI6_DADDI ||
2865                      main_opcode == HI6_DADDIU)                      main_opcode == HI6_DADDIU)
2866                          ic->arg[2] = (int16_t)iword;                          ic->arg[2] = (int16_t)iword;
2867                  else                  else
2868                          ic->arg[2] = (uint16_t)iword;                          ic->arg[2] = (uint16_t)iword;
2869    
2870                  switch (main_opcode) {                  switch (main_opcode) {
2871                    case HI6_ADDI:    ic->f = instr(addi); break;
2872                  case HI6_ADDIU:   ic->f = instr(addiu); break;                  case HI6_ADDIU:   ic->f = instr(addiu); break;
2873                    case HI6_SLTI:    ic->f = instr(slti); break;
2874                    case HI6_SLTIU:   ic->f = instr(sltiu); break;
2875                    case HI6_DADDI:   ic->f = instr(daddi); x64 = 1; break;
2876                  case HI6_DADDIU:  ic->f = instr(daddiu); x64 = 1; break;                  case HI6_DADDIU:  ic->f = instr(daddiu); x64 = 1; break;
2877                  case HI6_ANDI:    ic->f = instr(andi); break;                  case HI6_ANDI:    ic->f = instr(andi); break;
2878                  case HI6_ORI:     ic->f = instr(ori); break;                  case HI6_ORI:     ic->f = instr(ori); break;
2879                  case HI6_XORI:    ic->f = instr(xori); break;                  case HI6_XORI:    ic->f = instr(xori); break;
2880                  }                  }
2881    
2882                  if (rt == MIPS_GPR_ZERO)                  if (rt == MIPS_GPR_ZERO)
2883                          ic->f = instr(nop);                          ic->f = instr(nop);
2884    
2885                  if (ic->f == instr(addiu))                  if (ic->f == instr(addiu))
2886                          cpu->cd.mips.combination_check = COMBINE(b_addiu);                          cpu->cd.mips.combination_check = COMBINE(b_addiu);
2887                    if (ic->f == instr(daddiu))
2888                            cpu->cd.mips.combination_check = COMBINE(b_daddiu);
2889                  break;                  break;
2890    
2891          case HI6_LUI:          case HI6_LUI:
2892                  ic->f = instr(set);                  ic->f = instr(set);
2893                  ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];                  ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
2894                  ic->arg[1] = imm << 16;                  ic->arg[1] = (int32_t) (imm << 16);
2895                  if (rt == MIPS_GPR_ZERO)                  if (rt == MIPS_GPR_ZERO)
2896                          ic->f = instr(nop);                          ic->f = instr(nop);
2897                  break;                  break;
2898    
2899            case HI6_J:
2900            case HI6_JAL:
2901                    switch (main_opcode) {
2902                    case HI6_J:
2903                            ic->f = instr(j);
2904                            break;
2905                    case HI6_JAL:
2906                            if (cpu->machine->show_trace_tree)
2907                                    ic->f = instr(jal_trace);
2908                            else
2909                                    ic->f = instr(jal);
2910                            break;
2911                    }
2912                    ic->arg[0] = (iword & 0x03ffffff) << 2;
2913                    ic->arg[1] = (addr & 0xffc) + 8;
2914                    if (cpu->delay_slot) {
2915                            fatal("TODO: branch in delay slot (=%i)? (3); addr=%016"
2916                                PRIx64" iword=%08"PRIx32"\n", cpu->delay_slot,
2917                                (uint64_t)addr, iword);
2918                            goto bad;
2919                    }
2920                    break;
2921    
2922          case HI6_COP0:          case HI6_COP0:
2923                    /*  TODO: Is checking bit 25 enough, or perhaps all bits
2924                        25..21 must be checked?  */
2925                    if ((iword >> 25) & 1) {
2926                            ic->arg[2] = addr & 0xffc;
2927                            switch (iword & 0xff) {
2928                            case COP0_TLBR:
2929                                    ic->f = instr(tlbr);
2930                                    break;
2931                            case COP0_TLBWI:
2932                            case COP0_TLBWR:
2933                                    ic->f = instr(tlbw);
2934                                    ic->arg[0] = (iword & 0xff) == COP0_TLBWR;
2935                                    break;
2936                            case COP0_TLBP:
2937                                    ic->f = instr(tlbp);
2938                                    break;
2939                            case COP0_RFE:
2940                                    ic->f = instr(rfe);
2941                                    break;
2942                            case COP0_ERET:
2943                                    ic->f = instr(eret);
2944                                    break;
2945                            case COP0_DERET:
2946                                    ic->f = instr(deret);
2947                                    break;
2948                            case COP0_IDLE:
2949                            case COP0_STANDBY:
2950                            case COP0_SUSPEND:
2951                            case COP0_HIBERNATE:
2952                                    /*  TODO  */
2953                                    ic->f = instr(nop);
2954                                    break;
2955                            case COP0_EI:
2956                                    if (cpu->cd.mips.cpu_type.rev == MIPS_R5900) {
2957                                            ic->f = instr(ei_r5900);
2958                                    } else
2959                                            goto bad;
2960                                    break;
2961                            case COP0_DI:
2962                                    if (cpu->cd.mips.cpu_type.rev == MIPS_R5900) {
2963                                            ic->f = instr(di_r5900);
2964                                    } else
2965                                            goto bad;
2966                                    break;
2967                            default:fatal("UNIMPLEMENTED cop0 (func 0x%02x)\n",
2968                                        iword & 0xff);
2969                                    goto bad;
2970                            }
2971                            break;
2972                    }
2973    
2974                  /*  rs contains the coprocessor opcode!  */                  /*  rs contains the coprocessor opcode!  */
2975                  switch (rs) {                  switch (rs) {
2976                    case COPz_CFCz:
2977                            ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
2978                            ic->arg[1] = rd + ((iword & 7) << 5);
2979                            ic->arg[2] = addr & 0xffc;
2980                            ic->f = instr(cfc0);
2981                            if (rt == MIPS_GPR_ZERO)
2982                                    ic->f = instr(nop);
2983                            break;
2984                  case COPz_MFCz:                  case COPz_MFCz:
2985                  case COPz_DMFCz:                  case COPz_DMFCz:
2986                          ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];                          ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
# Line 887  X(to_be_translated) Line 2997  X(to_be_translated)
2997                          ic->arg[2] = addr & 0xffc;                          ic->arg[2] = addr & 0xffc;
2998                          ic->f = rs == COPz_MTCz? instr(mtc0) : instr(dmtc0);                          ic->f = rs == COPz_MTCz? instr(mtc0) : instr(dmtc0);
2999                          break;                          break;
3000                    case 8: if (iword == 0x4100ffff) {
3001                                    /*  R2020 DECstation write-loop thingy.  */
3002                                    ic->f = instr(nop);
3003                            } else {
3004                                    fatal("Unimplemented blah blah zzzz...\n");
3005                                    goto bad;
3006                            }
3007                            break;
3008                    
3009                  default:fatal("UNIMPLEMENTED cop0 (rs = %i)\n", rs);                  default:fatal("UNIMPLEMENTED cop0 (rs = %i)\n", rs);
3010                          goto bad;                          goto bad;
3011                  }                  }
3012                  break;                  break;
3013    
3014          case HI6_COP1:          case HI6_COP1:
3015                  /*  rs contains the coprocessor opcode!  */                  /*  Always cause a coprocessor unusable exception if
3016                        there is no floating point coprocessor:  */
3017                    if (cpu->cd.mips.cpu_type.flags & NOFPU ||
3018                        cpu->cd.mips.coproc[1] == NULL) {
3019                            ic->f = instr(cpu);
3020                            ic->arg[0] = 1;
3021                            break;
3022                    }
3023    
3024                    /*  Bits 25..21 are floating point main opcode:  */
3025                  switch (rs) {                  switch (rs) {
3026    
3027                    case COPz_BCzc:
3028                            /*  Conditional branch:  */
3029                            /*  TODO: Reimplement this in a faster way.  */
3030                            ic->f = instr(cop1_bc);
3031                            ic->arg[0] = (iword >> 18) & 7; /*  cc  */
3032                            ic->arg[1] = (iword >> 16) & 3; /*  nd, tf bits  */
3033                            ic->arg[2] = (int32_t) ((imm <<
3034                                MIPS_INSTR_ALIGNMENT_SHIFT) + (addr & 0xffc) + 4);
3035                            if (cpu->delay_slot) {
3036                                    fatal("TODO: branch in delay slot? (4)\n");
3037                                    goto bad;
3038                            }
3039                            if (cpu->cd.mips.cpu_type.isa_level <= 3 &&
3040                                ic->arg[0] != 0) {
3041                                    fatal("Attempt to execute a non-cc-0 BC*"
3042                                        " instruction on an isa level %i cpu. "
3043                                        "TODO: How should this be handled?\n",
3044                                        cpu->cd.mips.cpu_type.isa_level);
3045                                    goto bad;
3046                            }
3047    
3048                            break;
3049    
3050                    case COPz_DMFCz:
3051                    case COPz_DMTCz:
3052                            x64 = 1;
3053                            /*  FALL-THROUGH  */
3054                    case COP1_FMT_S:
3055                    case COP1_FMT_D:
3056                    case COP1_FMT_W:
3057                    case COP1_FMT_L:
3058                    case COP1_FMT_PS:
3059                  case COPz_CFCz:                  case COPz_CFCz:
3060                          ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];                  case COPz_CTCz:
3061                          ic->arg[1] = (size_t)&cpu->cd.mips.coproc[1]->fcr[rd];                  case COPz_MFCz:
3062                          ic->arg[2] = addr & 0xffc;                  case COPz_MTCz:
3063                          ic->f = instr(cfc1);                          /*  Fallback to slow pre-dyntrans code, for now.  */
3064                          if (rt == MIPS_GPR_ZERO)                          /*  TODO: Fix/optimize/rewrite.  */
3065                                  ic->f = instr(nop);                          ic->f = instr(cop1_slow);
3066                            ic->arg[0] = (uint32_t)iword & ((1 << 26) - 1);
3067                          break;                          break;
3068                  default:fatal("UNIMPLEMENTED cop1 (rs = %i)\n", rs);  
3069                    default:fatal("COP1 floating point opcode = 0x%02x\n", rs);
3070                          goto bad;                          goto bad;
3071                  }                  }
3072                  break;                  break;
3073    
3074            case HI6_COP2:
3075                    /*  Always cause a coprocessor unusable exception if
3076                        there is no coprocessor 2:  */
3077                    if (cpu->cd.mips.coproc[2] == NULL) {
3078                            ic->f = instr(cpu);
3079                            ic->arg[0] = 2;
3080                            break;
3081                    }
3082                    fatal("COP2 functionality not yet implemented\n");
3083                    goto bad;
3084                    break;
3085    
3086          case HI6_SPECIAL2:          case HI6_SPECIAL2:
3087                    if (cpu->cd.mips.cpu_type.rev == MIPS_R5900) {
3088                            /*  R5900, TX79/C790, have MMI instead of SPECIAL2:  */
3089                            int mmi_subopcode = (iword >> 6) & 0x1f;
3090    
3091                            switch (s6) {
3092    
3093                            case MMI_MADD:
3094                                    ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];
3095                                    ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rt];
3096                                    ic->arg[2] = (size_t)&cpu->cd.mips.gpr[rd];
3097                                    if (rd == MIPS_GPR_ZERO)
3098                                            ic->f = instr(madd);
3099                                    else
3100                                            ic->f = instr(madd_rd);
3101                                    break;
3102    
3103                            case MMI_MADDU:
3104                                    ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];
3105                                    ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rt];
3106                                    ic->arg[2] = (size_t)&cpu->cd.mips.gpr[rd];
3107                                    if (rd == MIPS_GPR_ZERO)
3108                                            ic->f = instr(maddu);
3109                                    else
3110                                            ic->f = instr(maddu_rd);
3111                                    break;
3112    
3113                            case MMI_MMI0:
3114                                    switch (mmi_subopcode) {
3115    
3116                                    case MMI0_PEXTLW:
3117                                            ic->arg[0] = rs;
3118                                            ic->arg[1] = rt;
3119                                            ic->arg[2] = rd;
3120                                            if (rd == MIPS_GPR_ZERO)
3121                                                    ic->f = instr(nop);
3122                                            else
3123                                                    ic->f = instr(pextlw);
3124                                            break;
3125    
3126                                    default:goto bad;
3127                                    }
3128                                    break;
3129    
3130                            case MMI_MMI3:
3131                                    switch (mmi_subopcode) {
3132    
3133                                    case MMI3_POR:
3134                                            ic->arg[0] = rs;
3135                                            ic->arg[1] = rt;
3136                                            ic->arg[2] = rd;
3137                                            if (rd == MIPS_GPR_ZERO)
3138                                                    ic->f = instr(nop);
3139                                            else
3140                                                    ic->f = instr(por);
3141                                            break;
3142    
3143                                    default:goto bad;
3144                                    }
3145                                    break;
3146    
3147                            default:goto bad;
3148                            }
3149                            break;
3150                    }
3151    
3152                    /*  TODO: is this correct? Or are there other non-MIPS32/64
3153                        MIPS processors that have support for SPECIAL2 opcodes?  */
3154                    if (cpu->cd.mips.cpu_type.isa_level < 32) {
3155                            ic->f = instr(reserved);
3156                            break;
3157                    }
3158    
3159                    /*  SPECIAL2:  */
3160                  switch (s6) {                  switch (s6) {
3161    
3162                    case SPECIAL2_MADD:
3163                    case SPECIAL2_MADDU:
3164                    case SPECIAL2_MSUB:
3165                    case SPECIAL2_MSUBU:
3166                            ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];
3167                            ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rt];
3168                            switch (s6) {
3169                            case SPECIAL2_MADD: ic->f = instr(madd); break;
3170                            case SPECIAL2_MADDU:ic->f = instr(maddu); break;
3171                            case SPECIAL2_MSUB: ic->f = instr(msub); break;
3172                            case SPECIAL2_MSUBU:ic->f = instr(msubu); break;
3173                            }
3174                            break;
3175    
3176                  case SPECIAL2_MUL:                  case SPECIAL2_MUL:
3177                          ic->f = instr(mul);                          ic->f = instr(mul);
3178                          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 3202  X(to_be_translated)
3202                  }                  }
3203                  break;                  break;
3204    
3205            case HI6_REGIMM:
3206                    switch (rt) {
3207                    case REGIMM_BGEZ:
3208                    case REGIMM_BGEZL:
3209                    case REGIMM_BLTZ:
3210                    case REGIMM_BLTZL:
3211                    case REGIMM_BGEZAL:
3212                    case REGIMM_BGEZALL:
3213                    case REGIMM_BLTZAL:
3214                    case REGIMM_BLTZALL:
3215                            samepage_function = NULL;
3216                            switch (rt) {
3217                            case REGIMM_BGEZ:
3218                                    ic->f = instr(bgez);
3219                                    samepage_function = instr(bgez_samepage);
3220                                    break;
3221                            case REGIMM_BGEZL:
3222                                    ic->f = instr(bgezl);
3223                                    samepage_function = instr(bgezl_samepage);
3224                                    break;
3225                            case REGIMM_BLTZ:
3226                                    ic->f = instr(bltz);
3227                                    samepage_function = instr(bltz_samepage);
3228                                    break;
3229                            case REGIMM_BLTZL:
3230                                    ic->f = instr(bltzl);
3231                                    samepage_function = instr(bltzl_samepage);
3232                                    break;
3233                            case REGIMM_BGEZAL:
3234                                    ic->f = instr(bgezal);
3235                                    samepage_function = instr(bgezal_samepage);
3236                                    break;
3237                            case REGIMM_BGEZALL:
3238                                    ic->f = instr(bgezall);
3239                                    samepage_function = instr(bgezall_samepage);
3240                                    break;
3241                            case REGIMM_BLTZAL:
3242                                    ic->f = instr(bltzal);
3243                                    samepage_function = instr(bltzal_samepage);
3244                                    break;
3245                            case REGIMM_BLTZALL:
3246                                    ic->f = instr(bltzall);
3247                                    samepage_function = instr(bltzall_samepage);
3248                                    break;
3249                            }
3250                            ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];
3251                            ic->arg[2] = (imm << MIPS_INSTR_ALIGNMENT_SHIFT)
3252                                + (addr & 0xffc) + 4;
3253                            /*  Is the offset from the start of the current page
3254                                still within the same page? Then use the
3255                                samepage_function:  */
3256                            if ((uint32_t)ic->arg[2] < ((MIPS_IC_ENTRIES_PER_PAGE-1)
3257                                << MIPS_INSTR_ALIGNMENT_SHIFT) && (addr & 0xffc)
3258                                < 0xffc) {
3259                                    ic->arg[2] = (size_t) (cpu->cd.mips.cur_ic_page+
3260                                        ((ic->arg[2] >> MIPS_INSTR_ALIGNMENT_SHIFT)
3261                                        & (MIPS_IC_ENTRIES_PER_PAGE - 1)));
3262                                    ic->f = samepage_function;
3263                            }
3264                            if (cpu->delay_slot) {
3265                                    fatal("TODO: branch in delay slot? (5)\n");
3266                                    goto bad;
3267                            }
3268                            break;
3269                    default:fatal("UNIMPLEMENTED regimm rt=%i\n", rt);
3270                            goto bad;
3271                    }
3272                    break;
3273    
3274            case HI6_LB:
3275            case HI6_LBU:
3276            case HI6_SB:
3277            case HI6_LH:
3278            case HI6_LHU:
3279            case HI6_SH:
3280            case HI6_LW:
3281            case HI6_LWU:
3282            case HI6_SW:
3283            case HI6_LD:
3284            case HI6_SD:
3285                    /*  TODO: LWU should probably also be x64=1?  */
3286                    size = 2; signedness = 0; store = 0;
3287                    switch (main_opcode) {
3288                    case HI6_LB:  size = 0; signedness = 1; break;
3289                    case HI6_LBU: size = 0; break;
3290                    case HI6_LH:  size = 1; signedness = 1; break;
3291                    case HI6_LHU: size = 1; break;
3292                    case HI6_LW:  signedness = 1; break;
3293                    case HI6_LWU: break;
3294                    case HI6_LD:  size = 3; x64 = 1; break;
3295                    case HI6_SB:  store = 1; size = 0; break;
3296                    case HI6_SH:  store = 1; size = 1; break;
3297                    case HI6_SW:  store = 1; break;
3298                    case HI6_SD:  store = 1; size = 3; x64 = 1; break;
3299                    }
3300    
3301                    ic->f =
3302    #ifdef MODE32
3303                        mips32_loadstore
3304    #else
3305                        mips_loadstore
3306    #endif
3307                        [ (cpu->byte_order == EMUL_LITTLE_ENDIAN? 0 : 16)
3308                        + store * 8 + size * 2 + signedness];
3309                    ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
3310                    ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rs];
3311                    ic->arg[2] = (int32_t)imm;
3312    
3313                    /*  Load into the dummy scratch register, if rt = zero  */
3314                    if (!store && rt == MIPS_GPR_ZERO)
3315                            ic->arg[0] = (size_t)&cpu->cd.mips.scratch;
3316                    break;
3317    
3318            case HI6_LL:
3319            case HI6_LLD:
3320            case HI6_SC:
3321            case HI6_SCD:
3322                    /*  32-bit load-linked/store-condition for ISA II and up:  */
3323                    /*  (64-bit load-linked/store-condition for ISA III...)  */
3324                    if (cpu->cd.mips.cpu_type.isa_level < 2) {
3325                            ic->f = instr(reserved);
3326                            break;
3327                    }
3328    
3329                    store = 0;
3330                    switch (main_opcode) {
3331                    case HI6_LL:  ic->f = instr(ll); break;
3332                    case HI6_LLD: ic->f = instr(lld); x64 = 1; break;
3333                    case HI6_SC:  ic->f = instr(sc); store = 1; break;
3334                    case HI6_SCD: ic->f = instr(scd); store = 1; x64 = 1; break;
3335                    }
3336                    ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
3337                    ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rs];
3338                    ic->arg[2] = (int32_t)imm;
3339                    if (!store && rt == MIPS_GPR_ZERO) {
3340                            fatal("HM... unusual load linked\n");
3341                            goto bad;
3342                    }
3343                    break;
3344    
3345            case HI6_LWL:
3346            case HI6_LWR:
3347            case HI6_LDL:
3348            case HI6_LDR:
3349            case HI6_SWL:
3350            case HI6_SWR:
3351            case HI6_SDL:
3352            case HI6_SDR:
3353                    /*  TODO: replace these with faster versions...  */
3354                    store = 0;
3355                    switch (main_opcode) {
3356                    case HI6_LWL: ic->f = instr(lwl); break;
3357                    case HI6_LWR: ic->f = instr(lwr); break;
3358                    case HI6_LDL: ic->f = instr(ldl); x64 = 1; break;
3359                    case HI6_LDR: ic->f = instr(ldr); x64 = 1; break;
3360                    case HI6_SWL: ic->f = instr(swl); store = 1; break;
3361                    case HI6_SWR: ic->f = instr(swr); store = 1; break;
3362                    case HI6_SDL: ic->f = instr(sdl); store = 1; x64 = 1; break;
3363                    case HI6_SDR: ic->f = instr(sdr); store = 1; x64 = 1; break;
3364                    }
3365                    ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
3366                    ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rs];
3367                    ic->arg[2] = (int32_t)imm;
3368    
3369                    /*  Load into the dummy scratch register, if rt = zero  */
3370                    if (!store && rt == MIPS_GPR_ZERO)
3371                            ic->arg[0] = (size_t)&cpu->cd.mips.scratch;
3372                    break;
3373    
3374            case HI6_LWC1:
3375            case HI6_SWC1:
3376            case HI6_LDC1:
3377            case HI6_SDC1:
3378                    /*  64-bit floating-point load/store for ISA II and up...  */
3379                    if ((main_opcode == HI6_LDC1 || main_opcode == HI6_SDC1)
3380                        && cpu->cd.mips.cpu_type.isa_level < 2) {
3381                            ic->f = instr(reserved);
3382                            break;
3383                    }
3384    
3385                    ic->arg[0] = (size_t)&cpu->cd.mips.coproc[1]->reg[rt];
3386                    ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rs];
3387                    ic->arg[2] = (int32_t)imm;
3388                    switch (main_opcode) {
3389                    case HI6_LWC1: ic->f = instr(lwc1); break;
3390                    case HI6_LDC1: ic->f = instr(ldc1); break;
3391                    case HI6_SWC1: ic->f = instr(swc1); break;
3392                    case HI6_SDC1: ic->f = instr(sdc1); break;
3393                    }
3394    
3395                    /*  Cause a coprocessor unusable exception if
3396                        there is no floating point coprocessor:  */
3397                    if (cpu->cd.mips.cpu_type.flags & NOFPU ||
3398                        cpu->cd.mips.coproc[1] == NULL) {
3399                            ic->f = instr(cpu);
3400                            ic->arg[0] = 1;
3401                    }
3402                    break;
3403    
3404            case HI6_LWC3:
3405                    /*  PREF (prefetch) on ISA IV and MIPS32/64:  */
3406                    if (cpu->cd.mips.cpu_type.isa_level >= 4) {
3407                            /*  Treat as nop for now:  */
3408                            ic->f = instr(nop);
3409                    } else {
3410                            fatal("TODO: lwc3 not implemented yet\n");
3411                            goto bad;
3412                    }
3413                    break;
3414    
3415            case HI6_LQ_MDMX:
3416                    if (cpu->cd.mips.cpu_type.rev == MIPS_R5900) {
3417                            fatal("TODO: R5900 128-bit loads\n");
3418                            goto bad;
3419                    }
3420    
3421                    fatal("TODO: MDMX\n");
3422                    goto bad;
3423                    /*  break  */
3424    
3425            case HI6_SQ_SPECIAL3:
3426                    if (cpu->cd.mips.cpu_type.rev == MIPS_R5900) {
3427                            fatal("TODO: R5900 128-bit stores\n");
3428                            goto bad;
3429                    }
3430    
3431                    if (cpu->cd.mips.cpu_type.isa_level < 32 ||
3432                        cpu->cd.mips.cpu_type.isa_revision < 2) {
3433                            static int warning = 0;
3434                            if (!warning) {
3435                                    fatal("[ WARNING! SPECIAL3 opcode used on a"
3436                                        " cpu which doesn't implement it ]\n");
3437                                    warning = 1;
3438                            }
3439                            ic->f = instr(reserved);
3440                            break;
3441                    }
3442    
3443                    switch (s6) {
3444    
3445                    case SPECIAL3_RDHWR:
3446                            ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
3447    
3448                            switch (rd) {
3449    
3450                            case 0: ic->f = instr(rdhwr_cpunum);
3451                                    if (rt == MIPS_GPR_ZERO)
3452                                            ic->f = instr(nop);
3453                                    break;
3454    
3455                            default:fatal("unimplemented rdhwr register rd=%i\n",
3456                                        rd);
3457                                    goto bad;
3458                            }
3459                            break;
3460    
3461                    default:goto bad;
3462                    }
3463                    break;
3464    
3465            case HI6_CACHE:
3466                    /*  TODO: rt and op etc...  */
3467                    ic->f = instr(cache);
3468                    break;
3469    
3470          default:goto bad;          default:goto bad;
3471          }          }
3472    
3473          if (x64)  #ifdef MODE32
3474                  ic->f = instr(invalid_32_64);          if (x64) {
3475                    static int has_warned = 0;
3476                    if (!has_warned)
3477                            fatal("[ WARNING/NOTE: attempt to execute a 64-bit"
3478                                " instruction on an emulated 32-bit processor; "
3479                                "pc=0x%08"PRIx32" ]\n", (uint32_t)cpu->pc);
3480                    has_warned = 1;
3481                    ic->f = instr(reserved);
3482            }
3483    #endif
3484    
         if (in_crosspage_delayslot)  
                 cpu->cd.mips.combination_check = NULL;  
3485    
3486  #define DYNTRANS_TO_BE_TRANSLATED_TAIL  #define DYNTRANS_TO_BE_TRANSLATED_TAIL
3487  #include "cpu_dyntrans.c"  #include "cpu_dyntrans.c"

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

  ViewVC Help
Powered by ViewVC 1.1.26