OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [tags/] [or1ksim/] [or1ksim-0.5.0rc1/] [cpu/] [or32/] [dyn-rec.c] - Diff between revs 19 and 347

Go to most recent revision | Only display areas with differences | Details | Blame | View Log

Rev 19 Rev 347
/* dyn-rec.c -- Dynamic recompiler implementation for or32
/* dyn-rec.c -- Dynamic recompiler implementation for or32
   Copyright (C) 2005 György `nog' Jeney, nog@sdf.lonestar.org
   Copyright (C) 2005 György `nog' Jeney, nog@sdf.lonestar.org
 
 
This file is part of OpenRISC 1000 Architectural Simulator.
This file is part of OpenRISC 1000 Architectural Simulator.
 
 
This program is free software; you can redistribute it and/or modify
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
(at your option) any later version.
 
 
This program is distributed in the hope that it will be useful,
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.
GNU General Public License for more details.
 
 
You should have received a copy of the GNU General Public License
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
 
 
#include <stdio.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdlib.h>
#include <string.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/mman.h>
#include <signal.h>
#include <signal.h>
#include <errno.h>
#include <errno.h>
#include <execinfo.h>
#include <execinfo.h>
 
 
#include "config.h"
#include "config.h"
 
 
#ifdef HAVE_INTTYPES_H
#ifdef HAVE_INTTYPES_H
#include <inttypes.h>
#include <inttypes.h>
#endif
#endif
 
 
#include "port.h"
#include "port.h"
#include "arch.h"
#include "arch.h"
#include "immu.h"
#include "immu.h"
#include "abstract.h"
#include "abstract.h"
#include "opcode/or32.h"
#include "opcode/or32.h"
#include "spr-defs.h"
#include "spr-defs.h"
#include "execute.h"
#include "execute.h"
#include "except.h"
#include "except.h"
#include "spr-defs.h"
#include "spr-defs.h"
#include "sim-config.h"
#include "sim-config.h"
#include "sched.h"
#include "sched.h"
#include "i386-regs.h"
#include "i386-regs.h"
#include "def-op-t.h"
#include "def-op-t.h"
#include "dyn-rec.h"
#include "dyn-rec.h"
#include "gen-ops.h"
#include "gen-ops.h"
#include "op-support.h"
#include "op-support.h"
#include "toplevel-support.h"
#include "toplevel-support.h"
 
 
 
 
/* NOTE: All openrisc (or) addresses in this file are *PHYSICAL* addresses */
/* NOTE: All openrisc (or) addresses in this file are *PHYSICAL* addresses */
 
 
/* FIXME: Optimise sorted list adding */
/* FIXME: Optimise sorted list adding */
 
 
typedef void (*generic_gen_op)(struct op_queue *opq, int end);
typedef void (*generic_gen_op)(struct op_queue *opq, int end);
typedef void (*imm_gen_op)(struct op_queue *opq, int end, uorreg_t imm);
typedef void (*imm_gen_op)(struct op_queue *opq, int end, uorreg_t imm);
 
 
void gen_l_invalid(struct op_queue *opq, int param_t[3], int delay_slot);
void gen_l_invalid(struct op_queue *opq, int param_t[3], int delay_slot);
 
 
/* ttg->temporary to gpr */
/* ttg->temporary to gpr */
DEF_GPR_OP(generic_gen_op, gen_op_move_gpr_t, gen_op_ttg_gpr);
DEF_GPR_OP(generic_gen_op, gen_op_move_gpr_t, gen_op_ttg_gpr);
/* gtt->gpr to temporary */
/* gtt->gpr to temporary */
DEF_GPR_OP(generic_gen_op, gen_op_move_t_gpr, gen_op_gtt_gpr);
DEF_GPR_OP(generic_gen_op, gen_op_move_t_gpr, gen_op_gtt_gpr);
 
 
DEF_1T_OP(imm_gen_op, calc_insn_ea_table, gen_op_calc_insn_ea);
DEF_1T_OP(imm_gen_op, calc_insn_ea_table, gen_op_calc_insn_ea);
 
 
/* Linker stubs.  This will allow the linker to link in op.o.  The relocations
/* Linker stubs.  This will allow the linker to link in op.o.  The relocations
 * that the linker does for these will be irrelevent anyway, since we patch the
 * that the linker does for these will be irrelevent anyway, since we patch the
 * relocations during recompilation. */
 * relocations during recompilation. */
uorreg_t __op_param1;
uorreg_t __op_param1;
uorreg_t __op_param2;
uorreg_t __op_param2;
uorreg_t __op_param3;
uorreg_t __op_param3;
 
 
/* The number of bytes that a dynamicly recompiled page should be enlarged by */
/* The number of bytes that a dynamicly recompiled page should be enlarged by */
#define RECED_PAGE_ENLARGE_BY 51200
#define RECED_PAGE_ENLARGE_BY 51200
 
 
/* The number of entries that the micro operations array in op_queue should be
/* The number of entries that the micro operations array in op_queue should be
 * enlarged by */
 * enlarged by */
#define OPS_ENLARGE_BY 5
#define OPS_ENLARGE_BY 5
 
 
#define T_NONE (-1)
#define T_NONE (-1)
 
 
/* Temporary is used as a source operand */
/* Temporary is used as a source operand */
#define TFLAG_SRC 1
#define TFLAG_SRC 1
/* Temporary is used as a destination operand */
/* Temporary is used as a destination operand */
#define TFLAG_DST 2
#define TFLAG_DST 2
/* Temporary has been saved to permanent storage */
/* Temporary has been saved to permanent storage */
#define TFLAG_SAVED 4
#define TFLAG_SAVED 4
/* Temporary contains the value of the register before the instruction execution
/* Temporary contains the value of the register before the instruction execution
 * occurs (either by an explicit reg->t move or implicitly being left over from
 * occurs (either by an explicit reg->t move or implicitly being left over from
 * a previous instruction) */
 * a previous instruction) */
#define TFLAG_SOURCED 8
#define TFLAG_SOURCED 8
 
 
/* FIXME: Put this into some header */
/* FIXME: Put this into some header */
extern int do_stats;
extern int do_stats;
 
 
static int sigsegv_state = 0;
static int sigsegv_state = 0;
static void *sigsegv_addr = NULL;
static void *sigsegv_addr = NULL;
 
 
void dyn_ret_stack_prot(void);
void dyn_ret_stack_prot(void);
 
 
void dyn_sigsegv_debug(int u, siginfo_t *siginf, void *dat)
void dyn_sigsegv_debug(int u, siginfo_t *siginf, void *dat)
{
{
  struct dyn_page *dp;
  struct dyn_page *dp;
  FILE *f;
  FILE *f;
  char filen[18]; /* 18 == strlen("or_page.%08x") + 1 */
  char filen[18]; /* 18 == strlen("or_page.%08x") + 1 */
  int i;
  int i;
  struct sigcontext *sigc = dat;
  struct sigcontext *sigc = dat;
 
 
  if(!sigsegv_state) {
  if(!sigsegv_state) {
    sigsegv_addr = siginf->si_addr;
    sigsegv_addr = siginf->si_addr;
  } else {
  } else {
    fprintf(stderr, "Nested SIGSEGV occured, dumping next chuck of info\n");
    fprintf(stderr, "Nested SIGSEGV occured, dumping next chuck of info\n");
    sigsegv_state++;
    sigsegv_state++;
  }
  }
 
 
  /* First dump all the data that does not need dereferenceing to get */
  /* First dump all the data that does not need dereferenceing to get */
  switch(sigsegv_state) {
  switch(sigsegv_state) {
  case 0:
  case 0:
    fflush(stderr);
    fflush(stderr);
    fprintf(stderr, "Segmentation fault on acces to %p at 0x%08lx, (or address: 0x%"PRIxADDR")\n\n",
    fprintf(stderr, "Segmentation fault on acces to %p at 0x%08lx, (or address: 0x%"PRIxADDR")\n\n",
            sigsegv_addr, sigc->eip, cpu_state.pc);
            sigsegv_addr, sigc->eip, cpu_state.pc);
    sigsegv_state++;
    sigsegv_state++;
  case 1:
  case 1:
    /* Run through the recompiled pages, dumping them to disk as we go */
    /* Run through the recompiled pages, dumping them to disk as we go */
    for(i = 0; i < (2 << (32 - immu_state->pagesize_log2)); i++) {
    for(i = 0; i < (2 << (32 - immu_state->pagesize_log2)); i++) {
      dp = cpu_state.dyn_pages[i];
      dp = cpu_state.dyn_pages[i];
      if(!dp)
      if(!dp)
        continue;
        continue;
      fprintf(stderr, "Dumping%s page 0x%"PRIxADDR" recompiled to %p (len: %u) to disk\n",
      fprintf(stderr, "Dumping%s page 0x%"PRIxADDR" recompiled to %p (len: %u) to disk\n",
             dp->dirty ? " dirty" : "", dp->or_page, dp->host_page,
             dp->dirty ? " dirty" : "", dp->or_page, dp->host_page,
             dp->host_len);
             dp->host_len);
      fflush(stdout);
      fflush(stdout);
 
 
      sprintf(filen, "or_page.%"PRIxADDR, dp->or_page);
      sprintf(filen, "or_page.%"PRIxADDR, dp->or_page);
      if(!(f = fopen(filen, "w"))) {
      if(!(f = fopen(filen, "w"))) {
        fprintf(stderr, "Unable to open %s to dump the recompiled page to: %s\n",
        fprintf(stderr, "Unable to open %s to dump the recompiled page to: %s\n",
                filen, strerror(errno));
                filen, strerror(errno));
        continue;
        continue;
      }
      }
      if(fwrite(dp->host_page, dp->host_len, 1, f) < 1)
      if(fwrite(dp->host_page, dp->host_len, 1, f) < 1)
        fprintf(stderr, "Unable to write recompiled data to file: %s\n",
        fprintf(stderr, "Unable to write recompiled data to file: %s\n",
                strerror(errno));
                strerror(errno));
 
 
      fclose(f);
      fclose(f);
    }
    }
    sigsegv_state++;
    sigsegv_state++;
  case 2:
  case 2:
    sim_done();
    sim_done();
  }
  }
}
}
 
 
struct dyn_page *new_dp(oraddr_t page)
struct dyn_page *new_dp(oraddr_t page)
{
{
  struct dyn_page *dp = malloc(sizeof(struct dyn_page));
  struct dyn_page *dp = malloc(sizeof(struct dyn_page));
  dp->or_page = IADDR_PAGE(page);
  dp->or_page = IADDR_PAGE(page);
 
 
  dp->locs = malloc(sizeof(void *) * (immu_state->pagesize / 4));
  dp->locs = malloc(sizeof(void *) * (immu_state->pagesize / 4));
 
 
  dp->host_len = 0;
  dp->host_len = 0;
  dp->host_page = NULL;
  dp->host_page = NULL;
  dp->dirty = 1;
  dp->dirty = 1;
 
 
  if(do_stats) {
  if(do_stats) {
    dp->insns = malloc(immu_state->pagesize);
    dp->insns = malloc(immu_state->pagesize);
    dp->insn_indexs = malloc(sizeof(unsigned int) * (immu_state->pagesize / 4));
    dp->insn_indexs = malloc(sizeof(unsigned int) * (immu_state->pagesize / 4));
  }
  }
 
 
  cpu_state.dyn_pages[dp->or_page >> immu_state->pagesize_log2] = dp;
  cpu_state.dyn_pages[dp->or_page >> immu_state->pagesize_log2] = dp;
  return dp;
  return dp;
}
}
 
 
void dyn_main(void)
void dyn_main(void)
{
{
  struct dyn_page *target_dp;
  struct dyn_page *target_dp;
  oraddr_t phys_page;
  oraddr_t phys_page;
 
 
  setjmp(cpu_state.excpt_loc);
  setjmp(cpu_state.excpt_loc);
  for(;;) {
  for(;;) {
    phys_page = immu_translate(cpu_state.pc);
    phys_page = immu_translate(cpu_state.pc);
 
 
/*
/*
    printf("Recompiled code jumping out to %"PRIxADDR" from %"PRIxADDR"\n",
    printf("Recompiled code jumping out to %"PRIxADDR" from %"PRIxADDR"\n",
           phys_page, cpu_state.sprs[SPR_PPC] - 4);
           phys_page, cpu_state.sprs[SPR_PPC] - 4);
*/
*/
 
 
    /* immu_translate() adds the hit delay to runtime.sim.mem_cycles but we add
    /* immu_translate() adds the hit delay to runtime.sim.mem_cycles but we add
     * it to the cycles when the instruction is executed so if we don't reset it
     * it to the cycles when the instruction is executed so if we don't reset it
     * now it will produce wrong results */
     * now it will produce wrong results */
    runtime.sim.mem_cycles = 0;
    runtime.sim.mem_cycles = 0;
 
 
    target_dp = cpu_state.dyn_pages[phys_page >> immu_state->pagesize_log2];
    target_dp = cpu_state.dyn_pages[phys_page >> immu_state->pagesize_log2];
 
 
    if(!target_dp)
    if(!target_dp)
      target_dp = new_dp(phys_page);
      target_dp = new_dp(phys_page);
 
 
    /* Since writes to the 0x0-0xff range do not dirtyfy a page recompile the
    /* Since writes to the 0x0-0xff range do not dirtyfy a page recompile the
     *  0x0 page if the jump is to that location */
     *  0x0 page if the jump is to that location */
    if(phys_page < 0x100)
    if(phys_page < 0x100)
      target_dp->dirty = 1;
      target_dp->dirty = 1;
 
 
    if(target_dp->dirty)
    if(target_dp->dirty)
      recompile_page(target_dp);
      recompile_page(target_dp);
 
 
    cpu_state.curr_page = target_dp;
    cpu_state.curr_page = target_dp;
 
 
    /* FIXME: If the page is backed by more than one type of memory, this will
    /* FIXME: If the page is backed by more than one type of memory, this will
     * produce wrong results */
     * produce wrong results */
    cpu_state.cycles_dec = target_dp->delayr;
    cpu_state.cycles_dec = target_dp->delayr;
    if(cpu_state.sprs[SPR_SR] & SPR_SR_IME)
    if(cpu_state.sprs[SPR_SR] & SPR_SR_IME)
      /* Add the mmu hit delay to the cycle counter */
      /* Add the mmu hit delay to the cycle counter */
      cpu_state.cycles_dec -= immu_state->hitdelay;
      cpu_state.cycles_dec -= immu_state->hitdelay;
 
 
    /* FIXME: ebp, ebx, esi and edi are expected to be preserved across function
    /* FIXME: ebp, ebx, esi and edi are expected to be preserved across function
     * calls but the recompiled code trashes them... */
     * calls but the recompiled code trashes them... */
    enter_dyn_code(phys_page, target_dp);
    enter_dyn_code(phys_page, target_dp);
  }
  }
}
}
 
 
static void immu_retranslate(void *dat)
static void immu_retranslate(void *dat)
{
{
  int got_en_dis = (int)dat;
  int got_en_dis = (int)dat;
  immu_translate(cpu_state.pc);
  immu_translate(cpu_state.pc);
  runtime.sim.mem_cycles = 0;
  runtime.sim.mem_cycles = 0;
 
 
  /* Only update the cycle decrementer if the mmu got enabled or disabled */
  /* Only update the cycle decrementer if the mmu got enabled or disabled */
  if(got_en_dis == IMMU_GOT_ENABLED)
  if(got_en_dis == IMMU_GOT_ENABLED)
    /* Add the mmu hit delay to the cycle counter */
    /* Add the mmu hit delay to the cycle counter */
    cpu_state.cycles_dec = cpu_state.curr_page->delayr - immu_state->hitdelay;
    cpu_state.cycles_dec = cpu_state.curr_page->delayr - immu_state->hitdelay;
  else if(got_en_dis == IMMU_GOT_DISABLED)
  else if(got_en_dis == IMMU_GOT_DISABLED)
    cpu_state.cycles_dec = cpu_state.curr_page->delayr;
    cpu_state.cycles_dec = cpu_state.curr_page->delayr;
}
}
 
 
/* This is called whenever the immu is either enabled/disabled or reconfigured
/* This is called whenever the immu is either enabled/disabled or reconfigured
 * while enabled.  This checks if an itlb miss would occour and updates the immu
 * while enabled.  This checks if an itlb miss would occour and updates the immu
 * hit delay counter */
 * hit delay counter */
void recheck_immu(int got_en_dis)
void recheck_immu(int got_en_dis)
{
{
  oraddr_t addr;
  oraddr_t addr;
 
 
  if(cpu_state.delay_insn)
  if(cpu_state.delay_insn)
    addr = cpu_state.pc_delay;
    addr = cpu_state.pc_delay;
  else
  else
    addr = cpu_state.pc + 4;
    addr = cpu_state.pc + 4;
 
 
  if(IADDR_PAGE(cpu_state.pc) == IADDR_PAGE(addr))
  if(IADDR_PAGE(cpu_state.pc) == IADDR_PAGE(addr))
    /* Schedule a job to do immu_translate() */
    /* Schedule a job to do immu_translate() */
    SCHED_ADD(immu_retranslate, (void *)got_en_dis, 0);
    SCHED_ADD(immu_retranslate, (void *)got_en_dis, 0);
}
}
 
 
/* Runs the scheduler.  Called from except_handler (and dirtyfy_page below) */
/* Runs the scheduler.  Called from except_handler (and dirtyfy_page below) */
void run_sched_out_of_line(void)
void run_sched_out_of_line(void)
{
{
  oraddr_t off = (cpu_state.pc & immu_state->page_offset_mask) >> 2;
  oraddr_t off = (cpu_state.pc & immu_state->page_offset_mask) >> 2;
 
 
  if(do_stats) {
  if(do_stats) {
    cpu_state.iqueue.insn_addr = cpu_state.pc;
    cpu_state.iqueue.insn_addr = cpu_state.pc;
    cpu_state.iqueue.insn = cpu_state.curr_page->insns[off];
    cpu_state.iqueue.insn = cpu_state.curr_page->insns[off];
    cpu_state.iqueue.insn_index = cpu_state.curr_page->insn_indexs[off];
    cpu_state.iqueue.insn_index = cpu_state.curr_page->insn_indexs[off];
    runtime.cpu.instructions++;
    runtime.cpu.instructions++;
    analysis(&cpu_state.iqueue);
    analysis(&cpu_state.iqueue);
  }
  }
 
 
  /* Run the scheduler */
  /* Run the scheduler */
  scheduler.job_queue->time += cpu_state.cycles_dec;
  scheduler.job_queue->time += cpu_state.cycles_dec;
  runtime.sim.cycles -= cpu_state.cycles_dec;
  runtime.sim.cycles -= cpu_state.cycles_dec;
 
 
  op_join_mem_cycles();
  op_join_mem_cycles();
  if(scheduler.job_queue->time <= 0)
  if(scheduler.job_queue->time <= 0)
    do_scheduler();
    do_scheduler();
}
}
 
 
/* Signals a page as dirty */
/* Signals a page as dirty */
static void dirtyfy_page(struct dyn_page *dp)
static void dirtyfy_page(struct dyn_page *dp)
{
{
  oraddr_t check;
  oraddr_t check;
 
 
  printf("Dirtyfying page 0x%"PRIxADDR"\n", dp->or_page);
  printf("Dirtyfying page 0x%"PRIxADDR"\n", dp->or_page);
 
 
  dp->dirty = 1;
  dp->dirty = 1;
 
 
  /* If the execution is currently in the page that was touched then recompile
  /* If the execution is currently in the page that was touched then recompile
   * it now and jump back to the point of execution */
   * it now and jump back to the point of execution */
  check = cpu_state.delay_insn ? cpu_state.pc_delay : cpu_state.pc + 4;
  check = cpu_state.delay_insn ? cpu_state.pc_delay : cpu_state.pc + 4;
  if(IADDR_PAGE(check) == dp->or_page) {
  if(IADDR_PAGE(check) == dp->or_page) {
    run_sched_out_of_line();
    run_sched_out_of_line();
    recompile_page(dp);
    recompile_page(dp);
 
 
    cpu_state.delay_insn = 0;
    cpu_state.delay_insn = 0;
 
 
    /* Jump out to the next instruction */
    /* Jump out to the next instruction */
    do_jump(check);
    do_jump(check);
  }
  }
}
}
 
 
/* Checks to see if a write happened to a recompiled page.  If so marks it as
/* Checks to see if a write happened to a recompiled page.  If so marks it as
 * dirty */
 * dirty */
void dyn_checkwrite(oraddr_t addr)
void dyn_checkwrite(oraddr_t addr)
{
{
  /* FIXME: Do this with mprotect() */
  /* FIXME: Do this with mprotect() */
  struct dyn_page *dp = cpu_state.dyn_pages[addr >> immu_state->pagesize_log2];
  struct dyn_page *dp = cpu_state.dyn_pages[addr >> immu_state->pagesize_log2];
 
 
  /* Since the locations 0x0-0xff are nearly always written to in an exception
  /* Since the locations 0x0-0xff are nearly always written to in an exception
   * handler, ignore any writes to these locations.  If code ends up jumping
   * handler, ignore any writes to these locations.  If code ends up jumping
   * out there, we'll recompile when the jump actually happens. */
   * out there, we'll recompile when the jump actually happens. */
  if((addr > 0x100) && dp && !dp->dirty)
  if((addr > 0x100) && dp && !dp->dirty)
    dirtyfy_page(dp);
    dirtyfy_page(dp);
}
}
 
 
/* Moves the temprary t to its permanent storage if it has been used as a
/* Moves the temprary t to its permanent storage if it has been used as a
 * destination register */
 * destination register */
static void ship_t_out(struct op_queue *opq, unsigned int t)
static void ship_t_out(struct op_queue *opq, unsigned int t)
{
{
  unsigned int gpr = opq->reg_t[t];
  unsigned int gpr = opq->reg_t[t];
 
 
  for(; opq; opq = opq->prev) {
  for(; opq; opq = opq->prev) {
    if(opq->reg_t[t] != gpr)
    if(opq->reg_t[t] != gpr)
      return;
      return;
    if((opq->tflags[t] & TFLAG_DST) && !(opq->tflags[t] & TFLAG_SAVED)) {
    if((opq->tflags[t] & TFLAG_DST) && !(opq->tflags[t] & TFLAG_SAVED)) {
      opq->tflags[t] |= TFLAG_SAVED;
      opq->tflags[t] |= TFLAG_SAVED;
 
 
      /* FIXME: Check if this is still neccesary */
      /* FIXME: Check if this is still neccesary */
      /* Before takeing the temporaries out, temporarily remove the op_do_sched
      /* Before takeing the temporaries out, temporarily remove the op_do_sched
       * operation such that dyn_page->ts_bound shall be correct before the
       * operation such that dyn_page->ts_bound shall be correct before the
       * scheduler runs */
       * scheduler runs */
      if(opq->num_ops && (opq->ops[opq->num_ops - 1] == op_do_sched_indx)) {
      if(opq->num_ops && (opq->ops[opq->num_ops - 1] == op_do_sched_indx)) {
        opq->num_ops--;
        opq->num_ops--;
        gen_op_move_gpr_t[t][gpr](opq, 1);
        gen_op_move_gpr_t[t][gpr](opq, 1);
        gen_op_do_sched(opq, 1);
        gen_op_do_sched(opq, 1);
        return;
        return;
      }
      }
 
 
      gen_op_move_gpr_t[t][gpr](opq, 1);
      gen_op_move_gpr_t[t][gpr](opq, 1);
 
 
      return;
      return;
    }
    }
  }
  }
}
}
 
 
static void ship_gprs_out_t(struct op_queue *opq)
static void ship_gprs_out_t(struct op_queue *opq)
{
{
  int i;
  int i;
 
 
  if(!opq)
  if(!opq)
    return;
    return;
 
 
  for(i = 0; i < NUM_T_REGS; i++) {
  for(i = 0; i < NUM_T_REGS; i++) {
    if(opq->reg_t[i] < 32)
    if(opq->reg_t[i] < 32)
      /* Ship temporaries out in the last opq that actually touched it */
      /* Ship temporaries out in the last opq that actually touched it */
      ship_t_out(opq, i);
      ship_t_out(opq, i);
  }
  }
}
}
 
 
/* FIXME: Look at the following instructions to make a better guess at which
/* FIXME: Look at the following instructions to make a better guess at which
 * temporary to return */
 * temporary to return */
static int find_t(struct op_queue *opq, unsigned int reg)
static int find_t(struct op_queue *opq, unsigned int reg)
{
{
  int i, j, t = -1;
  int i, j, t = -1;
 
 
  for(i = 0; i < NUM_T_REGS; i++) {
  for(i = 0; i < NUM_T_REGS; i++) {
    if(opq->reg_t[i] == reg)
    if(opq->reg_t[i] == reg)
      return i;
      return i;
 
 
    /* Ok, we have found an as-yet unused temporary, check if it is needed
    /* Ok, we have found an as-yet unused temporary, check if it is needed
     * later in this instruction */
     * later in this instruction */
    for(j = 0; j < opq->param_num; j++) {
    for(j = 0; j < opq->param_num; j++) {
      if((opq->param_type[j] & OPTYPE_REG) && (opq->param[j] == opq->reg_t[i]))
      if((opq->param_type[j] & OPTYPE_REG) && (opq->param[j] == opq->reg_t[i]))
        break;
        break;
    }
    }
 
 
    if(j != opq->param_num)
    if(j != opq->param_num)
      continue;
      continue;
 
 
    /* We have found the temporary (temporarily:) fit for use */
    /* We have found the temporary (temporarily:) fit for use */
    if((t == -1) || (opq->reg_t[i] == 32))
    if((t == -1) || (opq->reg_t[i] == 32))
      t = i;
      t = i;
  }
  }
 
 
  return t;
  return t;
}
}
 
 
/* Checks if there is enough space in dp->host_page, if not grow it */
/* Checks if there is enough space in dp->host_page, if not grow it */
void *enough_host_page(struct dyn_page *dp, void *cur, unsigned int *len,
void *enough_host_page(struct dyn_page *dp, void *cur, unsigned int *len,
                       unsigned int amount)
                       unsigned int amount)
{
{
  unsigned int used = cur - dp->host_page;
  unsigned int used = cur - dp->host_page;
 
 
  /* The array is long enough */
  /* The array is long enough */
  if((used + amount) <= *len)
  if((used + amount) <= *len)
    return cur;
    return cur;
 
 
  /* Reallocate */
  /* Reallocate */
  *len += RECED_PAGE_ENLARGE_BY;
  *len += RECED_PAGE_ENLARGE_BY;
 
 
  if(!(dp->host_page = realloc(dp->host_page, *len))) {
  if(!(dp->host_page = realloc(dp->host_page, *len))) {
    fprintf(stderr, "OOM\n");
    fprintf(stderr, "OOM\n");
    exit(1);
    exit(1);
  }
  }
 
 
  return dp->host_page + used;
  return dp->host_page + used;
}
}
 
 
/* Adds an operation to the opq */
/* Adds an operation to the opq */
void add_to_opq(struct op_queue *opq, int end, int op)
void add_to_opq(struct op_queue *opq, int end, int op)
{
{
  if(opq->num_ops == opq->ops_len) {
  if(opq->num_ops == opq->ops_len) {
    opq->ops_len += OPS_ENLARGE_BY;
    opq->ops_len += OPS_ENLARGE_BY;
    if(!(opq->ops = realloc(opq->ops, opq->ops_len * sizeof(int)))) {
    if(!(opq->ops = realloc(opq->ops, opq->ops_len * sizeof(int)))) {
      fprintf(stderr, "OOM\n");
      fprintf(stderr, "OOM\n");
      exit(1);
      exit(1);
    }
    }
  }
  }
 
 
  if(end)
  if(end)
    opq->ops[opq->num_ops] = op;
    opq->ops[opq->num_ops] = op;
  else {
  else {
    /* Shift everything over by one */
    /* Shift everything over by one */
    memmove(opq->ops + 1, opq->ops, opq->num_ops* sizeof(int));
    memmove(opq->ops + 1, opq->ops, opq->num_ops* sizeof(int));
    opq->ops[0] = op;
    opq->ops[0] = op;
  }
  }
 
 
  opq->num_ops++;
  opq->num_ops++;
}
}
 
 
static void gen_op_mark_loc(struct op_queue *opq, int end)
static void gen_op_mark_loc(struct op_queue *opq, int end)
{
{
  add_to_opq(opq, end, op_mark_loc_indx);
  add_to_opq(opq, end, op_mark_loc_indx);
}
}
 
 
/* Adds a parameter to the opq */
/* Adds a parameter to the opq */
void add_to_op_params(struct op_queue *opq, int end, unsigned long param)
void add_to_op_params(struct op_queue *opq, int end, unsigned long param)
{
{
  if(opq->num_ops_param == opq->ops_param_len) {
  if(opq->num_ops_param == opq->ops_param_len) {
    opq->ops_param_len += OPS_ENLARGE_BY;
    opq->ops_param_len += OPS_ENLARGE_BY;
    if(!(opq->ops_param = realloc(opq->ops_param, opq->ops_param_len * sizeof(int)))) {
    if(!(opq->ops_param = realloc(opq->ops_param, opq->ops_param_len * sizeof(int)))) {
      fprintf(stderr, "OOM\n");
      fprintf(stderr, "OOM\n");
      exit(1);
      exit(1);
    }
    }
  }
  }
 
 
  if(end)
  if(end)
    opq->ops_param[opq->num_ops_param] = param;
    opq->ops_param[opq->num_ops_param] = param;
  else {
  else {
    /* Shift everything over by one */
    /* Shift everything over by one */
    memmove(opq->ops_param + 1, opq->ops_param, opq->num_ops_param);
    memmove(opq->ops_param + 1, opq->ops_param, opq->num_ops_param);
    opq->ops_param[0] = param;
    opq->ops_param[0] = param;
  }
  }
 
 
  opq->num_ops_param++;
  opq->num_ops_param++;
}
}
 
 
/* Initialises the recompiler */
/* Initialises the recompiler */
void init_dyn_recomp(void)
void init_dyn_recomp(void)
{
{
  struct sigaction sigact;
  struct sigaction sigact;
  struct op_queue *opq = NULL;
  struct op_queue *opq = NULL;
  unsigned int i;
  unsigned int i;
 
 
  cpu_state.opqs = NULL;
  cpu_state.opqs = NULL;
 
 
  /* Allocate the operation queue list (+1 for the page chaining) */
  /* Allocate the operation queue list (+1 for the page chaining) */
  for(i = 0; i < (immu_state->pagesize / 4) + 1; i++) {
  for(i = 0; i < (immu_state->pagesize / 4) + 1; i++) {
    if(!(opq = malloc(sizeof(struct op_queue)))) {
    if(!(opq = malloc(sizeof(struct op_queue)))) {
      fprintf(stderr, "OOM\n");
      fprintf(stderr, "OOM\n");
      exit(1);
      exit(1);
    }
    }
 
 
    /* initialise some fields */
    /* initialise some fields */
    opq->ops_len = 0;
    opq->ops_len = 0;
    opq->ops = NULL;
    opq->ops = NULL;
    opq->ops_param_len = 0;
    opq->ops_param_len = 0;
    opq->ops_param = NULL;
    opq->ops_param = NULL;
    opq->xref = 0;
    opq->xref = 0;
 
 
    if(cpu_state.opqs)
    if(cpu_state.opqs)
      cpu_state.opqs->prev = opq;
      cpu_state.opqs->prev = opq;
 
 
    opq->next = cpu_state.opqs;
    opq->next = cpu_state.opqs;
    cpu_state.opqs = opq;
    cpu_state.opqs = opq;
  }
  }
 
 
  opq->prev = NULL;
  opq->prev = NULL;
 
 
  cpu_state.curr_page = NULL;
  cpu_state.curr_page = NULL;
  if(!(cpu_state.dyn_pages = malloc(sizeof(void *) * (2 << (32 -
  if(!(cpu_state.dyn_pages = malloc(sizeof(void *) * (2 << (32 -
                                                immu_state->pagesize_log2))))) {
                                                immu_state->pagesize_log2))))) {
    fprintf(stderr, "OOM\n");
    fprintf(stderr, "OOM\n");
    exit(1);
    exit(1);
  }
  }
  memset(cpu_state.dyn_pages, 0,
  memset(cpu_state.dyn_pages, 0,
         sizeof(void *) * (2 << (32 - immu_state->pagesize_log2)));
         sizeof(void *) * (2 << (32 - immu_state->pagesize_log2)));
 
 
  /* Register our segmentation fault handler */
  /* Register our segmentation fault handler */
  sigact.sa_sigaction = dyn_sigsegv_debug;
  sigact.sa_sigaction = dyn_sigsegv_debug;
  memset(&sigact.sa_mask, 0, sizeof(sigact.sa_mask));
  memset(&sigact.sa_mask, 0, sizeof(sigact.sa_mask));
  sigact.sa_flags = SA_SIGINFO | SA_NOMASK;
  sigact.sa_flags = SA_SIGINFO | SA_NOMASK;
  if(sigaction(SIGSEGV, &sigact, NULL))
  if(sigaction(SIGSEGV, &sigact, NULL))
    printf("WARN: Unable to install SIGSEGV handler! Don't expect to be able to debug the recompiler.\n");
    printf("WARN: Unable to install SIGSEGV handler! Don't expect to be able to debug the recompiler.\n");
 
 
  /* FIXME: Find a better place for this */
  /* FIXME: Find a better place for this */
    { /* Needed by execution */
    { /* Needed by execution */
      extern int do_stats;
      extern int do_stats;
      do_stats = config.cpu.dependstats || config.cpu.superscalar || config.cpu.dependstats
      do_stats = config.cpu.dependstats || config.cpu.superscalar || config.cpu.dependstats
              || config.sim.history || config.sim.exe_log;
              || config.sim.history || config.sim.exe_log;
    }
    }
 
 
  printf("Recompile engine up and running\n");
  printf("Recompile engine up and running\n");
}
}
 
 
/* Parses instructions and their operands and populates opq with them */
/* Parses instructions and their operands and populates opq with them */
static void eval_insn_ops(struct op_queue *opq, oraddr_t addr)
static void eval_insn_ops(struct op_queue *opq, oraddr_t addr)
{
{
  int breakp;
  int breakp;
  struct insn_op_struct *opd;
  struct insn_op_struct *opd;
 
 
  for(; opq->next; opq = opq->next, addr += 4) {
  for(; opq->next; opq = opq->next, addr += 4) {
    opq->param_num = 0;
    opq->param_num = 0;
    breakp = 0;
    breakp = 0;
    opq->insn = eval_insn(addr, &breakp);
    opq->insn = eval_insn(addr, &breakp);
 
 
    /* FIXME: If a breakpoint is set at this location, insert exception code */
    /* FIXME: If a breakpoint is set at this location, insert exception code */
    if(breakp) {
    if(breakp) {
      fprintf(stderr, "FIXME: Insert breakpoint code\n");
      fprintf(stderr, "FIXME: Insert breakpoint code\n");
    }
    }
 
 
    opq->insn_index = insn_decode(opq->insn);
    opq->insn_index = insn_decode(opq->insn);
 
 
    if(opq->insn_index == -1)
    if(opq->insn_index == -1)
      continue;
      continue;
 
 
    opd = op_start[opq->insn_index];
    opd = op_start[opq->insn_index];
 
 
    do {
    do {
      opq->param[opq->param_num] = eval_operand_val(opq->insn, opd);
      opq->param[opq->param_num] = eval_operand_val(opq->insn, opd);
      opq->param_type[opq->param_num] = opd->type;
      opq->param_type[opq->param_num] = opd->type;
 
 
      opq->param_num++;
      opq->param_num++;
      while(!(opd->type & OPTYPE_OP)) opd++;
      while(!(opd->type & OPTYPE_OP)) opd++;
    } while(!(opd++->type & OPTYPE_LAST));
    } while(!(opd++->type & OPTYPE_LAST));
  }
  }
}
}
 
 
/* Adds code to the opq for the instruction pointed to by addr */
/* Adds code to the opq for the instruction pointed to by addr */
static void recompile_insn(struct op_queue *opq, int delay_insn)
static void recompile_insn(struct op_queue *opq, int delay_insn)
{
{
  int j, k;
  int j, k;
  int param_t[5]; /* Which temporary the parameters reside in */
  int param_t[5]; /* Which temporary the parameters reside in */
 
 
  /* Check if we have an illegal instruction */
  /* Check if we have an illegal instruction */
  if(opq->insn_index == -1) {
  if(opq->insn_index == -1) {
    gen_l_invalid(opq, NULL, delay_insn);
    gen_l_invalid(opq, NULL, delay_insn);
    return;
    return;
  }
  }
 
 
  /* If we are recompileing an instruction that has a delay slot and is in the
  /* If we are recompileing an instruction that has a delay slot and is in the
   * delay slot, ignore it.  This is undefined behavour. */
   * delay slot, ignore it.  This is undefined behavour. */
  if(delay_insn && (or32_opcodes[opq->insn_index].flags & OR32_IF_DELAY))
  if(delay_insn && (or32_opcodes[opq->insn_index].flags & OR32_IF_DELAY))
    return;
    return;
 
 
  param_t[0] = T_NONE;
  param_t[0] = T_NONE;
  param_t[1] = T_NONE;
  param_t[1] = T_NONE;
  param_t[2] = T_NONE;
  param_t[2] = T_NONE;
  param_t[3] = T_NONE;
  param_t[3] = T_NONE;
  param_t[4] = T_NONE;
  param_t[4] = T_NONE;
 
 
  /* Jump instructions are special since they have a delay slot and thus they
  /* Jump instructions are special since they have a delay slot and thus they
   * need to control the exact operation sequence.  Special case these here to
   * need to control the exact operation sequence.  Special case these here to
   * avoid haveing loads of if(!(.& OR32_IF_DELAY)) below */
   * avoid haveing loads of if(!(.& OR32_IF_DELAY)) below */
  if(or32_opcodes[opq->insn_index].flags & OR32_IF_DELAY) {
  if(or32_opcodes[opq->insn_index].flags & OR32_IF_DELAY) {
    /* Jump instructions don't have a disposition */
    /* Jump instructions don't have a disposition */
    or32_opcodes[opq->insn_index].exec(opq, param_t, delay_insn);
    or32_opcodes[opq->insn_index].exec(opq, param_t, delay_insn);
 
 
    /* Analysis is done by the individual jump instructions */
    /* Analysis is done by the individual jump instructions */
    /* Jump instructions don't touch runtime.sim.mem_cycles */
    /* Jump instructions don't touch runtime.sim.mem_cycles */
    /* Jump instructions run their own scheduler */
    /* Jump instructions run their own scheduler */
    return;
    return;
  }
  }
 
 
  /* Before an exception takes place, all registers must be stored. */
  /* Before an exception takes place, all registers must be stored. */
  if((or32_opcodes[opq->insn_index].func_unit == it_exception)) {
  if((or32_opcodes[opq->insn_index].func_unit == it_exception)) {
    ship_gprs_out_t(opq);
    ship_gprs_out_t(opq);
 
 
    or32_opcodes[opq->insn_index].exec(opq, param_t, delay_insn);
    or32_opcodes[opq->insn_index].exec(opq, param_t, delay_insn);
    return;
    return;
  }
  }
 
 
  for(j = 0; j < opq->param_num; j++) {
  for(j = 0; j < opq->param_num; j++) {
    if(!(opq->param_type[j] & OPTYPE_REG))
    if(!(opq->param_type[j] & OPTYPE_REG))
      continue;
      continue;
 
 
    /* Never, ever, move r0 into a temporary */
    /* Never, ever, move r0 into a temporary */
    if(!opq->param[j])
    if(!opq->param[j])
      continue;
      continue;
 
 
    k = find_t(opq, opq->param[j]);
    k = find_t(opq, opq->param[j]);
 
 
    param_t[j] = k;
    param_t[j] = k;
 
 
    if(opq->reg_t[k] == opq->param[j]) {
    if(opq->reg_t[k] == opq->param[j]) {
      if(!(opq->param_type[j] & OPTYPE_DST) &&
      if(!(opq->param_type[j] & OPTYPE_DST) &&
         !(opq->tflags[k] & TFLAG_SOURCED)) {
         !(opq->tflags[k] & TFLAG_SOURCED)) {
        gen_op_move_t_gpr[k][opq->reg_t[k]](opq, 0);
        gen_op_move_t_gpr[k][opq->reg_t[k]](opq, 0);
        opq->tflags[k] |= TFLAG_SOURCED;
        opq->tflags[k] |= TFLAG_SOURCED;
      }
      }
 
 
      if(opq->param_type[j] & OPTYPE_DST)
      if(opq->param_type[j] & OPTYPE_DST)
        opq->tflags[k] |= TFLAG_DST;
        opq->tflags[k] |= TFLAG_DST;
      else
      else
        opq->tflags[k] |= TFLAG_SRC;
        opq->tflags[k] |= TFLAG_SRC;
 
 
      continue;
      continue;
    }
    }
 
 
    if(opq->reg_t[k] < 32) {
    if(opq->reg_t[k] < 32) {
      /* Only ship the temporary out if it has been used as a destination
      /* Only ship the temporary out if it has been used as a destination
       * register */
       * register */
      ship_t_out(opq, k);
      ship_t_out(opq, k);
    }
    }
 
 
    if(opq->param_type[j] & OPTYPE_DST)
    if(opq->param_type[j] & OPTYPE_DST)
      opq->tflags[k] = TFLAG_DST;
      opq->tflags[k] = TFLAG_DST;
    else
    else
      opq->tflags[k] = TFLAG_SRC;
      opq->tflags[k] = TFLAG_SRC;
 
 
    opq->reg_t[k] = opq->param[j];
    opq->reg_t[k] = opq->param[j];
 
 
    /* Only generate code to move the register into a temporary if it is used as
    /* Only generate code to move the register into a temporary if it is used as
     * a source operand */
     * a source operand */
    if(!(opq->param_type[j] & OPTYPE_DST)) {
    if(!(opq->param_type[j] & OPTYPE_DST)) {
      gen_op_move_t_gpr[k][opq->reg_t[k]](opq, 0);
      gen_op_move_t_gpr[k][opq->reg_t[k]](opq, 0);
      opq->tflags[k] |= TFLAG_SOURCED;
      opq->tflags[k] |= TFLAG_SOURCED;
    }
    }
  }
  }
 
 
  /* To get the execution log correct for instructions like l.lwz r4,0(r4) the
  /* To get the execution log correct for instructions like l.lwz r4,0(r4) the
   * effective address needs to be calculated before the instruction is
   * effective address needs to be calculated before the instruction is
   * simulated */
   * simulated */
  if(do_stats) {
  if(do_stats) {
    for(j = 0; j < opq->param_num; j++) {
    for(j = 0; j < opq->param_num; j++) {
      if(!(opq->param_type[j] & OPTYPE_DIS))
      if(!(opq->param_type[j] & OPTYPE_DIS))
        continue;
        continue;
 
 
      if(!opq->param[j + 1])
      if(!opq->param[j + 1])
        gen_op_store_insn_ea(opq, 1, opq->param[j]);
        gen_op_store_insn_ea(opq, 1, opq->param[j]);
      else
      else
        calc_insn_ea_table[param_t[j + 1]](opq, 1, opq->param[j]);
        calc_insn_ea_table[param_t[j + 1]](opq, 1, opq->param[j]);
    }
    }
  }
  }
 
 
  or32_opcodes[opq->insn_index].exec(opq, param_t, delay_insn);
  or32_opcodes[opq->insn_index].exec(opq, param_t, delay_insn);
 
 
  if(do_stats) {
  if(do_stats) {
    ship_gprs_out_t(opq);
    ship_gprs_out_t(opq);
    gen_op_analysis(opq, 1);
    gen_op_analysis(opq, 1);
  }
  }
 
 
  /* The call to join_mem_cycles() could be put into the individual operations
  /* The call to join_mem_cycles() could be put into the individual operations
   * that emulate the load/store instructions, but then it would be added to
   * that emulate the load/store instructions, but then it would be added to
   * the cycle counter before analysis() is called, which is not how the complex
   * the cycle counter before analysis() is called, which is not how the complex
   * execution model does it. */
   * execution model does it. */
  if((or32_opcodes[opq->insn_index].func_unit == it_load) ||
  if((or32_opcodes[opq->insn_index].func_unit == it_load) ||
     (or32_opcodes[opq->insn_index].func_unit == it_store))
     (or32_opcodes[opq->insn_index].func_unit == it_store))
    gen_op_join_mem_cycles(opq, 1);
    gen_op_join_mem_cycles(opq, 1);
 
 
  /* Delay slot instructions get a special scheduler, thus don't generate it
  /* Delay slot instructions get a special scheduler, thus don't generate it
   * here */
   * here */
  if(!delay_insn)
  if(!delay_insn)
    gen_op_do_sched(opq, 1);
    gen_op_do_sched(opq, 1);
}
}
 
 
/* Recompiles the page associated with *dyn */
/* Recompiles the page associated with *dyn */
void recompile_page(struct dyn_page *dyn)
void recompile_page(struct dyn_page *dyn)
{
{
  unsigned int j;
  unsigned int j;
  struct op_queue *opq = cpu_state.opqs;
  struct op_queue *opq = cpu_state.opqs;
  oraddr_t rec_addr = dyn->or_page;
  oraddr_t rec_addr = dyn->or_page;
  oraddr_t rec_page = dyn->or_page;
  oraddr_t rec_page = dyn->or_page;
  void **loc;
  void **loc;
 
 
  /* The start of the next page */
  /* The start of the next page */
  rec_page += immu_state->pagesize;
  rec_page += immu_state->pagesize;
 
 
  printf("Recompileing page %"PRIxADDR"\n", rec_addr);
  printf("Recompileing page %"PRIxADDR"\n", rec_addr);
  fflush(stdout);
  fflush(stdout);
 
 
  /* Mark all temporaries as not containing a register */
  /* Mark all temporaries as not containing a register */
  for(j = 0; j < NUM_T_REGS; j++) {
  for(j = 0; j < NUM_T_REGS; j++) {
    opq->reg_t[j] = 32; /* Out-of-range registers */
    opq->reg_t[j] = 32; /* Out-of-range registers */
    opq->tflags[j] = 0;
    opq->tflags[j] = 0;
  }
  }
 
 
  dyn->delayr = -verify_memoryarea(rec_addr)->ops.delayr;
  dyn->delayr = -verify_memoryarea(rec_addr)->ops.delayr;
 
 
  opq->num_ops = 0;
  opq->num_ops = 0;
  opq->num_ops_param = 0;
  opq->num_ops_param = 0;
 
 
  eval_insn_ops(opq, rec_addr);
  eval_insn_ops(opq, rec_addr);
 
 
  /* Insert code to check if the first instruction is exeucted in a delay slot*/
  /* Insert code to check if the first instruction is exeucted in a delay slot*/
  gen_op_check_delay_slot(opq, 1, 0);
  gen_op_check_delay_slot(opq, 1, 0);
  recompile_insn(opq, 1);
  recompile_insn(opq, 1);
  ship_gprs_out_t(opq);
  ship_gprs_out_t(opq);
  gen_op_do_sched_delay(opq, 1);
  gen_op_do_sched_delay(opq, 1);
  gen_op_clear_delay_insn(opq, 1);
  gen_op_clear_delay_insn(opq, 1);
  gen_op_do_jump_delay(opq, 1);
  gen_op_do_jump_delay(opq, 1);
  gen_op_do_jump(opq, 1);
  gen_op_do_jump(opq, 1);
  gen_op_mark_loc(opq, 1);
  gen_op_mark_loc(opq, 1);
 
 
  for(j = 0; j < NUM_T_REGS; j++)
  for(j = 0; j < NUM_T_REGS; j++)
    opq->reg_t[j] = 32; /* Out-of-range registers */
    opq->reg_t[j] = 32; /* Out-of-range registers */
 
 
  for(; rec_addr < rec_page; rec_addr += 4, opq = opq->next) {
  for(; rec_addr < rec_page; rec_addr += 4, opq = opq->next) {
    if(opq->prev) {
    if(opq->prev) {
      opq->num_ops = 0;
      opq->num_ops = 0;
      opq->num_ops_param = 0;
      opq->num_ops_param = 0;
    }
    }
    opq->jump_local = -1;
    opq->jump_local = -1;
    opq->not_jump_loc = -1;
    opq->not_jump_loc = -1;
 
 
    opq->insn_addr = rec_addr;
    opq->insn_addr = rec_addr;
 
 
    for(j = 0; j < NUM_T_REGS; j++)
    for(j = 0; j < NUM_T_REGS; j++)
      opq->tflags[j] = TFLAG_SOURCED;
      opq->tflags[j] = TFLAG_SOURCED;
 
 
    /* Check if this location is cross referenced */
    /* Check if this location is cross referenced */
    if(opq->xref) {
    if(opq->xref) {
      /* If the current address is cross-referenced, the temporaries shall be
      /* If the current address is cross-referenced, the temporaries shall be
       * in an undefined state, so we must assume that no registers reside in
       * in an undefined state, so we must assume that no registers reside in
       * them */
       * them */
      /* Ship out the current set of registers from the temporaries */
      /* Ship out the current set of registers from the temporaries */
      if(opq->prev) {
      if(opq->prev) {
        ship_gprs_out_t(opq->prev);
        ship_gprs_out_t(opq->prev);
        for(j = 0; j < NUM_T_REGS; j++) {
        for(j = 0; j < NUM_T_REGS; j++) {
          opq->reg_t[j] = 32;
          opq->reg_t[j] = 32;
          opq->prev->reg_t[j] = 32;
          opq->prev->reg_t[j] = 32;
        }
        }
      }
      }
    }
    }
 
 
    recompile_insn(opq, 0);
    recompile_insn(opq, 0);
 
 
    /* Store the state of the temporaries */
    /* Store the state of the temporaries */
    memcpy(opq->next->reg_t, opq->reg_t, sizeof(opq->reg_t));
    memcpy(opq->next->reg_t, opq->reg_t, sizeof(opq->reg_t));
  }
  }
 
 
  dyn->dirty = 0;
  dyn->dirty = 0;
 
 
  /* Ship temporaries out to the corrisponding registers */
  /* Ship temporaries out to the corrisponding registers */
  ship_gprs_out_t(opq->prev);
  ship_gprs_out_t(opq->prev);
 
 
  opq->num_ops = 0;
  opq->num_ops = 0;
  opq->num_ops_param = 0;
  opq->num_ops_param = 0;
  opq->not_jump_loc = -1;
  opq->not_jump_loc = -1;
  opq->jump_local = -1;
  opq->jump_local = -1;
 
 
  /* Insert code to jump to the next page */
  /* Insert code to jump to the next page */
  gen_op_do_jump(opq, 1);
  gen_op_do_jump(opq, 1);
 
 
  /* Generate the code */
  /* Generate the code */
  gen_code(cpu_state.opqs, dyn);
  gen_code(cpu_state.opqs, dyn);
 
 
  /* Fix up the locations */
  /* Fix up the locations */
  for(loc = dyn->locs; loc < &dyn->locs[immu_state->pagesize / 4]; loc++)
  for(loc = dyn->locs; loc < &dyn->locs[immu_state->pagesize / 4]; loc++)
    *loc += (unsigned int)dyn->host_page;
    *loc += (unsigned int)dyn->host_page;
 
 
  cpu_state.opqs->ops_param[0] += (unsigned int)dyn->host_page;
  cpu_state.opqs->ops_param[0] += (unsigned int)dyn->host_page;
 
 
  /* Search for page-local jumps */
  /* Search for page-local jumps */
  opq = cpu_state.opqs;
  opq = cpu_state.opqs;
  for(j = 0; j < (immu_state->pagesize / 4); opq = opq->next, j++) {
  for(j = 0; j < (immu_state->pagesize / 4); opq = opq->next, j++) {
    if(opq->jump_local != -1)
    if(opq->jump_local != -1)
      opq->ops_param[opq->jump_local] =
      opq->ops_param[opq->jump_local] =
                              (unsigned int)dyn->locs[opq->jump_local_loc >> 2];
                              (unsigned int)dyn->locs[opq->jump_local_loc >> 2];
 
 
    if(opq->not_jump_loc != -1)
    if(opq->not_jump_loc != -1)
      opq->ops_param[opq->not_jump_loc] = (unsigned int)dyn->locs[j + 1];
      opq->ops_param[opq->not_jump_loc] = (unsigned int)dyn->locs[j + 1];
 
 
    /* Store the state of the temporaries into dyn->ts_bound */
    /* Store the state of the temporaries into dyn->ts_bound */
    dyn->ts_bound[j] = 0;
    dyn->ts_bound[j] = 0;
    if(opq->reg_t[0] < 32)
    if(opq->reg_t[0] < 32)
      dyn->ts_bound[j] = opq->reg_t[0];
      dyn->ts_bound[j] = opq->reg_t[0];
    if(opq->reg_t[1] < 32)
    if(opq->reg_t[1] < 32)
      dyn->ts_bound[j] |= opq->reg_t[1] << 5;
      dyn->ts_bound[j] |= opq->reg_t[1] << 5;
    if(opq->reg_t[2] < 32)
    if(opq->reg_t[2] < 32)
      dyn->ts_bound[j] |= opq->reg_t[2] << 10;
      dyn->ts_bound[j] |= opq->reg_t[2] << 10;
 
 
    /* Reset for the next page to be recompiled */
    /* Reset for the next page to be recompiled */
    opq->xref = 0;
    opq->xref = 0;
  }
  }
 
 
  /* Patch the relocations */
  /* Patch the relocations */
  patch_relocs(cpu_state.opqs, dyn->host_page);
  patch_relocs(cpu_state.opqs, dyn->host_page);
 
 
  if(do_stats) {
  if(do_stats) {
    opq = cpu_state.opqs;
    opq = cpu_state.opqs;
    for(j = 0; j < (immu_state->pagesize / 4); j++, opq = opq->next) {
    for(j = 0; j < (immu_state->pagesize / 4); j++, opq = opq->next) {
      dyn->insns[j] = opq->insn;
      dyn->insns[j] = opq->insn;
      dyn->insn_indexs[j] = opq->insn_index;
      dyn->insn_indexs[j] = opq->insn_index;
    }
    }
  }
  }
 
 
  /* FIXME: Fix the issue below in a more elegent way */
  /* FIXME: Fix the issue below in a more elegent way */
  /* Since eval_insn is called to get the instruction, runtime.sim.mem_cycles is
  /* Since eval_insn is called to get the instruction, runtime.sim.mem_cycles is
   * updated but the recompiler expectes it to start a 0, so reset it */
   * updated but the recompiler expectes it to start a 0, so reset it */
  runtime.sim.mem_cycles = 0;
  runtime.sim.mem_cycles = 0;
}
}
 
 
/* Recompiles a delay-slot instruction (opq is the opq of the instruction
/* Recompiles a delay-slot instruction (opq is the opq of the instruction
 * haveing the delay-slot) */
 * haveing the delay-slot) */
static void recompile_delay_insn(struct op_queue *opq)
static void recompile_delay_insn(struct op_queue *opq)
{
{
  struct op_queue delay_opq;
  struct op_queue delay_opq;
  int i;
  int i;
 
 
  /* Setup a fake opq that looks very much like the delay slot instruction */
  /* Setup a fake opq that looks very much like the delay slot instruction */
  memcpy(&delay_opq, opq, sizeof(struct op_queue));
  memcpy(&delay_opq, opq, sizeof(struct op_queue));
  /* `Fix' a couple of bits */
  /* `Fix' a couple of bits */
  for(i = 0; i < NUM_T_REGS; i++)
  for(i = 0; i < NUM_T_REGS; i++)
    delay_opq.tflags[i] = TFLAG_SOURCED;
    delay_opq.tflags[i] = TFLAG_SOURCED;
  delay_opq.insn_index = opq->next->insn_index;
  delay_opq.insn_index = opq->next->insn_index;
  memcpy(delay_opq.param_type, opq->next->param_type, sizeof(delay_opq.param_type));
  memcpy(delay_opq.param_type, opq->next->param_type, sizeof(delay_opq.param_type));
  memcpy(delay_opq.param, opq->next->param, sizeof(delay_opq.param));
  memcpy(delay_opq.param, opq->next->param, sizeof(delay_opq.param));
  delay_opq.param_num = opq->next->param_num;
  delay_opq.param_num = opq->next->param_num;
  delay_opq.insn = opq->next->insn;
  delay_opq.insn = opq->next->insn;
 
 
  delay_opq.xref = 0;
  delay_opq.xref = 0;
  delay_opq.insn_addr = opq->insn_addr + 4;
  delay_opq.insn_addr = opq->insn_addr + 4;
  delay_opq.prev = opq->prev;
  delay_opq.prev = opq->prev;
  delay_opq.next = NULL;
  delay_opq.next = NULL;
 
 
  /* Generate the delay slot instruction */
  /* Generate the delay slot instruction */
  recompile_insn(&delay_opq, 1);
  recompile_insn(&delay_opq, 1);
 
 
  ship_gprs_out_t(&delay_opq);
  ship_gprs_out_t(&delay_opq);
 
 
  opq->num_ops = delay_opq.num_ops;
  opq->num_ops = delay_opq.num_ops;
  opq->ops_len = delay_opq.ops_len;
  opq->ops_len = delay_opq.ops_len;
  opq->ops = delay_opq.ops;
  opq->ops = delay_opq.ops;
  opq->num_ops_param = delay_opq.num_ops_param;
  opq->num_ops_param = delay_opq.num_ops_param;
  opq->ops_param_len = delay_opq.ops_param_len;
  opq->ops_param_len = delay_opq.ops_param_len;
  opq->ops_param = delay_opq.ops_param;
  opq->ops_param = delay_opq.ops_param;
 
 
  for(i = 0; i < NUM_T_REGS; i++)
  for(i = 0; i < NUM_T_REGS; i++)
    opq->reg_t[i] = 32;
    opq->reg_t[i] = 32;
}
}
 
 
/* Returns non-zero if the jump is into this page, 0 otherwise */
/* Returns non-zero if the jump is into this page, 0 otherwise */
static int find_jump_loc(oraddr_t j_ea, struct op_queue *opq)
static int find_jump_loc(oraddr_t j_ea, struct op_queue *opq)
{
{
  int i;
  int i;
 
 
  /* Mark the jump as non page local if the delay slot instruction is on the
  /* Mark the jump as non page local if the delay slot instruction is on the
   * next page to the jump instruction.  This should not be needed */
   * next page to the jump instruction.  This should not be needed */
  if(IADDR_PAGE(j_ea) != IADDR_PAGE(opq->insn_addr))
  if(IADDR_PAGE(j_ea) != IADDR_PAGE(opq->insn_addr))
    /* We can't do anything as the j_ea (as passed to find_jump_loc) is a
    /* We can't do anything as the j_ea (as passed to find_jump_loc) is a
     * VIRTUAL offset and the next physical page may not be the next VIRTUAL
     * VIRTUAL offset and the next physical page may not be the next VIRTUAL
     * page */
     * page */
    return 0;
    return 0;
 
 
  /* The jump is into the page currently undergoing dynamic recompilation */
  /* The jump is into the page currently undergoing dynamic recompilation */
 
 
  /* If we haven't got to the location of the jump, everything is ok */
  /* If we haven't got to the location of the jump, everything is ok */
  if(j_ea > opq->insn_addr) {
  if(j_ea > opq->insn_addr) {
    /* Find the corissponding opq and mark it as cross referenced */
    /* Find the corissponding opq and mark it as cross referenced */
    for(i = (j_ea - opq->insn_addr) / 4; i; i--)
    for(i = (j_ea - opq->insn_addr) / 4; i; i--)
      opq = opq->next;
      opq = opq->next;
    opq->xref = 1;
    opq->xref = 1;
    return 1;
    return 1;
  }
  }
 
 
  /* Insert temporary -> register code before the jump ea and register ->
  /* Insert temporary -> register code before the jump ea and register ->
   * temporary at the x-ref address */
   * temporary at the x-ref address */
  for(i = (opq->insn_addr - j_ea) / 4; i; i--)
  for(i = (opq->insn_addr - j_ea) / 4; i; i--)
    opq = opq->prev;
    opq = opq->prev;
 
 
  if(!opq->prev)
  if(!opq->prev)
    /* We're at the begining of a page, no need to do anything */
    /* We're at the begining of a page, no need to do anything */
    return 1;
    return 1;
 
 
  /* Found location, insert code */
  /* Found location, insert code */
 
 
  ship_gprs_out_t(opq->prev);
  ship_gprs_out_t(opq->prev);
 
 
  for(i = 0; i < NUM_T_REGS; i++) {
  for(i = 0; i < NUM_T_REGS; i++) {
    if(opq->prev->reg_t[i] < 32)
    if(opq->prev->reg_t[i] < 32)
      /* FIXME: Ship temporaries in the begining of the opq that needs it */
      /* FIXME: Ship temporaries in the begining of the opq that needs it */
      gen_op_move_t_gpr[i][opq->prev->reg_t[i]](opq, 0);
      gen_op_move_t_gpr[i][opq->prev->reg_t[i]](opq, 0);
  }
  }
 
 
  opq->xref = 1;
  opq->xref = 1;
 
 
  return 1;
  return 1;
}
}
 
 
static void gen_j_imm(struct op_queue *opq, oraddr_t off)
static void gen_j_imm(struct op_queue *opq, oraddr_t off)
{
{
  int jump_local;
  int jump_local;
 
 
  off <<= 2;
  off <<= 2;
 
 
  if(IADDR_PAGE(opq->insn_addr) != IADDR_PAGE(opq->insn_addr + 4)) {
  if(IADDR_PAGE(opq->insn_addr) != IADDR_PAGE(opq->insn_addr + 4)) {
    gen_op_set_pc_delay_imm(opq, 1, off);
    gen_op_set_pc_delay_imm(opq, 1, off);
    gen_op_do_sched(opq, 1);
    gen_op_do_sched(opq, 1);
    return;
    return;
  }
  }
 
 
  jump_local = find_jump_loc(opq->insn_addr + off, opq);
  jump_local = find_jump_loc(opq->insn_addr + off, opq);
 
 
  gen_op_set_delay_insn(opq, 1);
  gen_op_set_delay_insn(opq, 1);
  gen_op_do_sched(opq, 1);
  gen_op_do_sched(opq, 1);
 
 
  recompile_delay_insn(opq);
  recompile_delay_insn(opq);
 
 
  gen_op_add_pc(opq, 1, (orreg_t)off - 8);
  gen_op_add_pc(opq, 1, (orreg_t)off - 8);
  gen_op_clear_delay_insn(opq, 1);
  gen_op_clear_delay_insn(opq, 1);
  gen_op_do_sched_delay(opq, 1);
  gen_op_do_sched_delay(opq, 1);
 
 
  if(jump_local) {
  if(jump_local) {
    gen_op_jmp_imm(opq, 1, 0);
    gen_op_jmp_imm(opq, 1, 0);
    opq->jump_local = opq->num_ops_param - 1;
    opq->jump_local = opq->num_ops_param - 1;
    opq->jump_local_loc = (opq->insn_addr + (orreg_t)off) & immu_state->page_offset_mask;
    opq->jump_local_loc = (opq->insn_addr + (orreg_t)off) & immu_state->page_offset_mask;
  } else
  } else
    gen_op_do_jump(opq, 1);
    gen_op_do_jump(opq, 1);
}
}
 
 
static const generic_gen_op set_pc_delay_gpr[32] = {
static const generic_gen_op set_pc_delay_gpr[32] = {
 NULL,
 NULL,
 gen_op_move_gpr1_pc_delay,
 gen_op_move_gpr1_pc_delay,
 gen_op_move_gpr2_pc_delay,
 gen_op_move_gpr2_pc_delay,
 gen_op_move_gpr3_pc_delay,
 gen_op_move_gpr3_pc_delay,
 gen_op_move_gpr4_pc_delay,
 gen_op_move_gpr4_pc_delay,
 gen_op_move_gpr5_pc_delay,
 gen_op_move_gpr5_pc_delay,
 gen_op_move_gpr6_pc_delay,
 gen_op_move_gpr6_pc_delay,
 gen_op_move_gpr7_pc_delay,
 gen_op_move_gpr7_pc_delay,
 gen_op_move_gpr8_pc_delay,
 gen_op_move_gpr8_pc_delay,
 gen_op_move_gpr9_pc_delay,
 gen_op_move_gpr9_pc_delay,
 gen_op_move_gpr10_pc_delay,
 gen_op_move_gpr10_pc_delay,
 gen_op_move_gpr11_pc_delay,
 gen_op_move_gpr11_pc_delay,
 gen_op_move_gpr12_pc_delay,
 gen_op_move_gpr12_pc_delay,
 gen_op_move_gpr13_pc_delay,
 gen_op_move_gpr13_pc_delay,
 gen_op_move_gpr14_pc_delay,
 gen_op_move_gpr14_pc_delay,
 gen_op_move_gpr15_pc_delay,
 gen_op_move_gpr15_pc_delay,
 gen_op_move_gpr16_pc_delay,
 gen_op_move_gpr16_pc_delay,
 gen_op_move_gpr17_pc_delay,
 gen_op_move_gpr17_pc_delay,
 gen_op_move_gpr18_pc_delay,
 gen_op_move_gpr18_pc_delay,
 gen_op_move_gpr19_pc_delay,
 gen_op_move_gpr19_pc_delay,
 gen_op_move_gpr20_pc_delay,
 gen_op_move_gpr20_pc_delay,
 gen_op_move_gpr21_pc_delay,
 gen_op_move_gpr21_pc_delay,
 gen_op_move_gpr22_pc_delay,
 gen_op_move_gpr22_pc_delay,
 gen_op_move_gpr23_pc_delay,
 gen_op_move_gpr23_pc_delay,
 gen_op_move_gpr24_pc_delay,
 gen_op_move_gpr24_pc_delay,
 gen_op_move_gpr25_pc_delay,
 gen_op_move_gpr25_pc_delay,
 gen_op_move_gpr26_pc_delay,
 gen_op_move_gpr26_pc_delay,
 gen_op_move_gpr27_pc_delay,
 gen_op_move_gpr27_pc_delay,
 gen_op_move_gpr28_pc_delay,
 gen_op_move_gpr28_pc_delay,
 gen_op_move_gpr29_pc_delay,
 gen_op_move_gpr29_pc_delay,
 gen_op_move_gpr30_pc_delay,
 gen_op_move_gpr30_pc_delay,
 gen_op_move_gpr31_pc_delay };
 gen_op_move_gpr31_pc_delay };
 
 
static void gen_j_reg(struct op_queue *opq, unsigned int gpr)
static void gen_j_reg(struct op_queue *opq, unsigned int gpr)
{
{
  int i;
  int i;
 
 
  /* Ship the jump-to register out (if it exists).  It requires special
  /* Ship the jump-to register out (if it exists).  It requires special
   * handleing */
   * handleing */
  for(i = 0; i < NUM_T_REGS; i++) {
  for(i = 0; i < NUM_T_REGS; i++) {
    if(opq->reg_t[i] == opq->param[0])
    if(opq->reg_t[i] == opq->param[0])
      /* Ship temporary out in the last opq that used it */
      /* Ship temporary out in the last opq that used it */
      ship_t_out(opq, i);
      ship_t_out(opq, i);
  }
  }
 
 
  if(do_stats)
  if(do_stats)
    gen_op_analysis(opq, 1);
    gen_op_analysis(opq, 1);
 
 
  if(!gpr)
  if(!gpr)
    gen_op_clear_pc_delay(opq, 1);
    gen_op_clear_pc_delay(opq, 1);
  else
  else
    set_pc_delay_gpr[gpr](opq, 1);
    set_pc_delay_gpr[gpr](opq, 1);
 
 
  gen_op_do_sched(opq, 1);
  gen_op_do_sched(opq, 1);
 
 
  if(IADDR_PAGE(opq->insn_addr) != IADDR_PAGE(opq->insn_addr + 4))
  if(IADDR_PAGE(opq->insn_addr) != IADDR_PAGE(opq->insn_addr + 4))
    return;
    return;
 
 
  recompile_delay_insn(opq);
  recompile_delay_insn(opq);
 
 
  gen_op_set_pc_pc_delay(opq, 1);
  gen_op_set_pc_pc_delay(opq, 1);
  gen_op_clear_delay_insn(opq, 1);
  gen_op_clear_delay_insn(opq, 1);
  gen_op_do_sched_delay(opq, 1);
  gen_op_do_sched_delay(opq, 1);
 
 
  gen_op_do_jump_delay(opq, 1);
  gen_op_do_jump_delay(opq, 1);
  gen_op_do_jump(opq, 1);
  gen_op_do_jump(opq, 1);
}
}
 
 
/*------------------------------[ Operation generation for an instruction ]---*/
/*------------------------------[ Operation generation for an instruction ]---*/
/* FIXME: Flag setting is not done in any instruction */
/* FIXME: Flag setting is not done in any instruction */
/* FIXME: Since r0 is not moved into a temporary, check all arguments below! */
/* FIXME: Since r0 is not moved into a temporary, check all arguments below! */
 
 
DEF_1T_OP(generic_gen_op, clear_t, gen_op_clear);
DEF_1T_OP(generic_gen_op, clear_t, gen_op_clear);
DEF_2T_OP_NEQ(generic_gen_op, move_t_t, gen_op_move);
DEF_2T_OP_NEQ(generic_gen_op, move_t_t, gen_op_move);
DEF_1T_OP(imm_gen_op, mov_t_imm, gen_op_imm);
DEF_1T_OP(imm_gen_op, mov_t_imm, gen_op_imm);
 
 
DEF_2T_OP(imm_gen_op, l_add_imm_t_table, gen_op_add_imm);
DEF_2T_OP(imm_gen_op, l_add_imm_t_table, gen_op_add_imm);
DEF_3T_OP(generic_gen_op, l_add_t_table, gen_op_add);
DEF_3T_OP(generic_gen_op, l_add_t_table, gen_op_add);
 
 
void gen_l_add(struct op_queue *opq, int param_t[3], int delay_slot)
void gen_l_add(struct op_queue *opq, int param_t[3], int delay_slot)
{
{
  if(!opq->param[0])
  if(!opq->param[0])
    /* Screw this, the operation shall do nothing */
    /* Screw this, the operation shall do nothing */
    return;
    return;
 
 
  if(!opq->param[1] && !opq->param[2]) {
  if(!opq->param[1] && !opq->param[2]) {
    /* Just clear param_t[0] */
    /* Just clear param_t[0] */
    clear_t[param_t[0]](opq, 1);
    clear_t[param_t[0]](opq, 1);
    return;
    return;
  }
  }
 
 
  if(!opq->param[2]) {
  if(!opq->param[2]) {
    if(opq->param[0] != opq->param[1])
    if(opq->param[0] != opq->param[1])
      /* This just moves a register */
      /* This just moves a register */
      move_t_t[param_t[0]][param_t[1]](opq, 1);
      move_t_t[param_t[0]][param_t[1]](opq, 1);
    return;
    return;
  }
  }
 
 
  if(!opq->param[1]) {
  if(!opq->param[1]) {
    /* Check if we are moveing an immediate */
    /* Check if we are moveing an immediate */
    if(param_t[2] == T_NONE) {
    if(param_t[2] == T_NONE) {
      /* Yep, an immediate */
      /* Yep, an immediate */
      mov_t_imm[param_t[0]](opq, 1, opq->param[2]);
      mov_t_imm[param_t[0]](opq, 1, opq->param[2]);
      return;
      return;
    }
    }
    /* Just another move */
    /* Just another move */
    if(opq->param[0] != opq->param[2])
    if(opq->param[0] != opq->param[2])
      move_t_t[param_t[0]][param_t[2]](opq, 1);
      move_t_t[param_t[0]][param_t[2]](opq, 1);
    return;
    return;
  }
  }
 
 
  /* Ok, This _IS_ an add... */
  /* Ok, This _IS_ an add... */
  if(param_t[2] == T_NONE)
  if(param_t[2] == T_NONE)
    /* immediate */
    /* immediate */
    l_add_imm_t_table[param_t[0]][param_t[1]](opq, 1, opq->param[2]);
    l_add_imm_t_table[param_t[0]][param_t[1]](opq, 1, opq->param[2]);
  else
  else
    l_add_t_table[param_t[0]][param_t[1]][param_t[2]](opq, 1);
    l_add_t_table[param_t[0]][param_t[1]][param_t[2]](opq, 1);
}
}
 
 
DEF_3T_OP(generic_gen_op, l_addc_t_table, gen_op_addc);
DEF_3T_OP(generic_gen_op, l_addc_t_table, gen_op_addc);
 
 
void gen_l_addc(struct op_queue *opq, int param_t[3], int delay_slot)
void gen_l_addc(struct op_queue *opq, int param_t[3], int delay_slot)
{
{
  if(!opq->param[0])
  if(!opq->param[0])
    /* Screw this, the operation shall do nothing */
    /* Screw this, the operation shall do nothing */
    return;
    return;
 
 
  /* FIXME: More optimisations !! (...and immediate...) */
  /* FIXME: More optimisations !! (...and immediate...) */
  l_addc_t_table[param_t[0]][param_t[1]][param_t[2]](opq, 1);
  l_addc_t_table[param_t[0]][param_t[1]][param_t[2]](opq, 1);
}
}
 
 
DEF_2T_OP(imm_gen_op, l_and_imm_t_table, gen_op_and_imm);
DEF_2T_OP(imm_gen_op, l_and_imm_t_table, gen_op_and_imm);
DEF_3T_OP_NEQ(generic_gen_op, l_and_t_table, gen_op_and);
DEF_3T_OP_NEQ(generic_gen_op, l_and_t_table, gen_op_and);
 
 
void gen_l_and(struct op_queue *opq, int param_t[3], int delay_slot)
void gen_l_and(struct op_queue *opq, int param_t[3], int delay_slot)
{
{
  if(!opq->param[0])
  if(!opq->param[0])
    /* Screw this, the operation shall do nothing */
    /* Screw this, the operation shall do nothing */
    return;
    return;
 
 
  if(!opq->param[1] || !opq->param[2]) {
  if(!opq->param[1] || !opq->param[2]) {
    /* Just clear param_t[0] */
    /* Just clear param_t[0] */
    clear_t[param_t[0]](opq, 1);
    clear_t[param_t[0]](opq, 1);
    return;
    return;
  }
  }
 
 
  if((opq->param[0] == opq->param[1]) &&
  if((opq->param[0] == opq->param[1]) &&
     (opq->param[0] == opq->param[2]) &&
     (opq->param[0] == opq->param[2]) &&
     (param_t[2] != T_NONE))
     (param_t[2] != T_NONE))
    return;
    return;
 
 
  if(param_t[2] == T_NONE)
  if(param_t[2] == T_NONE)
    l_and_imm_t_table[param_t[0]][param_t[1]](opq, 1, opq->param[2]);
    l_and_imm_t_table[param_t[0]][param_t[1]](opq, 1, opq->param[2]);
  else
  else
    l_and_t_table[param_t[0]][param_t[1]][param_t[2]](opq, 1);
    l_and_t_table[param_t[0]][param_t[1]][param_t[2]](opq, 1);
}
}
 
 
void gen_l_bf(struct op_queue *opq, int param_t[3], int delay_slot)
void gen_l_bf(struct op_queue *opq, int param_t[3], int delay_slot)
{
{
  if(do_stats)
  if(do_stats)
    /* All gprs are current since this insn doesn't touch any reg */
    /* All gprs are current since this insn doesn't touch any reg */
    gen_op_analysis(opq, 1);
    gen_op_analysis(opq, 1);
 
 
  /* The temporaries are expected to be shiped out after the execution of the
  /* The temporaries are expected to be shiped out after the execution of the
   * branch instruction wether it branched or not */
   * branch instruction wether it branched or not */
  ship_gprs_out_t(opq->prev);
  ship_gprs_out_t(opq->prev);
 
 
  if(IADDR_PAGE(opq->insn_addr) != IADDR_PAGE(opq->insn_addr + 4)) {
  if(IADDR_PAGE(opq->insn_addr) != IADDR_PAGE(opq->insn_addr + 4)) {
    gen_op_check_flag_delay(opq, 1, opq->param[0] << 2);
    gen_op_check_flag_delay(opq, 1, opq->param[0] << 2);
    gen_op_do_sched(opq, 1);
    gen_op_do_sched(opq, 1);
    opq->not_jump_loc = -1;
    opq->not_jump_loc = -1;
    return;
    return;
  }
  }
 
 
  gen_op_check_flag(opq, 1, 0);
  gen_op_check_flag(opq, 1, 0);
  opq->not_jump_loc = opq->num_ops_param - 1;
  opq->not_jump_loc = opq->num_ops_param - 1;
 
 
  gen_j_imm(opq, opq->param[0]);
  gen_j_imm(opq, opq->param[0]);
}
}
 
 
void gen_l_bnf(struct op_queue *opq, int param_t[3], int delay_slot)
void gen_l_bnf(struct op_queue *opq, int param_t[3], int delay_slot)
{
{
  if(do_stats)
  if(do_stats)
    /* All gprs are current since this insn doesn't touch any reg */
    /* All gprs are current since this insn doesn't touch any reg */
    gen_op_analysis(opq, 1);
    gen_op_analysis(opq, 1);
 
 
  /* The temporaries are expected to be shiped out after the execution of the
  /* The temporaries are expected to be shiped out after the execution of the
   * branch instruction wether it branched or not */
   * branch instruction wether it branched or not */
  ship_gprs_out_t(opq->prev);
  ship_gprs_out_t(opq->prev);
 
 
  if(IADDR_PAGE(opq->insn_addr) != IADDR_PAGE(opq->insn_addr + 4)) {
  if(IADDR_PAGE(opq->insn_addr) != IADDR_PAGE(opq->insn_addr + 4)) {
    gen_op_check_not_flag_delay(opq, 1, opq->param[0] << 2);
    gen_op_check_not_flag_delay(opq, 1, opq->param[0] << 2);
    gen_op_do_sched(opq, 1);
    gen_op_do_sched(opq, 1);
    opq->not_jump_loc = -1;
    opq->not_jump_loc = -1;
    return;
    return;
  }
  }
 
 
  gen_op_check_not_flag(opq, 1, 0);
  gen_op_check_not_flag(opq, 1, 0);
  opq->not_jump_loc = opq->num_ops_param - 1;
  opq->not_jump_loc = opq->num_ops_param - 1;
 
 
  gen_j_imm(opq, opq->param[0]);
  gen_j_imm(opq, opq->param[0]);
}
}
 
 
DEF_3T_OP_NEQ(generic_gen_op, l_cmov_t_table, gen_op_cmov);
DEF_3T_OP_NEQ(generic_gen_op, l_cmov_t_table, gen_op_cmov);
 
 
/* FIXME: Check if either opperand 1 or 2 is r0 */
/* FIXME: Check if either opperand 1 or 2 is r0 */
void gen_l_cmov(struct op_queue *opq, int param_t[3], int delay_slot)
void gen_l_cmov(struct op_queue *opq, int param_t[3], int delay_slot)
{
{
  if(!opq->param[0])
  if(!opq->param[0])
    return;
    return;
 
 
  if(!opq->param[1] && !opq->param[2]) {
  if(!opq->param[1] && !opq->param[2]) {
    clear_t[param_t[0]](opq, 1);
    clear_t[param_t[0]](opq, 1);
    return;
    return;
  }
  }
 
 
  if((opq->param[1] == opq->param[2]) && (opq->param[0] == opq->param[1]))
  if((opq->param[1] == opq->param[2]) && (opq->param[0] == opq->param[1]))
    return;
    return;
 
 
  if(opq->param[1] == opq->param[2]) {
  if(opq->param[1] == opq->param[2]) {
    move_t_t[param_t[0]][param_t[1]](opq, 1);
    move_t_t[param_t[0]][param_t[1]](opq, 1);
    return;
    return;
  }
  }
 
 
  l_cmov_t_table[param_t[0]][param_t[1]][param_t[2]](opq, 1);
  l_cmov_t_table[param_t[0]][param_t[1]][param_t[2]](opq, 1);
}
}
 
 
void gen_l_cust1(struct op_queue *opq, int param_t[3], int delay_slot)
void gen_l_cust1(struct op_queue *opq, int param_t[3], int delay_slot)
{
{
}
}
 
 
void gen_l_cust2(struct op_queue *opq, int param_t[3], int delay_slot)
void gen_l_cust2(struct op_queue *opq, int param_t[3], int delay_slot)
{
{
}
}
 
 
void gen_l_cust3(struct op_queue *opq, int param_t[3], int delay_slot)
void gen_l_cust3(struct op_queue *opq, int param_t[3], int delay_slot)
{
{
}
}
 
 
void gen_l_cust4(struct op_queue *opq, int param_t[3], int delay_slot)
void gen_l_cust4(struct op_queue *opq, int param_t[3], int delay_slot)
{
{
}
}
 
 
void gen_l_cust5(struct op_queue *opq, int param_t[3], int delay_slot)
void gen_l_cust5(struct op_queue *opq, int param_t[3], int delay_slot)
{
{
}
}
 
 
void gen_l_cust6(struct op_queue *opq, int param_t[3], int delay_slot)
void gen_l_cust6(struct op_queue *opq, int param_t[3], int delay_slot)
{
{
}
}
 
 
void gen_l_cust7(struct op_queue *opq, int param_t[3], int delay_slot)
void gen_l_cust7(struct op_queue *opq, int param_t[3], int delay_slot)
{
{
}
}
 
 
void gen_l_cust8(struct op_queue *opq, int param_t[3], int delay_slot)
void gen_l_cust8(struct op_queue *opq, int param_t[3], int delay_slot)
{
{
}
}
 
 
/* FIXME: All registers need to be stored before the div instructions as they
/* FIXME: All registers need to be stored before the div instructions as they
 * have the potenticial to cause an exception */
 * have the potenticial to cause an exception */
 
 
DEF_1T_OP(generic_gen_op, check_null_excpt, gen_op_check_null_except);
DEF_1T_OP(generic_gen_op, check_null_excpt, gen_op_check_null_except);
DEF_1T_OP(generic_gen_op, check_null_excpt_delay, gen_op_check_null_except_delay);
DEF_1T_OP(generic_gen_op, check_null_excpt_delay, gen_op_check_null_except_delay);
DEF_3T_OP(generic_gen_op, l_div_t_table, gen_op_div);
DEF_3T_OP(generic_gen_op, l_div_t_table, gen_op_div);
 
 
void gen_l_div(struct op_queue *opq, int param_t[3], int delay_slot)
void gen_l_div(struct op_queue *opq, int param_t[3], int delay_slot)
{
{
  if(!opq->param[2]) {
  if(!opq->param[2]) {
    /* There is no option.  This _will_ cause an illeagal exception */
    /* There is no option.  This _will_ cause an illeagal exception */
    if(!delay_slot) {
    if(!delay_slot) {
      gen_op_illegal(opq, 1);
      gen_op_illegal(opq, 1);
      gen_op_do_jump(opq, 1);
      gen_op_do_jump(opq, 1);
    } else {
    } else {
      gen_op_illegal(opq, 1);
      gen_op_illegal(opq, 1);
      gen_op_do_jump(opq, 1);
      gen_op_do_jump(opq, 1);
    }
    }
    return;
    return;
  }
  }
 
 
  if(!delay_slot)
  if(!delay_slot)
    check_null_excpt[param_t[2]](opq, 1);
    check_null_excpt[param_t[2]](opq, 1);
  else
  else
    check_null_excpt_delay[param_t[2]](opq, 1);
    check_null_excpt_delay[param_t[2]](opq, 1);
 
 
  if(!opq->param[0])
  if(!opq->param[0])
    return;
    return;
 
 
  if(!opq->param[1]) {
  if(!opq->param[1]) {
    /* Clear param_t[0] */
    /* Clear param_t[0] */
    clear_t[param_t[0]](opq, 1);
    clear_t[param_t[0]](opq, 1);
    return;
    return;
  }
  }
 
 
  l_div_t_table[param_t[0]][param_t[1]][param_t[2]](opq, 1);
  l_div_t_table[param_t[0]][param_t[1]][param_t[2]](opq, 1);
}
}
 
 
DEF_3T_OP(generic_gen_op, l_divu_t_table, gen_op_divu);
DEF_3T_OP(generic_gen_op, l_divu_t_table, gen_op_divu);
 
 
void gen_l_divu(struct op_queue *opq, int param_t[3], int delay_slot)
void gen_l_divu(struct op_queue *opq, int param_t[3], int delay_slot)
{
{
  if(!opq->param[2]) {
  if(!opq->param[2]) {
    /* There is no option.  This _will_ cause an illeagal exception */
    /* There is no option.  This _will_ cause an illeagal exception */
    if(!delay_slot) {
    if(!delay_slot) {
      gen_op_illegal(opq, 1);
      gen_op_illegal(opq, 1);
      gen_op_do_jump(opq, 1);
      gen_op_do_jump(opq, 1);
    } else {
    } else {
      gen_op_illegal(opq, 1);
      gen_op_illegal(opq, 1);
      gen_op_do_jump(opq, 1);
      gen_op_do_jump(opq, 1);
    }
    }
    return;
    return;
  }
  }
 
 
  if(!delay_slot)
  if(!delay_slot)
    check_null_excpt[param_t[2]](opq, 1);
    check_null_excpt[param_t[2]](opq, 1);
  else
  else
    check_null_excpt_delay[param_t[2]](opq, 1);
    check_null_excpt_delay[param_t[2]](opq, 1);
 
 
  if(!opq->param[0])
  if(!opq->param[0])
    return;
    return;
 
 
  if(!opq->param[1]) {
  if(!opq->param[1]) {
    /* Clear param_t[0] */
    /* Clear param_t[0] */
    clear_t[param_t[0]](opq, 1);
    clear_t[param_t[0]](opq, 1);
    return;
    return;
  }
  }
 
 
  l_divu_t_table[param_t[0]][param_t[1]][param_t[2]](opq, 1);
  l_divu_t_table[param_t[0]][param_t[1]][param_t[2]](opq, 1);
}
}
 
 
DEF_2T_OP(generic_gen_op, l_extbs_t_table, gen_op_extbs);
DEF_2T_OP(generic_gen_op, l_extbs_t_table, gen_op_extbs);
 
 
void gen_l_extbs(struct op_queue *opq, int param_t[3], int delay_slot)
void gen_l_extbs(struct op_queue *opq, int param_t[3], int delay_slot)
{
{
  if(!opq->param[0])
  if(!opq->param[0])
    return;
    return;
 
 
  if(!opq->param[1]) {
  if(!opq->param[1]) {
    clear_t[param_t[0]](opq, 1);
    clear_t[param_t[0]](opq, 1);
    return;
    return;
  }
  }
 
 
  l_extbs_t_table[param_t[0]][param_t[1]](opq, 1);
  l_extbs_t_table[param_t[0]][param_t[1]](opq, 1);
}
}
 
 
DEF_2T_OP(generic_gen_op, l_extbz_t_table, gen_op_extbz);
DEF_2T_OP(generic_gen_op, l_extbz_t_table, gen_op_extbz);
 
 
void gen_l_extbz(struct op_queue *opq, int param_t[3], int delay_slot)
void gen_l_extbz(struct op_queue *opq, int param_t[3], int delay_slot)
{
{
  if(!opq->param[0])
  if(!opq->param[0])
    return;
    return;
 
 
  if(!opq->param[1]) {
  if(!opq->param[1]) {
    clear_t[param_t[0]](opq, 1);
    clear_t[param_t[0]](opq, 1);
    return;
    return;
  }
  }
 
 
  l_extbz_t_table[param_t[0]][param_t[1]](opq, 1);
  l_extbz_t_table[param_t[0]][param_t[1]](opq, 1);
}
}
 
 
DEF_2T_OP(generic_gen_op, l_exths_t_table, gen_op_exths);
DEF_2T_OP(generic_gen_op, l_exths_t_table, gen_op_exths);
 
 
void gen_l_exths(struct op_queue *opq, int param_t[3], int delay_slot)
void gen_l_exths(struct op_queue *opq, int param_t[3], int delay_slot)
{
{
  if(!opq->param[0])
  if(!opq->param[0])
    return;
    return;
 
 
  if(!opq->param[1]) {
  if(!opq->param[1]) {
    clear_t[param_t[0]](opq, 1);
    clear_t[param_t[0]](opq, 1);
    return;
    return;
  }
  }
 
 
  l_exths_t_table[param_t[0]][param_t[1]](opq, 1);
  l_exths_t_table[param_t[0]][param_t[1]](opq, 1);
}
}
 
 
DEF_2T_OP(generic_gen_op, l_exthz_t_table, gen_op_exthz);
DEF_2T_OP(generic_gen_op, l_exthz_t_table, gen_op_exthz);
 
 
void gen_l_exthz(struct op_queue *opq, int param_t[3], int delay_slot)
void gen_l_exthz(struct op_queue *opq, int param_t[3], int delay_slot)
{
{
  if(!opq->param[0])
  if(!opq->param[0])
    return;
    return;
 
 
  if(!opq->param[1]) {
  if(!opq->param[1]) {
    clear_t[param_t[0]](opq, 1);
    clear_t[param_t[0]](opq, 1);
    return;
    return;
  }
  }
 
 
  l_exthz_t_table[param_t[0]][param_t[1]](opq, 1);
  l_exthz_t_table[param_t[0]][param_t[1]](opq, 1);
}
}
 
 
void gen_l_extws(struct op_queue *opq, int param_t[3], int delay_slot)
void gen_l_extws(struct op_queue *opq, int param_t[3], int delay_slot)
{
{
  if(!opq->param[0])
  if(!opq->param[0])
    return;
    return;
 
 
  if(!opq->param[1]) {
  if(!opq->param[1]) {
    clear_t[param_t[0]](opq, 1);
    clear_t[param_t[0]](opq, 1);
    return;
    return;
  }
  }
 
 
  if(opq->param[0] == opq->param[1])
  if(opq->param[0] == opq->param[1])
    return;
    return;
 
 
  /* In the 32-bit architechture this instruction reduces to a move */
  /* In the 32-bit architechture this instruction reduces to a move */
  move_t_t[param_t[0]][param_t[1]](opq, 1);
  move_t_t[param_t[0]][param_t[1]](opq, 1);
}
}
 
 
void gen_l_extwz(struct op_queue *opq, int param_t[3], int delay_slot)
void gen_l_extwz(struct op_queue *opq, int param_t[3], int delay_slot)
{
{
  if(!opq->param[0])
  if(!opq->param[0])
    return;
    return;
 
 
  if(!opq->param[1]) {
  if(!opq->param[1]) {
    clear_t[param_t[0]](opq, 1);
    clear_t[param_t[0]](opq, 1);
    return;
    return;
  }
  }
 
 
  if(opq->param[0] == opq->param[1])
  if(opq->param[0] == opq->param[1])
    return;
    return;
 
 
  /* In the 32-bit architechture this instruction reduces to a move */
  /* In the 32-bit architechture this instruction reduces to a move */
  move_t_t[param_t[0]][param_t[1]](opq, 1);
  move_t_t[param_t[0]][param_t[1]](opq, 1);
}
}
 
 
DEF_2T_OP(generic_gen_op, l_ff1_t_table, gen_op_ff1);
DEF_2T_OP(generic_gen_op, l_ff1_t_table, gen_op_ff1);
 
 
void gen_l_ff1(struct op_queue *opq, int param_t[3], int delay_slot)
void gen_l_ff1(struct op_queue *opq, int param_t[3], int delay_slot)
{
{
  if(!opq->param[0])
  if(!opq->param[0])
    return;
    return;
 
 
  if(!opq->param[1]) {
  if(!opq->param[1]) {
    clear_t[param_t[0]](opq, 1);
    clear_t[param_t[0]](opq, 1);
    return;
    return;
  }
  }
 
 
  l_ff1_t_table[param_t[0]][param_t[1]](opq, 1);
  l_ff1_t_table[param_t[0]][param_t[1]](opq, 1);
}
}
 
 
void gen_l_j(struct op_queue *opq, int param_t[3], int delay_slot)
void gen_l_j(struct op_queue *opq, int param_t[3], int delay_slot)
{
{
  if(do_stats)
  if(do_stats)
    /* All gprs are current since this insn doesn't touch any reg */
    /* All gprs are current since this insn doesn't touch any reg */
    gen_op_analysis(opq, 1);
    gen_op_analysis(opq, 1);
 
 
  gen_j_imm(opq, opq->param[0]);
  gen_j_imm(opq, opq->param[0]);
}
}
 
 
void gen_l_jal(struct op_queue *opq, int param_t[3], int delay_slot)
void gen_l_jal(struct op_queue *opq, int param_t[3], int delay_slot)
{
{
  int i;
  int i;
 
 
  /* In the case of a l.jal instruction, make sure that LINK_REGNO is not in
  /* In the case of a l.jal instruction, make sure that LINK_REGNO is not in
   * a temporary.  The problem is that the l.jal(r) instruction stores the
   * a temporary.  The problem is that the l.jal(r) instruction stores the
   * `return address' in LINK_REGNO.  The temporaries are shiped out only
   * `return address' in LINK_REGNO.  The temporaries are shiped out only
   * after the delay slot instruction has executed and so it overwrittes the
   * after the delay slot instruction has executed and so it overwrittes the
   * `return address'. */
   * `return address'. */
  for(i = 0; i < NUM_T_REGS; i++) {
  for(i = 0; i < NUM_T_REGS; i++) {
    if(opq->reg_t[i] == LINK_REGNO) {
    if(opq->reg_t[i] == LINK_REGNO) {
      /* Don't bother storeing the register, it is going to get clobered in this
      /* Don't bother storeing the register, it is going to get clobered in this
       * instruction anyway */
       * instruction anyway */
      opq->reg_t[i] = 32;
      opq->reg_t[i] = 32;
      break;
      break;
    }
    }
  }
  }
 
 
  /* Store the return address */
  /* Store the return address */
  gen_op_store_link_addr_gpr(opq, 1);
  gen_op_store_link_addr_gpr(opq, 1);
 
 
  if(do_stats)
  if(do_stats)
    /* All gprs are current since this insn doesn't touch any reg */
    /* All gprs are current since this insn doesn't touch any reg */
    gen_op_analysis(opq, 1);
    gen_op_analysis(opq, 1);
 
 
  gen_j_imm(opq, opq->param[0]);
  gen_j_imm(opq, opq->param[0]);
}
}
 
 
void gen_l_jr(struct op_queue *opq, int param_t[3], int delay_slot)
void gen_l_jr(struct op_queue *opq, int param_t[3], int delay_slot)
{
{
  gen_j_reg(opq, opq->param[0]);
  gen_j_reg(opq, opq->param[0]);
}
}
 
 
void gen_l_jalr(struct op_queue *opq, int param_t[3], int delay_slot)
void gen_l_jalr(struct op_queue *opq, int param_t[3], int delay_slot)
{
{
  int i;
  int i;
 
 
  /* In the case of a l.jal instruction, make sure that LINK_REGNO is not in
  /* In the case of a l.jal instruction, make sure that LINK_REGNO is not in
   * a temporary.  The problem is that the l.jal(r) instruction stores the
   * a temporary.  The problem is that the l.jal(r) instruction stores the
   * `return address' in LINK_REGNO.  The temporaries are shiped out only
   * `return address' in LINK_REGNO.  The temporaries are shiped out only
   * after the delay slot instruction has executed and so it overwrittes the
   * after the delay slot instruction has executed and so it overwrittes the
   * `return address'. */
   * `return address'. */
  for(i = 0; i < NUM_T_REGS; i++) {
  for(i = 0; i < NUM_T_REGS; i++) {
    if(opq->reg_t[i] == LINK_REGNO) {
    if(opq->reg_t[i] == LINK_REGNO) {
      /* Don't bother storeing the register, it is going to get clobered in this
      /* Don't bother storeing the register, it is going to get clobered in this
       * instruction anyway */
       * instruction anyway */
      opq->reg_t[i] = 32;
      opq->reg_t[i] = 32;
      break;
      break;
    }
    }
  }
  }
 
 
  /* Store the return address */
  /* Store the return address */
  gen_op_store_link_addr_gpr(opq, 1);
  gen_op_store_link_addr_gpr(opq, 1);
 
 
  gen_j_reg(opq, opq->param[0]);
  gen_j_reg(opq, opq->param[0]);
}
}
 
 
/* FIXME: Optimise all load instruction when the disposition == 0 */
/* FIXME: Optimise all load instruction when the disposition == 0 */
 
 
DEF_1T_OP(imm_gen_op, l_lbs_imm_t_table, gen_op_lbs_imm);
DEF_1T_OP(imm_gen_op, l_lbs_imm_t_table, gen_op_lbs_imm);
DEF_2T_OP(imm_gen_op, l_lbs_t_table, gen_op_lbs);
DEF_2T_OP(imm_gen_op, l_lbs_t_table, gen_op_lbs);
 
 
void gen_l_lbs(struct op_queue *opq, int param_t[3], int delay_slot)
void gen_l_lbs(struct op_queue *opq, int param_t[3], int delay_slot)
{
{
  if(!opq->param[0]) {
  if(!opq->param[0]) {
    /* FIXME: This will work, but the statistics need to be updated... */
    /* FIXME: This will work, but the statistics need to be updated... */
    return;
    return;
  }
  }
 
 
  /* Just in case an exception happens */
  /* Just in case an exception happens */
  ship_gprs_out_t(opq->prev);
  ship_gprs_out_t(opq->prev);
 
 
  if(!opq->param[2]) {
  if(!opq->param[2]) {
    /* Load the data from the immediate */
    /* Load the data from the immediate */
    l_lbs_imm_t_table[param_t[0]](opq, 1, opq->param[1]);
    l_lbs_imm_t_table[param_t[0]](opq, 1, opq->param[1]);
    return;
    return;
  }
  }
 
 
  l_lbs_t_table[param_t[0]][param_t[2]](opq, 1, opq->param[1]);
  l_lbs_t_table[param_t[0]][param_t[2]](opq, 1, opq->param[1]);
}
}
 
 
DEF_1T_OP(imm_gen_op, l_lbz_imm_t_table, gen_op_lbz_imm);
DEF_1T_OP(imm_gen_op, l_lbz_imm_t_table, gen_op_lbz_imm);
DEF_2T_OP(imm_gen_op, l_lbz_t_table, gen_op_lbz);
DEF_2T_OP(imm_gen_op, l_lbz_t_table, gen_op_lbz);
 
 
void gen_l_lbz(struct op_queue *opq, int param_t[3], int delay_slot)
void gen_l_lbz(struct op_queue *opq, int param_t[3], int delay_slot)
{
{
  if(!opq->param[0]) {
  if(!opq->param[0]) {
    /* FIXME: This will work, but the statistics need to be updated... */
    /* FIXME: This will work, but the statistics need to be updated... */
    return;
    return;
  }
  }
 
 
  /* Just in case an exception happens */
  /* Just in case an exception happens */
  ship_gprs_out_t(opq->prev);
  ship_gprs_out_t(opq->prev);
 
 
  if(!opq->param[2]) {
  if(!opq->param[2]) {
    /* Load the data from the immediate */
    /* Load the data from the immediate */
    l_lbz_imm_t_table[param_t[0]](opq, 1, opq->param[1]);
    l_lbz_imm_t_table[param_t[0]](opq, 1, opq->param[1]);
    return;
    return;
  }
  }
 
 
  l_lbz_t_table[param_t[0]][param_t[2]](opq, 1, opq->param[1]);
  l_lbz_t_table[param_t[0]][param_t[2]](opq, 1, opq->param[1]);
}
}
 
 
DEF_1T_OP(imm_gen_op, l_lhs_imm_t_table, gen_op_lhs_imm);
DEF_1T_OP(imm_gen_op, l_lhs_imm_t_table, gen_op_lhs_imm);
DEF_2T_OP(imm_gen_op, l_lhs_t_table, gen_op_lhs);
DEF_2T_OP(imm_gen_op, l_lhs_t_table, gen_op_lhs);
 
 
void gen_l_lhs(struct op_queue *opq, int param_t[3], int delay_slot)
void gen_l_lhs(struct op_queue *opq, int param_t[3], int delay_slot)
{
{
  if(!opq->param[0]) {
  if(!opq->param[0]) {
    /* FIXME: This will work, but the statistics need to be updated... */
    /* FIXME: This will work, but the statistics need to be updated... */
    return;
    return;
  }
  }
 
 
  /* Just in case an exception happens */
  /* Just in case an exception happens */
  ship_gprs_out_t(opq->prev);
  ship_gprs_out_t(opq->prev);
 
 
  if(!opq->param[2]) {
  if(!opq->param[2]) {
    /* Load the data from the immediate */
    /* Load the data from the immediate */
    l_lhs_imm_t_table[param_t[0]](opq, 1, opq->param[1]);
    l_lhs_imm_t_table[param_t[0]](opq, 1, opq->param[1]);
    return;
    return;
  }
  }
 
 
  l_lhs_t_table[param_t[0]][param_t[2]](opq, 1, opq->param[1]);
  l_lhs_t_table[param_t[0]][param_t[2]](opq, 1, opq->param[1]);
}
}
 
 
DEF_1T_OP(imm_gen_op, l_lhz_imm_t_table, gen_op_lhz_imm);
DEF_1T_OP(imm_gen_op, l_lhz_imm_t_table, gen_op_lhz_imm);
DEF_2T_OP(imm_gen_op, l_lhz_t_table, gen_op_lhz);
DEF_2T_OP(imm_gen_op, l_lhz_t_table, gen_op_lhz);
 
 
void gen_l_lhz(struct op_queue *opq, int param_t[3], int delay_slot)
void gen_l_lhz(struct op_queue *opq, int param_t[3], int delay_slot)
{
{
  if(!opq->param[0]) {
  if(!opq->param[0]) {
    /* FIXME: This will work, but the statistics need to be updated... */
    /* FIXME: This will work, but the statistics need to be updated... */
    return;
    return;
  }
  }
 
 
  /* Just in case an exception happens */
  /* Just in case an exception happens */
  ship_gprs_out_t(opq->prev);
  ship_gprs_out_t(opq->prev);
 
 
  if(!opq->param[2]) {
  if(!opq->param[2]) {
    /* Load the data from the immediate */
    /* Load the data from the immediate */
    l_lhz_imm_t_table[param_t[0]](opq, 1, opq->param[1]);
    l_lhz_imm_t_table[param_t[0]](opq, 1, opq->param[1]);
    return;
    return;
  }
  }
 
 
  l_lhz_t_table[param_t[0]][param_t[2]](opq, 1, opq->param[1]);
  l_lhz_t_table[param_t[0]][param_t[2]](opq, 1, opq->param[1]);
}
}
 
 
DEF_1T_OP(imm_gen_op, l_lws_imm_t_table, gen_op_lws_imm);
DEF_1T_OP(imm_gen_op, l_lws_imm_t_table, gen_op_lws_imm);
DEF_2T_OP(imm_gen_op, l_lws_t_table, gen_op_lws);
DEF_2T_OP(imm_gen_op, l_lws_t_table, gen_op_lws);
 
 
void gen_l_lws(struct op_queue *opq, int param_t[3], int delay_slot)
void gen_l_lws(struct op_queue *opq, int param_t[3], int delay_slot)
{
{
  if(!opq->param[0]) {
  if(!opq->param[0]) {
    /* FIXME: This will work, but the statistics need to be updated... */
    /* FIXME: This will work, but the statistics need to be updated... */
    return;
    return;
  }
  }
 
 
  /* Just in case an exception happens */
  /* Just in case an exception happens */
  ship_gprs_out_t(opq->prev);
  ship_gprs_out_t(opq->prev);
 
 
  if(!opq->param[2]) {
  if(!opq->param[2]) {
    /* Load the data from the immediate */
    /* Load the data from the immediate */
    l_lws_imm_t_table[param_t[0]](opq, 1, opq->param[1]);
    l_lws_imm_t_table[param_t[0]](opq, 1, opq->param[1]);
    return;
    return;
  }
  }
 
 
  l_lws_t_table[param_t[0]][param_t[2]](opq, 1, opq->param[1]);
  l_lws_t_table[param_t[0]][param_t[2]](opq, 1, opq->param[1]);
}
}
 
 
DEF_1T_OP(imm_gen_op, l_lwz_imm_t_table, gen_op_lwz_imm);
DEF_1T_OP(imm_gen_op, l_lwz_imm_t_table, gen_op_lwz_imm);
DEF_2T_OP(imm_gen_op, l_lwz_t_table, gen_op_lwz);
DEF_2T_OP(imm_gen_op, l_lwz_t_table, gen_op_lwz);
 
 
void gen_l_lwz(struct op_queue *opq, int param_t[3], int delay_slot)
void gen_l_lwz(struct op_queue *opq, int param_t[3], int delay_slot)
{
{
  if(!opq->param[0]) {
  if(!opq->param[0]) {
    /* FIXME: This will work, but the statistics need to be updated... */
    /* FIXME: This will work, but the statistics need to be updated... */
    return;
    return;
  }
  }
 
 
  /* Just in case an exception happens */
  /* Just in case an exception happens */
  ship_gprs_out_t(opq->prev);
  ship_gprs_out_t(opq->prev);
 
 
  if(!opq->param[2]) {
  if(!opq->param[2]) {
    /* Load the data from the immediate */
    /* Load the data from the immediate */
    l_lwz_imm_t_table[param_t[0]](opq, 1, opq->param[1]);
    l_lwz_imm_t_table[param_t[0]](opq, 1, opq->param[1]);
    return;
    return;
  }
  }
 
 
  l_lwz_t_table[param_t[0]][param_t[2]](opq, 1, opq->param[1]);
  l_lwz_t_table[param_t[0]][param_t[2]](opq, 1, opq->param[1]);
}
}
 
 
DEF_1T_OP(imm_gen_op, l_mac_imm_t_table, gen_op_mac_imm);
DEF_1T_OP(imm_gen_op, l_mac_imm_t_table, gen_op_mac_imm);
DEF_2T_OP(generic_gen_op, l_mac_t_table, gen_op_mac);
DEF_2T_OP(generic_gen_op, l_mac_t_table, gen_op_mac);
 
 
void gen_l_mac(struct op_queue *opq, int param_t[3], int delay_slot)
void gen_l_mac(struct op_queue *opq, int param_t[3], int delay_slot)
{
{
  if(!opq->param[0] || !opq->param[1])
  if(!opq->param[0] || !opq->param[1])
    return;
    return;
 
 
  if(param_t[1] == T_NONE)
  if(param_t[1] == T_NONE)
    l_mac_imm_t_table[param_t[0]](opq, 1, opq->param[1]);
    l_mac_imm_t_table[param_t[0]](opq, 1, opq->param[1]);
  else
  else
    l_mac_t_table[param_t[0]][param_t[1]](opq, 1);
    l_mac_t_table[param_t[0]][param_t[1]](opq, 1);
}
}
 
 
DEF_1T_OP(generic_gen_op, l_macrc_t_table, gen_op_macrc);
DEF_1T_OP(generic_gen_op, l_macrc_t_table, gen_op_macrc);
 
 
void gen_l_macrc(struct op_queue *opq, int param_t[3], int delay_slot)
void gen_l_macrc(struct op_queue *opq, int param_t[3], int delay_slot)
{
{
  if(!opq->param[0]) {
  if(!opq->param[0]) {
    gen_op_macc(opq, 1);
    gen_op_macc(opq, 1);
    return;
    return;
  }
  }
 
 
  l_macrc_t_table[param_t[0]](opq, 1);
  l_macrc_t_table[param_t[0]](opq, 1);
}
}
 
 
DEF_1T_OP(imm_gen_op, l_mfspr_imm_t_table, gen_op_mfspr_imm);
DEF_1T_OP(imm_gen_op, l_mfspr_imm_t_table, gen_op_mfspr_imm);
DEF_2T_OP(imm_gen_op, l_mfspr_t_table, gen_op_mfspr);
DEF_2T_OP(imm_gen_op, l_mfspr_t_table, gen_op_mfspr);
 
 
void gen_l_mfspr(struct op_queue *opq, int param_t[3], int delay_slot)
void gen_l_mfspr(struct op_queue *opq, int param_t[3], int delay_slot)
{
{
  if(!opq->param[0])
  if(!opq->param[0])
    return;
    return;
 
 
  if(!opq->param[1]) {
  if(!opq->param[1]) {
    l_mfspr_imm_t_table[param_t[0]](opq, 1, opq->param[2]);
    l_mfspr_imm_t_table[param_t[0]](opq, 1, opq->param[2]);
    return;
    return;
  }
  }
 
 
  l_mfspr_t_table[param_t[0]][param_t[1]](opq, 1, opq->param[2]);
  l_mfspr_t_table[param_t[0]][param_t[1]](opq, 1, opq->param[2]);
}
}
 
 
void gen_l_movhi(struct op_queue *opq, int param_t[3], int delay_slot)
void gen_l_movhi(struct op_queue *opq, int param_t[3], int delay_slot)
{
{
  if(!opq->param[0])
  if(!opq->param[0])
    return;
    return;
 
 
  if(!opq->param[1]) {
  if(!opq->param[1]) {
    clear_t[param_t[0]](opq, 1);
    clear_t[param_t[0]](opq, 1);
    return;
    return;
  }
  }
 
 
  mov_t_imm[param_t[0]](opq, 1, opq->param[1] << 16);
  mov_t_imm[param_t[0]](opq, 1, opq->param[1] << 16);
}
}
 
 
DEF_2T_OP(generic_gen_op, l_msb_t_table, gen_op_msb);
DEF_2T_OP(generic_gen_op, l_msb_t_table, gen_op_msb);
 
 
void gen_l_msb(struct op_queue *opq, int param_t[3], int delay_slot)
void gen_l_msb(struct op_queue *opq, int param_t[3], int delay_slot)
{
{
  if(!opq->param[0] || !opq->param[1])
  if(!opq->param[0] || !opq->param[1])
    return;
    return;
 
 
  l_msb_t_table[param_t[0]][param_t[1]](opq, 1);
  l_msb_t_table[param_t[0]][param_t[1]](opq, 1);
}
}
 
 
DEF_1T_OP(imm_gen_op, l_mtspr_clear_t_table, gen_op_mtspr_clear);
DEF_1T_OP(imm_gen_op, l_mtspr_clear_t_table, gen_op_mtspr_clear);
DEF_1T_OP(imm_gen_op, l_mtspr_imm_t_table, gen_op_mtspr_imm);
DEF_1T_OP(imm_gen_op, l_mtspr_imm_t_table, gen_op_mtspr_imm);
DEF_2T_OP(imm_gen_op, l_mtspr_t_table, gen_op_mtspr);
DEF_2T_OP(imm_gen_op, l_mtspr_t_table, gen_op_mtspr);
 
 
void gen_l_mtspr(struct op_queue *opq, int param_t[3], int delay_slot)
void gen_l_mtspr(struct op_queue *opq, int param_t[3], int delay_slot)
{
{
  /* Just in case an exception happens */
  /* Just in case an exception happens */
  ship_gprs_out_t(opq->prev);
  ship_gprs_out_t(opq->prev);
 
 
  if(!opq->param[0]) {
  if(!opq->param[0]) {
    if(!opq->param[1]) {
    if(!opq->param[1]) {
      /* Clear the immediate SPR */
      /* Clear the immediate SPR */
      gen_op_mtspr_imm_clear(opq, 1, opq->param[2]);
      gen_op_mtspr_imm_clear(opq, 1, opq->param[2]);
      return;
      return;
    }
    }
    l_mtspr_imm_t_table[param_t[1]](opq, 1, opq->param[2]);
    l_mtspr_imm_t_table[param_t[1]](opq, 1, opq->param[2]);
    return;
    return;
  }
  }
 
 
  if(!opq->param[1]) {
  if(!opq->param[1]) {
    l_mtspr_clear_t_table[param_t[0]](opq, 1, opq->param[2]);
    l_mtspr_clear_t_table[param_t[0]](opq, 1, opq->param[2]);
    return;
    return;
  }
  }
 
 
  l_mtspr_t_table[param_t[0]][param_t[1]](opq, 1, opq->param[2]);
  l_mtspr_t_table[param_t[0]][param_t[1]](opq, 1, opq->param[2]);
}
}
 
 
DEF_2T_OP(imm_gen_op, l_mul_imm_t_table, gen_op_mul_imm);
DEF_2T_OP(imm_gen_op, l_mul_imm_t_table, gen_op_mul_imm);
DEF_3T_OP(generic_gen_op, l_mul_t_table, gen_op_mul);
DEF_3T_OP(generic_gen_op, l_mul_t_table, gen_op_mul);
 
 
void gen_l_mul(struct op_queue *opq, int param_t[3], int delay_slot)
void gen_l_mul(struct op_queue *opq, int param_t[3], int delay_slot)
{
{
  if(!opq->param[0])
  if(!opq->param[0])
    return;
    return;
 
 
  if(!opq->param[1] || !opq->param[2]) {
  if(!opq->param[1] || !opq->param[2]) {
    clear_t[param_t[0]](opq, 1);
    clear_t[param_t[0]](opq, 1);
    return;
    return;
  }
  }
 
 
  if(param_t[2] == T_NONE)
  if(param_t[2] == T_NONE)
    l_mul_imm_t_table[param_t[0]][param_t[1]](opq, 1, opq->param[2]);
    l_mul_imm_t_table[param_t[0]][param_t[1]](opq, 1, opq->param[2]);
  else
  else
    l_mul_t_table[param_t[0]][param_t[1]][param_t[2]](opq, 1);
    l_mul_t_table[param_t[0]][param_t[1]][param_t[2]](opq, 1);
}
}
 
 
DEF_3T_OP(generic_gen_op, l_mulu_t_table, gen_op_mulu);
DEF_3T_OP(generic_gen_op, l_mulu_t_table, gen_op_mulu);
 
 
void gen_l_mulu(struct op_queue *opq, int param_t[3], int delay_slot)
void gen_l_mulu(struct op_queue *opq, int param_t[3], int delay_slot)
{
{
  if(!opq->param[0])
  if(!opq->param[0])
    return;
    return;
 
 
  if(!opq->param[1] || !opq->param[2]) {
  if(!opq->param[1] || !opq->param[2]) {
    clear_t[param_t[0]](opq, 1);
    clear_t[param_t[0]](opq, 1);
    return;
    return;
  }
  }
 
 
  l_mulu_t_table[param_t[0]][param_t[1]][param_t[2]](opq, 1);
  l_mulu_t_table[param_t[0]][param_t[1]][param_t[2]](opq, 1);
}
}
 
 
void gen_l_nop(struct op_queue *opq, int param_t[3], int delay_slot)
void gen_l_nop(struct op_queue *opq, int param_t[3], int delay_slot)
{
{
  /* Do parameter switch now */
  /* Do parameter switch now */
  switch(opq->param[0]) {
  switch(opq->param[0]) {
  case NOP_NOP:
  case NOP_NOP:
    break;
    break;
  case NOP_EXIT:
  case NOP_EXIT:
    ship_gprs_out_t(opq->prev);
    ship_gprs_out_t(opq->prev);
    gen_op_nop_exit(opq, 1);
    gen_op_nop_exit(opq, 1);
    break;
    break;
  case NOP_CNT_RESET:
  case NOP_CNT_RESET:
    gen_op_nop_reset(opq, 1);
    gen_op_nop_reset(opq, 1);
    break;
    break;
  case NOP_PRINTF:
  case NOP_PRINTF:
    ship_gprs_out_t(opq->prev);
    ship_gprs_out_t(opq->prev);
    gen_op_nop_printf(opq, 1);
    gen_op_nop_printf(opq, 1);
    break;
    break;
  case NOP_REPORT:
  case NOP_REPORT:
    ship_gprs_out_t(opq->prev);
    ship_gprs_out_t(opq->prev);
    gen_op_nop_report(opq, 1);
    gen_op_nop_report(opq, 1);
    break;
    break;
  default:
  default:
    if((opq->param[0] >= NOP_REPORT_FIRST) && (opq->param[0] <= NOP_REPORT_LAST)) {
    if((opq->param[0] >= NOP_REPORT_FIRST) && (opq->param[0] <= NOP_REPORT_LAST)) {
      ship_gprs_out_t(opq->prev);
      ship_gprs_out_t(opq->prev);
      gen_op_nop_report_imm(opq, 1, opq->param[0] - NOP_REPORT_FIRST);
      gen_op_nop_report_imm(opq, 1, opq->param[0] - NOP_REPORT_FIRST);
    }
    }
    break;
    break;
  }
  }
}
}
 
 
DEF_2T_OP(imm_gen_op, l_or_imm_t_table, gen_op_or_imm);
DEF_2T_OP(imm_gen_op, l_or_imm_t_table, gen_op_or_imm);
DEF_3T_OP_NEQ(generic_gen_op, l_or_t_table, gen_op_or);
DEF_3T_OP_NEQ(generic_gen_op, l_or_t_table, gen_op_or);
 
 
void gen_l_or(struct op_queue *opq, int param_t[3], int delay_slot)
void gen_l_or(struct op_queue *opq, int param_t[3], int delay_slot)
{
{
  if(!opq->param[0])
  if(!opq->param[0])
    return;
    return;
 
 
  if((opq->param[0] == opq->param[1]) &&
  if((opq->param[0] == opq->param[1]) &&
     (opq->param[0] == opq->param[2]) &&
     (opq->param[0] == opq->param[2]) &&
     (param_t[2] != T_NONE))
     (param_t[2] != T_NONE))
    return;
    return;
 
 
  if(!opq->param[1] && !opq->param[2]) {
  if(!opq->param[1] && !opq->param[2]) {
    clear_t[param_t[0]](opq, 1);
    clear_t[param_t[0]](opq, 1);
    return;
    return;
  }
  }
 
 
  if(!opq->param[2]) {
  if(!opq->param[2]) {
    if((param_t[2] == T_NONE) && (opq->param[0] == opq->param[1]))
    if((param_t[2] == T_NONE) && (opq->param[0] == opq->param[1]))
      return;
      return;
    move_t_t[param_t[0]][param_t[1]](opq, 1);
    move_t_t[param_t[0]][param_t[1]](opq, 1);
    return;
    return;
  }
  }
 
 
  if(!opq->param[1]) {
  if(!opq->param[1]) {
    /* Check if we are moveing an immediate */
    /* Check if we are moveing an immediate */
    if(param_t[2] == T_NONE) {
    if(param_t[2] == T_NONE) {
      /* Yep, an immediate */
      /* Yep, an immediate */
      mov_t_imm[param_t[0]](opq, 1, opq->param[2]);
      mov_t_imm[param_t[0]](opq, 1, opq->param[2]);
      return;
      return;
    }
    }
    /* Just another move */
    /* Just another move */
    move_t_t[param_t[0]][param_t[2]](opq, 1);
    move_t_t[param_t[0]][param_t[2]](opq, 1);
    return;
    return;
  }
  }
 
 
  if(param_t[2] == T_NONE)
  if(param_t[2] == T_NONE)
    l_or_imm_t_table[param_t[0]][param_t[1]](opq, 1, opq->param[2]);
    l_or_imm_t_table[param_t[0]][param_t[1]](opq, 1, opq->param[2]);
  else
  else
    l_or_t_table[param_t[0]][param_t[1]][param_t[2]](opq, 1);
    l_or_t_table[param_t[0]][param_t[1]][param_t[2]](opq, 1);
}
}
 
 
void gen_l_rfe(struct op_queue *opq, int param_t[3], int delay_slot)
void gen_l_rfe(struct op_queue *opq, int param_t[3], int delay_slot)
{
{
  if(do_stats)
  if(do_stats)
    /* All gprs are current since this insn doesn't touch any reg */
    /* All gprs are current since this insn doesn't touch any reg */
    gen_op_analysis(opq, 1);
    gen_op_analysis(opq, 1);
 
 
  gen_op_prep_rfe(opq, 1);
  gen_op_prep_rfe(opq, 1);
  /* FIXME: rename op_do_sched_delay */
  /* FIXME: rename op_do_sched_delay */
  gen_op_do_sched_delay(opq, 1);
  gen_op_do_sched_delay(opq, 1);
  gen_op_do_jump(opq, 1);
  gen_op_do_jump(opq, 1);
}
}
 
 
/* FIXME: All store instructions should be optimised when the disposition = 0 */
/* FIXME: All store instructions should be optimised when the disposition = 0 */
 
 
DEF_1T_OP(imm_gen_op, l_sb_clear_table, gen_op_sb_clear);
DEF_1T_OP(imm_gen_op, l_sb_clear_table, gen_op_sb_clear);
DEF_1T_OP(imm_gen_op, l_sb_imm_t_table, gen_op_sb_imm);
DEF_1T_OP(imm_gen_op, l_sb_imm_t_table, gen_op_sb_imm);
DEF_2T_OP(imm_gen_op, l_sb_t_table, gen_op_sb);
DEF_2T_OP(imm_gen_op, l_sb_t_table, gen_op_sb);
 
 
void gen_l_sb(struct op_queue *opq, int param_t[3], int delay_slot)
void gen_l_sb(struct op_queue *opq, int param_t[3], int delay_slot)
{
{
  /* Just in case an exception happens */
  /* Just in case an exception happens */
  ship_gprs_out_t(opq->prev);
  ship_gprs_out_t(opq->prev);
 
 
  if(!opq->param[2]) {
  if(!opq->param[2]) {
    if(!opq->param[1]) {
    if(!opq->param[1]) {
      gen_op_sb_clear_imm(opq, 1, opq->param[0]);
      gen_op_sb_clear_imm(opq, 1, opq->param[0]);
      return;
      return;
    }
    }
    l_sb_clear_table[param_t[1]](opq, 1, opq->param[0]);
    l_sb_clear_table[param_t[1]](opq, 1, opq->param[0]);
    return;
    return;
  }
  }
 
 
  if(!opq->param[1]) {
  if(!opq->param[1]) {
    /* Store the data to the immediate */
    /* Store the data to the immediate */
    l_sb_imm_t_table[param_t[2]](opq, 1, opq->param[0]);
    l_sb_imm_t_table[param_t[2]](opq, 1, opq->param[0]);
    return;
    return;
  }
  }
 
 
  l_sb_t_table[param_t[1]][param_t[2]](opq, 1, opq->param[0]);
  l_sb_t_table[param_t[1]][param_t[2]](opq, 1, opq->param[0]);
}
}
 
 
DEF_1T_OP(imm_gen_op, l_sh_clear_table, gen_op_sh_clear);
DEF_1T_OP(imm_gen_op, l_sh_clear_table, gen_op_sh_clear);
DEF_1T_OP(imm_gen_op, l_sh_imm_t_table, gen_op_sh_imm);
DEF_1T_OP(imm_gen_op, l_sh_imm_t_table, gen_op_sh_imm);
DEF_2T_OP(imm_gen_op, l_sh_t_table, gen_op_sh);
DEF_2T_OP(imm_gen_op, l_sh_t_table, gen_op_sh);
 
 
void gen_l_sh(struct op_queue *opq, int param_t[3], int delay_slot)
void gen_l_sh(struct op_queue *opq, int param_t[3], int delay_slot)
{
{
  /* Just in case an exception happens */
  /* Just in case an exception happens */
  ship_gprs_out_t(opq->prev);
  ship_gprs_out_t(opq->prev);
 
 
  if(!opq->param[2]) {
  if(!opq->param[2]) {
    if(!opq->param[1]) {
    if(!opq->param[1]) {
      gen_op_sh_clear_imm(opq, 1, opq->param[0]);
      gen_op_sh_clear_imm(opq, 1, opq->param[0]);
      return;
      return;
    }
    }
    l_sh_clear_table[param_t[1]](opq, 1, opq->param[0]);
    l_sh_clear_table[param_t[1]](opq, 1, opq->param[0]);
    return;
    return;
  }
  }
 
 
  if(!opq->param[1]) {
  if(!opq->param[1]) {
    /* Store the data to the immediate */
    /* Store the data to the immediate */
    l_sh_imm_t_table[param_t[2]](opq, 1, opq->param[0]);
    l_sh_imm_t_table[param_t[2]](opq, 1, opq->param[0]);
    return;
    return;
  }
  }
 
 
  l_sh_t_table[param_t[1]][param_t[2]](opq, 1, opq->param[0]);
  l_sh_t_table[param_t[1]][param_t[2]](opq, 1, opq->param[0]);
}
}
 
 
DEF_1T_OP(imm_gen_op, l_sw_clear_table, gen_op_sw_clear);
DEF_1T_OP(imm_gen_op, l_sw_clear_table, gen_op_sw_clear);
DEF_1T_OP(imm_gen_op, l_sw_imm_t_table, gen_op_sw_imm);
DEF_1T_OP(imm_gen_op, l_sw_imm_t_table, gen_op_sw_imm);
DEF_2T_OP(imm_gen_op, l_sw_t_table, gen_op_sw);
DEF_2T_OP(imm_gen_op, l_sw_t_table, gen_op_sw);
 
 
void gen_l_sw(struct op_queue *opq, int param_t[3], int delay_slot)
void gen_l_sw(struct op_queue *opq, int param_t[3], int delay_slot)
{
{
  /* Just in case an exception happens */
  /* Just in case an exception happens */
  ship_gprs_out_t(opq->prev);
  ship_gprs_out_t(opq->prev);
 
 
  if(!opq->param[2]) {
  if(!opq->param[2]) {
    if(!opq->param[1]) {
    if(!opq->param[1]) {
      gen_op_sw_clear_imm(opq, 1, opq->param[0]);
      gen_op_sw_clear_imm(opq, 1, opq->param[0]);
      return;
      return;
    }
    }
    l_sw_clear_table[param_t[1]](opq, 1, opq->param[0]);
    l_sw_clear_table[param_t[1]](opq, 1, opq->param[0]);
    return;
    return;
  }
  }
 
 
  if(!opq->param[1]) {
  if(!opq->param[1]) {
    /* Store the data to the immediate */
    /* Store the data to the immediate */
    l_sw_imm_t_table[param_t[2]](opq, 1, opq->param[0]);
    l_sw_imm_t_table[param_t[2]](opq, 1, opq->param[0]);
    return;
    return;
  }
  }
 
 
  l_sw_t_table[param_t[1]][param_t[2]](opq, 1, opq->param[0]);
  l_sw_t_table[param_t[1]][param_t[2]](opq, 1, opq->param[0]);
}
}
 
 
DEF_1T_OP(generic_gen_op, l_sfeq_null_t_table, gen_op_sfeq_null);
DEF_1T_OP(generic_gen_op, l_sfeq_null_t_table, gen_op_sfeq_null);
DEF_1T_OP(imm_gen_op, l_sfeq_imm_t_table, gen_op_sfeq_imm);
DEF_1T_OP(imm_gen_op, l_sfeq_imm_t_table, gen_op_sfeq_imm);
DEF_2T_OP(generic_gen_op, l_sfeq_t_table, gen_op_sfeq);
DEF_2T_OP(generic_gen_op, l_sfeq_t_table, gen_op_sfeq);
 
 
void gen_l_sfeq(struct op_queue *opq, int param_t[3], int delay_slot)
void gen_l_sfeq(struct op_queue *opq, int param_t[3], int delay_slot)
{
{
  if(!opq->param[0] && !opq->param[1]) {
  if(!opq->param[0] && !opq->param[1]) {
    gen_op_set_flag(opq, 1);
    gen_op_set_flag(opq, 1);
    return;
    return;
  }
  }
 
 
  if(!opq->param[0]) {
  if(!opq->param[0]) {
    if(param_t[1] == T_NONE) {
    if(param_t[1] == T_NONE) {
      if(!opq->param[1])
      if(!opq->param[1])
        gen_op_set_flag(opq, 1);
        gen_op_set_flag(opq, 1);
      else
      else
        gen_op_clear_flag(opq, 1);
        gen_op_clear_flag(opq, 1);
    } else
    } else
      l_sfeq_null_t_table[param_t[1]](opq, 1);
      l_sfeq_null_t_table[param_t[1]](opq, 1);
    return;
    return;
  }
  }
 
 
  if(!opq->param[1]) {
  if(!opq->param[1]) {
    l_sfeq_null_t_table[param_t[0]](opq, 1);
    l_sfeq_null_t_table[param_t[0]](opq, 1);
    return;
    return;
  }
  }
 
 
  if(param_t[1] == T_NONE)
  if(param_t[1] == T_NONE)
    l_sfeq_imm_t_table[param_t[0]](opq, 1, opq->param[1]);
    l_sfeq_imm_t_table[param_t[0]](opq, 1, opq->param[1]);
  else
  else
    l_sfeq_t_table[param_t[0]][param_t[1]](opq, 1);
    l_sfeq_t_table[param_t[0]][param_t[1]](opq, 1);
}
}
 
 
DEF_1T_OP(generic_gen_op, l_sfges_null_t_table, gen_op_sfges_null);
DEF_1T_OP(generic_gen_op, l_sfges_null_t_table, gen_op_sfges_null);
DEF_1T_OP(generic_gen_op, l_sfles_null_t_table, gen_op_sfles_null);
DEF_1T_OP(generic_gen_op, l_sfles_null_t_table, gen_op_sfles_null);
DEF_1T_OP(imm_gen_op, l_sfges_imm_t_table, gen_op_sfges_imm);
DEF_1T_OP(imm_gen_op, l_sfges_imm_t_table, gen_op_sfges_imm);
DEF_2T_OP(generic_gen_op, l_sfges_t_table, gen_op_sfges);
DEF_2T_OP(generic_gen_op, l_sfges_t_table, gen_op_sfges);
 
 
void gen_l_sfges(struct op_queue *opq, int param_t[3], int delay_slot)
void gen_l_sfges(struct op_queue *opq, int param_t[3], int delay_slot)
{
{
  if(!opq->param[0] && !opq->param[1]) {
  if(!opq->param[0] && !opq->param[1]) {
    gen_op_set_flag(opq, 1);
    gen_op_set_flag(opq, 1);
    return;
    return;
  }
  }
 
 
  if(!opq->param[0]) {
  if(!opq->param[0]) {
    /* sfles IS correct */
    /* sfles IS correct */
    if(param_t[1] == T_NONE) {
    if(param_t[1] == T_NONE) {
      if(0 >= (orreg_t)opq->param[1])
      if(0 >= (orreg_t)opq->param[1])
        gen_op_set_flag(opq, 1);
        gen_op_set_flag(opq, 1);
      else
      else
        gen_op_clear_flag(opq, 1);
        gen_op_clear_flag(opq, 1);
    } else
    } else
      l_sfles_null_t_table[param_t[1]](opq, 1);
      l_sfles_null_t_table[param_t[1]](opq, 1);
    return;
    return;
  }
  }
 
 
  if(!opq->param[1]) {
  if(!opq->param[1]) {
    l_sfges_null_t_table[param_t[0]](opq, 1);
    l_sfges_null_t_table[param_t[0]](opq, 1);
    return;
    return;
  }
  }
 
 
  if(param_t[1] == T_NONE)
  if(param_t[1] == T_NONE)
    l_sfges_imm_t_table[param_t[0]](opq, 1, opq->param[1]);
    l_sfges_imm_t_table[param_t[0]](opq, 1, opq->param[1]);
  else
  else
    l_sfges_t_table[param_t[0]][param_t[1]](opq, 1);
    l_sfges_t_table[param_t[0]][param_t[1]](opq, 1);
}
}
 
 
DEF_1T_OP(generic_gen_op, l_sfgeu_null_t_table, gen_op_sfgeu_null);
DEF_1T_OP(generic_gen_op, l_sfgeu_null_t_table, gen_op_sfgeu_null);
DEF_1T_OP(generic_gen_op, l_sfleu_null_t_table, gen_op_sfleu_null);
DEF_1T_OP(generic_gen_op, l_sfleu_null_t_table, gen_op_sfleu_null);
DEF_1T_OP(imm_gen_op, l_sfgeu_imm_t_table, gen_op_sfgeu_imm);
DEF_1T_OP(imm_gen_op, l_sfgeu_imm_t_table, gen_op_sfgeu_imm);
DEF_2T_OP(generic_gen_op, l_sfgeu_t_table, gen_op_sfgeu);
DEF_2T_OP(generic_gen_op, l_sfgeu_t_table, gen_op_sfgeu);
 
 
void gen_l_sfgeu(struct op_queue *opq, int param_t[3], int delay_slot)
void gen_l_sfgeu(struct op_queue *opq, int param_t[3], int delay_slot)
{
{
  if(!opq->param[0] && !opq->param[1]) {
  if(!opq->param[0] && !opq->param[1]) {
    gen_op_set_flag(opq, 1);
    gen_op_set_flag(opq, 1);
    return;
    return;
  }
  }
 
 
  if(!opq->param[0]) {
  if(!opq->param[0]) {
    /* sfleu IS correct */
    /* sfleu IS correct */
    if(param_t[1] == T_NONE) {
    if(param_t[1] == T_NONE) {
      if(0 >= opq->param[1])
      if(0 >= opq->param[1])
        gen_op_set_flag(opq, 1);
        gen_op_set_flag(opq, 1);
      else
      else
        gen_op_clear_flag(opq, 1);
        gen_op_clear_flag(opq, 1);
    } else
    } else
      l_sfleu_null_t_table[param_t[1]](opq, 1);
      l_sfleu_null_t_table[param_t[1]](opq, 1);
    return;
    return;
  }
  }
 
 
  if(!opq->param[1]) {
  if(!opq->param[1]) {
    l_sfgeu_null_t_table[param_t[0]](opq, 1);
    l_sfgeu_null_t_table[param_t[0]](opq, 1);
    return;
    return;
  }
  }
  if(param_t[1] == T_NONE)
  if(param_t[1] == T_NONE)
    l_sfgeu_imm_t_table[param_t[0]](opq, 1, opq->param[1]);
    l_sfgeu_imm_t_table[param_t[0]](opq, 1, opq->param[1]);
  else
  else
    l_sfgeu_t_table[param_t[0]][param_t[1]](opq, 1);
    l_sfgeu_t_table[param_t[0]][param_t[1]](opq, 1);
}
}
 
 
DEF_1T_OP(generic_gen_op, l_sfgts_null_t_table, gen_op_sfgts_null);
DEF_1T_OP(generic_gen_op, l_sfgts_null_t_table, gen_op_sfgts_null);
DEF_1T_OP(generic_gen_op, l_sflts_null_t_table, gen_op_sflts_null);
DEF_1T_OP(generic_gen_op, l_sflts_null_t_table, gen_op_sflts_null);
DEF_1T_OP(imm_gen_op, l_sfgts_imm_t_table, gen_op_sfgts_imm);
DEF_1T_OP(imm_gen_op, l_sfgts_imm_t_table, gen_op_sfgts_imm);
DEF_2T_OP(generic_gen_op, l_sfgts_t_table, gen_op_sfgts);
DEF_2T_OP(generic_gen_op, l_sfgts_t_table, gen_op_sfgts);
 
 
void gen_l_sfgts(struct op_queue *opq, int param_t[3], int delay_slot)
void gen_l_sfgts(struct op_queue *opq, int param_t[3], int delay_slot)
{
{
  if(!opq->param[0] && !opq->param[1]) {
  if(!opq->param[0] && !opq->param[1]) {
    gen_op_clear_flag(opq, 1);
    gen_op_clear_flag(opq, 1);
    return;
    return;
  }
  }
 
 
  if(!opq->param[0]) {
  if(!opq->param[0]) {
    /* sflts IS correct */
    /* sflts IS correct */
    if(param_t[1] == T_NONE) {
    if(param_t[1] == T_NONE) {
      if(0 > (orreg_t)opq->param[1])
      if(0 > (orreg_t)opq->param[1])
        gen_op_set_flag(opq, 1);
        gen_op_set_flag(opq, 1);
      else
      else
        gen_op_clear_flag(opq, 1);
        gen_op_clear_flag(opq, 1);
    } else
    } else
      l_sflts_null_t_table[param_t[1]](opq, 1);
      l_sflts_null_t_table[param_t[1]](opq, 1);
    return;
    return;
  }
  }
 
 
  if(!opq->param[1]) {
  if(!opq->param[1]) {
    l_sfgts_null_t_table[param_t[0]](opq, 1);
    l_sfgts_null_t_table[param_t[0]](opq, 1);
    return;
    return;
  }
  }
 
 
  if(param_t[1] == T_NONE)
  if(param_t[1] == T_NONE)
    l_sfgts_imm_t_table[param_t[0]](opq, 1, opq->param[1]);
    l_sfgts_imm_t_table[param_t[0]](opq, 1, opq->param[1]);
  else
  else
    l_sfgts_t_table[param_t[0]][param_t[1]](opq, 1);
    l_sfgts_t_table[param_t[0]][param_t[1]](opq, 1);
}
}
 
 
DEF_1T_OP(generic_gen_op, l_sfgtu_null_t_table, gen_op_sfgtu_null);
DEF_1T_OP(generic_gen_op, l_sfgtu_null_t_table, gen_op_sfgtu_null);
DEF_1T_OP(generic_gen_op, l_sfltu_null_t_table, gen_op_sfltu_null);
DEF_1T_OP(generic_gen_op, l_sfltu_null_t_table, gen_op_sfltu_null);
DEF_1T_OP(imm_gen_op, l_sfgtu_imm_t_table, gen_op_sfgtu_imm);
DEF_1T_OP(imm_gen_op, l_sfgtu_imm_t_table, gen_op_sfgtu_imm);
DEF_2T_OP(generic_gen_op, l_sfgtu_t_table, gen_op_sfgtu);
DEF_2T_OP(generic_gen_op, l_sfgtu_t_table, gen_op_sfgtu);
 
 
void gen_l_sfgtu(struct op_queue *opq, int param_t[3], int delay_slot)
void gen_l_sfgtu(struct op_queue *opq, int param_t[3], int delay_slot)
{
{
  if(!opq->param[0] && !opq->param[1]) {
  if(!opq->param[0] && !opq->param[1]) {
    gen_op_clear_flag(opq, 1);
    gen_op_clear_flag(opq, 1);
    return;
    return;
  }
  }
 
 
  if(!opq->param[0]) {
  if(!opq->param[0]) {
    /* sfltu IS correct */
    /* sfltu IS correct */
    if(param_t[1] == T_NONE) {
    if(param_t[1] == T_NONE) {
      if(0 > opq->param[1])
      if(0 > opq->param[1])
        gen_op_set_flag(opq, 1);
        gen_op_set_flag(opq, 1);
      else
      else
        gen_op_clear_flag(opq, 1);
        gen_op_clear_flag(opq, 1);
    } else
    } else
      l_sfltu_null_t_table[param_t[1]](opq, 1);
      l_sfltu_null_t_table[param_t[1]](opq, 1);
    return;
    return;
  }
  }
 
 
  if(!opq->param[1]) {
  if(!opq->param[1]) {
    l_sfgtu_null_t_table[param_t[0]](opq, 1);
    l_sfgtu_null_t_table[param_t[0]](opq, 1);
    return;
    return;
  }
  }
 
 
  if(param_t[1] == T_NONE)
  if(param_t[1] == T_NONE)
    l_sfgtu_imm_t_table[param_t[0]](opq, 1, opq->param[1]);
    l_sfgtu_imm_t_table[param_t[0]](opq, 1, opq->param[1]);
  else
  else
    l_sfgtu_t_table[param_t[0]][param_t[1]](opq, 1);
    l_sfgtu_t_table[param_t[0]][param_t[1]](opq, 1);
}
}
 
 
DEF_1T_OP(imm_gen_op, l_sfles_imm_t_table, gen_op_sfles_imm);
DEF_1T_OP(imm_gen_op, l_sfles_imm_t_table, gen_op_sfles_imm);
DEF_2T_OP(generic_gen_op, l_sfles_t_table, gen_op_sfles);
DEF_2T_OP(generic_gen_op, l_sfles_t_table, gen_op_sfles);
 
 
void gen_l_sfles(struct op_queue *opq, int param_t[3], int delay_slot)
void gen_l_sfles(struct op_queue *opq, int param_t[3], int delay_slot)
{
{
  if(!opq->param[0] && !opq->param[1]) {
  if(!opq->param[0] && !opq->param[1]) {
    gen_op_set_flag(opq, 1);
    gen_op_set_flag(opq, 1);
    return;
    return;
  }
  }
 
 
  if(!opq->param[0]) {
  if(!opq->param[0]) {
    /* sfges IS correct */
    /* sfges IS correct */
    if(param_t[1] == T_NONE) {
    if(param_t[1] == T_NONE) {
      if(0 <= (orreg_t)opq->param[1])
      if(0 <= (orreg_t)opq->param[1])
        gen_op_set_flag(opq, 1);
        gen_op_set_flag(opq, 1);
      else
      else
        gen_op_clear_flag(opq, 1);
        gen_op_clear_flag(opq, 1);
    } else
    } else
      l_sfges_null_t_table[param_t[1]](opq, 1);
      l_sfges_null_t_table[param_t[1]](opq, 1);
    return;
    return;
  }
  }
 
 
  if(!opq->param[1]) {
  if(!opq->param[1]) {
    l_sfles_null_t_table[param_t[0]](opq, 1);
    l_sfles_null_t_table[param_t[0]](opq, 1);
    return;
    return;
  }
  }
 
 
  if(param_t[1] == T_NONE)
  if(param_t[1] == T_NONE)
    l_sfles_imm_t_table[param_t[0]](opq, 1, opq->param[1]);
    l_sfles_imm_t_table[param_t[0]](opq, 1, opq->param[1]);
  else
  else
    l_sfles_t_table[param_t[0]][param_t[1]](opq, 1);
    l_sfles_t_table[param_t[0]][param_t[1]](opq, 1);
}
}
 
 
DEF_1T_OP(imm_gen_op, l_sfleu_imm_t_table, gen_op_sfleu_imm);
DEF_1T_OP(imm_gen_op, l_sfleu_imm_t_table, gen_op_sfleu_imm);
DEF_2T_OP(generic_gen_op, l_sfleu_t_table, gen_op_sfleu);
DEF_2T_OP(generic_gen_op, l_sfleu_t_table, gen_op_sfleu);
 
 
void gen_l_sfleu(struct op_queue *opq, int param_t[3], int delay_slot)
void gen_l_sfleu(struct op_queue *opq, int param_t[3], int delay_slot)
{
{
  if(!opq->param[0] && !opq->param[1]) {
  if(!opq->param[0] && !opq->param[1]) {
    gen_op_set_flag(opq, 1);
    gen_op_set_flag(opq, 1);
    return;
    return;
  }
  }
 
 
  if(!opq->param[0]) {
  if(!opq->param[0]) {
    /* sfleu IS correct */
    /* sfleu IS correct */
    if(param_t[1] == T_NONE) {
    if(param_t[1] == T_NONE) {
      if(0 <= opq->param[1])
      if(0 <= opq->param[1])
        gen_op_set_flag(opq, 1);
        gen_op_set_flag(opq, 1);
      else
      else
        gen_op_clear_flag(opq, 1);
        gen_op_clear_flag(opq, 1);
    } else
    } else
      l_sfgeu_null_t_table[param_t[1]](opq, 1);
      l_sfgeu_null_t_table[param_t[1]](opq, 1);
    return;
    return;
  }
  }
 
 
  if(!opq->param[1]) {
  if(!opq->param[1]) {
    l_sfleu_null_t_table[param_t[0]](opq, 1);
    l_sfleu_null_t_table[param_t[0]](opq, 1);
    return;
    return;
  }
  }
 
 
  if(param_t[1] == T_NONE)
  if(param_t[1] == T_NONE)
    l_sfleu_imm_t_table[param_t[0]](opq, 1, opq->param[1]);
    l_sfleu_imm_t_table[param_t[0]](opq, 1, opq->param[1]);
  else
  else
    l_sfleu_t_table[param_t[0]][param_t[1]](opq, 1);
    l_sfleu_t_table[param_t[0]][param_t[1]](opq, 1);
}
}
 
 
DEF_1T_OP(imm_gen_op, l_sflts_imm_t_table, gen_op_sflts_imm);
DEF_1T_OP(imm_gen_op, l_sflts_imm_t_table, gen_op_sflts_imm);
DEF_2T_OP(generic_gen_op, l_sflts_t_table, gen_op_sflts);
DEF_2T_OP(generic_gen_op, l_sflts_t_table, gen_op_sflts);
 
 
void gen_l_sflts(struct op_queue *opq, int param_t[3], int delay_slot)
void gen_l_sflts(struct op_queue *opq, int param_t[3], int delay_slot)
{
{
  if(!opq->param[0] && !opq->param[1]) {
  if(!opq->param[0] && !opq->param[1]) {
    gen_op_clear_flag(opq, 1);
    gen_op_clear_flag(opq, 1);
    return;
    return;
  }
  }
 
 
  if(!opq->param[0]) {
  if(!opq->param[0]) {
    /* sfgts IS correct */
    /* sfgts IS correct */
    if(param_t[1] == T_NONE) {
    if(param_t[1] == T_NONE) {
      if(0 < (orreg_t)opq->param[1])
      if(0 < (orreg_t)opq->param[1])
        gen_op_set_flag(opq, 1);
        gen_op_set_flag(opq, 1);
      else
      else
        gen_op_clear_flag(opq, 1);
        gen_op_clear_flag(opq, 1);
    } else
    } else
      l_sfgts_null_t_table[param_t[1]](opq, 1);
      l_sfgts_null_t_table[param_t[1]](opq, 1);
    return;
    return;
  }
  }
 
 
  if(!opq->param[1]) {
  if(!opq->param[1]) {
    l_sflts_null_t_table[param_t[0]](opq, 1);
    l_sflts_null_t_table[param_t[0]](opq, 1);
    return;
    return;
  }
  }
 
 
  if(param_t[1] == T_NONE)
  if(param_t[1] == T_NONE)
    l_sflts_imm_t_table[param_t[0]](opq, 1, opq->param[1]);
    l_sflts_imm_t_table[param_t[0]](opq, 1, opq->param[1]);
  else
  else
    l_sflts_t_table[param_t[0]][param_t[1]](opq, 1);
    l_sflts_t_table[param_t[0]][param_t[1]](opq, 1);
}
}
 
 
DEF_1T_OP(imm_gen_op, l_sfltu_imm_t_table, gen_op_sfltu_imm);
DEF_1T_OP(imm_gen_op, l_sfltu_imm_t_table, gen_op_sfltu_imm);
DEF_2T_OP(generic_gen_op, l_sfltu_t_table, gen_op_sfltu);
DEF_2T_OP(generic_gen_op, l_sfltu_t_table, gen_op_sfltu);
 
 
void gen_l_sfltu(struct op_queue *opq, int param_t[3], int delay_slot)
void gen_l_sfltu(struct op_queue *opq, int param_t[3], int delay_slot)
{
{
  if(!opq->param[0] && !opq->param[1]) {
  if(!opq->param[0] && !opq->param[1]) {
    gen_op_clear_flag(opq, 1);
    gen_op_clear_flag(opq, 1);
    return;
    return;
  }
  }
 
 
  if(!opq->param[0]) {
  if(!opq->param[0]) {
    /* sfgtu IS correct */
    /* sfgtu IS correct */
    if(param_t[1] == T_NONE) {
    if(param_t[1] == T_NONE) {
      if(0 < opq->param[1])
      if(0 < opq->param[1])
        gen_op_set_flag(opq, 1);
        gen_op_set_flag(opq, 1);
      else
      else
        gen_op_clear_flag(opq, 1);
        gen_op_clear_flag(opq, 1);
    } else
    } else
      l_sfgtu_null_t_table[param_t[1]](opq, 1);
      l_sfgtu_null_t_table[param_t[1]](opq, 1);
    return;
    return;
  }
  }
 
 
  if(!opq->param[1]) {
  if(!opq->param[1]) {
    l_sfltu_null_t_table[param_t[0]](opq, 1);
    l_sfltu_null_t_table[param_t[0]](opq, 1);
    return;
    return;
  }
  }
 
 
  if(param_t[1] == T_NONE)
  if(param_t[1] == T_NONE)
    l_sfltu_imm_t_table[param_t[0]](opq, 1, opq->param[1]);
    l_sfltu_imm_t_table[param_t[0]](opq, 1, opq->param[1]);
  else
  else
    l_sfltu_t_table[param_t[0]][param_t[1]](opq, 1);
    l_sfltu_t_table[param_t[0]][param_t[1]](opq, 1);
}
}
 
 
DEF_1T_OP(generic_gen_op, l_sfne_null_t_table, gen_op_sfne_null);
DEF_1T_OP(generic_gen_op, l_sfne_null_t_table, gen_op_sfne_null);
DEF_1T_OP(imm_gen_op, l_sfne_imm_t_table, gen_op_sfne_imm);
DEF_1T_OP(imm_gen_op, l_sfne_imm_t_table, gen_op_sfne_imm);
DEF_2T_OP(generic_gen_op, l_sfne_t_table, gen_op_sfne);
DEF_2T_OP(generic_gen_op, l_sfne_t_table, gen_op_sfne);
 
 
void gen_l_sfne(struct op_queue *opq, int param_t[3], int delay_slot)
void gen_l_sfne(struct op_queue *opq, int param_t[3], int delay_slot)
{
{
  if(!opq->param[0] && !opq->param[1]) {
  if(!opq->param[0] && !opq->param[1]) {
    gen_op_set_flag(opq, 1);
    gen_op_set_flag(opq, 1);
    return;
    return;
  }
  }
 
 
  if(!opq->param[0]) {
  if(!opq->param[0]) {
    if(param_t[1] == T_NONE)
    if(param_t[1] == T_NONE)
      if(opq->param[1])
      if(opq->param[1])
        gen_op_set_flag(opq, 1);
        gen_op_set_flag(opq, 1);
      else
      else
        gen_op_clear_flag(opq, 1);
        gen_op_clear_flag(opq, 1);
    else
    else
      l_sfne_null_t_table[param_t[1]](opq, 1);
      l_sfne_null_t_table[param_t[1]](opq, 1);
    return;
    return;
  }
  }
 
 
  if(!opq->param[1]) {
  if(!opq->param[1]) {
    l_sfne_null_t_table[param_t[0]](opq, 1);
    l_sfne_null_t_table[param_t[0]](opq, 1);
    return;
    return;
  }
  }
 
 
  if(param_t[1] == T_NONE)
  if(param_t[1] == T_NONE)
    l_sfne_imm_t_table[param_t[0]](opq, 1, opq->param[1]);
    l_sfne_imm_t_table[param_t[0]](opq, 1, opq->param[1]);
  else
  else
    l_sfne_t_table[param_t[0]][param_t[1]](opq, 1);
    l_sfne_t_table[param_t[0]][param_t[1]](opq, 1);
}
}
 
 
DEF_2T_OP(imm_gen_op, l_sll_imm_t_table, gen_op_sll_imm);
DEF_2T_OP(imm_gen_op, l_sll_imm_t_table, gen_op_sll_imm);
DEF_3T_OP(generic_gen_op, l_sll_t_table, gen_op_sll);
DEF_3T_OP(generic_gen_op, l_sll_t_table, gen_op_sll);
 
 
void gen_l_sll(struct op_queue *opq, int param_t[3], int delay_slot)
void gen_l_sll(struct op_queue *opq, int param_t[3], int delay_slot)
{
{
  if(!opq->param[0])
  if(!opq->param[0])
    return;
    return;
 
 
  if(!opq->param[1]) {
  if(!opq->param[1]) {
    clear_t[param_t[0]](opq, 1);
    clear_t[param_t[0]](opq, 1);
    return;
    return;
  }
  }
 
 
  if(!opq->param[2]) {
  if(!opq->param[2]) {
    move_t_t[param_t[0]][param_t[1]](opq, 1);
    move_t_t[param_t[0]][param_t[1]](opq, 1);
    return;
    return;
  }
  }
 
 
  if(param_t[2] == T_NONE)
  if(param_t[2] == T_NONE)
    l_sll_imm_t_table[param_t[0]][param_t[1]](opq, 1, opq->param[2]);
    l_sll_imm_t_table[param_t[0]][param_t[1]](opq, 1, opq->param[2]);
  else
  else
    l_sll_t_table[param_t[0]][param_t[1]][param_t[2]](opq, 1);
    l_sll_t_table[param_t[0]][param_t[1]][param_t[2]](opq, 1);
}
}
 
 
DEF_2T_OP(imm_gen_op, l_sra_imm_t_table, gen_op_sra_imm);
DEF_2T_OP(imm_gen_op, l_sra_imm_t_table, gen_op_sra_imm);
DEF_3T_OP(generic_gen_op, l_sra_t_table, gen_op_sra);
DEF_3T_OP(generic_gen_op, l_sra_t_table, gen_op_sra);
 
 
void gen_l_sra(struct op_queue *opq, int param_t[3], int delay_slot)
void gen_l_sra(struct op_queue *opq, int param_t[3], int delay_slot)
{
{
  if(!opq->param[0])
  if(!opq->param[0])
    return;
    return;
 
 
  if(!opq->param[1]) {
  if(!opq->param[1]) {
    clear_t[param_t[0]](opq, 1);
    clear_t[param_t[0]](opq, 1);
    return;
    return;
  }
  }
 
 
  if(!opq->param[2]) {
  if(!opq->param[2]) {
    move_t_t[param_t[0]][param_t[1]](opq, 1);
    move_t_t[param_t[0]][param_t[1]](opq, 1);
    return;
    return;
  }
  }
 
 
  if(param_t[2] == T_NONE)
  if(param_t[2] == T_NONE)
    l_sra_imm_t_table[param_t[0]][param_t[1]](opq, 1, opq->param[2]);
    l_sra_imm_t_table[param_t[0]][param_t[1]](opq, 1, opq->param[2]);
  else
  else
    l_sra_t_table[param_t[0]][param_t[1]][param_t[2]](opq, 1);
    l_sra_t_table[param_t[0]][param_t[1]][param_t[2]](opq, 1);
}
}
 
 
DEF_2T_OP(imm_gen_op, l_srl_imm_t_table, gen_op_srl_imm);
DEF_2T_OP(imm_gen_op, l_srl_imm_t_table, gen_op_srl_imm);
DEF_3T_OP(generic_gen_op, l_srl_t_table, gen_op_srl);
DEF_3T_OP(generic_gen_op, l_srl_t_table, gen_op_srl);
 
 
void gen_l_srl(struct op_queue *opq, int param_t[3], int delay_slot)
void gen_l_srl(struct op_queue *opq, int param_t[3], int delay_slot)
{
{
  if(!opq->param[0])
  if(!opq->param[0])
    return;
    return;
 
 
  if(!opq->param[1]) {
  if(!opq->param[1]) {
    clear_t[param_t[0]](opq, 1);
    clear_t[param_t[0]](opq, 1);
    return;
    return;
  }
  }
 
 
  if(!opq->param[2]) {
  if(!opq->param[2]) {
    move_t_t[param_t[0]][param_t[1]](opq, 1);
    move_t_t[param_t[0]][param_t[1]](opq, 1);
    return;
    return;
  }
  }
 
 
  if(param_t[2] == T_NONE)
  if(param_t[2] == T_NONE)
    l_srl_imm_t_table[param_t[0]][param_t[1]](opq, 1, opq->param[2]);
    l_srl_imm_t_table[param_t[0]][param_t[1]](opq, 1, opq->param[2]);
  else
  else
    l_srl_t_table[param_t[0]][param_t[1]][param_t[2]](opq, 1);
    l_srl_t_table[param_t[0]][param_t[1]][param_t[2]](opq, 1);
}
}
 
 
DEF_2T_OP(generic_gen_op, l_neg_t_table, gen_op_neg);
DEF_2T_OP(generic_gen_op, l_neg_t_table, gen_op_neg);
DEF_3T_OP(generic_gen_op, l_sub_t_table, gen_op_sub);
DEF_3T_OP(generic_gen_op, l_sub_t_table, gen_op_sub);
 
 
void gen_l_sub(struct op_queue *opq, int param_t[3], int delay_slot)
void gen_l_sub(struct op_queue *opq, int param_t[3], int delay_slot)
{
{
  if(!opq->param[0])
  if(!opq->param[0])
    return;
    return;
 
 
  if((param_t[2] != T_NONE) && (opq->param[1] == opq->param[2])) {
  if((param_t[2] != T_NONE) && (opq->param[1] == opq->param[2])) {
    clear_t[param_t[0]](opq, 1);
    clear_t[param_t[0]](opq, 1);
    return;
    return;
  }
  }
 
 
  if(!opq->param[1] && !opq->param[2]) {
  if(!opq->param[1] && !opq->param[2]) {
    clear_t[param_t[0]](opq, 1);
    clear_t[param_t[0]](opq, 1);
    return;
    return;
  }
  }
 
 
  if(!opq->param[1]) {
  if(!opq->param[1]) {
    if(param_t[2] == T_NONE)
    if(param_t[2] == T_NONE)
      mov_t_imm[param_t[0]](opq, 1, -opq->param[2]);
      mov_t_imm[param_t[0]](opq, 1, -opq->param[2]);
    else
    else
      l_neg_t_table[param_t[0]][param_t[2]](opq, 1);
      l_neg_t_table[param_t[0]][param_t[2]](opq, 1);
    return;
    return;
  }
  }
 
 
  if(!opq->param[2]) {
  if(!opq->param[2]) {
    move_t_t[param_t[0]][param_t[1]](opq, 1);
    move_t_t[param_t[0]][param_t[1]](opq, 1);
    return;
    return;
  }
  }
 
 
  l_sub_t_table[param_t[0]][param_t[1]][param_t[2]](opq, 1);
  l_sub_t_table[param_t[0]][param_t[1]][param_t[2]](opq, 1);
}
}
 
 
/* FIXME: This will not work if the l.sys is in a delay slot */
/* FIXME: This will not work if the l.sys is in a delay slot */
void gen_l_sys(struct op_queue *opq, int param_t[3], int delay_slot)
void gen_l_sys(struct op_queue *opq, int param_t[3], int delay_slot)
{
{
  if(do_stats)
  if(do_stats)
    /* All gprs are current since this insn doesn't touch any reg */
    /* All gprs are current since this insn doesn't touch any reg */
    gen_op_analysis(opq, 1);
    gen_op_analysis(opq, 1);
 
 
  if(!delay_slot)
  if(!delay_slot)
    gen_op_prep_sys(opq, 1);
    gen_op_prep_sys(opq, 1);
  else
  else
    gen_op_prep_sys_delay(opq, 1);
    gen_op_prep_sys_delay(opq, 1);
 
 
  gen_op_do_sched(opq, 1);
  gen_op_do_sched(opq, 1);
  gen_op_do_jump(opq, 1);
  gen_op_do_jump(opq, 1);
}
}
 
 
/* FIXME: This will not work if the l.trap is in a delay slot */
/* FIXME: This will not work if the l.trap is in a delay slot */
void gen_l_trap(struct op_queue *opq, int param_t[3], int delay_slot)
void gen_l_trap(struct op_queue *opq, int param_t[3], int delay_slot)
{
{
  if(do_stats)
  if(do_stats)
    /* All gprs are current since this insn doesn't touch any reg */
    /* All gprs are current since this insn doesn't touch any reg */
    gen_op_analysis(opq, 1);
    gen_op_analysis(opq, 1);
 
 
  if(!delay_slot)
  if(!delay_slot)
    gen_op_prep_trap(opq, 1);
    gen_op_prep_trap(opq, 1);
  else
  else
    gen_op_prep_trap_delay(opq, 1);
    gen_op_prep_trap_delay(opq, 1);
}
}
 
 
DEF_2T_OP(imm_gen_op, l_xor_imm_t_table, gen_op_xor_imm);
DEF_2T_OP(imm_gen_op, l_xor_imm_t_table, gen_op_xor_imm);
/* FIXME: Make unused elements NULL */
/* FIXME: Make unused elements NULL */
DEF_3T_OP_NEQ(generic_gen_op, l_xor_t_table, gen_op_xor);
DEF_3T_OP_NEQ(generic_gen_op, l_xor_t_table, gen_op_xor);
 
 
void gen_l_xor(struct op_queue *opq, int param_t[3], int delay_slot)
void gen_l_xor(struct op_queue *opq, int param_t[3], int delay_slot)
{
{
  if(!opq->param[0])
  if(!opq->param[0])
    return;
    return;
 
 
  if((param_t[2] != T_NONE) && (opq->param[1] == opq->param[2])) {
  if((param_t[2] != T_NONE) && (opq->param[1] == opq->param[2])) {
    clear_t[param_t[0]](opq, 1);
    clear_t[param_t[0]](opq, 1);
    return;
    return;
  }
  }
 
 
  if(!opq->param[2]) {
  if(!opq->param[2]) {
    if((param_t[2] == T_NONE) && (opq->param[0] == opq->param[1]))
    if((param_t[2] == T_NONE) && (opq->param[0] == opq->param[1]))
      return;
      return;
    move_t_t[param_t[0]][param_t[1]](opq, 1);
    move_t_t[param_t[0]][param_t[1]](opq, 1);
    return;
    return;
  }
  }
 
 
  if(!opq->param[1]) {
  if(!opq->param[1]) {
    if(param_t[2] == T_NONE) {
    if(param_t[2] == T_NONE) {
      mov_t_imm[param_t[0]](opq, 1, opq->param[2]);
      mov_t_imm[param_t[0]](opq, 1, opq->param[2]);
      return;
      return;
    }
    }
    move_t_t[param_t[0]][param_t[2]](opq, 1);
    move_t_t[param_t[0]][param_t[2]](opq, 1);
    return;
    return;
  }
  }
 
 
  if(param_t[2] == T_NONE)
  if(param_t[2] == T_NONE)
    l_xor_imm_t_table[param_t[0]][param_t[1]](opq, 1, opq->param[2]);
    l_xor_imm_t_table[param_t[0]][param_t[1]](opq, 1, opq->param[2]);
  else
  else
    l_xor_t_table[param_t[0]][param_t[1]][param_t[2]](opq, 1);
    l_xor_t_table[param_t[0]][param_t[1]][param_t[2]](opq, 1);
}
}
 
 
void gen_l_invalid(struct op_queue *opq, int param_t[3], int delay_slot)
void gen_l_invalid(struct op_queue *opq, int param_t[3], int delay_slot)
{
{
  if(!delay_slot) {
  if(!delay_slot) {
    gen_op_illegal(opq, 1);
    gen_op_illegal(opq, 1);
    gen_op_do_jump(opq, 1);
    gen_op_do_jump(opq, 1);
  } else {
  } else {
    gen_op_illegal_delay(opq, 1);
    gen_op_illegal_delay(opq, 1);
    gen_op_do_jump(opq, 1);
    gen_op_do_jump(opq, 1);
  }
  }
}
}
 
 
/*----------------------------------[ Floating point instructions (stubs) ]---*/
/*----------------------------------[ Floating point instructions (stubs) ]---*/
void gen_lf_add_s(struct op_queue *opq, int param_t[3], int delay_slot)
void gen_lf_add_s(struct op_queue *opq, int param_t[3], int delay_slot)
{
{
  gen_l_invalid(opq, param_t, delay_slot);
  gen_l_invalid(opq, param_t, delay_slot);
}
}
 
 
void gen_lf_div_s(struct op_queue *opq, int param_t[3], int delay_slot)
void gen_lf_div_s(struct op_queue *opq, int param_t[3], int delay_slot)
{
{
  gen_l_invalid(opq, param_t, delay_slot);
  gen_l_invalid(opq, param_t, delay_slot);
}
}
 
 
void gen_lf_ftoi_s(struct op_queue *opq, int param_t[3], int delay_slot)
void gen_lf_ftoi_s(struct op_queue *opq, int param_t[3], int delay_slot)
{
{
  gen_l_invalid(opq, param_t, delay_slot);
  gen_l_invalid(opq, param_t, delay_slot);
}
}
 
 
void gen_lf_itof_s(struct op_queue *opq, int param_t[3], int delay_slot)
void gen_lf_itof_s(struct op_queue *opq, int param_t[3], int delay_slot)
{
{
  gen_l_invalid(opq, param_t, delay_slot);
  gen_l_invalid(opq, param_t, delay_slot);
}
}
 
 
void gen_lf_madd_s(struct op_queue *opq, int param_t[3], int delay_slot)
void gen_lf_madd_s(struct op_queue *opq, int param_t[3], int delay_slot)
{
{
  gen_l_invalid(opq, param_t, delay_slot);
  gen_l_invalid(opq, param_t, delay_slot);
}
}
 
 
void gen_lf_mul_s(struct op_queue *opq, int param_t[3], int delay_slot)
void gen_lf_mul_s(struct op_queue *opq, int param_t[3], int delay_slot)
{
{
  gen_l_invalid(opq, param_t, delay_slot);
  gen_l_invalid(opq, param_t, delay_slot);
}
}
 
 
void gen_lf_rem_s(struct op_queue *opq, int param_t[3], int delay_slot)
void gen_lf_rem_s(struct op_queue *opq, int param_t[3], int delay_slot)
{
{
  gen_l_invalid(opq, param_t, delay_slot);
  gen_l_invalid(opq, param_t, delay_slot);
}
}
 
 
void gen_lf_sfeq_s(struct op_queue *opq, int param_t[3], int delay_slot)
void gen_lf_sfeq_s(struct op_queue *opq, int param_t[3], int delay_slot)
{
{
  gen_l_invalid(opq, param_t, delay_slot);
  gen_l_invalid(opq, param_t, delay_slot);
}
}
 
 
void gen_lf_sfge_s(struct op_queue *opq, int param_t[3], int delay_slot)
void gen_lf_sfge_s(struct op_queue *opq, int param_t[3], int delay_slot)
{
{
  gen_l_invalid(opq, param_t, delay_slot);
  gen_l_invalid(opq, param_t, delay_slot);
}
}
 
 
void gen_lf_sfgt_s(struct op_queue *opq, int param_t[3], int delay_slot)
void gen_lf_sfgt_s(struct op_queue *opq, int param_t[3], int delay_slot)
{
{
  gen_l_invalid(opq, param_t, delay_slot);
  gen_l_invalid(opq, param_t, delay_slot);
}
}
 
 
void gen_lf_sfle_s(struct op_queue *opq, int param_t[3], int delay_slot)
void gen_lf_sfle_s(struct op_queue *opq, int param_t[3], int delay_slot)
{
{
  gen_l_invalid(opq, param_t, delay_slot);
  gen_l_invalid(opq, param_t, delay_slot);
}
}
 
 
void gen_lf_sflt_s(struct op_queue *opq, int param_t[3], int delay_slot)
void gen_lf_sflt_s(struct op_queue *opq, int param_t[3], int delay_slot)
{
{
  gen_l_invalid(opq, param_t, delay_slot);
  gen_l_invalid(opq, param_t, delay_slot);
}
}
 
 
void gen_lf_sfne_s(struct op_queue *opq, int param_t[3], int delay_slot)
void gen_lf_sfne_s(struct op_queue *opq, int param_t[3], int delay_slot)
{
{
  gen_l_invalid(opq, param_t, delay_slot);
  gen_l_invalid(opq, param_t, delay_slot);
}
}
 
 
void gen_lf_sub_s(struct op_queue *opq, int param_t[3], int delay_slot)
void gen_lf_sub_s(struct op_queue *opq, int param_t[3], int delay_slot)
{
{
  gen_l_invalid(opq, param_t, delay_slot);
  gen_l_invalid(opq, param_t, delay_slot);
}
}
 
 
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.