/[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 26 by dpavlin, Mon Oct 8 16:20:10 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.87 2006/06/25 02:46:08 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    
1620          cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);          cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
1621          cpu->pc |= ic->arg[2];          cpu->pc |= ic->arg[2];
1622    
1623          /*  TODO: cause exception if necessary  */          /*  TODO: cause exception if necessary  */
1624          coproc_register_write(cpu, cpu->cd.mips.coproc[0], rd,          coproc_register_write(cpu, cpu->cd.mips.coproc[0], rd, &tmp, 0, select);
1625              (uint64_t *)ic->arg[0], 0, select);  
1626            /*
1627             *  Interrupts enabled, and any interrupt pending? (Note/TODO: This
1628             *  code is duplicated in cpu_dyntrans.c. Fix this?)
1629             */
1630            if (rd == COP0_STATUS && !cpu->delay_slot) {
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_EXL | STATUS_ERL))
1636                            status &= ~STATUS_IE;
1637                    /*  Ugly R5900 special case:  (TODO: move this?)  */
1638                    if (cpu->cd.mips.cpu_type.rev == MIPS_R5900 &&
1639                        !(status & R5900_STATUS_EIE))
1640                            status &= ~STATUS_IE;
1641                    if (status & STATUS_IE && (status & cause & STATUS_IM_MASK)) {
1642                            cpu->pc += sizeof(uint32_t);
1643                            mips_cpu_exception(cpu, EXCEPTION_INT, 0, 0,0,0,0,0);
1644                    }
1645            }
1646  }  }
1647  X(dmfc0)  X(dmfc0)
1648  {  {
# Line 446  X(dmtc0) Line 1662  X(dmtc0)
1662          coproc_register_write(cpu, cpu->cd.mips.coproc[0], rd,          coproc_register_write(cpu, cpu->cd.mips.coproc[0], rd,
1663              (uint64_t *)ic->arg[0], 1, select);              (uint64_t *)ic->arg[0], 1, select);
1664  }  }
1665  X(cfc1)  
1666    
1667    /*
1668     *  cop1_bc:  Floating point conditional branch.
1669     *
1670     *  arg[0] = cc
1671     *  arg[1] = nd (=2) and tf (=1) bits
1672     *  arg[2] = offset (relative to start of this page)
1673     */
1674    X(cop1_bc)
1675    {
1676            MODE_int_t old_pc = cpu->pc;
1677            const int cpnr = 1;
1678            int x, low_pc, cc = ic->arg[0];
1679    
1680            low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1681                / sizeof(struct mips_instr_call);
1682            cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<< MIPS_INSTR_ALIGNMENT_SHIFT);
1683            cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1684            if (!(cpu->cd.mips.coproc[0]->
1685                reg[COP0_STATUS] & ((1 << cpnr) << STATUS_CU_SHIFT)) ) {
1686                    mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0, cpnr, 0, 0, 0);
1687                    return;
1688            }
1689    
1690            /*  Get the correct condition code bit:  */
1691            if (cc == 0)
1692                    x = (cpu->cd.mips.coproc[1]->fcr[MIPS_FPU_FCSR]
1693                        >> MIPS_FCSR_FCC0_SHIFT) & 1;
1694            else
1695                    x = (cpu->cd.mips.coproc[1]->fcr[MIPS_FPU_FCSR]
1696                        >> (MIPS_FCSR_FCC1_SHIFT + cc-1)) & 1;
1697    
1698            /*  Branch on false? Then invert the truth value.  */
1699            if (!(ic->arg[1] & 1))
1700                    x ^= 1;
1701    
1702            /*  Execute the delay slot (except if it is nullified):  */
1703            cpu->delay_slot = TO_BE_DELAYED;
1704            if (x || !(ic->arg[1] & 2))
1705                    ic[1].f(cpu, ic+1);
1706            cpu->n_translated_instrs ++;
1707    
1708            if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
1709                    /*  Note: Must be non-delayed when jumping to the new pc:  */
1710                    cpu->delay_slot = NOT_DELAYED;
1711                    if (x) {
1712                            old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
1713                                MIPS_INSTR_ALIGNMENT_SHIFT);
1714                            cpu->pc = old_pc + (int32_t)ic->arg[2];
1715                            quick_pc_to_pointers(cpu);
1716                    } else
1717                            cpu->cd.mips.next_ic ++;
1718            } else
1719                    cpu->delay_slot = NOT_DELAYED;
1720    }
1721    
1722    
1723    /*
1724     *  cop1_slow:  Fallback to legacy cop1 code. (Slow, but it should work.)
1725     */
1726    X(cop1_slow)
1727    {
1728            const int cpnr = 1;
1729            int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1730                / sizeof(struct mips_instr_call);
1731            cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<< MIPS_INSTR_ALIGNMENT_SHIFT);
1732            cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1733    
1734            if (!(cpu->cd.mips.coproc[0]->
1735                reg[COP0_STATUS] & ((1 << cpnr) << STATUS_CU_SHIFT)) ) {
1736                    mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0, cpnr, 0, 0, 0);
1737                    return;
1738            }
1739    
1740            coproc_function(cpu, cpu->cd.mips.coproc[1], 1, ic->arg[0], 0, 1);
1741    }
1742    
1743    
1744    /*
1745     *  syscall, break:  Synchronize the PC and cause an exception.
1746     */
1747    X(syscall)
1748    {
1749            int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1750                / sizeof(struct mips_instr_call);
1751            cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<< MIPS_INSTR_ALIGNMENT_SHIFT);
1752            cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1753            mips_cpu_exception(cpu, EXCEPTION_SYS, 0, 0, 0, 0, 0, 0);
1754    }
1755    X(break)
1756    {
1757            int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1758                / sizeof(struct mips_instr_call);
1759            cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<< MIPS_INSTR_ALIGNMENT_SHIFT);
1760            cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1761            mips_cpu_exception(cpu, EXCEPTION_BP, 0, 0, 0, 0, 0, 0);
1762    }
1763    
1764    
1765    /*
1766     *  promemul:  PROM software emulation.
1767     */
1768    X(promemul)
1769    {
1770            /*  Synchronize the PC and call the correct emulation layer:  */
1771            MODE_int_t old_pc;
1772            int res, low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1773                / sizeof(struct mips_instr_call);
1774            cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<< MIPS_INSTR_ALIGNMENT_SHIFT);
1775            cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1776            old_pc = cpu->pc;
1777    
1778            switch (cpu->machine->machine_type) {
1779            case MACHINE_PMAX:
1780                    res = decstation_prom_emul(cpu);
1781                    break;
1782            case MACHINE_PS2:
1783                    res = playstation2_sifbios_emul(cpu);
1784                    break;
1785            case MACHINE_ARC:
1786            case MACHINE_SGI:
1787                    res = arcbios_emul(cpu);
1788                    break;
1789            case MACHINE_EVBMIPS:
1790                    res = yamon_emul(cpu);
1791                    break;
1792            default:fatal("TODO: Unimplemented machine type for PROM magic trap\n");
1793                    exit(1);
1794            }
1795    
1796            if (res) {
1797                    /*  Return from the PROM call:  */
1798                    cpu->pc = (MODE_int_t)cpu->cd.mips.gpr[MIPS_GPR_RA];
1799                    cpu->delay_slot = NOT_DELAYED;
1800    
1801                    if (cpu->machine->show_trace_tree)
1802                            cpu_functioncall_trace_return(cpu);
1803            } else {
1804                    /*  The PROM call blocks.  */
1805                    cpu->n_translated_instrs += 10;
1806                    cpu->pc = old_pc;
1807            }
1808    
1809            quick_pc_to_pointers(cpu);
1810    }
1811    
1812    
1813    /*
1814     *  tlbw: TLB write indexed and random
1815     *
1816     *  arg[0] = 1 for random, 0 for indexed
1817     *  arg[2] = relative addr of this instruction within the page
1818     */
1819    X(tlbw)
1820  {  {
1821          cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);          cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
1822          cpu->pc |= ic->arg[2];          cpu->pc |= ic->arg[2];
1823          /*  TODO: cause exception if necessary  */          coproc_tlbwri(cpu, ic->arg[0]);
1824          reg(ic->arg[0]) = reg(ic->arg[1]);  }
1825    
1826    
1827    /*
1828     *  tlbp: TLB probe
1829     *  tlbr: TLB read
1830     *
1831     *  arg[2] = relative addr of this instruction within the page
1832     */
1833    X(tlbp)
1834    {
1835            cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
1836            cpu->pc |= ic->arg[2];
1837            coproc_tlbpr(cpu, 0);
1838    }
1839    X(tlbr)
1840    {
1841            cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
1842            cpu->pc |= ic->arg[2];
1843            coproc_tlbpr(cpu, 1);
1844    }
1845    
1846    
1847    /*
1848     *  rfe: Return from exception handler (R2000/R3000)
1849     */
1850    X(rfe)
1851    {
1852            coproc_rfe(cpu);
1853    
1854            /*  Note: no pc to pointers conversion is necessary here.  */
1855    }
1856    
1857    
1858    /*
1859     *  eret: Return from exception handler
1860     */
1861    X(eret)
1862    {
1863            coproc_eret(cpu);
1864            quick_pc_to_pointers(cpu);
1865    }
1866    
1867    
1868    /*
1869     *  deret: Return from debug (EJTAG) handler
1870     */
1871    X(deret)
1872    {
1873            /*
1874             *  According to the MIPS64 manual, deret loads PC from the DEPC cop0
1875             *  register, and jumps there immediately. No delay slot.
1876             *
1877             *  TODO: This instruction is only available if the processor is in
1878             *  debug mode. (What does that mean?)
1879             *
1880             *  TODO: This instruction is undefined in a delay slot.
1881             */
1882    
1883            cpu->pc = cpu->cd.mips.coproc[0]->reg[COP0_DEPC];
1884            cpu->delay_slot = 0;
1885            cpu->cd.mips.coproc[0]->reg[COP0_STATUS] &= ~STATUS_EXL;
1886            quick_pc_to_pointers(cpu);
1887    }
1888    
1889    
1890    /*
1891     *  rdhwr: Read hardware register into gpr (MIPS32/64 rev 2).
1892     *
1893     *  arg[0] = ptr to rt (destination register)
1894     */
1895    X(rdhwr_cpunum)
1896    {
1897            reg(ic->arg[0]) = cpu->cpu_id;
1898    }
1899    
1900    
1901    #include "tmp_mips_loadstore.c"
1902    
1903    
1904    /*
1905     *  Load linked / store conditional:
1906     *
1907     *  A Load-linked instruction initiates a RMW (read-modify-write) sequence.
1908     *  COP0_LLADDR is updated for diagnostic purposes, except for CPUs in the
1909     *  R10000 family.
1910     *
1911     *  A Store-conditional instruction ends the sequence.
1912     *
1913     *  arg[0] = ptr to rt
1914     *  arg[1] = ptr to rs
1915     *  arg[2] = int32_t imm
1916     */
1917    X(ll)
1918    {
1919            MODE_int_t addr = reg(ic->arg[1]) + (int32_t)ic->arg[2];
1920            int low_pc;
1921            uint8_t word[sizeof(uint32_t)];
1922    
1923            /*  Synch. PC and load using slow memory_rw():  */
1924            low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1925                / sizeof(struct mips_instr_call);
1926            cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
1927                << MIPS_INSTR_ALIGNMENT_SHIFT);
1928            cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1929    
1930            if (addr & (sizeof(word)-1)) {
1931                    fatal("TODO: load linked unaligned access: exception\n");
1932                    exit(1);
1933            }
1934    
1935            if (!cpu->memory_rw(cpu, cpu->mem, addr, word,
1936                sizeof(word), MEM_READ, CACHE_DATA)) {
1937                    /*  An exception occurred.  */
1938                    return;
1939            }
1940    
1941            cpu->cd.mips.rmw = 1;
1942            cpu->cd.mips.rmw_addr = addr;
1943            cpu->cd.mips.rmw_len = sizeof(word);
1944            if (cpu->cd.mips.cpu_type.exc_model != MMU10K)
1945                    cpu->cd.mips.coproc[0]->reg[COP0_LLADDR] =
1946                        (addr >> 4) & 0xffffffffULL;
1947    
1948            if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
1949                    reg(ic->arg[0]) = (int32_t) (word[0] + (word[1] << 8)
1950                        + (word[2] << 16) + (word[3] << 24));
1951            else
1952                    reg(ic->arg[0]) = (int32_t) (word[3] + (word[2] << 8)
1953                        + (word[1] << 16) + (word[0] << 24));
1954    }
1955    X(lld)
1956    {
1957            MODE_int_t addr = reg(ic->arg[1]) + (int32_t)ic->arg[2];
1958            int low_pc;
1959            uint8_t word[sizeof(uint64_t)];
1960    
1961            /*  Synch. PC and load using slow memory_rw():  */
1962            low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1963                / sizeof(struct mips_instr_call);
1964            cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
1965                << MIPS_INSTR_ALIGNMENT_SHIFT);
1966            cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1967    
1968            if (addr & (sizeof(word)-1)) {
1969                    fatal("TODO: load linked unaligned access: exception\n");
1970                    exit(1);
1971            }
1972    
1973            if (!cpu->memory_rw(cpu, cpu->mem, addr, word,
1974                sizeof(word), MEM_READ, CACHE_DATA)) {
1975                    /*  An exception occurred.  */
1976                    return;
1977            }
1978    
1979            cpu->cd.mips.rmw = 1;
1980            cpu->cd.mips.rmw_addr = addr;
1981            cpu->cd.mips.rmw_len = sizeof(word);
1982            if (cpu->cd.mips.cpu_type.exc_model != MMU10K)
1983                    cpu->cd.mips.coproc[0]->reg[COP0_LLADDR] =
1984                        (addr >> 4) & 0xffffffffULL;
1985    
1986            if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
1987                    reg(ic->arg[0]) = word[0] + (word[1] << 8)
1988                        + (word[2] << 16) + ((uint64_t)word[3] << 24) +
1989                        + ((uint64_t)word[4] << 32) + ((uint64_t)word[5] << 40)
1990                        + ((uint64_t)word[6] << 48) + ((uint64_t)word[7] << 56);
1991            else
1992                    reg(ic->arg[0]) = word[7] + (word[6] << 8)
1993                        + (word[5] << 16) + ((uint64_t)word[4] << 24) +
1994                        + ((uint64_t)word[3] << 32) + ((uint64_t)word[2] << 40)
1995                        + ((uint64_t)word[1] << 48) + ((uint64_t)word[0] << 56);
1996    }
1997    X(sc)
1998    {
1999            MODE_int_t addr = reg(ic->arg[1]) + (int32_t)ic->arg[2];
2000            uint64_t r = reg(ic->arg[0]);
2001            int low_pc, i;
2002            uint8_t word[sizeof(uint32_t)];
2003    
2004            /*  Synch. PC and store using slow memory_rw():  */
2005            low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
2006                / sizeof(struct mips_instr_call);
2007            cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
2008                << MIPS_INSTR_ALIGNMENT_SHIFT);
2009            cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
2010    
2011            if (addr & (sizeof(word)-1)) {
2012                    fatal("TODO: sc unaligned access: exception\n");
2013                    exit(1);
2014            }
2015    
2016            if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {
2017                    word[0]=r; word[1]=r>>8; word[2]=r>>16; word[3]=r>>24;
2018            } else {
2019                    word[3]=r; word[2]=r>>8; word[1]=r>>16; word[0]=r>>24;
2020            }
2021    
2022            /*  If rmw is 0, then the store failed.  (This cache-line was written
2023                to by someone else.)  */
2024            if (cpu->cd.mips.rmw == 0 || cpu->cd.mips.rmw_addr != addr
2025                || cpu->cd.mips.rmw_len != sizeof(word)) {
2026                    reg(ic->arg[0]) = 0;
2027                    cpu->cd.mips.rmw = 0;
2028                    return;
2029            }
2030    
2031            if (!cpu->memory_rw(cpu, cpu->mem, addr, word,
2032                sizeof(word), MEM_WRITE, CACHE_DATA)) {
2033                    /*  An exception occurred.  */
2034                    return;
2035            }
2036    
2037            /*  We succeeded. Let's invalidate everybody else's store to this
2038                cache line:  */
2039            for (i=0; i<cpu->machine->ncpus; i++) {
2040                    if (cpu->machine->cpus[i]->cd.mips.rmw) {
2041                            uint64_t yaddr = addr, xaddr = cpu->machine->cpus[i]->
2042                                cd.mips.rmw_addr;
2043                            uint64_t mask = ~(cpu->machine->cpus[i]->
2044                                cd.mips.cache_linesize[CACHE_DATA] - 1);
2045                            xaddr &= mask;
2046                            yaddr &= mask;
2047                            if (xaddr == yaddr)
2048                                    cpu->machine->cpus[i]->cd.mips.rmw = 0;
2049                    }
2050            }
2051    
2052            reg(ic->arg[0]) = 1;
2053            cpu->cd.mips.rmw = 0;
2054    }
2055    X(scd)
2056    {
2057            MODE_int_t addr = reg(ic->arg[1]) + (int32_t)ic->arg[2];
2058            uint64_t r = reg(ic->arg[0]);
2059            int low_pc, i;
2060            uint8_t word[sizeof(uint64_t)];
2061    
2062            /*  Synch. PC and store using slow memory_rw():  */
2063            low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
2064                / sizeof(struct mips_instr_call);
2065            cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
2066                << MIPS_INSTR_ALIGNMENT_SHIFT);
2067            cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
2068    
2069            if (addr & (sizeof(word)-1)) {
2070                    fatal("TODO: sc unaligned access: exception\n");
2071                    exit(1);
2072            }
2073    
2074            if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {
2075                    word[0]=r;     word[1]=r>>8; word[2]=r>>16; word[3]=r>>24;
2076                    word[4]=r>>32; word[5]=r>>40; word[6]=r>>48; word[7]=r>>56;
2077            } else {
2078                    word[7]=r;     word[6]=r>>8; word[5]=r>>16; word[4]=r>>24;
2079                    word[3]=r>>32; word[2]=r>>40; word[1]=r>>48; word[0]=r>>56;
2080            }
2081    
2082            /*  If rmw is 0, then the store failed.  (This cache-line was written
2083                to by someone else.)  */
2084            if (cpu->cd.mips.rmw == 0 || cpu->cd.mips.rmw_addr != addr
2085                || cpu->cd.mips.rmw_len != sizeof(word)) {
2086                    reg(ic->arg[0]) = 0;
2087                    cpu->cd.mips.rmw = 0;
2088                    return;
2089            }
2090    
2091            if (!cpu->memory_rw(cpu, cpu->mem, addr, word,
2092                sizeof(word), MEM_WRITE, CACHE_DATA)) {
2093                    /*  An exception occurred.  */
2094                    return;
2095            }
2096    
2097            /*  We succeeded. Let's invalidate everybody else's store to this
2098                cache line:  */
2099            for (i=0; i<cpu->machine->ncpus; i++) {
2100                    if (cpu->machine->cpus[i]->cd.mips.rmw) {
2101                            uint64_t yaddr = addr, xaddr = cpu->machine->cpus[i]->
2102                                cd.mips.rmw_addr;
2103                            uint64_t mask = ~(cpu->machine->cpus[i]->
2104                                cd.mips.cache_linesize[CACHE_DATA] - 1);
2105                            xaddr &= mask;
2106                            yaddr &= mask;
2107                            if (xaddr == yaddr)
2108                                    cpu->machine->cpus[i]->cd.mips.rmw = 0;
2109                    }
2110            }
2111    
2112            reg(ic->arg[0]) = 1;
2113            cpu->cd.mips.rmw = 0;
2114    }
2115    
2116    
2117    /*
2118     *  lwc1, swc1:  Coprocessor 1 load/store (32-bit)
2119     *  ldc1, sdc1:  Coprocessor 1 load/store (64-bit)
2120     *
2121     *  arg[0] = ptr to coprocessor register
2122     *  arg[1] = ptr to rs (base pointer register)
2123     *  arg[2] = int32_t imm
2124     */
2125    X(lwc1)
2126    {
2127            const int cpnr = 1;
2128    
2129            /*  Synch. PC and call the generic load/store function:  */
2130            int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
2131                / sizeof(struct mips_instr_call);
2132            cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
2133                << MIPS_INSTR_ALIGNMENT_SHIFT);
2134            cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
2135    
2136            /*  ... but first, let's see if the coprocessor is available:  */
2137            if (!(cpu->cd.mips.coproc[0]->
2138                reg[COP0_STATUS] & ((1 << cpnr) << STATUS_CU_SHIFT)) ) {
2139                    mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0, cpnr, 0, 0, 0);
2140                    return;
2141            }
2142    
2143    #ifdef MODE32
2144            mips32_loadstore
2145    #else
2146            mips_loadstore
2147    #endif
2148                [ (cpu->byte_order == EMUL_LITTLE_ENDIAN? 0 : 16) + 2 * 2 + 1]
2149                (cpu, ic);
2150    }
2151    X(swc1)
2152    {
2153            const int cpnr = 1;
2154    
2155            /*  Synch. PC and call the generic load/store function:  */
2156            int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
2157                / sizeof(struct mips_instr_call);
2158            cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
2159                << MIPS_INSTR_ALIGNMENT_SHIFT);
2160            cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
2161    
2162            /*  ... but first, let's see if the coprocessor is available:  */
2163            if (!(cpu->cd.mips.coproc[0]->
2164                reg[COP0_STATUS] & ((1 << cpnr) << STATUS_CU_SHIFT)) ) {
2165                    mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0, cpnr, 0, 0, 0);
2166                    return;
2167            }
2168    
2169    #ifdef MODE32
2170            mips32_loadstore
2171    #else
2172            mips_loadstore
2173    #endif
2174                [ (cpu->byte_order == EMUL_LITTLE_ENDIAN? 0 : 16) + 8 + 2 * 2]
2175                (cpu, ic);
2176    }
2177    X(ldc1)
2178    {
2179            const int cpnr = 1;
2180            int use_fp_pairs =
2181                !(cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & STATUS_FR);
2182            uint64_t fpr, *backup_ptr;
2183    
2184            /*  Synch. PC and call the generic load/store function:  */
2185            int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
2186                / sizeof(struct mips_instr_call);
2187            cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
2188                << MIPS_INSTR_ALIGNMENT_SHIFT);
2189            cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
2190    
2191            /*  ... but first, let's see if the coprocessor is available:  */
2192            if (!(cpu->cd.mips.coproc[0]->
2193                reg[COP0_STATUS] & ((1 << cpnr) << STATUS_CU_SHIFT)) ) {
2194                    mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0, cpnr, 0, 0, 0);
2195                    return;
2196            }
2197    
2198            backup_ptr = (uint64_t *) ic->arg[0];
2199            ic->arg[0] = (size_t) &fpr;
2200    
2201    #ifdef MODE32
2202            mips32_loadstore
2203    #else
2204            mips_loadstore
2205    #endif
2206                [ (cpu->byte_order == EMUL_LITTLE_ENDIAN? 0 : 16) + 3 * 2 + 1]
2207                (cpu, ic);
2208    
2209            if (use_fp_pairs) {
2210                    backup_ptr[0] = (int64_t)(int32_t) fpr;
2211                    backup_ptr[1] = (int64_t)(int32_t) (fpr >> 32);
2212            } else {
2213                    *backup_ptr = fpr;
2214            }
2215    
2216            ic->arg[0] = (size_t) backup_ptr;
2217    }
2218    X(sdc1)
2219    {
2220            const int cpnr = 1;
2221            int use_fp_pairs =
2222                !(cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & STATUS_FR);
2223            uint64_t fpr, *backup_ptr;
2224    
2225            /*  Synch. PC and call the generic load/store function:  */
2226            int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
2227                / sizeof(struct mips_instr_call);
2228            cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
2229                << MIPS_INSTR_ALIGNMENT_SHIFT);
2230            cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
2231    
2232            /*  ... but first, let's see if the coprocessor is available:  */
2233            if (!(cpu->cd.mips.coproc[0]->
2234                reg[COP0_STATUS] & ((1 << cpnr) << STATUS_CU_SHIFT)) ) {
2235                    mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0, cpnr, 0, 0, 0);
2236                    return;
2237            }
2238    
2239            backup_ptr = (uint64_t *) ic->arg[0];
2240            ic->arg[0] = (size_t) &fpr;
2241    
2242            if (use_fp_pairs) {
2243                    uint32_t lo = backup_ptr[0];
2244                    uint32_t hi = backup_ptr[1];
2245                    fpr = (((uint64_t)hi) << 32) | lo;
2246            } else {
2247                    fpr = *backup_ptr;
2248            }
2249    
2250    #ifdef MODE32
2251            mips32_loadstore
2252    #else
2253            mips_loadstore
2254    #endif
2255                [ (cpu->byte_order == EMUL_LITTLE_ENDIAN? 0 : 16) + 8 + 3 * 2]
2256                (cpu, ic);
2257    
2258            ic->arg[0] = (size_t) backup_ptr;
2259    }
2260    
2261    
2262    /*
2263     *  Unaligned loads/stores:
2264     *
2265     *  arg[0] = ptr to rt
2266     *  arg[1] = ptr to rs
2267     *  arg[2] = int32_t imm
2268     */
2269    X(lwl) { mips_unaligned_loadstore(cpu, ic, 1, sizeof(uint32_t), 0); }
2270    X(lwr) { mips_unaligned_loadstore(cpu, ic, 0, sizeof(uint32_t), 0); }
2271    X(ldl) { mips_unaligned_loadstore(cpu, ic, 1, sizeof(uint64_t), 0); }
2272    X(ldr) { mips_unaligned_loadstore(cpu, ic, 0, sizeof(uint64_t), 0); }
2273    X(swl) { mips_unaligned_loadstore(cpu, ic, 1, sizeof(uint32_t), 1); }
2274    X(swr) { mips_unaligned_loadstore(cpu, ic, 0, sizeof(uint32_t), 1); }
2275    X(sdl) { mips_unaligned_loadstore(cpu, ic, 1, sizeof(uint64_t), 1); }
2276    X(sdr) { mips_unaligned_loadstore(cpu, ic, 0, sizeof(uint64_t), 1); }
2277    
2278    
2279    /*
2280     *  di, ei: R5900 interrupt enable/disable.
2281     *
2282     *  TODO: check the R5900_STATUS_EDI bit in the status register. If it is
2283     *  cleared, and we are not running in kernel mode, then both the EI and DI
2284     *  instructions should be treated as NOPs!
2285     */
2286    X(di_r5900)
2287    {
2288            cpu->cd.mips.coproc[0]->reg[COP0_STATUS] &= ~R5900_STATUS_EIE;
2289    }
2290    X(ei_r5900)
2291    {
2292            cpu->cd.mips.coproc[0]->reg[COP0_STATUS] |= R5900_STATUS_EIE;
2293  }  }
2294    
2295    
# Line 465  X(cfc1) Line 2303  X(cfc1)
2303   */   */
2304  X(b_samepage_addiu)  X(b_samepage_addiu)
2305  {  {
2306          reg(ic[1].arg[1]) = reg(ic[1].arg[0]) + (int32_t)ic[1].arg[2];          reg(ic[1].arg[1]) = (int32_t)
2307                ( (int32_t)reg(ic[1].arg[0]) + (int32_t)ic[1].arg[2] );
2308            cpu->n_translated_instrs ++;
2309            cpu->cd.mips.next_ic = (struct mips_instr_call *) ic->arg[2];
2310    }
2311    
2312    
2313    /*
2314     *  b_samepage_daddiu:
2315     *
2316     *  Combination of branch within the same page, followed by daddiu.
2317     */
2318    X(b_samepage_daddiu)
2319    {
2320            *(uint64_t *)ic[1].arg[1] = *(uint64_t *)ic[1].arg[0] +
2321                (int32_t)ic[1].arg[2];
2322          cpu->n_translated_instrs ++;          cpu->n_translated_instrs ++;
2323          cpu->cd.mips.next_ic = (struct mips_instr_call *) ic->arg[2];          cpu->cd.mips.next_ic = (struct mips_instr_call *) ic->arg[2];
2324  }  }
# Line 476  X(b_samepage_addiu) Line 2329  X(b_samepage_addiu)
2329    
2330  X(end_of_page)  X(end_of_page)
2331  {  {
         struct mips_instr_call self;  
   
2332          /*  Update the PC:  (offset 0, but on the next page)  */          /*  Update the PC:  (offset 0, but on the next page)  */
2333          cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<          cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
2334              MIPS_INSTR_ALIGNMENT_SHIFT);              MIPS_INSTR_ALIGNMENT_SHIFT);
2335          cpu->pc += (MIPS_IC_ENTRIES_PER_PAGE << MIPS_INSTR_ALIGNMENT_SHIFT);          cpu->pc += (MIPS_IC_ENTRIES_PER_PAGE << MIPS_INSTR_ALIGNMENT_SHIFT);
2336    
2337          /*  Simple jump to the next page (if we are lucky):  */          /*  end_of_page doesn't count as an executed instruction:  */
2338          if (cpu->cd.mips.delay_slot == NOT_DELAYED) {          cpu->n_translated_instrs --;
2339    
2340                  /*  Find the new physpage and update translation pointers:  */          /*
2341                  quick_pc_to_pointers(cpu);           *  Find the new physpage and update translation pointers.
2342             *
2343             *  Note: This may cause an exception, if e.g. the new page is
2344             *  not accessible.
2345             */
2346            quick_pc_to_pointers(cpu);
2347    
2348                  /*  end_of_page doesn't count as an executed instruction:  */          /*  Simple jump to the next page (if we are lucky):  */
2349                  cpu->n_translated_instrs --;          if (cpu->delay_slot == NOT_DELAYED)
2350                    return;
2351    
2352            /*
2353             *  If we were in a delay slot, and we got an exception while doing
2354             *  quick_pc_to_pointers, then return. The function which called
2355             *  end_of_page should handle this case.
2356             */
2357            if (cpu->delay_slot == EXCEPTION_IN_DELAY_SLOT)
2358                  return;                  return;
         }  
2359    
2360          /*  Tricky situation; the delay slot is on the next virtual page:  */          /*
2361             *  Tricky situation; the delay slot is on the next virtual page.
2362             *  Calling to_be_translated will translate one instruction manually,
2363             *  execute it, and then discard it.
2364             */
2365          /*  fatal("[ end_of_page: delay slot across page boundary! ]\n");  */          /*  fatal("[ end_of_page: delay slot across page boundary! ]\n");  */
2366    
2367          /*  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);  
2368    
2369          /*  The instruction in the delay slot has now executed.  */          /*  The instruction in the delay slot has now executed.  */
2370            /*  fatal("[ end_of_page: back from executing the delay slot, %i ]\n",
2371                cpu->delay_slot);  */
2372    
2373          /*  Find the physpage etc of the instruction in the delay slot          /*  Find the physpage etc of the instruction in the delay slot
2374              (or, if there was an exception, the exception handler):  */              (or, if there was an exception, the exception handler):  */
2375          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");  */  
2376  }  }
2377    
2378    
2379  X(end_of_page2)  X(end_of_page2)
2380  {  {
2381  fatal("this should be removed: end of page2\n");          /*  Synchronize PC on the _second_ instruction on the next page:  */
2382  exit(1);          int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
2383                / sizeof(struct mips_instr_call);
2384          /*  Update the PC:  (offset 4, but on the next page)  */          cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
2385          cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<              << MIPS_INSTR_ALIGNMENT_SHIFT);
2386              MIPS_INSTR_ALIGNMENT_SHIFT);          cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
         cpu->pc += ((MIPS_IC_ENTRIES_PER_PAGE+1) << MIPS_INSTR_ALIGNMENT_SHIFT);  
2387    
2388          if (cpu->cd.mips.delay_slot == NOT_DELAYED) {          /*  This doesn't count as an executed instruction.  */
2389                  /*  Find the new physpage and update translation pointers:  */          cpu->n_translated_instrs --;
                 quick_pc_to_pointers(cpu);  
2390    
2391                  /*  end_of_page doesn't count as an executed instruction:  */          quick_pc_to_pointers(cpu);
                 cpu->n_translated_instrs --;  
2392    
2393            if (cpu->delay_slot == NOT_DELAYED)
2394                  return;                  return;
         }  
2395    
2396          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");
2397          exit(1);          exit(1);
2398  }  }
2399    
# Line 565  void COMBINE(b_addiu)(struct cpu *cpu, s Line 2422  void COMBINE(b_addiu)(struct cpu *cpu, s
2422  }  }
2423    
2424    
2425    /*
2426     *  Combine: [Conditional] branch, followed by daddiu.
2427     */
2428    void COMBINE(b_daddiu)(struct cpu *cpu, struct mips_instr_call *ic,
2429            int low_addr)
2430    {
2431            int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
2432                & (MIPS_IC_ENTRIES_PER_PAGE - 1);
2433    
2434            if (n_back < 1)
2435                    return;
2436    
2437            if (ic[-1].f == instr(b_samepage)) {
2438                    ic[-1].f = instr(b_samepage_daddiu);
2439                    combined;
2440            }
2441    
2442            /*  TODO: other branches that are followed by daddiu should be here  */
2443    }
2444    
2445    
2446  /*****************************************************************************/  /*****************************************************************************/
2447    
2448    
2449  /*  /*
2450   *  mips_instr_to_be_translated():   *  mips_instr_to_be_translated():
2451   *   *
2452   *  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
2453   *  valid data for the translated instruction, or a "nothing" instruction if   *  valid data for the translated instruction, or a "nothing" instruction if
2454   *  there was a translation failure. The newly translated instruction is then   *  there was a translation failure. The newly translated instruction is then
2455   *  executed.   *  executed.
# Line 582  X(to_be_translated) Line 2460  X(to_be_translated)
2460          uint32_t iword, imm;          uint32_t iword, imm;
2461          unsigned char *page;          unsigned char *page;
2462          unsigned char ib[4];          unsigned char ib[4];
 #ifdef DYNTRANS_BACKEND  
         int simple = 0;  
 #endif  
2463          int main_opcode, rt, rs, rd, sa, s6, x64 = 0;          int main_opcode, rt, rs, rd, sa, s6, x64 = 0;
2464          int in_crosspage_delayslot = 0;          int in_crosspage_delayslot = 0;
         int delay_slot_danger = 1;  
2465          void (*samepage_function)(struct cpu *, struct mips_instr_call *);          void (*samepage_function)(struct cpu *, struct mips_instr_call *);
2466            int store, signedness, size;
2467    
2468          /*  Figure out the (virtual) address of the instruction:  */          /*  Figure out the (virtual) address of the instruction:  */
2469          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)
2470              / sizeof(struct mips_instr_call);              / sizeof(struct mips_instr_call);
2471    
2472          /*  Special case for branch with delayslot on the next page:  */          /*  Special case for branch with delayslot on the next page:  */
2473          if (low_pc >= MIPS_IC_ENTRIES_PER_PAGE) {          if (cpu->delay_slot == TO_BE_DELAYED && low_pc == 0) {
2474                  /*  fatal("[ TEMPORARY delay-slot translation ]\n");  */                  /*  fatal("[ delay-slot translation across page "
2475                  low_pc = 0;                      "boundary ]\n");  */
2476                  in_crosspage_delayslot = 1;                  in_crosspage_delayslot = 1;
2477          }          }
2478    
2479          addr = cpu->pc & ~((MIPS_IC_ENTRIES_PER_PAGE-1)          addr = cpu->pc & ~((MIPS_IC_ENTRIES_PER_PAGE-1)
2480              << MIPS_INSTR_ALIGNMENT_SHIFT);              << MIPS_INSTR_ALIGNMENT_SHIFT);
2481          addr += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);          addr += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
2482          cpu->pc = addr;          cpu->pc = (MODE_int_t)addr;
2483          addr &= ~((1 << MIPS_INSTR_ALIGNMENT_SHIFT) - 1);          addr &= ~((1 << MIPS_INSTR_ALIGNMENT_SHIFT) - 1);
2484    
2485          /*  Read the instruction word from memory:  */          /*  Read the instruction word from memory:  */
2486    #ifdef MODE32
2487          page = cpu->cd.mips.host_load[(uint32_t)addr >> 12];          page = cpu->cd.mips.host_load[(uint32_t)addr >> 12];
2488    #else
2489            {
2490                    const uint32_t mask1 = (1 << DYNTRANS_L1N) - 1;
2491                    const uint32_t mask2 = (1 << DYNTRANS_L2N) - 1;
2492                    const uint32_t mask3 = (1 << DYNTRANS_L3N) - 1;
2493                    uint32_t x1 = (addr >> (64-DYNTRANS_L1N)) & mask1;
2494                    uint32_t x2 = (addr >> (64-DYNTRANS_L1N-DYNTRANS_L2N)) & mask2;
2495                    uint32_t x3 = (addr >> (64-DYNTRANS_L1N-DYNTRANS_L2N-
2496                        DYNTRANS_L3N)) & mask3;
2497                    struct DYNTRANS_L2_64_TABLE *l2 = cpu->cd.mips.l1_64[x1];
2498                    struct DYNTRANS_L3_64_TABLE *l3 = l2->l3[x2];
2499                    page = l3->host_load[x3];
2500            }
2501    #endif
2502    
2503          if (page != NULL) {          if (page != NULL) {
2504                  /*  fatal("TRANSLATION HIT!\n");  */                  /*  fatal("TRANSLATION HIT!\n");  */
2505                  memcpy(ib, page + (addr & 0xfff), sizeof(ib));                  memcpy(ib, page + (addr & 0xffc), sizeof(ib));
2506          } else {          } else {
2507                  /*  fatal("TRANSLATION MISS!\n");  */                  /*  fatal("TRANSLATION MISS!\n");  */
2508                  if (!cpu->memory_rw(cpu, cpu->mem, addr, ib,                  if (!cpu->memory_rw(cpu, cpu->mem, addr, ib,
2509                      sizeof(ib), MEM_READ, CACHE_INSTRUCTION)) {                      sizeof(ib), MEM_READ, CACHE_INSTRUCTION)) {
2510                          fatal("to_be_translated(): "                          fatal("to_be_translated(): read failed: TODO\n");
                             "read failed: TODO\n");  
2511                          goto bad;                          goto bad;
2512                  }                  }
2513          }          }
# Line 630  X(to_be_translated) Line 2519  X(to_be_translated)
2519          else          else
2520                  iword = BE32_TO_HOST(iword);                  iword = BE32_TO_HOST(iword);
2521    
         /*  Is the instruction in the delay slot known to be safe?  */  
         if ((addr & 0xffc) < 0xffc) {  
                 /*  TODO: check the instruction  */  
                 delay_slot_danger = 0;  
         }  
   
2522    
2523  #define DYNTRANS_TO_BE_TRANSLATED_HEAD  #define DYNTRANS_TO_BE_TRANSLATED_HEAD
2524  #include "cpu_dyntrans.c"  #include "cpu_dyntrans.c"
# Line 645  X(to_be_translated) Line 2528  X(to_be_translated)
2528          /*          /*
2529           *  Translate the instruction:           *  Translate the instruction:
2530           *           *
2531           *  NOTE: _NEVER_ allow writes to the zero register; all such           *  NOTE: _NEVER_ allow writes to the zero register; all instructions
2532           *  instructions should be made into NOPs.           *  that use the zero register as their destination should be treated
2533             *  as NOPs, except those that access memory (they should use the
2534             *  scratch register instead).
2535           */           */
2536    
2537          main_opcode = iword >> 26;          main_opcode = iword >> 26;
# Line 663  X(to_be_translated) Line 2548  X(to_be_translated)
2548                  switch (s6) {                  switch (s6) {
2549    
2550                  case SPECIAL_SLL:                  case SPECIAL_SLL:
2551                    case SPECIAL_SLLV:
2552                  case SPECIAL_SRL:                  case SPECIAL_SRL:
2553                    case SPECIAL_SRLV:
2554                  case SPECIAL_SRA:                  case SPECIAL_SRA:
2555                    case SPECIAL_SRAV:
2556                    case SPECIAL_DSRL:
2557                    case SPECIAL_DSRLV:
2558                    case SPECIAL_DSRL32:
2559                    case SPECIAL_DSLL:
2560                    case SPECIAL_DSLLV:
2561                    case SPECIAL_DSLL32:
2562                    case SPECIAL_DSRA:
2563                    case SPECIAL_DSRAV:
2564                    case SPECIAL_DSRA32:
2565                          switch (s6) {                          switch (s6) {
2566                          case SPECIAL_SLL:  ic->f = instr(sll); break;                          case SPECIAL_SLL:  ic->f = instr(sll); break;
2567                            case SPECIAL_SLLV: ic->f = instr(sllv); sa = -1; break;
2568                          case SPECIAL_SRL:  ic->f = instr(srl); break;                          case SPECIAL_SRL:  ic->f = instr(srl); break;
2569                            case SPECIAL_SRLV: ic->f = instr(srlv); sa = -1; break;
2570                          case SPECIAL_SRA:  ic->f = instr(sra); break;                          case SPECIAL_SRA:  ic->f = instr(sra); break;
2571                            case SPECIAL_SRAV: ic->f = instr(srav); sa = -1; break;
2572                            case SPECIAL_DSRL: ic->f = instr(dsrl); x64=1; break;
2573                            case SPECIAL_DSRLV:ic->f = instr(dsrlv);
2574                                               x64 = 1; sa = -1; break;
2575                            case SPECIAL_DSRL32:ic->f= instr(dsrl); x64=1;
2576                                               sa += 32; break;
2577                            case SPECIAL_DSLL: ic->f = instr(dsll); x64=1; break;
2578                            case SPECIAL_DSLLV:ic->f = instr(dsllv);
2579                                               x64 = 1; sa = -1; break;
2580                            case SPECIAL_DSLL32:ic->f= instr(dsll); x64=1;
2581                                               sa += 32; break;
2582                            case SPECIAL_DSRA: ic->f = instr(dsra); x64=1; break;
2583                            case SPECIAL_DSRAV:ic->f = instr(dsrav);
2584                                               x64 = 1; sa = -1; break;
2585                            case SPECIAL_DSRA32:ic->f = instr(dsra); x64=1;
2586                                               sa += 32; break;
2587                          }                          }
2588                          ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];                          ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
2589                          ic->arg[1] = sa;                          if (sa >= 0)
2590                                    ic->arg[1] = sa;
2591                            else
2592                                    ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rs];
2593                          ic->arg[2] = (size_t)&cpu->cd.mips.gpr[rd];                          ic->arg[2] = (size_t)&cpu->cd.mips.gpr[rd];
2594                          if (rd == MIPS_GPR_ZERO)                          if (rd == MIPS_GPR_ZERO)
2595                                  ic->f = instr(nop);                                  ic->f = instr(nop);
2596                          break;                          break;
2597    
2598                    case SPECIAL_ADD:
2599                  case SPECIAL_ADDU:                  case SPECIAL_ADDU:
2600                    case SPECIAL_SUB:
2601                  case SPECIAL_SUBU:                  case SPECIAL_SUBU:
2602                    case SPECIAL_DADD:
2603                  case SPECIAL_DADDU:                  case SPECIAL_DADDU:
2604                    case SPECIAL_DSUB:
2605                  case SPECIAL_DSUBU:                  case SPECIAL_DSUBU:
2606                  case SPECIAL_SLT:                  case SPECIAL_SLT:
2607                  case SPECIAL_SLTU:                  case SPECIAL_SLTU:
2608                    case SPECIAL_AND:
2609                  case SPECIAL_OR:                  case SPECIAL_OR:
2610                  case SPECIAL_XOR:                  case SPECIAL_XOR:
2611                  case SPECIAL_NOR:                  case SPECIAL_NOR:
2612                    case SPECIAL_MOVN:
2613                    case SPECIAL_MOVZ:
2614                  case SPECIAL_MFHI:                  case SPECIAL_MFHI:
2615                  case SPECIAL_MFLO:                  case SPECIAL_MFLO:
2616                  case SPECIAL_MTHI:                  case SPECIAL_MTHI:
2617                  case SPECIAL_MTLO:                  case SPECIAL_MTLO:
2618                    case SPECIAL_DIV:
2619                    case SPECIAL_DIVU:
2620                    case SPECIAL_DDIV:
2621                    case SPECIAL_DDIVU:
2622                    case SPECIAL_MULT:
2623                    case SPECIAL_MULTU:
2624                    case SPECIAL_DMULT:
2625                    case SPECIAL_DMULTU:
2626                    case SPECIAL_TGE:
2627                    case SPECIAL_TGEU:
2628                    case SPECIAL_TLT:
2629                    case SPECIAL_TLTU:
2630                    case SPECIAL_TEQ:
2631                    case SPECIAL_TNE:
2632                          switch (s6) {                          switch (s6) {
2633                            case SPECIAL_ADD:   ic->f = instr(add); break;
2634                          case SPECIAL_ADDU:  ic->f = instr(addu); break;                          case SPECIAL_ADDU:  ic->f = instr(addu); break;
2635                            case SPECIAL_SUB:   ic->f = instr(sub); break;
2636                          case SPECIAL_SUBU:  ic->f = instr(subu); break;                          case SPECIAL_SUBU:  ic->f = instr(subu); break;
2637                            case SPECIAL_DADD:  ic->f = instr(dadd); x64=1; break;
2638                          case SPECIAL_DADDU: ic->f = instr(daddu); x64=1; break;                          case SPECIAL_DADDU: ic->f = instr(daddu); x64=1; break;
2639                            case SPECIAL_DSUB:  ic->f = instr(dsub); x64=1; break;
2640                          case SPECIAL_DSUBU: ic->f = instr(dsubu); x64=1; break;                          case SPECIAL_DSUBU: ic->f = instr(dsubu); x64=1; break;
2641                          case SPECIAL_SLT:   ic->f = instr(slt); break;                          case SPECIAL_SLT:   ic->f = instr(slt); break;
2642                          case SPECIAL_SLTU:  ic->f = instr(sltu); break;                          case SPECIAL_SLTU:  ic->f = instr(sltu); break;
2643                            case SPECIAL_AND:   ic->f = instr(and); break;
2644                          case SPECIAL_OR:    ic->f = instr(or); break;                          case SPECIAL_OR:    ic->f = instr(or); break;
2645                          case SPECIAL_XOR:   ic->f = instr(xor); break;                          case SPECIAL_XOR:   ic->f = instr(xor); break;
2646                          case SPECIAL_NOR:   ic->f = instr(nor); break;                          case SPECIAL_NOR:   ic->f = instr(nor); break;
# Line 704  X(to_be_translated) Line 2648  X(to_be_translated)
2648                          case SPECIAL_MFLO:  ic->f = instr(mov); break;                          case SPECIAL_MFLO:  ic->f = instr(mov); break;
2649                          case SPECIAL_MTHI:  ic->f = instr(mov); break;                          case SPECIAL_MTHI:  ic->f = instr(mov); break;
2650                          case SPECIAL_MTLO:  ic->f = instr(mov); break;                          case SPECIAL_MTLO:  ic->f = instr(mov); break;
2651                            case SPECIAL_DIV:   ic->f = instr(div); break;
2652                            case SPECIAL_DIVU:  ic->f = instr(divu); break;
2653                            case SPECIAL_DDIV:  ic->f = instr(ddiv); x64=1; break;
2654                            case SPECIAL_DDIVU: ic->f = instr(ddivu); x64=1; break;
2655                            case SPECIAL_MULT : ic->f = instr(mult); break;
2656                            case SPECIAL_MULTU: ic->f = instr(multu); break;
2657                            case SPECIAL_DMULT: ic->f = instr(dmult); x64=1; break;
2658                            case SPECIAL_DMULTU:ic->f = instr(dmultu); x64=1; break;
2659                            case SPECIAL_TGE:   ic->f = instr(tge); break;
2660                            case SPECIAL_TGEU:  ic->f = instr(tgeu); break;
2661                            case SPECIAL_TLT:   ic->f = instr(tlt); break;
2662                            case SPECIAL_TLTU:  ic->f = instr(tltu); break;
2663                            case SPECIAL_TEQ:   ic->f = instr(teq); break;
2664                            case SPECIAL_TNE:   ic->f = instr(tne); break;
2665                            case SPECIAL_MOVN:  ic->f = instr(movn); break;
2666                            case SPECIAL_MOVZ:  ic->f = instr(movz); break;
2667                          }                          }
2668                          ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];                          ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];
2669                          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 2682  X(to_be_translated)
2682                                  ic->arg[2] = (size_t)&cpu->cd.mips.lo;                                  ic->arg[2] = (size_t)&cpu->cd.mips.lo;
2683                                  break;                                  break;
2684                          }                          }
2685                          /*  rd==0 => nop:  */                          /*  Special cases for rd:  */
2686                          switch (s6) {                          switch (s6) {
2687                          case SPECIAL_MTHI:                          case SPECIAL_MTHI:
2688                          case SPECIAL_MTLO:                          case SPECIAL_MTLO:
2689                                  /*  These instructions don't use rd.  */                          case SPECIAL_DIV:
2690                                  break;                          case SPECIAL_DIVU:
2691                          default:if (rd == MIPS_GPR_ZERO)                          case SPECIAL_DDIV:
2692                                          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) {  
2693                          case SPECIAL_MULT:                          case SPECIAL_MULT:
2694                          case SPECIAL_MULTU:                          case SPECIAL_MULTU:
2695                          case SPECIAL_DMULT:                          case SPECIAL_DMULT:
2696                          case SPECIAL_DMULTU:                          case SPECIAL_DMULTU:
2697                                  ic->arg[2] = (size_t)&cpu->cd.mips.gpr[rd];                          case SPECIAL_TGE:
2698                            case SPECIAL_TGEU:
2699                            case SPECIAL_TLT:
2700                            case SPECIAL_TLTU:
2701                            case SPECIAL_TEQ:
2702                            case SPECIAL_TNE:
2703                                    if (s6 == SPECIAL_MULT && rd != MIPS_GPR_ZERO) {
2704                                            if (cpu->cd.mips.cpu_type.rev ==
2705                                                MIPS_R5900) {
2706                                                    ic->f = instr(mult_r5900);
2707                                                    break;
2708                                            }
2709                                            break;
2710                                    }
2711                                    if (s6 == SPECIAL_MULTU && rd!=MIPS_GPR_ZERO) {
2712                                            if (cpu->cd.mips.cpu_type.rev ==
2713                                                MIPS_R5900) {
2714                                                    ic->f = instr(multu_r5900);
2715                                                    break;
2716                                            }
2717                                    }
2718                                  if (rd != MIPS_GPR_ZERO) {                                  if (rd != MIPS_GPR_ZERO) {
2719                                          fatal("TODO: mult with rd NON-zero\n");                                          fatal("TODO: rd NON-zero\n");
2720                                          goto bad;                                          goto bad;
2721                                  }                                  }
2722                                    /*  These instructions don't use rd.  */
2723                                  break;                                  break;
2724                            default:if (rd == MIPS_GPR_ZERO)
2725                                            ic->f = instr(nop);
2726                          }                          }
2727                          break;                          break;
2728    
# Line 761  X(to_be_translated) Line 2730  X(to_be_translated)
2730                  case SPECIAL_JALR:                  case SPECIAL_JALR:
2731                          ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];                          ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];
2732                          ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rd];                          ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rd];
2733                          if (main_opcode == SPECIAL_JALR && rd == MIPS_GPR_ZERO)                          if (s6 == SPECIAL_JALR && rd == MIPS_GPR_ZERO)
2734                                  main_opcode = SPECIAL_JR;                                  s6 = SPECIAL_JR;
2735                          ic->arg[2] = (addr & 0xffc) + 4;                          ic->arg[2] = (addr & 0xffc) + 8;
2736                          switch (main_opcode) {                          switch (s6) {
2737                          case SPECIAL_JR:                          case SPECIAL_JR:
2738                                  if (rs == MIPS_GPR_RA) {                                  if (rs == MIPS_GPR_RA) {
2739                                          if (cpu->machine->show_trace_tree)                                          if (cpu->machine->show_trace_tree)
# Line 782  X(to_be_translated) Line 2751  X(to_be_translated)
2751                                          ic->f = instr(jalr);                                          ic->f = instr(jalr);
2752                                  break;                                  break;
2753                          }                          }
2754                          if (in_crosspage_delayslot) {                          if (cpu->delay_slot) {
2755                                  fatal("[ WARNING: branch in delay slot? ]\n");                                  fatal("TODO: branch in delay slot? (1)\n");
2756                                  ic->f = instr(nop);                                  goto bad;
2757                          }                          }
2758                          break;                          break;
2759    
2760                    case SPECIAL_SYSCALL:
2761                            if (((iword >> 6) & 0xfffff) == 0x30378) {
2762                                    /*  "Magic trap" for PROM emulation:  */
2763                                    ic->f = instr(promemul);
2764                            } else {
2765                                    ic->f = instr(syscall);
2766                            }
2767                            break;
2768    
2769                    case SPECIAL_BREAK:
2770                            ic->f = instr(break);
2771                            break;
2772    
2773                  case SPECIAL_SYNC:                  case SPECIAL_SYNC:
2774                          ic->f = instr(nop);                          ic->f = instr(nop);
2775                          break;                          break;
# Line 798  X(to_be_translated) Line 2780  X(to_be_translated)
2780    
2781          case HI6_BEQ:          case HI6_BEQ:
2782          case HI6_BNE:          case HI6_BNE:
2783            case HI6_BEQL:
2784            case HI6_BNEL:
2785            case HI6_BLEZ:
2786            case HI6_BLEZL:
2787            case HI6_BGTZ:
2788            case HI6_BGTZL:
2789                  samepage_function = NULL;  /*  get rid of a compiler warning  */                  samepage_function = NULL;  /*  get rid of a compiler warning  */
2790                  switch (main_opcode) {                  switch (main_opcode) {
2791                  case HI6_BEQ:                  case HI6_BEQ:
# Line 812  X(to_be_translated) Line 2800  X(to_be_translated)
2800                  case HI6_BNE:                  case HI6_BNE:
2801                          ic->f = instr(bne);                          ic->f = instr(bne);
2802                          samepage_function = instr(bne_samepage);                          samepage_function = instr(bne_samepage);
2803                            break;
2804                    case HI6_BEQL:
2805                            ic->f = instr(beql);
2806                            samepage_function = instr(beql_samepage);
2807                            /*  Special case: comparing a register with itself:  */
2808                            if (rs == rt) {
2809                                    ic->f = instr(b);
2810                                    samepage_function = instr(b_samepage);
2811                            }
2812                            break;
2813                    case HI6_BNEL:
2814                            ic->f = instr(bnel);
2815                            samepage_function = instr(bnel_samepage);
2816                            break;
2817                    case HI6_BLEZ:
2818                            ic->f = instr(blez);
2819                            samepage_function = instr(blez_samepage);
2820                            break;
2821                    case HI6_BLEZL:
2822                            ic->f = instr(blezl);
2823                            samepage_function = instr(blezl_samepage);
2824                            break;
2825                    case HI6_BGTZ:
2826                            ic->f = instr(bgtz);
2827                            samepage_function = instr(bgtz_samepage);
2828                            break;
2829                    case HI6_BGTZL:
2830                            ic->f = instr(bgtzl);
2831                            samepage_function = instr(bgtzl_samepage);
2832                            break;
2833                  }                  }
2834                  ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];                  ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];
2835                  ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rt];                  ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rt];
2836                  ic->arg[2] = (imm << MIPS_INSTR_ALIGNMENT_SHIFT)                  ic->arg[2] = (int32_t) ( (imm << MIPS_INSTR_ALIGNMENT_SHIFT)
2837                      + (addr & 0xffc) + 4;                      + (addr & 0xffc) + 4 );
2838                  /*  Is the offset from the start of the current page still                  /*  Is the offset from the start of the current page still
2839                      within the same page? Then use the samepage_function:  */                      within the same page? Then use the samepage_function:  */
2840                  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 2844  X(to_be_translated)
2844                              & (MIPS_IC_ENTRIES_PER_PAGE - 1)));                              & (MIPS_IC_ENTRIES_PER_PAGE - 1)));
2845                          ic->f = samepage_function;                          ic->f = samepage_function;
2846                  }                  }
2847                  if (in_crosspage_delayslot) {                  if (cpu->delay_slot) {
2848                          fatal("[ WARNING: branch in delay slot? ]\n");                          fatal("TODO: branch in delay slot? (2)\n");
2849                          ic->f = instr(nop);                          goto bad;
2850                  }                  }
2851                  break;                  break;
2852    
2853            case HI6_ADDI:
2854          case HI6_ADDIU:          case HI6_ADDIU:
2855            case HI6_SLTI:
2856            case HI6_SLTIU:
2857            case HI6_DADDI:
2858          case HI6_DADDIU:          case HI6_DADDIU:
2859          case HI6_ANDI:          case HI6_ANDI:
2860          case HI6_ORI:          case HI6_ORI:
# Line 841  X(to_be_translated) Line 2863  X(to_be_translated)
2863                  ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rt];                  ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rt];
2864                  if (main_opcode == HI6_ADDI ||                  if (main_opcode == HI6_ADDI ||
2865                      main_opcode == HI6_ADDIU ||                      main_opcode == HI6_ADDIU ||
2866                        main_opcode == HI6_SLTI ||
2867                        main_opcode == HI6_SLTIU ||
2868                      main_opcode == HI6_DADDI ||                      main_opcode == HI6_DADDI ||
2869                      main_opcode == HI6_DADDIU)                      main_opcode == HI6_DADDIU)
2870                          ic->arg[2] = (int16_t)iword;                          ic->arg[2] = (int16_t)iword;
2871                  else                  else
2872                          ic->arg[2] = (uint16_t)iword;                          ic->arg[2] = (uint16_t)iword;
2873    
2874                  switch (main_opcode) {                  switch (main_opcode) {
2875                    case HI6_ADDI:    ic->f = instr(addi); break;
2876                  case HI6_ADDIU:   ic->f = instr(addiu); break;                  case HI6_ADDIU:   ic->f = instr(addiu); break;
2877                    case HI6_SLTI:    ic->f = instr(slti); break;
2878                    case HI6_SLTIU:   ic->f = instr(sltiu); break;
2879                    case HI6_DADDI:   ic->f = instr(daddi); x64 = 1; break;
2880                  case HI6_DADDIU:  ic->f = instr(daddiu); x64 = 1; break;                  case HI6_DADDIU:  ic->f = instr(daddiu); x64 = 1; break;
2881                  case HI6_ANDI:    ic->f = instr(andi); break;                  case HI6_ANDI:    ic->f = instr(andi); break;
2882                  case HI6_ORI:     ic->f = instr(ori); break;                  case HI6_ORI:     ic->f = instr(ori); break;
2883                  case HI6_XORI:    ic->f = instr(xori); break;                  case HI6_XORI:    ic->f = instr(xori); break;
2884                  }                  }
2885    
2886                  if (rt == MIPS_GPR_ZERO)                  if (rt == MIPS_GPR_ZERO)
2887                          ic->f = instr(nop);                          ic->f = instr(nop);
2888    
2889                  if (ic->f == instr(addiu))                  if (ic->f == instr(addiu))
2890                          cpu->cd.mips.combination_check = COMBINE(b_addiu);                          cpu->cd.mips.combination_check = COMBINE(b_addiu);
2891                    if (ic->f == instr(daddiu))
2892                            cpu->cd.mips.combination_check = COMBINE(b_daddiu);
2893                  break;                  break;
2894    
2895          case HI6_LUI:          case HI6_LUI:
2896                  ic->f = instr(set);                  ic->f = instr(set);
2897                  ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];                  ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
2898                  ic->arg[1] = imm << 16;                  ic->arg[1] = (int32_t) (imm << 16);
2899                  if (rt == MIPS_GPR_ZERO)                  if (rt == MIPS_GPR_ZERO)
2900                          ic->f = instr(nop);                          ic->f = instr(nop);
2901                  break;                  break;
2902    
2903            case HI6_J:
2904            case HI6_JAL:
2905                    switch (main_opcode) {
2906                    case HI6_J:
2907                            ic->f = instr(j);
2908                            break;
2909                    case HI6_JAL:
2910                            if (cpu->machine->show_trace_tree)
2911                                    ic->f = instr(jal_trace);
2912                            else
2913                                    ic->f = instr(jal);
2914                            break;
2915                    }
2916                    ic->arg[0] = (iword & 0x03ffffff) << 2;
2917                    ic->arg[1] = (addr & 0xffc) + 8;
2918                    if (cpu->delay_slot) {
2919                            fatal("TODO: branch in delay slot (=%i)? (3); addr=%016"
2920                                PRIx64" iword=%08"PRIx32"\n", cpu->delay_slot,
2921                                (uint64_t)addr, iword);
2922                            goto bad;
2923                    }
2924                    break;
2925    
2926          case HI6_COP0:          case HI6_COP0:
2927                    /*  TODO: Is checking bit 25 enough, or perhaps all bits
2928                        25..21 must be checked?  */
2929                    if ((iword >> 25) & 1) {
2930                            ic->arg[2] = addr & 0xffc;
2931                            switch (iword & 0xff) {
2932                            case COP0_TLBR:
2933                                    ic->f = instr(tlbr);
2934                                    break;
2935                            case COP0_TLBWI:
2936                            case COP0_TLBWR:
2937                                    ic->f = instr(tlbw);
2938                                    ic->arg[0] = (iword & 0xff) == COP0_TLBWR;
2939                                    break;
2940                            case COP0_TLBP:
2941                                    ic->f = instr(tlbp);
2942                                    break;
2943                            case COP0_RFE:
2944                                    ic->f = instr(rfe);
2945                                    break;
2946                            case COP0_ERET:
2947                                    ic->f = instr(eret);
2948                                    break;
2949                            case COP0_DERET:
2950                                    ic->f = instr(deret);
2951                                    break;
2952                            case COP0_IDLE:
2953                            case COP0_STANDBY:
2954                            case COP0_SUSPEND:
2955                            case COP0_HIBERNATE:
2956                                    /*  TODO  */
2957                                    ic->f = instr(nop);
2958                                    break;
2959                            case COP0_EI:
2960                                    if (cpu->cd.mips.cpu_type.rev == MIPS_R5900) {
2961                                            ic->f = instr(ei_r5900);
2962                                    } else
2963                                            goto bad;
2964                                    break;
2965                            case COP0_DI:
2966                                    if (cpu->cd.mips.cpu_type.rev == MIPS_R5900) {
2967                                            ic->f = instr(di_r5900);
2968                                    } else
2969                                            goto bad;
2970                                    break;
2971                            default:fatal("UNIMPLEMENTED cop0 (func 0x%02x)\n",
2972                                        iword & 0xff);
2973                                    goto bad;
2974                            }
2975                            break;
2976                    }
2977    
2978                  /*  rs contains the coprocessor opcode!  */                  /*  rs contains the coprocessor opcode!  */
2979                  switch (rs) {                  switch (rs) {
2980                    case COPz_CFCz:
2981                            ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
2982                            ic->arg[1] = rd + ((iword & 7) << 5);
2983                            ic->arg[2] = addr & 0xffc;
2984                            ic->f = instr(cfc0);
2985                            if (rt == MIPS_GPR_ZERO)
2986                                    ic->f = instr(nop);
2987                            break;
2988                  case COPz_MFCz:                  case COPz_MFCz:
2989                  case COPz_DMFCz:                  case COPz_DMFCz:
2990                          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 3001  X(to_be_translated)
3001                          ic->arg[2] = addr & 0xffc;                          ic->arg[2] = addr & 0xffc;
3002                          ic->f = rs == COPz_MTCz? instr(mtc0) : instr(dmtc0);                          ic->f = rs == COPz_MTCz? instr(mtc0) : instr(dmtc0);
3003                          break;                          break;
3004                    case 8: if (iword == 0x4100ffff) {
3005                                    /*  R2020 DECstation write-loop thingy.  */
3006                                    ic->f = instr(nop);
3007                            } else {
3008                                    fatal("Unimplemented blah blah zzzz...\n");
3009                                    goto bad;
3010                            }
3011                            break;
3012                    
3013                  default:fatal("UNIMPLEMENTED cop0 (rs = %i)\n", rs);                  default:fatal("UNIMPLEMENTED cop0 (rs = %i)\n", rs);
3014                          goto bad;                          goto bad;
3015                  }                  }
3016                  break;                  break;
3017    
3018          case HI6_COP1:          case HI6_COP1:
3019                  /*  rs contains the coprocessor opcode!  */                  /*  Always cause a coprocessor unusable exception if
3020                        there is no floating point coprocessor:  */
3021                    if (cpu->cd.mips.cpu_type.flags & NOFPU ||
3022                        cpu->cd.mips.coproc[1] == NULL) {
3023                            ic->f = instr(cpu);
3024                            ic->arg[0] = 1;
3025                            break;
3026                    }
3027    
3028                    /*  Bits 25..21 are floating point main opcode:  */
3029                  switch (rs) {                  switch (rs) {
3030    
3031                    case COPz_BCzc:
3032                            /*  Conditional branch:  */
3033                            /*  TODO: Reimplement this in a faster way.  */
3034                            ic->f = instr(cop1_bc);
3035                            ic->arg[0] = (iword >> 18) & 7; /*  cc  */
3036                            ic->arg[1] = (iword >> 16) & 3; /*  nd, tf bits  */
3037                            ic->arg[2] = (int32_t) ((imm <<
3038                                MIPS_INSTR_ALIGNMENT_SHIFT) + (addr & 0xffc) + 4);
3039                            if (cpu->delay_slot) {
3040                                    fatal("TODO: branch in delay slot? (4)\n");
3041                                    goto bad;
3042                            }
3043                            if (cpu->cd.mips.cpu_type.isa_level <= 3 &&
3044                                ic->arg[0] != 0) {
3045                                    fatal("Attempt to execute a non-cc-0 BC*"
3046                                        " instruction on an isa level %i cpu. "
3047                                        "TODO: How should this be handled?\n",
3048                                        cpu->cd.mips.cpu_type.isa_level);
3049                                    goto bad;
3050                            }
3051    
3052                            break;
3053    
3054                    case COPz_DMFCz:
3055                    case COPz_DMTCz:
3056                            x64 = 1;
3057                            /*  FALL-THROUGH  */
3058                    case COP1_FMT_S:
3059                    case COP1_FMT_D:
3060                    case COP1_FMT_W:
3061                    case COP1_FMT_L:
3062                    case COP1_FMT_PS:
3063                  case COPz_CFCz:                  case COPz_CFCz:
3064                          ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];                  case COPz_CTCz:
3065                          ic->arg[1] = (size_t)&cpu->cd.mips.coproc[1]->fcr[rd];                  case COPz_MFCz:
3066                          ic->arg[2] = addr & 0xffc;                  case COPz_MTCz:
3067                          ic->f = instr(cfc1);                          /*  Fallback to slow pre-dyntrans code, for now.  */
3068                          if (rt == MIPS_GPR_ZERO)                          /*  TODO: Fix/optimize/rewrite.  */
3069                                  ic->f = instr(nop);                          ic->f = instr(cop1_slow);
3070                            ic->arg[0] = (uint32_t)iword & ((1 << 26) - 1);
3071                          break;                          break;
3072                  default:fatal("UNIMPLEMENTED cop1 (rs = %i)\n", rs);  
3073                    default:fatal("COP1 floating point opcode = 0x%02x\n", rs);
3074                          goto bad;                          goto bad;
3075                  }                  }
3076                  break;                  break;
3077    
3078            case HI6_COP2:
3079                    /*  Always cause a coprocessor unusable exception if
3080                        there is no coprocessor 2:  */
3081                    if (cpu->cd.mips.coproc[2] == NULL) {
3082                            ic->f = instr(cpu);
3083                            ic->arg[0] = 2;
3084                            break;
3085                    }
3086                    fatal("COP2 functionality not yet implemented\n");
3087                    goto bad;
3088                    break;
3089    
3090          case HI6_SPECIAL2:          case HI6_SPECIAL2:
3091                    if (cpu->cd.mips.cpu_type.rev == MIPS_R5900) {
3092                            /*  R5900, TX79/C790, have MMI instead of SPECIAL2:  */
3093                            int mmi_subopcode = (iword >> 6) & 0x1f;
3094    
3095                            switch (s6) {
3096    
3097                            case MMI_MADD:
3098                                    ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];
3099                                    ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rt];
3100                                    ic->arg[2] = (size_t)&cpu->cd.mips.gpr[rd];
3101                                    if (rd == MIPS_GPR_ZERO)
3102                                            ic->f = instr(madd);
3103                                    else
3104                                            ic->f = instr(madd_rd);
3105                                    break;
3106    
3107                            case MMI_MADDU:
3108                                    ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];
3109                                    ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rt];
3110                                    ic->arg[2] = (size_t)&cpu->cd.mips.gpr[rd];
3111                                    if (rd == MIPS_GPR_ZERO)
3112                                            ic->f = instr(maddu);
3113                                    else
3114                                            ic->f = instr(maddu_rd);
3115                                    break;
3116    
3117                            case MMI_MMI0:
3118                                    switch (mmi_subopcode) {
3119    
3120                                    case MMI0_PEXTLW:
3121                                            ic->arg[0] = rs;
3122                                            ic->arg[1] = rt;
3123                                            ic->arg[2] = rd;
3124                                            if (rd == MIPS_GPR_ZERO)
3125                                                    ic->f = instr(nop);
3126                                            else
3127                                                    ic->f = instr(pextlw);
3128                                            break;
3129    
3130                                    default:goto bad;
3131                                    }
3132                                    break;
3133    
3134                            case MMI_MMI3:
3135                                    switch (mmi_subopcode) {
3136    
3137                                    case MMI3_POR:
3138                                            ic->arg[0] = rs;
3139                                            ic->arg[1] = rt;
3140                                            ic->arg[2] = rd;
3141                                            if (rd == MIPS_GPR_ZERO)
3142                                                    ic->f = instr(nop);
3143                                            else
3144                                                    ic->f = instr(por);
3145                                            break;
3146    
3147                                    default:goto bad;
3148                                    }
3149                                    break;
3150    
3151                            default:goto bad;
3152                            }
3153                            break;
3154                    }
3155    
3156                    /*  TODO: is this correct? Or are there other non-MIPS32/64
3157                        MIPS processors that have support for SPECIAL2 opcodes?  */
3158                    if (cpu->cd.mips.cpu_type.isa_level < 32) {
3159                            ic->f = instr(reserved);
3160                            break;
3161                    }
3162    
3163                    /*  SPECIAL2:  */
3164                  switch (s6) {                  switch (s6) {
3165    
3166                    case SPECIAL2_MADD:
3167                    case SPECIAL2_MADDU:
3168                    case SPECIAL2_MSUB:
3169                    case SPECIAL2_MSUBU:
3170                            ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];
3171                            ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rt];
3172                            switch (s6) {
3173                            case SPECIAL2_MADD: ic->f = instr(madd); break;
3174                            case SPECIAL2_MADDU:ic->f = instr(maddu); break;
3175                            case SPECIAL2_MSUB: ic->f = instr(msub); break;
3176                            case SPECIAL2_MSUBU:ic->f = instr(msubu); break;
3177                            }
3178                            break;
3179    
3180                  case SPECIAL2_MUL:                  case SPECIAL2_MUL:
3181                          ic->f = instr(mul);                          ic->f = instr(mul);
3182                          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 3206  X(to_be_translated)
3206                  }                  }
3207                  break;                  break;
3208    
3209            case HI6_REGIMM:
3210                    switch (rt) {
3211                    case REGIMM_BGEZ:
3212                    case REGIMM_BGEZL:
3213                    case REGIMM_BLTZ:
3214                    case REGIMM_BLTZL:
3215                    case REGIMM_BGEZAL:
3216                    case REGIMM_BGEZALL:
3217                    case REGIMM_BLTZAL:
3218                    case REGIMM_BLTZALL:
3219                            samepage_function = NULL;
3220                            switch (rt) {
3221                            case REGIMM_BGEZ:
3222                                    ic->f = instr(bgez);
3223                                    samepage_function = instr(bgez_samepage);
3224                                    break;
3225                            case REGIMM_BGEZL:
3226                                    ic->f = instr(bgezl);
3227                                    samepage_function = instr(bgezl_samepage);
3228                                    break;
3229                            case REGIMM_BLTZ:
3230                                    ic->f = instr(bltz);
3231                                    samepage_function = instr(bltz_samepage);
3232                                    break;
3233                            case REGIMM_BLTZL:
3234                                    ic->f = instr(bltzl);
3235                                    samepage_function = instr(bltzl_samepage);
3236                                    break;
3237                            case REGIMM_BGEZAL:
3238                                    ic->f = instr(bgezal);
3239                                    samepage_function = instr(bgezal_samepage);
3240                                    break;
3241                            case REGIMM_BGEZALL:
3242                                    ic->f = instr(bgezall);
3243                                    samepage_function = instr(bgezall_samepage);
3244                                    break;
3245                            case REGIMM_BLTZAL:
3246                                    ic->f = instr(bltzal);
3247                                    samepage_function = instr(bltzal_samepage);
3248                                    break;
3249                            case REGIMM_BLTZALL:
3250                                    ic->f = instr(bltzall);
3251                                    samepage_function = instr(bltzall_samepage);
3252                                    break;
3253                            }
3254                            ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];
3255                            ic->arg[2] = (imm << MIPS_INSTR_ALIGNMENT_SHIFT)
3256                                + (addr & 0xffc) + 4;
3257                            /*  Is the offset from the start of the current page
3258                                still within the same page? Then use the
3259                                samepage_function:  */
3260                            if ((uint32_t)ic->arg[2] < ((MIPS_IC_ENTRIES_PER_PAGE-1)
3261                                << MIPS_INSTR_ALIGNMENT_SHIFT) && (addr & 0xffc)
3262                                < 0xffc) {
3263                                    ic->arg[2] = (size_t) (cpu->cd.mips.cur_ic_page+
3264                                        ((ic->arg[2] >> MIPS_INSTR_ALIGNMENT_SHIFT)
3265                                        & (MIPS_IC_ENTRIES_PER_PAGE - 1)));
3266                                    ic->f = samepage_function;
3267                            }
3268                            if (cpu->delay_slot) {
3269                                    fatal("TODO: branch in delay slot? (5)\n");
3270                                    goto bad;
3271                            }
3272                            break;
3273                    default:fatal("UNIMPLEMENTED regimm rt=%i\n", rt);
3274                            goto bad;
3275                    }
3276                    break;
3277    
3278            case HI6_LB:
3279            case HI6_LBU:
3280            case HI6_SB:
3281            case HI6_LH:
3282            case HI6_LHU:
3283            case HI6_SH:
3284            case HI6_LW:
3285            case HI6_LWU:
3286            case HI6_SW:
3287            case HI6_LD:
3288            case HI6_SD:
3289                    /*  TODO: LWU should probably also be x64=1?  */
3290                    size = 2; signedness = 0; store = 0;
3291                    switch (main_opcode) {
3292                    case HI6_LB:  size = 0; signedness = 1; break;
3293                    case HI6_LBU: size = 0; break;
3294                    case HI6_LH:  size = 1; signedness = 1; break;
3295                    case HI6_LHU: size = 1; break;
3296                    case HI6_LW:  signedness = 1; break;
3297                    case HI6_LWU: break;
3298                    case HI6_LD:  size = 3; x64 = 1; break;
3299                    case HI6_SB:  store = 1; size = 0; break;
3300                    case HI6_SH:  store = 1; size = 1; break;
3301                    case HI6_SW:  store = 1; break;
3302                    case HI6_SD:  store = 1; size = 3; x64 = 1; break;
3303                    }
3304    
3305                    ic->f =
3306    #ifdef MODE32
3307                        mips32_loadstore
3308    #else
3309                        mips_loadstore
3310    #endif
3311                        [ (cpu->byte_order == EMUL_LITTLE_ENDIAN? 0 : 16)
3312                        + store * 8 + size * 2 + signedness];
3313                    ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
3314                    ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rs];
3315                    ic->arg[2] = (int32_t)imm;
3316    
3317                    /*  Load into the dummy scratch register, if rt = zero  */
3318                    if (!store && rt == MIPS_GPR_ZERO)
3319                            ic->arg[0] = (size_t)&cpu->cd.mips.scratch;
3320                    break;
3321    
3322            case HI6_LL:
3323            case HI6_LLD:
3324            case HI6_SC:
3325            case HI6_SCD:
3326                    /*  32-bit load-linked/store-condition for ISA II and up:  */
3327                    /*  (64-bit load-linked/store-condition for ISA III...)  */
3328                    if (cpu->cd.mips.cpu_type.isa_level < 2) {
3329                            ic->f = instr(reserved);
3330                            break;
3331                    }
3332    
3333                    store = 0;
3334                    switch (main_opcode) {
3335                    case HI6_LL:  ic->f = instr(ll); break;
3336                    case HI6_LLD: ic->f = instr(lld); x64 = 1; break;
3337                    case HI6_SC:  ic->f = instr(sc); store = 1; break;
3338                    case HI6_SCD: ic->f = instr(scd); store = 1; x64 = 1; break;
3339                    }
3340                    ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
3341                    ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rs];
3342                    ic->arg[2] = (int32_t)imm;
3343                    if (!store && rt == MIPS_GPR_ZERO) {
3344                            fatal("HM... unusual load linked\n");
3345                            goto bad;
3346                    }
3347                    break;
3348    
3349            case HI6_LWL:
3350            case HI6_LWR:
3351            case HI6_LDL:
3352            case HI6_LDR:
3353            case HI6_SWL:
3354            case HI6_SWR:
3355            case HI6_SDL:
3356            case HI6_SDR:
3357                    /*  TODO: replace these with faster versions...  */
3358                    store = 0;
3359                    switch (main_opcode) {
3360                    case HI6_LWL: ic->f = instr(lwl); break;
3361                    case HI6_LWR: ic->f = instr(lwr); break;
3362                    case HI6_LDL: ic->f = instr(ldl); x64 = 1; break;
3363                    case HI6_LDR: ic->f = instr(ldr); x64 = 1; break;
3364                    case HI6_SWL: ic->f = instr(swl); store = 1; break;
3365                    case HI6_SWR: ic->f = instr(swr); store = 1; break;
3366                    case HI6_SDL: ic->f = instr(sdl); store = 1; x64 = 1; break;
3367                    case HI6_SDR: ic->f = instr(sdr); store = 1; x64 = 1; break;
3368                    }
3369                    ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
3370                    ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rs];
3371                    ic->arg[2] = (int32_t)imm;
3372    
3373                    /*  Load into the dummy scratch register, if rt = zero  */
3374                    if (!store && rt == MIPS_GPR_ZERO)
3375                            ic->arg[0] = (size_t)&cpu->cd.mips.scratch;
3376                    break;
3377    
3378            case HI6_LWC1:
3379            case HI6_SWC1:
3380            case HI6_LDC1:
3381            case HI6_SDC1:
3382                    /*  64-bit floating-point load/store for ISA II and up...  */
3383                    if ((main_opcode == HI6_LDC1 || main_opcode == HI6_SDC1)
3384                        && cpu->cd.mips.cpu_type.isa_level < 2) {
3385                            ic->f = instr(reserved);
3386                            break;
3387                    }
3388    
3389                    ic->arg[0] = (size_t)&cpu->cd.mips.coproc[1]->reg[rt];
3390                    ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rs];
3391                    ic->arg[2] = (int32_t)imm;
3392                    switch (main_opcode) {
3393                    case HI6_LWC1: ic->f = instr(lwc1); break;
3394                    case HI6_LDC1: ic->f = instr(ldc1); break;
3395                    case HI6_SWC1: ic->f = instr(swc1); break;
3396                    case HI6_SDC1: ic->f = instr(sdc1); break;
3397                    }
3398    
3399                    /*  Cause a coprocessor unusable exception if
3400                        there is no floating point coprocessor:  */
3401                    if (cpu->cd.mips.cpu_type.flags & NOFPU ||
3402                        cpu->cd.mips.coproc[1] == NULL) {
3403                            ic->f = instr(cpu);
3404                            ic->arg[0] = 1;
3405                    }
3406                    break;
3407    
3408            case HI6_LWC3:
3409                    /*  PREF (prefetch) on ISA IV and MIPS32/64:  */
3410                    if (cpu->cd.mips.cpu_type.isa_level >= 4) {
3411                            /*  Treat as nop for now:  */
3412                            ic->f = instr(nop);
3413                    } else {
3414                            fatal("TODO: lwc3 not implemented yet\n");
3415                            goto bad;
3416                    }
3417                    break;
3418    
3419            case HI6_LQ_MDMX:
3420                    if (cpu->cd.mips.cpu_type.rev == MIPS_R5900) {
3421                            fatal("TODO: R5900 128-bit loads\n");
3422                            goto bad;
3423                    }
3424    
3425                    fatal("TODO: MDMX\n");
3426                    goto bad;
3427                    /*  break  */
3428    
3429            case HI6_SQ_SPECIAL3:
3430                    if (cpu->cd.mips.cpu_type.rev == MIPS_R5900) {
3431                            fatal("TODO: R5900 128-bit stores\n");
3432                            goto bad;
3433                    }
3434    
3435                    if (cpu->cd.mips.cpu_type.isa_level < 32 ||
3436                        cpu->cd.mips.cpu_type.isa_revision < 2) {
3437                            static int warning = 0;
3438                            if (!warning) {
3439                                    fatal("[ WARNING! SPECIAL3 opcode used on a"
3440                                        " cpu which doesn't implement it ]\n");
3441                                    warning = 1;
3442                            }
3443                            ic->f = instr(reserved);
3444                            break;
3445                    }
3446    
3447                    switch (s6) {
3448    
3449                    case SPECIAL3_RDHWR:
3450                            ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
3451    
3452                            switch (rd) {
3453    
3454                            case 0: ic->f = instr(rdhwr_cpunum);
3455                                    if (rt == MIPS_GPR_ZERO)
3456                                            ic->f = instr(nop);
3457                                    break;
3458    
3459                            default:fatal("unimplemented rdhwr register rd=%i\n",
3460                                        rd);
3461                                    goto bad;
3462                            }
3463                            break;
3464    
3465                    default:goto bad;
3466                    }
3467                    break;
3468    
3469            case HI6_CACHE:
3470                    /*  TODO: rt and op etc...  */
3471                    ic->f = instr(cache);
3472                    break;
3473    
3474          default:goto bad;          default:goto bad;
3475          }          }
3476    
3477          if (x64)  #ifdef MODE32
3478                  ic->f = instr(invalid_32_64);          if (x64) {
3479                    static int has_warned = 0;
3480                    if (!has_warned)
3481                            fatal("[ WARNING/NOTE: attempt to execute a 64-bit"
3482                                " instruction on an emulated 32-bit processor; "
3483                                "pc=0x%08"PRIx32" ]\n", (uint32_t)cpu->pc);
3484                    has_warned = 1;
3485                    ic->f = instr(reserved);
3486            }
3487    #endif
3488    
         if (in_crosspage_delayslot)  
                 cpu->cd.mips.combination_check = NULL;  
3489    
3490  #define DYNTRANS_TO_BE_TRANSLATED_TAIL  #define DYNTRANS_TO_BE_TRANSLATED_TAIL
3491  #include "cpu_dyntrans.c"  #include "cpu_dyntrans.c"

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

  ViewVC Help
Powered by ViewVC 1.1.26