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

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

  ViewVC Help
Powered by ViewVC 1.1.26