Add floating point model specific support; Redo method model specific support is...
authorMichael Meissner <gnu@the-meissners.org>
Tue, 21 Nov 1995 21:41:25 +0000 (21:41 +0000)
committerMichael Meissner <gnu@the-meissners.org>
Tue, 21 Nov 1995 21:41:25 +0000 (21:41 +0000)
sim/ppc/ChangeLog
sim/ppc/igen.c
sim/ppc/ppc-instructions

index 72d86eb4e1f80dd434802ce4b87e683450fa4b16..89d46361e305cace57d90b6fdb35a3af99e57cbc 100644 (file)
@@ -1,3 +1,15 @@
+Tue Nov 21 16:31:25 1995  Michael Meissner  <meissner@tiktok.cygnus.com>
+
+       * igen.c (insn_table_load_insns): Add support for model-static for
+       internal functions that should not be inlined.
+       (lf_print_c_semantic): Remove model_cleanup.
+       (gen_model_{c,h}): Ditto.
+
+       * ppc-instructions: Redo model specific support once again.  Add
+       floating point support to the model specific information.  Flesh
+       out all of the floating mutiply add/subtract instructions.  Add
+       better tracing support to the model specific information.
+
 Sun Nov 19 23:00:52 1995  Michael Meissner  <meissner@tiktok.cygnus.com>
 
        * ppc-instructions (model data, model_busy): Rather than using a
index 79010edcd2ab4441ffdd45fdd5969158508a6ffd..57211db86d0166d28b0a87598c651d31430fa484 100644 (file)
@@ -634,6 +634,9 @@ static insn *last_model_function;
 static insn *model_internal;
 static insn *last_model_internal;
 
+static insn *model_static;
+static insn *last_model_static;
+
 static insn *model_data;
 static insn *last_model_data;
 
@@ -1033,6 +1036,9 @@ insn_table_load_insns(char *file_name)
     else if (it_is("model-internal", file_entry->fields[insn_flags])) {
       model_table_insert_specific(table, file_entry, &model_internal, &last_model_internal);
     }
+    else if (it_is("model-static", file_entry->fields[insn_flags])) {
+      model_table_insert_specific(table, file_entry, &model_static, &last_model_static);
+    }
     else if (it_is("model-data", file_entry->fields[insn_flags])) {
       model_table_insert_specific(table, file_entry, &model_data, &last_model_data);
     }
@@ -1316,6 +1322,12 @@ lf_print_my_prefix(lf *file,
            (idecode ? "idecode" : "semantics"),
            file_entry->fields[insn_name],
            file_entry->line_nr);
+  lf_printf(file, "const itable_index my_index = ");
+  lf_print_function_name(file,
+                        file_entry->fields[insn_name],
+                        NULL,
+                        function_name_prefix_itable);
+  lf_printf(file, ";\n");
 }
 
 
@@ -2133,16 +2145,6 @@ lf_print_c_semantic(lf *file,
                         NULL,
                         function_name_prefix_itable);
   lf_printf(file, ", processor, cia);\n");
-  lf_printf(file, "\n");
-  lf_printf(file, "  if (WITH_MODEL_ISSUE)\n");
-  lf_printf(file, "    model_issue(");
-  lf_print_function_name(file,
-                        instruction->file_entry->fields[insn_name],
-                        NULL,
-                        function_name_prefix_itable);
-  lf_printf(file, ", cpu_model(processor), cia, %s);\n",
-           ((idecode_cache) ? "cache_entry, 0" : "(idecode_cache *)0, instruction"));
-
   lf_printf(file, "}\n");
   lf_printf(file, "\n");
 
@@ -2177,7 +2179,6 @@ lf_print_c_semantic(lf *file,
     lf_printf(file, "\n");
   }
 
-  /* the function footer */
   lf_printf(file, "return nia;\n");
   lf_indent(file, -2);
   lf_printf(file, "}\n");
@@ -2979,7 +2980,6 @@ gen_model_h(insn_table *table, lf *file)
   int model_create_p = 0;
   int model_init_p = 0;
   int model_halt_p = 0;
-  int model_issue_p = 0;
   int model_mon_info_p = 0;
   int model_mon_info_free_p = 0;
 
@@ -3040,8 +3040,6 @@ gen_model_h(insn_table *table, lf *file)
       model_init_p = 1;
     else if (strcmp (name, "model_halt") == 0)
       model_halt_p = 1;
-    else if (strcmp (name, "model_issue") == 0)
-      model_issue_p = 1;
     else if (strcmp (name, "model_mon_info") == 0)
       model_mon_info_p = 1;
     else if (strcmp (name, "model_mon_info_free") == 0)
@@ -3066,16 +3064,6 @@ gen_model_h(insn_table *table, lf *file)
     lf_printf(file, "\n");
   }
 
-  if (!model_issue_p) {
-    lf_printf(file, "INLINE_MODEL void model_issue\n");
-    lf_printf(file, "(itable_index index,\n");
-    lf_printf(file, " model_data *model_ptr,\n");
-    lf_printf(file, " unsigned_word cia,\n");
-    lf_printf(file, " idecode_cache *cache_entry,\n");
-    lf_printf(file, " instruction_word instruction);\n");
-    lf_printf(file, "\n");
-  }
-
   if (!model_mon_info_p) {
     lf_printf(file, "INLINE_MODEL model_print *model_mon_info\n");
     lf_printf(file, "(model_data *model_ptr);\n");
@@ -3170,7 +3158,6 @@ gen_model_c(insn_table *table, lf *file)
   int model_create_p = 0;
   int model_init_p = 0;
   int model_halt_p = 0;
-  int model_issue_p = 0;
   int model_mon_info_p = 0;
   int model_mon_info_free_p = 0;
 
@@ -3191,10 +3178,18 @@ gen_model_c(insn_table *table, lf *file)
     model_c_or_h_data(table, file, insn_ptr->file_entry);
   }
 
+  for(insn_ptr = model_static; insn_ptr; insn_ptr = insn_ptr->next) {
+    model_c_or_h_function(table, file, insn_ptr->file_entry, "STATIC_MODEL");
+  }
+
   for(insn_ptr = model_internal; insn_ptr; insn_ptr = insn_ptr->next) {
     model_c_or_h_function(table, file, insn_ptr->file_entry, "STATIC_INLINE_MODEL");
   }
 
+  for(insn_ptr = model_static; insn_ptr; insn_ptr = insn_ptr->next) {
+    model_c_function(table, file, insn_ptr->file_entry, "STATIC_MODEL");
+  }
+
   for(insn_ptr = model_internal; insn_ptr; insn_ptr = insn_ptr->next) {
     model_c_function(table, file, insn_ptr->file_entry, "STATIC_INLINE_MODEL");
   }
@@ -3208,8 +3203,6 @@ gen_model_c(insn_table *table, lf *file)
       model_init_p = 1;
     else if (strcmp (name, "model_halt") == 0)
       model_halt_p = 1;
-    else if (strcmp (name, "model_issue") == 0)
-      model_issue_p = 1;
     else if (strcmp (name, "model_mon_info") == 0)
       model_mon_info_p = 1;
     else if (strcmp (name, "model_mon_info_free") == 0)
@@ -3238,17 +3231,6 @@ gen_model_c(insn_table *table, lf *file)
     lf_printf(file, "\n");
   }
 
-  if (!model_issue_p) {
-    lf_printf(file, "INLINE_MODEL void model_issue(itable_index index,\n");
-    lf_printf(file, "                              model_data *model_ptr,\n");
-    lf_printf(file, "                              unsigned_word cia,\n");
-    lf_printf(file, "                              idecode_cache *cache_entry,\n");
-    lf_printf(file, "                              instruction_word instruction)\n");
-    lf_printf(file, "{\n");
-    lf_printf(file, "}\n");
-    lf_printf(file, "\n");
-  }
-
   if (!model_mon_info_p) {
     lf_printf(file, "INLINE_MODEL model_print *model_mon_info(model_data *model_ptr)\n");
     lf_printf(file, "{\n");
index e0f0a1d74984b85a9d3dbc988210b308f7cca697..ffdcbeffd363744d416329d956cd6c8c2ad60a0f 100644 (file)
@@ -65,6 +65,7 @@
 #
 #      6       Comma separated list of functional units
 
+\f
 # PowerPC models
 ::model:604:ppc604:  PPC_UNIT_BAD,   PPC_UNIT_BAD,   1,  1,  0
 ::model:603e:ppc603e:PPC_UNIT_BAD,   PPC_UNIT_BAD,   1,  1,  0
          unsigned32        flags;                      /* any flags that are needed */
        };
 
-       /* Register mappings */
-       #define PPC_INT_REG     0                       /* start of integer registers */
-       #define PPC_FLOAT_REG   (PPC_INT_REG + 32)      /* start of floating point registers */
-       #define PPC_CR_REG      (PPC_FLOAT_REG + 32)    /* start of CR0 .. CR7 */
-       #define PPC_SPR_REG     (PPC_CR_REG + 8)        /* start of special purpose registers */
-       #define PPC_FPSCR_REG   (PPC_SPR_REG + 1024)    /* start of fpscr register */
-       #define NR_PPC_REGS     (PPC_FPSCR_REG + 1)     /* # of registers to allocate */
-
-       /* Structure for each register to indicate whether it is free or not */
-       typedef struct _model_reg model_reg;
-       struct _model_reg {
-         model_reg *next;                              /* next register to be released */
-         int in_use;                                   /* non zero if register is used */
-       };
+       /* Register mappings in status masks */
+       #define PPC_CR_REG      0                       /* start of CR0 .. CR7 */
+       #define PPC_FPSCR_REG   (PPC_CR_REG + 8)        /* start of fpscr register */
+
+       #define PPC_NO_SPR      (-1)                    /* flag for no SPR register */
 
        /* Structure for each functional unit that is busy */
        typedef struct _model_busy model_busy;
        struct _model_busy {
          model_busy *next;                             /* next function unit */
-         model_reg *reg;                               /* list of registers to release */
          ppc_function_unit unit;                       /* function unit name */
-         signed16 issue;                               /* # of cycles until unit can accept another insn */
-         signed16 done;                                /* # of cycles until insn is done */
+         unsigned32 int_busy;                          /* int registers that are busy */
+         unsigned32 fp_busy;                           /* floating point registers that are busy */
+         unsigned32 cr_fpscr_busy;                     /* CR/FPSCR registers that are busy */
+         signed16 spr_busy;                            /* SPR register that is busy or PPC_NO_SPR */
+         signed8 issue;                                /* # of cycles until unit can accept another insn */
+         signed8 done;                                 /* # of cycles until insn is done */
        };
 
        /* Structure to hold the current state information for the simulated CPU model */
          const model_time *timing;                     /* timing information */
          model_busy *busy_list;                        /* list of busy function units */
          model_busy *free_list;                        /* list of model_busy structs not in use */
-         model_reg registers[NR_PPC_REGS];             /* register status */
          count_type nr_cycles;                         /* # cycles */
          count_type nr_branches;                       /* # branches */
          count_type nr_branches_fallthrough;           /* # conditional branches that fell through */
          count_type nr_stalls_data;                    /* # of stalls for data */
          count_type nr_stalls_unit;                    /* # of stalls waiting for a function unit */
          count_type nr_stalls_serialize;               /* # of stalls waiting for things to quiet down */
-         count_type nr_insns_not_handled;              /* # of instructions not handled */
          count_type nr_units[nr_ppc_function_units];   /* function unit counts */
-         int insn_handled;                             /* whether last insn was handled */
-         unsigned_1 busy[nr_ppc_function_units];       /* whether a function is busy or not */
+         unsigned32 int_busy;                          /* int registers that are busy */
+         unsigned32 fp_busy;                           /* floating point registers that are busy */
+         unsigned32 cr_fpscr_busy;                     /* CR/FPSCR registers that are busy */
+         unsigned8 spr_busy[nr_of_sprs];               /* SPR registers that are busy */
+         unsigned8 busy[nr_ppc_function_units];        /* whether a function is busy or not */
        };
 
        STATIC_MODEL const char *const ppc_function_unit_name[ (int)nr_ppc_function_units ] = {
          "branch functional unit instruction",
        };
 
-# Code called after executing the semantics of the function
-void::model-function::model_cleanup:itable_index index, model_data *model_ptr
-       if (model_ptr->insn_handled)
-         model_ptr->insn_handled = 0;
-       else {
-         model_ptr->nr_insns_not_handled++;
-         TRACE(trace_tbd,("model specific code for %s not done\n", itable[index].name));
+\f
+# Trace releasing resources
+void::model-static::model_trace_release:model_data *model_ptr, model_busy *busy
+       int i;
+       TRACE(trace_model,("done, %s\n", ppc_function_unit_name[busy->unit]));
+       if (busy->int_busy) {
+         for(i = 0; i < 32; i++) {
+           if (((1 << i) & busy->int_busy) != 0) {
+             TRACE(trace_model, ("Register r%d is now available.\n", i));
+           }
+         }
+       }
+       if (busy->fp_busy) {
+         for(i = 0; i < 32; i++) {
+           if (((1 << i) & busy->fp_busy) != 0) {
+             TRACE(trace_model, ("Register f%d is now available.\n", i));
+           }
+         }
+       }
+       if (busy->cr_fpscr_busy) {
+         for(i = 0; i < 8; i++) {
+           if (((1 << i) & busy->cr_fpscr_busy) != 0) {
+             TRACE(trace_model, ("Register cr%d is now available.\n", i));
+           }
+         }
+         if (busy->cr_fpscr_busy & 0x100)
+           TRACE(trace_model, ("Register fpscr is now available.\n"));
        }
+       if (busy->spr_busy != PPC_NO_SPR)
+         TRACE(trace_model, ("Register %s is now available.\n", spr_name(busy->spr_busy)));
 
+# Trace waiting for registers to become available
+void::model-static::model_trace_busy_p:model_data *model_ptr, unsigned32 int_busy, unsigned32 fp_busy, unsigned32 cr_or_fpscr_busy, int spr_busy
+       int i;
+       if (int_busy) {
+         int_busy &= model_ptr->int_busy;
+         for(i = 0; i < 32; i++) {
+           if (((1 << i) & int_busy) != 0) {
+             TRACE(trace_model, ("Waiting for register r%d.\n", i));
+           }
+         }
+       }
+       if (fp_busy) {
+         fp_busy &= model_ptr->fp_busy;
+         for(i = 0; i < 32; i++) {
+           if (((1 << i) & fp_busy) != 0) {
+             TRACE(trace_model, ("Waiting for register f%d.\n", i));
+           }
+         }
+       }
+       if (cr_or_fpscr_busy) {
+         cr_or_fpscr_busy &= model_ptr->cr_fpscr_busy;
+         for(i = 0; i < 8; i++) {
+           if (((1 << i) & cr_or_fpscr_busy) != 0) {
+             TRACE(trace_model, ("Waiting for register cr%d.\n", i));
+           }
+         }
+         if (cr_or_fpscr_busy & 0x100)
+           TRACE(trace_model, ("Waiting for register fpscr.\n"));
+       }
+       if (spr_busy != PPC_NO_SPR && model_ptr->spr_busy[spr_busy])
+         TRACE(trace_model, ("Waiting for register %s.\n", spr_name(spr_busy)));
+\f
 # Advance state to next cycle, releasing any registers allocated
 void::model-internal::model_new_cycle:model_data *model_ptr
        model_busy *cur_busy  = model_ptr->busy_list;
@@ -174,13 +224,15 @@ void::model-internal::model_new_cycle:model_data *model_ptr
        for ( ; cur_busy; cur_busy = next) {
          next = cur_busy->next;
          if (--cur_busy->done <= 0) {          /* function unit done, release registers */
-           model_reg *reg = cur_busy->reg;
-           TRACE(trace_model,("done, retiring %s\n", ppc_function_unit_name[cur_busy->unit]));
-           while (reg) {
-             TRACE(trace_model,("freeing up reg, address 0x%lx (%d)\n", (long)reg, reg - &model_ptr->registers[0]));
-             reg->in_use = 0;
-             reg = reg->next;
-           }
+           model_ptr->int_busy &= ~cur_busy->int_busy;
+           model_ptr->fp_busy &= ~cur_busy->fp_busy;
+           model_ptr->cr_fpscr_busy &= ~cur_busy->cr_fpscr_busy;
+           if (cur_busy->spr_busy != PPC_NO_SPR)
+             model_ptr->spr_busy[cur_busy->spr_busy] = 0;
+
+           if (WITH_TRACE && ppc_trace[trace_model])
+             model_trace_release(model_ptr, cur_busy);
+
            model_ptr->busy[cur_busy->unit] = 0;
            cur_busy->next = free_list;
            free_list = cur_busy;
@@ -204,12 +256,11 @@ void::model-internal::model_new_cycle:model_data *model_ptr
        model_ptr->busy_list = next_busy;
        model_ptr->free_list = free_list;
 
-# Mark a function unit as busy, return the busy structure so regs can be added to be released
+# Mark a function unit as busy, return the busy structure
 model_busy *::model-internal::model_make_busy:model_data *model_ptr, ppc_function_unit unit, int issue, int done
        model_busy *busy;
 
        TRACE(trace_model,("unit = %s, issue = %d, done = %d\n", ppc_function_unit_name[unit], issue, done));
-       model_ptr->insn_handled = 1;
 
        if (!model_ptr->free_list) {
          busy = ZALLOC(model_busy);
@@ -217,17 +268,45 @@ model_busy *::model-internal::model_make_busy:model_data *model_ptr, ppc_functio
        else {
          busy = model_ptr->free_list;
          model_ptr->free_list = busy->next;
-         busy->reg = (model_reg *)0;
        }
        busy->next = model_ptr->busy_list;
        busy->unit = unit;
        busy->issue = issue;
        busy->done = done;
+       busy->int_busy = 0;
+       busy->fp_busy = 0;
+       busy->cr_fpscr_busy = 0;
+       busy->spr_busy = PPC_NO_SPR;
        model_ptr->busy_list = busy;
        model_ptr->busy[unit] = 1;
        model_ptr->nr_units[unit]++;
        return busy;
-
+\f
+# Make a given integer register busy
+void::model-internal::model_make_int_reg_busy:model_data *model_ptr, model_busy *busy_ptr, int regno
+       TRACE(trace_model,("Marking register r%d as busy\n", regno));
+       busy_ptr->int_busy |= (1 << regno);
+       model_ptr->int_busy |= (1 << regno);
+
+# Make a given floating point register busy
+void::model-internal::model_make_fp_reg_busy:model_data *model_ptr, model_busy *busy_ptr, int regno
+       TRACE(trace_model,("Marking register f%d as busy\n", regno));
+       busy_ptr->fp_busy |= (1 << regno);
+       model_ptr->fp_busy |= (1 << regno);
+
+# Make a given CR register busy
+void::model-internal::model_make_cr_reg_busy:model_data *model_ptr, model_busy *busy_ptr, int regno
+       TRACE(trace_model,("Marking register cr%d as busy\n", regno));
+       busy_ptr->cr_fpscr_busy |= (1 << regno);
+       model_ptr->cr_fpscr_busy |= (1 << regno);
+
+# Make a given SPR register busy
+void::model-internal::model_make_spr_reg_busy:model_data *model_ptr, model_busy *busy_ptr, int regno
+       TRACE(trace_model,("Marking register %s as busy\n", spr_name(regno)));
+       busy_ptr->spr_busy = regno;
+       model_ptr->spr_busy[regno] = 1;
+
+\f
 # Wait until a function unit is non-busy, and then allocate a busy pointer & return the pointer
 model_busy *::model-internal::model_wait_for_unit:itable_index index, model_data *const model_ptr, const model_time *const time_ptr
        ppc_function_unit first_unit = time_ptr->first_unit;
@@ -266,11 +345,13 @@ void::model-function::model_serialize:itable_index index, model_data *model_ptr
 # Wait for a CR to become unbusy
 void::model-function::model_wait_for_cr:model_data *model_ptr, unsigned CRBIT
        unsigned u;
+       unsigned32 cr_mask;
        int cr_var = 0;
        for (u = 0xc0000000; (u != 0) && (CRBIT & u) == 0; u >>= 4 )
          cr_var++;
 
-       while (model_ptr->registers[cr_var + PPC_CR_REG].in_use) {
+       cr_mask = (1 << cr_var);
+       while ((model_ptr->cr_fpscr_busy & cr_mask) != 0) {
          TRACE(trace_model,("waiting for CR %d\n", cr_var));
          model_ptr->nr_stalls_data++;
          model_new_cycle(model_ptr);
@@ -278,92 +359,144 @@ void::model-function::model_wait_for_cr:model_data *model_ptr, unsigned CRBIT
 
 # Schedule an instruction that takes 2 integer input registers and produces an output register & possibly sets CR0
 void::model-function::ppc_insn_int2:itable_index index, cpu *processor, model_data *model_ptr, signed_word *rD, signed_word *rA, signed_word *rB, unsigned Rc
+       registers *cpu_regs = cpu_registers(processor);
+       const unsigned ppc_RA = (rA - &cpu_regs->gpr[0]);
+       const unsigned ppc_RB = (rB - &cpu_regs->gpr[0]);
+       const unsigned ppc_RD = (rD - &cpu_regs->gpr[0]);
+       const unsigned32 int_mask = (1 << ppc_RA) | (1 << ppc_RB) | (1 << ppc_RD);
+       model_busy *busy_ptr;
+
        if (!WITH_MODEL_ISSUE)
          return;
 
+       else if (!Rc) {
+         if ((model_ptr->int_busy & int_mask) != 0) {
+           model_new_cycle(model_ptr);                 /* don't count first dependency as a stall */
+
+           while ((model_ptr->int_busy & int_mask) != 0) {
+             if (WITH_TRACE && ppc_trace[trace_model])
+               model_trace_busy_p(model_ptr, int_mask, 0, 0, PPC_NO_SPR);
+
+             model_ptr->nr_stalls_data++;
+             model_new_cycle(model_ptr);
+           }
+         }
+
+         busy_ptr = model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]);
+         model_make_int_reg_busy(model_ptr, busy_ptr, ppc_RD);
+         return;
+       }
+
        else {
-         registers *cpu_regs = cpu_registers(processor);
-         const unsigned ppc_RA = (rA - &cpu_regs->gpr[0]) + PPC_INT_REG;
-         const unsigned ppc_RB = (rB - &cpu_regs->gpr[0]) + PPC_INT_REG;
-         const unsigned ppc_RD = (rD - &cpu_regs->gpr[0]) + PPC_INT_REG;
-         model_reg *ppc_regs = model_ptr->registers;
-         model_busy *busy_ptr;
+         const unsigned32 cr_mask = (1 << 0);
 
-         if (ppc_regs[ppc_RA].in_use | ppc_regs[ppc_RB].in_use) {
+         if ((model_ptr->int_busy & int_mask) || (model_ptr->cr_fpscr_busy & cr_mask)) {
            model_new_cycle(model_ptr);                 /* don't count first dependency as a stall */
 
-           while (ppc_regs[ppc_RA].in_use | ppc_regs[ppc_RB].in_use) {
+           while ((model_ptr->int_busy & int_mask) || (model_ptr->cr_fpscr_busy & cr_mask)) {
+             if (WITH_TRACE && ppc_trace[trace_model])
+               model_trace_busy_p(model_ptr, int_mask, 0, cr_mask, PPC_NO_SPR);
+
              model_ptr->nr_stalls_data++;
              model_new_cycle(model_ptr);
            }
          }
 
          busy_ptr = model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]);
-         ppc_regs[ppc_RD].next = (model_reg *)0;
-         ppc_regs[ppc_RD].in_use = 1;
-         if (!Rc)
-           busy_ptr->reg = &ppc_regs[ppc_RD];
-         else {
-           model_reg *reg_CR0 = &ppc_regs[0 + PPC_CR_REG];
-           reg_CR0->next = &ppc_regs[ppc_RD];
-           busy_ptr->reg = reg_CR0;
-         }
+         model_make_int_reg_busy(model_ptr, busy_ptr, ppc_RD);
+         model_make_cr_reg_busy(model_ptr, busy_ptr, 0);
+         return;
        }
 
 # Schedule an instruction that takes 1 integer input registers and produces an output register & possibly sets CR0
 void::model-function::ppc_insn_int1:itable_index index, cpu *processor, model_data *model_ptr, signed_word *rD, signed_word *rA, unsigned Rc
+       registers *cpu_regs = cpu_registers(processor);
+       const unsigned ppc_RA = (rA - &cpu_regs->gpr[0]);
+       const unsigned ppc_RD = (rD - &cpu_regs->gpr[0]);
+       const unsigned32 int_mask = (1 << ppc_RA) | (1 << ppc_RD);
+       model_busy *busy_ptr;
+
        if (!WITH_MODEL_ISSUE)
          return;
 
+       else if (!Rc) {
+         if ((model_ptr->int_busy & int_mask) != 0) {
+           model_new_cycle(model_ptr);                 /* don't count first dependency as a stall */
+
+           while ((model_ptr->int_busy & int_mask) != 0) {
+             if (WITH_TRACE && ppc_trace[trace_model])
+               model_trace_busy_p(model_ptr, int_mask, 0, 0, PPC_NO_SPR);
+
+             model_ptr->nr_stalls_data++;
+             model_new_cycle(model_ptr);
+           }
+         }
+
+         busy_ptr = model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]);
+         model_make_int_reg_busy(model_ptr, busy_ptr, ppc_RD);
+         return;
+       }
+
        else {
-         registers *cpu_regs = cpu_registers(processor);
-         const unsigned ppc_RA = (rA - &cpu_regs->gpr[0]) + PPC_INT_REG;
-         const unsigned ppc_RD = (rD - &cpu_regs->gpr[0]) + PPC_INT_REG;
-         model_reg *ppc_regs = model_ptr->registers;
-         model_busy *busy_ptr;
+         const unsigned32 cr_mask = (1 << 0);
 
-       if (ppc_regs[ppc_RA].in_use) {
+         if ((model_ptr->int_busy & int_mask) || (model_ptr->cr_fpscr_busy & cr_mask)) {
            model_new_cycle(model_ptr);                 /* don't count first dependency as a stall */
 
-           while (ppc_regs[ppc_RA].in_use) {
+           while ((model_ptr->int_busy & int_mask) || (model_ptr->cr_fpscr_busy & cr_mask)) {
+             if (WITH_TRACE && ppc_trace[trace_model])
+               model_trace_busy_p(model_ptr, int_mask, 0, cr_mask, PPC_NO_SPR);
+
              model_ptr->nr_stalls_data++;
              model_new_cycle(model_ptr);
            }
          }
 
          busy_ptr = model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]);
-         ppc_regs[ppc_RD].next = (model_reg *)0;
-         ppc_regs[ppc_RD].in_use = 1;
-         if (!Rc)
-           busy_ptr->reg = &ppc_regs[ppc_RD];
-         else {
-           model_reg *reg_CR0 = &ppc_regs[0 + PPC_CR_REG];
-           reg_CR0->next = &ppc_regs[ppc_RD];
-           busy_ptr->reg = reg_CR0;
-         }
+         model_make_int_reg_busy(model_ptr, busy_ptr, ppc_RD);
+         model_make_cr_reg_busy(model_ptr, busy_ptr, 0);
+         return;
        }
 
 # Schedule an instruction that takes no integer input registers and produces an output register & possibly sets CR0
 void::model-function::ppc_insn_int0:itable_index index, cpu *processor, model_data *model_ptr, signed_word *rD, unsigned Rc
+       registers *cpu_regs = cpu_registers(processor);
+       const unsigned ppc_RD = (rD - &cpu_regs->gpr[0]);
+       const unsigned32 int_mask = (1 << ppc_RD);
+       model_busy *busy_ptr;
+
        if (!WITH_MODEL_ISSUE)
          return;
 
-       else {
-         registers *cpu_regs = cpu_registers(processor);
-         const unsigned ppc_RD = (rD - &cpu_regs->gpr[0]) + PPC_INT_REG;
-         model_reg *ppc_regs = model_ptr->registers;
-         model_busy *busy_ptr;
+       else if (!Rc) {
+         while ((model_ptr->int_busy & int_mask) != 0) {
+           if (WITH_TRACE && ppc_trace[trace_model])
+             model_trace_busy_p(model_ptr, int_mask, 0, 0, PPC_NO_SPR);
+
+             model_ptr->nr_stalls_data++;
+             model_new_cycle(model_ptr);
+         }
 
          busy_ptr = model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]);
-         ppc_regs[ppc_RD].next = (model_reg *)0;
-         ppc_regs[ppc_RD].in_use = 1;
-         if (!Rc)
-           busy_ptr->reg = &ppc_regs[ppc_RD];
-         else {
-           model_reg *reg_CR0 = &ppc_regs[0 + PPC_CR_REG];
-           reg_CR0->next = &ppc_regs[ppc_RD];
-           busy_ptr->reg = reg_CR0;
+         model_make_int_reg_busy(model_ptr, busy_ptr, ppc_RD);
+         return;
+       }
+
+       else {
+         const unsigned32 cr_mask = (1 << 0);
+
+         while ((model_ptr->int_busy & int_mask) || (model_ptr->cr_fpscr_busy & cr_mask)) {
+           if (WITH_TRACE && ppc_trace[trace_model])
+             model_trace_busy_p(model_ptr, int_mask, 0, cr_mask, PPC_NO_SPR);
+
+             model_ptr->nr_stalls_data++;
+             model_new_cycle(model_ptr);
          }
+
+         busy_ptr = model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]);
+         model_make_int_reg_busy(model_ptr, busy_ptr, ppc_RD);
+         model_make_cr_reg_busy(model_ptr, busy_ptr, 0);
+         return;
        }
 
 # Schedule an instruction that takes 2 integer input registers and produces an output register & updates a second register
@@ -373,28 +506,27 @@ void::model-function::ppc_insn_int2_update:itable_index index, cpu *processor, m
 
        else {
          registers *cpu_regs = cpu_registers(processor);
-         const unsigned ppc_RA = (rA - &cpu_regs->gpr[0]) + PPC_INT_REG;
-         const unsigned ppc_RB = (rB - &cpu_regs->gpr[0]) + PPC_INT_REG;
-         const unsigned ppc_RD = (rD - &cpu_regs->gpr[0]) + PPC_INT_REG;
-         model_reg *ppc_regs = model_ptr->registers;
+         const unsigned ppc_RA = (rA - &cpu_regs->gpr[0]);
+         const unsigned ppc_RB = (rB - &cpu_regs->gpr[0]);
+         const unsigned ppc_RD = (rD - &cpu_regs->gpr[0]);
+         const unsigned32 int_mask = (1 << ppc_RA) | (1 << ppc_RB) | (1 << ppc_RD);
          model_busy *busy_ptr;
 
-         if (ppc_regs[ppc_RA].in_use | ppc_regs[ppc_RB].in_use) {
+         if ((model_ptr->int_busy & int_mask) != 0) {
            model_new_cycle(model_ptr);                 /* don't count first dependency as a stall */
 
-           while (ppc_regs[ppc_RA].in_use | ppc_regs[ppc_RB].in_use) {
+           while ((model_ptr->int_busy & int_mask) != 0) {
+             if (WITH_TRACE && ppc_trace[trace_model])
+               model_trace_busy_p(model_ptr, int_mask, 0, 0, PPC_NO_SPR);
+
              model_ptr->nr_stalls_data++;
              model_new_cycle(model_ptr);
            }
          }
 
          busy_ptr = model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]);
-         ppc_regs[ppc_RA].next = (model_reg *)0;
-         ppc_regs[ppc_RA].in_use = 1;
-
-         ppc_regs[ppc_RD].next = &ppc_regs[ppc_RA];
-         ppc_regs[ppc_RD].in_use = 1;
-         busy_ptr->reg = &ppc_regs[ppc_RD];
+         model_make_int_reg_busy(model_ptr, busy_ptr, ppc_RA);
+         model_make_int_reg_busy(model_ptr, busy_ptr, ppc_RD);
        }
 
 # Schedule an instruction that takes 1 integer input registers and produces an output register & updates the other register
@@ -404,27 +536,26 @@ void::model-function::ppc_insn_int1_update:itable_index index, cpu *processor, m
 
        else {
          registers *cpu_regs = cpu_registers(processor);
-         const unsigned ppc_RA = (rA - &cpu_regs->gpr[0]) + PPC_INT_REG;
-         const unsigned ppc_RD = (rD - &cpu_regs->gpr[0]) + PPC_INT_REG;
-         model_reg *ppc_regs = model_ptr->registers;
+         const unsigned ppc_RA = (rA - &cpu_regs->gpr[0]);
+         const unsigned ppc_RD = (rD - &cpu_regs->gpr[0]);
+         const unsigned32 int_mask = (1 << ppc_RA) | (1 << ppc_RD);
          model_busy *busy_ptr;
 
-         if (ppc_regs[ppc_RA].in_use) {
+         if ((model_ptr->int_busy & int_mask) != 0) {
            model_new_cycle(model_ptr);                 /* don't count first dependency as a stall */
 
-           while (ppc_regs[ppc_RA].in_use) {
+           while ((model_ptr->int_busy & int_mask) != 0) {
+             if (WITH_TRACE && ppc_trace[trace_model])
+               model_trace_busy_p(model_ptr, int_mask, 0, 0, PPC_NO_SPR);
+
              model_ptr->nr_stalls_data++;
              model_new_cycle(model_ptr);
            }
          }
 
          busy_ptr = model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]);
-         ppc_regs[ppc_RA].next = (model_reg *)0;
-         ppc_regs[ppc_RA].in_use = 1;
-
-         ppc_regs[ppc_RD].next = &ppc_regs[ppc_RA];
-         ppc_regs[ppc_RD].in_use = 1;
-         busy_ptr->reg = &ppc_regs[ppc_RD];
+         model_make_int_reg_busy(model_ptr, busy_ptr, ppc_RA);
+         model_make_int_reg_busy(model_ptr, busy_ptr, ppc_RD);
        }
 
 # Schedule an instruction that takes 2 integer input registers and produces no output register
@@ -434,14 +565,17 @@ void::model-function::ppc_insn_int2_noout:itable_index index, cpu *processor, mo
 
        else {
          registers *cpu_regs = cpu_registers(processor);
-         const unsigned ppc_RA = (rA - &cpu_regs->gpr[0]) + PPC_INT_REG;
-         const unsigned ppc_RB = (rB - &cpu_regs->gpr[0]) + PPC_INT_REG;
-         model_reg *ppc_regs = model_ptr->registers;
+         const unsigned ppc_RA = (rA - &cpu_regs->gpr[0]);
+         const unsigned ppc_RB = (rB - &cpu_regs->gpr[0]);
+         const unsigned32 int_mask = (1 << ppc_RA) | (1 << ppc_RB);
 
-         if (ppc_regs[ppc_RA].in_use | ppc_regs[ppc_RB].in_use) {
+         if ((model_ptr->int_busy & int_mask) != 0) {
            model_new_cycle(model_ptr);                 /* don't count first dependency as a stall */
 
-           while (ppc_regs[ppc_RA].in_use | ppc_regs[ppc_RB].in_use) {
+           while ((model_ptr->int_busy & int_mask) != 0) {
+             if (WITH_TRACE && ppc_trace[trace_model])
+               model_trace_busy_p(model_ptr, int_mask, 0, 0, PPC_NO_SPR);
+
              model_ptr->nr_stalls_data++;
              model_new_cycle(model_ptr);
            }
@@ -457,13 +591,16 @@ void::model-function::ppc_insn_int1_noout:itable_index index, cpu *processor, mo
 
        else {
          registers *cpu_regs = cpu_registers(processor);
-         const unsigned ppc_RA = (rA - &cpu_regs->gpr[0]) + PPC_INT_REG;
-         model_reg *ppc_regs = model_ptr->registers;
+         const unsigned ppc_RA = (rA - &cpu_regs->gpr[0]);
+         const unsigned32 int_mask = (1 << ppc_RA);
 
-         if (ppc_regs[ppc_RA].in_use) {
+         if ((model_ptr->int_busy & int_mask) != 0) {
            model_new_cycle(model_ptr);                 /* don't count first dependency as a stall */
 
-           while (ppc_regs[ppc_RA].in_use) {
+           while ((model_ptr->int_busy & int_mask) != 0) {
+             if (WITH_TRACE && ppc_trace[trace_model])
+               model_trace_busy_p(model_ptr, int_mask, 0, 0, PPC_NO_SPR);
+
              model_ptr->nr_stalls_data++;
              model_new_cycle(model_ptr);
            }
@@ -488,25 +625,26 @@ void::model-function::ppc_insn_int2_cr:itable_index index, cpu *processor, model
 
        else {
          registers *cpu_regs = cpu_registers(processor);
-         const unsigned ppc_RA = (rA - &cpu_regs->gpr[0]) + PPC_INT_REG;
-         const unsigned ppc_RB = (rB - &cpu_regs->gpr[0]) + PPC_INT_REG;
-         const unsigned ppc_CRD = CRD + PPC_CR_REG;
-         model_reg *ppc_regs = model_ptr->registers;
+         const unsigned ppc_RA = (rA - &cpu_regs->gpr[0]);
+         const unsigned ppc_RB = (rB - &cpu_regs->gpr[0]);
+         const unsigned32 int_mask = (1 << ppc_RA) | (1 << ppc_RB);
+         const unsigned32 cr_mask = (1 << CRD);
          model_busy *busy_ptr;
 
-         if (ppc_regs[ppc_RA].in_use | ppc_regs[ppc_RB].in_use) {
+         if ((model_ptr->int_busy & int_mask) || (model_ptr->cr_fpscr_busy & cr_mask)) {
            model_new_cycle(model_ptr);                 /* don't count first dependency as a stall */
 
-           while (ppc_regs[ppc_RA].in_use | ppc_regs[ppc_RB].in_use) {
+           while ((model_ptr->int_busy & int_mask) || (model_ptr->cr_fpscr_busy & cr_mask)) {
+             if (WITH_TRACE && ppc_trace[trace_model])
+               model_trace_busy_p(model_ptr, int_mask, 0, cr_mask, PPC_NO_SPR);
+
              model_ptr->nr_stalls_data++;
              model_new_cycle(model_ptr);
            }
          }
 
          busy_ptr = model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]);
-         ppc_regs[ppc_CRD].next = (model_reg *)0;
-         ppc_regs[ppc_CRD].in_use = 1;
-         busy_ptr->reg = &ppc_regs[ppc_CRD];
+         model_make_cr_reg_busy(model_ptr, busy_ptr, CRD);
        }
 
 # Schedule an instruction that takes 1 integer input register and produces a CR output register
@@ -516,24 +654,271 @@ void::model-function::ppc_insn_int1_cr:itable_index index, cpu *processor, model
 
        else {
          registers *cpu_regs = cpu_registers(processor);
-         const unsigned ppc_RA = (rA - &cpu_regs->gpr[0]) + PPC_INT_REG;
-         const unsigned ppc_CRD = CRD + PPC_CR_REG;
-         model_reg *ppc_regs = model_ptr->registers;
+         const unsigned ppc_RA = (rA - &cpu_regs->gpr[0]);
+         const unsigned32 int_mask = (1 << ppc_RA);
+         const unsigned32 cr_mask = (1 << CRD);
+         model_busy *busy_ptr;
+
+         if ((model_ptr->int_busy & int_mask) || (model_ptr->cr_fpscr_busy & cr_mask)) {
+           model_new_cycle(model_ptr);                 /* don't count first dependency as a stall */
+
+           while ((model_ptr->int_busy & int_mask) || (model_ptr->cr_fpscr_busy & cr_mask)) {
+             if (WITH_TRACE && ppc_trace[trace_model])
+               model_trace_busy_p(model_ptr, int_mask, 0, cr_mask, PPC_NO_SPR);
+
+             model_ptr->nr_stalls_data++;
+             model_new_cycle(model_ptr);
+           }
+         }
+
+         busy_ptr = model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]);
+         model_make_cr_reg_busy(model_ptr, busy_ptr, CRD);
+       }
+
+# Schedule an instruction that takes 3 floating point input registers and produces an output register & possibly sets CR1
+void::model-function::ppc_insn_fp3:itable_index index, cpu *processor, model_data *model_ptr, unsigned64 *rD, unsigned64 *rA, unsigned64 *rB, unsigned64 *rC, unsigned Rc
+       registers *cpu_regs = cpu_registers(processor);
+       const unsigned ppc_RA = (rA - &cpu_regs->fpr[0]);
+       const unsigned ppc_RB = (rB - &cpu_regs->fpr[0]);
+       const unsigned ppc_RC = (rC - &cpu_regs->fpr[0]);
+       const unsigned ppc_RD = (rD - &cpu_regs->fpr[0]);
+       const unsigned32 fp_mask = (1 << ppc_RA) | (1 << ppc_RB) | (1 << ppc_RC) | (1 << ppc_RD);
+       model_busy *busy_ptr;
+
+       if (!WITH_MODEL_ISSUE)
+         return;
+
+       else if (!Rc) {
+         if ((model_ptr->fp_busy & fp_mask) != 0) {
+           model_new_cycle(model_ptr);                 /* don't count first dependency as a stall */
+
+           while ((model_ptr->fp_busy & fp_mask) != 0) {
+             if (WITH_TRACE && ppc_trace[trace_model])
+               model_trace_busy_p(model_ptr, 0, fp_mask, 0, PPC_NO_SPR);
+
+             model_ptr->nr_stalls_data++;
+             model_new_cycle(model_ptr);
+           }
+         }
+
+         busy_ptr = model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]);
+         model_make_fp_reg_busy(model_ptr, busy_ptr, ppc_RD);
+         return;
+       }
+
+       else {
+         const unsigned32 cr_mask = (1 << 1);
+         if ((model_ptr->fp_busy & fp_mask) || (model_ptr->cr_fpscr_busy & cr_mask)) {
+           model_new_cycle(model_ptr);                 /* don't count first dependency as a stall */
+
+           while ((model_ptr->fp_busy & fp_mask) || (model_ptr->cr_fpscr_busy & cr_mask)) {
+             if (WITH_TRACE && ppc_trace[trace_model])
+               model_trace_busy_p(model_ptr, 0, fp_mask, cr_mask, PPC_NO_SPR);
+
+             model_ptr->nr_stalls_data++;
+             model_new_cycle(model_ptr);
+           }
+         }
+
+         busy_ptr = model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]);
+         model_make_fp_reg_busy(model_ptr, busy_ptr, ppc_RD);
+         model_make_cr_reg_busy(model_ptr, busy_ptr, 1);
+         return;
+       }
+
+# Schedule an instruction that takes 2 floating point input registers and produces an output register & possibly sets CR1
+void::model-function::ppc_insn_fp2:itable_index index, cpu *processor, model_data *model_ptr, unsigned64 *rD, unsigned64 *rA, unsigned64 *rB, unsigned Rc
+       registers *cpu_regs = cpu_registers(processor);
+       const unsigned ppc_RA = (rA - &cpu_regs->fpr[0]);
+       const unsigned ppc_RB = (rB - &cpu_regs->fpr[0]);
+       const unsigned ppc_RD = (rD - &cpu_regs->fpr[0]);
+       const unsigned32 fp_mask = (1 << ppc_RA) | (1 << ppc_RB) | (1 << ppc_RD);
+       model_busy *busy_ptr;
+
+       if (!WITH_MODEL_ISSUE)
+         return;
+
+       else if (!Rc) {
+         if ((model_ptr->fp_busy & fp_mask) != 0) {
+           model_new_cycle(model_ptr);                 /* don't count first dependency as a stall */
+
+           while ((model_ptr->fp_busy & fp_mask) != 0) {
+             if (WITH_TRACE && ppc_trace[trace_model])
+               model_trace_busy_p(model_ptr, 0, fp_mask, 0, PPC_NO_SPR);
+
+             model_ptr->nr_stalls_data++;
+             model_new_cycle(model_ptr);
+           }
+         }
+
+         busy_ptr = model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]);
+         model_make_fp_reg_busy(model_ptr, busy_ptr, ppc_RD);
+       }
+
+       else {
+         const unsigned32 cr_mask = (1 << 1);
+
+         if ((model_ptr->fp_busy & fp_mask) || (model_ptr->cr_fpscr_busy & cr_mask)) {
+           model_new_cycle(model_ptr);                 /* don't count first dependency as a stall */
+
+           while ((model_ptr->fp_busy & fp_mask) || (model_ptr->cr_fpscr_busy & cr_mask)) {
+             if (WITH_TRACE && ppc_trace[trace_model])
+               model_trace_busy_p(model_ptr, 0, fp_mask, cr_mask, PPC_NO_SPR);
+
+             model_ptr->nr_stalls_data++;
+             model_new_cycle(model_ptr);
+           }
+         }
+
+         busy_ptr = model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]);
+         model_make_fp_reg_busy(model_ptr, busy_ptr, ppc_RD);
+         model_make_cr_reg_busy(model_ptr, busy_ptr, 1);
+       }
+
+# Schedule an instruction that takes 1 floating point input registers and produces an output register & possibly sets CR1
+void::model-function::ppc_insn_fp1:itable_index index, cpu *processor, model_data *model_ptr, unsigned64 *rD, unsigned64 *rA, unsigned Rc
+       registers *cpu_regs = cpu_registers(processor);
+       const unsigned ppc_RA = (rA - &cpu_regs->fpr[0]);
+       const unsigned ppc_RD = (rD - &cpu_regs->fpr[0]);
+       const unsigned32 fp_mask = (1 << ppc_RA) | (1 << ppc_RD);
+       model_busy *busy_ptr;
+
+       if (!WITH_MODEL_ISSUE)
+         return;
+
+       else if (!Rc) {
+         if ((model_ptr->fp_busy & fp_mask) != 0) {
+           model_new_cycle(model_ptr);                 /* don't count first dependency as a stall */
+
+           while ((model_ptr->fp_busy & fp_mask) != 0) {
+             if (WITH_TRACE && ppc_trace[trace_model])
+               model_trace_busy_p(model_ptr, 0, fp_mask, 0, PPC_NO_SPR);
+
+             model_ptr->nr_stalls_data++;
+             model_new_cycle(model_ptr);
+           }
+         }
+
+         busy_ptr = model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]);
+         model_make_fp_reg_busy(model_ptr, busy_ptr, ppc_RD);
+       }
+
+       else {
+         const unsigned32 cr_mask = (1 << 1);
+
+         if ((model_ptr->fp_busy & fp_mask) || (model_ptr->cr_fpscr_busy & cr_mask)) {
+           model_new_cycle(model_ptr);                 /* don't count first dependency as a stall */
+
+           while ((model_ptr->fp_busy & fp_mask) || (model_ptr->cr_fpscr_busy & cr_mask)) {
+             if (WITH_TRACE && ppc_trace[trace_model])
+               model_trace_busy_p(model_ptr, 0, fp_mask, cr_mask, PPC_NO_SPR);
+
+             model_ptr->nr_stalls_data++;
+             model_new_cycle(model_ptr);
+           }
+         }
+
+         busy_ptr = model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]);
+         model_make_fp_reg_busy(model_ptr, busy_ptr, ppc_RD);
+         model_make_cr_reg_busy(model_ptr, busy_ptr, 1);
+       }
+
+# Schedule an instruction that takes 1 floating point input register & 2 integer registers and does not produce an output
+# (or takes 2 integer registers and produces an output in the floating point register)
+void::model-function::ppc_insn_int2_fp1:itable_index index, cpu *processor, model_data *model_ptr, unsigned64 *rD, signed_word *rA, signed_word *rB, int RD_is_output, int RA_is_update
+       if (!WITH_MODEL_ISSUE)
+         return;
+
+       else {
+         registers *cpu_regs = cpu_registers(processor);
+         const unsigned ppc_RA = (rA - &cpu_regs->gpr[0]);
+         const unsigned ppc_RB = (rB - &cpu_regs->gpr[0]);
+         const unsigned ppc_RD = (rD - &cpu_regs->fpr[0]);
+         const unsigned32 int_mask =  (1 << ppc_RB) | ((ppc_RA == 0) ? 0 : (1 << ppc_RA));
+         const unsigned32 fp_mask = (1 << ppc_RD);
+         model_busy *busy_ptr;
+
+         if ((model_ptr->int_busy & int_mask) || (model_ptr->fp_busy & fp_mask)) {
+           model_new_cycle(model_ptr);                 /* don't count first dependency as a stall */
+
+           while ((model_ptr->int_busy & int_mask) || (model_ptr->fp_busy & fp_mask)) {
+             if (WITH_TRACE && ppc_trace[trace_model])
+               model_trace_busy_p(model_ptr, int_mask, fp_mask, 0, PPC_NO_SPR);
+
+             model_ptr->nr_stalls_data++;
+             model_new_cycle(model_ptr);
+           }
+         }
+
+         busy_ptr = model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]);
+         if (RD_is_output)
+           model_make_fp_reg_busy(model_ptr, busy_ptr, ppc_RD);
+
+         if (RA_is_update)
+           model_make_int_reg_busy(model_ptr, busy_ptr, ppc_RA);
+       }
+
+# Schedule an instruction that takes 1 floating point input register & 1 integer register and does not produce an output
+# (or takes 1 integer register and produces an output in the floating point register)
+void::model-function::ppc_insn_int1_fp1:itable_index index, cpu *processor, model_data *model_ptr, unsigned64 *rD, signed_word *rA, int RD_is_output, int RA_is_update
+       if (!WITH_MODEL_ISSUE)
+         return;
+
+       else {
+         registers *cpu_regs = cpu_registers(processor);
+         const unsigned ppc_RA = (rA - &cpu_regs->gpr[0]);
+         const unsigned ppc_RD = (rD - &cpu_regs->fpr[0]);
+         const unsigned32 int_mask = ((ppc_RA == 0) ? 0 : (1 << ppc_RA));
+         const unsigned32 fp_mask = (1 << ppc_RD);
+         model_busy *busy_ptr;
+
+         if ((model_ptr->int_busy & int_mask) || (model_ptr->fp_busy & fp_mask)) {
+           model_new_cycle(model_ptr);                 /* don't count first dependency as a stall */
+
+           while ((model_ptr->int_busy & int_mask) || (model_ptr->fp_busy & fp_mask)) {
+             if (WITH_TRACE && ppc_trace[trace_model])
+               model_trace_busy_p(model_ptr, int_mask, fp_mask, 0, PPC_NO_SPR);
+
+             model_ptr->nr_stalls_data++;
+             model_new_cycle(model_ptr);
+           }
+         }
+
+         busy_ptr = model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]);
+         if (RD_is_output)
+           model_make_fp_reg_busy(model_ptr, busy_ptr, ppc_RD);
+
+         if (RA_is_update)
+           model_make_int_reg_busy(model_ptr, busy_ptr, ppc_RA);
+       }
+
+# Schedule an instruction that takes 2 floating input registers and produces a CR output register
+void::model-function::ppc_insn_fp2_cr:itable_index index, cpu *processor, model_data *model_ptr, unsigned CRD, unsigned64 *rA, unsigned64 *rB
+       if (!WITH_MODEL_ISSUE)
+         return;
+
+       else {
+         registers *cpu_regs = cpu_registers(processor);
+         const unsigned ppc_RA = (rA - &cpu_regs->fpr[0]);
+         const unsigned ppc_RB = (rB - &cpu_regs->fpr[0]);
+         const unsigned32 fp_mask = (1 << ppc_RA) | (1 << ppc_RB);
+         const unsigned32 cr_mask = (1 << CRD);
          model_busy *busy_ptr;
 
-         if (ppc_regs[ppc_RA].in_use) {
+         if (((model_ptr->fp_busy & fp_mask) | (model_ptr->cr_fpscr_busy & cr_mask)) != 0) {
            model_new_cycle(model_ptr);                 /* don't count first dependency as a stall */
 
-           while (ppc_regs[ppc_RA].in_use) {
+           while (((model_ptr->fp_busy & fp_mask) | (model_ptr->cr_fpscr_busy & cr_mask)) != 0) {
+             if (WITH_TRACE && ppc_trace[trace_model])
+               model_trace_busy_p(model_ptr, 0, fp_mask, cr_mask, PPC_NO_SPR);
+
              model_ptr->nr_stalls_data++;
              model_new_cycle(model_ptr);
            }
          }
 
          busy_ptr = model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]);
-         ppc_regs[ppc_CRD].next = (model_reg *)0;
-         ppc_regs[ppc_CRD].in_use = 1;
-         busy_ptr->reg = &ppc_regs[ppc_CRD];
+         model_make_cr_reg_busy(model_ptr, busy_ptr, CRD);
        }
 
 # Schedule an MFSPR instruction that takes 1 special purpose register and produces an integer output register
@@ -543,20 +928,20 @@ void::model-function::ppc_insn_from_spr:itable_index index, cpu *processor, mode
 
        else {
          registers *cpu_regs = cpu_registers(processor);
-         const unsigned ppc_RD = (rD - &cpu_regs->gpr[0]) + PPC_INT_REG;
-         const unsigned ppc_SPR = nSPR + PPC_SPR_REG;
-         model_reg *ppc_regs = model_ptr->registers;
+         const unsigned ppc_RD = (rD - &cpu_regs->gpr[0]);
+         const unsigned32 int_mask = (1 << ppc_RD);
          model_busy *busy_ptr;
 
-         while (ppc_regs[ppc_SPR].in_use) {
+         while ((model_ptr->int_busy & int_mask) != 0 || model_ptr->spr_busy[nSPR] != 0) {
+           if (WITH_TRACE && ppc_trace[trace_model])
+             model_trace_busy_p(model_ptr, int_mask, 0, 0, nSPR);
+
            model_ptr->nr_stalls_data++;
            model_new_cycle(model_ptr);
          }
 
          busy_ptr = model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]);
-         ppc_regs[ppc_RD].next = (model_reg *)0;
-         ppc_regs[ppc_RD].in_use = 1;
-         busy_ptr->reg = &ppc_regs[ppc_RD];
+         model_make_int_reg_busy(model_ptr, busy_ptr, ppc_RD);
        }
 
 # Schedule an MTSPR instruction that takes 1 integer register and produces a special purpose output register
@@ -566,20 +951,20 @@ void::model-function::ppc_insn_to_spr:itable_index index, cpu *processor, model_
 
        else {
          registers *cpu_regs = cpu_registers(processor);
-         const unsigned ppc_RS = (rS - &cpu_regs->gpr[0]) + PPC_INT_REG;
-         const unsigned ppc_SPR = nSPR + PPC_SPR_REG;
-         model_reg *ppc_regs = model_ptr->registers;
+         const unsigned ppc_RS = (rS - &cpu_regs->gpr[0]);
+         const unsigned32 int_mask = (1 << ppc_RS);
          model_busy *busy_ptr;
 
-         while (ppc_regs[ppc_RS].in_use) {
+         while ((model_ptr->int_busy & int_mask) != 0 || model_ptr->spr_busy[nSPR] != 0) {
+           if (WITH_TRACE && ppc_trace[trace_model])
+             model_trace_busy_p(model_ptr, int_mask, 0, 0, nSPR);
+
            model_ptr->nr_stalls_data++;
            model_new_cycle(model_ptr);
          }
 
          busy_ptr = model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]);
-         ppc_regs[ppc_SPR].next = (model_reg *)0;
-         ppc_regs[ppc_SPR].in_use = 1;
-         busy_ptr->reg = &ppc_regs[ppc_SPR];
+         model_make_spr_reg_busy(model_ptr, busy_ptr, nSPR);
        }
 
 # Schedule a MFCR instruction that moves the CR into an integer regsiter
@@ -589,59 +974,55 @@ void::model-function::ppc_insn_mfcr:itable_index index, cpu *processor, model_da
 
        else {
          registers *cpu_regs = cpu_registers(processor);
-         const unsigned ppc_RD = (rD - &cpu_regs->gpr[0]) + PPC_INT_REG;
-         model_reg *ppc_regs = model_ptr->registers;
+         const unsigned ppc_RD = (rD - &cpu_regs->gpr[0]);
+         const unsigned32 int_mask = (1 << ppc_RD);
+         const unsigned32 cr_mask = 0xff;
          model_busy *busy_ptr;
 
-         while (ppc_regs[0 + PPC_CR_REG].in_use
-                | ppc_regs[1 + PPC_CR_REG].in_use
-                | ppc_regs[2 + PPC_CR_REG].in_use
-                | ppc_regs[3 + PPC_CR_REG].in_use
-                | ppc_regs[4 + PPC_CR_REG].in_use
-                | ppc_regs[5 + PPC_CR_REG].in_use
-                | ppc_regs[6 + PPC_CR_REG].in_use
-                | ppc_regs[7 + PPC_CR_REG].in_use) {
+         while (((model_ptr->int_busy & int_mask) | (model_ptr->cr_fpscr_busy & cr_mask)) != 0) {
+           if (WITH_TRACE && ppc_trace[trace_model])
+             model_trace_busy_p(model_ptr, int_mask, 0, cr_mask, PPC_NO_SPR);
 
            model_ptr->nr_stalls_data++;
            model_new_cycle(model_ptr);
          }
 
          busy_ptr = model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]);
-         ppc_regs[ppc_RD].next = (model_reg *)0;
-         ppc_regs[ppc_RD].in_use = 1;
-         busy_ptr->reg = &ppc_regs[ppc_RD];
+         model_make_int_reg_busy(model_ptr, busy_ptr, ppc_RD);
        }
 
 # Schedule a MTCR instruction that moves an integer register into the CR
-void::model-function::ppc_insn_mtcr:itable_index index, cpu *processor, model_data *model_ptr, signed_word *rT
+void::model-function::ppc_insn_mtcr:itable_index index, cpu *processor, model_data *model_ptr, signed_word *rT, unsigned FXM
        if (!WITH_MODEL_ISSUE)
          return;
 
        else {
          registers *cpu_regs = cpu_registers(processor);
-         const unsigned ppc_RT = (rT - &cpu_regs->gpr[0]) + PPC_INT_REG;
-         model_reg *ppc_regs = model_ptr->registers;
+         const unsigned ppc_RT = (rT - &cpu_regs->gpr[0]);
+         const unsigned32 int_mask = (1 << ppc_RT);
+         const unsigned32 cr_mask = 0xff;
+         const model_time *normal_time = &model_ptr->timing[index];
+         static const model_time ppc604_1bit_time = { PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1,  1,  0 };
          model_busy *busy_ptr;
-         model_reg *prev_reg;
          int i;
 
-         if (ppc_regs[ppc_RT].in_use) {
-           model_new_cycle(model_ptr);                 /* don't count first dependency as a stall */
+         while (((model_ptr->int_busy & int_mask) | (model_ptr->cr_fpscr_busy & cr_mask)) != 0) {
+           if (WITH_TRACE && ppc_trace[trace_model])
+             model_trace_busy_p(model_ptr, int_mask, 0, cr_mask, PPC_NO_SPR);
 
-           while (ppc_regs[ppc_RT].in_use) {
-             model_ptr->nr_stalls_data++;
-             model_new_cycle(model_ptr);
-           }
+           model_ptr->nr_stalls_data++;
+           model_new_cycle(model_ptr);
          }
 
-         busy_ptr = model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]);
-         prev_reg = (model_reg *)0;
+         /* If only one bit is being moved, use the SCIU, not the MCIU on the 604 */
+         if (CURRENT_MODEL == MODEL_ppc604 && (FXM & (FXM-1)) == 0) {
+           normal_time = &ppc604_1bit_time;
+         }
+
+         busy_ptr = model_wait_for_unit(index, model_ptr, normal_time);
          for (i = 0; i < 8; i++) {
-           ppc_regs[i + PPC_CR_REG].next = prev_reg;
-           ppc_regs[i + PPC_CR_REG].in_use = 1;
-           prev_reg = &ppc_regs[i + PPC_CR_REG];
+           model_make_cr_reg_busy(model_ptr, busy_ptr, i);
          }
-         busy_ptr->reg = prev_reg;
        }
 
 # Convert a BIT32(x) number back into the original number
@@ -661,21 +1042,21 @@ void::model-function::ppc_insn_cr2:itable_index index, cpu *processor, model_dat
          return;
 
        else {
-         const unsigned ppc_CRA = ppc_undo_bit32(crA_bit) + PPC_CR_REG;
-         const unsigned ppc_CRB = ppc_undo_bit32(crB_bit) + PPC_CR_REG;
-         const unsigned ppc_CRD = crD + PPC_CR_REG;
-         model_reg *ppc_regs = model_ptr->registers;
+         const unsigned ppc_CRA = ppc_undo_bit32(crA_bit);
+         const unsigned ppc_CRB = ppc_undo_bit32(crB_bit);
+         const unsigned32 cr_mask = (1 << ppc_CRA) | (1 << ppc_CRB) | (1 << crD);
          model_busy *busy_ptr;
 
-         while (ppc_regs[ppc_CRA].in_use | ppc_regs[ppc_CRB].in_use) {
+         while ((model_ptr->cr_fpscr_busy & cr_mask) != 0) {
+           if (WITH_TRACE && ppc_trace[trace_model])
+               model_trace_busy_p(model_ptr, 0, 0, cr_mask, PPC_NO_SPR);
+
            model_ptr->nr_stalls_data++;
            model_new_cycle(model_ptr);
          }
 
          busy_ptr = model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]);
-         ppc_regs[ppc_CRD].next = (model_reg *)0;
-         ppc_regs[ppc_CRD].in_use = 1;
-         busy_ptr->reg = &ppc_regs[ppc_CRD];
+         model_make_cr_reg_busy(model_ptr, busy_ptr, crD);
        }
 
 # Schedule an instruction that takes 1 CR input registers and produces an output CR register
@@ -684,20 +1065,19 @@ void::model-function::ppc_insn_cr1:itable_index index, cpu *processor, model_dat
          return;
 
        else {
-         const unsigned ppc_CRA = CRA + PPC_CR_REG;
-         const unsigned ppc_CRD = crD + PPC_CR_REG;
-         model_reg *ppc_regs = model_ptr->registers;
+         const unsigned32 cr_mask = (1 << CRA) | (1 << crD);
          model_busy *busy_ptr;
 
-         while (ppc_regs[ppc_CRA].in_use) {
+         while ((model_ptr->cr_fpscr_busy & cr_mask) != 0) {
+           if (WITH_TRACE && ppc_trace[trace_model])
+               model_trace_busy_p(model_ptr, 0, 0, cr_mask, PPC_NO_SPR);
+
            model_ptr->nr_stalls_data++;
            model_new_cycle(model_ptr);
          }
 
          busy_ptr = model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]);
-         ppc_regs[ppc_CRD].next = (model_reg *)0;
-         ppc_regs[ppc_CRD].in_use = 1;
-         busy_ptr->reg = &ppc_regs[ppc_CRD];
+         model_make_cr_reg_busy(model_ptr, busy_ptr, crD);
        }
 
 model_data *::model-function::model_create:cpu *processor
@@ -720,6 +1100,7 @@ model_print *::model-function::model_mon_info:model_data *model_ptr
        model_print *head;
        model_print *tail;
        ppc_function_unit i;
+       count_type nr_insns;
 
        head = tail = ZALLOC(model_print);
        tail->count = model_ptr->nr_cycles;
@@ -754,15 +1135,6 @@ model_print *::model-function::model_mon_info:model_data *model_ptr
          tail->suffix_singular = " waiting for serialization";
        }
 
-       if (model_ptr->nr_insns_not_handled) {
-         tail->next = ZALLOC(model_print);
-         tail = tail->next;
-         tail->count = model_ptr->nr_insns_not_handled;
-         tail->name = "instruction";
-         tail->suffix_plural = "s that were not accounted for in timing info";
-         tail->suffix_singular = " that was not accounted for in timing info";
-       }
-
        if (model_ptr->nr_branches) {
          tail->next = ZALLOC(model_print);
          tail = tail->next;
@@ -799,8 +1171,10 @@ model_print *::model-function::model_mon_info:model_data *model_ptr
          tail->suffix_singular = "";
        }
 
+       nr_insns = 0;
        for (i = PPC_UNIT_BAD; i < nr_ppc_function_units; i++) {
          if (model_ptr->nr_units[i]) {
+           nr_insns += model_ptr->nr_units[i];
            tail->next = ZALLOC(model_print);
            tail = tail->next;
            tail->count = model_ptr->nr_units[i];
@@ -810,6 +1184,13 @@ model_print *::model-function::model_mon_info:model_data *model_ptr
          }
        }
 
+       tail->next = ZALLOC(model_print);
+       tail = tail->next;
+       tail->count = nr_insns;
+       tail->name = "instruction";
+       tail->suffix_plural = "s that were accounted for in timing info";
+       tail->suffix_singular = " that was accounted for in timing info";
+
        tail->next = (model_print *)0;
        return head;
 
@@ -822,7 +1203,6 @@ void::model-function::model_mon_info_free:model_data *model_ptr, model_print *pt
 
 void::model-function::model_branches:model_data *model_ptr, int failed
        model_ptr->nr_units[PPC_UNIT_BPU]++;
-       model_ptr->insn_handled = 1;
        if (failed)
          model_ptr->nr_branches_fallthrough++;
        else
@@ -835,6 +1215,7 @@ void::model-function::model_branch_predict:model_data *model_ptr, int success
        else
          model_ptr->nr_branch_predict_falses++;
 
+\f
 # The following (illegal) instruction is `known' by gen and is
 # called when ever an illegal instruction is encountered
 ::internal::illegal
@@ -3060,7 +3441,6 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
        }
        ppc_insn_from_spr(my_index, processor, cpu_model(processor), rT, n);
 
-# FIXME: 604 uses SCIU{1,2} if only one bit is being set
 0.31,6.RS,11./,12.FXM,20./,21.144,31./:XFX::mtfcr:Move to Condition Register Fields
 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    2,  2,  0
 *603: PPC_UNIT_SRU,   PPC_UNIT_SRU,   1,  1,  0
@@ -3078,7 +3458,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
          }
          CR = (MASKED(*rS, 32, 63) & mask) | (CR & ~mask);
        }
-       ppc_insn_mtcr(my_index, processor, cpu_model(processor), rS);
+       ppc_insn_mtcr(my_index, processor, cpu_model(processor), rS, FXM);
 
 0.31,6.BF,9./,11./,16./,21.512,31./:X:::Move to Condition Register from XER
 
@@ -3105,6 +3485,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
        else         b = *rA;
        EA = b + EXTS(D);
        *frT = DOUBLE(MEM(unsigned, EA, 4));
+       ppc_insn_int1_fp1(my_index, processor, cpu_model(processor), frT, rA, 0/*RD_is_output*/, 0/*RA_is_update*/);
 
 0.31,6.FRT,11.RA,16.RB,21.535,31./:X:f::Load Floating-Point Single Indexed
 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    3,  3,  0
@@ -3117,6 +3498,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
        else         b = *rA;
        EA = b + *rB;
        *frT = DOUBLE(MEM(unsigned, EA, 4));
+       ppc_insn_int2_fp1(my_index, processor, cpu_model(processor), frT, rA, rB, 0/*RD_is_output*/, 0/*RA_is_update*/);
 
 0.49,6.FRT,11.RA,16.D:D:f::Load Floating-Point Single with Update
 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    3,  3,  0
@@ -3130,6 +3512,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
        EA = *rA + EXTS(D);
        *frT = DOUBLE(MEM(unsigned, EA, 4));
        *rA = EA;
+       ppc_insn_int1_fp1(my_index, processor, cpu_model(processor), frT, rA, 0/*RD_is_output*/, 1/*RA_is_update*/);
 
 0.31,6.FRT,11.RA,16.RB,21.576,31./:X:f::Load Floating-Point Single with Update Indexed
 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    3,  3,  0
@@ -3143,6 +3526,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
        EA = *rA + *rB;
        *frT = DOUBLE(MEM(unsigned, EA, 4));
        *rA = EA;
+       ppc_insn_int2_fp1(my_index, processor, cpu_model(processor), frT, rA, rB, 0/*RD_is_output*/, 1/*RA_is_update*/);
 
 0.50,6.FRT,11.RA,16.D:D:f::Load Floating-Point Double
 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    3,  3,  0
@@ -3155,6 +3539,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
        else         b = *rA;
        EA = b + EXTS(D);
        *frT = MEM(unsigned, EA, 8);
+       ppc_insn_int1_fp1(my_index, processor, cpu_model(processor), frT, rA, 0/*RD_is_output*/, 0/*RA_is_update*/);
 
 0.31,6.FRT,11.RA,16.RB,21.599,31./:X:f::Load Floating-Point Double Indexed
 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    3,  3,  0
@@ -3167,6 +3552,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
        else         b = *rA;
        EA = b + *rB;
        *frT = MEM(unsigned, EA, 8);
+       ppc_insn_int2_fp1(my_index, processor, cpu_model(processor), frT, rA, rB, 0/*RD_is_output*/, 0/*RA_is_update*/);
 
 0.51,6.FRT,11.RA,16.D:D:f::Load Floating-Point Double with Update
 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    3,  3,  0
@@ -3180,6 +3566,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
        EA = *rA + EXTS(D);
        *frT = MEM(unsigned, EA, 8);
        *rA = EA;
+       ppc_insn_int1_fp1(my_index, processor, cpu_model(processor), frT, rA, 0/*RD_is_output*/, 1/*RA_is_update*/);
 
 0.31,6.FRT,11.RA,16.RB,21.631,31./:X:f::Load Floating-Point Double with Update Indexed
 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    3,  3,  0
@@ -3193,6 +3580,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
        EA = *rA + *rB;
        *frT = MEM(unsigned, EA, 8);
        *rA = EA;
+       ppc_insn_int2_fp1(my_index, processor, cpu_model(processor), frT, rA, rB, 0/*RD_is_output*/, 1/*RA_is_update*/);
 
 
 #
@@ -3210,6 +3598,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
        else         b = *rA;
        EA = b + EXTS(D);
        STORE(EA, 4, SINGLE(*frS));
+       ppc_insn_int1_fp1(my_index, processor, cpu_model(processor), frS, rA, 1/*RD_is_output*/, 0/*RA_is_update*/);
 
 0.31,6.FRS,11.RA,16.RB,21.663,31./:X:f::Store Floating-Point Single Indexed
 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
@@ -3222,6 +3611,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
        else         b = *rA;
        EA = b + *rB;
        STORE(EA, 4, SINGLE(*frS));
+       ppc_insn_int2_fp1(my_index, processor, cpu_model(processor), frS, rA, rB, 1/*RD_is_output*/, 0/*RA_is_update*/);
 
 0.53,6.FRS,11.RA,16.D:D:f::Store Floating-Point Single with Update
 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
@@ -3235,6 +3625,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
        EA = *rA + EXTS(D);
        STORE(EA, 4, SINGLE(*frS));
        *rA = EA;
+       ppc_insn_int1_fp1(my_index, processor, cpu_model(processor), frS, rA, 1/*RD_is_output*/, 1/*RA_is_update*/);
 
 0.31,6.FRS,11.RA,16.RB,21.695,31./:X:f::Store Floating-Point Single with Update Indexed
 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
@@ -3248,6 +3639,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
        EA = *rA + *rB;
        STORE(EA, 4, SINGLE(*frS));
        *rA = EA;
+       ppc_insn_int2_fp1(my_index, processor, cpu_model(processor), frS, rA, rB, 1/*RD_is_output*/, 1/*RA_is_update*/);
 
 0.54,6.FRS,11.RA,16.D:D:f::Store Floating-Point Double
 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
@@ -3260,6 +3652,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
        else         b = *rA;
        EA = b + EXTS(D);
        STORE(EA, 8, *frS);
+       ppc_insn_int1_fp1(my_index, processor, cpu_model(processor), frS, rA, 1/*RD_is_output*/, 0/*RA_is_update*/);
 
 0.31,6.FRS,11.RA,16.RB,21.727,31./:X:f::Store Floating-Point Double Indexed
 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
@@ -3272,6 +3665,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
        else         b = *rA;
        EA = b + *rB;
        STORE(EA, 8, *frS);
+       ppc_insn_int2_fp1(my_index, processor, cpu_model(processor), frS, rA, rB, 1/*RD_is_output*/, 0/*RA_is_update*/);
 
 0.55,6.FRS,11.RA,16.D:D:f::Store Floating-Point Double with Update
 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
@@ -3285,6 +3679,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
        EA = *rA + EXTS(D);
        STORE(EA, 8, *frS);
        *rA = EA;
+       ppc_insn_int1_fp1(my_index, processor, cpu_model(processor), frS, rA, 1/*RD_is_output*/, 1/*RA_is_update*/);
 
 0.31,6.FRS,11.RA,16.RB,21.759,31./:X:f::Store Floating-Point Double with Update Indexed
 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
@@ -3298,6 +3693,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
        EA = *rA + *rB;
        STORE(EA, 8, *frS);
        *rA = EA;
+       ppc_insn_int2_fp1(my_index, processor, cpu_model(processor), frS, rA, rB, 1/*RD_is_output*/, 1/*RA_is_update*/);
 
 
 #
@@ -3311,6 +3707,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
 *604: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
        *frT = *frB;
        CR1_UPDATE(Rc);
+       ppc_insn_fp1(my_index, processor, cpu_model(processor), frT, frB, Rc);
 
 0.63,6.FRT,11./,16.FRB,21.40,31.Rc:X:f::Floating Negate
 *601: PPC_UNIT_FPU,   PPC_UNIT_FPU,   4,  4,  0
@@ -3319,6 +3716,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
 *604: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
        *frT = *frB ^ BIT64(0);
        CR1_UPDATE(Rc);
+       ppc_insn_fp1(my_index, processor, cpu_model(processor), frT, frB, Rc);
 
 0.63,6.FRT,11./,16.FRB,21.264,31.Rc:X:f::Floating Absolute Value
 *601: PPC_UNIT_FPU,   PPC_UNIT_FPU,   4,  4,  0
@@ -3327,6 +3725,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
 *604: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
        *frT = *frB & ~BIT64(0);
        CR1_UPDATE(Rc);
+       ppc_insn_fp1(my_index, processor, cpu_model(processor), frT, frB, Rc);
 
 0.63,6.FRT,11./,16.FRB,21.136,31.Rc:X:f::Floating Negative Absolute Value
 *601: PPC_UNIT_FPU,   PPC_UNIT_FPU,   4,  4,  0
@@ -3335,6 +3734,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
 *604: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
        *frT = *frB | BIT64(0);
        CR1_UPDATE(Rc);
+       ppc_insn_fp1(my_index, processor, cpu_model(processor), frT, frB, Rc);
 
 
 
@@ -3366,6 +3766,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
          *(double*)frT = s;
        }
        FPSCR_END(Rc);
+       ppc_insn_fp2(my_index, processor, cpu_model(processor), frT, frA, frB, Rc);
 
 0.59,6.FRT,11.FRA,16.FRB,21./,26.21,31.Rc:A:f:fadds:Floating Add Single
 *601: PPC_UNIT_FPU,   PPC_UNIT_FPU,   4,  4,  0
@@ -3391,6 +3792,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
          *(double*)frT = s;
        }
        FPSCR_END(Rc);
+       ppc_insn_fp2(my_index, processor, cpu_model(processor), frT, frA, frB, Rc);
 
 0.63,6.FRT,11.FRA,16.FRB,21./,26.20,31.Rc:A:f:fsub:Floating Subtract
 *601: PPC_UNIT_FPU,   PPC_UNIT_FPU,   4,  4,  0
@@ -3416,6 +3818,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
          *(double*)frT = s;
        }
        FPSCR_END(Rc);
+       ppc_insn_fp2(my_index, processor, cpu_model(processor), frT, frA, frB, Rc);
 
 0.59,6.FRT,11.FRA,16.FRB,21./,26.20,31.Rc:A:f:fsubs:Floating Subtract Single
 *601: PPC_UNIT_FPU,   PPC_UNIT_FPU,   4,  4,  0
@@ -3440,6 +3843,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
          float s = *(double*)frA - *(double*)frB;
          *(double*)frT = s;
        }
+       ppc_insn_fp2(my_index, processor, cpu_model(processor), frT, frA, frB, Rc);
        FPSCR_END(Rc);
 
 0.63,6.FRT,11.FRA,16./,21.FRC,26.25,31.Rc:A:f:fmul:Floating Multiply
@@ -3466,6 +3870,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
          *(double*)frT = s;
        }
        FPSCR_END(Rc);
+       ppc_insn_fp2(my_index, processor, cpu_model(processor), frT, frA, frC, Rc);
 
 0.59,6.FRT,11.FRA,16./,21.FRC,26.25,31.Rc:A:f:fmuls:Floating Multiply Single
 *601: PPC_UNIT_FPU,   PPC_UNIT_FPU,   4,  4,  0
@@ -3491,6 +3896,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
          *(double*)frT = s;
        }
        FPSCR_END(Rc);
+       ppc_insn_fp2(my_index, processor, cpu_model(processor), frT, frA, frC, Rc);
 
 0.63,6.FRT,11.FRA,16.FRB,21./,26.18,31.Rc:A:f:fdiv:Floating Divide
 *601: PPC_UNIT_FPU,   PPC_UNIT_FPU,   31, 31, 0
@@ -3516,6 +3922,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
          *(double*)frT = s;
        }
        FPSCR_END(Rc);
+       ppc_insn_fp2(my_index, processor, cpu_model(processor), frT, frA, frB, Rc);
 
 0.59,6.FRT,11.FRA,16.FRB,21./,26.18,31.Rc:A:f:fdivs:Floating Divide Single
 *601: PPC_UNIT_FPU,   PPC_UNIT_FPU,   17, 17, 0
@@ -3541,6 +3948,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
          *(double*)frT = s;
        }
        FPSCR_END(Rc);
+       ppc_insn_fp2(my_index, processor, cpu_model(processor), frT, frA, frB, Rc);
 
 0.63,6.FRT,11.FRA,16.FRB,21.FRC,26.29,31.Rc:A:f:fmadd:Floating Multiply-Add
 *601: PPC_UNIT_FPU,   PPC_UNIT_FPU,   5,  5,  0
@@ -3585,48 +3993,322 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
          *(double*)frT = s;
        }
        FPSCR_END(Rc);
+       ppc_insn_fp3(my_index, processor, cpu_model(processor), frT, frA, frB, frC, Rc);
 
 0.59,6.FRT,11.FRA,16.FRB,21.FRC,26.29,31.Rc:A:f::Floating Multiply-Add Single
 *601: PPC_UNIT_FPU,   PPC_UNIT_FPU,   4,  4,  0
 *603: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
 *603e:PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
 *604: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
-
-0.63,6.FRT,11.FRA,16.FRB,21.FRC,26.28,31.Rc:A:f::Floating Multiply-Subtract
-*601: PPC_UNIT_FPU,   PPC_UNIT_FPU,   5,  5,  0
-*603: PPC_UNIT_FPU,   PPC_UNIT_FPU,   2,  4,  0
-*603e:PPC_UNIT_FPU,   PPC_UNIT_FPU,   2,  4,  0
+       FPSCR_BEGIN;
+       float product; /*HACK! - incorrectly loosing precision ... */
+       /* compute the multiply */
+       if (is_invalid_operation(processor, cia,
+                                *frA, *frC,
+                                fpscr_vxsnan | fpscr_vximz,
+                                1, /*single?*/
+                                0) /*negate?*/) {
+         invalid_arithemetic_operation(processor, cia,
+                                       (unsigned64*)&product, *frA, 0, *frC,
+                                       0, /*instruction_is_frsp*/
+                                       0, /*instruction_is_convert_to_64bit*/
+                                       0, /*instruction_is_convert_to_32bit*/
+                                       0); /*single-precision*/
+       }
+       else {
+         /*HACK!*/
+         product = *(double*)frA * *(double*)frC;
+       }
+       /* compute the add */
+       if (is_invalid_operation(processor, cia,
+                                product, *frB,
+                                fpscr_vxsnan | fpscr_vxisi,
+                                1, /*single?*/
+                                0) /*negate?*/) {
+         invalid_arithemetic_operation(processor, cia,
+                                       frT, product, *frB, 0,
+                                       0, /*instruction_is_frsp*/
+                                       0, /*instruction_is_convert_to_64bit*/
+                                       0, /*instruction_is_convert_to_32bit*/
+                                       0); /*single-precision*/
+       }
+       else {
+         /*HACK!*/
+         float s = product + *(double*)frB;
+         *(double*)frT = (double)s;
+       }
+       FPSCR_END(Rc);
+       ppc_insn_fp3(my_index, processor, cpu_model(processor), frT, frA, frB, frC, Rc);
+
+0.63,6.FRT,11.FRA,16.FRB,21.FRC,26.28,31.Rc:A:f::Floating Multiply-Subtract
+*601: PPC_UNIT_FPU,   PPC_UNIT_FPU,   5,  5,  0
+*603: PPC_UNIT_FPU,   PPC_UNIT_FPU,   2,  4,  0
+*603e:PPC_UNIT_FPU,   PPC_UNIT_FPU,   2,  4,  0
 *604: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
+       FPSCR_BEGIN;
+       double product; /*HACK! - incorrectly loosing precision ... */
+       /* compute the multiply */
+       if (is_invalid_operation(processor, cia,
+                                *frA, *frC,
+                                fpscr_vxsnan | fpscr_vximz,
+                                0, /*single?*/
+                                0) /*negate?*/) {
+         invalid_arithemetic_operation(processor, cia,
+                                       (unsigned64*)&product, *frA, 0, *frC,
+                                       0, /*instruction_is_frsp*/
+                                       0, /*instruction_is_convert_to_64bit*/
+                                       0, /*instruction_is_convert_to_32bit*/
+                                       0); /*single-precision*/
+       }
+       else {
+         /*HACK!*/
+         product = *(double*)frA * *(double*)frC;
+       }
+       /* compute the subtract */
+       if (is_invalid_operation(processor, cia,
+                                product, *frB,
+                                fpscr_vxsnan | fpscr_vxisi,
+                                0, /*single?*/
+                                0) /*negate?*/) {
+         invalid_arithemetic_operation(processor, cia,
+                                       frT, product, *frB, 0,
+                                       0, /*instruction_is_frsp*/
+                                       0, /*instruction_is_convert_to_64bit*/
+                                       0, /*instruction_is_convert_to_32bit*/
+                                       0); /*single-precision*/
+       }
+       else {
+         /*HACK!*/
+         double s = product - *(double*)frB;
+         *(double*)frT = s;
+       }
+       FPSCR_END(Rc);
+       ppc_insn_fp3(my_index, processor, cpu_model(processor), frT, frA, frB, frC, Rc);
 
 0.59,6.FRT,11.FRA,16.FRB,21.FRC,26.28,31.Rc:A:f::Floating Multiply-Subtract Single
 *601: PPC_UNIT_FPU,   PPC_UNIT_FPU,   4,  4,  0
 *603: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
 *603e:PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
 *604: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
+       FPSCR_BEGIN;
+       float product; /*HACK! - incorrectly loosing precision ... */
+       /* compute the multiply */
+       if (is_invalid_operation(processor, cia,
+                                *frA, *frC,
+                                fpscr_vxsnan | fpscr_vximz,
+                                1, /*single?*/
+                                0) /*negate?*/) {
+         invalid_arithemetic_operation(processor, cia,
+                                       (unsigned64*)&product, *frA, 0, *frC,
+                                       0, /*instruction_is_frsp*/
+                                       0, /*instruction_is_convert_to_64bit*/
+                                       0, /*instruction_is_convert_to_32bit*/
+                                       0); /*single-precision*/
+       }
+       else {
+         /*HACK!*/
+         product = *(double*)frA * *(double*)frC;
+       }
+       /* compute the subtract */
+       if (is_invalid_operation(processor, cia,
+                                product, *frB,
+                                fpscr_vxsnan | fpscr_vxisi,
+                                1, /*single?*/
+                                0) /*negate?*/) {
+         invalid_arithemetic_operation(processor, cia,
+                                       frT, product, *frB, 0,
+                                       0, /*instruction_is_frsp*/
+                                       0, /*instruction_is_convert_to_64bit*/
+                                       0, /*instruction_is_convert_to_32bit*/
+                                       0); /*single-precision*/
+       }
+       else {
+         /*HACK!*/
+         float s = product - *(double*)frB;
+         *(double*)frT = (double)s;
+       }
+       FPSCR_END(Rc);
+       ppc_insn_fp3(my_index, processor, cpu_model(processor), frT, frA, frB, frC, Rc);
 
 0.63,6.FRT,11.FRA,16.FRB,21.FRC,26.31,31.Rc:A:f::Floating Negative Multiply-Add
 *601: PPC_UNIT_FPU,   PPC_UNIT_FPU,   5,  5,  0
 *603: PPC_UNIT_FPU,   PPC_UNIT_FPU,   2,  4,  0
 *603e:PPC_UNIT_FPU,   PPC_UNIT_FPU,   2,  4,  0
 *604: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
+       FPSCR_BEGIN;
+       double product; /*HACK! - incorrectly loosing precision ... */
+       /* compute the multiply */
+       if (is_invalid_operation(processor, cia,
+                                *frA, *frC,
+                                fpscr_vxsnan | fpscr_vximz,
+                                0, /*single?*/
+                                0) /*negate?*/) {
+         invalid_arithemetic_operation(processor, cia,
+                                       (unsigned64*)&product, *frA, 0, *frC,
+                                       0, /*instruction_is_frsp*/
+                                       0, /*instruction_is_convert_to_64bit*/
+                                       0, /*instruction_is_convert_to_32bit*/
+                                       0); /*single-precision*/
+       }
+       else {
+         /*HACK!*/
+         product = *(double*)frA * *(double*)frC;
+       }
+       /* compute the add */
+       if (is_invalid_operation(processor, cia,
+                                product, *frB,
+                                fpscr_vxsnan | fpscr_vxisi,
+                                0, /*single?*/
+                                0) /*negate?*/) {
+         invalid_arithemetic_operation(processor, cia,
+                                       frT, product, *frB, 0,
+                                       0, /*instruction_is_frsp*/
+                                       0, /*instruction_is_convert_to_64bit*/
+                                       0, /*instruction_is_convert_to_32bit*/
+                                       0); /*single-precision*/
+       }
+       else {
+         /*HACK!*/
+         double s = -(product + *(double*)frB);
+         *(double*)frT = s;
+       }
+       FPSCR_END(Rc);
+       ppc_insn_fp3(my_index, processor, cpu_model(processor), frT, frA, frB, frC, Rc);
 
 0.59,6.FRT,11.FRA,16.FRB,21.FRC,26.31,31.Rc:A:f::Floating Negative Multiply-Add Single
 *601: PPC_UNIT_FPU,   PPC_UNIT_FPU,   4,  4,  0
 *603: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
 *603e:PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
 *604: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
+       FPSCR_BEGIN;
+       float product; /*HACK! - incorrectly loosing precision ... */
+       /* compute the multiply */
+       if (is_invalid_operation(processor, cia,
+                                *frA, *frC,
+                                fpscr_vxsnan | fpscr_vximz,
+                                1, /*single?*/
+                                0) /*negate?*/) {
+         invalid_arithemetic_operation(processor, cia,
+                                       (unsigned64*)&product, *frA, 0, *frC,
+                                       0, /*instruction_is_frsp*/
+                                       0, /*instruction_is_convert_to_64bit*/
+                                       0, /*instruction_is_convert_to_32bit*/
+                                       0); /*single-precision*/
+       }
+       else {
+         /*HACK!*/
+         product = *(double*)frA * *(double*)frC;
+       }
+       /* compute the add */
+       if (is_invalid_operation(processor, cia,
+                                product, *frB,
+                                fpscr_vxsnan | fpscr_vxisi,
+                                1, /*single?*/
+                                0) /*negate?*/) {
+         invalid_arithemetic_operation(processor, cia,
+                                       frT, product, *frB, 0,
+                                       0, /*instruction_is_frsp*/
+                                       0, /*instruction_is_convert_to_64bit*/
+                                       0, /*instruction_is_convert_to_32bit*/
+                                       0); /*single-precision*/
+       }
+       else {
+         /*HACK!*/
+         float s = -(product + *(double*)frB);
+         *(double*)frT = (double)s;
+       }
+       FPSCR_END(Rc);
+       ppc_insn_fp3(my_index, processor, cpu_model(processor), frT, frA, frB, frC, Rc);
 
 0.63,6.FRT,11.FRA,16.FRB,21.FRC,26.30,31.Rc:A:f::Floating Negative Multiply-Subtract
 *601: PPC_UNIT_FPU,   PPC_UNIT_FPU,   5,  5,  0
 *603: PPC_UNIT_FPU,   PPC_UNIT_FPU,   2,  4,  0
 *603e:PPC_UNIT_FPU,   PPC_UNIT_FPU,   2,  4,  0
 *604: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
+       FPSCR_BEGIN;
+       double product; /*HACK! - incorrectly loosing precision ... */
+       /* compute the multiply */
+       if (is_invalid_operation(processor, cia,
+                                *frA, *frC,
+                                fpscr_vxsnan | fpscr_vximz,
+                                0, /*single?*/
+                                0) /*negate?*/) {
+         invalid_arithemetic_operation(processor, cia,
+                                       (unsigned64*)&product, *frA, 0, *frC,
+                                       0, /*instruction_is_frsp*/
+                                       0, /*instruction_is_convert_to_64bit*/
+                                       0, /*instruction_is_convert_to_32bit*/
+                                       0); /*single-precision*/
+       }
+       else {
+         /*HACK!*/
+         product = *(double*)frA * *(double*)frC;
+       }
+       /* compute the subtract */
+       if (is_invalid_operation(processor, cia,
+                                product, *frB,
+                                fpscr_vxsnan | fpscr_vxisi,
+                                0, /*single?*/
+                                0) /*negate?*/) {
+         invalid_arithemetic_operation(processor, cia,
+                                       frT, product, *frB, 0,
+                                       0, /*instruction_is_frsp*/
+                                       0, /*instruction_is_convert_to_64bit*/
+                                       0, /*instruction_is_convert_to_32bit*/
+                                       0); /*single-precision*/
+       }
+       else {
+         /*HACK!*/
+         double s = -(product - *(double*)frB);
+         *(double*)frT = s;
+       }
+       FPSCR_END(Rc);
+       ppc_insn_fp3(my_index, processor, cpu_model(processor), frT, frA, frB, frC, Rc);
 
 0.59,6.FRT,11.FRA,16.FRB,21.FRC,26.30,31.Rc:A:f::Floating Negative Multiply-Subtract Single
 *601: PPC_UNIT_FPU,   PPC_UNIT_FPU,   4,  4,  0
 *603: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
 *603e:PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
 *604: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
+       FPSCR_BEGIN;
+       float product; /*HACK! - incorrectly loosing precision ... */
+       /* compute the multiply */
+       if (is_invalid_operation(processor, cia,
+                                *frA, *frC,
+                                fpscr_vxsnan | fpscr_vximz,
+                                1, /*single?*/
+                                0) /*negate?*/) {
+         invalid_arithemetic_operation(processor, cia,
+                                       (unsigned64*)&product, *frA, 0, *frC,
+                                       0, /*instruction_is_frsp*/
+                                       0, /*instruction_is_convert_to_64bit*/
+                                       0, /*instruction_is_convert_to_32bit*/
+                                       0); /*single-precision*/
+       }
+       else {
+         /*HACK!*/
+         product = *(double*)frA * *(double*)frC;
+       }
+       /* compute the subtract */
+       if (is_invalid_operation(processor, cia,
+                                product, *frB,
+                                fpscr_vxsnan | fpscr_vxisi,
+                                1, /*single?*/
+                                0) /*negate?*/) {
+         invalid_arithemetic_operation(processor, cia,
+                                       frT, product, *frB, 0,
+                                       0, /*instruction_is_frsp*/
+                                       0, /*instruction_is_convert_to_64bit*/
+                                       0, /*instruction_is_convert_to_32bit*/
+                                       0); /*single-precision*/
+       }
+       else {
+         /*HACK!*/
+         float s = -(product - *(double*)frB);
+         *(double*)frT = (double)s;
+       }
+       FPSCR_END(Rc);
+       ppc_insn_fp3(my_index, processor, cpu_model(processor), frT, frA, frB, frC, Rc);
 
 
 #
@@ -3839,6 +4521,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
          if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_neg_normal_number);
          goto Done;
        Done:
+       ppc_insn_fp1(my_index, processor, cpu_model(processor), frT, frB, Rc);
 
 0.63,6.FRT,11./,16.FRB,21.814,31.Rc:X:64,f::Floating Convert To Integer Doubleword
 
@@ -3856,6 +4539,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
                           frT, *frB,
                           fpscr_rn_round_towards_zero, 32);
        FPSCR_END(Rc);
+       ppc_insn_fp1(my_index, processor, cpu_model(processor), frT, frB, Rc);
 
 0.63,6.FRT,11./,16.FRB,21.846,31.Rc:X:64,f::Floating Convert from Integer Doubleword
        int sign = EXTRACTED64(*frB, 0, 0);
@@ -3884,6 +4568,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
          goto Done;
        /**/
        Done:
+       ppc_insn_fp1(my_index, processor, cpu_model(processor), frT, frB, Rc);
 
 #
 # I.4.6.7 Floating-Point Compare Instructions
@@ -3909,6 +4594,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
        if (is_SNaN(*frA, 0) || is_SNaN(*frB, 0))
          FPSCR_OR_VX(fpscr_vxsnan);
        FPSCR_END(0);
+       ppc_insn_fp2_cr(my_index, processor, cpu_model(processor), BF, frA, frB);
 
 0.63,6.BF,9./,11.FRA,16.FRB,21.32,31./:X:f:fcmpo:Floating Compare Ordered
 *601: PPC_UNIT_FPU,   PPC_UNIT_FPU,   4,  4,  0
@@ -3936,6 +4622,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
          FPSCR_OR_VX(fpscr_vxvc);
        }
        FPSCR_END(0);
+       ppc_insn_fp2_cr(my_index, processor, cpu_model(processor), BF, frA, frB);
 
 
 #
@@ -3992,6 +4679,10 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
        #if WITH_IDECODE_CACHE_SIZE
        cpu_flush_icache(processor);
        #endif
+       if (RA == 0)
+         ppc_insn_int1_noout(my_index, processor, cpu_model(processor), rB);
+       else
+         ppc_insn_int2_noout(my_index, processor, cpu_model(processor), rA, rB);
 
 0.19,6./,11./,16./,21.150,31./:XL::isync:Instruction Synchronize
 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
@@ -3999,6 +4690,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
 *603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  3,  0
 *604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  1,  0
        cpu_synchronize_context(processor);
+       ppc_insn_int0_noout(my_index, processor, cpu_model(processor));
 
 
 #
@@ -4011,6 +4703,10 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
 *603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   2,  2,  0
 *604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  1,  0
        TRACE(trace_tbd,("Data Cache Block Touch\n"));
+       if (RA == 0)
+         ppc_insn_int1_noout(my_index, processor, cpu_model(processor), rB);
+       else
+         ppc_insn_int2_noout(my_index, processor, cpu_model(processor), rA, rB);
 
 0.31,6./,11.RA,16.RB,21.246,31./:X:::Data Cache Block Touch for Store
 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
@@ -4018,6 +4714,10 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
 *603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   2,  2,  0
 *604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  3,  0
        TRACE(trace_tbd,("Data Cache Block Touch for Store\n"));
+       if (RA == 0)
+         ppc_insn_int1_noout(my_index, processor, cpu_model(processor), rB);
+       else
+         ppc_insn_int2_noout(my_index, processor, cpu_model(processor), rA, rB);
 
 0.31,6./,11.RA,16.RB,21.1014,31./:X:::Data Cache Block set to Zero
 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
@@ -4025,6 +4725,10 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
 *603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   10, 10, 0
 *604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  3,  0
        TRACE(trace_tbd,("Data Cache Block set to Zero\n"));
+       if (RA == 0)
+         ppc_insn_int1_noout(my_index, processor, cpu_model(processor), rB);
+       else
+         ppc_insn_int2_noout(my_index, processor, cpu_model(processor), rA, rB);
 
 0.31,6./,11.RA,16.RB,21.54,31./:X:::Data Cache Block Store
 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
@@ -4032,6 +4736,10 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
 *603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   5,  5,  0
 *604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  1,  0
        TRACE(trace_tbd,("Data Cache Block Store\n"));
+       if (RA == 0)
+         ppc_insn_int1_noout(my_index, processor, cpu_model(processor), rB);
+       else
+         ppc_insn_int2_noout(my_index, processor, cpu_model(processor), rA, rB);
 
 0.31,6./,11.RA,16.RB,21.86,31./:X:::Data Cache Block Flush
 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
@@ -4039,6 +4747,10 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
 *603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   5,  5,  0
 *604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  1,  0
        TRACE(trace_tbd,("Data Cache Block Flush\n"));
+       if (RA == 0)
+         ppc_insn_int1_noout(my_index, processor, cpu_model(processor), rB);
+       else
+         ppc_insn_int2_noout(my_index, processor, cpu_model(processor), rA, rB);
 
 #
 # II.3.3 Enforce In-order Execution of I/O Instruction