/[gxemul]/trunk/src/cpus/cpu_ppc_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_ppc_instr.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 20 by dpavlin, Mon Oct 8 16:19:23 2007 UTC revision 30 by dpavlin, Mon Oct 8 16:20:40 2007 UTC
# Line 1  Line 1 
1  /*  /*
2   *  Copyright (C) 2005  Anders Gavare.  All rights reserved.   *  Copyright (C) 2005-2006  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_ppc_instr.c,v 1.44 2005/11/24 01:31:54 debug Exp $   *  $Id: cpu_ppc_instr.c,v 1.71 2006/07/26 23:21:48 debug Exp $
29   *   *
30   *  POWER/PowerPC instructions.   *  POWER/PowerPC instructions.
31   *   *
# Line 46  Line 46 
46  #define DOT2(n) X(n ## _dot) { instr(n)(cpu,ic); \  #define DOT2(n) X(n ## _dot) { instr(n)(cpu,ic); \
47          update_cr0(cpu, reg(ic->arg[2])); }          update_cr0(cpu, reg(ic->arg[2])); }
48    
49    #ifndef CHECK_FOR_FPU_EXCEPTION
50    #define CHECK_FOR_FPU_EXCEPTION { if (!(cpu->cd.ppc.msr & PPC_MSR_FP)) { \
51                    /*  Synchronize the PC, and cause an FPU exception:  */  \
52                    uint64_t low_pc = ((size_t)ic -                          \
53                        (size_t)cpu->cd.ppc.cur_ic_page)                     \
54                        / sizeof(struct ppc_instr_call);                     \
55                    cpu->pc = (cpu->pc & ~((PPC_IC_ENTRIES_PER_PAGE-1) <<    \
56                        PPC_INSTR_ALIGNMENT_SHIFT)) + (low_pc <<             \
57                        PPC_INSTR_ALIGNMENT_SHIFT);                          \
58                    ppc_exception(cpu, PPC_EXCEPTION_FPU);                   \
59                    return; } }
60    #endif
61    
62    
63    
64  /*  /*
65   *  nop:  Do nothing.   *  nop:  Do nothing.
# Line 76  X(addi) Line 90  X(addi)
90  {  {
91          reg(ic->arg[2]) = reg(ic->arg[0]) + (int32_t)ic->arg[1];          reg(ic->arg[2]) = reg(ic->arg[0]) + (int32_t)ic->arg[1];
92  }  }
93    X(li)
94    {
95            reg(ic->arg[2]) = (int32_t)ic->arg[1];
96    }
97    X(li_0)
98    {
99            reg(ic->arg[2]) = 0;
100    }
101    
102    
103  /*  /*
# Line 160  X(addic_dot) Line 182  X(addic_dot)
182   */   */
183  X(bclr)  X(bclr)
184  {  {
185          int bo = ic->arg[0], bi31m = ic->arg[1]  /* , bh = ic->arg[2]  */;          unsigned int bo = ic->arg[0], bi31m = ic->arg[1];
186          int ctr_ok, cond_ok;          int ctr_ok, cond_ok;
187          uint64_t old_pc = cpu->pc;          uint64_t old_pc = cpu->pc;
188          MODE_uint_t tmp, addr = cpu->cd.ppc.spr[SPR_LR];          MODE_uint_t tmp, addr = cpu->cd.ppc.spr[SPR_LR];
# Line 187  X(bclr) Line 209  X(bclr)
209                              PPC_INSTR_ALIGNMENT_SHIFT);                              PPC_INSTR_ALIGNMENT_SHIFT);
210                  } else {                  } else {
211                          /*  Find the new physical page and update pointers:  */                          /*  Find the new physical page and update pointers:  */
212                          DYNTRANS_PC_TO_POINTERS(cpu);                          quick_pc_to_pointers(cpu);
213                  }                  }
214          }          }
215  }  }
216  X(bclr_20)  X(bclr_20)
217  {  {
218          cpu->pc = cpu->cd.ppc.spr[SPR_LR];          cpu->pc = cpu->cd.ppc.spr[SPR_LR];
219          DYNTRANS_PC_TO_POINTERS(cpu);          quick_pc_to_pointers(cpu);
220  }  }
221  X(bclr_l)  X(bclr_l)
222  {  {
223          uint64_t low_pc, old_pc = cpu->pc;          uint64_t low_pc, old_pc = cpu->pc;
224          int bo = ic->arg[0], bi31m = ic->arg[1]  /* , bh = ic->arg[2]  */;          unsigned int bo = ic->arg[0], bi31m = ic->arg[1]  /* ,bh = ic->arg[2]*/;
225          int ctr_ok, cond_ok;          int ctr_ok, cond_ok;
226          MODE_uint_t tmp, addr = cpu->cd.ppc.spr[SPR_LR];          MODE_uint_t tmp, addr = cpu->cd.ppc.spr[SPR_LR];
227          if (!(bo & 4))          if (!(bo & 4))
# Line 213  X(bclr_l) Line 235  X(bclr_l)
235          /*  Calculate return PC:  */          /*  Calculate return PC:  */
236          low_pc = ((size_t)ic - (size_t)          low_pc = ((size_t)ic - (size_t)
237              cpu->cd.ppc.cur_ic_page) / sizeof(struct ppc_instr_call) + 1;              cpu->cd.ppc.cur_ic_page) / sizeof(struct ppc_instr_call) + 1;
238          cpu->cd.ppc.spr[SPR_LR] = cpu->pc & ~((PPC_IC_ENTRIES_PER_PAGE-1) << 2);          cpu->cd.ppc.spr[SPR_LR] = cpu->pc & ~((PPC_IC_ENTRIES_PER_PAGE-1)
239          cpu->cd.ppc.spr[SPR_LR] += (low_pc << 2);              << PPC_INSTR_ALIGNMENT_SHIFT);
240            cpu->cd.ppc.spr[SPR_LR] += (low_pc << PPC_INSTR_ALIGNMENT_SHIFT);
241    
242          if (ctr_ok && cond_ok) {          if (ctr_ok && cond_ok) {
243                  uint64_t mask_within_page =                  uint64_t mask_within_page =
# Line 234  X(bclr_l) Line 257  X(bclr_l)
257                              PPC_INSTR_ALIGNMENT_SHIFT);                              PPC_INSTR_ALIGNMENT_SHIFT);
258                  } else {                  } else {
259                          /*  Find the new physical page and update pointers:  */                          /*  Find the new physical page and update pointers:  */
260                          DYNTRANS_PC_TO_POINTERS(cpu);                          quick_pc_to_pointers(cpu);
261                  }                  }
262          }          }
263  }  }
# Line 249  X(bclr_l) Line 272  X(bclr_l)
272   */   */
273  X(bcctr)  X(bcctr)
274  {  {
275          int bo = ic->arg[0], bi31m = ic->arg[1]  /* , bh = ic->arg[2]  */;          unsigned int bo = ic->arg[0], bi31m = ic->arg[1]  /*,bh = ic->arg[2]*/;
276          uint64_t old_pc = cpu->pc;          uint64_t old_pc = cpu->pc;
277          MODE_uint_t addr = cpu->cd.ppc.spr[SPR_CTR];          MODE_uint_t addr = cpu->cd.ppc.spr[SPR_CTR];
278          int cond_ok = (bo >> 4) & 1;          int cond_ok = (bo >> 4) & 1;
# Line 270  X(bcctr) Line 293  X(bcctr)
293                              PPC_INSTR_ALIGNMENT_SHIFT);                              PPC_INSTR_ALIGNMENT_SHIFT);
294                  } else {                  } else {
295                          /*  Find the new physical page and update pointers:  */                          /*  Find the new physical page and update pointers:  */
296                          DYNTRANS_PC_TO_POINTERS(cpu);                          quick_pc_to_pointers(cpu);
297                  }                  }
298          }          }
299  }  }
300  X(bcctr_l)  X(bcctr_l)
301  {  {
302          uint64_t low_pc, old_pc = cpu->pc;          uint64_t low_pc, old_pc = cpu->pc;
303          int bo = ic->arg[0], bi31m = ic->arg[1]  /* , bh = ic->arg[2]  */;          unsigned int bo = ic->arg[0], bi31m = ic->arg[1]  /*,bh = ic->arg[2] */;
304          MODE_uint_t addr = cpu->cd.ppc.spr[SPR_CTR];          MODE_uint_t addr = cpu->cd.ppc.spr[SPR_CTR];
305          int cond_ok = (bo >> 4) & 1;          int cond_ok = (bo >> 4) & 1;
306          cond_ok |= ( ((bo >> 3) & 1) == ((cpu->cd.ppc.cr >> bi31m) & 1) );          cond_ok |= ( ((bo >> 3) & 1) == ((cpu->cd.ppc.cr >> bi31m) & 1) );
# Line 285  X(bcctr_l) Line 308  X(bcctr_l)
308          /*  Calculate return PC:  */          /*  Calculate return PC:  */
309          low_pc = ((size_t)ic - (size_t)          low_pc = ((size_t)ic - (size_t)
310              cpu->cd.ppc.cur_ic_page) / sizeof(struct ppc_instr_call) + 1;              cpu->cd.ppc.cur_ic_page) / sizeof(struct ppc_instr_call) + 1;
311          cpu->cd.ppc.spr[SPR_LR] = cpu->pc & ~((PPC_IC_ENTRIES_PER_PAGE-1) << 2);          cpu->cd.ppc.spr[SPR_LR] = cpu->pc & ~((PPC_IC_ENTRIES_PER_PAGE-1)
312          cpu->cd.ppc.spr[SPR_LR] += (low_pc << 2);              << PPC_INSTR_ALIGNMENT_SHIFT);
313            cpu->cd.ppc.spr[SPR_LR] += (low_pc << PPC_INSTR_ALIGNMENT_SHIFT);
314    
315          if (cond_ok) {          if (cond_ok) {
316                  uint64_t mask_within_page =                  uint64_t mask_within_page =
# Line 304  X(bcctr_l) Line 328  X(bcctr_l)
328                              PPC_INSTR_ALIGNMENT_SHIFT);                              PPC_INSTR_ALIGNMENT_SHIFT);
329                  } else {                  } else {
330                          /*  Find the new physical page and update pointers:  */                          /*  Find the new physical page and update pointers:  */
331                          DYNTRANS_PC_TO_POINTERS(cpu);                          quick_pc_to_pointers(cpu);
332                  }                  }
333          }          }
334  }  }
# Line 313  X(bcctr_l) Line 337  X(bcctr_l)
337  /*  /*
338   *  b:  Branch (to a different translated page)   *  b:  Branch (to a different translated page)
339   *   *
340   *  arg[0] = relative offset (as an int32_t)   *  arg[0] = relative offset (as an int32_t) from start of page
341   */   */
342  X(b)  X(b)
343  {  {
344          uint64_t low_pc;          cpu->pc &= ~((PPC_IC_ENTRIES_PER_PAGE-1) << PPC_INSTR_ALIGNMENT_SHIFT);
   
         /*  Calculate new PC from this instruction + arg[0]  */  
         low_pc = ((size_t)ic - (size_t)  
             cpu->cd.ppc.cur_ic_page) / sizeof(struct ppc_instr_call);  
         cpu->pc &= ~((PPC_IC_ENTRIES_PER_PAGE-1) << 2);  
         cpu->pc += (low_pc << 2);  
345          cpu->pc += (int32_t)ic->arg[0];          cpu->pc += (int32_t)ic->arg[0];
346    
347          /*  Find the new physical page and update the translation pointers:  */          /*  Find the new physical page and update the translation pointers:  */
348          DYNTRANS_PC_TO_POINTERS(cpu);          quick_pc_to_pointers(cpu);
349  }  }
350  X(ba)  X(ba)
351  {  {
352          cpu->pc = (int32_t)ic->arg[0];          cpu->pc = (int32_t)ic->arg[0];
353          DYNTRANS_PC_TO_POINTERS(cpu);          quick_pc_to_pointers(cpu);
354  }  }
355    
356    
357  /*  /*
358   *  bc:  Branch Conditional (to a different translated page)   *  bc:  Branch Conditional (to a different translated page)
359   *   *
360   *  arg[0] = relative offset (as an int32_t)   *  arg[0] = relative offset (as an int32_t) from start of page
361   *  arg[1] = bo   *  arg[1] = bo
362   *  arg[2] = bi   *  arg[2] = 31-bi
363   */   */
364  X(bc)  X(bc)
365  {  {
366          MODE_uint_t tmp;          MODE_uint_t tmp;
367          int ctr_ok, cond_ok, bi = ic->arg[2], bo = ic->arg[1];          unsigned int ctr_ok, cond_ok, bi31m = ic->arg[2], bo = ic->arg[1];
368          if (!(bo & 4))          if (!(bo & 4))
369                  cpu->cd.ppc.spr[SPR_CTR] --;                  cpu->cd.ppc.spr[SPR_CTR] --;
370          ctr_ok = (bo >> 2) & 1;          ctr_ok = (bo >> 2) & 1;
# Line 354  X(bc) Line 372  X(bc)
372          ctr_ok |= ( (tmp != 0) ^ ((bo >> 1) & 1) );          ctr_ok |= ( (tmp != 0) ^ ((bo >> 1) & 1) );
373          cond_ok = (bo >> 4) & 1;          cond_ok = (bo >> 4) & 1;
374          cond_ok |= ( ((bo >> 3) & 1) ==          cond_ok |= ( ((bo >> 3) & 1) ==
375              ((cpu->cd.ppc.cr >> (31-bi)) & 1)  );              ((cpu->cd.ppc.cr >> (bi31m)) & 1)  );
376          if (ctr_ok && cond_ok)          if (ctr_ok && cond_ok)
377                  instr(b)(cpu,ic);                  instr(b)(cpu,ic);
378  }  }
379  X(bcl)  X(bcl)
380  {  {
381          MODE_uint_t tmp;          MODE_uint_t tmp;
382          int ctr_ok, cond_ok, bi = ic->arg[2], bo = ic->arg[1], low_pc;          unsigned int ctr_ok, cond_ok, bi31m = ic->arg[2], bo = ic->arg[1];
383            int low_pc;
384    
385          /*  Calculate LR:  */          /*  Calculate LR:  */
386          low_pc = ((size_t)ic - (size_t)          low_pc = ((size_t)ic - (size_t)
387              cpu->cd.ppc.cur_ic_page) / sizeof(struct ppc_instr_call) + 1;              cpu->cd.ppc.cur_ic_page) / sizeof(struct ppc_instr_call) + 1;
388          cpu->cd.ppc.spr[SPR_LR] = cpu->pc & ~((PPC_IC_ENTRIES_PER_PAGE-1) << 2);          cpu->cd.ppc.spr[SPR_LR] = cpu->pc & ~((PPC_IC_ENTRIES_PER_PAGE-1)
389          cpu->cd.ppc.spr[SPR_LR] += (low_pc << 2);              << PPC_INSTR_ALIGNMENT_SHIFT);
390            cpu->cd.ppc.spr[SPR_LR] += (low_pc << PPC_INSTR_ALIGNMENT_SHIFT);
391    
392          if (!(bo & 4))          if (!(bo & 4))
393                  cpu->cd.ppc.spr[SPR_CTR] --;                  cpu->cd.ppc.spr[SPR_CTR] --;
# Line 376  X(bcl) Line 396  X(bcl)
396          ctr_ok |= ( (tmp != 0) ^ ((bo >> 1) & 1) );          ctr_ok |= ( (tmp != 0) ^ ((bo >> 1) & 1) );
397          cond_ok = (bo >> 4) & 1;          cond_ok = (bo >> 4) & 1;
398          cond_ok |= ( ((bo >> 3) & 1) ==          cond_ok |= ( ((bo >> 3) & 1) ==
399              ((cpu->cd.ppc.cr >> (31-bi)) & 1)  );              ((cpu->cd.ppc.cr >> bi31m) & 1)  );
400          if (ctr_ok && cond_ok)          if (ctr_ok && cond_ok)
401                  instr(b)(cpu,ic);                  instr(b)(cpu,ic);
402  }  }
# Line 398  X(b_samepage) Line 418  X(b_samepage)
418   *   *
419   *  arg[0] = new ic ptr   *  arg[0] = new ic ptr
420   *  arg[1] = bo   *  arg[1] = bo
421   *  arg[2] = bi   *  arg[2] = 31-bi
422   */   */
423  X(bc_samepage)  X(bc_samepage)
424  {  {
425          MODE_uint_t tmp;          MODE_uint_t tmp;
426          int ctr_ok, cond_ok, bi = ic->arg[2], bo = ic->arg[1];          unsigned int ctr_ok, cond_ok, bi31m = ic->arg[2], bo = ic->arg[1];
427          if (!(bo & 4))          if (!(bo & 4))
428                  cpu->cd.ppc.spr[SPR_CTR] --;                  cpu->cd.ppc.spr[SPR_CTR] --;
429          ctr_ok = (bo >> 2) & 1;          ctr_ok = (bo >> 2) & 1;
# Line 411  X(bc_samepage) Line 431  X(bc_samepage)
431          ctr_ok |= ( (tmp != 0) ^ ((bo >> 1) & 1) );          ctr_ok |= ( (tmp != 0) ^ ((bo >> 1) & 1) );
432          cond_ok = (bo >> 4) & 1;          cond_ok = (bo >> 4) & 1;
433          cond_ok |= ( ((bo >> 3) & 1) ==          cond_ok |= ( ((bo >> 3) & 1) ==
434              ((cpu->cd.ppc.cr >> (31-bi)) & 1)  );              ((cpu->cd.ppc.cr >> bi31m) & 1)  );
435          if (ctr_ok && cond_ok)          if (ctr_ok && cond_ok)
436                  cpu->cd.ppc.next_ic = (struct ppc_instr_call *) ic->arg[0];                  cpu->cd.ppc.next_ic = (struct ppc_instr_call *) ic->arg[0];
437  }  }
438  X(bc_samepage_no_ctr)  X(bc_samepage_simple0)
439  {  {
440          int cond_ok, bi = ic->arg[2], bo = ic->arg[1];          int bi31m = ic->arg[2];
441          cond_ok = (bo >> 4) & 1;          if (!((cpu->cd.ppc.cr >> bi31m) & 1))
442          cond_ok |= ( ((bo >> 3) & 1) == ((cpu->cd.ppc.cr >> (31-bi)) & 1)  );                  cpu->cd.ppc.next_ic = (struct ppc_instr_call *) ic->arg[0];
443          if (cond_ok)  }
444    X(bc_samepage_simple1)
445    {
446            int bi31m = ic->arg[2];
447            if ((cpu->cd.ppc.cr >> bi31m) & 1)
448                  cpu->cd.ppc.next_ic = (struct ppc_instr_call *) ic->arg[0];                  cpu->cd.ppc.next_ic = (struct ppc_instr_call *) ic->arg[0];
449  }  }
450  X(bcl_samepage)  X(bcl_samepage)
451  {  {
452          MODE_uint_t tmp;          MODE_uint_t tmp;
453          int ctr_ok, cond_ok, bi = ic->arg[2], bo = ic->arg[1], low_pc;          unsigned int ctr_ok, cond_ok, bi31m = ic->arg[2], bo = ic->arg[1];
454            int low_pc;
455    
456          /*  Calculate LR:  */          /*  Calculate LR:  */
457          low_pc = ((size_t)ic - (size_t)          low_pc = ((size_t)ic - (size_t)
458              cpu->cd.ppc.cur_ic_page) / sizeof(struct ppc_instr_call) + 1;              cpu->cd.ppc.cur_ic_page) / sizeof(struct ppc_instr_call) + 1;
459          cpu->cd.ppc.spr[SPR_LR] = cpu->pc & ~((PPC_IC_ENTRIES_PER_PAGE-1) << 2);          cpu->cd.ppc.spr[SPR_LR] = cpu->pc & ~((PPC_IC_ENTRIES_PER_PAGE-1)
460          cpu->cd.ppc.spr[SPR_LR] += (low_pc << 2);              << PPC_INSTR_ALIGNMENT_SHIFT);
461            cpu->cd.ppc.spr[SPR_LR] += (low_pc << PPC_INSTR_ALIGNMENT_SHIFT);
462    
463          if (!(bo & 4))          if (!(bo & 4))
464                  cpu->cd.ppc.spr[SPR_CTR] --;                  cpu->cd.ppc.spr[SPR_CTR] --;
# Line 441  X(bcl_samepage) Line 467  X(bcl_samepage)
467          ctr_ok |= ( (tmp != 0) ^ ((bo >> 1) & 1) );          ctr_ok |= ( (tmp != 0) ^ ((bo >> 1) & 1) );
468          cond_ok = (bo >> 4) & 1;          cond_ok = (bo >> 4) & 1;
469          cond_ok |= ( ((bo >> 3) & 1) ==          cond_ok |= ( ((bo >> 3) & 1) ==
470              ((cpu->cd.ppc.cr >> (31-bi)) & 1)  );              ((cpu->cd.ppc.cr >> bi31m) & 1)  );
471          if (ctr_ok && cond_ok)          if (ctr_ok && cond_ok)
472                  cpu->cd.ppc.next_ic = (struct ppc_instr_call *) ic->arg[0];                  cpu->cd.ppc.next_ic = (struct ppc_instr_call *) ic->arg[0];
473  }  }
# Line 450  X(bcl_samepage) Line 476  X(bcl_samepage)
476  /*  /*
477   *  bl:  Branch and Link (to a different translated page)   *  bl:  Branch and Link (to a different translated page)
478   *   *
479   *  arg[0] = relative offset (as an int32_t)   *  arg[0] = relative offset (as an int32_t) from start of page
480     *  arg[1] = lr offset (relative to start of current page)
481   */   */
482  X(bl)  X(bl)
483  {  {
484          uint32_t low_pc;          /*  Calculate LR and new PC:  */
485            cpu->pc &= ~((PPC_IC_ENTRIES_PER_PAGE-1) << PPC_INSTR_ALIGNMENT_SHIFT);
486          /*  Calculate LR:  */          cpu->cd.ppc.spr[SPR_LR] = cpu->pc + ic->arg[1];
         low_pc = ((size_t)ic - (size_t)  
             cpu->cd.ppc.cur_ic_page) / sizeof(struct ppc_instr_call) + 1;  
         cpu->cd.ppc.spr[SPR_LR] = cpu->pc & ~((PPC_IC_ENTRIES_PER_PAGE-1) << 2);  
         cpu->cd.ppc.spr[SPR_LR] += (low_pc << 2);  
   
         /*  Calculate new PC from this instruction + arg[0]  */  
         low_pc = ((size_t)ic - (size_t)  
             cpu->cd.ppc.cur_ic_page) / sizeof(struct ppc_instr_call);  
         cpu->pc &= ~((PPC_IC_ENTRIES_PER_PAGE-1) << 2);  
         cpu->pc += (low_pc << 2);  
487          cpu->pc += (int32_t)ic->arg[0];          cpu->pc += (int32_t)ic->arg[0];
488    
489          /*  Find the new physical page and update the translation pointers:  */          /*  Find the new physical page and update the translation pointers:  */
490          DYNTRANS_PC_TO_POINTERS(cpu);          quick_pc_to_pointers(cpu);
491  }  }
492  X(bla)  X(bla)
493  {  {
494          uint32_t low_pc = ((size_t)ic - (size_t)          /*  Calculate LR:  */
495              cpu->cd.ppc.cur_ic_page) / sizeof(struct ppc_instr_call) + 1;          cpu->cd.ppc.spr[SPR_LR] = (cpu->pc & ~((PPC_IC_ENTRIES_PER_PAGE-1)
496          cpu->cd.ppc.spr[SPR_LR] = cpu->pc & ~((PPC_IC_ENTRIES_PER_PAGE-1) << 2);              << PPC_INSTR_ALIGNMENT_SHIFT)) + ic->arg[1];
497          cpu->cd.ppc.spr[SPR_LR] += (low_pc << 2);  
498          cpu->pc = (int32_t)ic->arg[0];          cpu->pc = (int32_t)ic->arg[0];
499          DYNTRANS_PC_TO_POINTERS(cpu);          quick_pc_to_pointers(cpu);
500  }  }
501    
502    
503  /*  /*
504   *  bl_trace:  Branch and Link (to a different translated page)  (with trace)   *  bl_trace:  Branch and Link (to a different translated page)  (with trace)
505   *   *
506   *  arg[0] = relative offset (as an int32_t)   *  arg[0] = relative offset (as an int32_t) from start of page
507     *  arg[1] = lr offset (relative to start of current page)
508   */   */
509  X(bl_trace)  X(bl_trace)
510  {  {
         uint32_t low_pc;  
   
511          /*  Calculate LR:  */          /*  Calculate LR:  */
512          low_pc = ((size_t)ic - (size_t)          cpu->cd.ppc.spr[SPR_LR] = (cpu->pc & ~((PPC_IC_ENTRIES_PER_PAGE-1)
513              cpu->cd.ppc.cur_ic_page) / sizeof(struct ppc_instr_call) + 1;              << PPC_INSTR_ALIGNMENT_SHIFT)) + ic->arg[1];
         cpu->cd.ppc.spr[SPR_LR] = cpu->pc & ~((PPC_IC_ENTRIES_PER_PAGE-1) << 2);  
         cpu->cd.ppc.spr[SPR_LR] += (low_pc << 2);  
514    
515          /*  Calculate new PC from this instruction + arg[0]  */          /*  Calculate new PC from start of page + arg[0]  */
516          low_pc = ((size_t)ic - (size_t)          cpu->pc &= ~((PPC_IC_ENTRIES_PER_PAGE-1) << PPC_INSTR_ALIGNMENT_SHIFT);
             cpu->cd.ppc.cur_ic_page) / sizeof(struct ppc_instr_call);  
         cpu->pc &= ~((PPC_IC_ENTRIES_PER_PAGE-1) << 2);  
         cpu->pc += (low_pc << 2);  
517          cpu->pc += (int32_t)ic->arg[0];          cpu->pc += (int32_t)ic->arg[0];
518    
519          cpu_functioncall_trace(cpu, cpu->pc);          cpu_functioncall_trace(cpu, cpu->pc);
520    
521          /*  Find the new physical page and update the translation pointers:  */          /*  Find the new physical page and update the translation pointers:  */
522          DYNTRANS_PC_TO_POINTERS(cpu);          quick_pc_to_pointers(cpu);
523  }  }
524  X(bla_trace)  X(bla_trace)
525  {  {
526          uint32_t low_pc = ((size_t)ic - (size_t)          /*  Calculate LR:  */
527              cpu->cd.ppc.cur_ic_page) / sizeof(struct ppc_instr_call) + 1;          cpu->cd.ppc.spr[SPR_LR] = (cpu->pc & ~((PPC_IC_ENTRIES_PER_PAGE-1)
528          cpu->cd.ppc.spr[SPR_LR] = cpu->pc & ~((PPC_IC_ENTRIES_PER_PAGE-1) << 2);              << PPC_INSTR_ALIGNMENT_SHIFT)) + ic->arg[1];
529          cpu->cd.ppc.spr[SPR_LR] += (low_pc << 2);  
530          cpu->pc = (int32_t)ic->arg[0];          cpu->pc = (int32_t)ic->arg[0];
531          cpu_functioncall_trace(cpu, cpu->pc);          cpu_functioncall_trace(cpu, cpu->pc);
532          DYNTRANS_PC_TO_POINTERS(cpu);          quick_pc_to_pointers(cpu);
533  }  }
534    
535    
# Line 526  X(bla_trace) Line 537  X(bla_trace)
537   *  bl_samepage:  Branch and Link (to within the same translated page)   *  bl_samepage:  Branch and Link (to within the same translated page)
538   *   *
539   *  arg[0] = pointer to new ppc_instr_call   *  arg[0] = pointer to new ppc_instr_call
540     *  arg[1] = lr offset (relative to start of current page)
541   */   */
542  X(bl_samepage)  X(bl_samepage)
543  {  {
         uint32_t low_pc;  
   
544          /*  Calculate LR:  */          /*  Calculate LR:  */
545          low_pc = ((size_t)ic - (size_t)          cpu->cd.ppc.spr[SPR_LR] = (cpu->pc & ~((PPC_IC_ENTRIES_PER_PAGE-1)
546              cpu->cd.ppc.cur_ic_page) / sizeof(struct ppc_instr_call) + 1;              << PPC_INSTR_ALIGNMENT_SHIFT)) + ic->arg[1];
         cpu->cd.ppc.spr[SPR_LR] = cpu->pc & ~((PPC_IC_ENTRIES_PER_PAGE-1) << 2);  
         cpu->cd.ppc.spr[SPR_LR] += (low_pc << 2);  
547    
548          cpu->cd.ppc.next_ic = (struct ppc_instr_call *) ic->arg[0];          cpu->cd.ppc.next_ic = (struct ppc_instr_call *) ic->arg[0];
549  }  }
# Line 545  X(bl_samepage) Line 553  X(bl_samepage)
553   *  bl_samepage_trace:  Branch and Link (to within the same translated page)   *  bl_samepage_trace:  Branch and Link (to within the same translated page)
554   *   *
555   *  arg[0] = pointer to new ppc_instr_call   *  arg[0] = pointer to new ppc_instr_call
556     *  arg[1] = lr offset (relative to start of current page)
557   */   */
558  X(bl_samepage_trace)  X(bl_samepage_trace)
559  {  {
560          uint32_t low_pc;          uint32_t low_pc;
561    
562          /*  Calculate LR:  */          /*  Calculate LR:  */
563          low_pc = ((size_t)ic - (size_t)          cpu->cd.ppc.spr[SPR_LR] = (cpu->pc & ~((PPC_IC_ENTRIES_PER_PAGE-1)
564              cpu->cd.ppc.cur_ic_page) / sizeof(struct ppc_instr_call) + 1;              << PPC_INSTR_ALIGNMENT_SHIFT)) + ic->arg[1];
         cpu->cd.ppc.spr[SPR_LR] = cpu->pc & ~((PPC_IC_ENTRIES_PER_PAGE-1) << 2);  
         cpu->cd.ppc.spr[SPR_LR] += (low_pc << 2);  
565    
566          cpu->cd.ppc.next_ic = (struct ppc_instr_call *) ic->arg[0];          cpu->cd.ppc.next_ic = (struct ppc_instr_call *) ic->arg[0];
567    
568          /*  Calculate new PC (for the trace)  */          /*  Calculate new PC (for the trace)  */
569          low_pc = ((size_t)cpu->cd.ppc.next_ic - (size_t)          low_pc = ((size_t)cpu->cd.ppc.next_ic - (size_t)
570              cpu->cd.ppc.cur_ic_page) / sizeof(struct ppc_instr_call);              cpu->cd.ppc.cur_ic_page) / sizeof(struct ppc_instr_call);
571          cpu->pc &= ~((PPC_IC_ENTRIES_PER_PAGE-1) << 2);          cpu->pc &= ~((PPC_IC_ENTRIES_PER_PAGE-1) << PPC_INSTR_ALIGNMENT_SHIFT);
572          cpu->pc += (low_pc << 2);          cpu->pc += (low_pc << PPC_INSTR_ALIGNMENT_SHIFT);
573          cpu_functioncall_trace(cpu, cpu->pc);          cpu_functioncall_trace(cpu, cpu->pc);
574  }  }
575    
# Line 704  X(cmpw) Line 711  X(cmpw)
711          cpu->cd.ppc.cr &= ~(0xf << bf_shift);          cpu->cd.ppc.cr &= ~(0xf << bf_shift);
712          cpu->cd.ppc.cr |= (c << bf_shift);          cpu->cd.ppc.cr |= (c << bf_shift);
713  }  }
714    X(cmpw_cr0)
715    {
716            /*  arg[2] is assumed to be 28  */
717            int32_t tmp = reg(ic->arg[0]), tmp2 = reg(ic->arg[1]);
718            cpu->cd.ppc.cr &= ~(0xf0000000);
719            if (tmp < tmp2)
720                    cpu->cd.ppc.cr |= 0x80000000;
721            else if (tmp > tmp2)
722                    cpu->cd.ppc.cr |= 0x40000000;
723            else
724                    cpu->cd.ppc.cr |= 0x20000000;
725            cpu->cd.ppc.cr |= ((cpu->cd.ppc.spr[SPR_XER] >> 3) & 0x10000000);
726    }
727    
728    
729  /*  /*
# Line 752  X(cmpwi) Line 772  X(cmpwi)
772          cpu->cd.ppc.cr &= ~(0xf << bf_shift);          cpu->cd.ppc.cr &= ~(0xf << bf_shift);
773          cpu->cd.ppc.cr |= (c << bf_shift);          cpu->cd.ppc.cr |= (c << bf_shift);
774  }  }
775    X(cmpwi_cr0)
776    {
777            /*  arg[2] is assumed to be 28  */
778            int32_t tmp = reg(ic->arg[0]), imm = ic->arg[1];
779            cpu->cd.ppc.cr &= ~(0xf0000000);
780            if (tmp < imm)
781                    cpu->cd.ppc.cr |= 0x80000000;
782            else if (tmp > imm)
783                    cpu->cd.ppc.cr |= 0x40000000;
784            else
785                    cpu->cd.ppc.cr |= 0x20000000;
786            cpu->cd.ppc.cr |= ((cpu->cd.ppc.spr[SPR_XER] >> 3) & 0x10000000);
787    }
788    
789    
790  /*  /*
# Line 788  X(dcbz) Line 821  X(dcbz)
821  {  {
822          MODE_uint_t addr = reg(ic->arg[0]) + reg(ic->arg[1]);          MODE_uint_t addr = reg(ic->arg[0]) + reg(ic->arg[1]);
823          unsigned char cacheline[128];          unsigned char cacheline[128];
824          int cacheline_size = 1 << cpu->cd.ppc.cpu_type.dlinesize;          size_t cacheline_size = 1 << cpu->cd.ppc.cpu_type.dlinesize;
825          int cleared = 0;          size_t cleared = 0;
826    
827          /*  Synchronize the PC first:  */          /*  Synchronize the PC first:  */
828          cpu->pc = (cpu->pc & ~0xfff) + ic->arg[2];          cpu->pc = (cpu->pc & ~0xfff) + ic->arg[2];
# Line 797  X(dcbz) Line 830  X(dcbz)
830          addr &= ~(cacheline_size - 1);          addr &= ~(cacheline_size - 1);
831          memset(cacheline, 0, sizeof(cacheline));          memset(cacheline, 0, sizeof(cacheline));
832    
         /*  TODO: Don't use memory_rw() unless it is necessary.  */  
833          while (cleared < cacheline_size) {          while (cleared < cacheline_size) {
834                  int to_clear = cacheline_size < sizeof(cacheline)?                  int to_clear = cacheline_size < sizeof(cacheline)?
835                      cacheline_size : sizeof(cacheline);                      cacheline_size : sizeof(cacheline);
836                  if (cpu->memory_rw(cpu, cpu->mem, addr, cacheline, to_clear,  #ifdef MODE32
837                      MEM_WRITE, CACHE_DATA) != MEMORY_ACCESS_OK) {                  unsigned char *page = cpu->cd.ppc.host_store[addr >> 12];
838                    if (page != NULL) {
839                            memset(page + (addr & 0xfff), 0, to_clear);
840                    } else
841    #endif
842                    if (cpu->memory_rw(cpu, cpu->mem, addr, cacheline,
843                        to_clear, MEM_WRITE, CACHE_DATA) != MEMORY_ACCESS_OK) {
844                          /*  exception  */                          /*  exception  */
845                          return;                          return;
846                  }                  }
# Line 821  X(dcbz) Line 859  X(dcbz)
859   */   */
860  X(mtfsf)  X(mtfsf)
861  {  {
862          /*  Sync. PC in case of an exception:  */          CHECK_FOR_FPU_EXCEPTION;
         uint64_t low_pc = ((size_t)ic - (size_t)  
             cpu->cd.ppc.cur_ic_page) / sizeof(struct ppc_instr_call);  
         cpu->pc = (cpu->pc & ~((PPC_IC_ENTRIES_PER_PAGE-1) << 2))  
             + (low_pc << 2);  
         if (!(cpu->cd.ppc.msr & PPC_MSR_FP)) {  
                 ppc_exception(cpu, PPC_EXCEPTION_FPU);  
                 return;  
         }  
   
863          cpu->cd.ppc.fpscr &= ~ic->arg[1];          cpu->cd.ppc.fpscr &= ~ic->arg[1];
864          cpu->cd.ppc.fpscr |= (ic->arg[1] & (*(uint64_t *)ic->arg[0]));          cpu->cd.ppc.fpscr |= (ic->arg[1] & (*(uint64_t *)ic->arg[0]));
865  }  }
# Line 843  X(mtfsf) Line 872  X(mtfsf)
872   */   */
873  X(mffs)  X(mffs)
874  {  {
875          /*  Sync. PC in case of an exception:  */          CHECK_FOR_FPU_EXCEPTION;
         uint64_t low_pc = ((size_t)ic - (size_t)  
             cpu->cd.ppc.cur_ic_page) / sizeof(struct ppc_instr_call);  
         cpu->pc = (cpu->pc & ~((PPC_IC_ENTRIES_PER_PAGE-1) << 2)) + (low_pc<<2);  
         if (!(cpu->cd.ppc.msr & PPC_MSR_FP)) {  
                 ppc_exception(cpu, PPC_EXCEPTION_FPU);  
                 return;  
         }  
   
876          (*(uint64_t *)ic->arg[0]) = cpu->cd.ppc.fpscr;          (*(uint64_t *)ic->arg[0]) = cpu->cd.ppc.fpscr;
877  }  }
878    
# Line 864  X(mffs) Line 885  X(mffs)
885   */   */
886  X(fmr)  X(fmr)
887  {  {
888          /*  Sync. PC in case of an exception:  */          /*
889          uint64_t low_pc = ((size_t)ic - (size_t)           *  This works like a normal register to register copy, but
890              cpu->cd.ppc.cur_ic_page) / sizeof(struct ppc_instr_call);           *  a) it can cause an FPU exception, and b) the move is always
891          cpu->pc = (cpu->pc & ~((PPC_IC_ENTRIES_PER_PAGE-1) << 2)) + (low_pc<<2);           *  64-bit, even when running in 32-bit mode.
892          if (!(cpu->cd.ppc.msr & PPC_MSR_FP)) {           */
893                  ppc_exception(cpu, PPC_EXCEPTION_FPU);          CHECK_FOR_FPU_EXCEPTION;
                 return;  
         }  
   
894          *(uint64_t *)ic->arg[1] = *(uint64_t *)ic->arg[0];          *(uint64_t *)ic->arg[1] = *(uint64_t *)ic->arg[0];
895  }  }
896    
# Line 886  X(fmr) Line 904  X(fmr)
904  X(fneg)  X(fneg)
905  {  {
906          uint64_t v;          uint64_t v;
907            CHECK_FOR_FPU_EXCEPTION;
         /*  Sync. PC in case of an exception:  */  
         uint64_t low_pc = ((size_t)ic - (size_t)  
             cpu->cd.ppc.cur_ic_page) / sizeof(struct ppc_instr_call);  
         cpu->pc = (cpu->pc & ~((PPC_IC_ENTRIES_PER_PAGE-1) << 2)) + (low_pc<<2);  
         if (!(cpu->cd.ppc.msr & PPC_MSR_FP)) {  
                 ppc_exception(cpu, PPC_EXCEPTION_FPU);  
                 return;  
         }  
   
908          v = *(uint64_t *)ic->arg[0];          v = *(uint64_t *)ic->arg[0];
909          *(uint64_t *)ic->arg[1] = v ^ 0x8000000000000000ULL;          *(uint64_t *)ic->arg[1] = v ^ 0x8000000000000000ULL;
910  }  }
# Line 913  X(fcmpu) Line 922  X(fcmpu)
922          struct ieee_float_value fra, frb;          struct ieee_float_value fra, frb;
923          int bf_shift = ic->arg[0], c = 0;          int bf_shift = ic->arg[0], c = 0;
924    
925          /*  Sync. PC in case of an exception:  */          CHECK_FOR_FPU_EXCEPTION;
         uint64_t low_pc = ((size_t)ic - (size_t)  
             cpu->cd.ppc.cur_ic_page) / sizeof(struct ppc_instr_call);  
         cpu->pc = (cpu->pc & ~((PPC_IC_ENTRIES_PER_PAGE-1) << 2)) + (low_pc<<2);  
         if (!(cpu->cd.ppc.msr & PPC_MSR_FP)) {  
                 ppc_exception(cpu, PPC_EXCEPTION_FPU);  
                 return;  
         }  
926    
927          ieee_interpret_float_value(*(uint64_t *)ic->arg[1], &fra, IEEE_FMT_D);          ieee_interpret_float_value(*(uint64_t *)ic->arg[1], &fra, IEEE_FMT_D);
928          ieee_interpret_float_value(*(uint64_t *)ic->arg[2], &frb, IEEE_FMT_D);          ieee_interpret_float_value(*(uint64_t *)ic->arg[2], &frb, IEEE_FMT_D);
# Line 954  X(frsp) Line 956  X(frsp)
956          float fl = 0.0;          float fl = 0.0;
957          int c = 0;          int c = 0;
958    
959          /*  Sync. PC in case of an exception:  */          CHECK_FOR_FPU_EXCEPTION;
         uint64_t low_pc = ((size_t)ic - (size_t)  
             cpu->cd.ppc.cur_ic_page) / sizeof(struct ppc_instr_call);  
         cpu->pc = (cpu->pc & ~((PPC_IC_ENTRIES_PER_PAGE-1) << 2)) + (low_pc<<2);  
         if (!(cpu->cd.ppc.msr & PPC_MSR_FP)) {  
                 ppc_exception(cpu, PPC_EXCEPTION_FPU);  
                 return;  
         }  
960    
961          ieee_interpret_float_value(*(uint64_t *)ic->arg[0], &frb, IEEE_FMT_D);          ieee_interpret_float_value(*(uint64_t *)ic->arg[0], &frb, IEEE_FMT_D);
962          if (frb.nan) {          if (frb.nan) {
# Line 992  X(frsp) Line 987  X(frsp)
987  X(fctiwz)  X(fctiwz)
988  {  {
989          struct ieee_float_value frb;          struct ieee_float_value frb;
990          int32_t res = 0;          uint32_t res = 0;
991    
992          /*  Sync. PC in case of an exception:  */          CHECK_FOR_FPU_EXCEPTION;
         uint64_t low_pc = ((size_t)ic - (size_t)  
             cpu->cd.ppc.cur_ic_page) / sizeof(struct ppc_instr_call);  
         cpu->pc = (cpu->pc & ~((PPC_IC_ENTRIES_PER_PAGE-1) << 2)) + (low_pc<<2);  
         if (!(cpu->cd.ppc.msr & PPC_MSR_FP)) {  
                 ppc_exception(cpu, PPC_EXCEPTION_FPU);  
                 return;  
         }  
993    
994          ieee_interpret_float_value(*(uint64_t *)ic->arg[0], &frb, IEEE_FMT_D);          ieee_interpret_float_value(*(uint64_t *)ic->arg[0], &frb, IEEE_FMT_D);
995          if (!frb.nan) {          if (!frb.nan) {
# Line 1030  X(fmul) Line 1018  X(fmul)
1018          double result = 0.0;          double result = 0.0;
1019          int c, nan = 0;          int c, nan = 0;
1020    
1021          /*  Sync. PC in case of an exception:  */          CHECK_FOR_FPU_EXCEPTION;
         uint64_t low_pc = ((size_t)ic - (size_t)  
             cpu->cd.ppc.cur_ic_page) / sizeof(struct ppc_instr_call);  
         cpu->pc = (cpu->pc & ~((PPC_IC_ENTRIES_PER_PAGE-1) << 2))  
             + (low_pc << 2);  
         if (!(cpu->cd.ppc.msr & PPC_MSR_FP)) {  
                 ppc_exception(cpu, PPC_EXCEPTION_FPU);  
                 return;  
         }  
1022    
1023          ieee_interpret_float_value(*(uint64_t *)ic->arg[1], &fra, IEEE_FMT_D);          ieee_interpret_float_value(*(uint64_t *)ic->arg[1], &fra, IEEE_FMT_D);
1024          ieee_interpret_float_value(*(uint64_t *)ic->arg[2], &frc, IEEE_FMT_D);          ieee_interpret_float_value(*(uint64_t *)ic->arg[2], &frc, IEEE_FMT_D);
# Line 1087  X(fmadd) Line 1067  X(fmadd)
1067          double result = 0.0;          double result = 0.0;
1068          int nan = 0, cc;          int nan = 0, cc;
1069    
1070          /*  Sync. PC in case of an exception:  */          CHECK_FOR_FPU_EXCEPTION;
         uint64_t low_pc = ((size_t)ic - (size_t)  
             cpu->cd.ppc.cur_ic_page) / sizeof(struct ppc_instr_call);  
         cpu->pc = (cpu->pc & ~((PPC_IC_ENTRIES_PER_PAGE-1) << 2))  
             + (low_pc << 2);  
         if (!(cpu->cd.ppc.msr & PPC_MSR_FP)) {  
                 ppc_exception(cpu, PPC_EXCEPTION_FPU);  
                 return;  
         }  
1071    
1072          ieee_interpret_float_value(*(uint64_t *)ic->arg[1], &fra, IEEE_FMT_D);          ieee_interpret_float_value(*(uint64_t *)ic->arg[1], &fra, IEEE_FMT_D);
1073          ieee_interpret_float_value(cpu->cd.ppc.fpr[b], &frb, IEEE_FMT_D);          ieee_interpret_float_value(cpu->cd.ppc.fpr[b], &frb, IEEE_FMT_D);
# Line 1140  X(fmsub) Line 1112  X(fmsub)
1112          double result = 0.0;          double result = 0.0;
1113          int nan = 0, cc;          int nan = 0, cc;
1114    
1115          /*  Sync. PC in case of an exception:  */          CHECK_FOR_FPU_EXCEPTION;
         uint64_t low_pc = ((size_t)ic - (size_t)  
             cpu->cd.ppc.cur_ic_page) / sizeof(struct ppc_instr_call);  
         cpu->pc = (cpu->pc & ~((PPC_IC_ENTRIES_PER_PAGE-1) << 2))  
             + (low_pc << 2);  
         if (!(cpu->cd.ppc.msr & PPC_MSR_FP)) {  
                 ppc_exception(cpu, PPC_EXCEPTION_FPU);  
                 return;  
         }  
1116    
1117          ieee_interpret_float_value(*(uint64_t *)ic->arg[1], &fra, IEEE_FMT_D);          ieee_interpret_float_value(*(uint64_t *)ic->arg[1], &fra, IEEE_FMT_D);
1118          ieee_interpret_float_value(cpu->cd.ppc.fpr[b], &frb, IEEE_FMT_D);          ieee_interpret_float_value(cpu->cd.ppc.fpr[b], &frb, IEEE_FMT_D);
# Line 1190  X(fadd) Line 1154  X(fadd)
1154          double result = 0.0;          double result = 0.0;
1155          int nan = 0, c;          int nan = 0, c;
1156    
1157          /*  Sync. PC in case of an exception:  */          CHECK_FOR_FPU_EXCEPTION;
         uint64_t low_pc = ((size_t)ic - (size_t)  
             cpu->cd.ppc.cur_ic_page) / sizeof(struct ppc_instr_call);  
         cpu->pc = (cpu->pc & ~((PPC_IC_ENTRIES_PER_PAGE-1) << 2))  
             + (low_pc << 2);  
         if (!(cpu->cd.ppc.msr & PPC_MSR_FP)) {  
                 ppc_exception(cpu, PPC_EXCEPTION_FPU);  
                 return;  
         }  
1158    
1159          ieee_interpret_float_value(*(uint64_t *)ic->arg[0], &fra, IEEE_FMT_D);          ieee_interpret_float_value(*(uint64_t *)ic->arg[0], &fra, IEEE_FMT_D);
1160          ieee_interpret_float_value(*(uint64_t *)ic->arg[1], &frb, IEEE_FMT_D);          ieee_interpret_float_value(*(uint64_t *)ic->arg[1], &frb, IEEE_FMT_D);
# Line 1235  X(fsub) Line 1191  X(fsub)
1191          double result = 0.0;          double result = 0.0;
1192          int nan = 0, c;          int nan = 0, c;
1193    
1194          /*  Sync. PC in case of an exception:  */          CHECK_FOR_FPU_EXCEPTION;
         uint64_t low_pc = ((size_t)ic - (size_t)  
             cpu->cd.ppc.cur_ic_page) / sizeof(struct ppc_instr_call);  
         cpu->pc = (cpu->pc & ~((PPC_IC_ENTRIES_PER_PAGE-1) << 2)) + (low_pc<<2);  
         if (!(cpu->cd.ppc.msr & PPC_MSR_FP)) {  
                 ppc_exception(cpu, PPC_EXCEPTION_FPU);  
                 return;  
         }  
1195    
1196          ieee_interpret_float_value(*(uint64_t *)ic->arg[0], &fra, IEEE_FMT_D);          ieee_interpret_float_value(*(uint64_t *)ic->arg[0], &fra, IEEE_FMT_D);
1197          ieee_interpret_float_value(*(uint64_t *)ic->arg[1], &frb, IEEE_FMT_D);          ieee_interpret_float_value(*(uint64_t *)ic->arg[1], &frb, IEEE_FMT_D);
# Line 1279  X(fdiv) Line 1228  X(fdiv)
1228          double result = 0.0;          double result = 0.0;
1229          int nan = 0, c;          int nan = 0, c;
1230    
1231          /*  Sync. PC in case of an exception:  */          CHECK_FOR_FPU_EXCEPTION;
         uint64_t low_pc = ((size_t)ic - (size_t)  
             cpu->cd.ppc.cur_ic_page) / sizeof(struct ppc_instr_call);  
         cpu->pc = (cpu->pc & ~((PPC_IC_ENTRIES_PER_PAGE-1) << 2)) + (low_pc<<2);  
         if (!(cpu->cd.ppc.msr & PPC_MSR_FP)) {  
                 ppc_exception(cpu, PPC_EXCEPTION_FPU);  
                 return;  
         }  
1232    
1233          ieee_interpret_float_value(*(uint64_t *)ic->arg[0], &fra, IEEE_FMT_D);          ieee_interpret_float_value(*(uint64_t *)ic->arg[0], &fra, IEEE_FMT_D);
1234          ieee_interpret_float_value(*(uint64_t *)ic->arg[1], &frb, IEEE_FMT_D);          ieee_interpret_float_value(*(uint64_t *)ic->arg[1], &frb, IEEE_FMT_D);
# Line 1420  X(llsc) Line 1362  X(llsc)
1362    
1363    
1364  /*  /*
1365   *  mtsr:  Move To Segment Register   *  mtsr, mtsrin:  Move To Segment Register [Indirect]
1366   *   *
1367   *  arg[0] = sr number, or for indirect mode: ptr to rb   *  arg[0] = sr number, or for indirect mode: ptr to rb
1368   *  arg[1] = ptr to rt   *  arg[1] = ptr to rt
1369     *
1370     *  TODO: These only work for 32-bit mode!
1371   */   */
1372  X(mtsr)  X(mtsr)
1373  {  {
1374          /*  TODO: This only works for 32-bit mode  */          int sr_num = ic->arg[0];
1375          cpu->cd.ppc.sr[ic->arg[0]] = reg(ic->arg[1]);          uint32_t old = cpu->cd.ppc.sr[sr_num];
1376            cpu->cd.ppc.sr[sr_num] = reg(ic->arg[1]);
1377    
1378          cpu->invalidate_translation_caches(cpu, 0, INVALIDATE_ALL);          if (cpu->cd.ppc.sr[sr_num] != old)
1379                    cpu->invalidate_translation_caches(cpu, ic->arg[0] << 28,
1380                        INVALIDATE_ALL | INVALIDATE_VADDR_UPPER4);
1381  }  }
1382  X(mtsrin)  X(mtsrin)
1383  {  {
1384          /*  TODO: This only works for 32-bit mode  */          int sr_num = reg(ic->arg[0]) >> 28;
1385          uint32_t sr_num = reg(ic->arg[0]) >> 28;          uint32_t old = cpu->cd.ppc.sr[sr_num];
1386          cpu->cd.ppc.sr[sr_num] = reg(ic->arg[1]);          cpu->cd.ppc.sr[sr_num] = reg(ic->arg[1]);
1387    
1388          cpu->invalidate_translation_caches(cpu, 0, INVALIDATE_ALL);          if (cpu->cd.ppc.sr[sr_num] != old)
1389                    cpu->invalidate_translation_caches(cpu, sr_num << 28,
1390                        INVALIDATE_ALL | INVALIDATE_VADDR_UPPER4);
1391  }  }
1392    
1393    
# Line 1462  X(mfsrin) Line 1411  X(mfsrin)
1411    
1412    
1413  /*  /*
1414     *  rldicl:
1415     *
1416     *  arg[0] = copy of the instruction word
1417     */
1418    X(rldicl)
1419    {
1420            int rs = (ic->arg[0] >> 21) & 31;
1421            int ra = (ic->arg[0] >> 16) & 31;
1422            int sh = ((ic->arg[0] >> 11) & 31) | ((ic->arg[0] & 2) << 4);
1423            int mb = ((ic->arg[0] >> 6) & 31) | (ic->arg[0] & 0x20);
1424            int rc = ic->arg[0] & 1;
1425            uint64_t tmp = cpu->cd.ppc.gpr[rs], tmp2;
1426            /*  TODO: Fix this, its performance is awful:  */
1427            while (sh-- != 0) {
1428                    int b = (tmp >> 63) & 1;
1429                    tmp = (tmp << 1) | b;
1430            }
1431            tmp2 = 0;
1432            while (mb <= 63) {
1433                    tmp |= ((uint64_t)1 << (63-mb));
1434                    mb ++;
1435            }
1436            cpu->cd.ppc.gpr[ra] = tmp & tmp2;
1437            if (rc)
1438                    update_cr0(cpu, cpu->cd.ppc.gpr[ra]);
1439    }
1440    
1441    
1442    /*
1443   *  rldicr:   *  rldicr:
1444   *   *
1445   *  arg[0] = copy of the instruction word   *  arg[0] = copy of the instruction word
# Line 1488  X(rldicr) Line 1466  X(rldicr)
1466    
1467    
1468  /*  /*
1469     *  rldimi:
1470     *
1471     *  arg[0] = copy of the instruction word
1472     */
1473    X(rldimi)
1474    {
1475            uint32_t iw = ic->arg[0];
1476            int rs = (iw >> 21) & 31, ra = (iw >> 16) & 31;
1477            int sh = ((iw >> 11) & 31) | ((iw & 2) << 4);
1478            int mb = ((iw >> 6) & 31) | (iw & 0x20);
1479            int rc = ic->arg[0] & 1;
1480            int m;
1481            uint64_t tmp, s = cpu->cd.ppc.gpr[rs];
1482            /*  TODO: Fix this, its performance is awful:  */
1483            while (sh-- != 0) {
1484                    int b = (s >> 63) & 1;
1485                    s = (s << 1) | b;
1486            }
1487            m = mb; tmp = 0;
1488            do {
1489                    tmp |= ((uint64_t)1 << (63-m));
1490                    m ++;
1491            } while (m != 63 - sh);
1492            cpu->cd.ppc.gpr[ra] &= ~tmp;
1493            cpu->cd.ppc.gpr[ra] |= (tmp & s);
1494            if (rc)
1495                    update_cr0(cpu, cpu->cd.ppc.gpr[ra]);
1496    }
1497    
1498    
1499    /*
1500   *  rlwnm:   *  rlwnm:
1501   *   *
1502   *  arg[0] = ptr to ra   *  arg[0] = ptr to ra
# Line 1647  X(cror) { Line 1656  X(cror) {
1656          if (ba | bb)          if (ba | bb)
1657                  cpu->cd.ppc.cr |= (1 << (31-bt));                  cpu->cd.ppc.cr |= (1 << (31-bt));
1658  }  }
1659    X(crorc) {
1660            uint32_t iword = ic->arg[0]; int bt = (iword >> 21) & 31;
1661            int ba = (iword >> 16) & 31, bb = (iword >> 11) & 31;
1662            ba = (cpu->cd.ppc.cr >> (31-ba)) & 1;
1663            bb = (cpu->cd.ppc.cr >> (31-bb)) & 1;
1664            cpu->cd.ppc.cr &= ~(1 << (31-bt));
1665            if (!(ba | bb))
1666                    cpu->cd.ppc.cr |= (1 << (31-bt));
1667    }
1668  X(crnor) {  X(crnor) {
1669          uint32_t iword = ic->arg[0]; int bt = (iword >> 21) & 31;          uint32_t iword = ic->arg[0]; int bt = (iword >> 21) & 31;
1670          int ba = (iword >> 16) & 31, bb = (iword >> 11) & 31;          int ba = (iword >> 16) & 31, bb = (iword >> 11) & 31;
# Line 1674  X(crxor) { Line 1692  X(crxor) {
1692   *  arg[1] = pointer to source SPR   *  arg[1] = pointer to source SPR
1693   */   */
1694  X(mfspr) {  X(mfspr) {
1695            /*  TODO: Check permission  */
1696          reg(ic->arg[0]) = reg(ic->arg[1]);          reg(ic->arg[0]) = reg(ic->arg[1]);
1697  }  }
1698  X(mfspr_pmc1) {  X(mfspr_pmc1) {
# Line 1702  X(mftbu) { Line 1721  X(mftbu) {
1721   *  arg[1] = pointer to the SPR   *  arg[1] = pointer to the SPR
1722   */   */
1723  X(mtspr) {  X(mtspr) {
1724            /*  TODO: Check permission  */
1725          reg(ic->arg[1]) = reg(ic->arg[0]);          reg(ic->arg[1]) = reg(ic->arg[0]);
1726  }  }
1727    X(mtlr) {
1728            cpu->cd.ppc.spr[SPR_LR] = reg(ic->arg[0]);
1729    }
1730    X(mtctr) {
1731            cpu->cd.ppc.spr[SPR_CTR] = reg(ic->arg[0]);
1732    }
1733    
1734    
1735  /*  /*
1736   *  rfi:  Return from Interrupt   *  rfi[d]:  Return from Interrupt
1737   */   */
1738  X(rfi)  X(rfi)
1739  {  {
# Line 1719  X(rfi) Line 1745  X(rfi)
1745          reg_access_msr(cpu, &tmp, 1, 0);          reg_access_msr(cpu, &tmp, 1, 0);
1746    
1747          cpu->pc = cpu->cd.ppc.spr[SPR_SRR0];          cpu->pc = cpu->cd.ppc.spr[SPR_SRR0];
1748          DYNTRANS_PC_TO_POINTERS(cpu);          quick_pc_to_pointers(cpu);
1749    }
1750    X(rfid)
1751    {
1752            uint64_t tmp, mask = 0x800000000000ff73ULL;
1753    
1754            reg_access_msr(cpu, &tmp, 0, 0);
1755            tmp &= ~mask;
1756            tmp |= (cpu->cd.ppc.spr[SPR_SRR1] & mask);
1757            reg_access_msr(cpu, &tmp, 1, 0);
1758    
1759            cpu->pc = cpu->cd.ppc.spr[SPR_SRR0];
1760            if (!(tmp & PPC_MSR_SF))
1761                    cpu->pc = (uint32_t)cpu->pc;
1762            quick_pc_to_pointers(cpu);
1763  }  }
1764    
1765    
# Line 1749  X(mfmsr) Line 1789  X(mfmsr)
1789   *  mtmsr:  Move To MSR   *  mtmsr:  Move To MSR
1790   *   *
1791   *  arg[0] = pointer to source register   *  arg[0] = pointer to source register
1792     *  arg[1] = page offset of the next instruction
1793     *  arg[2] = 0 for 32-bit (mtmsr), 1 for 64-bit (mtmsrd)
1794   */   */
1795  X(mtmsr)  X(mtmsr)
1796  {  {
1797            MODE_uint_t old_pc;
1798            uint64_t x = reg(ic->arg[0]);
1799    
1800            /*  TODO: check permission!  */
1801    
1802            /*  Synchronize the PC (pointing to _after_ this instruction)  */
1803            cpu->pc = (cpu->pc & ~0xfff) + ic->arg[1];
1804            old_pc = cpu->pc;
1805    
1806            if (!ic->arg[2]) {
1807                    uint64_t y;
1808                    reg_access_msr(cpu, &y, 0, 0);
1809                    x = (y & 0xffffffff00000000ULL) | (x & 0xffffffffULL);
1810            }
1811    
1812            reg_access_msr(cpu, &x, 1, 1);
1813    
1814            /*
1815             *  Super-ugly hack:  If the pc wasn't changed (i.e. if there was no
1816             *  exception while accessing the msr), then we _decrease_ the PC by 4
1817             *  again. This is because the next ic could be an end_of_page.
1818             */
1819            if ((MODE_uint_t)cpu->pc == old_pc)
1820                    cpu->pc -= 4;
1821    }
1822    
1823    
1824    /*
1825     *  wrteei:  Write EE immediate  (on PPC405GP)
1826     *
1827     *  arg[0] = either 0 or 0x8000
1828     */
1829    X(wrteei)
1830    {
1831            /*  TODO: check permission!  */
1832            uint64_t x;
1833    
1834          /*  Synchronize the PC (pointing to _after_ this instruction)  */          /*  Synchronize the PC (pointing to _after_ this instruction)  */
1835          cpu->pc = (cpu->pc & ~0xfff) + ic->arg[1];          cpu->pc = (cpu->pc & ~0xfff) + ic->arg[1];
1836    
1837          reg_access_msr(cpu, (uint64_t*)ic->arg[0], 1, 1);          reg_access_msr(cpu, &x, 0, 0);
1838            x = (x & ~0x8000) | ic->arg[0];
1839            reg_access_msr(cpu, &x, 1, 1);
1840  }  }
1841    
1842    
# Line 1950  X(extsh) { Line 2031  X(extsh) {
2031  DOT2(extsh)  DOT2(extsh)
2032  X(extsw) {  X(extsw) {
2033  #ifdef MODE32  #ifdef MODE32
2034          fatal("TODO: extsw: invalid instruction\n"); exit(1);          fatal("TODO: extsw: invalid instruction\n");
2035  #else  #else
2036          reg(ic->arg[2]) = (int64_t)(int32_t)reg(ic->arg[0]);          reg(ic->arg[2]) = (int64_t)(int32_t)reg(ic->arg[0]);
2037  #endif  #endif
# Line 1959  DOT2(extsw) Line 2040  DOT2(extsw)
2040  X(slw) {        reg(ic->arg[2]) = (uint64_t)reg(ic->arg[0])  X(slw) {        reg(ic->arg[2]) = (uint64_t)reg(ic->arg[0])
2041                      << (reg(ic->arg[1]) & 31); }                      << (reg(ic->arg[1]) & 31); }
2042  DOT2(slw)  DOT2(slw)
2043    X(sld) {int sa = reg(ic->arg[1]) & 127;
2044            if (sa >= 64)   reg(ic->arg[2]) = 0;
2045            else reg(ic->arg[2]) = (uint64_t)reg(ic->arg[0]) << (sa & 63); }
2046    DOT2(sld)
2047  X(sraw)  X(sraw)
2048  {  {
2049          uint32_t tmp = reg(ic->arg[0]);          uint32_t tmp = reg(ic->arg[0]);
# Line 1990  X(andc) {      reg(ic->arg[2]) = reg(ic->arg[ Line 2075  X(andc) {      reg(ic->arg[2]) = reg(ic->arg[
2075  DOT2(andc)  DOT2(andc)
2076  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])); }
2077  DOT2(nor)  DOT2(nor)
2078    X(mr) {         reg(ic->arg[2]) = reg(ic->arg[1]); }
2079  X(or) {         reg(ic->arg[2]) = reg(ic->arg[0]) | reg(ic->arg[1]); }  X(or) {         reg(ic->arg[2]) = reg(ic->arg[0]) | reg(ic->arg[1]); }
2080  DOT2(or)  DOT2(or)
2081  X(orc) {        reg(ic->arg[2]) = reg(ic->arg[0]) | (~reg(ic->arg[1])); }  X(orc) {        reg(ic->arg[2]) = reg(ic->arg[0]) | (~reg(ic->arg[1])); }
2082  DOT2(orc)  DOT2(orc)
2083  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]); }
2084  DOT2(xor)  DOT2(xor)
2085    X(eqv) {        reg(ic->arg[2]) = ~(reg(ic->arg[0]) ^ reg(ic->arg[1])); }
2086    DOT2(eqv)
2087    
2088    
2089  /*  /*
# Line 2230  X(xori) { reg(ic->arg[2]) = reg(ic->arg[ Line 2318  X(xori) { reg(ic->arg[2]) = reg(ic->arg[
2318   */   */
2319  X(lfs)  X(lfs)
2320  {  {
2321          /*  Sync. PC in case of an exception:  */          /*  Sync. PC in case of an exception, and remember it:  */
2322          uint64_t old_pc, low_pc = ((size_t)ic - (size_t)          uint64_t old_pc, low_pc = ((size_t)ic - (size_t)
2323              cpu->cd.ppc.cur_ic_page) / sizeof(struct ppc_instr_call);              cpu->cd.ppc.cur_ic_page) / sizeof(struct ppc_instr_call);
2324          old_pc = cpu->pc = (cpu->pc & ~((PPC_IC_ENTRIES_PER_PAGE-1) << 2))          old_pc = cpu->pc = (cpu->pc & ~((PPC_IC_ENTRIES_PER_PAGE-1) <<
2325              + (low_pc << 2);              PPC_INSTR_ALIGNMENT_SHIFT)) + (low_pc << PPC_INSTR_ALIGNMENT_SHIFT);
2326          if (!(cpu->cd.ppc.msr & PPC_MSR_FP)) {          if (!(cpu->cd.ppc.msr & PPC_MSR_FP)) {
2327                  ppc_exception(cpu, PPC_EXCEPTION_FPU);                  ppc_exception(cpu, PPC_EXCEPTION_FPU);
2328                  return;                  return;
# Line 2260  X(lfs) Line 2348  X(lfs)
2348  }  }
2349  X(lfsx)  X(lfsx)
2350  {  {
2351          /*  Sync. PC in case of an exception:  */          /*  Sync. PC in case of an exception, and remember it:  */
2352          uint64_t old_pc, low_pc = ((size_t)ic - (size_t)          uint64_t old_pc, low_pc = ((size_t)ic - (size_t)
2353              cpu->cd.ppc.cur_ic_page) / sizeof(struct ppc_instr_call);              cpu->cd.ppc.cur_ic_page) / sizeof(struct ppc_instr_call);
2354          old_pc = cpu->pc = (cpu->pc & ~((PPC_IC_ENTRIES_PER_PAGE-1) << 2))          old_pc = cpu->pc = (cpu->pc & ~((PPC_IC_ENTRIES_PER_PAGE-1) <<
2355              + (low_pc << 2);              PPC_INSTR_ALIGNMENT_SHIFT)) + (low_pc << PPC_INSTR_ALIGNMENT_SHIFT);
2356          if (!(cpu->cd.ppc.msr & PPC_MSR_FP)) {          if (!(cpu->cd.ppc.msr & PPC_MSR_FP)) {
2357                  ppc_exception(cpu, PPC_EXCEPTION_FPU);                  ppc_exception(cpu, PPC_EXCEPTION_FPU);
2358                  return;                  return;
# Line 2290  X(lfsx) Line 2378  X(lfsx)
2378  }  }
2379  X(lfd)  X(lfd)
2380  {  {
2381          /*  Sync. PC in case of an exception:  */          CHECK_FOR_FPU_EXCEPTION;
         uint64_t low_pc = ((size_t)ic - (size_t)  
             cpu->cd.ppc.cur_ic_page) / sizeof(struct ppc_instr_call);  
         cpu->pc = (cpu->pc & ~((PPC_IC_ENTRIES_PER_PAGE-1) << 2)) + (low_pc<<2);  
         if (!(cpu->cd.ppc.msr & PPC_MSR_FP)) {  
                 ppc_exception(cpu, PPC_EXCEPTION_FPU);  
                 return;  
         }  
2382    
2383          /*  Perform a 64-bit load:  */          /*  Perform a 64-bit load:  */
2384  #ifdef MODE32  #ifdef MODE32
# Line 2309  X(lfd) Line 2390  X(lfd)
2390  }  }
2391  X(lfdx)  X(lfdx)
2392  {  {
2393          /*  Sync. PC in case of an exception:  */          CHECK_FOR_FPU_EXCEPTION;
2394          uint64_t low_pc = ((size_t)ic - (size_t)  
             cpu->cd.ppc.cur_ic_page) / sizeof(struct ppc_instr_call);  
         cpu->pc = (cpu->pc & ~((PPC_IC_ENTRIES_PER_PAGE-1) << 2)) + (low_pc<<2);  
         if (!(cpu->cd.ppc.msr & PPC_MSR_FP)) {  
                 ppc_exception(cpu, PPC_EXCEPTION_FPU);  
                 return;  
         }  
2395          /*  Perform a 64-bit load:  */          /*  Perform a 64-bit load:  */
2396  #ifdef MODE32  #ifdef MODE32
2397          ppc32_loadstore_indexed          ppc32_loadstore_indexed
# Line 2331  X(stfs) Line 2406  X(stfs)
2406          struct ieee_float_value val;          struct ieee_float_value val;
2407          uint64_t tmp_val;          uint64_t tmp_val;
2408    
2409          /*  Sync. PC in case of an exception:  */          CHECK_FOR_FPU_EXCEPTION;
         uint64_t low_pc = ((size_t)ic - (size_t)  
             cpu->cd.ppc.cur_ic_page) / sizeof(struct ppc_instr_call);  
         cpu->pc = (cpu->pc & ~((PPC_IC_ENTRIES_PER_PAGE-1) << 2)) + (low_pc<<2);  
         if (!(cpu->cd.ppc.msr & PPC_MSR_FP)) {  
                 ppc_exception(cpu, PPC_EXCEPTION_FPU);  
                 return;  
         }  
2410    
2411          ieee_interpret_float_value(*old_arg0, &val, IEEE_FMT_D);          ieee_interpret_float_value(*old_arg0, &val, IEEE_FMT_D);
2412          tmp_val = ieee_store_float_value(val.f, IEEE_FMT_S, val.nan);          tmp_val = ieee_store_float_value(val.f, IEEE_FMT_S, val.nan);
# Line 2361  X(stfsx) Line 2429  X(stfsx)
2429          struct ieee_float_value val;          struct ieee_float_value val;
2430          uint64_t tmp_val;          uint64_t tmp_val;
2431    
2432          /*  Sync. PC in case of an exception:  */          CHECK_FOR_FPU_EXCEPTION;
         uint64_t low_pc = ((size_t)ic - (size_t)  
             cpu->cd.ppc.cur_ic_page) / sizeof(struct ppc_instr_call);  
         cpu->pc = (cpu->pc & ~((PPC_IC_ENTRIES_PER_PAGE-1) << 2)) + (low_pc<<2);  
         if (!(cpu->cd.ppc.msr & PPC_MSR_FP)) {  
                 ppc_exception(cpu, PPC_EXCEPTION_FPU);  
                 return;  
         }  
2433    
2434          ieee_interpret_float_value(*old_arg0, &val, IEEE_FMT_D);          ieee_interpret_float_value(*old_arg0, &val, IEEE_FMT_D);
2435          tmp_val = ieee_store_float_value(val.f, IEEE_FMT_S, val.nan);          tmp_val = ieee_store_float_value(val.f, IEEE_FMT_S, val.nan);
# Line 2387  X(stfsx) Line 2448  X(stfsx)
2448  }  }
2449  X(stfd)  X(stfd)
2450  {  {
2451          /*  Sync. PC in case of an exception:  */          CHECK_FOR_FPU_EXCEPTION;
2452          uint64_t low_pc = ((size_t)ic - (size_t)  
             cpu->cd.ppc.cur_ic_page) / sizeof(struct ppc_instr_call);  
         cpu->pc = (cpu->pc & ~((PPC_IC_ENTRIES_PER_PAGE-1) << 2)) + (low_pc<<2);  
         if (!(cpu->cd.ppc.msr & PPC_MSR_FP)) {  
                 ppc_exception(cpu, PPC_EXCEPTION_FPU);  
                 return;  
         }  
2453          /*  Perform a 64-bit store:  */          /*  Perform a 64-bit store:  */
2454  #ifdef MODE32  #ifdef MODE32
2455          ppc32_loadstore          ppc32_loadstore
# Line 2405  X(stfd) Line 2460  X(stfd)
2460  }  }
2461  X(stfdx)  X(stfdx)
2462  {  {
2463          /*  Sync. PC in case of an exception:  */          CHECK_FOR_FPU_EXCEPTION;
2464          uint64_t low_pc = ((size_t)ic - (size_t)  
             cpu->cd.ppc.cur_ic_page) / sizeof(struct ppc_instr_call);  
         cpu->pc = (cpu->pc & ~((PPC_IC_ENTRIES_PER_PAGE-1) << 2)) + (low_pc<<2);  
         if (!(cpu->cd.ppc.msr & PPC_MSR_FP)) {  
                 ppc_exception(cpu, PPC_EXCEPTION_FPU);  
                 return;  
         }  
2465          /*  Perform a 64-bit store:  */          /*  Perform a 64-bit store:  */
2466  #ifdef MODE32  #ifdef MODE32
2467          ppc32_loadstore_indexed          ppc32_loadstore_indexed
# Line 2428  X(stfdx) Line 2477  X(stfdx)
2477   */   */
2478  X(tlbia)  X(tlbia)
2479  {  {
2480  printf("tlbia\n");          fatal("[ tlbia ]\n");
 exit(1);  
2481          cpu->invalidate_translation_caches(cpu, 0, INVALIDATE_ALL);          cpu->invalidate_translation_caches(cpu, 0, INVALIDATE_ALL);
2482  }  }
2483    
# Line 2439  exit(1); Line 2487  exit(1);
2487   */   */
2488  X(tlbie)  X(tlbie)
2489  {  {
2490            /*  fatal("[ tlbie ]\n");  */
2491          cpu->invalidate_translation_caches(cpu, reg(ic->arg[0]),          cpu->invalidate_translation_caches(cpu, reg(ic->arg[0]),
2492              INVALIDATE_VADDR);              INVALIDATE_VADDR);
2493  }  }
# Line 2453  X(sc) Line 2502  X(sc)
2502          cpu->pc = (cpu->pc & ~0xfff) + ic->arg[1];          cpu->pc = (cpu->pc & ~0xfff) + ic->arg[1];
2503    
2504          ppc_exception(cpu, PPC_EXCEPTION_SC);          ppc_exception(cpu, PPC_EXCEPTION_SC);
2505    
2506            /*  This caused an update to the PC register, so there is no need
2507                to worry about the next instruction being an end_of_page.  */
2508  }  }
2509    
2510    
# Line 2464  X(sc) Line 2516  X(sc)
2516  X(user_syscall)  X(user_syscall)
2517  {  {
2518          useremul_syscall(cpu, ic->arg[0]);          useremul_syscall(cpu, ic->arg[0]);
2519    
2520            if (!cpu->running) {
2521                    cpu->n_translated_instrs --;
2522                    cpu->cd.ppc.next_ic = &nothing_call;
2523            }
2524  }  }
2525    
2526    
# Line 2473  X(user_syscall) Line 2530  X(user_syscall)
2530  X(openfirmware)  X(openfirmware)
2531  {  {
2532          of_emul(cpu);          of_emul(cpu);
2533            if (cpu->running == 0) {
2534                    cpu->n_translated_instrs --;
2535                    cpu->cd.ppc.next_ic = &nothing_call;
2536            }
2537          cpu->pc = cpu->cd.ppc.spr[SPR_LR];          cpu->pc = cpu->cd.ppc.spr[SPR_LR];
2538          if (cpu->machine->show_trace_tree)          if (cpu->machine->show_trace_tree)
2539                  cpu_functioncall_trace_return(cpu);                  cpu_functioncall_trace_return(cpu);
2540          DYNTRANS_PC_TO_POINTERS(cpu);          quick_pc_to_pointers(cpu);
2541    }
2542    
2543    
2544    /*
2545     *  tlbsx_dot: TLB scan
2546     */
2547    X(tlbsx_dot)
2548    {
2549            /*  TODO  */
2550            cpu->cd.ppc.cr &= ~(0xf0000000);
2551            cpu->cd.ppc.cr |= 0x20000000;
2552            cpu->cd.ppc.cr |= ((cpu->cd.ppc.spr[SPR_XER] >> 3) & 0x10000000);
2553  }  }
2554    
2555    
# Line 2485  X(openfirmware) Line 2558  X(openfirmware)
2558   */   */
2559  X(tlbli)  X(tlbli)
2560  {  {
2561            fatal("tlbli\n");
2562            cpu->invalidate_translation_caches(cpu, 0, INVALIDATE_ALL);
2563  }  }
2564    
2565    
# Line 2496  X(tlbld) Line 2571  X(tlbld)
2571          /*  MODE_uint_t vaddr = reg(ic->arg[0]);          /*  MODE_uint_t vaddr = reg(ic->arg[0]);
2572              MODE_uint_t paddr = cpu->cd.ppc.spr[SPR_RPA];  */              MODE_uint_t paddr = cpu->cd.ppc.spr[SPR_RPA];  */
2573    
2574          /*  TODO?  */          fatal("tlbld\n");
2575            cpu->invalidate_translation_caches(cpu, 0, INVALIDATE_ALL);
2576  }  }
2577    
2578    
# Line 2506  X(tlbld) Line 2582  X(tlbld)
2582  X(end_of_page)  X(end_of_page)
2583  {  {
2584          /*  Update the PC:  (offset 0, but on the next page)  */          /*  Update the PC:  (offset 0, but on the next page)  */
2585          cpu->pc &= ~((PPC_IC_ENTRIES_PER_PAGE-1) << 2);          cpu->pc &= ~((PPC_IC_ENTRIES_PER_PAGE-1) << PPC_INSTR_ALIGNMENT_SHIFT);
2586          cpu->pc += (PPC_IC_ENTRIES_PER_PAGE << 2);          cpu->pc += (PPC_IC_ENTRIES_PER_PAGE << PPC_INSTR_ALIGNMENT_SHIFT);
2587    
2588          /*  Find the new physical page and update the translation pointers:  */          /*  Find the new physical page and update the translation pointers:  */
2589          DYNTRANS_PC_TO_POINTERS(cpu);          quick_pc_to_pointers(cpu);
2590    
2591          /*  end_of_page doesn't count as an executed instruction:  */          /*  end_of_page doesn't count as an executed instruction:  */
2592          cpu->n_translated_instrs --;          cpu->n_translated_instrs --;
# Line 2523  X(end_of_page) Line 2599  X(end_of_page)
2599  /*  /*
2600   *  ppc_instr_to_be_translated():   *  ppc_instr_to_be_translated():
2601   *   *
2602   *  Translate an instruction word into an ppc_instr_call. ic is filled in with   *  Translate an instruction word into a ppc_instr_call. ic is filled in with
2603   *  valid data for the translated instruction, or a "nothing" instruction if   *  valid data for the translated instruction, or a "nothing" instruction if
2604   *  there was a translation failure. The newly translated instruction is then   *  there was a translation failure. The newly translated instruction is then
2605   *  executed.   *  executed.
# Line 2550  X(to_be_translated) Line 2626  X(to_be_translated)
2626          addr &= ~((1 << PPC_INSTR_ALIGNMENT_SHIFT) - 1);          addr &= ~((1 << PPC_INSTR_ALIGNMENT_SHIFT) - 1);
2627    
2628          /*  Read the instruction word from memory:  */          /*  Read the instruction word from memory:  */
2629          page = cpu->cd.ppc.host_load[addr >> 12];  #ifdef MODE32
2630            page = cpu->cd.ppc.host_load[((uint32_t)addr) >> 12];
2631    #else
2632            {
2633                    const uint32_t mask1 = (1 << DYNTRANS_L1N) - 1;
2634                    const uint32_t mask2 = (1 << DYNTRANS_L2N) - 1;
2635                    const uint32_t mask3 = (1 << DYNTRANS_L3N) - 1;
2636                    uint32_t x1 = (addr >> (64-DYNTRANS_L1N)) & mask1;
2637                    uint32_t x2 = (addr >> (64-DYNTRANS_L1N-DYNTRANS_L2N)) & mask2;
2638                    uint32_t x3 = (addr >> (64-DYNTRANS_L1N-DYNTRANS_L2N-
2639                        DYNTRANS_L3N)) & mask3;
2640                    struct DYNTRANS_L2_64_TABLE *l2 = cpu->cd.ppc.l1_64[x1];
2641                    struct DYNTRANS_L3_64_TABLE *l3 = l2->l3[x2];
2642                    page = l3->host_load[x3];
2643            }
2644    #endif
2645    
2646          if (page != NULL) {          if (page != NULL) {
2647                  /*  fatal("TRANSLATION HIT!\n");  */                  /*  fatal("TRANSLATION HIT!\n");  */
# Line 2567  X(to_be_translated) Line 2658  X(to_be_translated)
2658          }          }
2659    
2660          iword = *((uint32_t *)&ib[0]);          iword = *((uint32_t *)&ib[0]);
2661            iword = BE32_TO_HOST(iword);
 #ifdef HOST_LITTLE_ENDIAN  
         if (cpu->byte_order == EMUL_BIG_ENDIAN)  
 #else  
         if (cpu->byte_order == EMUL_LITTLE_ENDIAN)  
 #endif  
                 iword = ((iword & 0xff) << 24) |  
                         ((iword & 0xff00) << 8) |  
                         ((iword & 0xff0000) >> 8) |  
                         ((iword & 0xff000000) >> 24);  
2662    
2663    
2664  #define DYNTRANS_TO_BE_TRANSLATED_HEAD  #define DYNTRANS_TO_BE_TRANSLATED_HEAD
# Line 2592  X(to_be_translated) Line 2674  X(to_be_translated)
2674    
2675          switch (main_opcode) {          switch (main_opcode) {
2676    
2677            case 0x04:
2678                    fatal("[ TODO: ALTIVEC ]\n");
2679                    ic->f = instr(nop);
2680                    break;
2681    
2682          case PPC_HI6_MULLI:          case PPC_HI6_MULLI:
2683                  rt = (iword >> 21) & 31;                  rt = (iword >> 21) & 31;
2684                  ra = (iword >> 16) & 31;                  ra = (iword >> 16) & 31;
# Line 2627  X(to_be_translated) Line 2714  X(to_be_translated)
2714                          imm = (int16_t)(iword & 0xffff);                          imm = (int16_t)(iword & 0xffff);
2715                          if (l_bit)                          if (l_bit)
2716                                  ic->f = instr(cmpdi);                                  ic->f = instr(cmpdi);
2717                          else                          else {
2718                                  ic->f = instr(cmpwi);                                  if (bf == 0)
2719                                            ic->f = instr(cmpwi_cr0);
2720                                    else
2721                                            ic->f = instr(cmpwi);
2722                            }
2723                  }                  }
2724                  ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[ra]);                  ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[ra]);
2725                  ic->arg[1] = (ssize_t)imm;                  ic->arg[1] = (ssize_t)imm;
# Line 2658  X(to_be_translated) Line 2749  X(to_be_translated)
2749                  rt = (iword >> 21) & 31; ra = (iword >> 16) & 31;                  rt = (iword >> 21) & 31; ra = (iword >> 16) & 31;
2750                  ic->f = instr(addi);                  ic->f = instr(addi);
2751                  if (ra == 0)                  if (ra == 0)
2752                          ic->arg[0] = (size_t)(&cpu->cd.ppc.zero);                          ic->f = instr(li);
2753                  else                  else
2754                          ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[ra]);                          ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[ra]);
2755                  ic->arg[1] = (int16_t)(iword & 0xffff);                  ic->arg[1] = (int16_t)(iword & 0xffff);
2756                  if (main_opcode == PPC_HI6_ADDIS)                  if (main_opcode == PPC_HI6_ADDIS)
2757                          ic->arg[1] <<= 16;                          ic->arg[1] <<= 16;
2758                    if (ra == 0 && ic->arg[1] == 0)
2759                            ic->f = instr(li_0);
2760                  ic->arg[2] = (size_t)(&cpu->cd.ppc.gpr[rt]);                  ic->arg[2] = (size_t)(&cpu->cd.ppc.gpr[rt]);
2761                  break;                  break;
2762    
# Line 2704  X(to_be_translated) Line 2797  X(to_be_translated)
2797          case PPC_HI6_LHAU:          case PPC_HI6_LHAU:
2798          case PPC_HI6_LWZ:          case PPC_HI6_LWZ:
2799          case PPC_HI6_LWZU:          case PPC_HI6_LWZU:
2800            case PPC_HI6_LD:
2801          case PPC_HI6_LFD:          case PPC_HI6_LFD:
2802          case PPC_HI6_LFS:          case PPC_HI6_LFS:
2803          case PPC_HI6_STB:          case PPC_HI6_STB:
# Line 2712  X(to_be_translated) Line 2806  X(to_be_translated)
2806          case PPC_HI6_STHU:          case PPC_HI6_STHU:
2807          case PPC_HI6_STW:          case PPC_HI6_STW:
2808          case PPC_HI6_STWU:          case PPC_HI6_STWU:
2809            case PPC_HI6_STD:
2810          case PPC_HI6_STFD:          case PPC_HI6_STFD:
2811          case PPC_HI6_STFS:          case PPC_HI6_STFS:
2812                  rs = (iword >> 21) & 31;                  rs = (iword >> 21) & 31;
# Line 2728  X(to_be_translated) Line 2823  X(to_be_translated)
2823                  case PPC_HI6_LHZU: load=1; size=1; update=1; break;                  case PPC_HI6_LHZU: load=1; size=1; update=1; break;
2824                  case PPC_HI6_LWZ:  load=1; size=2; break;                  case PPC_HI6_LWZ:  load=1; size=2; break;
2825                  case PPC_HI6_LWZU: load=1; size=2; update=1; break;                  case PPC_HI6_LWZU: load=1; size=2; update=1; break;
2826                    case PPC_HI6_LD:   load=1; size=3; break;
2827                  case PPC_HI6_LFD:  load=1; size=3; fp=1;ic->f=instr(lfd);break;                  case PPC_HI6_LFD:  load=1; size=3; fp=1;ic->f=instr(lfd);break;
2828                  case PPC_HI6_LFS:  load=1; size=2; fp=1;ic->f=instr(lfs);break;                  case PPC_HI6_LFS:  load=1; size=2; fp=1;ic->f=instr(lfs);break;
2829                  case PPC_HI6_STB:  break;                  case PPC_HI6_STB:  break;
# Line 2736  X(to_be_translated) Line 2832  X(to_be_translated)
2832                  case PPC_HI6_STHU: size=1; update=1; break;                  case PPC_HI6_STHU: size=1; update=1; break;
2833                  case PPC_HI6_STW:  size=2; break;                  case PPC_HI6_STW:  size=2; break;
2834                  case PPC_HI6_STWU: size=2; update=1; break;                  case PPC_HI6_STWU: size=2; update=1; break;
2835                    case PPC_HI6_STD:  size=3; break;
2836                  case PPC_HI6_STFD: size=3; fp=1; ic->f = instr(stfd); break;                  case PPC_HI6_STFD: size=3; fp=1; ic->f = instr(stfd); break;
2837                  case PPC_HI6_STFS: size=2; fp=1; ic->f = instr(stfs); break;                  case PPC_HI6_STFS: size=2; fp=1; ic->f = instr(stfs); break;
2838                  }                  }
# Line 2779  X(to_be_translated) Line 2876  X(to_be_translated)
2876                          samepage_function = instr(bcl_samepage);                          samepage_function = instr(bcl_samepage);
2877                  } else {                  } else {
2878                          ic->f = instr(bc);                          ic->f = instr(bc);
2879                          if (bo & 4)                          if ((bo & 0x14) == 0x04) {
2880                                  samepage_function = instr(bc_samepage_no_ctr);                                  samepage_function = bo & 8?
2881                          else                                      instr(bc_samepage_simple1) :
2882                                        instr(bc_samepage_simple0);
2883                            } else
2884                                  samepage_function = instr(bc_samepage);                                  samepage_function = instr(bc_samepage);
2885                  }                  }
2886                  ic->arg[0] = (ssize_t)tmp_addr;                  ic->arg[0] = (ssize_t)(tmp_addr + (addr & 0xffc));
2887                  ic->arg[1] = bo;                  ic->arg[1] = bo;
2888                  ic->arg[2] = bi;                  ic->arg[2] = 31-bi;
2889                  /*  Branches are calculated as cur PC + offset.  */                  /*  Branches are calculated as cur PC + offset.  */
2890                  /*  Special case: branch within the same page:  */                  /*  Special case: branch within the same page:  */
2891                  {                  {
2892                          uint64_t mask_within_page =                          uint64_t mask_within_page =
2893                              ((PPC_IC_ENTRIES_PER_PAGE-1) << 2) | 3;                              ((PPC_IC_ENTRIES_PER_PAGE-1) << 2) | 3;
2894                          uint64_t old_pc = addr;                          uint64_t old_pc = addr;
2895                          uint64_t new_pc = old_pc + (int32_t)ic->arg[0];                          uint64_t new_pc = old_pc + (int32_t)tmp_addr;
2896                          if ((old_pc & ~mask_within_page) ==                          if ((old_pc & ~mask_within_page) ==
2897                              (new_pc & ~mask_within_page)) {                              (new_pc & ~mask_within_page)) {
2898                                  ic->f = samepage_function;                                  ic->f = samepage_function;
# Line 2833  X(to_be_translated) Line 2932  X(to_be_translated)
2932                          ic->f = instr(b);                          ic->f = instr(b);
2933                          samepage_function = instr(b_samepage);                          samepage_function = instr(b_samepage);
2934                  }                  }
2935                  ic->arg[0] = (ssize_t)tmp_addr;                  ic->arg[0] = (ssize_t)(tmp_addr + (addr & 0xffc));
2936                    ic->arg[1] = (addr & 0xffc) + 4;
2937                  /*  Branches are calculated as cur PC + offset.  */                  /*  Branches are calculated as cur PC + offset.  */
2938                  /*  Special case: branch within the same page:  */                  /*  Special case: branch within the same page:  */
2939                  {                  {
2940                          uint64_t mask_within_page =                          uint64_t mask_within_page =
2941                              ((PPC_IC_ENTRIES_PER_PAGE-1) << 2) | 3;                              ((PPC_IC_ENTRIES_PER_PAGE-1) << 2) | 3;
2942                          uint64_t old_pc = addr;                          uint64_t old_pc = addr;
2943                          uint64_t new_pc = old_pc + (int32_t)ic->arg[0];                          uint64_t new_pc = old_pc + (int32_t)tmp_addr;
2944                          if ((old_pc & ~mask_within_page) ==                          if ((old_pc & ~mask_within_page) ==
2945                              (new_pc & ~mask_within_page)) {                              (new_pc & ~mask_within_page)) {
2946                                  ic->f = samepage_function;                                  ic->f = samepage_function;
# Line 2902  X(to_be_translated) Line 3002  X(to_be_translated)
3002                          ic->f = instr(rfi);                          ic->f = instr(rfi);
3003                          break;                          break;
3004    
3005                    case PPC_19_RFID:
3006                            ic->f = instr(rfid);
3007                            break;
3008    
3009                  case PPC_19_MCRF:                  case PPC_19_MCRF:
3010                          bf = (iword >> 23) & 7;                          bf = (iword >> 23) & 7;
3011                          bfa = (iword >> 18) & 7;                          bfa = (iword >> 18) & 7;
# Line 2914  X(to_be_translated) Line 3018  X(to_be_translated)
3018                  case PPC_19_CRANDC:                  case PPC_19_CRANDC:
3019                  case PPC_19_CREQV:                  case PPC_19_CREQV:
3020                  case PPC_19_CROR:                  case PPC_19_CROR:
3021                    case PPC_19_CRORC:
3022                  case PPC_19_CRNOR:                  case PPC_19_CRNOR:
3023                  case PPC_19_CRXOR:                  case PPC_19_CRXOR:
3024                          switch (xo) {                          switch (xo) {
# Line 2921  X(to_be_translated) Line 3026  X(to_be_translated)
3026                          case PPC_19_CRANDC: ic->f = instr(crandc); break;                          case PPC_19_CRANDC: ic->f = instr(crandc); break;
3027                          case PPC_19_CREQV:  ic->f = instr(creqv); break;                          case PPC_19_CREQV:  ic->f = instr(creqv); break;
3028                          case PPC_19_CROR:   ic->f = instr(cror); break;                          case PPC_19_CROR:   ic->f = instr(cror); break;
3029                            case PPC_19_CRORC:  ic->f = instr(crorc); break;
3030                          case PPC_19_CRNOR:  ic->f = instr(crnor); break;                          case PPC_19_CRNOR:  ic->f = instr(crnor); break;
3031                          case PPC_19_CRXOR:  ic->f = instr(crxor); break;                          case PPC_19_CRXOR:  ic->f = instr(crxor); break;
3032                          }                          }
# Line 2989  X(to_be_translated) Line 3095  X(to_be_translated)
3095                  xo = (iword >> 2) & 7;                  xo = (iword >> 2) & 7;
3096                  switch (xo) {                  switch (xo) {
3097    
3098                    case PPC_30_RLDICL:
3099                  case PPC_30_RLDICR:                  case PPC_30_RLDICR:
3100                          ic->f = instr(rldicr);                  case PPC_30_RLDIMI:
3101                            switch (xo) {
3102                            case PPC_30_RLDICL: ic->f = instr(rldicl); break;
3103                            case PPC_30_RLDICR: ic->f = instr(rldicr); break;
3104                            case PPC_30_RLDIMI: ic->f = instr(rldimi); break;
3105                            }
3106                          ic->arg[0] = iword;                          ic->arg[0] = iword;
3107                          if (cpu->cd.ppc.bits == 32) {                          if (cpu->cd.ppc.bits == 32) {
3108                                  fatal("TODO: rldicr in 32-bit mode?\n");                                  fatal("TODO: rld* in 32-bit mode?\n");
3109                                  goto bad;                                  goto bad;
3110                          }                          }
3111                          break;                          break;
# Line 3020  X(to_be_translated) Line 3132  X(to_be_translated)
3132                          } else {                          } else {
3133                                  if (l_bit)                                  if (l_bit)
3134                                          ic->f = instr(cmpd);                                          ic->f = instr(cmpd);
3135                                  else                                  else {
3136                                          ic->f = instr(cmpw);                                          if (bf == 0)
3137                                                    ic->f = instr(cmpw_cr0);
3138                                            else
3139                                                    ic->f = instr(cmpw);
3140                                    }
3141                          }                          }
3142                          ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[ra]);                          ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[ra]);
3143                          ic->arg[1] = (size_t)(&cpu->cd.ppc.gpr[rb]);                          ic->arg[1] = (size_t)(&cpu->cd.ppc.gpr[rb]);
# Line 3059  X(to_be_translated) Line 3175  X(to_be_translated)
3175                          debug_spr_usage(cpu->pc, spr);                          debug_spr_usage(cpu->pc, spr);
3176                          ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[rs]);                          ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[rs]);
3177                          ic->arg[1] = (size_t)(&cpu->cd.ppc.spr[spr]);                          ic->arg[1] = (size_t)(&cpu->cd.ppc.spr[spr]);
3178                          ic->f = instr(mtspr);                          switch (spr) {
3179                            case SPR_LR:
3180                                    ic->f = instr(mtlr);
3181                                    break;
3182                            case SPR_CTR:
3183                                    ic->f = instr(mtctr);
3184                                    break;
3185                            default:ic->f = instr(mtspr);
3186                            }
3187                          break;                          break;
3188    
3189                  case PPC_31_MFCR:                  case PPC_31_MFCR:
# Line 3075  X(to_be_translated) Line 3199  X(to_be_translated)
3199                          break;                          break;
3200    
3201                  case PPC_31_MTMSR:                  case PPC_31_MTMSR:
3202                    case PPC_31_MTMSRD:
3203                          rs = (iword >> 21) & 31;                          rs = (iword >> 21) & 31;
3204                          l_bit = (iword >> 16) & 1;                          l_bit = (iword >> 16) & 1;
3205                          if (l_bit) {                          if (l_bit) {
# Line 3083  X(to_be_translated) Line 3208  X(to_be_translated)
3208                          }                          }
3209                          ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[rs]);                          ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[rs]);
3210                          ic->arg[1] = (addr & 0xfff) + 4;                          ic->arg[1] = (addr & 0xfff) + 4;
3211                            ic->arg[2] = xo == PPC_31_MTMSRD;
3212                          ic->f = instr(mtmsr);                          ic->f = instr(mtmsr);
3213                          break;                          break;
3214    
# Line 3148  X(to_be_translated) Line 3274  X(to_be_translated)
3274                          break;                          break;
3275    
3276                  case PPC_31_SYNC:                  case PPC_31_SYNC:
3277                    case PPC_31_DSSALL:
3278                  case PPC_31_EIEIO:                  case PPC_31_EIEIO:
3279                  case PPC_31_DCBST:                  case PPC_31_DCBST:
3280                  case PPC_31_DCBTST:                  case PPC_31_DCBTST:
# Line 3200  X(to_be_translated) Line 3327  X(to_be_translated)
3327                          ic->f = instr(tlbli);                          ic->f = instr(tlbli);
3328                          break;                          break;
3329    
3330                    case PPC_31_TLBSX_DOT:
3331                            /*  TODO  */
3332                            ic->f = instr(tlbsx_dot);
3333                            break;
3334    
3335                  case PPC_31_MFTB:                  case PPC_31_MFTB:
3336                          rt = (iword >> 21) & 31;                          rt = (iword >> 21) & 31;
3337                          spr = ((iword >> 6) & 0x3e0) + ((iword >> 16) & 31);                          spr = ((iword >> 6) & 0x3e0) + ((iword >> 16) & 31);
# Line 3249  X(to_be_translated) Line 3381  X(to_be_translated)
3381                          }                          }
3382                          break;                          break;
3383    
3384                    case PPC_31_WRTEEI:
3385                            ic->arg[0] = iword & 0x8000;
3386                            ic->f = instr(wrteei);
3387                            break;
3388    
3389                  case 0x1c3:                  case 0x1c3:
3390                          fatal("[ mtdcr: TODO ]\n");                          fatal("[ mtdcr: TODO ]\n");
3391                          ic->f = instr(nop);                          ic->f = instr(nop);
# Line 3346  X(to_be_translated) Line 3483  X(to_be_translated)
3483                  case PPC_31_EXTSH:                  case PPC_31_EXTSH:
3484                  case PPC_31_EXTSW:                  case PPC_31_EXTSW:
3485                  case PPC_31_SLW:                  case PPC_31_SLW:
3486                    case PPC_31_SLD:
3487                  case PPC_31_SRAW:                  case PPC_31_SRAW:
3488                  case PPC_31_SRW:                  case PPC_31_SRW:
3489                  case PPC_31_AND:                  case PPC_31_AND:
# Line 3355  X(to_be_translated) Line 3493  X(to_be_translated)
3493                  case PPC_31_OR:                  case PPC_31_OR:
3494                  case PPC_31_ORC:                  case PPC_31_ORC:
3495                  case PPC_31_XOR:                  case PPC_31_XOR:
3496                    case PPC_31_EQV:
3497                          rs = (iword >> 21) & 31;                          rs = (iword >> 21) & 31;
3498                          ra = (iword >> 16) & 31;                          ra = (iword >> 16) & 31;
3499                          rb = (iword >> 11) & 31;                          rb = (iword >> 11) & 31;
# Line 3369  X(to_be_translated) Line 3508  X(to_be_translated)
3508                                            rc_f  = instr(extsw_dot); break;                                            rc_f  = instr(extsw_dot); break;
3509                          case PPC_31_SLW:  ic->f = instr(slw);                          case PPC_31_SLW:  ic->f = instr(slw);
3510                                            rc_f  = instr(slw_dot); break;                                            rc_f  = instr(slw_dot); break;
3511                            case PPC_31_SLD:  ic->f = instr(sld);
3512                                              rc_f  = instr(sld_dot); break;
3513                          case PPC_31_SRAW: ic->f = instr(sraw);                          case PPC_31_SRAW: ic->f = instr(sraw);
3514                                            rc_f  = instr(sraw_dot); break;                                            rc_f  = instr(sraw_dot); break;
3515                          case PPC_31_SRW:  ic->f = instr(srw);                          case PPC_31_SRW:  ic->f = instr(srw);
# Line 3381  X(to_be_translated) Line 3522  X(to_be_translated)
3522                                            rc_f  = instr(andc_dot); break;                                            rc_f  = instr(andc_dot); break;
3523                          case PPC_31_NOR:  ic->f = instr(nor);                          case PPC_31_NOR:  ic->f = instr(nor);
3524                                            rc_f  = instr(nor_dot); break;                                            rc_f  = instr(nor_dot); break;
3525                          case PPC_31_OR:   ic->f = instr(or);                          case PPC_31_OR:   ic->f = rs == rb? instr(mr)
3526                                                    : instr(or);
3527                                            rc_f  = instr(or_dot); break;                                            rc_f  = instr(or_dot); break;
3528                          case PPC_31_ORC:  ic->f = instr(orc);                          case PPC_31_ORC:  ic->f = instr(orc);
3529                                            rc_f  = instr(orc_dot); break;                                            rc_f  = instr(orc_dot); break;
3530                          case PPC_31_XOR:  ic->f = instr(xor);                          case PPC_31_XOR:  ic->f = instr(xor);
3531                                            rc_f  = instr(xor_dot); break;                                            rc_f  = instr(xor_dot); break;
3532                            case PPC_31_EQV:  ic->f = instr(eqv);
3533                                              rc_f  = instr(eqv_dot); break;
3534                          }                          }
3535                          ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[rs]);                          ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[rs]);
3536                          ic->arg[1] = (size_t)(&cpu->cd.ppc.gpr[rb]);                          ic->arg[1] = (size_t)(&cpu->cd.ppc.gpr[rb]);
# Line 3479  X(to_be_translated) Line 3623  X(to_be_translated)
3623                          }                          }
3624                          break;                          break;
3625    
3626                    case PPC_31_LVX:
3627                    case PPC_31_LVXL:
3628                    case PPC_31_STVX:
3629                    case PPC_31_STVXL:
3630                            fatal("[ TODO: altivec load/store ]\n");
3631                            load = 0;
3632                            switch (xo) {
3633                            case PPC_31_LVX:
3634                            case PPC_31_LVXL:
3635                                    load = 1; break;
3636                            }
3637                            rs = (iword >> 21) & 31;
3638                            ra = (iword >> 16) & 31;
3639                            rb = (iword >> 11) & 31;
3640                            ic->arg[0] = (size_t)(&cpu->cd.ppc.vr_hi[rs]);
3641                            if (ra == 0)
3642                                    ic->arg[1] = (size_t)(&cpu->cd.ppc.zero);
3643                            else
3644                                    ic->arg[1] = (size_t)(&cpu->cd.ppc.gpr[ra]);
3645                            ic->arg[2] = (size_t)(&cpu->cd.ppc.gpr[rb]);
3646                            ic->f =
3647    #ifdef MODE32
3648                                        ppc32_loadstore_indexed
3649    #else
3650                                        ppc_loadstore_indexed
3651    #endif
3652                                        [3 + 4 * load];
3653                            break;
3654    
3655                  default:goto bad;                  default:goto bad;
3656                  }                  }
3657                  break;                  break;

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

  ViewVC Help
Powered by ViewVC 1.1.26