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

Subversion Repositories or1k

[/] [or1k/] [tags/] [nog_patch_47/] [or1ksim/] [cpu/] [or32/] [execute.c] - Diff between revs 1419 and 1765

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

Rev 1419 Rev 1765
/* execute.c -- OR1K architecture dependent simulation
/* execute.c -- OR1K architecture dependent simulation
   Copyright (C) 1999 Damjan Lampret, lampret@opencores.org
   Copyright (C) 1999 Damjan Lampret, lampret@opencores.org
   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. */
 
 
/* Most of the OR1K simulation is done in here.
/* Most of the OR1K simulation is done in here.
 
 
   When SIMPLE_EXECUTION is defined below a file insnset.c is included!
   When SIMPLE_EXECUTION is defined below a file insnset.c is included!
*/
*/
 
 
#include <stdlib.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdio.h>
#include <string.h>
#include <string.h>
#include <ctype.h>
#include <ctype.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 "branch_predict.h"
#include "branch_predict.h"
#include "abstract.h"
#include "abstract.h"
#include "labels.h"
#include "labels.h"
#include "parse.h"
#include "parse.h"
#include "execute.h"
#include "execute.h"
#include "except.h"
#include "except.h"
#include "sprs.h"
#include "sprs.h"
#include "sim-config.h"
#include "sim-config.h"
#include "debug_unit.h"
#include "debug_unit.h"
#include "opcode/or32.h"
#include "opcode/or32.h"
#include "immu.h"
#include "immu.h"
#include "dmmu.h"
#include "dmmu.h"
#include "debug.h"
#include "debug.h"
#include "stats.h"
#include "stats.h"
 
 
/* General purpose registers. */
/* General purpose registers. */
uorreg_t reg[MAX_GPRS];
uorreg_t reg[MAX_GPRS];
 
 
/* Instruction queue */
/* Instruction queue */
struct iqueue_entry iqueue[20];
struct iqueue_entry iqueue[20];
 
 
/* Is current insn in execution a delay insn? */
/* Is current insn in execution a delay insn? */
int delay_insn;
int delay_insn;
 
 
/* Benchmark multi issue execution */
/* Benchmark multi issue execution */
int multissue[20];
int multissue[20];
int issued_per_cycle = 4;
int issued_per_cycle = 4;
 
 
/* Completition queue */
/* Completition queue */
struct iqueue_entry icomplet[20];
struct iqueue_entry icomplet[20];
 
 
/* Program counter (and translated PC) */
/* Program counter (and translated PC) */
oraddr_t pc;
oraddr_t pc;
 
 
/* Previous program counter */
/* Previous program counter */
oraddr_t pcprev = 0;
oraddr_t pcprev = 0;
 
 
/* Temporary program counter */
/* Temporary program counter */
oraddr_t pcnext;
oraddr_t pcnext;
 
 
/* Delay instruction effective address register */
/* Delay instruction effective address register */
oraddr_t pcdelay;
oraddr_t pcdelay;
 
 
/* CCR */
/* CCR */
int flag;
int flag;
 
 
/* Store buffer analysis - stores are accumulated and commited when IO is idle */
/* Store buffer analysis - stores are accumulated and commited when IO is idle */
static int sbuf_head = 0, sbuf_tail = 0, sbuf_count = 0;
static int sbuf_head = 0, sbuf_tail = 0, sbuf_count = 0;
static int sbuf_buf[MAX_SBUF_LEN] = {0};
static int sbuf_buf[MAX_SBUF_LEN] = {0};
static int sbuf_prev_cycles = 0;
static int sbuf_prev_cycles = 0;
 
 
/* Num cycles waiting for stores to complete */
/* Num cycles waiting for stores to complete */
int sbuf_wait_cyc = 0;
int sbuf_wait_cyc = 0;
 
 
/* Number of total store cycles */
/* Number of total store cycles */
int sbuf_total_cyc = 0;
int sbuf_total_cyc = 0;
 
 
/* Whether we are doing statistical analysis */
/* Whether we are doing statistical analysis */
int do_stats = 0;
int do_stats = 0;
 
 
/* Local data needed for execution.  */
/* Local data needed for execution.  */
static int next_delay_insn;
static int next_delay_insn;
static int breakpoint;
static int breakpoint;
 
 
/* Effective address of instructions that have an effective address.  This is
/* Effective address of instructions that have an effective address.  This is
 * only used to get dump_exe_log correct */
 * only used to get dump_exe_log correct */
static oraddr_t insn_ea;
static oraddr_t insn_ea;
 
 
/* History of execution */
/* History of execution */
struct hist_exec *hist_exec_tail = NULL;
struct hist_exec *hist_exec_tail = NULL;
 
 
/* Implementation specific.
/* Implementation specific.
   Get an actual value of a specific register. */
   Get an actual value of a specific register. */
 
 
uorreg_t evalsim_reg(unsigned int regno)
uorreg_t evalsim_reg(unsigned int regno)
{
{
  if (regno < MAX_GPRS) {
  if (regno < MAX_GPRS) {
    return reg[regno];
    return reg[regno];
  } else {
  } else {
    PRINTF("\nABORT: read out of registers\n");
    PRINTF("\nABORT: read out of registers\n");
    runtime.sim.cont_run = 0;
    runtime.sim.cont_run = 0;
    return 0;
    return 0;
  }
  }
}
}
 
 
/* Implementation specific.
/* Implementation specific.
   Set a specific register with value. */
   Set a specific register with value. */
 
 
void setsim_reg(unsigned int regno, uorreg_t value)
void setsim_reg(unsigned int regno, uorreg_t value)
{
{
  if (regno == 0)               /* gpr0 is always zero */
  if (regno == 0)               /* gpr0 is always zero */
    value = 0;
    value = 0;
 
 
  if (regno < MAX_GPRS) {
  if (regno < MAX_GPRS) {
    reg[regno] = value;
    reg[regno] = value;
  } else {
  } else {
    PRINTF("\nABORT: write out of registers\n");
    PRINTF("\nABORT: write out of registers\n");
    runtime.sim.cont_run = 0;
    runtime.sim.cont_run = 0;
  }
  }
}
}
 
 
/* Implementation specific.
/* Implementation specific.
   Set a specific register with value. */
   Set a specific register with value. */
 
 
inline static void set_reg(int regno, uorreg_t value)
inline static void set_reg(int regno, uorreg_t value)
{
{
#if 0   
#if 0   
  if (strcmp(regstr, FRAME_REG) == 0) {
  if (strcmp(regstr, FRAME_REG) == 0) {
    PRINTF("FP (%s) modified by insn at %x. ", FRAME_REG, pc);
    PRINTF("FP (%s) modified by insn at %x. ", FRAME_REG, pc);
    PRINTF("Old:%.8lx  New:%.8lx\n", eval_reg(regno), value);
    PRINTF("Old:%.8lx  New:%.8lx\n", eval_reg(regno), value);
  }
  }
 
 
  if (strcmp(regstr, STACK_REG) == 0) {
  if (strcmp(regstr, STACK_REG) == 0) {
    PRINTF("SP (%s) modified by insn at %x. ", STACK_REG, pc);
    PRINTF("SP (%s) modified by insn at %x. ", STACK_REG, pc);
    PRINTF("Old:%.8lx  New:%.8lx\n", eval_reg(regno), value);
    PRINTF("Old:%.8lx  New:%.8lx\n", eval_reg(regno), value);
  }
  }
#endif
#endif
 
 
  if (regno < MAX_GPRS) {
  if (regno < MAX_GPRS) {
    reg[regno] = value;
    reg[regno] = value;
#if RAW_RANGE_STATS
#if RAW_RANGE_STATS
    raw_stats.reg[regno] = runtime.sim.cycles;
    raw_stats.reg[regno] = runtime.sim.cycles;
#endif /* RAW_RANGE */
#endif /* RAW_RANGE */
  } else {
  } else {
    PRINTF("\nABORT: write out of registers\n");
    PRINTF("\nABORT: write out of registers\n");
    runtime.sim.cont_run = 0;
    runtime.sim.cont_run = 0;
  }
  }
}
}
 
 
/* Implementation specific.
/* Implementation specific.
   Evaluates source operand opd. */
   Evaluates source operand opd. */
 
 
static uorreg_t eval_operand_val(uint32_t insn, struct insn_op_struct *opd)
static uorreg_t eval_operand_val(uint32_t insn, struct insn_op_struct *opd)
{
{
  unsigned long operand = 0;
  unsigned long operand = 0;
  unsigned long sbit;
  unsigned long sbit;
  unsigned int nbits = 0;
  unsigned int nbits = 0;
 
 
  while(1) {
  while(1) {
    operand |= ((insn >> (opd->type & OPTYPE_SHR)) & ((1 << opd->data) - 1)) << nbits;
    operand |= ((insn >> (opd->type & OPTYPE_SHR)) & ((1 << opd->data) - 1)) << nbits;
    nbits += opd->data;
    nbits += opd->data;
 
 
    if(opd->type & OPTYPE_OP)
    if(opd->type & OPTYPE_OP)
      break;
      break;
    opd++;
    opd++;
  }
  }
 
 
  if(opd->type & OPTYPE_SIG) {
  if(opd->type & OPTYPE_SIG) {
    sbit = (opd->type & OPTYPE_SBIT) >> OPTYPE_SBIT_SHR;
    sbit = (opd->type & OPTYPE_SBIT) >> OPTYPE_SBIT_SHR;
    if(operand & (1 << sbit)) operand |= ~REG_C(0) << sbit;
    if(operand & (1 << sbit)) operand |= ~REG_C(0) << sbit;
  }
  }
 
 
  return operand;
  return operand;
}
}
 
 
/* Does source operand depend on computation of dstoperand? Return
/* Does source operand depend on computation of dstoperand? Return
   non-zero if yes.
   non-zero if yes.
 
 
 Cycle t                 Cycle t+1
 Cycle t                 Cycle t+1
dst: irrelevant         src: immediate                  always 0
dst: irrelevant         src: immediate                  always 0
dst: reg1 direct        src: reg2 direct                0 if reg1 != reg2
dst: reg1 direct        src: reg2 direct                0 if reg1 != reg2
dst: reg1 disp          src: reg2 direct                always 0
dst: reg1 disp          src: reg2 direct                always 0
dst: reg1 direct        src: reg2 disp                  0 if reg1 != reg2
dst: reg1 direct        src: reg2 disp                  0 if reg1 != reg2
dst: reg1 disp          src: reg2 disp                  always 1 (store must
dst: reg1 disp          src: reg2 disp                  always 1 (store must
                                                        finish before load)
                                                        finish before load)
dst: flag               src: flag                       always 1
dst: flag               src: flag                       always 1
*/
*/
 
 
int depend_operands(prev, next)
int depend_operands(prev, next)
     struct iqueue_entry *prev;
     struct iqueue_entry *prev;
     struct iqueue_entry *next;
     struct iqueue_entry *next;
{
{
  /* Find destination type. */
  /* Find destination type. */
  unsigned long type = 0;
  unsigned long type = 0;
  int prev_dis, next_dis;
  int prev_dis, next_dis;
  orreg_t prev_reg_val = 0;
  orreg_t prev_reg_val = 0;
  struct insn_op_struct *opd;
  struct insn_op_struct *opd;
 
 
  if (or32_opcodes[prev->insn_index].flags & OR32_W_FLAG
  if (or32_opcodes[prev->insn_index].flags & OR32_W_FLAG
      && or32_opcodes[next->insn_index].flags & OR32_R_FLAG)
      && or32_opcodes[next->insn_index].flags & OR32_R_FLAG)
    return 1;
    return 1;
 
 
  opd = op_start[prev->insn_index];
  opd = op_start[prev->insn_index];
  prev_dis = 0;
  prev_dis = 0;
 
 
  while (1) {
  while (1) {
    if (opd->type & OPTYPE_DIS)
    if (opd->type & OPTYPE_DIS)
      prev_dis = 1;
      prev_dis = 1;
 
 
    if (opd->type & OPTYPE_DST) {
    if (opd->type & OPTYPE_DST) {
      type = opd->type;
      type = opd->type;
      if (prev_dis)
      if (prev_dis)
        type |= OPTYPE_DIS;
        type |= OPTYPE_DIS;
      /* Destination is always a register */
      /* Destination is always a register */
      prev_reg_val = eval_operand_val (prev->insn, opd);
      prev_reg_val = eval_operand_val (prev->insn, opd);
      break;
      break;
    }
    }
    if (opd->type & OPTYPE_LAST)
    if (opd->type & OPTYPE_LAST)
      return 0; /* Doesn't have a destination operand */
      return 0; /* Doesn't have a destination operand */
    if (opd->type & OPTYPE_OP)
    if (opd->type & OPTYPE_OP)
      prev_dis = 0;
      prev_dis = 0;
    opd++;
    opd++;
  }
  }
 
 
  /* We search all source operands - if we find confict => return 1 */
  /* We search all source operands - if we find confict => return 1 */
  opd = op_start[next->insn_index];
  opd = op_start[next->insn_index];
  next_dis = 0;
  next_dis = 0;
 
 
  while (1) {
  while (1) {
    if (opd->type & OPTYPE_DIS)
    if (opd->type & OPTYPE_DIS)
      next_dis = 1;
      next_dis = 1;
    /* This instruction sequence also depends on order of execution:
    /* This instruction sequence also depends on order of execution:
     * l.lw r1, k(r1)
     * l.lw r1, k(r1)
     * l.sw k(r1), r4
     * l.sw k(r1), r4
     * Here r1 is a destination in l.sw */
     * Here r1 is a destination in l.sw */
    /* FIXME: This situation is not handeld here when r1 == r2:
    /* FIXME: This situation is not handeld here when r1 == r2:
     * l.sw k(r1), r4
     * l.sw k(r1), r4
     * l.lw r3, k(r2)
     * l.lw r3, k(r2)
     */
     */
    if (!(opd->type & OPTYPE_DST) || (next_dis && (opd->type & OPTYPE_DST))) {
    if (!(opd->type & OPTYPE_DST) || (next_dis && (opd->type & OPTYPE_DST))) {
      if (opd->type & OPTYPE_REG)
      if (opd->type & OPTYPE_REG)
        if (eval_operand_val (next->insn, opd) == prev_reg_val)
        if (eval_operand_val (next->insn, opd) == prev_reg_val)
          return 1;
          return 1;
    }
    }
    if (opd->type & OPTYPE_LAST)
    if (opd->type & OPTYPE_LAST)
      break;
      break;
    opd++;
    opd++;
  }
  }
 
 
  return 0;
  return 0;
}
}
 
 
/* Sets a new SPR_SR_OV value, based on next register value */
/* Sets a new SPR_SR_OV value, based on next register value */
 
 
#if SET_OV_FLAG
#if SET_OV_FLAG
#define set_ov_flag(value) if((value) & 0x80000000) setsprbits (SPR_SR, SPR_SR_OV, 1); else setsprbits (SPR_SR, SPR_SR_OV, 0)
#define set_ov_flag(value) if((value) & 0x80000000) setsprbits (SPR_SR, SPR_SR_OV, 1); else setsprbits (SPR_SR, SPR_SR_OV, 0)
#else
#else
#define set_ov_flag(value)
#define set_ov_flag(value)
#endif
#endif
 
 
/* Modified by CZ 26/05/01 for new mode execution */
/* Modified by CZ 26/05/01 for new mode execution */
/* Fetch returns nonzero if instruction should NOT be executed.  */
/* Fetch returns nonzero if instruction should NOT be executed.  */
static inline int fetch()
static inline int fetch()
{
{
  static int break_just_hit = 0;
  static int break_just_hit = 0;
 
 
  if (CHECK_BREAKPOINTS) {
  if (CHECK_BREAKPOINTS) {
    /* MM: Check for breakpoint.  This has to be done in fetch cycle,
    /* MM: Check for breakpoint.  This has to be done in fetch cycle,
       because of peripheria.
       because of peripheria.
       MM1709: if we cannot access the memory entry, we could not set the
       MM1709: if we cannot access the memory entry, we could not set the
       breakpoint earlier, so just check the breakpoint list.  */
       breakpoint earlier, so just check the breakpoint list.  */
    if (has_breakpoint (peek_into_itlb (pc)) && !break_just_hit) {
    if (has_breakpoint (peek_into_itlb (pc)) && !break_just_hit) {
      break_just_hit = 1;
      break_just_hit = 1;
      return 1; /* Breakpoint set. */
      return 1; /* Breakpoint set. */
    }
    }
    break_just_hit = 0;
    break_just_hit = 0;
  }
  }
 
 
  breakpoint = 0;
  breakpoint = 0;
  /* Fetch instruction. */
  /* Fetch instruction. */
  iqueue[0].insn_addr = pc;
  iqueue[0].insn_addr = pc;
  iqueue[0].insn = eval_insn (pc, &breakpoint);
  iqueue[0].insn = eval_insn (pc, &breakpoint);
 
 
  if (!except_pending)
  if (!except_pending)
    runtime.cpu.instructions++;
    runtime.cpu.instructions++;
 
 
  /* update_pc will be called after execution */
  /* update_pc will be called after execution */
 
 
  return 0;
  return 0;
}
}
 
 
/* This code actually updates the PC value.  */
/* This code actually updates the PC value.  */
static inline void update_pc ()
static inline void update_pc ()
{
{
  delay_insn = next_delay_insn;
  delay_insn = next_delay_insn;
  pcprev = pc; /* Store value for later */
  pcprev = pc; /* Store value for later */
  pc = pcnext;
  pc = pcnext;
  pcnext = delay_insn ? pcdelay : pcnext + 4;
  pcnext = delay_insn ? pcdelay : pcnext + 4;
}
}
 
 
#if SIMPLE_EXECUTION
#if SIMPLE_EXECUTION
static inline
static inline
#endif
#endif
void analysis (struct iqueue_entry *current)
void analysis (struct iqueue_entry *current)
{
{
  if (config.cpu.dependstats) {
  if (config.cpu.dependstats) {
    /* Dynamic, dependency stats. */
    /* Dynamic, dependency stats. */
    adddstats(icomplet[0].insn_index, current->insn_index, 1, check_depend());
    adddstats(icomplet[0].insn_index, current->insn_index, 1, check_depend());
 
 
    /* Dynamic, functional units stats. */
    /* Dynamic, functional units stats. */
    addfstats(or32_opcodes[icomplet[0].insn_index].func_unit,
    addfstats(or32_opcodes[icomplet[0].insn_index].func_unit,
              or32_opcodes[current->insn_index].func_unit, 1, check_depend());
              or32_opcodes[current->insn_index].func_unit, 1, check_depend());
 
 
    /* Dynamic, single stats. */
    /* Dynamic, single stats. */
    addsstats(current->insn_index, 1);
    addsstats(current->insn_index, 1);
  }
  }
 
 
  if (config.cpu.superscalar) {
  if (config.cpu.superscalar) {
    if ((or32_opcodes[current->insn_index].func_unit == it_branch) ||
    if ((or32_opcodes[current->insn_index].func_unit == it_branch) ||
        (or32_opcodes[current->insn_index].func_unit == it_jump))
        (or32_opcodes[current->insn_index].func_unit == it_jump))
      runtime.sim.storecycles += 0;
      runtime.sim.storecycles += 0;
 
 
    if (or32_opcodes[current->insn_index].func_unit == it_store)
    if (or32_opcodes[current->insn_index].func_unit == it_store)
      runtime.sim.storecycles += 1;
      runtime.sim.storecycles += 1;
 
 
    if (or32_opcodes[current->insn_index].func_unit == it_load)
    if (or32_opcodes[current->insn_index].func_unit == it_load)
      runtime.sim.loadcycles += 1;
      runtime.sim.loadcycles += 1;
#if 0        
#if 0        
    if ((icomplet[0].func_unit == it_load) && check_depend())
    if ((icomplet[0].func_unit == it_load) && check_depend())
      runtime.sim.loadcycles++;
      runtime.sim.loadcycles++;
#endif
#endif
 
 
    /* Pseudo multiple issue benchmark */
    /* Pseudo multiple issue benchmark */
    if ((multissue[or32_opcodes[current->insn_index].func_unit] < 1) ||
    if ((multissue[or32_opcodes[current->insn_index].func_unit] < 1) ||
        (check_depend()) || (issued_per_cycle < 1)) {
        (check_depend()) || (issued_per_cycle < 1)) {
      int i;
      int i;
      for (i = 0; i < 20; i++)
      for (i = 0; i < 20; i++)
        multissue[i] = 2;
        multissue[i] = 2;
      issued_per_cycle = 2;
      issued_per_cycle = 2;
      runtime.cpu.supercycles++;
      runtime.cpu.supercycles++;
      if (check_depend())
      if (check_depend())
        runtime.cpu.hazardwait++;
        runtime.cpu.hazardwait++;
      multissue[it_unknown] = 2;
      multissue[it_unknown] = 2;
      multissue[it_shift] = 2;
      multissue[it_shift] = 2;
      multissue[it_compare] = 1;
      multissue[it_compare] = 1;
      multissue[it_branch] = 1;
      multissue[it_branch] = 1;
      multissue[it_jump] = 1;
      multissue[it_jump] = 1;
      multissue[it_extend] = 2;
      multissue[it_extend] = 2;
      multissue[it_nop] = 2;
      multissue[it_nop] = 2;
      multissue[it_move] = 2;
      multissue[it_move] = 2;
      multissue[it_movimm] = 2;
      multissue[it_movimm] = 2;
      multissue[it_arith] = 2;
      multissue[it_arith] = 2;
      multissue[it_store] = 2;
      multissue[it_store] = 2;
      multissue[it_load] = 2;
      multissue[it_load] = 2;
    }
    }
    multissue[or32_opcodes[current->insn_index].func_unit]--;
    multissue[or32_opcodes[current->insn_index].func_unit]--;
    issued_per_cycle--;
    issued_per_cycle--;
  }
  }
 
 
  if (config.cpu.dependstats)
  if (config.cpu.dependstats)
    /* Instruction waits in completition buffer until retired. */
    /* Instruction waits in completition buffer until retired. */
    memcpy (&icomplet[0], current, sizeof (struct iqueue_entry));
    memcpy (&icomplet[0], current, sizeof (struct iqueue_entry));
 
 
  if (config.sim.history) {
  if (config.sim.history) {
    /* History of execution */
    /* History of execution */
    hist_exec_tail = hist_exec_tail->next;
    hist_exec_tail = hist_exec_tail->next;
    hist_exec_tail->addr = icomplet[0].insn_addr;
    hist_exec_tail->addr = icomplet[0].insn_addr;
  }
  }
 
 
  if (config.sim.exe_log) dump_exe_log();
  if (config.sim.exe_log) dump_exe_log();
}
}
 
 
/* Store buffer analysis - stores are accumulated and commited when IO is idle */
/* Store buffer analysis - stores are accumulated and commited when IO is idle */
static inline void sbuf_store (int cyc) {
static inline void sbuf_store (int cyc) {
  int delta = runtime.sim.cycles - sbuf_prev_cycles;
  int delta = runtime.sim.cycles - sbuf_prev_cycles;
  sbuf_total_cyc += cyc;
  sbuf_total_cyc += cyc;
  sbuf_prev_cycles = runtime.sim.cycles;
  sbuf_prev_cycles = runtime.sim.cycles;
 
 
  //PRINTF (">STORE %i,%i,%i,%i,%i\n", delta, sbuf_count, sbuf_tail, sbuf_head, sbuf_buf[sbuf_tail], sbuf_buf[sbuf_head]);
  //PRINTF (">STORE %i,%i,%i,%i,%i\n", delta, sbuf_count, sbuf_tail, sbuf_head, sbuf_buf[sbuf_tail], sbuf_buf[sbuf_head]);
  //PRINTF ("|%i,%i\n", sbuf_total_cyc, sbuf_wait_cyc);
  //PRINTF ("|%i,%i\n", sbuf_total_cyc, sbuf_wait_cyc);
  /* Take stores from buffer, that occured meanwhile */
  /* Take stores from buffer, that occured meanwhile */
  while (sbuf_count && delta >= sbuf_buf[sbuf_tail]) {
  while (sbuf_count && delta >= sbuf_buf[sbuf_tail]) {
    delta -= sbuf_buf[sbuf_tail];
    delta -= sbuf_buf[sbuf_tail];
    sbuf_tail = (sbuf_tail + 1) % MAX_SBUF_LEN;
    sbuf_tail = (sbuf_tail + 1) % MAX_SBUF_LEN;
    sbuf_count--;
    sbuf_count--;
  }
  }
  if (sbuf_count)
  if (sbuf_count)
    sbuf_buf[sbuf_tail] -= delta;
    sbuf_buf[sbuf_tail] -= delta;
 
 
  /* Store buffer is full, take one out */
  /* Store buffer is full, take one out */
  if (sbuf_count >= config.cpu.sbuf_len) {
  if (sbuf_count >= config.cpu.sbuf_len) {
    sbuf_wait_cyc += sbuf_buf[sbuf_tail];
    sbuf_wait_cyc += sbuf_buf[sbuf_tail];
    runtime.sim.mem_cycles += sbuf_buf[sbuf_tail];
    runtime.sim.mem_cycles += sbuf_buf[sbuf_tail];
    sbuf_prev_cycles += sbuf_buf[sbuf_tail];
    sbuf_prev_cycles += sbuf_buf[sbuf_tail];
    sbuf_tail = (sbuf_tail + 1) % MAX_SBUF_LEN;
    sbuf_tail = (sbuf_tail + 1) % MAX_SBUF_LEN;
    sbuf_count--;
    sbuf_count--;
  }
  }
  /* Put newest store in the buffer */
  /* Put newest store in the buffer */
  sbuf_buf[sbuf_head] = cyc;
  sbuf_buf[sbuf_head] = cyc;
  sbuf_head = (sbuf_head + 1) % MAX_SBUF_LEN;
  sbuf_head = (sbuf_head + 1) % MAX_SBUF_LEN;
  sbuf_count++;
  sbuf_count++;
  //PRINTF ("|STORE %i,%i,%i,%i,%i\n", delta, sbuf_count, sbuf_tail, sbuf_head, sbuf_buf[sbuf_tail], sbuf_buf[sbuf_head]);
  //PRINTF ("|STORE %i,%i,%i,%i,%i\n", delta, sbuf_count, sbuf_tail, sbuf_head, sbuf_buf[sbuf_tail], sbuf_buf[sbuf_head]);
}
}
 
 
/* Store buffer analysis - previous stores should commit, before any load */
/* Store buffer analysis - previous stores should commit, before any load */
static inline void sbuf_load () {
static inline void sbuf_load () {
  int delta = runtime.sim.cycles - sbuf_prev_cycles;
  int delta = runtime.sim.cycles - sbuf_prev_cycles;
  sbuf_prev_cycles = runtime.sim.cycles;
  sbuf_prev_cycles = runtime.sim.cycles;
 
 
  //PRINTF (">LOAD  %i,%i,%i,%i,%i\n", delta, sbuf_count, sbuf_tail, sbuf_head, sbuf_buf[sbuf_tail], sbuf_buf[sbuf_head]);
  //PRINTF (">LOAD  %i,%i,%i,%i,%i\n", delta, sbuf_count, sbuf_tail, sbuf_head, sbuf_buf[sbuf_tail], sbuf_buf[sbuf_head]);
  //PRINTF ("|%i,%i\n", sbuf_total_cyc, sbuf_wait_cyc);
  //PRINTF ("|%i,%i\n", sbuf_total_cyc, sbuf_wait_cyc);
  /* Take stores from buffer, that occured meanwhile */
  /* Take stores from buffer, that occured meanwhile */
  while (sbuf_count && delta >= sbuf_buf[sbuf_tail]) {
  while (sbuf_count && delta >= sbuf_buf[sbuf_tail]) {
    delta -= sbuf_buf[sbuf_tail];
    delta -= sbuf_buf[sbuf_tail];
    sbuf_tail = (sbuf_tail + 1) % MAX_SBUF_LEN;
    sbuf_tail = (sbuf_tail + 1) % MAX_SBUF_LEN;
    sbuf_count--;
    sbuf_count--;
  }
  }
  if (sbuf_count)
  if (sbuf_count)
    sbuf_buf[sbuf_tail] -= delta;
    sbuf_buf[sbuf_tail] -= delta;
 
 
  /* Wait for all stores to complete */
  /* Wait for all stores to complete */
  while (sbuf_count > 0) {
  while (sbuf_count > 0) {
    sbuf_wait_cyc += sbuf_buf[sbuf_tail];
    sbuf_wait_cyc += sbuf_buf[sbuf_tail];
    runtime.sim.mem_cycles += sbuf_buf[sbuf_tail];
    runtime.sim.mem_cycles += sbuf_buf[sbuf_tail];
    sbuf_prev_cycles += sbuf_buf[sbuf_tail];
    sbuf_prev_cycles += sbuf_buf[sbuf_tail];
    sbuf_tail = (sbuf_tail + 1) % MAX_SBUF_LEN;
    sbuf_tail = (sbuf_tail + 1) % MAX_SBUF_LEN;
    sbuf_count--;
    sbuf_count--;
  }
  }
  //PRINTF ("|LOAD  %i,%i,%i,%i,%i\n", delta, sbuf_count, sbuf_tail, sbuf_head, sbuf_buf[sbuf_tail], sbuf_buf[sbuf_head]);
  //PRINTF ("|LOAD  %i,%i,%i,%i,%i\n", delta, sbuf_count, sbuf_tail, sbuf_head, sbuf_buf[sbuf_tail], sbuf_buf[sbuf_head]);
}
}
 
 
/* Outputs dissasembled instruction */
/* Outputs dissasembled instruction */
void dump_exe_log ()
void dump_exe_log ()
{
{
  oraddr_t insn_addr = iqueue[0].insn_addr;
  oraddr_t insn_addr = iqueue[0].insn_addr;
  unsigned int i, j;
  unsigned int i, j;
  uorreg_t operand;
  uorreg_t operand;
 
 
  if (insn_addr == 0xffffffff) return;
  if (insn_addr == 0xffffffff) return;
  if ((config.sim.exe_log_start <= runtime.cpu.instructions) &&
  if ((config.sim.exe_log_start <= runtime.cpu.instructions) &&
      ((config.sim.exe_log_end <= 0) ||
      ((config.sim.exe_log_end <= 0) ||
       (runtime.cpu.instructions <= config.sim.exe_log_end))) {
       (runtime.cpu.instructions <= config.sim.exe_log_end))) {
    if (config.sim.exe_log_marker &&
    if (config.sim.exe_log_marker &&
        !(runtime.cpu.instructions % config.sim.exe_log_marker)) {
        !(runtime.cpu.instructions % config.sim.exe_log_marker)) {
      fprintf (runtime.sim.fexe_log, "--------------------- %8lli instruction ---------------------\n", runtime.cpu.instructions);
      fprintf (runtime.sim.fexe_log, "--------------------- %8lli instruction ---------------------\n", runtime.cpu.instructions);
    }
    }
    switch (config.sim.exe_log_type) {
    switch (config.sim.exe_log_type) {
    case EXE_LOG_HARDWARE:
    case EXE_LOG_HARDWARE:
      fprintf (runtime.sim.fexe_log, "\nEXECUTED(%11llu): %"PRIxADDR":  ",
      fprintf (runtime.sim.fexe_log, "\nEXECUTED(%11llu): %"PRIxADDR":  ",
               runtime.cpu.instructions, insn_addr);
               runtime.cpu.instructions, insn_addr);
      fprintf (runtime.sim.fexe_log, "%.2x%.2x", evalsim_mem8_void(insn_addr),
      fprintf (runtime.sim.fexe_log, "%.2x%.2x", evalsim_mem8_void(insn_addr),
               evalsim_mem8_void(insn_addr + 1));
               evalsim_mem8_void(insn_addr + 1));
      fprintf (runtime.sim.fexe_log, "%.2x%.2x",
      fprintf (runtime.sim.fexe_log, "%.2x%.2x",
               evalsim_mem8_void(insn_addr + 2),
               evalsim_mem8_void(insn_addr + 2),
               evalsim_mem8_void(insn_addr + 3));
               evalsim_mem8_void(insn_addr + 3));
      for(i = 0; i < MAX_GPRS; i++) {
      for(i = 0; i < MAX_GPRS; i++) {
        if (i % 4 == 0)
        if (i % 4 == 0)
          fprintf(runtime.sim.fexe_log, "\n");
          fprintf(runtime.sim.fexe_log, "\n");
        fprintf (runtime.sim.fexe_log, "GPR%2u: %"PRIxREG"  ", i, reg[i]);
        fprintf (runtime.sim.fexe_log, "GPR%2u: %"PRIxREG"  ", i, reg[i]);
      }
      }
      fprintf (runtime.sim.fexe_log, "\n");
      fprintf (runtime.sim.fexe_log, "\n");
      fprintf (runtime.sim.fexe_log, "SR   : %.8lx  ", mfspr(SPR_SR));
      fprintf (runtime.sim.fexe_log, "SR   : %.8lx  ", mfspr(SPR_SR));
      fprintf (runtime.sim.fexe_log, "EPCR0: %.8lx  ", mfspr(SPR_EPCR_BASE));
      fprintf (runtime.sim.fexe_log, "EPCR0: %.8lx  ", mfspr(SPR_EPCR_BASE));
      fprintf (runtime.sim.fexe_log, "EEAR0: %.8lx  ", mfspr(SPR_EEAR_BASE));
      fprintf (runtime.sim.fexe_log, "EEAR0: %.8lx  ", mfspr(SPR_EEAR_BASE));
      fprintf (runtime.sim.fexe_log, "ESR0 : %.8lx\n", mfspr(SPR_ESR_BASE));
      fprintf (runtime.sim.fexe_log, "ESR0 : %.8lx\n", mfspr(SPR_ESR_BASE));
      break;
      break;
    case EXE_LOG_SIMPLE:
    case EXE_LOG_SIMPLE:
    case EXE_LOG_SOFTWARE:
    case EXE_LOG_SOFTWARE:
      {
      {
        extern char *disassembled;
        extern char *disassembled;
        disassemble_index (iqueue[0].insn, iqueue[0].insn_index);
        disassemble_index (iqueue[0].insn, iqueue[0].insn_index);
        {
        {
          struct label_entry *entry;
          struct label_entry *entry;
          entry = get_label(insn_addr);
          entry = get_label(insn_addr);
          if (entry)
          if (entry)
            fprintf (runtime.sim.fexe_log, "%s:\n", entry->name);
            fprintf (runtime.sim.fexe_log, "%s:\n", entry->name);
        }
        }
 
 
        if (config.sim.exe_log_type == EXE_LOG_SOFTWARE) {
        if (config.sim.exe_log_type == EXE_LOG_SOFTWARE) {
          struct insn_op_struct *opd = op_start[iqueue[0].insn_index];
          struct insn_op_struct *opd = op_start[iqueue[0].insn_index];
 
 
          j = 0;
          j = 0;
          while (1) {
          while (1) {
            operand = eval_operand_val (iqueue[0].insn, opd);
            operand = eval_operand_val (iqueue[0].insn, opd);
            while (!(opd->type & OPTYPE_OP))
            while (!(opd->type & OPTYPE_OP))
              opd++;
              opd++;
            if (opd->type & OPTYPE_DIS) {
            if (opd->type & OPTYPE_DIS) {
              fprintf (runtime.sim.fexe_log, "EA =%"PRIxADDR" PA =%"PRIxADDR" ",
              fprintf (runtime.sim.fexe_log, "EA =%"PRIxADDR" PA =%"PRIxADDR" ",
                       insn_ea, peek_into_dtlb(insn_ea,0,0));
                       insn_ea, peek_into_dtlb(insn_ea,0,0));
              opd++; /* Skip of register operand */
              opd++; /* Skip of register operand */
              j++;
              j++;
            } else if ((opd->type & OPTYPE_REG) && operand) {
            } else if ((opd->type & OPTYPE_REG) && operand) {
              fprintf (runtime.sim.fexe_log, "r%-2i=%"PRIxREG" ",
              fprintf (runtime.sim.fexe_log, "r%-2i=%"PRIxREG" ",
                       (int)operand, evalsim_reg (operand));
                       (int)operand, evalsim_reg (operand));
            } else
            } else
              fprintf (runtime.sim.fexe_log, "             ");
              fprintf (runtime.sim.fexe_log, "             ");
            j++;
            j++;
            if(opd->type & OPTYPE_LAST)
            if(opd->type & OPTYPE_LAST)
              break;
              break;
            opd++;
            opd++;
          }
          }
          while(j < 3) {
          while(j < 3) {
            fprintf (runtime.sim.fexe_log, "             ");
            fprintf (runtime.sim.fexe_log, "             ");
            j++;
            j++;
          }
          }
        }
        }
        fprintf (runtime.sim.fexe_log, "%"PRIxADDR" ", insn_addr);
        fprintf (runtime.sim.fexe_log, "%"PRIxADDR" ", insn_addr);
        fprintf (runtime.sim.fexe_log, "%s\n", disassembled);
        fprintf (runtime.sim.fexe_log, "%s\n", disassembled);
      }
      }
    }
    }
  }
  }
}
}
 
 
/* Dump registers - 'r' or 't' command */
/* Dump registers - 'r' or 't' command */
void dumpreg()
void dumpreg()
{
{
  int i;
  int i;
  oraddr_t physical_pc;
  oraddr_t physical_pc;
 
 
  if ((physical_pc = peek_into_itlb(iqueue[0].insn_addr))) {
  if ((physical_pc = peek_into_itlb(iqueue[0].insn_addr))) {
    /*
    /*
     * PRINTF("\t\t\tEA: %08x <--> PA: %08x\n", iqueue[0].insn_addr, physical_pc);
     * PRINTF("\t\t\tEA: %08x <--> PA: %08x\n", iqueue[0].insn_addr, physical_pc);
     */
     */
    dumpmemory(physical_pc, physical_pc + 4, 1, 0);
    dumpmemory(physical_pc, physical_pc + 4, 1, 0);
  }
  }
  else {
  else {
    PRINTF("INTERNAL SIMULATOR ERROR:\n");
    PRINTF("INTERNAL SIMULATOR ERROR:\n");
    PRINTF("no translation for currently executed instruction\n");
    PRINTF("no translation for currently executed instruction\n");
  }
  }
 
 
  // generate_time_pretty (temp, runtime.sim.cycles * config.sim.clkcycle_ps);
  // generate_time_pretty (temp, runtime.sim.cycles * config.sim.clkcycle_ps);
  PRINTF(" (executed) [cycle %lld, #%lld]\n", runtime.sim.cycles,
  PRINTF(" (executed) [cycle %lld, #%lld]\n", runtime.sim.cycles,
         runtime.cpu.instructions);
         runtime.cpu.instructions);
  if (config.cpu.superscalar)
  if (config.cpu.superscalar)
    PRINTF ("Superscalar CYCLES: %u", runtime.cpu.supercycles);
    PRINTF ("Superscalar CYCLES: %u", runtime.cpu.supercycles);
  if (config.cpu.hazards)
  if (config.cpu.hazards)
    PRINTF ("  HAZARDWAIT: %u\n", runtime.cpu.hazardwait);
    PRINTF ("  HAZARDWAIT: %u\n", runtime.cpu.hazardwait);
  else
  else
    if (config.cpu.superscalar)
    if (config.cpu.superscalar)
      PRINTF ("\n");
      PRINTF ("\n");
 
 
  if ((physical_pc = peek_into_itlb(pc))) {
  if ((physical_pc = peek_into_itlb(pc))) {
    /*
    /*
     * PRINTF("\t\t\tEA: %08x <--> PA: %08x\n", pc, physical_pc);
     * PRINTF("\t\t\tEA: %08x <--> PA: %08x\n", pc, physical_pc);
     */
     */
    dumpmemory(physical_pc, physical_pc + 4, 1, 0);
    dumpmemory(physical_pc, physical_pc + 4, 1, 0);
  }
  }
  else
  else
    PRINTF("%"PRIxADDR": : xxxxxxxx  ITLB miss follows", pc);
    PRINTF("%"PRIxADDR": : xxxxxxxx  ITLB miss follows", pc);
 
 
  PRINTF(" (next insn) %s", (delay_insn?"(delay insn)":""));
  PRINTF(" (next insn) %s", (delay_insn?"(delay insn)":""));
  for(i = 0; i < MAX_GPRS; i++) {
  for(i = 0; i < MAX_GPRS; i++) {
    if (i % 4 == 0)
    if (i % 4 == 0)
      PRINTF("\n");
      PRINTF("\n");
    PRINTF("GPR%.2u: %"PRIxREG"  ", i, evalsim_reg(i));
    PRINTF("GPR%.2u: %"PRIxREG"  ", i, evalsim_reg(i));
  }
  }
  PRINTF("flag: %u\n", flag);
  PRINTF("flag: %u\n", flag);
}
}
 
 
/* Generated/built in decoding/executing function */
/* Generated/built in decoding/executing function */
static inline void decode_execute (struct iqueue_entry *current);
static inline void decode_execute (struct iqueue_entry *current);
 
 
/* Wrapper around real decode_execute function -- some statistics here only */
/* Wrapper around real decode_execute function -- some statistics here only */
static inline void decode_execute_wrapper (struct iqueue_entry *current)
static inline void decode_execute_wrapper (struct iqueue_entry *current)
{
{
  breakpoint = 0;
  breakpoint = 0;
 
 
#ifndef HAS_EXECUTION
#ifndef HAS_EXECUTION
#error HAS_EXECUTION has to be defined in order to execute programs.
#error HAS_EXECUTION has to be defined in order to execute programs.
#endif
#endif
 
 
  decode_execute (current);
  decode_execute (current);
 
 
#if SET_OV_FLAG
#if SET_OV_FLAG
  /* Check for range exception */
  /* Check for range exception */
  if (testsprbits (SPR_SR, SPR_SR_OVE) && testsprbits (SPR_SR, SPR_SR_OV))
  if (testsprbits (SPR_SR, SPR_SR_OVE) && testsprbits (SPR_SR, SPR_SR_OV))
    except_handle (EXCEPT_RANGE, mfspr(SPR_EEAR_BASE));
    except_handle (EXCEPT_RANGE, mfspr(SPR_EEAR_BASE));
#endif
#endif
 
 
  if(breakpoint)
  if(breakpoint)
    except_handle(EXCEPT_TRAP, mfspr(SPR_EEAR_BASE));
    except_handle(EXCEPT_TRAP, mfspr(SPR_EEAR_BASE));
}
}
 
 
/* Reset the CPU */
/* Reset the CPU */
void cpu_reset()
void cpu_reset()
{
{
  int i;
  int i;
  struct hist_exec *hist_exec_head = NULL;
  struct hist_exec *hist_exec_head = NULL;
  struct hist_exec *hist_exec_new;
  struct hist_exec *hist_exec_new;
 
 
  runtime.sim.cycles = 0;
  runtime.sim.cycles = 0;
  runtime.sim.loadcycles = 0;
  runtime.sim.loadcycles = 0;
  runtime.sim.storecycles = 0;
  runtime.sim.storecycles = 0;
  runtime.cpu.instructions = 0;
  runtime.cpu.instructions = 0;
  runtime.cpu.supercycles = 0;
  runtime.cpu.supercycles = 0;
  runtime.cpu.hazardwait = 0;
  runtime.cpu.hazardwait = 0;
  for (i = 0; i < MAX_GPRS; i++)
  for (i = 0; i < MAX_GPRS; i++)
    set_reg (i, 0);
    set_reg (i, 0);
  memset(iqueue, 0, sizeof(iqueue));
  memset(iqueue, 0, sizeof(iqueue));
  memset(icomplet, 0, sizeof(icomplet));
  memset(icomplet, 0, sizeof(icomplet));
 
 
  sbuf_head = 0;
  sbuf_head = 0;
  sbuf_tail = 0;
  sbuf_tail = 0;
  sbuf_count = 0;
  sbuf_count = 0;
  sbuf_prev_cycles = 0;
  sbuf_prev_cycles = 0;
 
 
  /* Initialise execution history circular buffer */
  /* Initialise execution history circular buffer */
  for (i = 0; i < HISTEXEC_LEN; i++) {
  for (i = 0; i < HISTEXEC_LEN; i++) {
    hist_exec_new = malloc(sizeof(struct hist_exec));
    hist_exec_new = malloc(sizeof(struct hist_exec));
    if(!hist_exec_new) {
    if(!hist_exec_new) {
      fprintf(stderr, "Out-of-memory\n");
      fprintf(stderr, "Out-of-memory\n");
      exit(1);
      exit(1);
    }
    }
    if(!hist_exec_head)
    if(!hist_exec_head)
      hist_exec_head = hist_exec_new;
      hist_exec_head = hist_exec_new;
    else
    else
      hist_exec_tail->next = hist_exec_new;
      hist_exec_tail->next = hist_exec_new;
 
 
    hist_exec_new->prev = hist_exec_tail;
    hist_exec_new->prev = hist_exec_tail;
    hist_exec_tail = hist_exec_new;
    hist_exec_tail = hist_exec_new;
  }
  }
  /* Make hist_exec_tail->next point to hist_exec_head */
  /* Make hist_exec_tail->next point to hist_exec_head */
  hist_exec_tail->next = hist_exec_head;
  hist_exec_tail->next = hist_exec_head;
  hist_exec_head->prev = hist_exec_tail;
  hist_exec_head->prev = hist_exec_tail;
 
 
  /* Cpu configuration */
  /* Cpu configuration */
  mtspr(SPR_UPR, config.cpu.upr);
  mtspr(SPR_UPR, config.cpu.upr);
  setsprbits(SPR_VR, SPR_VR_VER, config.cpu.ver);
  setsprbits(SPR_VR, SPR_VR_VER, config.cpu.ver);
  setsprbits(SPR_VR, SPR_VR_REV, config.cpu.rev);
  setsprbits(SPR_VR, SPR_VR_REV, config.cpu.rev);
  mtspr(SPR_SR, config.cpu.sr);
  mtspr(SPR_SR, config.cpu.sr);
 
 
  pcnext = 0x0; /* MM1409: All programs should start at reset vector entry!  */
  pcnext = 0x0; /* MM1409: All programs should start at reset vector entry!  */
  if (config.sim.verbose) PRINTF ("Starting at 0x%"PRIxADDR"\n", pcnext);
  if (config.sim.verbose) PRINTF ("Starting at 0x%"PRIxADDR"\n", pcnext);
  pc = pcnext;
  pc = pcnext;
  pcnext += 4;
  pcnext += 4;
  debug(1, "reset ...\n");
  debug(1, "reset ...\n");
 
 
  /* MM1409: All programs should set their stack pointer!  */
  /* MM1409: All programs should set their stack pointer!  */
  except_handle(EXCEPT_RESET, 0);
  except_handle(EXCEPT_RESET, 0);
  update_pc();
  update_pc();
  except_pending = 0;
  except_pending = 0;
}
}
 
 
/* Simulates one CPU clock cycle */
/* Simulates one CPU clock cycle */
inline int cpu_clock ()
inline int cpu_clock ()
{
{
  except_pending = 0;
  except_pending = 0;
  next_delay_insn = 0;
  next_delay_insn = 0;
  if(fetch()) {
  if(fetch()) {
    PRINTF ("Breakpoint hit.\n");
    PRINTF ("Breakpoint hit.\n");
    runtime.sim.cont_run = 0; /* memory breakpoint encountered */
    runtime.sim.cont_run = 0; /* memory breakpoint encountered */
    return 1;
    return 1;
  }
  }
 
 
  if(except_pending) {
  if(except_pending) {
    update_pc();
    update_pc();
    except_pending = 0;
    except_pending = 0;
    return 0;
    return 0;
  }
  }
 
 
  if(breakpoint) {
  if(breakpoint) {
    except_handle(EXCEPT_TRAP, mfspr(SPR_EEAR_BASE));
    except_handle(EXCEPT_TRAP, mfspr(SPR_EEAR_BASE));
    update_pc();
    update_pc();
    except_pending = 0;
    except_pending = 0;
    return 0;
    return 0;
  }
  }
 
 
  decode_execute_wrapper (&iqueue[0]);
  decode_execute_wrapper (&iqueue[0]);
  update_pc();
  update_pc();
  return 0;
  return 0;
}
}
 
 
/* If decoding cannot be found, call this function */
/* If decoding cannot be found, call this function */
#if SIMPLE_EXECUTION
#if SIMPLE_EXECUTION
void l_invalid (struct iqueue_entry *current) {
void l_invalid (struct iqueue_entry *current) {
#else
#else
void l_invalid () {
void l_invalid () {
#endif
#endif
  except_handle(EXCEPT_ILLEGAL, iqueue[0].insn_addr);
  except_handle(EXCEPT_ILLEGAL, iqueue[0].insn_addr);
}
}
 
 
#if !SIMPLE_EXECUTION
#if !SIMPLE_EXECUTION
 
 
/* Include decode_execute function */
/* Include decode_execute function */
#include "execgen.c"
#include "execgen.c"
 
 
#else /* SIMPLE_EXECUTION */
#else /* SIMPLE_EXECUTION */
 
 
 
 
#define INSTRUCTION(name) void name (struct iqueue_entry *current)
#define INSTRUCTION(name) void name (struct iqueue_entry *current)
 
 
/* Implementation specific.
/* Implementation specific.
   Get an actual value of a specific register. */
   Get an actual value of a specific register. */
 
 
static uorreg_t eval_reg(unsigned int regno)
static uorreg_t eval_reg(unsigned int regno)
{
{
  if (regno < MAX_GPRS) {
  if (regno < MAX_GPRS) {
#if RAW_RANGE_STATS
#if RAW_RANGE_STATS
      int delta = (runtime.sim.cycles - raw_stats.reg[regno]);
      int delta = (runtime.sim.cycles - raw_stats.reg[regno]);
      if ((unsigned long)delta < (unsigned long)MAX_RAW_RANGE)
      if ((unsigned long)delta < (unsigned long)MAX_RAW_RANGE)
        raw_stats.range[delta]++;
        raw_stats.range[delta]++;
#endif /* RAW_RANGE */
#endif /* RAW_RANGE */
    return reg[regno];
    return reg[regno];
  } else {
  } else {
    PRINTF("\nABORT: read out of registers\n");
    PRINTF("\nABORT: read out of registers\n");
    runtime.sim.cont_run = 0;
    runtime.sim.cont_run = 0;
    return 0;
    return 0;
  }
  }
}
}
 
 
/* Implementation specific.
/* Implementation specific.
   Evaluates source operand op_no. */
   Evaluates source operand op_no. */
 
 
static uorreg_t eval_operand (int op_no, unsigned long insn_index, uint32_t insn)
static uorreg_t eval_operand (int op_no, unsigned long insn_index, uint32_t insn)
{
{
  struct insn_op_struct *opd = op_start[insn_index];
  struct insn_op_struct *opd = op_start[insn_index];
  uorreg_t ret;
  uorreg_t ret;
 
 
  while (op_no) {
  while (op_no) {
    if(opd->type & OPTYPE_LAST) {
    if(opd->type & OPTYPE_LAST) {
      fprintf (stderr, "Instruction requested more operands than it has\n");
      fprintf (stderr, "Instruction requested more operands than it has\n");
      exit (1);
      exit (1);
    }
    }
    if((opd->type & OPTYPE_OP) && !(opd->type & OPTYPE_DIS))
    if((opd->type & OPTYPE_OP) && !(opd->type & OPTYPE_DIS))
      op_no--;
      op_no--;
    opd++;
    opd++;
  }
  }
 
 
  if (opd->type & OPTYPE_DIS) {
  if (opd->type & OPTYPE_DIS) {
    ret = eval_operand_val (insn, opd);
    ret = eval_operand_val (insn, opd);
    while (!(opd->type & OPTYPE_OP))
    while (!(opd->type & OPTYPE_OP))
      opd++;
      opd++;
    opd++;
    opd++;
    ret += eval_reg (eval_operand_val (insn, opd));
    ret += eval_reg (eval_operand_val (insn, opd));
    insn_ea = ret;
    insn_ea = ret;
    return ret;
    return ret;
  }
  }
  if (opd->type & OPTYPE_REG)
  if (opd->type & OPTYPE_REG)
    return eval_reg (eval_operand_val (insn, opd));
    return eval_reg (eval_operand_val (insn, opd));
 
 
  return eval_operand_val (insn, opd);
  return eval_operand_val (insn, opd);
}
}
 
 
/* Implementation specific.
/* Implementation specific.
   Set destination operand (reister direct) with value. */
   Set destination operand (reister direct) with value. */
 
 
inline static void set_operand(int op_no, orreg_t value,
inline static void set_operand(int op_no, orreg_t value,
                               unsigned long insn_index, uint32_t insn)
                               unsigned long insn_index, uint32_t insn)
{
{
  struct insn_op_struct *opd = op_start[insn_index];
  struct insn_op_struct *opd = op_start[insn_index];
 
 
  while (op_no) {
  while (op_no) {
    if(opd->type & OPTYPE_LAST) {
    if(opd->type & OPTYPE_LAST) {
      fprintf (stderr, "Instruction requested more operands than it has\n");
      fprintf (stderr, "Instruction requested more operands than it has\n");
      exit (1);
      exit (1);
    }
    }
    if((opd->type & OPTYPE_OP) && !(opd->type & OPTYPE_DIS))
    if((opd->type & OPTYPE_OP) && !(opd->type & OPTYPE_DIS))
      op_no--;
      op_no--;
    opd++;
    opd++;
  }
  }
 
 
  if (!(opd->type & OPTYPE_REG)) {
  if (!(opd->type & OPTYPE_REG)) {
    fprintf (stderr, "Trying to set a non-register operand\n");
    fprintf (stderr, "Trying to set a non-register operand\n");
    exit (1);
    exit (1);
  }
  }
  set_reg (eval_operand_val (insn, opd), value);
  set_reg (eval_operand_val (insn, opd), value);
}
}
 
 
/* Simple and rather slow decoding function based on built automata. */
/* Simple and rather slow decoding function based on built automata. */
static inline void decode_execute (struct iqueue_entry *current)
static inline void decode_execute (struct iqueue_entry *current)
{
{
  int insn_index;
  int insn_index;
 
 
  current->insn_index = insn_index = insn_decode(current->insn);
  current->insn_index = insn_index = insn_decode(current->insn);
 
 
  if (insn_index < 0)
  if (insn_index < 0)
    l_invalid(current);
    l_invalid(current);
  else {
  else {
    or32_opcodes[insn_index].exec(current);
    or32_opcodes[insn_index].exec(current);
  }
  }
  if (do_stats) analysis(&iqueue[0]);
  if (do_stats) analysis(&iqueue[0]);
}
}
 
 
#define SET_PARAM0(val) set_operand(0, val, current->insn_index, current->insn)
#define SET_PARAM0(val) set_operand(0, val, current->insn_index, current->insn)
 
 
#define PARAM0 eval_operand(0, current->insn_index, current->insn)
#define PARAM0 eval_operand(0, current->insn_index, current->insn)
#define PARAM1 eval_operand(1, current->insn_index, current->insn)
#define PARAM1 eval_operand(1, current->insn_index, current->insn)
#define PARAM2 eval_operand(2, current->insn_index, current->insn)
#define PARAM2 eval_operand(2, current->insn_index, current->insn)
 
 
#include "insnset.c"
#include "insnset.c"
 
 
#endif /* !SIMPLE_EXECUTION */
#endif /* !SIMPLE_EXECUTION */
 
 

powered by: WebSVN 2.1.0

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