TriCore bugfixes and synchronous trap implementation
-----BEGIN PGP SIGNATURE----- Version: GnuPG v2 iQIcBAABCgAGBQJWzuw1AAoJEArSxjlracoUJ/UP/0g8jF2XGXuw+FBAEZLC9RGn ZYmUrToQtsIWxUsQzKyF/q9Y5c1yAXbuO8rwrTEbX1YKF/eO2gdL0aHfgzXOajwZ o6MORUSNPY9Ml2QcsmcML/9SIANlUpGVGnfot5J10ogTf2G9aA90YH6zkwTUb2F9 c9fYGQcxhoScnTJwr+YOnRzChU1Xk7OqQzkc6U+kt6oJdfahE03ViZC/1KS5kZWK PFsH83FLBl1Jc70TY7tr44jL7EKzfq3Rc1Zw/45K3NiHFxOw7zA67Jfo9ClcHLdh kVTE1qSwUNFh9jpp5VjRFTBvNDV2C7k1iVDNPDbyU9iSdm/nFy9h9xKOVCOnPwBU jRKIXM765TzMpp/Yv648ecPuoO9Top98Cb9zc73/sZw+CjcMFpapFFdY2D+jEWYz YBRx7EsGIQV/KcmMM4bxMPB98bLkVoBgQ5effERq6zPKqmLczqWEwcLrVNfL4Cx/ q0NgsR3a9oaRga8kvrl77gCOxxjM/bzGNSXHfzHq3fXnYvnz/M7C6anWJlIULW3W kIDtQjlkwLGYwbPpp2JLTKHQwvTt8ZywryHb+0L3aenTqPUh0nbRQFCslHVlHFal DsJFWQEVkrfMDXNSeIz8PDuSynVs72pBSyJORngh5sfUZ/5IoE3/CuuBOL0mge3P VhZ3hsL18DNZzp+KY++9 =SOM3 -----END PGP SIGNATURE----- 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: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
774ae4254d
@ -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) +
|
||||
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user