@@ -19,3 +19,6 @@
DEF_HELPER_4(shac, i32, env, i32, i32, i32)
DEF_HELPER_3(add_ssov, i32, env, i32, i32)
DEF_HELPER_3(sub_ssov, i32, env, i32, i32)
+/* CSA */
+DEF_HELPER_2(call, void, env, i32)
+DEF_HELPER_1(ret, void, env)
@@ -95,6 +95,166 @@ target_ulong helper_sub_ssov(CPUTRICOREState *env, target_ulong r1,
return ret;
}
+/* context save area (CSA) related helpers */
+
+static int cdc_increment(target_ulong *psw)
+{
+ if ((*psw & MASK_PSW_CDC) == 0x7f) {
+ return 0;
+ }
+
+ (*psw)++;
+ /* check for overflow */
+ if (((6 - clo32(*psw & MASK_PSW_CDC)) & *psw)) {
+ return 1;
+ }
+ return 0;
+}
+
+static int cdc_decrement(target_ulong *psw)
+{
+ if ((*psw & MASK_PSW_CDC) == 0x7f) {
+ return 0;
+ }
+ /* check for underflow */
+ if ((((1 << (6 - clo32(*psw & MASK_PSW_CDC))) - 1) & *psw)== 0) {
+ (*psw)--;
+ return 1;
+ }
+ (*psw)--;
+ return 0;
+}
+
+static void save_context_upper(CPUTRICOREState *env, int ea,
+ target_ulong *new_FCX)
+{
+ *new_FCX = cpu_ldl_data(env, ea);
+ cpu_stl_data(env, ea, env->PCXI);
+ cpu_stl_data(env, ea+4, env->PSW);
+ 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]);
+ cpu_stl_data(env, ea+20, env->gpr_d[9]);
+ cpu_stl_data(env, ea+24, env->gpr_d[10]);
+ cpu_stl_data(env, ea+28, env->gpr_d[11]);
+ cpu_stl_data(env, ea+32, env->gpr_a[12]);
+ cpu_stl_data(env, ea+36, env->gpr_a[13]);
+ cpu_stl_data(env, ea+40, env->gpr_a[14]);
+ cpu_stl_data(env, ea+44, env->gpr_a[15]);
+ cpu_stl_data(env, ea+48, env->gpr_d[12]);
+ cpu_stl_data(env, ea+52, env->gpr_d[13]);
+ cpu_stl_data(env, ea+56, env->gpr_d[14]);
+ cpu_stl_data(env, ea+60, env->gpr_d[15]);
+
+}
+
+static void restore_context_upper(CPUTRICOREState *env, int ea,
+ target_ulong *new_PCXI, target_ulong *new_PSW)
+{
+ *new_PCXI = cpu_ldl_data(env, ea);
+ *new_PSW = cpu_ldl_data(env, ea+4);
+ env->gpr_a[10] = cpu_ldl_data(env, ea+8);
+ env->gpr_a[11] = cpu_ldl_data(env, ea+12);
+ env->gpr_d[8] = cpu_ldl_data(env, ea+16);
+ env->gpr_d[9] = cpu_ldl_data(env, ea+20);
+ env->gpr_d[10] = cpu_ldl_data(env, ea+24);
+ env->gpr_d[11] = cpu_ldl_data(env, ea+28);
+ env->gpr_a[12] = cpu_ldl_data(env, ea+32);
+ env->gpr_a[13] = cpu_ldl_data(env, ea+36);
+ env->gpr_a[14] = cpu_ldl_data(env, ea+40);
+ env->gpr_a[15] = cpu_ldl_data(env, ea+44);
+ env->gpr_d[12] = cpu_ldl_data(env, ea+48);
+ env->gpr_d[13] = cpu_ldl_data(env, ea+52);
+ env->gpr_d[14] = cpu_ldl_data(env, ea+56);
+ env->gpr_d[15] = cpu_ldl_data(env, ea+60);
+ cpu_stl_data(env, ea, env->FCX);
+}
+
+void helper_call(CPUTRICOREState *env, uint32_t next_pc)
+{
+ target_ulong tmp_FCX;
+ target_ulong ea;
+ target_ulong new_FCX;
+
+ /* if (FCX == 0) trap(FCU); */
+ if (env->FCX == 0) {
+ /* FCU trap */
+ }
+ /* if (PSW.CDE) then if (cdc_increment()) then trap(CDO); */
+ if (env->PSW & MASK_PSW_CDE) {
+ if (cdc_increment(&(env->PSW))) {
+ /* CDO trap */
+ }
+ }
+ /* PSW.CDE = 1;*/
+ env->PSW |= MASK_PSW_CDE;
+ /* 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);
+ 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, &new_FCX);
+
+ /* 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);
+ /* A[11] = next_pc[31: 0]; */
+ env->gpr_a[11] = next_pc;
+
+ /* if (tmp_FCX == LCX) trap(FCD);*/
+ if (tmp_FCX == env->LCX) {
+ /* FCD trap */
+ }
+}
+
+void helper_ret(CPUTRICOREState *env)
+{
+ target_ulong ea;
+ target_ulong new_PCXI;
+ target_ulong new_PSW;
+ /* if (PSW.CDE) then if (cdc_decrement()) then trap(CDU);*/
+ if (env->PSW & MASK_PSW_CDE) {
+ if (cdc_decrement(&(env->PSW))) {
+ /* CDU trap */
+ }
+ }
+ /* if (PCXI[19: 0] == 0) then trap(CSU); */
+ if ((env->PCXI & 0xfffff) == 0) {
+ /* CSU trap */
+ }
+ /* if (PCXI.UL == 0) then trap(CTYP); */
+ if ((env->PCXI & MASK_PCXI_UL) == 0) {
+ /* CTYP trap */
+ }
+ /* PC = {A11 [31: 1], 1’b0}; */
+ env->PC = env->gpr_a[11] & 0xfffffffe;
+
+ /* EA = {PCXI.PCXS, 6'b0, PCXI.PCXO, 6'b0}; */
+ ea = ((env->PCXI & MASK_PCXI_PCXS) << 12) +
+ ((env->PCXI & MASK_PCXI_PCXO) << 6);
+ /* {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);
+ M(EA, word) = FCX; */
+ restore_context_upper(env, ea, &new_PCXI, &new_PSW);
+ /* FCX[19: 0] = PCXI[19: 0]; */
+ env->FCX = (env->FCX & 0xfff00000) + (env->PCXI & 0x000fffff);
+ /* PCXI = new_PCXI; */
+ env->PCXI = new_PCXI;
+}
static inline void QEMU_NORETURN do_raise_exception_err(CPUTRICOREState *env,
uint32_t exception,
@@ -99,6 +99,14 @@ void tricore_cpu_dump_state(CPUState *cs, FILE *f,
* Functions to generate micro-ops
*/
+/* Makros for generating helpers */
+
+#define gen_helper_1arg(name, arg) do { \
+ TCGv_i32 helper_tmp = tcg_const_i32(arg); \
+ gen_helper_##name(cpu_env, helper_tmp); \
+ tcg_temp_free_i32(helper_tmp); \
+ } while (0)
+
/* Functions for load/save to/from memory */
static inline void gen_offset_ld(DisasContext *ctx, TCGv r1, TCGv r2,
int16_t con, TCGMemOp mop)
@@ -190,6 +198,78 @@ static inline void gen_subs(TCGv ret, TCGv r1, TCGv r2)
tcg_temp_free(temp);
}
+/* helpers for generating program flow micro-ops */
+
+static inline void gen_save_pc(target_ulong pc)
+{
+ tcg_gen_movi_tl(cpu_PC, pc);
+}
+
+static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
+{
+ TranslationBlock *tb;
+ tb = ctx->tb;
+ if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) &&
+ likely(!ctx->singlestep_enabled)) {
+ tcg_gen_goto_tb(n);
+ gen_save_pc(dest);
+ tcg_gen_exit_tb((uintptr_t)tb + n);
+ } else {
+ gen_save_pc(dest);
+ if (ctx->singlestep_enabled) {
+ /* raise exception debug */
+ }
+ tcg_gen_exit_tb(0);
+ }
+}
+
+static inline void gen_branch_cond(DisasContext *ctx, int cond, TCGv r1,
+ TCGv r2, int16_t address)
+{
+ int jumpLabel;
+ jumpLabel = gen_new_label();
+ tcg_gen_brcond_tl(cond, r1, r2, jumpLabel);
+
+ gen_goto_tb(ctx, 1, ctx->next_pc);
+
+ gen_set_label(jumpLabel);
+ gen_goto_tb(ctx, 0, ctx->pc + address * 2);
+}
+
+static inline void gen_branch_condi(DisasContext *ctx, int cond, TCGv r1,
+ int r2, int16_t address)
+{
+ TCGv temp = tcg_const_i32(r2);
+ gen_branch_cond(ctx, cond, r1, temp, address);
+ tcg_temp_free(temp);
+}
+
+static void gen_compute_branch(DisasContext *ctx, uint32_t opc,
+ int r1, int r2 , int32_t constant , int32_t offset)
+{
+
+ switch (opc) {
+/* SB-format jumps */
+ case OPC1_16_SB_J:
+ case OPC1_32_B_J:
+ gen_goto_tb(ctx, 0, ctx->pc + offset * 2);
+ break;
+ case OPC1_16_SB_CALL:
+ gen_helper_1arg(call, ctx->next_pc);
+ gen_goto_tb(ctx, 0, ctx->pc + sextract32(offset, 0, 8) * 2);
+ case OPC1_16_SB_JZ:
+ gen_branch_condi(ctx, TCG_COND_EQ, cpu_gpr_d[15], 0, offset);
+ break;
+ case OPC1_16_SB_JNZ:
+ gen_branch_condi(ctx, TCG_COND_NE, cpu_gpr_d[15], 0, offset);
+ break;
+ default:
+ printf("Branch Error at %x\n", ctx->pc);
+ }
+ ctx->bstate = BS_BRANCH;
+}
+
+
/*
* Functions for decoding instructions
*/
@@ -394,6 +474,7 @@ static void decode_16Bit_opc(CPUTRICOREState *env, DisasContext *ctx)
int op1;
int r1, r2;
int32_t const16;
+ int32_t address;
TCGv temp;
op1 = MASK_OP_MAJOR(ctx->opcode);
@@ -482,6 +563,14 @@ static void decode_16Bit_opc(CPUTRICOREState *env, DisasContext *ctx)
const16 = MASK_OP_SLRO_OFF4(ctx->opcode);
gen_offset_ld(ctx, cpu_gpr_d[r1], cpu_gpr_a[15], const16 * 4, MO_LESL);
break;
+/* SB-format */
+ case OPC1_16_SB_CALL:
+ case OPC1_16_SB_J:
+ case OPC1_16_SB_JNZ:
+ case OPC1_16_SB_JZ:
+ address = MASK_OP_SB_DISP8_SEXT(ctx->opcode);
+ gen_compute_branch(ctx, op1, 0, 0, 0, address);
+ break;
}
}
Add instructions of SB opcode format. Add helper call/ret. Add micro-op generator functions for branches. Add makro to generate helper functions. Signed-off-by: Bastian Koppelmann <kbastian@mail.uni-paderborn.de> --- v1 -> v2: - Fill in cdc_increment/cdc_decrement - Replace save/restore_context with save/restore_context_upper and save_context_lower (see patch v2 13/15) - Remove CONTEXT_LOWER/UPPER enum. - Remove printfs - helper_call uses next_pc instead of pc and insn_bytes. - Add gen_goto_tb. - Replace tcg_gen_exit_tb with gen_goto_tb in gen_compute_branch and gen_branch_cond. - Moved SB instructions to one case. target-tricore/helper.h | 3 + target-tricore/op_helper.c | 160 +++++++++++++++++++++++++++++++++++++++++++++ target-tricore/translate.c | 89 +++++++++++++++++++++++++ 3 files changed, 252 insertions(+) -- 2.0.1