Line 53... |
Line 53... |
#include "debug-unit.h"
|
#include "debug-unit.h"
|
#include "branch-predict.h"
|
#include "branch-predict.h"
|
#include "sprs.h"
|
#include "sprs.h"
|
#include "rsp-server.h"
|
#include "rsp-server.h"
|
#include <fenv.h> // Floating point environment for FPU instructions
|
#include <fenv.h> // Floating point environment for FPU instructions
|
#include "execute-fp.h"
|
|
|
|
/* Includes and macros for simple execution */
|
/* Includes and macros for simple execution */
|
#if SIMPLE_EXECUTION
|
#if SIMPLE_EXECUTION
|
|
|
#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)
|
Line 106... |
Line 105... |
|
|
/* Variables used throughout this file to share information */
|
/* Variables used throughout this file to share information */
|
static int breakpoint;
|
static int breakpoint;
|
static int next_delay_insn;
|
static int next_delay_insn;
|
|
|
/* Functions to configure the host machine's FPU before doing simulated OR1k
|
|
FP ops, handle flags and restore things when it's done. One for before and
|
|
one for afterwards.
|
|
*/
|
|
void fp_set_or1k_rm(void);
|
|
void fp_set_flags_restore_host_rm(void);
|
|
|
|
/* A place to store the host's FPU rounding mode while OR1k's is used */
|
/* A place to store the host's FPU rounding mode while OR1k's is used */
|
int host_fp_rm;
|
static int host_fp_rm;
|
|
|
/* Forward declaration of static functions */
|
/* Forward declaration of static functions */
|
#if !(DYNAMIC_EXECUTION)
|
#if !(DYNAMIC_EXECUTION)
|
static void decode_execute (struct iqueue_entry *current);
|
static void decode_execute (struct iqueue_entry *current);
|
#endif
|
#endif
|
Line 267... |
Line 259... |
int prev_dis;
|
int prev_dis;
|
int next_dis;
|
int 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 (or1ksim_or32_opcodes[prev->insn_index].flags & OR32_W_FLAG
|
&& or32_opcodes[next->insn_index].flags & OR32_R_FLAG)
|
&& or1ksim_or32_opcodes[next->insn_index].flags & OR32_R_FLAG)
|
{
|
{
|
return 1;
|
return 1;
|
}
|
}
|
|
|
opd = op_start[prev->insn_index];
|
opd = or1ksim_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)
|
Line 311... |
Line 303... |
|
|
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 = or1ksim_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)
|
Line 426... |
Line 418... |
/* Dynamic, dependency stats. */
|
/* Dynamic, dependency stats. */
|
adddstats (cpu_state.icomplet.insn_index, current->insn_index, 1,
|
adddstats (cpu_state.icomplet.insn_index, current->insn_index, 1,
|
check_depend (&cpu_state.icomplet, current));
|
check_depend (&cpu_state.icomplet, current));
|
|
|
/* Dynamic, functional units stats. */
|
/* Dynamic, functional units stats. */
|
addfstats (or32_opcodes[cpu_state.icomplet.insn_index].func_unit,
|
addfstats (or1ksim_or32_opcodes[cpu_state.icomplet.insn_index].func_unit,
|
or32_opcodes[current->insn_index].func_unit, 1,
|
or1ksim_or32_opcodes[current->insn_index].func_unit, 1,
|
check_depend (&cpu_state.icomplet, current));
|
check_depend (&cpu_state.icomplet, current));
|
|
|
/* 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 ((or1ksim_or32_opcodes[current->insn_index].func_unit == it_branch) ||
|
(or32_opcodes[current->insn_index].func_unit == it_jump))
|
(or1ksim_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 (or1ksim_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 (or1ksim_or32_opcodes[current->insn_index].func_unit == it_load)
|
runtime.sim.loadcycles += 1;
|
runtime.sim.loadcycles += 1;
|
|
|
/* Pseudo multiple issue benchmark */
|
/* Pseudo multiple issue benchmark */
|
if ((multissue[or32_opcodes[current->insn_index].func_unit] < 1) ||
|
if ((multissue[or1ksim_or32_opcodes[current->insn_index].func_unit] < 1) ||
|
(check_depend (&cpu_state.icomplet, current))
|
(check_depend (&cpu_state.icomplet, current))
|
|| (issued_per_cycle < 1))
|
|| (issued_per_cycle < 1))
|
{
|
{
|
int i;
|
int i;
|
for (i = 0; i < 20; i++)
|
for (i = 0; i < 20; i++)
|
Line 471... |
Line 463... |
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[or1ksim_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. */
|
Line 649... |
Line 641... |
cpu_state.sprs[SPR_ESR_BASE]);
|
cpu_state.sprs[SPR_ESR_BASE]);
|
break;
|
break;
|
|
|
case EXE_LOG_SIMPLE:
|
case EXE_LOG_SIMPLE:
|
case EXE_LOG_SOFTWARE:
|
case EXE_LOG_SOFTWARE:
|
disassemble_index (cpu_state.iqueue.insn,
|
or1ksim_disassemble_index (cpu_state.iqueue.insn,
|
cpu_state.iqueue.insn_index);
|
cpu_state.iqueue.insn_index);
|
|
|
entry = get_label (insn_addr);
|
entry = get_label (insn_addr);
|
if (entry)
|
if (entry)
|
{
|
{
|
Line 661... |
Line 653... |
}
|
}
|
|
|
if (config.sim.exe_log_type == EXE_LOG_SOFTWARE)
|
if (config.sim.exe_log_type == EXE_LOG_SOFTWARE)
|
{
|
{
|
struct insn_op_struct *opd =
|
struct insn_op_struct *opd =
|
op_start[cpu_state.iqueue.insn_index];
|
or1ksim_op_start[cpu_state.iqueue.insn_index];
|
|
|
j = 0;
|
j = 0;
|
while (1)
|
while (1)
|
{
|
{
|
operand = eval_operand_val (cpu_state.iqueue.insn, opd);
|
operand = eval_operand_val (cpu_state.iqueue.insn, opd);
|
Line 696... |
Line 688... |
{
|
{
|
break;
|
break;
|
}
|
}
|
opd++;
|
opd++;
|
}
|
}
|
if (or32_opcodes[cpu_state.iqueue.insn_index].flags & OR32_R_FLAG)
|
if (or1ksim_or32_opcodes[cpu_state.iqueue.insn_index].flags & OR32_R_FLAG)
|
{
|
{
|
fprintf (runtime.sim.fexe_log, "SR =%" PRIxREG " ",
|
fprintf (runtime.sim.fexe_log, "SR =%" PRIxREG " ",
|
cpu_state.sprs[SPR_SR]);
|
cpu_state.sprs[SPR_SR]);
|
j++;
|
j++;
|
}
|
}
|
Line 709... |
Line 701... |
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", or1ksim_disassembled);
|
}
|
}
|
}
|
}
|
} /* dump_exe_log() */
|
} /* dump_exe_log() */
|
|
|
|
|
Line 1067... |
Line 1059... |
Save host rounding mode, set it to OR1K's according to FPCSR
|
Save host rounding mode, set it to OR1K's according to FPCSR
|
This function should be called before performing any FP instructions to
|
This function should be called before performing any FP instructions to
|
ensure the OR1K's rounding mode is installed in the host
|
ensure the OR1K's rounding mode is installed in the host
|
*/
|
*/
|
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
void fp_set_or1k_rm(void)
|
static void
|
|
fp_set_or1k_rm(void)
|
{
|
{
|
// Set OR1K's RM in host machine
|
// Set OR1K's RM in host machine
|
// First save host RM to restore it later
|
// First save host RM to restore it later
|
host_fp_rm = fegetround();
|
host_fp_rm = fegetround();
|
// Now map OR1K RM to host RM
|
// Now map OR1K RM to host RM
|
Line 1101... |
Line 1094... |
|
|
Copy flags from floating point op into OR1K's FPCSR, and restore the host's
|
Copy flags from floating point op into OR1K's FPCSR, and restore the host's
|
rounding mode.
|
rounding mode.
|
*/
|
*/
|
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
void fp_set_flags_restore_host_rm(void)
|
static void
|
|
fp_set_flags_restore_host_rm(void)
|
{
|
{
|
// Check FP flags on host, convert to OR1K FPCSR bits
|
// Check FP flags on host, convert to OR1K FPCSR bits
|
// First clear all flags in OR1K FPCSR
|
// First clear all flags in OR1K FPCSR
|
cpu_state.sprs[SPR_FPCSR] &= ~SPR_FPCSR_ALLF;
|
cpu_state.sprs[SPR_FPCSR] &= ~SPR_FPCSR_ALLF;
|
|
|
Line 1149... |
Line 1143... |
static uorreg_t
|
static uorreg_t
|
eval_operand (int op_no,
|
eval_operand (int op_no,
|
unsigned long insn_index,
|
unsigned long insn_index,
|
uint32_t insn)
|
uint32_t insn)
|
{
|
{
|
struct insn_op_struct *opd = op_start[insn_index];
|
struct insn_op_struct *opd = or1ksim_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)
|
Line 1211... |
Line 1205... |
set_operand (int op_no,
|
set_operand (int op_no,
|
orreg_t value,
|
orreg_t value,
|
unsigned long insn_index,
|
unsigned long insn_index,
|
uint32_t insn)
|
uint32_t insn)
|
{
|
{
|
struct insn_op_struct *opd = op_start[insn_index];
|
struct insn_op_struct *opd = or1ksim_op_start[insn_index];
|
|
|
while (op_no)
|
while (op_no)
|
{
|
{
|
if (opd->type & OPTYPE_LAST)
|
if (opd->type & OPTYPE_LAST)
|
{
|
{
|
Line 1253... |
Line 1247... |
static void
|
static void
|
decode_execute (struct iqueue_entry *current)
|
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 = or1ksim_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);
|
or1ksim_or32_opcodes[insn_index].exec (current);
|
}
|
}
|
|
|
if (do_stats)
|
if (do_stats)
|
analysis (&cpu_state.iqueue);
|
analysis (&cpu_state.iqueue);
|
}
|
}
|