[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 10/15] target-tricore: Add instructions of SB opcode
From: |
Bastian Koppelmann |
Subject: |
[Qemu-devel] [PATCH 10/15] target-tricore: Add instructions of SB opcode format |
Date: |
Mon, 7 Jul 2014 19:13:37 +0100 |
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 <address@hidden>
---
target-tricore/helper.h | 5 ++
target-tricore/op_helper.c | 192 +++++++++++++++++++++++++++++++++++++++++++++
target-tricore/translate.c | 85 ++++++++++++++++++++
3 files changed, 282 insertions(+)
diff --git a/target-tricore/helper.h b/target-tricore/helper.h
index acea104..0d79d1d 100644
--- a/target-tricore/helper.h
+++ b/target-tricore/helper.h
@@ -17,3 +17,8 @@
/* Arithmetic */
DEF_HELPER_3(shac, i32, env, i32, i32)
+
+/* CSA */
+DEF_HELPER_3(call, void, env, i32, i32)
+DEF_HELPER_1(ret, void, env)
+
diff --git a/target-tricore/op_helper.c b/target-tricore/op_helper.c
index b9fbfad..5267fd0 100644
--- a/target-tricore/op_helper.c
+++ b/target-tricore/op_helper.c
@@ -56,6 +56,198 @@ target_ulong helper_shac(CPUTRICOREState *env, target_ulong
r1,
return ret;
}
+/* context save area (CSA) related helpers */
+
+enum {
+ CONTEXT_LOWER = 0,
+ CONTEXT_UPPER = 1,
+};
+
+static int cdc_increment(TCState *tc)
+{
+ tc->PSW++;
+ return 0;
+}
+
+static int cdc_decrement(TCState *tc)
+{
+ tc->PSW--;
+ return 0;
+}
+
+static void save_context(CPUTRICOREState *env, int ea, int ul,
+ target_ulong *new_FCX)
+{
+ *new_FCX = cpu_ldl_data(env, ea);
+ cpu_stl_data(env, ea, env->active_tc.PCXI);
+ if (ul == CONTEXT_UPPER) {
+ cpu_stl_data(env, ea+4, env->active_tc.PSW);
+ cpu_stl_data(env, ea+8, env->active_tc.gpr_a[10]);
+ cpu_stl_data(env, ea+12, env->active_tc.gpr_a[11]);
+ cpu_stl_data(env, ea+16, env->active_tc.gpr_d[8]);
+ cpu_stl_data(env, ea+20, env->active_tc.gpr_d[9]);
+ cpu_stl_data(env, ea+24, env->active_tc.gpr_d[10]);
+ cpu_stl_data(env, ea+28, env->active_tc.gpr_d[11]);
+ cpu_stl_data(env, ea+32, env->active_tc.gpr_a[12]);
+ cpu_stl_data(env, ea+36, env->active_tc.gpr_a[13]);
+ cpu_stl_data(env, ea+40, env->active_tc.gpr_a[14]);
+ cpu_stl_data(env, ea+44, env->active_tc.gpr_a[15]);
+ cpu_stl_data(env, ea+48, env->active_tc.gpr_d[12]);
+ cpu_stl_data(env, ea+52, env->active_tc.gpr_d[13]);
+ cpu_stl_data(env, ea+56, env->active_tc.gpr_d[14]);
+ cpu_stl_data(env, ea+60, env->active_tc.gpr_d[15]);
+ } else {
+ cpu_stl_data(env, ea+4, env->active_tc.gpr_a[11]);
+ cpu_stl_data(env, ea+8, env->active_tc.gpr_a[2]);
+ cpu_stl_data(env, ea+12, env->active_tc.gpr_a[3]);
+ cpu_stl_data(env, ea+16, env->active_tc.gpr_d[0]);
+ cpu_stl_data(env, ea+20, env->active_tc.gpr_d[1]);
+ cpu_stl_data(env, ea+24, env->active_tc.gpr_d[2]);
+ cpu_stl_data(env, ea+28, env->active_tc.gpr_d[3]);
+ cpu_stl_data(env, ea+32, env->active_tc.gpr_a[4]);
+ cpu_stl_data(env, ea+36, env->active_tc.gpr_a[5]);
+ cpu_stl_data(env, ea+40, env->active_tc.gpr_a[6]);
+ cpu_stl_data(env, ea+44, env->active_tc.gpr_a[7]);
+ cpu_stl_data(env, ea+48, env->active_tc.gpr_d[4]);
+ cpu_stl_data(env, ea+52, env->active_tc.gpr_d[5]);
+ cpu_stl_data(env, ea+56, env->active_tc.gpr_d[6]);
+ cpu_stl_data(env, ea+60, env->active_tc.gpr_d[7]);
+ }
+}
+
+static void restore_context(CPUTRICOREState *env, int ea, int ul,
+ target_ulong *new_PCXI, target_ulong *new_PSW)
+{
+ *new_PCXI = cpu_ldl_data(env, ea);
+ if (ul == CONTEXT_UPPER) {
+ *new_PSW = cpu_ldl_data(env, ea+4);
+ env->active_tc.gpr_a[10] = cpu_ldl_data(env, ea+8);
+ env->active_tc.gpr_a[11] = cpu_ldl_data(env, ea+12);
+ env->active_tc.gpr_d[8] = cpu_ldl_data(env, ea+16);
+ env->active_tc.gpr_d[9] = cpu_ldl_data(env, ea+20);
+ env->active_tc.gpr_d[10] = cpu_ldl_data(env, ea+24);
+ env->active_tc.gpr_d[11] = cpu_ldl_data(env, ea+28);
+ env->active_tc.gpr_a[12] = cpu_ldl_data(env, ea+32);
+ env->active_tc.gpr_a[13] = cpu_ldl_data(env, ea+36);
+ env->active_tc.gpr_a[14] = cpu_ldl_data(env, ea+40);
+ env->active_tc.gpr_a[15] = cpu_ldl_data(env, ea+44);
+ env->active_tc.gpr_d[12] = cpu_ldl_data(env, ea+48);
+ env->active_tc.gpr_d[13] = cpu_ldl_data(env, ea+52);
+ env->active_tc.gpr_d[14] = cpu_ldl_data(env, ea+56);
+ env->active_tc.gpr_d[15] = cpu_ldl_data(env, ea+60);
+ } else {
+ env->active_tc.gpr_a[11] = cpu_ldl_data(env, ea+4);
+ env->active_tc.gpr_a[2] = cpu_ldl_data(env, ea+8);
+ env->active_tc.gpr_a[3] = cpu_ldl_data(env, ea+12);
+ env->active_tc.gpr_d[0] = cpu_ldl_data(env, ea+16);
+ env->active_tc.gpr_d[1] = cpu_ldl_data(env, ea+20);
+ env->active_tc.gpr_d[2] = cpu_ldl_data(env, ea+24);
+ env->active_tc.gpr_d[3] = cpu_ldl_data(env, ea+28);
+ env->active_tc.gpr_a[4] = cpu_ldl_data(env, ea+32);
+ env->active_tc.gpr_a[5] = cpu_ldl_data(env, ea+36);
+ env->active_tc.gpr_a[6] = cpu_ldl_data(env, ea+40);
+ env->active_tc.gpr_a[7] = cpu_ldl_data(env, ea+44);
+ env->active_tc.gpr_d[4] = cpu_ldl_data(env, ea+48);
+ env->active_tc.gpr_d[5] = cpu_ldl_data(env, ea+52);
+ env->active_tc.gpr_d[6] = cpu_ldl_data(env, ea+56);
+ env->active_tc.gpr_d[7] = cpu_ldl_data(env, ea+60);
+ }
+ cpu_stl_data(env, ea, env->active_tc.FCX);
+}
+
+void helper_call(CPUTRICOREState *env, uint32_t pc,
+ uint32_t insnsize)
+{
+ target_ulong ret_address;
+ target_ulong tmp_FCX;
+ target_ulong ea;
+ target_ulong new_FCX;
+
+ /* if (FCX == 0) trap(FCU); */
+ if (env->active_tc.FCX == 0) {
+ printf("FCU trap");
+ }
+ /* if (PSW.CDE) then if (cdc_increment()) then trap(CDO); */
+ if (env->active_tc.PSW & MASK_PSW_CDE) {
+ if (cdc_increment(&(env->active_tc))) {
+ printf("CDO trap\n");
+ }
+ }
+ /* PSW.CDE = 1;*/
+ env->active_tc.PSW |= MASK_PSW_CDE;
+ /* ret_addr = PC + 4; */
+ ret_address = pc + insnsize;
+ /* tmp_FCX = FCX; */
+ tmp_FCX = env->active_tc.FCX;
+ /* EA = {FCX.FCXS, 6'b0, FCX.FCXO, 6'b0}; */
+ ea = ((env->active_tc.FCX & MASK_FCX_FCXS) << 12) +
+ ((env->active_tc.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(env, ea, 1, &new_FCX);
+
+ /* PCXI.PCPN = ICR.CCPN; */
+ env->active_tc.PCXI = (env->active_tc.PCXI & 0xffffff) +
+ ((env->active_tc.ICR & MASK_ICR_CCPN) << 24);
+ /* PCXI.PIE = ICR.IE; */
+ env->active_tc.PCXI = ((env->active_tc.PCXI & ~MASK_PCXI_PIE) +
+ ((env->active_tc.ICR & MASK_ICR_IE) << 15));
+ /* PCXI.UL = 1; */
+ env->active_tc.PCXI |= MASK_PCXI_UL;
+
+ /* PCXI[19: 0] = FCX[19: 0]; */
+ env->active_tc.PCXI = (env->active_tc.PCXI & 0xfff00000) +
+ (env->active_tc.FCX & 0xfffff);
+ /* FCX[19: 0] = new_FCX[19: 0]; */
+ env->active_tc.FCX = (env->active_tc.FCX & 0xfff00000) +
+ (new_FCX & 0xfffff);
+ /* A[11] = ret_addr[31: 0]; */
+ env->active_tc.gpr_a[11] = ret_address;
+
+ /* if (tmp_FCX == LCX) trap(FCD);*/
+ if (tmp_FCX == env->active_tc.LCX) {
+ printf("FCD trap\n");
+ }
+}
+
+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->active_tc.PSW & MASK_PSW_CDE) {
+ if (cdc_decrement(&(env->active_tc))) {
+ printf("CDU trap\n");
+ }
+ }
+ /* if (PCXI[19: 0] == 0) then trap(CSU); */
+ if ((env->active_tc.PCXI & 0xfffff) == 0) {
+ printf("CSU trap\n");
+ }
+ /* if (PCXI.UL == 0) then trap(CTYP); */
+ if ((env->active_tc.PCXI & MASK_PCXI_UL) == 0) {
+ printf("CTYP trap\n");
+ }
+ /* PC = {A11 [31: 1], 1’b0}; */
+ env->active_tc.PC = env->active_tc.gpr_a[11] & 0xfffffffe;
+
+ /* EA = {PCXI.PCXS, 6'b0, PCXI.PCXO, 6'b0}; */
+ ea = ((env->active_tc.PCXI & MASK_PCXI_PCXS) << 12) +
+ ((env->active_tc.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(env, ea, CONTEXT_UPPER, &new_PCXI, &new_PSW);
+ /* FCX[19: 0] = PCXI[19: 0]; */
+ env->active_tc.FCX = (env->active_tc.FCX & 0xfff00000) +
+ (env->active_tc.PCXI & 0x000fffff);
+ /* PCXI = new_PCXI; */
+ env->active_tc.PCXI = new_PCXI;
+}
+
static inline void QEMU_NORETURN do_raise_exception_err(CPUTRICOREState *env,
uint32_t exception,
int error_code,
diff --git a/target-tricore/translate.c b/target-tricore/translate.c
index 39f29bb..f32e1d1 100644
--- a/target-tricore/translate.c
+++ b/target-tricore/translate.c
@@ -117,6 +117,15 @@ static int sign_extend(uint32_t val, uint32_t width)
* Functions to generate micro-ops
*/
+/* Makros for generating helpers */
+#define gen_helper_2arg(name, arg0, arg1) do { \
+ TCGv_i32 helper_tmp0 = tcg_const_i32(arg0); \
+ TCGv_i32 helper_tmp1 = tcg_const_i32(arg1); \
+ gen_helper_##name(cpu_env, helper_tmp0, helper_tmp1); \
+ tcg_temp_free_i32(helper_tmp0); \
+ tcg_temp_free_i32(helper_tmp1); \
+ } while (0)
+
/* Functions for load/save to/from memory */
#define OP_MEM_INDIRECT(insn) \
static inline void gen_indirect_##insn(DisasContext *ctx, TCGv r1, TCGv r2, \
@@ -241,6 +250,64 @@ static inline void gen_ssov(TCGv ret, TCGv arg, int32_t
cons)
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_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_save_pc(ctx->pc + insn_bytes);
+ tcg_gen_exit_tb(0);
+
+ gen_set_label(jumpLabel);
+ gen_save_pc(ctx->pc + address * 2);
+ tcg_gen_exit_tb(0);
+
+}
+
+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_save_pc(ctx->pc+offset*2);
+ tcg_gen_exit_tb(0);
+ break;
+ case OPC1_16_SB_CALL:
+ gen_helper_2arg(call, ctx->pc, insn_bytes);
+ gen_save_pc(ctx->pc+sign_extend(offset, 7)*2);
+ tcg_gen_exit_tb(0);
+ 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
*/
@@ -249,6 +316,7 @@ static void decode_16Bit_opc(CPUTRICOREState *env,
DisasContext *ctx)
target_ulong op1;
int r1, r2;
uint16_t const16;
+ int32_t address;
TCGv temp;
op1 = MASK_OP_MAJOR(ctx->opcode);
@@ -541,6 +609,23 @@ static void decode_16Bit_opc(CPUTRICOREState *env,
DisasContext *ctx)
const16 = MASK_OP_SLRO_OFF4(ctx->opcode);
gen_indirect_ld32s(ctx, cpu_gpr_d[r1], cpu_gpr_a[15], const16 * 4);
break;
+/* SB-format */
+ case OPC1_16_SB_CALL:
+ address = MASK_OP_SB_DISP8(ctx->opcode);
+ gen_compute_branch(ctx, op1, 0, 0, 0, address);
+ break;
+ case OPC1_16_SB_J:
+ address = MASK_OP_SB_DISP8(ctx->opcode);
+ gen_compute_branch(ctx, op1, 0, 0, 0, address);
+ break;
+ case OPC1_16_SB_JNZ:
+ address = sign_extend(MASK_OP_SB_DISP8(ctx->opcode), 7);
+ gen_compute_branch(ctx, op1, 0, 0, 0, address);
+ break;
+ case OPC1_16_SB_JZ:
+ address = sign_extend(MASK_OP_SB_DISP8(ctx->opcode), 7);
+ gen_compute_branch(ctx, op1, 0, 0, 0, address);
+ break;
}
}
--
2.0.1
- [Qemu-devel] [PATCH 11/15] target-tricore: Add instructions of SBC and SBRN opcode format, (continued)
- [Qemu-devel] [PATCH 11/15] target-tricore: Add instructions of SBC and SBRN opcode format, Bastian Koppelmann, 2014/07/07
- [Qemu-devel] [PATCH 12/15] target-tricore: Add instructions of SBR opcode format, Bastian Koppelmann, 2014/07/07
- [Qemu-devel] [PATCH 01/15] target-tricore: Add target stubs and qom-cpu, Bastian Koppelmann, 2014/07/07
- [Qemu-devel] [PATCH 08/15] target-tricore: Add instructions of SSR opcode format, Bastian Koppelmann, 2014/07/07
- [Qemu-devel] [PATCH 10/15] target-tricore: Add instructions of SB opcode format,
Bastian Koppelmann <=
- [Qemu-devel] [PATCH 14/15] target-tricore: Add instructions of SLR, SSRO and SRO opcode format, Bastian Koppelmann, 2014/07/07
- [Qemu-devel] [PATCH 03/15] target-tricore: Add softmmu support, Bastian Koppelmann, 2014/07/07
- [Qemu-devel] [PATCH 09/15] target-tricore: Add instructions of SRRS and SLRO opcode format., Bastian Koppelmann, 2014/07/07
- [Qemu-devel] [PATCH 07/15] target-tricore: Add instructions of SRR opcode format, Bastian Koppelmann, 2014/07/07
- [Qemu-devel] [PATCH 02/15] target-tricore: Add board for systemmode, Bastian Koppelmann, 2014/07/07