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
|
Copyright (C) 2005 György `nog' Jeney, nog@sdf.lonestar.org
|
Copyright (C) 2008 Embecosm Limited
|
Copyright (C) 2008 Embecosm Limited
|
|
Copyright (C) 2010 ORSoC AB
|
|
|
Contributor Jeremy Bennett <jeremy.bennett@embecosm.com>
|
Contributor Jeremy Bennett <jeremy.bennett@embecosm.com>
|
|
Contributor Julius Baxter <julius.baxter@orsoc.se>
|
|
|
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 it
|
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 the Free
|
under the terms of the GNU General Public License as published by the Free
|
Line 52... |
Line 54... |
#include "vapi.h"
|
#include "vapi.h"
|
#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 "softfloat.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 105... |
Line 107... |
|
|
/* 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;
|
|
|
/* A place to store the host's FPU rounding mode while OR1k's is used */
|
|
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 1050... |
Line 1049... |
do_scheduler ();
|
do_scheduler ();
|
}
|
}
|
}
|
}
|
} /* exec_main() */
|
} /* exec_main() */
|
|
|
|
|
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
/*!Floating point operation setup function
|
/*!Update the rounding mode variable the softfloat library reads */
|
|
|
Save host rounding mode, set it to OR1K's according to FPCSR
|
|
This function should be called before performing any FP instructions to
|
|
ensure the OR1K's rounding mode is installed in the host
|
|
*/
|
|
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
static void
|
static void
|
fp_set_or1k_rm(void)
|
float_set_rm ()
|
{
|
{
|
// Set OR1K's RM in host machine
|
//
|
// First save host RM to restore it later
|
// float_rounding_mode is used by the softfloat library, it is declared in
|
host_fp_rm = fegetround();
|
// "softfloat.h"
|
// Now map OR1K RM to host RM
|
//
|
int or1k_rm = 0;
|
|
switch(cpu_state.sprs[SPR_FPCSR] & SPR_FPCSR_RM)
|
switch(cpu_state.sprs[SPR_FPCSR] & SPR_FPCSR_RM)
|
{
|
{
|
case FPCSR_RM_RN:
|
case FPCSR_RM_RN:
|
or1k_rm = FE_TONEAREST;
|
//printf("or1ksim <%s>: rounding mode RN\n",__FUNCTION__);
|
|
float_rounding_mode = float_round_nearest_even;
|
break;
|
break;
|
case FPCSR_RM_RZ:
|
case FPCSR_RM_RZ:
|
or1k_rm = FE_TOWARDZERO;
|
//printf("or1ksim <%s>: rounding mode RZ\n",__FUNCTION__);
|
|
float_rounding_mode = float_round_to_zero;
|
break;
|
break;
|
case FPCSR_RM_RIP:
|
case FPCSR_RM_RIP:
|
or1k_rm = FE_UPWARD;
|
//printf("or1ksim <%s>: rounding mode R+\n",__FUNCTION__);
|
|
float_rounding_mode = float_round_up;
|
break;
|
break;
|
case FPCSR_RM_RIN:
|
case FPCSR_RM_RIN:
|
or1k_rm = FE_TOWARDZERO;
|
//printf("or1ksim <%s>: rounding mode R-\n",__FUNCTION__);
|
|
float_rounding_mode = float_round_down;
|
break;
|
break;
|
}
|
}
|
// Now set this RM for the host
|
|
fesetround(or1k_rm); // TODO - check for nonzero return here, if RM not
|
|
// able to be set, maybe warn user
|
|
}
|
}
|
|
|
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
/*!Floating point operation flag set and host restore function
|
/*!Update the OR1K's FPCSR after each floating point instruction */
|
|
|
Copy flags from floating point op into OR1K's FPCSR, and restore the host's
|
|
rounding mode.
|
|
*/
|
|
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
static void
|
static void
|
fp_set_flags_restore_host_rm(void)
|
float_set_flags ()
|
{
|
{
|
// Check FP flags on host, convert to OR1K FPCSR bits
|
// Get the flags from softfloat's variable and set the OR1K's FPCR values
|
// 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;
|
|
|
// Test host flags, set appropriate OR1K flags
|
if (float_exception_flags & float_flag_invalid)
|
if (fetestexcept(FE_DIVBYZERO)) cpu_state.sprs[SPR_FPCSR] |= SPR_FPCSR_DZF;
|
cpu_state.sprs[SPR_FPCSR] |= SPR_FPCSR_IVF;
|
if (fetestexcept(FE_INEXACT)) cpu_state.sprs[SPR_FPCSR] |= SPR_FPCSR_IXF;
|
if (float_exception_flags & float_flag_divbyzero)
|
if (fetestexcept(FE_INVALID)) cpu_state.sprs[SPR_FPCSR] |= SPR_FPCSR_IVF;
|
cpu_state.sprs[SPR_FPCSR] |= SPR_FPCSR_DZF;
|
if (fetestexcept(FE_OVERFLOW)) cpu_state.sprs[SPR_FPCSR] |= SPR_FPCSR_OVF;
|
if (float_exception_flags & float_flag_overflow)
|
if (fetestexcept(FE_UNDERFLOW)) cpu_state.sprs[SPR_FPCSR] |= SPR_FPCSR_UNF;
|
cpu_state.sprs[SPR_FPCSR] |= SPR_FPCSR_OVF;
|
|
if (float_exception_flags & float_flag_underflow)
|
// Restore the hosts's rounding mode
|
cpu_state.sprs[SPR_FPCSR] |= SPR_FPCSR_UNF;
|
fesetround(host_fp_rm);
|
if (float_exception_flags & float_flag_inexact)
|
|
cpu_state.sprs[SPR_FPCSR] |= SPR_FPCSR_IXF;
|
|
/*
|
|
printf("or1ksim: post-fp-op flags from softfloat: %x%x%x%x%x\n",
|
|
!!(float_exception_flags & float_flag_invalid),
|
|
!!(float_exception_flags & float_flag_divbyzero),
|
|
!!(float_exception_flags & float_flag_overflow),
|
|
!!(float_exception_flags & float_flag_underflow),
|
|
!!(float_exception_flags & float_flag_inexact));
|
|
*/
|
// TODO: Call FP exception is FPEE set and any of the flags were set
|
// TODO: Call FP exception is FPEE set and any of the flags were set
|
/*
|
/*
|
if ((cpu_state.sprs[SPR_FPCSR] & SPR_FPCSR_FPEE) &
|
if ((cpu_state.sprs[SPR_FPCSR] & SPR_FPCSR_FPEE) &
|
(|(cpu_state.sprs[SPR_FPCSR] & SPR_FPCSR_ALLF)))
|
(|(cpu_state.sprs[SPR_FPCSR] & SPR_FPCSR_ALLF)))
|
except_handle (EXCEPT_FPE, cpu_state.iqueue.insn_addr);
|
except_handle (EXCEPT_FPE, cpu_state.iqueue.insn_addr);
|
*/
|
*/
|
|
// Now clear softfloat's flags:
|
|
float_exception_flags = 0;
|
|
|
}
|
}
|
|
|
#if COMPLEX_EXECUTION
|
#if COMPLEX_EXECUTION
|
|
|
/* Include generated/built in decode_execute function */
|
/* Include generated/built in decode_execute function */
|