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

Subversion Repositories or1k

[/] [or1k/] [tags/] [nog_patch_34/] [or1ksim/] [cpu/] [or32/] [execute.c] - Diff between revs 1344 and 1346

Go to most recent revision | Show entire file | Details | Blame | View Log

Rev 1344 Rev 1346
Line 1... Line 1...
/* 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
 
 
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
Line 100... Line 101...
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;
static unsigned long *op;
 
static int num_op;
/* Effective address of instructions that have an effective address.  This is
 
 * only used to get dump_exe_log correct */
 
static unsigned long insn_ea;
 
 
/* Implementation specific.
/* Implementation specific.
   Get an actual value of a specific register. */
   Get an actual value of a specific register. */
 
 
unsigned long evalsim_reg32(int regno)
unsigned long evalsim_reg32(int regno)
Line 180... Line 183...
    PRINTF("\nABORT: write out of registers\n");
    PRINTF("\nABORT: write out of registers\n");
    runtime.sim.cont_run = 0;
    runtime.sim.cont_run = 0;
  }
  }
}
}
 
 
/* Does srcoperand depend on computation of dstoperand? Return
/* Implementation specific.
 
   Evaluates source operand opd. */
 
 
 
static unsigned long eval_operand_val(unsigned long insn,
 
                                      struct insn_op_struct *opd)
 
{
 
  unsigned long operand = 0;
 
  unsigned long sbit;
 
  unsigned int nbits = 0;
 
 
 
  while(1) {
 
    operand |= ((insn >> (opd->type & OPTYPE_SHR)) & ((1 << opd->data) - 1)) << nbits;
 
    nbits += opd->data;
 
 
 
    if(opd->type & OPTYPE_OP)
 
      break;
 
    opd++;
 
  }
 
 
 
  if(opd->type & OPTYPE_SIG) {
 
    sbit = (opd->type & OPTYPE_SBIT) >> OPTYPE_SBIT_SHR;
 
    if(operand & (1 << sbit)) operand |= 0xffffffff << sbit;
 
  }
 
 
 
  return operand;
 
}
 
 
 
/* 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
Line 199... Line 229...
     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 i = 0;
  int prev_dis, next_dis;
 
  unsigned int prev_reg_val = 0;
 
  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;
 
 
  while (!(prev->op[i + MAX_OPERANDS] & OPTYPE_LAST))
  opd = op_start[prev->insn_index];
    if (prev->op[i + MAX_OPERANDS] & OPTYPE_DST)
  prev_dis = 0;
      {
 
        type = prev->op[i + MAX_OPERANDS];
  while (1) {
 
    if (opd->type & OPTYPE_DIS)
 
      prev_dis = 1;
 
 
 
    if (opd->type & OPTYPE_DST) {
 
      type = opd->type;
 
      if (prev_dis)
 
        type |= OPTYPE_DIS;
 
      /* Destination is always a register */
 
      prev_reg_val = eval_operand_val (prev->insn, opd);
        break;
        break;
      }
      }
    else
    if (opd->type & OPTYPE_LAST)
      i++;
      return 0; /* Doesn't have a destination operand */
 
    if (opd->type & OPTYPE_OP)
 
      prev_dis = 0;
 
    opd++;
 
  }
 
 
  /* We search all source operands - if we find confict => return 1 */
  /* We search all source operands - if we find confict => return 1 */
  i = 0;
  opd = op_start[next->insn_index];
  while (!(next->op[i + MAX_OPERANDS] & OPTYPE_LAST))
  next_dis = 0;
    if (!(next->op[i + MAX_OPERANDS] & OPTYPE_DST))
 
      {
  while (1) {
        if (next->op[i + MAX_OPERANDS] & OPTYPE_DIS) {
    if (opd->type & OPTYPE_DIS)
          if (type & OPTYPE_DIS)
      next_dis = 1;
            return 1;
    /* This instruction sequence also depends on order of execution:
          else if (next->op[i] == prev->op[i]
     * l.lw r1, k(r1)
                   && (next->op[i + MAX_OPERANDS] & OPTYPE_REG))
     * l.sw k(r1), r4
 
     * Here r1 is a destination in l.sw */
 
    /* FIXME: This situation is not handeld here when r1 == r2:
 
     * l.sw k(r1), r4
 
     * l.lw r3, k(r2)
 
     */
 
    if (!(opd->type & OPTYPE_DST) || (next_dis && (opd->type & OPTYPE_DST))) {
 
      if (opd->type & OPTYPE_REG)
 
        if (eval_operand_val (next->insn, opd) == prev_reg_val)
            return 1;
            return 1;
        }
        }
        if (next->op[i] == prev->op[i]
    if (opd->type & OPTYPE_LAST)
            && (next->op[i + MAX_OPERANDS] & OPTYPE_REG)
      break;
            && (type & OPTYPE_REG))
    opd++;
          return 1;
 
        i++;
 
      }
      }
    else
 
      i++;
 
  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 */
 
 
Line 425... Line 476...
}
}
 
 
/* Outputs dissasembled instruction */
/* Outputs dissasembled instruction */
void dump_exe_log ()
void dump_exe_log ()
{
{
  unsigned long i = iqueue[0].insn_addr;
  unsigned long insn_addr = iqueue[0].insn_addr;
 
  unsigned long i, j;
 
 
  if (i == 0xffffffff) return;
  if (insn_addr == 0xffffffff) return;
  if (config.sim.exe_log_start <= runtime.cpu.instructions && (config.sim.exe_log_end <= 0 || runtime.cpu.instructions <= config.sim.exe_log_end)) {
  if ((config.sim.exe_log_start <= runtime.cpu.instructions) &&
    if (config.sim.exe_log_marker && runtime.cpu.instructions % config.sim.exe_log_marker == 0) {
      ((config.sim.exe_log_end <= 0) ||
 
       (runtime.cpu.instructions <= config.sim.exe_log_end))) {
 
    if (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): %.8lx:  ", runtime.cpu.instructions, i);
      fprintf (runtime.sim.fexe_log, "\nEXECUTED(%11llu): %.8lx:  ",
      fprintf (runtime.sim.fexe_log, "%.2x%.2x", evalsim_mem8_void(i), evalsim_mem8_void(i + 1));
               runtime.cpu.instructions, insn_addr);
      fprintf (runtime.sim.fexe_log, "%.2x%.2x", evalsim_mem8_void(i + 2), evalsim_mem8_void(i + 3));
      fprintf (runtime.sim.fexe_log, "%.2x%.2x", evalsim_mem8_void(insn_addr),
 
               evalsim_mem8_void(insn_addr + 1));
 
      fprintf (runtime.sim.fexe_log, "%.2x%.2x",
 
               evalsim_mem8_void(insn_addr + 2),
 
               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%2lu: %.8lx  ", i, reg[i]);
        fprintf (runtime.sim.fexe_log, "GPR%2lu: %.8lx  ", i, reg[i]);
      }
      }
Line 455... Line 514...
      {
      {
        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(i);
          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) {
          int i,j=0;
          struct insn_op_struct *opd = op_start[iqueue[0].insn_index];
 
 
          for (i = 0; i < num_op; i++)
          j = 0;
            if (op[i + MAX_OPERANDS] & OPTYPE_DIS) {
          while (1) {
              j=1;
            i = eval_operand_val (iqueue[0].insn, opd);
              fprintf (runtime.sim.fexe_log, "EA =%08lx PA =%08lx ", op[i],
            while (!(opd->type & OPTYPE_OP))
                       peek_into_dtlb(op[i],0,0));
              opd++;
            } else if ((op[i + MAX_OPERANDS] & OPTYPE_REG) && op[i]) {
            if (opd->type & OPTYPE_DIS) {
              fprintf (runtime.sim.fexe_log, "r%-2li=%08lx ", op[i],
              fprintf (runtime.sim.fexe_log, "EA =%08lx PA =%08lx ", insn_ea,
                       evalsim_reg32 (op[i]));
                       peek_into_dtlb(insn_ea,0,0));
 
              opd++; /* Skip of register operand */
 
              j++;
 
            } else if ((opd->type & OPTYPE_REG) && i) {
 
              fprintf (runtime.sim.fexe_log, "r%-2li=%08lx ", i,
 
                       evalsim_reg32 (i));
            } else
            } else
              fprintf (runtime.sim.fexe_log, "             ");
              fprintf (runtime.sim.fexe_log, "             ");
 
            j++;
          i+=j;
            if(opd->type & OPTYPE_LAST)
          for (; i < 3; i++)
              break;
 
            opd++;
 
          }
 
          while(j < 3) {
            fprintf (runtime.sim.fexe_log, "             ");
            fprintf (runtime.sim.fexe_log, "             ");
 
            j++;
        }
        }
        fprintf (runtime.sim.fexe_log, "%.8lx ", i);
        }
 
        fprintf (runtime.sim.fexe_log, "%.8lx ", insn_addr);
        fprintf (runtime.sim.fexe_log, "%s\n", disassembled);
        fprintf (runtime.sim.fexe_log, "%s\n", disassembled);
      }
      }
    }
    }
  }
  }
}
}
Line 628... Line 697...
 
 
 
 
#define INSTRUCTION(name) void name (struct iqueue_entry *current)
#define INSTRUCTION(name) void name (struct iqueue_entry *current)
 
 
/* Implementation specific.
/* Implementation specific.
   Parses and returns operands. */
   Evaluates source operand op_no. */
 
 
static void
static unsigned long eval_operand (int op_no, unsigned long insn_index,
eval_operands (unsigned long insn, int insn_index, int* breakpoint)
                                   unsigned long insn)
{
{
  struct insn_op_struct *opd = op_start[insn_index];
  struct insn_op_struct *opd = op_start[insn_index];
  unsigned long data = 0;
  unsigned long ret;
  int dis = 0;
 
  int no = 0;
 
 
 
  while (1)
  while (op_no) {
    {
    if(opd->type & OPTYPE_LAST) {
      unsigned long tmp = 0, nbits = 0;
      fprintf (stderr, "Instruction requested more operands than it has\n");
      while (1)
      exit (1);
        {
    }
          tmp |= ((insn  >> (opd->type & OPTYPE_SHR)) & ((1 << opd->data) - 1)) << nbits;
    if((opd->type & OPTYPE_OP) && !(opd->type & OPTYPE_DIS))
          nbits += opd->data;
      op_no--;
          if (opd->type & OPTYPE_OP)
 
            break;
 
          opd++;
          opd++;
        }
        }
 
 
      /* Do we have to sign extend? */
 
      if (opd->type & OPTYPE_SIG)
 
        {
 
          int sbit = (opd->type & OPTYPE_SBIT) >> OPTYPE_SBIT_SHR;
 
          if (tmp & (1 << sbit))
 
            tmp |= 0xFFFFFFFF << sbit;
 
        }
 
      if (opd->type & OPTYPE_DIS) {
      if (opd->type & OPTYPE_DIS) {
        /* We have to read register later.  */
    ret = eval_operand_val (insn, opd);
        data += tmp;
    while (!(opd->type & OPTYPE_OP))
        dis = 1;
 
      } else
 
        {
 
          if (dis && (opd->type & OPTYPE_REG))
 
            op[no] = data + eval_reg32 (tmp);
 
          else
 
            op[no] = tmp;
 
          op[no + MAX_OPERANDS] = opd->type | (dis ? OPTYPE_DIS : 0);
 
          no++;
 
          data = 0;
 
          dis = 0;
 
        }
 
      if(opd->type & OPTYPE_LAST) {
 
        num_op = no;
 
        return;
 
      }
 
      opd++;
      opd++;
 
    opd++;
 
    ret += eval_reg32 (eval_operand_val (insn, opd));
 
    insn_ea = ret;
 
    return ret;
    }
    }
  num_op = no;
  if (opd->type & OPTYPE_REG)
 
    return eval_reg32 (eval_operand_val (insn, opd));
 
 
 
  return eval_operand_val (insn, opd);
}
}
 
 
/* Implementation specific.
/* Implementation specific.
   Evaluates source operand op_no. */
   Set destination operand (reister direct) with value. */
 
 
static unsigned long eval_operand (int op_no)
inline static void set_operand(int op_no, unsigned long value,
 
                               unsigned long insn_index, unsigned long insn)
{
{
  if (op[op_no + MAX_OPERANDS] & OPTYPE_DIS) {
  struct insn_op_struct *opd = op_start[insn_index];
    return op[op_no];
 
  } else if (op[op_no + MAX_OPERANDS] & OPTYPE_REG) {
  while (op_no) {
    return eval_reg32 (op[op_no]);
    if(opd->type & OPTYPE_LAST) {
  } else {
      fprintf (stderr, "Instruction requested more operands than it has\n");
    return op[op_no];
      exit (1);
  }
  }
 
    if((opd->type & OPTYPE_OP) && !(opd->type & OPTYPE_DIS))
 
      op_no--;
 
    opd++;
}
}
 
 
/* Implementation specific.
  if (!(opd->type & OPTYPE_REG)) {
   Set destination operand (reister direct) with value. */
 
 
 
inline static void set_operand(int op_no, unsigned long value)
 
{
 
  /* Mark this as destination operand.  */
 
  if (!(op[op_no + MAX_OPERANDS] & 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_reg32(op[op_no], value);
  set_reg32 (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)
{
{
Line 718... Line 765...
  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 {
    op = &current->op[0];
 
    eval_operands (current->insn, insn_index, &breakpoint);
 
    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)
#define SET_PARAM0(val) set_operand(0, val, current->insn_index, current->insn)
 
 
#define PARAM0 eval_operand(0)
#define PARAM0 eval_operand(0, current->insn_index, current->insn)
#define PARAM1 eval_operand(1)
#define PARAM1 eval_operand(1, current->insn_index, current->insn)
#define PARAM2 eval_operand(2)
#define PARAM2 eval_operand(2, current->insn_index, current->insn)
 
 
#include "insnset.c"
#include "insnset.c"
 
 
#endif /* !SIMPLE_EXECUTION */
#endif /* !SIMPLE_EXECUTION */
 
 
 No newline at end of file
 No newline at end of file

powered by: WebSVN 2.1.0

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