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:
Peter Maydell 2016-02-25 12:57:22 +00:00
commit 774ae4254d
5 changed files with 615 additions and 37 deletions

View File

@ -270,6 +270,7 @@ enum {
TRAPC_ASSERT = 5,
TRAPC_SYSCALL = 6,
TRAPC_NMI = 7,
TRAPC_IRQ = 8
};
/* Class 0 TIN */

View File

@ -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;
}

View File

@ -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)

View File

@ -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], 1b0}; */
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