mirror of https://github.com/xemu-project/xemu.git
- Refactor PCXI/ICR field handling in newer ISA versions
- Add simple tests written in C -----BEGIN PGP SIGNATURE----- iQJTBAABCgA9FiEEbmNqfoPy3Qz6bm43CtLGOWtpyhQFAmSArqkfHGtiYXN0aWFu QG1haWwudW5pLXBhZGVyYm9ybi5kZQAKCRAK0sY5a2nKFKKTD/0dXpexGX7K62d4 dLZwj9AHOa/9NOD4E6+ub2UYovF7UlydSzy+mgJyxiIUGaPBHYe3dFfktHOppSwn OGJp9TTqeutpXYF8/zvDnmf+TDJ71DRQWM40uC0HAUXrjUO43PiK0LMh+fm5D9uG vRHSDGBWUNZrNxTZSj8Kx7Sb7PkqeB8qWvpIJh1AVVhIT+dyoAp5V7EkAETpwhtz a7qKclQpFNWdaYnthCF5wcmoMawQKMUnO96j0lQWIXfnhDP7XmrWlNM7Ry2cMPEy aRxAT3hTOr2dD2Cic8brF/w1NeXJjxWDz65uD7X7Rog54+SD4+SmfZiYwdAs5YMo 1XTkbG0qE6HwrtaO+nZDQZFc8tdvLSlDcBd/cjOonwxJyvJVX8qjR2Ufb3PSfTct 85R5wRBsEapSbQwicwu71fK0N8ZVkLM3fc4nFEKMxOx8I66eJm3bcTxpT/A8knEw OwykEVB3Xiq45JlWOV2BkyZJ1EiHeFQzZfzckW4bYFDdCnuMHlaVG9qpKEAu7mQh 4Ug3Y4KhYqZA0UDHG6Ik6Ms64FYU4s+zbFYic/Jhew9NC4MoMXa8oKqXJC5W7RCl 1HesyBPu1i/45Xk6/kneJ16YO+i4hcH+Hp/osJrRE6qFHGtbvKJ0EFy1471YHyLf HjRQBmsd9XW2TaYBQgST80UvCh9CkQ== =5m1P -----END PGP SIGNATURE----- Merge tag 'pull-tricore-20230607' of https://github.com/bkoppelmann/qemu into staging - Refactor PCXI/ICR field handling in newer ISA versions - Add simple tests written in C # -----BEGIN PGP SIGNATURE----- # # iQJTBAABCgA9FiEEbmNqfoPy3Qz6bm43CtLGOWtpyhQFAmSArqkfHGtiYXN0aWFu # QG1haWwudW5pLXBhZGVyYm9ybi5kZQAKCRAK0sY5a2nKFKKTD/0dXpexGX7K62d4 # dLZwj9AHOa/9NOD4E6+ub2UYovF7UlydSzy+mgJyxiIUGaPBHYe3dFfktHOppSwn # OGJp9TTqeutpXYF8/zvDnmf+TDJ71DRQWM40uC0HAUXrjUO43PiK0LMh+fm5D9uG # vRHSDGBWUNZrNxTZSj8Kx7Sb7PkqeB8qWvpIJh1AVVhIT+dyoAp5V7EkAETpwhtz # a7qKclQpFNWdaYnthCF5wcmoMawQKMUnO96j0lQWIXfnhDP7XmrWlNM7Ry2cMPEy # aRxAT3hTOr2dD2Cic8brF/w1NeXJjxWDz65uD7X7Rog54+SD4+SmfZiYwdAs5YMo # 1XTkbG0qE6HwrtaO+nZDQZFc8tdvLSlDcBd/cjOonwxJyvJVX8qjR2Ufb3PSfTct # 85R5wRBsEapSbQwicwu71fK0N8ZVkLM3fc4nFEKMxOx8I66eJm3bcTxpT/A8knEw # OwykEVB3Xiq45JlWOV2BkyZJ1EiHeFQzZfzckW4bYFDdCnuMHlaVG9qpKEAu7mQh # 4Ug3Y4KhYqZA0UDHG6Ik6Ms64FYU4s+zbFYic/Jhew9NC4MoMXa8oKqXJC5W7RCl # 1HesyBPu1i/45Xk6/kneJ16YO+i4hcH+Hp/osJrRE6qFHGtbvKJ0EFy1471YHyLf # HjRQBmsd9XW2TaYBQgST80UvCh9CkQ== # =5m1P # -----END PGP SIGNATURE----- # gpg: Signature made Wed 07 Jun 2023 09:22:01 AM PDT # gpg: using RSA key 6E636A7E83F2DD0CFA6E6E370AD2C6396B69CA14 # gpg: issuer "kbastian@mail.uni-paderborn.de" # gpg: Good signature from "Bastian Koppelmann <kbastian@mail.uni-paderborn.de>" [unknown] # gpg: WARNING: This key is not certified with a trusted signature! # gpg: There is no indication that the signature belongs to the owner. # Primary key fingerprint: 6E63 6A7E 83F2 DD0C FA6E 6E37 0AD2 C639 6B69 CA14 * tag 'pull-tricore-20230607' of https://github.com/bkoppelmann/qemu: tests/tcg/tricore: Add recursion test for CSAs target/tricore: Fix wrong PSW for call insns target/tricore: Refactor PCXI/ICR register fields tests/tcg/tricore: Add first C program tests/tcg/tricore: Uses label for memory addresses tests/tcg/tricore: Move asm tests into 'asm' directory Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
commit
45ae97993a
|
@ -1383,6 +1383,7 @@ probe_target_compiler() {
|
||||||
container_cross_prefix=tricore-
|
container_cross_prefix=tricore-
|
||||||
container_cross_as=tricore-as
|
container_cross_as=tricore-as
|
||||||
container_cross_ld=tricore-ld
|
container_cross_ld=tricore-ld
|
||||||
|
container_cross_cc=tricore-gcc
|
||||||
break
|
break
|
||||||
;;
|
;;
|
||||||
x86_64)
|
x86_64)
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#define TRICORE_CPU_H
|
#define TRICORE_CPU_H
|
||||||
|
|
||||||
#include "cpu-qom.h"
|
#include "cpu-qom.h"
|
||||||
|
#include "hw/registerfields.h"
|
||||||
#include "exec/cpu-defs.h"
|
#include "exec/cpu-defs.h"
|
||||||
#include "qemu/cpu-float.h"
|
#include "qemu/cpu-float.h"
|
||||||
#include "tricore-defs.h"
|
#include "tricore-defs.h"
|
||||||
|
@ -199,13 +200,33 @@ struct ArchCPU {
|
||||||
hwaddr tricore_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
|
hwaddr tricore_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
|
||||||
void tricore_cpu_dump_state(CPUState *cpu, FILE *f, int flags);
|
void tricore_cpu_dump_state(CPUState *cpu, FILE *f, int flags);
|
||||||
|
|
||||||
|
FIELD(PCXI, PCPN_13, 24, 8)
|
||||||
|
FIELD(PCXI, PCPN_161, 22, 8)
|
||||||
|
FIELD(PCXI, PIE_13, 23, 1)
|
||||||
|
FIELD(PCXI, PIE_161, 21, 1)
|
||||||
|
FIELD(PCXI, UL_13, 22, 1)
|
||||||
|
FIELD(PCXI, UL_161, 20, 1)
|
||||||
|
FIELD(PCXI, PCXS, 16, 4)
|
||||||
|
FIELD(PCXI, PCXO, 0, 16)
|
||||||
|
uint32_t pcxi_get_ul(CPUTriCoreState *env);
|
||||||
|
uint32_t pcxi_get_pie(CPUTriCoreState *env);
|
||||||
|
uint32_t pcxi_get_pcpn(CPUTriCoreState *env);
|
||||||
|
uint32_t pcxi_get_pcxs(CPUTriCoreState *env);
|
||||||
|
uint32_t pcxi_get_pcxo(CPUTriCoreState *env);
|
||||||
|
void pcxi_set_ul(CPUTriCoreState *env, uint32_t val);
|
||||||
|
void pcxi_set_pie(CPUTriCoreState *env, uint32_t val);
|
||||||
|
void pcxi_set_pcpn(CPUTriCoreState *env, uint32_t val);
|
||||||
|
|
||||||
#define MASK_PCXI_PCPN 0xff000000
|
FIELD(ICR, IE_161, 15, 1)
|
||||||
#define MASK_PCXI_PIE_1_3 0x00800000
|
FIELD(ICR, IE_13, 8, 1)
|
||||||
#define MASK_PCXI_PIE_1_6 0x00200000
|
FIELD(ICR, PIPN, 16, 8)
|
||||||
#define MASK_PCXI_UL 0x00400000
|
FIELD(ICR, CCPN, 0, 8)
|
||||||
#define MASK_PCXI_PCXS 0x000f0000
|
|
||||||
#define MASK_PCXI_PCXO 0x0000ffff
|
uint32_t icr_get_ie(CPUTriCoreState *env);
|
||||||
|
uint32_t icr_get_ccpn(CPUTriCoreState *env);
|
||||||
|
|
||||||
|
void icr_set_ccpn(CPUTriCoreState *env, uint32_t val);
|
||||||
|
void icr_set_ie(CPUTriCoreState *env, uint32_t val);
|
||||||
|
|
||||||
#define MASK_PSW_USB 0xff000000
|
#define MASK_PSW_USB 0xff000000
|
||||||
#define MASK_USB_C 0x80000000
|
#define MASK_USB_C 0x80000000
|
||||||
|
@ -228,10 +249,6 @@ void tricore_cpu_dump_state(CPUState *cpu, FILE *f, int flags);
|
||||||
#define MASK_CPUID_MOD_32B 0x0000ff00
|
#define MASK_CPUID_MOD_32B 0x0000ff00
|
||||||
#define MASK_CPUID_REV 0x000000ff
|
#define MASK_CPUID_REV 0x000000ff
|
||||||
|
|
||||||
#define MASK_ICR_PIPN 0x00ff0000
|
|
||||||
#define MASK_ICR_IE_1_3 0x00000100
|
|
||||||
#define MASK_ICR_IE_1_6 0x00008000
|
|
||||||
#define MASK_ICR_CCPN 0x000000ff
|
|
||||||
|
|
||||||
#define MASK_FCX_FCXS 0x000f0000
|
#define MASK_FCX_FCXS 0x000f0000
|
||||||
#define MASK_FCX_FCXO 0x0000ffff
|
#define MASK_FCX_FCXO 0x0000ffff
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
|
|
||||||
#include "qemu/osdep.h"
|
#include "qemu/osdep.h"
|
||||||
#include "qemu/log.h"
|
#include "qemu/log.h"
|
||||||
|
#include "hw/registerfields.h"
|
||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
#include "exec/exec-all.h"
|
#include "exec/exec-all.h"
|
||||||
#include "fpu/softfloat-helpers.h"
|
#include "fpu/softfloat-helpers.h"
|
||||||
|
@ -152,3 +153,47 @@ void psw_write(CPUTriCoreState *env, uint32_t val)
|
||||||
|
|
||||||
fpu_set_state(env);
|
fpu_set_state(env);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define FIELD_GETTER_WITH_FEATURE(NAME, REG, FIELD, FEATURE) \
|
||||||
|
uint32_t NAME(CPUTriCoreState *env) \
|
||||||
|
{ \
|
||||||
|
if (tricore_feature(env, TRICORE_FEATURE_##FEATURE)) { \
|
||||||
|
return FIELD_EX32(env->REG, REG, FIELD ## _ ## FEATURE); \
|
||||||
|
} \
|
||||||
|
return FIELD_EX32(env->REG, REG, FIELD ## _13); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define FIELD_GETTER(NAME, REG, FIELD) \
|
||||||
|
uint32_t NAME(CPUTriCoreState *env) \
|
||||||
|
{ \
|
||||||
|
return FIELD_EX32(env->REG, REG, FIELD); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define FIELD_SETTER_WITH_FEATURE(NAME, REG, FIELD, FEATURE) \
|
||||||
|
void NAME(CPUTriCoreState *env, uint32_t val) \
|
||||||
|
{ \
|
||||||
|
if (tricore_feature(env, TRICORE_FEATURE_##FEATURE)) { \
|
||||||
|
env->REG = FIELD_DP32(env->REG, REG, FIELD ## _ ## FEATURE, val); \
|
||||||
|
} \
|
||||||
|
env->REG = FIELD_DP32(env->REG, REG, FIELD ## _13, val); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define FIELD_SETTER(NAME, REG, FIELD) \
|
||||||
|
void NAME(CPUTriCoreState *env, uint32_t val) \
|
||||||
|
{ \
|
||||||
|
env->REG = FIELD_DP32(env->REG, REG, FIELD, val); \
|
||||||
|
}
|
||||||
|
|
||||||
|
FIELD_GETTER_WITH_FEATURE(pcxi_get_pcpn, PCXI, PCPN, 161)
|
||||||
|
FIELD_SETTER_WITH_FEATURE(pcxi_set_pcpn, PCXI, PCPN, 161)
|
||||||
|
FIELD_GETTER_WITH_FEATURE(pcxi_get_pie, PCXI, PIE, 161)
|
||||||
|
FIELD_SETTER_WITH_FEATURE(pcxi_set_pie, PCXI, PIE, 161)
|
||||||
|
FIELD_GETTER_WITH_FEATURE(pcxi_get_ul, PCXI, UL, 161)
|
||||||
|
FIELD_SETTER_WITH_FEATURE(pcxi_set_ul, PCXI, UL, 161)
|
||||||
|
FIELD_GETTER(pcxi_get_pcxs, PCXI, PCXS)
|
||||||
|
FIELD_GETTER(pcxi_get_pcxo, PCXI, PCXO)
|
||||||
|
|
||||||
|
FIELD_GETTER_WITH_FEATURE(icr_get_ie, ICR, IE, 161)
|
||||||
|
FIELD_SETTER_WITH_FEATURE(icr_set_ie, ICR, IE, 161)
|
||||||
|
FIELD_GETTER(icr_get_ccpn, ICR, CCPN)
|
||||||
|
FIELD_SETTER(icr_set_ccpn, ICR, CCPN)
|
||||||
|
|
|
@ -84,11 +84,10 @@ void raise_exception_sync_internal(CPUTriCoreState *env, uint32_t class, int tin
|
||||||
ICR.IE and ICR.CCPN are saved */
|
ICR.IE and ICR.CCPN are saved */
|
||||||
|
|
||||||
/* PCXI.PIE = ICR.IE */
|
/* PCXI.PIE = ICR.IE */
|
||||||
env->PCXI = ((env->PCXI & ~MASK_PCXI_PIE_1_3) +
|
pcxi_set_pie(env, icr_get_ie(env));
|
||||||
((env->ICR & MASK_ICR_IE_1_3) << 15));
|
|
||||||
/* PCXI.PCPN = ICR.CCPN */
|
/* PCXI.PCPN = ICR.CCPN */
|
||||||
env->PCXI = (env->PCXI & 0xffffff) +
|
pcxi_set_pcpn(env, icr_get_ccpn(env));
|
||||||
((env->ICR & MASK_ICR_CCPN) << 24);
|
|
||||||
/* Update PC using the trap vector table */
|
/* Update PC using the trap vector table */
|
||||||
env->PC = env->BTV | (class << 5);
|
env->PC = env->BTV | (class << 5);
|
||||||
|
|
||||||
|
@ -2448,6 +2447,8 @@ void helper_call(CPUTriCoreState *env, uint32_t next_pc)
|
||||||
}
|
}
|
||||||
/* PSW.CDE = 1;*/
|
/* PSW.CDE = 1;*/
|
||||||
psw |= MASK_PSW_CDE;
|
psw |= MASK_PSW_CDE;
|
||||||
|
psw_write(env, psw);
|
||||||
|
|
||||||
/* tmp_FCX = FCX; */
|
/* tmp_FCX = FCX; */
|
||||||
tmp_FCX = env->FCX;
|
tmp_FCX = env->FCX;
|
||||||
/* EA = {FCX.FCXS, 6'b0, FCX.FCXO, 6'b0}; */
|
/* EA = {FCX.FCXS, 6'b0, FCX.FCXO, 6'b0}; */
|
||||||
|
@ -2461,13 +2462,11 @@ void helper_call(CPUTriCoreState *env, uint32_t next_pc)
|
||||||
save_context_upper(env, ea);
|
save_context_upper(env, ea);
|
||||||
|
|
||||||
/* PCXI.PCPN = ICR.CCPN; */
|
/* PCXI.PCPN = ICR.CCPN; */
|
||||||
env->PCXI = (env->PCXI & 0xffffff) +
|
pcxi_set_pcpn(env, icr_get_ccpn(env));
|
||||||
((env->ICR & MASK_ICR_CCPN) << 24);
|
|
||||||
/* PCXI.PIE = ICR.IE; */
|
/* PCXI.PIE = ICR.IE; */
|
||||||
env->PCXI = ((env->PCXI & ~MASK_PCXI_PIE_1_3) +
|
pcxi_set_pie(env, icr_get_ie(env));
|
||||||
((env->ICR & MASK_ICR_IE_1_3) << 15));
|
|
||||||
/* PCXI.UL = 1; */
|
/* PCXI.UL = 1; */
|
||||||
env->PCXI |= MASK_PCXI_UL;
|
pcxi_set_ul(env, 1);
|
||||||
|
|
||||||
/* PCXI[19: 0] = FCX[19: 0]; */
|
/* PCXI[19: 0] = FCX[19: 0]; */
|
||||||
env->PCXI = (env->PCXI & 0xfff00000) + (env->FCX & 0xfffff);
|
env->PCXI = (env->PCXI & 0xfff00000) + (env->FCX & 0xfffff);
|
||||||
|
@ -2506,7 +2505,7 @@ void helper_ret(CPUTriCoreState *env)
|
||||||
raise_exception_sync_helper(env, TRAPC_CTX_MNG, TIN3_CSU, GETPC());
|
raise_exception_sync_helper(env, TRAPC_CTX_MNG, TIN3_CSU, GETPC());
|
||||||
}
|
}
|
||||||
/* if (PCXI.UL == 0) then trap(CTYP); */
|
/* if (PCXI.UL == 0) then trap(CTYP); */
|
||||||
if ((env->PCXI & MASK_PCXI_UL) == 0) {
|
if (pcxi_get_ul(env) == 0) {
|
||||||
/* CTYP trap */
|
/* CTYP trap */
|
||||||
cdc_increment(&psw); /* restore to the start of helper */
|
cdc_increment(&psw); /* restore to the start of helper */
|
||||||
psw_write(env, psw);
|
psw_write(env, psw);
|
||||||
|
@ -2516,8 +2515,8 @@ void helper_ret(CPUTriCoreState *env)
|
||||||
env->PC = env->gpr_a[11] & 0xfffffffe;
|
env->PC = env->gpr_a[11] & 0xfffffffe;
|
||||||
|
|
||||||
/* EA = {PCXI.PCXS, 6'b0, PCXI.PCXO, 6'b0}; */
|
/* EA = {PCXI.PCXS, 6'b0, PCXI.PCXO, 6'b0}; */
|
||||||
ea = ((env->PCXI & MASK_PCXI_PCXS) << 12) +
|
ea = (pcxi_get_pcxs(env) << 28) |
|
||||||
((env->PCXI & MASK_PCXI_PCXO) << 6);
|
(pcxi_get_pcxo(env) << 6);
|
||||||
/* {new_PCXI, new_PSW, A[10], A[11], D[8], D[9], D[10], D[11], A[12],
|
/* {new_PCXI, new_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]} = M(EA, 16 * word); */
|
A[13], A[14], A[15], D[12], D[13], D[14], D[15]} = M(EA, 16 * word); */
|
||||||
restore_context_upper(env, ea, &new_PCXI, &new_PSW);
|
restore_context_upper(env, ea, &new_PCXI, &new_PSW);
|
||||||
|
@ -2559,21 +2558,21 @@ void helper_bisr(CPUTriCoreState *env, uint32_t const9)
|
||||||
|
|
||||||
|
|
||||||
/* PCXI.PCPN = ICR.CCPN */
|
/* PCXI.PCPN = ICR.CCPN */
|
||||||
env->PCXI = (env->PCXI & 0xffffff) +
|
pcxi_set_pcpn(env, icr_get_ccpn(env));
|
||||||
((env->ICR & MASK_ICR_CCPN) << 24);
|
|
||||||
/* PCXI.PIE = ICR.IE */
|
/* PCXI.PIE = ICR.IE */
|
||||||
env->PCXI = ((env->PCXI & ~MASK_PCXI_PIE_1_3) +
|
pcxi_set_pie(env, icr_get_ie(env));
|
||||||
((env->ICR & MASK_ICR_IE_1_3) << 15));
|
|
||||||
/* PCXI.UL = 0 */
|
/* PCXI.UL = 0 */
|
||||||
env->PCXI &= ~(MASK_PCXI_UL);
|
pcxi_set_ul(env, 0);
|
||||||
|
|
||||||
/* PCXI[19: 0] = FCX[19: 0] */
|
/* PCXI[19: 0] = FCX[19: 0] */
|
||||||
env->PCXI = (env->PCXI & 0xfff00000) + (env->FCX & 0xfffff);
|
env->PCXI = (env->PCXI & 0xfff00000) + (env->FCX & 0xfffff);
|
||||||
/* FXC[19: 0] = new_FCX[19: 0] */
|
/* FXC[19: 0] = new_FCX[19: 0] */
|
||||||
env->FCX = (env->FCX & 0xfff00000) + (new_FCX & 0xfffff);
|
env->FCX = (env->FCX & 0xfff00000) + (new_FCX & 0xfffff);
|
||||||
/* ICR.IE = 1 */
|
|
||||||
env->ICR |= MASK_ICR_IE_1_3;
|
|
||||||
|
|
||||||
env->ICR |= const9; /* ICR.CCPN = const9[7: 0];*/
|
/* ICR.IE = 1 */
|
||||||
|
icr_set_ie(env, 1);
|
||||||
|
|
||||||
|
icr_set_ccpn(env, const9);
|
||||||
|
|
||||||
if (tmp_FCX == env->LCX) {
|
if (tmp_FCX == env->LCX) {
|
||||||
/* FCD trap */
|
/* FCD trap */
|
||||||
|
@ -2592,7 +2591,7 @@ void helper_rfe(CPUTriCoreState *env)
|
||||||
raise_exception_sync_helper(env, TRAPC_CTX_MNG, TIN3_CSU, GETPC());
|
raise_exception_sync_helper(env, TRAPC_CTX_MNG, TIN3_CSU, GETPC());
|
||||||
}
|
}
|
||||||
/* if (PCXI.UL == 0) then trap(CTYP); */
|
/* if (PCXI.UL == 0) then trap(CTYP); */
|
||||||
if ((env->PCXI & MASK_PCXI_UL) == 0) {
|
if (pcxi_get_ul(env) == 0) {
|
||||||
/* raise CTYP trap */
|
/* raise CTYP trap */
|
||||||
raise_exception_sync_helper(env, TRAPC_CTX_MNG, TIN3_CTYP, GETPC());
|
raise_exception_sync_helper(env, TRAPC_CTX_MNG, TIN3_CTYP, GETPC());
|
||||||
}
|
}
|
||||||
|
@ -2603,14 +2602,15 @@ void helper_rfe(CPUTriCoreState *env)
|
||||||
}
|
}
|
||||||
env->PC = env->gpr_a[11] & ~0x1;
|
env->PC = env->gpr_a[11] & ~0x1;
|
||||||
/* ICR.IE = PCXI.PIE; */
|
/* ICR.IE = PCXI.PIE; */
|
||||||
env->ICR = (env->ICR & ~MASK_ICR_IE_1_3)
|
icr_set_ie(env, pcxi_get_pie(env));
|
||||||
+ ((env->PCXI & MASK_PCXI_PIE_1_3) >> 15);
|
|
||||||
/* ICR.CCPN = PCXI.PCPN; */
|
/* ICR.CCPN = PCXI.PCPN; */
|
||||||
env->ICR = (env->ICR & ~MASK_ICR_CCPN) +
|
icr_set_ccpn(env, pcxi_get_pcpn(env));
|
||||||
((env->PCXI & MASK_PCXI_PCPN) >> 24);
|
|
||||||
/*EA = {PCXI.PCXS, 6'b0, PCXI.PCXO, 6'b0};*/
|
/*EA = {PCXI.PCXS, 6'b0, PCXI.PCXO, 6'b0};*/
|
||||||
ea = ((env->PCXI & MASK_PCXI_PCXS) << 12) +
|
ea = (pcxi_get_pcxs(env) << 28) |
|
||||||
((env->PCXI & MASK_PCXI_PCXO) << 6);
|
(pcxi_get_pcxo(env) << 6);
|
||||||
|
|
||||||
/*{new_PCXI, PSW, A[10], A[11], D[8], D[9], D[10], D[11], A[12],
|
/*{new_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]} = M(EA, 16 * word); */
|
A[13], A[14], A[15], D[12], D[13], D[14], D[15]} = M(EA, 16 * word); */
|
||||||
restore_context_upper(env, ea, &new_PCXI, &new_PSW);
|
restore_context_upper(env, ea, &new_PCXI, &new_PSW);
|
||||||
|
@ -2628,11 +2628,10 @@ void helper_rfm(CPUTriCoreState *env)
|
||||||
{
|
{
|
||||||
env->PC = (env->gpr_a[11] & ~0x1);
|
env->PC = (env->gpr_a[11] & ~0x1);
|
||||||
/* ICR.IE = PCXI.PIE; */
|
/* ICR.IE = PCXI.PIE; */
|
||||||
env->ICR = (env->ICR & ~MASK_ICR_IE_1_3)
|
icr_set_ie(env, pcxi_get_pie(env));
|
||||||
| ((env->PCXI & MASK_PCXI_PIE_1_3) >> 15);
|
|
||||||
/* ICR.CCPN = PCXI.PCPN; */
|
/* ICR.CCPN = PCXI.PCPN; */
|
||||||
env->ICR = (env->ICR & ~MASK_ICR_CCPN) |
|
icr_set_ccpn(env, pcxi_get_pcpn(env));
|
||||||
((env->PCXI & MASK_PCXI_PCPN) >> 24);
|
|
||||||
/* {PCXI, PSW, A[10], A[11]} = M(DCX, 4 * word); */
|
/* {PCXI, PSW, A[10], A[11]} = M(DCX, 4 * word); */
|
||||||
env->PCXI = cpu_ldl_data(env, env->DCX);
|
env->PCXI = cpu_ldl_data(env, env->DCX);
|
||||||
psw_write(env, cpu_ldl_data(env, env->DCX+4));
|
psw_write(env, cpu_ldl_data(env, env->DCX+4));
|
||||||
|
@ -2691,13 +2690,13 @@ void helper_svlcx(CPUTriCoreState *env)
|
||||||
save_context_lower(env, ea);
|
save_context_lower(env, ea);
|
||||||
|
|
||||||
/* PCXI.PCPN = ICR.CCPN; */
|
/* PCXI.PCPN = ICR.CCPN; */
|
||||||
env->PCXI = (env->PCXI & 0xffffff) +
|
pcxi_set_pcpn(env, icr_get_ccpn(env));
|
||||||
((env->ICR & MASK_ICR_CCPN) << 24);
|
|
||||||
/* PCXI.PIE = ICR.IE; */
|
/* PCXI.PIE = ICR.IE; */
|
||||||
env->PCXI = ((env->PCXI & ~MASK_PCXI_PIE_1_3) +
|
pcxi_set_pie(env, icr_get_ie(env));
|
||||||
((env->ICR & MASK_ICR_IE_1_3) << 15));
|
|
||||||
/* PCXI.UL = 0; */
|
/* PCXI.UL = 0; */
|
||||||
env->PCXI &= ~MASK_PCXI_UL;
|
pcxi_set_ul(env, 0);
|
||||||
|
|
||||||
/* PCXI[19: 0] = FCX[19: 0]; */
|
/* PCXI[19: 0] = FCX[19: 0]; */
|
||||||
env->PCXI = (env->PCXI & 0xfff00000) + (env->FCX & 0xfffff);
|
env->PCXI = (env->PCXI & 0xfff00000) + (env->FCX & 0xfffff);
|
||||||
|
@ -2734,13 +2733,13 @@ void helper_svucx(CPUTriCoreState *env)
|
||||||
save_context_upper(env, ea);
|
save_context_upper(env, ea);
|
||||||
|
|
||||||
/* PCXI.PCPN = ICR.CCPN; */
|
/* PCXI.PCPN = ICR.CCPN; */
|
||||||
env->PCXI = (env->PCXI & 0xffffff) +
|
pcxi_set_pcpn(env, icr_get_ccpn(env));
|
||||||
((env->ICR & MASK_ICR_CCPN) << 24);
|
|
||||||
/* PCXI.PIE = ICR.IE; */
|
/* PCXI.PIE = ICR.IE; */
|
||||||
env->PCXI = ((env->PCXI & ~MASK_PCXI_PIE_1_3) +
|
pcxi_set_pie(env, icr_get_ie(env));
|
||||||
((env->ICR & MASK_ICR_IE_1_3) << 15));
|
|
||||||
/* PCXI.UL = 1; */
|
/* PCXI.UL = 1; */
|
||||||
env->PCXI |= MASK_PCXI_UL;
|
pcxi_set_ul(env, 1);
|
||||||
|
|
||||||
/* PCXI[19: 0] = FCX[19: 0]; */
|
/* PCXI[19: 0] = FCX[19: 0]; */
|
||||||
env->PCXI = (env->PCXI & 0xfff00000) + (env->FCX & 0xfffff);
|
env->PCXI = (env->PCXI & 0xfff00000) + (env->FCX & 0xfffff);
|
||||||
|
@ -2764,13 +2763,15 @@ void helper_rslcx(CPUTriCoreState *env)
|
||||||
raise_exception_sync_helper(env, TRAPC_CTX_MNG, TIN3_CSU, GETPC());
|
raise_exception_sync_helper(env, TRAPC_CTX_MNG, TIN3_CSU, GETPC());
|
||||||
}
|
}
|
||||||
/* if (PCXI.UL == 1) then trap(CTYP); */
|
/* if (PCXI.UL == 1) then trap(CTYP); */
|
||||||
if ((env->PCXI & MASK_PCXI_UL) != 0) {
|
if (pcxi_get_ul(env) == 1) {
|
||||||
/* CTYP trap */
|
/* CTYP trap */
|
||||||
raise_exception_sync_helper(env, TRAPC_CTX_MNG, TIN3_CTYP, GETPC());
|
raise_exception_sync_helper(env, TRAPC_CTX_MNG, TIN3_CTYP, GETPC());
|
||||||
}
|
}
|
||||||
/* EA = {PCXI.PCXS, 6'b0, PCXI.PCXO, 6'b0}; */
|
/* EA = {PCXI.PCXS, 6'b0, PCXI.PCXO, 6'b0}; */
|
||||||
ea = ((env->PCXI & MASK_PCXI_PCXS) << 12) +
|
/* EA = {PCXI.PCXS, 6'b0, PCXI.PCXO, 6'b0}; */
|
||||||
((env->PCXI & MASK_PCXI_PCXO) << 6);
|
ea = (pcxi_get_pcxs(env) << 28) |
|
||||||
|
(pcxi_get_pcxo(env) << 6);
|
||||||
|
|
||||||
/* {new_PCXI, A[11], A[10], A[11], D[8], D[9], D[10], D[11], A[12],
|
/* {new_PCXI, A[11], 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]} = M(EA, 16 * word); */
|
A[13], A[14], A[15], D[12], D[13], D[14], D[15]} = M(EA, 16 * word); */
|
||||||
restore_context_lower(env, ea, &env->gpr_a[11], &new_PCXI);
|
restore_context_lower(env, ea, &env->gpr_a[11], &new_PCXI);
|
||||||
|
|
|
@ -75,6 +75,7 @@ typedef struct DisasContext {
|
||||||
int mem_idx;
|
int mem_idx;
|
||||||
uint32_t hflags, saved_hflags;
|
uint32_t hflags, saved_hflags;
|
||||||
uint64_t features;
|
uint64_t features;
|
||||||
|
uint32_t icr_ie_mask;
|
||||||
} DisasContext;
|
} DisasContext;
|
||||||
|
|
||||||
static int has_feature(DisasContext *ctx, int feature)
|
static int has_feature(DisasContext *ctx, int feature)
|
||||||
|
@ -7850,12 +7851,12 @@ static void decode_sys_interrupts(DisasContext *ctx)
|
||||||
/* raise EXCP_DEBUG */
|
/* raise EXCP_DEBUG */
|
||||||
break;
|
break;
|
||||||
case OPC2_32_SYS_DISABLE:
|
case OPC2_32_SYS_DISABLE:
|
||||||
tcg_gen_andi_tl(cpu_ICR, cpu_ICR, ~MASK_ICR_IE_1_3);
|
tcg_gen_andi_tl(cpu_ICR, cpu_ICR, ~ctx->icr_ie_mask);
|
||||||
break;
|
break;
|
||||||
case OPC2_32_SYS_DSYNC:
|
case OPC2_32_SYS_DSYNC:
|
||||||
break;
|
break;
|
||||||
case OPC2_32_SYS_ENABLE:
|
case OPC2_32_SYS_ENABLE:
|
||||||
tcg_gen_ori_tl(cpu_ICR, cpu_ICR, MASK_ICR_IE_1_3);
|
tcg_gen_ori_tl(cpu_ICR, cpu_ICR, ctx->icr_ie_mask);
|
||||||
break;
|
break;
|
||||||
case OPC2_32_SYS_ISYNC:
|
case OPC2_32_SYS_ISYNC:
|
||||||
break;
|
break;
|
||||||
|
@ -8259,6 +8260,11 @@ static void tricore_tr_init_disas_context(DisasContextBase *dcbase,
|
||||||
ctx->mem_idx = cpu_mmu_index(env, false);
|
ctx->mem_idx = cpu_mmu_index(env, false);
|
||||||
ctx->hflags = (uint32_t)ctx->base.tb->flags;
|
ctx->hflags = (uint32_t)ctx->base.tb->flags;
|
||||||
ctx->features = env->features;
|
ctx->features = env->features;
|
||||||
|
if (has_feature(ctx, TRICORE_FEATURE_161)) {
|
||||||
|
ctx->icr_ie_mask = R_ICR_IE_161_MASK;
|
||||||
|
} else {
|
||||||
|
ctx->icr_ie_mask = R_ICR_IE_13_MASK;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tricore_tr_tb_start(DisasContextBase *db, CPUState *cpu)
|
static void tricore_tr_tb_start(DisasContextBase *db, CPUState *cpu)
|
||||||
|
|
|
@ -1,34 +1,49 @@
|
||||||
TESTS_PATH = $(SRC_PATH)/tests/tcg/tricore
|
TESTS_PATH = $(SRC_PATH)/tests/tcg/tricore
|
||||||
|
ASM_TESTS_PATH = $(TESTS_PATH)/asm
|
||||||
|
C_TESTS_PATH = $(TESTS_PATH)/c
|
||||||
|
|
||||||
LDFLAGS = -T$(TESTS_PATH)/link.ld --mcpu=tc162
|
LDFLAGS = -T$(TESTS_PATH)/link.ld --mcpu=tc162
|
||||||
ASFLAGS = -mtc162
|
ASFLAGS = -mtc162
|
||||||
|
CFLAGS = -mtc162 -c -I$(TESTS_PATH)
|
||||||
|
|
||||||
TESTS += test_abs.tst
|
TESTS += test_abs.asm.tst
|
||||||
TESTS += test_bmerge.tst
|
TESTS += test_bmerge.asm.tst
|
||||||
TESTS += test_clz.tst
|
TESTS += test_clz.asm.tst
|
||||||
TESTS += test_dextr.tst
|
TESTS += test_dextr.asm.tst
|
||||||
TESTS += test_dvstep.tst
|
TESTS += test_dvstep.asm.tst
|
||||||
TESTS += test_fadd.tst
|
TESTS += test_fadd.asm.tst
|
||||||
TESTS += test_fmul.tst
|
TESTS += test_fmul.asm.tst
|
||||||
TESTS += test_ftoi.tst
|
TESTS += test_ftoi.asm.tst
|
||||||
TESTS += test_imask.tst
|
TESTS += test_imask.asm.tst
|
||||||
TESTS += test_insert.tst
|
TESTS += test_insert.asm.tst
|
||||||
TESTS += test_ld_bu.tst
|
TESTS += test_ld_bu.asm.tst
|
||||||
TESTS += test_ld_h.tst
|
TESTS += test_ld_h.asm.tst
|
||||||
TESTS += test_madd.tst
|
TESTS += test_madd.asm.tst
|
||||||
TESTS += test_msub.tst
|
TESTS += test_msub.asm.tst
|
||||||
TESTS += test_muls.tst
|
TESTS += test_muls.asm.tst
|
||||||
|
|
||||||
|
TESTS += test_boot_to_main.c.tst
|
||||||
|
TESTS += test_context_save_areas.c.tst
|
||||||
|
|
||||||
QEMU_OPTS += -M tricore_testboard -cpu tc27x -nographic -kernel
|
QEMU_OPTS += -M tricore_testboard -cpu tc27x -nographic -kernel
|
||||||
|
|
||||||
%.pS: $(TESTS_PATH)/%.S
|
%.pS: $(ASM_TESTS_PATH)/%.S
|
||||||
$(HOST_CC) -E -o $@ $<
|
$(HOST_CC) -E -o $@ $<
|
||||||
|
|
||||||
%.o: %.pS
|
%.o: %.pS
|
||||||
$(AS) $(ASFLAGS) -o $@ $<
|
$(AS) $(ASFLAGS) -o $@ $<
|
||||||
|
|
||||||
%.tst: %.o
|
%.asm.tst: %.o
|
||||||
$(LD) $(LDFLAGS) $< -o $@
|
$(LD) $(LDFLAGS) $< -o $@
|
||||||
|
|
||||||
|
crt0-tc2x.o: $(C_TESTS_PATH)/crt0-tc2x.S
|
||||||
|
$(AS) $(ASFLAGS) -o $@ $<
|
||||||
|
|
||||||
|
%.o: $(C_TESTS_PATH)/%.c
|
||||||
|
$(CC) $(CFLAGS) -o $@ $<
|
||||||
|
|
||||||
|
%.c.tst: %.o crt0-tc2x.o
|
||||||
|
$(LD) $(LDFLAGS) -o $@ $^
|
||||||
|
|
||||||
# We don't currently support the multiarch system tests
|
# We don't currently support the multiarch system tests
|
||||||
undefine MULTIARCH_TESTS
|
undefine MULTIARCH_TESTS
|
||||||
|
|
|
@ -25,7 +25,6 @@
|
||||||
|
|
||||||
#define AREG_ADDR %a0
|
#define AREG_ADDR %a0
|
||||||
#define AREG_CORRECT_RESULT %a3
|
#define AREG_CORRECT_RESULT %a3
|
||||||
#define MEM_BASE_ADDR 0xd0000000
|
|
||||||
|
|
||||||
#define DREG_DEV_ADDR %a15
|
#define DREG_DEV_ADDR %a15
|
||||||
|
|
|
@ -9,7 +9,7 @@ _start:
|
||||||
# expect. addr reg val after load
|
# expect. addr reg val after load
|
||||||
# insn num expect. load value | pattern for loading
|
# insn num expect. load value | pattern for loading
|
||||||
# | | | | |
|
# | | | | |
|
||||||
TEST_LD(ld.bu, 1, 0xff, MEM_BASE_ADDR + 4, [+AREG_ADDR]4) # pre_inc
|
TEST_LD(ld.bu, 1, 0xff, test_data + 4, [+AREG_ADDR]4) # pre_inc
|
||||||
TEST_LD(ld.bu, 2, 0xad, MEM_BASE_ADDR + 4, [AREG_ADDR+]4) # post_inc
|
TEST_LD(ld.bu, 2, 0xad, test_data + 4, [AREG_ADDR+]4) # post_inc
|
||||||
|
|
||||||
TEST_PASSFAIL
|
TEST_PASSFAIL
|
|
@ -0,0 +1,15 @@
|
||||||
|
#include "macros.h"
|
||||||
|
.data
|
||||||
|
test_data:
|
||||||
|
.word 0xaffedead
|
||||||
|
.word 0x001122ff
|
||||||
|
.text
|
||||||
|
.global _start
|
||||||
|
_start:
|
||||||
|
# expect. addr reg val after load
|
||||||
|
# insn num expect. load value | pattern for loading
|
||||||
|
# | | | | |
|
||||||
|
TEST_LD (ld.h, 1, 0xffffaffe, test_data, [AREG_ADDR]2)
|
||||||
|
TEST_LD_SRO(ld.h, 2, 0x000022ff, test_data, [AREG_ADDR]4)
|
||||||
|
|
||||||
|
TEST_PASSFAIL
|
|
@ -0,0 +1,335 @@
|
||||||
|
/*
|
||||||
|
* crt0-tc2x.S -- Startup code for GNU/TriCore applications.
|
||||||
|
*
|
||||||
|
* Copyright (C) 1998-2014 HighTec EDV-Systeme GmbH.
|
||||||
|
*
|
||||||
|
* This file is part of GCC.
|
||||||
|
*
|
||||||
|
* GCC 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 Software Foundation; either version 3, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* GCC is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* Under Section 7 of GPL version 3, you are granted additional
|
||||||
|
* permissions described in the GCC Runtime Library Exception, version
|
||||||
|
* 3.1, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License and
|
||||||
|
* a copy of the GCC Runtime Library Exception along with this program;
|
||||||
|
* see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||||
|
* <http://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
|
/* Define the Derivate Name as a hexvalue. This value
|
||||||
|
* is built-in defined in tricore-c.c (from tricore-devices.c)
|
||||||
|
* the derivate number as a hexvalue (e.g. TC1796 => 0x1796
|
||||||
|
* This name will be used in the memory.x Memory description to
|
||||||
|
* to confirm that the crt0.o and the memory.x will be get from
|
||||||
|
* same directory
|
||||||
|
*/
|
||||||
|
.section ".startup_code", "ax", @progbits
|
||||||
|
.global _start
|
||||||
|
.type _start,@function
|
||||||
|
|
||||||
|
/* default BMI header (only TC2xxx devices) */
|
||||||
|
.word 0x00000000
|
||||||
|
.word 0xb3590070
|
||||||
|
.word 0x00000000
|
||||||
|
.word 0x00000000
|
||||||
|
.word 0x00000000
|
||||||
|
.word 0x00000000
|
||||||
|
.word 0x791eb864
|
||||||
|
.word 0x86e1479b
|
||||||
|
|
||||||
|
_start:
|
||||||
|
.code32
|
||||||
|
j _startaddr
|
||||||
|
.align 2
|
||||||
|
|
||||||
|
_startaddr:
|
||||||
|
/*
|
||||||
|
* initialize user and interrupt stack pointers
|
||||||
|
*/
|
||||||
|
movh.a %sp,hi:__USTACK # load %sp
|
||||||
|
lea %sp,[%sp]lo:__USTACK
|
||||||
|
movh %d0,hi:__ISTACK # load $isp
|
||||||
|
addi %d0,%d0,lo:__ISTACK
|
||||||
|
mtcr $isp,%d0
|
||||||
|
isync
|
||||||
|
|
||||||
|
#; install trap handlers
|
||||||
|
|
||||||
|
movh %d0,hi:first_trap_table #; load $btv
|
||||||
|
addi %d0,%d0,lo:first_trap_table
|
||||||
|
mtcr $btv,%d0
|
||||||
|
isync
|
||||||
|
|
||||||
|
/*
|
||||||
|
* initialize call depth counter
|
||||||
|
*/
|
||||||
|
|
||||||
|
mfcr %d0,$psw
|
||||||
|
or %d0,%d0,0x7f # disable call depth counting
|
||||||
|
andn %d0,%d0,0x80 # clear CDE bit
|
||||||
|
mtcr $psw,%d0
|
||||||
|
isync
|
||||||
|
|
||||||
|
/*
|
||||||
|
* initialize access to system global registers
|
||||||
|
*/
|
||||||
|
|
||||||
|
mfcr %d0,$psw
|
||||||
|
or %d0,%d0,0x100 # set GW bit
|
||||||
|
mtcr $psw,%d0
|
||||||
|
isync
|
||||||
|
|
||||||
|
/*
|
||||||
|
* initialize SDA base pointers
|
||||||
|
*/
|
||||||
|
.global _SMALL_DATA_,_SMALL_DATA2_,_SMALL_DATA3_,_SMALL_DATA4_
|
||||||
|
.weak _SMALL_DATA_,_SMALL_DATA2_,_SMALL_DATA3_,_SMALL_DATA4_
|
||||||
|
|
||||||
|
movh.a %a0,hi:_SMALL_DATA_ # %a0 addresses .sdata/.sbss
|
||||||
|
lea %a0,[%a0]lo:_SMALL_DATA_
|
||||||
|
movh.a %a1,hi:_SMALL_DATA2_ # %a1 addresses .sdata2/.sbss2
|
||||||
|
lea %a1,[%a1]lo:_SMALL_DATA2_
|
||||||
|
movh.a %a8,hi:_SMALL_DATA3_ # %a8 addresses .sdata3/.sbss3
|
||||||
|
lea %a8,[%a8]lo:_SMALL_DATA3_
|
||||||
|
movh.a %a9,hi:_SMALL_DATA4_ # %a9 addresses .sdata4/.sbss4
|
||||||
|
lea %a9,[%a9]lo:_SMALL_DATA4_
|
||||||
|
|
||||||
|
/*
|
||||||
|
* reset access to system global registers
|
||||||
|
*/
|
||||||
|
|
||||||
|
mfcr %d0,$psw
|
||||||
|
andn %d0,%d0,0x100 # clear GW bit
|
||||||
|
mtcr $psw,%d0
|
||||||
|
isync
|
||||||
|
|
||||||
|
/*
|
||||||
|
* initialize context save areas
|
||||||
|
*/
|
||||||
|
|
||||||
|
jl __init_csa
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* handle clear table (i.e., fill BSS with zeros)
|
||||||
|
*/
|
||||||
|
|
||||||
|
jl __clear_table_func
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* handle copy table (support for romable code)
|
||||||
|
*/
|
||||||
|
|
||||||
|
jl __copy_table_func
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* _exit (main (0, NULL));
|
||||||
|
*/
|
||||||
|
mov %d4,0 # argc = 0
|
||||||
|
sub.a %sp,8
|
||||||
|
st.w [%sp]0,%d4
|
||||||
|
st.w [%sp]4,%d4
|
||||||
|
mov.aa %a4,%sp # argv
|
||||||
|
|
||||||
|
call main # int retval = main (0, NULL);
|
||||||
|
mov.a %a14,%d2 # move exit code to match trap handler
|
||||||
|
j _exit # _exit (retval);
|
||||||
|
|
||||||
|
debug # should never come here
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* initialize context save areas (CSAs), PCXI, LCX and FCX
|
||||||
|
*/
|
||||||
|
|
||||||
|
.global __init_csa
|
||||||
|
.type __init_csa,function
|
||||||
|
|
||||||
|
__init_csa:
|
||||||
|
movh %d0,0
|
||||||
|
mtcr $pcxi,%d0
|
||||||
|
isync
|
||||||
|
movh %d0,hi:__CSA_BEGIN #; %d0 = begin of CSA
|
||||||
|
addi %d0,%d0,lo:__CSA_BEGIN
|
||||||
|
addi %d0,%d0,63 #; force alignment (2^6)
|
||||||
|
andn %d0,%d0,63
|
||||||
|
movh %d2,hi:__CSA_END #; %d2 = end of CSA
|
||||||
|
addi %d2,%d2,lo:__CSA_END
|
||||||
|
andn %d2,%d2,63 #; force alignment (2^6)
|
||||||
|
sub %d2,%d2,%d0
|
||||||
|
sh %d2,%d2,-6 #; %d2 = number of CSAs
|
||||||
|
mov.a %a3,%d0 #; %a3 = address of first CSA
|
||||||
|
extr.u %d0,%d0,28,4 #; %d0 = segment << 16
|
||||||
|
sh %d0,%d0,16
|
||||||
|
lea %a4,0 #; %a4 = previous CSA = 0
|
||||||
|
st.a [%a3],%a4 #; store it in 1st CSA
|
||||||
|
mov.aa %a4,%a3 #; %a4 = current CSA
|
||||||
|
lea %a3,[%a3]64 #; %a3 = %a3->nextCSA
|
||||||
|
mov.d %d1,%a3
|
||||||
|
extr.u %d1,%d1,6,16 #; get CSA index
|
||||||
|
or %d1,%d1,%d0 #; add segment number
|
||||||
|
mtcr $lcx,%d1 #; initialize LCX
|
||||||
|
add %d2,%d2,-2 #; CSAs to initialize -= 2
|
||||||
|
mov.a %a5,%d2 #; %a5 = loop counter
|
||||||
|
csa_loop:
|
||||||
|
mov.d %d1,%a4 #; %d1 = current CSA address
|
||||||
|
extr.u %d1,%d1,6,16 #; get CSA index
|
||||||
|
or %d1,%d1,%d0 #; add segment number
|
||||||
|
st.w [%a3],%d1 #; store "nextCSA" pointer
|
||||||
|
mov.aa %a4,%a3 #; %a4 = current CSA address
|
||||||
|
lea %a3,[%a3]64 #; %a3 = %a3->nextCSA
|
||||||
|
loop %a5,csa_loop #; repeat until done
|
||||||
|
|
||||||
|
mov.d %d1,%a4 #; %d1 = current CSA address
|
||||||
|
extr.u %d1,%d1,6,16 #; get CSA index
|
||||||
|
or %d1,%d1,%d0 #; add segment number
|
||||||
|
mtcr $fcx,%d1 #; initialize FCX
|
||||||
|
isync
|
||||||
|
ji %a11
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* handle clear table (i.e., fill BSS with zeros)
|
||||||
|
*/
|
||||||
|
.global __clear_table_func
|
||||||
|
.type __clear_table_func,@function
|
||||||
|
|
||||||
|
__clear_table_func:
|
||||||
|
mov %d14,0 # %e14 = 0
|
||||||
|
mov %d15,0
|
||||||
|
movh.a %a13,hi:__clear_table # %a13 = &first table entry
|
||||||
|
lea %a13,[%a13]lo:__clear_table
|
||||||
|
|
||||||
|
__clear_table_next:
|
||||||
|
ld.a %a15,[%a13+]4 # %a15 = current block base
|
||||||
|
ld.w %d3,[%a13+]4 # %d3 = current block length
|
||||||
|
jeq %d3,-1,__clear_table_done # length == -1 => end of table
|
||||||
|
sh %d0,%d3,-3 # %d0 = length / 8 (doublewords)
|
||||||
|
and %d1,%d3,7 # %d1 = length % 8 (rem. bytes)
|
||||||
|
jz %d0,__clear_word # block size < 8 => clear word
|
||||||
|
addi %d0,%d0,-1 # else doublewords -= 1
|
||||||
|
mov.a %a2,%d0 # %a2 = loop counter
|
||||||
|
__clear_dword:
|
||||||
|
st.d [%a15+]8,%e14 # clear one doubleword
|
||||||
|
loop %a2,__clear_dword
|
||||||
|
__clear_word:
|
||||||
|
jz %d1,__clear_table_next
|
||||||
|
sh %d0,%d1,-2 # %d0 = length / 4 (words)
|
||||||
|
and %d1,%d1,3 # %d1 = length % 4 (rem. bytes)
|
||||||
|
jz %d0,__clear_hword # block size < 4 => clear hword
|
||||||
|
st.w [%a15+]4,%d15 # clear one word
|
||||||
|
__clear_hword:
|
||||||
|
jz %d1,__clear_table_next
|
||||||
|
sh %d0,%d1,-1 # %d0 = length / 2 (halfwords)
|
||||||
|
and %d1,%d1,1 # %d1 = length % 2 (rem. bytes)
|
||||||
|
jz %d0,__clear_byte # block size < 2 => clear byte
|
||||||
|
st.h [%a15+]2,%d15 # clear one halfword
|
||||||
|
__clear_byte:
|
||||||
|
jz %d1,__clear_table_next
|
||||||
|
st.b [%a15],%d15 # clear one byte
|
||||||
|
j __clear_table_next # handle next clear table entry
|
||||||
|
__clear_table_done:
|
||||||
|
|
||||||
|
ji %a11
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* handle copy table (support for romable code)
|
||||||
|
*/
|
||||||
|
.global __copy_table_func
|
||||||
|
.type __copy_table_func,@function
|
||||||
|
|
||||||
|
__copy_table_func:
|
||||||
|
movh.a %a13,hi:__copy_table # %a13 = &first table entry
|
||||||
|
lea %a13,[%a13]lo:__copy_table
|
||||||
|
|
||||||
|
__copy_table_next:
|
||||||
|
ld.a %a15,[%a13+]4 # %a15 = src address
|
||||||
|
ld.a %a14,[%a13+]4 # %a14 = dst address
|
||||||
|
ld.w %d3,[%a13+]4 # %d3 = block length
|
||||||
|
jeq %d3,-1,__copy_table_done # length == -1 => end of table
|
||||||
|
sh %d0,%d3,-3 # %d0 = length / 8 (doublewords)
|
||||||
|
and %d1,%d3,7 # %d1 = lenght % 8 (rem. bytes)
|
||||||
|
jz %d0,__copy_word # block size < 8 => copy word
|
||||||
|
addi %d0,%d0,-1 # else doublewords -= 1
|
||||||
|
mov.a %a2,%d0 # %a2 = loop counter
|
||||||
|
__copy_dword:
|
||||||
|
ld.d %e14,[%a15+]8 # copy one doubleword
|
||||||
|
st.d [%a14+]8,%e14
|
||||||
|
loop %a2,__copy_dword
|
||||||
|
__copy_word:
|
||||||
|
jz %d1,__copy_table_next
|
||||||
|
sh %d0,%d1,-2 # %d0 = length / 4 (words)
|
||||||
|
and %d1,%d1,3 # %d1 = lenght % 4 (rem. bytes)
|
||||||
|
jz %d0,__copy_hword # block size < 4 => copy hword
|
||||||
|
ld.w %d14,[%a15+]4 # copy one word
|
||||||
|
st.w [%a14+]4,%d14
|
||||||
|
__copy_hword:
|
||||||
|
jz %d1,__copy_table_next
|
||||||
|
sh %d0,%d1,-1 # %d0 = length / 2 (halfwords)
|
||||||
|
and %d1,%d1,1 # %d1 = length % 2 (rem. bytes)
|
||||||
|
jz %d0,__copy_byte # block size < 2 => copy byte
|
||||||
|
ld.h %d14,[%a15+]2 # copy one halfword
|
||||||
|
st.h [%a14+]2,%d14
|
||||||
|
__copy_byte:
|
||||||
|
jz %d1,__copy_table_next
|
||||||
|
ld.b %d14,[%a15]0 # copy one byte
|
||||||
|
st.b [%a14],%d14
|
||||||
|
j __copy_table_next # handle next copy table entry
|
||||||
|
__copy_table_done:
|
||||||
|
|
||||||
|
ji %a11
|
||||||
|
|
||||||
|
_exit:
|
||||||
|
movh.a %a15, hi:__TESTDEVICE
|
||||||
|
lea %a15,[%a15]lo:__TESTDEVICE
|
||||||
|
mov.d %d2, %a14
|
||||||
|
st.w [%a15], %d2 # write exit code to testdevice
|
||||||
|
debug
|
||||||
|
|
||||||
|
/*============================================================================*
|
||||||
|
* Exception handlers (exceptions in startup code)
|
||||||
|
*
|
||||||
|
* This is a minimal trap vector table, which consists of eight
|
||||||
|
* entries, each consisting of eight words (32 bytes).
|
||||||
|
*============================================================================*/
|
||||||
|
|
||||||
|
|
||||||
|
#; .section .traptab, "ax", @progbits
|
||||||
|
|
||||||
|
.macro trapentry from=0, to=7
|
||||||
|
mov.u %d14, \from << 8
|
||||||
|
add %d14,%d14,%d15
|
||||||
|
mov.a %a14,%d14
|
||||||
|
addih.a %a14,%a14,0 # if we trap, we fail
|
||||||
|
j _exit
|
||||||
|
0:
|
||||||
|
j 0b
|
||||||
|
nop
|
||||||
|
rfe
|
||||||
|
.align 5
|
||||||
|
|
||||||
|
.if \to-\from
|
||||||
|
trapentry "(\from+1)",\to
|
||||||
|
.endif
|
||||||
|
.endm
|
||||||
|
|
||||||
|
.align 8
|
||||||
|
.global first_trap_table
|
||||||
|
first_trap_table:
|
||||||
|
trapentry 0, 7
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2023 Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
|
||||||
|
*
|
||||||
|
* This code is licensed under the GPL version 2 or later. See the
|
||||||
|
* COPYING file in the top-level directory.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "testdev_assert.h"
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
testdev_assert(1);
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
#include "testdev_assert.h"
|
||||||
|
|
||||||
|
static int fib(int n)
|
||||||
|
{
|
||||||
|
if (n == 1 || n == 2) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return fib(n - 2) + fib(n - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
testdev_assert(fib(10) == 55);
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2023 Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
|
||||||
|
*
|
||||||
|
* This code is licensed under the GPL version 2 or later. See the
|
||||||
|
* COPYING file in the top-level directory.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int *testdev = (int *)0xf0000000;
|
||||||
|
|
||||||
|
#define FAIL 1
|
||||||
|
static inline void testdev_assert(int condition)
|
||||||
|
{
|
||||||
|
if (!condition) {
|
||||||
|
*testdev = FAIL;
|
||||||
|
asm("debug");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@ MEMORY
|
||||||
/*
|
/*
|
||||||
* Define the sizes of the user and system stacks.
|
* Define the sizes of the user and system stacks.
|
||||||
*/
|
*/
|
||||||
|
__ISTACK_SIZE = DEFINED (__ISTACK_SIZE) ? __ISTACK_SIZE : 256 ;
|
||||||
__USTACK_SIZE = DEFINED (__USTACK_SIZE) ? __USTACK_SIZE : 1K ;
|
__USTACK_SIZE = DEFINED (__USTACK_SIZE) ? __USTACK_SIZE : 1K ;
|
||||||
/*
|
/*
|
||||||
* Define the start address and the size of the context save area.
|
* Define the start address and the size of the context save area.
|
||||||
|
@ -20,6 +21,8 @@ __CSA_BEGIN = 0xd0000000 ;
|
||||||
__CSA_SIZE = 8k ;
|
__CSA_SIZE = 8k ;
|
||||||
__CSA_END = __CSA_BEGIN + __CSA_SIZE ;
|
__CSA_END = __CSA_BEGIN + __CSA_SIZE ;
|
||||||
|
|
||||||
|
__TESTDEVICE = 0xf0000000 ;
|
||||||
|
|
||||||
SECTIONS
|
SECTIONS
|
||||||
{
|
{
|
||||||
.text :
|
.text :
|
||||||
|
@ -32,6 +35,18 @@ SECTIONS
|
||||||
{
|
{
|
||||||
*(.rodata)
|
*(.rodata)
|
||||||
*(.rodata1)
|
*(.rodata1)
|
||||||
|
/*
|
||||||
|
* Create the clear and copy tables that tell the startup code
|
||||||
|
* which memory areas to clear and to copy, respectively.
|
||||||
|
*/
|
||||||
|
. = ALIGN(4) ;
|
||||||
|
PROVIDE(__clear_table = .) ;
|
||||||
|
LONG(0 + ADDR(.bss)); LONG(SIZEOF(.bss));
|
||||||
|
LONG(-1); LONG(-1);
|
||||||
|
PROVIDE(__copy_table = .) ;
|
||||||
|
LONG(LOADADDR(.data)); LONG(0 + ADDR(.data)); LONG(SIZEOF(.data));
|
||||||
|
LONG(-1); LONG(-1); LONG(-1);
|
||||||
|
. = ALIGN(8);
|
||||||
} > data_ram
|
} > data_ram
|
||||||
|
|
||||||
.data :
|
.data :
|
||||||
|
@ -40,6 +55,7 @@ SECTIONS
|
||||||
*(.data)
|
*(.data)
|
||||||
*(.data.*)
|
*(.data.*)
|
||||||
. = ALIGN(8) ;
|
. = ALIGN(8) ;
|
||||||
|
__ISTACK = . + __ISTACK_SIZE ;
|
||||||
__USTACK = . + __USTACK_SIZE -768;
|
__USTACK = . + __USTACK_SIZE -768;
|
||||||
|
|
||||||
} > data_ram
|
} > data_ram
|
||||||
|
|
|
@ -1,15 +0,0 @@
|
||||||
#include "macros.h"
|
|
||||||
.data
|
|
||||||
test_data:
|
|
||||||
.word 0xaffedead
|
|
||||||
.word 0x001122ff
|
|
||||||
.text
|
|
||||||
.global _start
|
|
||||||
_start:
|
|
||||||
# expect. addr reg val after load
|
|
||||||
# insn num expect. load value | pattern for loading
|
|
||||||
# | | | | |
|
|
||||||
TEST_LD (ld.h, 1, 0xffffaffe, MEM_BASE_ADDR, [AREG_ADDR]2)
|
|
||||||
TEST_LD_SRO(ld.h, 2, 0x000022ff, MEM_BASE_ADDR, [AREG_ADDR]4)
|
|
||||||
|
|
||||||
TEST_PASSFAIL
|
|
Loading…
Reference in New Issue