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

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

  ViewVC Help
Powered by ViewVC 1.1.26