提交 774ae425 编写于 作者: P Peter Maydell

Merge remote-tracking branch 'remotes/bkoppelmann/tags/pull-tricore-20160225' into staging

TriCore bugfixes and synchronous trap implementation

# gpg: Signature made Thu 25 Feb 2016 11:57:41 GMT using RSA key ID 6B69CA14
# gpg: Good signature from "Bastian Koppelmann <kbastian@mail.uni-paderborn.de>"

* remotes/bkoppelmann/tags/pull-tricore-20160225:
  target-tricore: add opd trap generation
  target-tricore: add illegal opcode trap generation
  target-tricore: add context managment trap generation
  target-tricore: Add trap handling & SOVF/OVF traps
  target-tricore: Fix wrong precedences on psw_write
  target-tricore: fix save_context_upper using env->PSW
Signed-off-by: NPeter Maydell <peter.maydell@linaro.org>
......@@ -270,6 +270,7 @@ enum {
TRAPC_ASSERT = 5,
TRAPC_SYSCALL = 6,
TRAPC_NMI = 7,
TRAPC_IRQ = 8
};
/* Class 0 TIN */
......
......@@ -127,9 +127,9 @@ uint32_t psw_read(CPUTriCoreState *env)
void psw_write(CPUTriCoreState *env, uint32_t val)
{
env->PSW_USB_C = (val & MASK_USB_C);
env->PSW_USB_V = (val & MASK_USB_V << 1);
env->PSW_USB_SV = (val & MASK_USB_SV << 2);
env->PSW_USB_AV = ((val & MASK_USB_AV) << 3);
env->PSW_USB_SAV = ((val & MASK_USB_SAV) << 4);
env->PSW_USB_V = (val & MASK_USB_V) << 1;
env->PSW_USB_SV = (val & MASK_USB_SV) << 2;
env->PSW_USB_AV = (val & MASK_USB_AV) << 3;
env->PSW_USB_SAV = (val & MASK_USB_SAV) << 4;
env->PSW = val;
}
......@@ -132,6 +132,7 @@ DEF_HELPER_2(lducx, void, env, i32)
DEF_HELPER_2(stlcx, void, env, i32)
DEF_HELPER_2(stucx, void, env, i32)
DEF_HELPER_1(svlcx, void, env)
DEF_HELPER_1(svucx, void, env)
DEF_HELPER_1(rslcx, void, env)
/* Address mode helper */
DEF_HELPER_1(br_update, i32, i32)
......@@ -139,3 +140,5 @@ DEF_HELPER_2(circ_update, i32, i32, i32)
/* PSW cache helper */
DEF_HELPER_2(psw_write, void, env, i32)
DEF_HELPER_1(psw_read, i32, env)
/* Exceptions */
DEF_HELPER_3(raise_exception_sync, noreturn, env, i32, i32)
......@@ -21,6 +21,93 @@
#include "exec/cpu_ldst.h"
#include <zlib.h> /* for crc32 */
/* Exception helpers */
static void QEMU_NORETURN
raise_exception_sync_internal(CPUTriCoreState *env, uint32_t class, int tin,
uintptr_t pc, uint32_t fcd_pc)
{
CPUState *cs = CPU(tricore_env_get_cpu(env));
/* in case we come from a helper-call we need to restore the PC */
if (pc) {
cpu_restore_state(cs, pc);
}
/* Tin is loaded into d[15] */
env->gpr_d[15] = tin;
if (class == TRAPC_CTX_MNG && tin == TIN3_FCU) {
/* upper context cannot be saved, if the context list is empty */
} else {
helper_svucx(env);
}
/* The return address in a[11] is updated */
if (class == TRAPC_CTX_MNG && tin == TIN3_FCD) {
env->SYSCON |= MASK_SYSCON_FCD_SF;
/* when we run out of CSAs after saving a context a FCD trap is taken
and the return address is the start of the trap handler which used
the last CSA */
env->gpr_a[11] = fcd_pc;
} else if (class == TRAPC_SYSCALL) {
env->gpr_a[11] = env->PC + 4;
} else {
env->gpr_a[11] = env->PC;
}
/* The stack pointer in A[10] is set to the Interrupt Stack Pointer (ISP)
when the processor was not previously using the interrupt stack
(in case of PSW.IS = 0). The stack pointer bit is set for using the
interrupt stack: PSW.IS = 1. */
if ((env->PSW & MASK_PSW_IS) == 0) {
env->gpr_a[10] = env->ISP;
}
env->PSW |= MASK_PSW_IS;
/* The I/O mode is set to Supervisor mode, which means all permissions
are enabled: PSW.IO = 10 B .*/
env->PSW |= (2 << 10);
/*The current Protection Register Set is set to 0: PSW.PRS = 00 B .*/
env->PSW &= ~MASK_PSW_PRS;
/* The Call Depth Counter (CDC) is cleared, and the call depth limit is
set for 64: PSW.CDC = 0000000 B .*/
env->PSW &= ~MASK_PSW_CDC;
/* Call Depth Counter is enabled, PSW.CDE = 1. */
env->PSW |= MASK_PSW_CDE;
/* Write permission to global registers A[0], A[1], A[8], A[9] is
disabled: PSW.GW = 0. */
env->PSW &= ~MASK_PSW_GW;
/*The interrupt system is globally disabled: ICR.IE = 0. The ‘old’
ICR.IE and ICR.CCPN are saved */
/* PCXI.PIE = ICR.IE */
env->PCXI = ((env->PCXI & ~MASK_PCXI_PIE) +
((env->ICR & MASK_ICR_IE) << 15));
/* PCXI.PCPN = ICR.CCPN */
env->PCXI = (env->PCXI & 0xffffff) +
((env->ICR & MASK_ICR_CCPN) << 24);
/* Update PC using the trap vector table */
env->PC = env->BTV | (class << 5);
cpu_loop_exit(cs);
}
void helper_raise_exception_sync(CPUTriCoreState *env, uint32_t class,
uint32_t tin)
{
raise_exception_sync_internal(env, class, tin, 0, 0);
}
static void raise_exception_sync_helper(CPUTriCoreState *env, uint32_t class,
uint32_t tin, uintptr_t pc)
{
raise_exception_sync_internal(env, class, tin, pc, 0);
}
/* Addressing mode helper */
static uint16_t reverse16(uint16_t val)
......@@ -2279,7 +2366,7 @@ static bool cdc_zero(target_ulong *psw)
static void save_context_upper(CPUTriCoreState *env, int ea)
{
cpu_stl_data(env, ea, env->PCXI);
cpu_stl_data(env, ea+4, env->PSW);
cpu_stl_data(env, ea+4, psw_read(env));
cpu_stl_data(env, ea+8, env->gpr_a[10]);
cpu_stl_data(env, ea+12, env->gpr_a[11]);
cpu_stl_data(env, ea+16, env->gpr_d[8]);
......@@ -2369,11 +2456,13 @@ void helper_call(CPUTriCoreState *env, uint32_t next_pc)
/* if (FCX == 0) trap(FCU); */
if (env->FCX == 0) {
/* FCU trap */
raise_exception_sync_helper(env, TRAPC_CTX_MNG, TIN3_FCU, GETPC());
}
/* if (PSW.CDE) then if (cdc_increment()) then trap(CDO); */
if (psw & MASK_PSW_CDE) {
if (cdc_increment(&psw)) {
/* CDO trap */
raise_exception_sync_helper(env, TRAPC_CTX_MNG, TIN3_CDO, GETPC());
}
}
/* PSW.CDE = 1;*/
......@@ -2409,6 +2498,7 @@ void helper_call(CPUTriCoreState *env, uint32_t next_pc)
/* if (tmp_FCX == LCX) trap(FCD);*/
if (tmp_FCX == env->LCX) {
/* FCD trap */
raise_exception_sync_helper(env, TRAPC_CTX_MNG, TIN3_FCD, GETPC());
}
psw_write(env, psw);
}
......@@ -2421,18 +2511,25 @@ void helper_ret(CPUTriCoreState *env)
psw = psw_read(env);
/* if (PSW.CDE) then if (cdc_decrement()) then trap(CDU);*/
if (env->PSW & MASK_PSW_CDE) {
if (cdc_decrement(&(env->PSW))) {
if (psw & MASK_PSW_CDE) {
if (cdc_decrement(&psw)) {
/* CDU trap */
psw_write(env, psw);
raise_exception_sync_helper(env, TRAPC_CTX_MNG, TIN3_CDU, GETPC());
}
}
/* if (PCXI[19: 0] == 0) then trap(CSU); */
if ((env->PCXI & 0xfffff) == 0) {
/* CSU trap */
psw_write(env, psw);
raise_exception_sync_helper(env, TRAPC_CTX_MNG, TIN3_CSU, GETPC());
}
/* if (PCXI.UL == 0) then trap(CTYP); */
if ((env->PCXI & MASK_PCXI_UL) == 0) {
/* CTYP trap */
cdc_increment(&psw); /* restore to the start of helper */
psw_write(env, psw);
raise_exception_sync_helper(env, TRAPC_CTX_MNG, TIN3_CTYP, GETPC());
}
/* PC = {A11 [31: 1], 1’b0}; */
env->PC = env->gpr_a[11] & 0xfffffffe;
......@@ -2467,6 +2564,7 @@ void helper_bisr(CPUTriCoreState *env, uint32_t const9)
if (env->FCX == 0) {
/* FCU trap */
raise_exception_sync_helper(env, TRAPC_CTX_MNG, TIN3_FCU, GETPC());
}
tmp_FCX = env->FCX;
......@@ -2498,6 +2596,7 @@ void helper_bisr(CPUTriCoreState *env, uint32_t const9)
if (tmp_FCX == env->LCX) {
/* FCD trap */
raise_exception_sync_helper(env, TRAPC_CTX_MNG, TIN3_FCD, GETPC());
}
}
......@@ -2509,14 +2608,17 @@ void helper_rfe(CPUTriCoreState *env)
/* if (PCXI[19: 0] == 0) then trap(CSU); */
if ((env->PCXI & 0xfffff) == 0) {
/* raise csu trap */
raise_exception_sync_helper(env, TRAPC_CTX_MNG, TIN3_CSU, GETPC());
}
/* if (PCXI.UL == 0) then trap(CTYP); */
if ((env->PCXI & MASK_PCXI_UL) == 0) {
/* raise CTYP trap */
raise_exception_sync_helper(env, TRAPC_CTX_MNG, TIN3_CTYP, GETPC());
}
/* if (!cdc_zero() AND PSW.CDE) then trap(NEST); */
if (!cdc_zero(&(env->PSW)) && (env->PSW & MASK_PSW_CDE)) {
/* raise MNG trap */
/* raise NEST trap */
raise_exception_sync_helper(env, TRAPC_CTX_MNG, TIN3_NEST, GETPC());
}
env->PC = env->gpr_a[11] & ~0x1;
/* ICR.IE = PCXI.PIE; */
......@@ -2592,6 +2694,7 @@ void helper_svlcx(CPUTriCoreState *env)
if (env->FCX == 0) {
/* FCU trap */
raise_exception_sync_helper(env, TRAPC_CTX_MNG, TIN3_FCU, GETPC());
}
/* tmp_FCX = FCX; */
tmp_FCX = env->FCX;
......@@ -2622,6 +2725,50 @@ void helper_svlcx(CPUTriCoreState *env)
/* if (tmp_FCX == LCX) trap(FCD);*/
if (tmp_FCX == env->LCX) {
/* FCD trap */
raise_exception_sync_helper(env, TRAPC_CTX_MNG, TIN3_FCD, GETPC());
}
}
void helper_svucx(CPUTriCoreState *env)
{
target_ulong tmp_FCX;
target_ulong ea;
target_ulong new_FCX;
if (env->FCX == 0) {
/* FCU trap */
raise_exception_sync_helper(env, TRAPC_CTX_MNG, TIN3_FCU, GETPC());
}
/* tmp_FCX = FCX; */
tmp_FCX = env->FCX;
/* EA = {FCX.FCXS, 6'b0, FCX.FCXO, 6'b0}; */
ea = ((env->FCX & MASK_FCX_FCXS) << 12) +
((env->FCX & MASK_FCX_FCXO) << 6);
/* new_FCX = M(EA, word); */
new_FCX = cpu_ldl_data(env, ea);
/* M(EA, 16 * word) = {PCXI, PSW, A[10], A[11], D[8], D[9], D[10], D[11],
A[12], A[13], A[14], A[15], D[12], D[13], D[14],
D[15]}; */
save_context_upper(env, ea);
/* PCXI.PCPN = ICR.CCPN; */
env->PCXI = (env->PCXI & 0xffffff) +
((env->ICR & MASK_ICR_CCPN) << 24);
/* PCXI.PIE = ICR.IE; */
env->PCXI = ((env->PCXI & ~MASK_PCXI_PIE) +
((env->ICR & MASK_ICR_IE) << 15));
/* PCXI.UL = 1; */
env->PCXI |= MASK_PCXI_UL;
/* PCXI[19: 0] = FCX[19: 0]; */
env->PCXI = (env->PCXI & 0xfff00000) + (env->FCX & 0xfffff);
/* FCX[19: 0] = new_FCX[19: 0]; */
env->FCX = (env->FCX & 0xfff00000) + (new_FCX & 0xfffff);
/* if (tmp_FCX == LCX) trap(FCD);*/
if (tmp_FCX == env->LCX) {
/* FCD trap */
raise_exception_sync_helper(env, TRAPC_CTX_MNG, TIN3_FCD, GETPC());
}
}
......@@ -2632,10 +2779,12 @@ void helper_rslcx(CPUTriCoreState *env)
/* if (PCXI[19: 0] == 0) then trap(CSU); */
if ((env->PCXI & 0xfffff) == 0) {
/* CSU trap */
raise_exception_sync_helper(env, TRAPC_CTX_MNG, TIN3_CSU, GETPC());
}
/* if (PCXI.UL == 1) then trap(CTYP); */
if ((env->PCXI & MASK_PCXI_UL) != 0) {
/* CTYP trap */
raise_exception_sync_helper(env, TRAPC_CTX_MNG, TIN3_CTYP, GETPC());
}
/* EA = {PCXI.PCXS, 6'b0, PCXI.PCXO, 6'b0}; */
ea = ((env->PCXI & MASK_PCXI_PCXS) << 12) +
......
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册