/[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 21 by dpavlin, Mon Oct 8 16:19:23 2007 UTC revision 22 by dpavlin, Mon Oct 8 16:19:37 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.59 2006/02/09 22:40:27 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 994  X(fctiwz) Line 989  X(fctiwz)
989          struct ieee_float_value frb;          struct ieee_float_value frb;
990          int32_t res = 0;          int32_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 1647  X(cror) { Line 1596  X(cror) {
1596          if (ba | bb)          if (ba | bb)
1597                  cpu->cd.ppc.cr |= (1 << (31-bt));                  cpu->cd.ppc.cr |= (1 << (31-bt));
1598  }  }
1599    X(crorc) {
1600            uint32_t iword = ic->arg[0]; int bt = (iword >> 21) & 31;
1601            int ba = (iword >> 16) & 31, bb = (iword >> 11) & 31;
1602            ba = (cpu->cd.ppc.cr >> (31-ba)) & 1;
1603            bb = (cpu->cd.ppc.cr >> (31-bb)) & 1;
1604            cpu->cd.ppc.cr &= ~(1 << (31-bt));
1605            if (!(ba | bb))
1606                    cpu->cd.ppc.cr |= (1 << (31-bt));
1607    }
1608  X(crnor) {  X(crnor) {
1609          uint32_t iword = ic->arg[0]; int bt = (iword >> 21) & 31;          uint32_t iword = ic->arg[0]; int bt = (iword >> 21) & 31;
1610          int ba = (iword >> 16) & 31, bb = (iword >> 11) & 31;          int ba = (iword >> 16) & 31, bb = (iword >> 11) & 31;
# Line 1674  X(crxor) { Line 1632  X(crxor) {
1632   *  arg[1] = pointer to source SPR   *  arg[1] = pointer to source SPR
1633   */   */
1634  X(mfspr) {  X(mfspr) {
1635            /*  TODO: Check permission  */
1636          reg(ic->arg[0]) = reg(ic->arg[1]);          reg(ic->arg[0]) = reg(ic->arg[1]);
1637  }  }
1638  X(mfspr_pmc1) {  X(mfspr_pmc1) {
# Line 1702  X(mftbu) { Line 1661  X(mftbu) {
1661   *  arg[1] = pointer to the SPR   *  arg[1] = pointer to the SPR
1662   */   */
1663  X(mtspr) {  X(mtspr) {
1664            /*  TODO: Check permission  */
1665          reg(ic->arg[1]) = reg(ic->arg[0]);          reg(ic->arg[1]) = reg(ic->arg[0]);
1666  }  }
1667    X(mtlr) {
1668            cpu->cd.ppc.spr[SPR_LR] = reg(ic->arg[0]);
1669    }
1670    X(mtctr) {
1671            cpu->cd.ppc.spr[SPR_CTR] = reg(ic->arg[0]);
1672    }
1673    
1674    
1675  /*  /*
# Line 1719  X(rfi) Line 1685  X(rfi)
1685          reg_access_msr(cpu, &tmp, 1, 0);          reg_access_msr(cpu, &tmp, 1, 0);
1686    
1687          cpu->pc = cpu->cd.ppc.spr[SPR_SRR0];          cpu->pc = cpu->cd.ppc.spr[SPR_SRR0];
1688          DYNTRANS_PC_TO_POINTERS(cpu);          quick_pc_to_pointers(cpu);
1689  }  }
1690    
1691    
# Line 1752  X(mfmsr) Line 1718  X(mfmsr)
1718   */   */
1719  X(mtmsr)  X(mtmsr)
1720  {  {
1721            MODE_uint_t old_pc;
1722    
1723            /*  TODO: check permission!  */
1724    
1725          /*  Synchronize the PC (pointing to _after_ this instruction)  */          /*  Synchronize the PC (pointing to _after_ this instruction)  */
1726          cpu->pc = (cpu->pc & ~0xfff) + ic->arg[1];          cpu->pc = (cpu->pc & ~0xfff) + ic->arg[1];
1727            old_pc = cpu->pc;
1728    
1729          reg_access_msr(cpu, (uint64_t*)ic->arg[0], 1, 1);          reg_access_msr(cpu, (uint64_t*)ic->arg[0], 1, 1);
1730    
1731            /*
1732             *  Super-ugly hack:  If the pc wasn't changed (i.e. if there was no
1733             *  exception while accessing the msr), then we _decrease_ the PC by 4
1734             *  again. This is because the next ic could be an end_of_page.
1735             */
1736            if ((MODE_uint_t)cpu->pc == old_pc)
1737                    cpu->pc -= 4;
1738    }
1739    
1740    
1741    /*
1742     *  wrteei:  Write EE immediate  (on PPC405GP)
1743     *
1744     *  arg[0] = either 0 or 0x8000
1745     */
1746    X(wrteei)
1747    {
1748            /*  TODO: check permission!  */
1749            uint64_t x;
1750    
1751            /*  Synchronize the PC (pointing to _after_ this instruction)  */
1752            cpu->pc = (cpu->pc & ~0xfff) + ic->arg[1];
1753    
1754            reg_access_msr(cpu, &x, 0, 0);
1755            x = (x & ~0x8000) | ic->arg[0];
1756            reg_access_msr(cpu, &x, 1, 1);
1757  }  }
1758    
1759    
# Line 1990  X(andc) {      reg(ic->arg[2]) = reg(ic->arg[ Line 1988  X(andc) {      reg(ic->arg[2]) = reg(ic->arg[
1988  DOT2(andc)  DOT2(andc)
1989  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])); }
1990  DOT2(nor)  DOT2(nor)
1991    X(mr) {         reg(ic->arg[2]) = reg(ic->arg[1]); }
1992  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]); }
1993  DOT2(or)  DOT2(or)
1994  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])); }
# Line 2230  X(xori) { reg(ic->arg[2]) = reg(ic->arg[ Line 2229  X(xori) { reg(ic->arg[2]) = reg(ic->arg[
2229   */   */
2230  X(lfs)  X(lfs)
2231  {  {
2232          /*  Sync. PC in case of an exception:  */          /*  Sync. PC in case of an exception, and remember it:  */
2233          uint64_t old_pc, low_pc = ((size_t)ic - (size_t)          uint64_t old_pc, low_pc = ((size_t)ic - (size_t)
2234              cpu->cd.ppc.cur_ic_page) / sizeof(struct ppc_instr_call);              cpu->cd.ppc.cur_ic_page) / sizeof(struct ppc_instr_call);
2235          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) <<
2236              + (low_pc << 2);              PPC_INSTR_ALIGNMENT_SHIFT)) + (low_pc << PPC_INSTR_ALIGNMENT_SHIFT);
2237          if (!(cpu->cd.ppc.msr & PPC_MSR_FP)) {          if (!(cpu->cd.ppc.msr & PPC_MSR_FP)) {
2238                  ppc_exception(cpu, PPC_EXCEPTION_FPU);                  ppc_exception(cpu, PPC_EXCEPTION_FPU);
2239                  return;                  return;
# Line 2260  X(lfs) Line 2259  X(lfs)
2259  }  }
2260  X(lfsx)  X(lfsx)
2261  {  {
2262          /*  Sync. PC in case of an exception:  */          /*  Sync. PC in case of an exception, and remember it:  */
2263          uint64_t old_pc, low_pc = ((size_t)ic - (size_t)          uint64_t old_pc, low_pc = ((size_t)ic - (size_t)
2264              cpu->cd.ppc.cur_ic_page) / sizeof(struct ppc_instr_call);              cpu->cd.ppc.cur_ic_page) / sizeof(struct ppc_instr_call);
2265          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) <<
2266              + (low_pc << 2);              PPC_INSTR_ALIGNMENT_SHIFT)) + (low_pc << PPC_INSTR_ALIGNMENT_SHIFT);
2267          if (!(cpu->cd.ppc.msr & PPC_MSR_FP)) {          if (!(cpu->cd.ppc.msr & PPC_MSR_FP)) {
2268                  ppc_exception(cpu, PPC_EXCEPTION_FPU);                  ppc_exception(cpu, PPC_EXCEPTION_FPU);
2269                  return;                  return;
# Line 2290  X(lfsx) Line 2289  X(lfsx)
2289  }  }
2290  X(lfd)  X(lfd)
2291  {  {
2292          /*  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;  
         }  
2293    
2294          /*  Perform a 64-bit load:  */          /*  Perform a 64-bit load:  */
2295  #ifdef MODE32  #ifdef MODE32
# Line 2309  X(lfd) Line 2301  X(lfd)
2301  }  }
2302  X(lfdx)  X(lfdx)
2303  {  {
2304          /*  Sync. PC in case of an exception:  */          CHECK_FOR_FPU_EXCEPTION;
2305          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;  
         }  
2306          /*  Perform a 64-bit load:  */          /*  Perform a 64-bit load:  */
2307  #ifdef MODE32  #ifdef MODE32
2308          ppc32_loadstore_indexed          ppc32_loadstore_indexed
# Line 2331  X(stfs) Line 2317  X(stfs)
2317          struct ieee_float_value val;          struct ieee_float_value val;
2318          uint64_t tmp_val;          uint64_t tmp_val;
2319    
2320          /*  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;  
         }  
2321    
2322          ieee_interpret_float_value(*old_arg0, &val, IEEE_FMT_D);          ieee_interpret_float_value(*old_arg0, &val, IEEE_FMT_D);
2323          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 2340  X(stfsx)
2340          struct ieee_float_value val;          struct ieee_float_value val;
2341          uint64_t tmp_val;          uint64_t tmp_val;
2342    
2343          /*  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;  
         }  
2344    
2345          ieee_interpret_float_value(*old_arg0, &val, IEEE_FMT_D);          ieee_interpret_float_value(*old_arg0, &val, IEEE_FMT_D);
2346          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 2359  X(stfsx)
2359  }  }
2360  X(stfd)  X(stfd)
2361  {  {
2362          /*  Sync. PC in case of an exception:  */          CHECK_FOR_FPU_EXCEPTION;
2363          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;  
         }  
2364          /*  Perform a 64-bit store:  */          /*  Perform a 64-bit store:  */
2365  #ifdef MODE32  #ifdef MODE32
2366          ppc32_loadstore          ppc32_loadstore
# Line 2405  X(stfd) Line 2371  X(stfd)
2371  }  }
2372  X(stfdx)  X(stfdx)
2373  {  {
2374          /*  Sync. PC in case of an exception:  */          CHECK_FOR_FPU_EXCEPTION;
2375          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;  
         }  
2376          /*  Perform a 64-bit store:  */          /*  Perform a 64-bit store:  */
2377  #ifdef MODE32  #ifdef MODE32
2378          ppc32_loadstore_indexed          ppc32_loadstore_indexed
# Line 2428  X(stfdx) Line 2388  X(stfdx)
2388   */   */
2389  X(tlbia)  X(tlbia)
2390  {  {
2391  printf("tlbia\n");          printf("[ tlbia ]\n");
 exit(1);  
2392          cpu->invalidate_translation_caches(cpu, 0, INVALIDATE_ALL);          cpu->invalidate_translation_caches(cpu, 0, INVALIDATE_ALL);
2393  }  }
2394    
# Line 2453  X(sc) Line 2412  X(sc)
2412          cpu->pc = (cpu->pc & ~0xfff) + ic->arg[1];          cpu->pc = (cpu->pc & ~0xfff) + ic->arg[1];
2413    
2414          ppc_exception(cpu, PPC_EXCEPTION_SC);          ppc_exception(cpu, PPC_EXCEPTION_SC);
2415    
2416            /*  This caused an update to the PC register, so there is no need
2417                to worry about the next instruction being an end_of_page.  */
2418  }  }
2419    
2420    
# Line 2473  X(user_syscall) Line 2435  X(user_syscall)
2435  X(openfirmware)  X(openfirmware)
2436  {  {
2437          of_emul(cpu);          of_emul(cpu);
2438            if (cpu->running == 0) {
2439                    cpu->running_translated = 0;
2440            }
2441          cpu->pc = cpu->cd.ppc.spr[SPR_LR];          cpu->pc = cpu->cd.ppc.spr[SPR_LR];
2442          if (cpu->machine->show_trace_tree)          if (cpu->machine->show_trace_tree)
2443                  cpu_functioncall_trace_return(cpu);                  cpu_functioncall_trace_return(cpu);
2444          DYNTRANS_PC_TO_POINTERS(cpu);          quick_pc_to_pointers(cpu);
2445    }
2446    
2447    
2448    /*
2449     *  tlbsx_dot: TLB scan
2450     */
2451    X(tlbsx_dot)
2452    {
2453            /*  TODO  */
2454            cpu->cd.ppc.cr &= ~(0xf0000000);
2455            cpu->cd.ppc.cr |= 0x20000000;
2456            cpu->cd.ppc.cr |= ((cpu->cd.ppc.spr[SPR_XER] >> 3) & 0x10000000);
2457  }  }
2458    
2459    
# Line 2485  X(openfirmware) Line 2462  X(openfirmware)
2462   */   */
2463  X(tlbli)  X(tlbli)
2464  {  {
2465            fatal("tlbli\n");
2466            cpu->invalidate_translation_caches(cpu, 0, INVALIDATE_ALL);
2467  }  }
2468    
2469    
# Line 2496  X(tlbld) Line 2475  X(tlbld)
2475          /*  MODE_uint_t vaddr = reg(ic->arg[0]);          /*  MODE_uint_t vaddr = reg(ic->arg[0]);
2476              MODE_uint_t paddr = cpu->cd.ppc.spr[SPR_RPA];  */              MODE_uint_t paddr = cpu->cd.ppc.spr[SPR_RPA];  */
2477    
2478          /*  TODO?  */          fatal("tlbld\n");
2479            cpu->invalidate_translation_caches(cpu, 0, INVALIDATE_ALL);
2480  }  }
2481    
2482    
# Line 2506  X(tlbld) Line 2486  X(tlbld)
2486  X(end_of_page)  X(end_of_page)
2487  {  {
2488          /*  Update the PC:  (offset 0, but on the next page)  */          /*  Update the PC:  (offset 0, but on the next page)  */
2489          cpu->pc &= ~((PPC_IC_ENTRIES_PER_PAGE-1) << 2);          cpu->pc &= ~((PPC_IC_ENTRIES_PER_PAGE-1) << PPC_INSTR_ALIGNMENT_SHIFT);
2490          cpu->pc += (PPC_IC_ENTRIES_PER_PAGE << 2);          cpu->pc += (PPC_IC_ENTRIES_PER_PAGE << PPC_INSTR_ALIGNMENT_SHIFT);
2491    
2492          /*  Find the new physical page and update the translation pointers:  */          /*  Find the new physical page and update the translation pointers:  */
2493          DYNTRANS_PC_TO_POINTERS(cpu);          quick_pc_to_pointers(cpu);
2494    
2495          /*  end_of_page doesn't count as an executed instruction:  */          /*  end_of_page doesn't count as an executed instruction:  */
2496          cpu->n_translated_instrs --;          cpu->n_translated_instrs --;
# Line 2534  X(to_be_translated) Line 2514  X(to_be_translated)
2514          uint32_t iword, mask;          uint32_t iword, mask;
2515          unsigned char *page;          unsigned char *page;
2516          unsigned char ib[4];          unsigned char ib[4];
2517    #ifdef DYNTRANS_BACKEND
2518            int simple = 0;
2519    #endif
2520          int main_opcode, rt, rs, ra, rb, rc, aa_bit, l_bit, lk_bit, spr, sh,          int main_opcode, rt, rs, ra, rb, rc, aa_bit, l_bit, lk_bit, spr, sh,
2521              xo, imm, load, size, update, zero, bf, bo, bi, bh, oe_bit, n64=0,              xo, imm, load, size, update, zero, bf, bo, bi, bh, oe_bit, n64=0,
2522              bfa, fp, byterev, nb, mb, me;              bfa, fp, byterev, nb, mb, me;
# Line 2567  X(to_be_translated) Line 2550  X(to_be_translated)
2550          }          }
2551    
2552          iword = *((uint32_t *)&ib[0]);          iword = *((uint32_t *)&ib[0]);
2553            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);  
2554    
2555    
2556  #define DYNTRANS_TO_BE_TRANSLATED_HEAD  #define DYNTRANS_TO_BE_TRANSLATED_HEAD
# Line 2592  X(to_be_translated) Line 2566  X(to_be_translated)
2566    
2567          switch (main_opcode) {          switch (main_opcode) {
2568    
2569            case 0x04:
2570                    fatal("[ TODO: ALTIVEC ]\n");
2571                    ic->f = instr(nop);
2572                    break;
2573    
2574          case PPC_HI6_MULLI:          case PPC_HI6_MULLI:
2575                  rt = (iword >> 21) & 31;                  rt = (iword >> 21) & 31;
2576                  ra = (iword >> 16) & 31;                  ra = (iword >> 16) & 31;
# Line 2627  X(to_be_translated) Line 2606  X(to_be_translated)
2606                          imm = (int16_t)(iword & 0xffff);                          imm = (int16_t)(iword & 0xffff);
2607                          if (l_bit)                          if (l_bit)
2608                                  ic->f = instr(cmpdi);                                  ic->f = instr(cmpdi);
2609                          else                          else {
2610                                  ic->f = instr(cmpwi);                                  if (bf == 0)
2611                                            ic->f = instr(cmpwi_cr0);
2612                                    else
2613                                            ic->f = instr(cmpwi);
2614                            }
2615                  }                  }
2616                  ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[ra]);                  ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[ra]);
2617                  ic->arg[1] = (ssize_t)imm;                  ic->arg[1] = (ssize_t)imm;
# Line 2658  X(to_be_translated) Line 2641  X(to_be_translated)
2641                  rt = (iword >> 21) & 31; ra = (iword >> 16) & 31;                  rt = (iword >> 21) & 31; ra = (iword >> 16) & 31;
2642                  ic->f = instr(addi);                  ic->f = instr(addi);
2643                  if (ra == 0)                  if (ra == 0)
2644                          ic->arg[0] = (size_t)(&cpu->cd.ppc.zero);                          ic->f = instr(li);
2645                  else                  else
2646                          ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[ra]);                          ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[ra]);
2647                  ic->arg[1] = (int16_t)(iword & 0xffff);                  ic->arg[1] = (int16_t)(iword & 0xffff);
2648                  if (main_opcode == PPC_HI6_ADDIS)                  if (main_opcode == PPC_HI6_ADDIS)
2649                          ic->arg[1] <<= 16;                          ic->arg[1] <<= 16;
2650                    if (ra == 0 && ic->arg[1] == 0)
2651                            ic->f = instr(li_0);
2652                  ic->arg[2] = (size_t)(&cpu->cd.ppc.gpr[rt]);                  ic->arg[2] = (size_t)(&cpu->cd.ppc.gpr[rt]);
2653                  break;                  break;
2654    
# Line 2779  X(to_be_translated) Line 2764  X(to_be_translated)
2764                          samepage_function = instr(bcl_samepage);                          samepage_function = instr(bcl_samepage);
2765                  } else {                  } else {
2766                          ic->f = instr(bc);                          ic->f = instr(bc);
2767                          if (bo & 4)                          if ((bo & 0x14) == 0x04) {
2768                                  samepage_function = instr(bc_samepage_no_ctr);                                  samepage_function = bo & 8?
2769                          else                                      instr(bc_samepage_simple1) :
2770                                        instr(bc_samepage_simple0);
2771                            } else
2772                                  samepage_function = instr(bc_samepage);                                  samepage_function = instr(bc_samepage);
2773                  }                  }
2774                  ic->arg[0] = (ssize_t)tmp_addr;                  ic->arg[0] = (ssize_t)(tmp_addr + (addr & 0xffc));
2775                  ic->arg[1] = bo;                  ic->arg[1] = bo;
2776                  ic->arg[2] = bi;                  ic->arg[2] = 31-bi;
2777                  /*  Branches are calculated as cur PC + offset.  */                  /*  Branches are calculated as cur PC + offset.  */
2778                  /*  Special case: branch within the same page:  */                  /*  Special case: branch within the same page:  */
2779                  {                  {
2780                          uint64_t mask_within_page =                          uint64_t mask_within_page =
2781                              ((PPC_IC_ENTRIES_PER_PAGE-1) << 2) | 3;                              ((PPC_IC_ENTRIES_PER_PAGE-1) << 2) | 3;
2782                          uint64_t old_pc = addr;                          uint64_t old_pc = addr;
2783                          uint64_t new_pc = old_pc + (int32_t)ic->arg[0];                          uint64_t new_pc = old_pc + (int32_t)tmp_addr;
2784                          if ((old_pc & ~mask_within_page) ==                          if ((old_pc & ~mask_within_page) ==
2785                              (new_pc & ~mask_within_page)) {                              (new_pc & ~mask_within_page)) {
2786                                  ic->f = samepage_function;                                  ic->f = samepage_function;
# Line 2833  X(to_be_translated) Line 2820  X(to_be_translated)
2820                          ic->f = instr(b);                          ic->f = instr(b);
2821                          samepage_function = instr(b_samepage);                          samepage_function = instr(b_samepage);
2822                  }                  }
2823                  ic->arg[0] = (ssize_t)tmp_addr;                  ic->arg[0] = (ssize_t)(tmp_addr + (addr & 0xffc));
2824                    ic->arg[1] = (addr & 0xffc) + 4;
2825                  /*  Branches are calculated as cur PC + offset.  */                  /*  Branches are calculated as cur PC + offset.  */
2826                  /*  Special case: branch within the same page:  */                  /*  Special case: branch within the same page:  */
2827                  {                  {
2828                          uint64_t mask_within_page =                          uint64_t mask_within_page =
2829                              ((PPC_IC_ENTRIES_PER_PAGE-1) << 2) | 3;                              ((PPC_IC_ENTRIES_PER_PAGE-1) << 2) | 3;
2830                          uint64_t old_pc = addr;                          uint64_t old_pc = addr;
2831                          uint64_t new_pc = old_pc + (int32_t)ic->arg[0];                          uint64_t new_pc = old_pc + (int32_t)tmp_addr;
2832                          if ((old_pc & ~mask_within_page) ==                          if ((old_pc & ~mask_within_page) ==
2833                              (new_pc & ~mask_within_page)) {                              (new_pc & ~mask_within_page)) {
2834                                  ic->f = samepage_function;                                  ic->f = samepage_function;
# Line 2914  X(to_be_translated) Line 2902  X(to_be_translated)
2902                  case PPC_19_CRANDC:                  case PPC_19_CRANDC:
2903                  case PPC_19_CREQV:                  case PPC_19_CREQV:
2904                  case PPC_19_CROR:                  case PPC_19_CROR:
2905                    case PPC_19_CRORC:
2906                  case PPC_19_CRNOR:                  case PPC_19_CRNOR:
2907                  case PPC_19_CRXOR:                  case PPC_19_CRXOR:
2908                          switch (xo) {                          switch (xo) {
# Line 2921  X(to_be_translated) Line 2910  X(to_be_translated)
2910                          case PPC_19_CRANDC: ic->f = instr(crandc); break;                          case PPC_19_CRANDC: ic->f = instr(crandc); break;
2911                          case PPC_19_CREQV:  ic->f = instr(creqv); break;                          case PPC_19_CREQV:  ic->f = instr(creqv); break;
2912                          case PPC_19_CROR:   ic->f = instr(cror); break;                          case PPC_19_CROR:   ic->f = instr(cror); break;
2913                            case PPC_19_CRORC:  ic->f = instr(crorc); break;
2914                          case PPC_19_CRNOR:  ic->f = instr(crnor); break;                          case PPC_19_CRNOR:  ic->f = instr(crnor); break;
2915                          case PPC_19_CRXOR:  ic->f = instr(crxor); break;                          case PPC_19_CRXOR:  ic->f = instr(crxor); break;
2916                          }                          }
# Line 3020  X(to_be_translated) Line 3010  X(to_be_translated)
3010                          } else {                          } else {
3011                                  if (l_bit)                                  if (l_bit)
3012                                          ic->f = instr(cmpd);                                          ic->f = instr(cmpd);
3013                                  else                                  else {
3014                                          ic->f = instr(cmpw);                                          if (bf == 0)
3015                                                    ic->f = instr(cmpw_cr0);
3016                                            else
3017                                                    ic->f = instr(cmpw);
3018                                    }
3019                          }                          }
3020                          ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[ra]);                          ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[ra]);
3021                          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 3053  X(to_be_translated)
3053                          debug_spr_usage(cpu->pc, spr);                          debug_spr_usage(cpu->pc, spr);
3054                          ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[rs]);                          ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[rs]);
3055                          ic->arg[1] = (size_t)(&cpu->cd.ppc.spr[spr]);                          ic->arg[1] = (size_t)(&cpu->cd.ppc.spr[spr]);
3056                          ic->f = instr(mtspr);                          switch (spr) {
3057                            case SPR_LR:
3058                                    ic->f = instr(mtlr);
3059                                    break;
3060                            case SPR_CTR:
3061                                    ic->f = instr(mtctr);
3062                                    break;
3063                            default:ic->f = instr(mtspr);
3064                            }
3065                          break;                          break;
3066    
3067                  case PPC_31_MFCR:                  case PPC_31_MFCR:
# Line 3200  X(to_be_translated) Line 3202  X(to_be_translated)
3202                          ic->f = instr(tlbli);                          ic->f = instr(tlbli);
3203                          break;                          break;
3204    
3205                    case PPC_31_TLBSX_DOT:
3206                            /*  TODO  */
3207                            ic->f = instr(tlbsx_dot);
3208                            break;
3209    
3210                  case PPC_31_MFTB:                  case PPC_31_MFTB:
3211                          rt = (iword >> 21) & 31;                          rt = (iword >> 21) & 31;
3212                          spr = ((iword >> 6) & 0x3e0) + ((iword >> 16) & 31);                          spr = ((iword >> 6) & 0x3e0) + ((iword >> 16) & 31);
# Line 3249  X(to_be_translated) Line 3256  X(to_be_translated)
3256                          }                          }
3257                          break;                          break;
3258    
3259                    case PPC_31_WRTEEI:
3260                            ic->arg[0] = iword & 0x8000;
3261                            ic->f = instr(wrteei);
3262                            break;
3263    
3264                  case 0x1c3:                  case 0x1c3:
3265                          fatal("[ mtdcr: TODO ]\n");                          fatal("[ mtdcr: TODO ]\n");
3266                          ic->f = instr(nop);                          ic->f = instr(nop);
# Line 3381  X(to_be_translated) Line 3393  X(to_be_translated)
3393                                            rc_f  = instr(andc_dot); break;                                            rc_f  = instr(andc_dot); break;
3394                          case PPC_31_NOR:  ic->f = instr(nor);                          case PPC_31_NOR:  ic->f = instr(nor);
3395                                            rc_f  = instr(nor_dot); break;                                            rc_f  = instr(nor_dot); break;
3396                          case PPC_31_OR:   ic->f = instr(or);                          case PPC_31_OR:   ic->f = rs == rb? instr(mr)
3397                                                    : instr(or);
3398                                            rc_f  = instr(or_dot); break;                                            rc_f  = instr(or_dot); break;
3399                          case PPC_31_ORC:  ic->f = instr(orc);                          case PPC_31_ORC:  ic->f = instr(orc);
3400                                            rc_f  = instr(orc_dot); break;                                            rc_f  = instr(orc_dot); break;
# Line 3479  X(to_be_translated) Line 3492  X(to_be_translated)
3492                          }                          }
3493                          break;                          break;
3494    
3495                    case 359:
3496                            fatal("[ TODO: 359 ]\n");
3497                            ic->f = instr(nop);
3498                            break;
3499                    case PPC_31_LVX:
3500                            fatal("[ TODO: lvx ]\n");
3501                            ic->f = instr(nop);
3502                            break;
3503                    case PPC_31_STVX:
3504                            fatal("[ TODO: stvx ]\n");
3505                            ic->f = instr(nop);
3506                            break;
3507                    case PPC_31_STVXL:
3508                            fatal("[ TODO: stvxl ]\n");
3509                            ic->f = instr(nop);
3510                            break;
3511    
3512                  default:goto bad;                  default:goto bad;
3513                  }                  }
3514                  break;                  break;

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

  ViewVC Help
Powered by ViewVC 1.1.26