From fd5ecf31d4c48651de97c1aaf8771762753de9a7 Mon Sep 17 00:00:00 2001 From: Bastian Koppelmann Date: Sun, 22 Mar 2015 12:49:12 +0000 Subject: [PATCH 01/10] target-tricore: Add ISA v1.3.1 cpu and fix tc1796 to using v1.3 Signed-off-by: Bastian Koppelmann Reviewed-by: Richard Henderson --- target-tricore/cpu.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/target-tricore/cpu.c b/target-tricore/cpu.c index 2ba0cf4c89..9fe0b9783f 100644 --- a/target-tricore/cpu.c +++ b/target-tricore/cpu.c @@ -118,6 +118,13 @@ static void tc1796_initfn(Object *obj) { TriCoreCPU *cpu = TRICORE_CPU(obj); + set_feature(&cpu->env, TRICORE_FEATURE_13); +} + +static void tc1797_initfn(Object *obj) +{ + TriCoreCPU *cpu = TRICORE_CPU(obj); + set_feature(&cpu->env, TRICORE_FEATURE_131); } @@ -136,6 +143,7 @@ typedef struct TriCoreCPUInfo { static const TriCoreCPUInfo tricore_cpus[] = { { .name = "tc1796", .initfn = tc1796_initfn }, + { .name = "tc1797", .initfn = tc1797_initfn }, { .name = "aurix", .initfn = aurix_initfn }, { .name = NULL } }; From 6d2afc8a5edc042e4e7c2ceb49f7cabe02aae793 Mon Sep 17 00:00:00 2001 From: Bastian Koppelmann Date: Wed, 6 May 2015 20:18:41 +0200 Subject: [PATCH 02/10] target-tricore: introduce ISA v1.6.1 feature The aurix platform contains of several different cpu models and uses the 1.6.1 ISA. This patch changes the generic aurix model to the more specific tc27x cpu model and sets specific features. Signed-off-by: Bastian Koppelmann Reviewed-by: Richard Henderson --- target-tricore/cpu.c | 10 +++++++--- target-tricore/cpu.h | 1 + 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/target-tricore/cpu.c b/target-tricore/cpu.c index 9fe0b9783f..b3e5512bbf 100644 --- a/target-tricore/cpu.c +++ b/target-tricore/cpu.c @@ -68,6 +68,10 @@ static void tricore_cpu_realizefn(DeviceState *dev, Error **errp) CPUTriCoreState *env = &cpu->env; /* Some features automatically imply others */ + if (tricore_feature(env, TRICORE_FEATURE_161)) { + set_feature(env, TRICORE_FEATURE_16); + } + if (tricore_feature(env, TRICORE_FEATURE_16)) { set_feature(env, TRICORE_FEATURE_131); } @@ -128,11 +132,11 @@ static void tc1797_initfn(Object *obj) set_feature(&cpu->env, TRICORE_FEATURE_131); } -static void aurix_initfn(Object *obj) +static void tc27x_initfn(Object *obj) { TriCoreCPU *cpu = TRICORE_CPU(obj); - set_feature(&cpu->env, TRICORE_FEATURE_16); + set_feature(&cpu->env, TRICORE_FEATURE_161); } typedef struct TriCoreCPUInfo { @@ -144,7 +148,7 @@ typedef struct TriCoreCPUInfo { static const TriCoreCPUInfo tricore_cpus[] = { { .name = "tc1796", .initfn = tc1796_initfn }, { .name = "tc1797", .initfn = tc1797_initfn }, - { .name = "aurix", .initfn = aurix_initfn }, + { .name = "tc27x", .initfn = tc27x_initfn }, { .name = NULL } }; diff --git a/target-tricore/cpu.h b/target-tricore/cpu.h index c14b5f9016..504f15623d 100644 --- a/target-tricore/cpu.h +++ b/target-tricore/cpu.h @@ -254,6 +254,7 @@ enum tricore_features { TRICORE_FEATURE_13, TRICORE_FEATURE_131, TRICORE_FEATURE_16, + TRICORE_FEATURE_161, }; static inline int tricore_feature(CPUTriCoreState *env, int feature) From fcecf12684e1169653df72ed307ec2a82ca69b18 Mon Sep 17 00:00:00 2001 From: Bastian Koppelmann Date: Wed, 6 May 2015 20:22:45 +0200 Subject: [PATCH 03/10] target-tricore: Add SRC_MOV_E instruction of the v1.6 ISA Signed-off-by: Bastian Koppelmann Reviewed-by: Richard Henderson --- target-tricore/translate.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/target-tricore/translate.c b/target-tricore/translate.c index 663b2a0796..1c37e48133 100644 --- a/target-tricore/translate.c +++ b/target-tricore/translate.c @@ -3485,7 +3485,7 @@ static void gen_compute_branch(DisasContext *ctx, uint32_t opc, int r1, * Functions for decoding instructions */ -static void decode_src_opc(DisasContext *ctx, int op1) +static void decode_src_opc(CPUTriCoreState *env, DisasContext *ctx, int op1) { int r1; int32_t const4; @@ -3546,6 +3546,12 @@ static void decode_src_opc(DisasContext *ctx, int op1) const4 = MASK_OP_SRC_CONST4(ctx->opcode); tcg_gen_movi_tl(cpu_gpr_a[r1], const4); break; + case OPC1_16_SRC_MOV_E: + if (tricore_feature(env, TRICORE_FEATURE_16)) { + tcg_gen_movi_tl(cpu_gpr_d[r1], const4); + tcg_gen_sari_tl(cpu_gpr_d[r1+1], cpu_gpr_d[r1], 31); + } /* TODO: else raise illegal opcode trap */ + break; case OPC1_16_SRC_SH: gen_shi(cpu_gpr_d[r1], cpu_gpr_d[r1], const4); break; @@ -3883,9 +3889,10 @@ static void decode_16Bit_opc(CPUTriCoreState *env, DisasContext *ctx) case OPC1_16_SRC_LT: case OPC1_16_SRC_MOV: case OPC1_16_SRC_MOV_A: + case OPC1_16_SRC_MOV_E: case OPC1_16_SRC_SH: case OPC1_16_SRC_SHA: - decode_src_opc(ctx, op1); + decode_src_opc(env, ctx, op1); break; /* SRR-format */ case OPC1_16_SRR_ADD: From 62872ebc38d700ea30b0cd861e40703dccdcae2a Mon Sep 17 00:00:00 2001 From: Bastian Koppelmann Date: Wed, 6 May 2015 20:47:39 +0200 Subject: [PATCH 04/10] target-tricore: add CMPSWP instructions of the v1.6.1 ISA Those instruction were introduced in the new Aurix platform. Signed-off-by: Bastian Koppelmann Reviewed-by: Richard Henderson --- target-tricore/translate.c | 35 ++++++++++++++++++++++++++++++++ target-tricore/tricore-opcodes.h | 5 +++++ 2 files changed, 40 insertions(+) diff --git a/target-tricore/translate.c b/target-tricore/translate.c index 1c37e48133..06d183b146 100644 --- a/target-tricore/translate.c +++ b/target-tricore/translate.c @@ -319,6 +319,20 @@ static void gen_swap(DisasContext *ctx, int reg, TCGv ea) tcg_temp_free(temp); } +static void gen_cmpswap(DisasContext *ctx, int reg, TCGv ea) +{ + TCGv temp = tcg_temp_new(); + TCGv temp2 = tcg_temp_new(); + tcg_gen_qemu_ld_tl(temp, ea, ctx->mem_idx, MO_LEUL); + tcg_gen_movcond_tl(TCG_COND_EQ, temp2, cpu_gpr_d[reg+1], temp, + cpu_gpr_d[reg], temp); + tcg_gen_qemu_st_tl(temp2, ea, ctx->mem_idx, MO_LEUL); + tcg_gen_mov_tl(cpu_gpr_d[reg], temp); + + tcg_temp_free(temp); + tcg_temp_free(temp2); +} + /* We generate loads and store to core special function register (csfr) through the function gen_mfcr and gen_mtcr. To handle access permissions, we use 3 makros R, A and E, which allow read-only, all and endinit protected access. @@ -5046,6 +5060,18 @@ static void decode_bo_addrmode_stctx_post_pre_base(CPUTriCoreState *env, tcg_gen_addi_tl(cpu_gpr_a[r2], cpu_gpr_a[r2], off10); gen_swap(ctx, r1, cpu_gpr_a[r2]); break; + case OPC2_32_BO_CMPSWAP_W_SHORTOFF: + tcg_gen_addi_tl(temp, cpu_gpr_a[r2], off10); + gen_cmpswap(ctx, r1, temp); + break; + case OPC2_32_BO_CMPSWAP_W_POSTINC: + gen_cmpswap(ctx, r1, cpu_gpr_a[r2]); + tcg_gen_addi_tl(cpu_gpr_a[r2], cpu_gpr_a[r2], off10); + break; + case OPC2_32_BO_CMPSWAP_W_PREINC: + tcg_gen_addi_tl(cpu_gpr_a[r2], cpu_gpr_a[r2], off10); + gen_cmpswap(ctx, r1, cpu_gpr_a[r2]); + break; } tcg_temp_free(temp); tcg_temp_free(temp2); @@ -5089,7 +5115,16 @@ static void decode_bo_addrmode_ldmst_bitreverse_circular(CPUTriCoreState *env, gen_swap(ctx, r1, temp2); gen_helper_circ_update(cpu_gpr_a[r2+1], cpu_gpr_a[r2+1], temp3); break; + case OPC2_32_BO_CMPSWAP_W_BR: + gen_cmpswap(ctx, r1, temp2); + gen_helper_br_update(cpu_gpr_a[r2+1], cpu_gpr_a[r2+1]); + break; + case OPC2_32_BO_CMPSWAP_W_CIRC: + gen_cmpswap(ctx, r1, temp2); + gen_helper_circ_update(cpu_gpr_a[r2+1], cpu_gpr_a[r2+1], temp3); + break; } + tcg_temp_free(temp); tcg_temp_free(temp2); tcg_temp_free(temp3); diff --git a/target-tricore/tricore-opcodes.h b/target-tricore/tricore-opcodes.h index 2291f75fd9..95837aa370 100644 --- a/target-tricore/tricore-opcodes.h +++ b/target-tricore/tricore-opcodes.h @@ -763,6 +763,9 @@ enum { OPC2_32_BO_SWAP_W_SHORTOFF = 0x20, OPC2_32_BO_SWAP_W_POSTINC = 0x00, OPC2_32_BO_SWAP_W_PREINC = 0x10, + OPC2_32_BO_CMPSWAP_W_SHORTOFF = 0x23, + OPC2_32_BO_CMPSWAP_W_POSTINC = 0x03, + OPC2_32_BO_CMPSWAP_W_PREINC = 0x13, }; /*OPCM_32_BO_ADDRMODE_LDMST_BITREVERSE_CIRCULAR */ enum { @@ -770,6 +773,8 @@ enum { OPC2_32_BO_LDMST_CIRC = 0x11, OPC2_32_BO_SWAP_W_BR = 0x00, OPC2_32_BO_SWAP_W_CIRC = 0x10, + OPC2_32_BO_CMPSWAP_W_BR = 0x03, + OPC2_32_BO_CMPSWAP_W_CIRC = 0x13, }; /* * BRC Format From ddd8cebe3106bdfb2681d8d283296199fd6c7417 Mon Sep 17 00:00:00 2001 From: Bastian Koppelmann Date: Wed, 6 May 2015 20:57:10 +0200 Subject: [PATCH 05/10] target-tricore: add SWAPMSK instructions of the v1.6.1 ISA Those instruction were introduced in the new Aurix platform. Signed-off-by: Bastian Koppelmann Reviewed-by: Richard Henderson --- target-tricore/translate.c | 39 ++++++++++++++++++++++++++++++++ target-tricore/tricore-opcodes.h | 5 ++++ 2 files changed, 44 insertions(+) diff --git a/target-tricore/translate.c b/target-tricore/translate.c index 06d183b146..b2e25e7c7f 100644 --- a/target-tricore/translate.c +++ b/target-tricore/translate.c @@ -333,6 +333,25 @@ static void gen_cmpswap(DisasContext *ctx, int reg, TCGv ea) tcg_temp_free(temp2); } +static void gen_swapmsk(DisasContext *ctx, int reg, TCGv ea) +{ + TCGv temp = tcg_temp_new(); + TCGv temp2 = tcg_temp_new(); + TCGv temp3 = tcg_temp_new(); + + tcg_gen_qemu_ld_tl(temp, ea, ctx->mem_idx, MO_LEUL); + tcg_gen_and_tl(temp2, cpu_gpr_d[reg], cpu_gpr_d[reg+1]); + tcg_gen_andc_tl(temp3, temp, cpu_gpr_d[reg+1]); + tcg_gen_or_tl(temp2, temp2, temp3); + tcg_gen_qemu_st_tl(temp2, ea, ctx->mem_idx, MO_LEUL); + tcg_gen_mov_tl(cpu_gpr_d[reg], temp); + + tcg_temp_free(temp); + tcg_temp_free(temp2); + tcg_temp_free(temp3); +} + + /* We generate loads and store to core special function register (csfr) through the function gen_mfcr and gen_mtcr. To handle access permissions, we use 3 makros R, A and E, which allow read-only, all and endinit protected access. @@ -5072,6 +5091,18 @@ static void decode_bo_addrmode_stctx_post_pre_base(CPUTriCoreState *env, tcg_gen_addi_tl(cpu_gpr_a[r2], cpu_gpr_a[r2], off10); gen_cmpswap(ctx, r1, cpu_gpr_a[r2]); break; + case OPC2_32_BO_SWAPMSK_W_SHORTOFF: + tcg_gen_addi_tl(temp, cpu_gpr_a[r2], off10); + gen_swapmsk(ctx, r1, temp); + break; + case OPC2_32_BO_SWAPMSK_W_POSTINC: + gen_swapmsk(ctx, r1, cpu_gpr_a[r2]); + tcg_gen_addi_tl(cpu_gpr_a[r2], cpu_gpr_a[r2], off10); + break; + case OPC2_32_BO_SWAPMSK_W_PREINC: + tcg_gen_addi_tl(cpu_gpr_a[r2], cpu_gpr_a[r2], off10); + gen_swapmsk(ctx, r1, cpu_gpr_a[r2]); + break; } tcg_temp_free(temp); tcg_temp_free(temp2); @@ -5123,6 +5154,14 @@ static void decode_bo_addrmode_ldmst_bitreverse_circular(CPUTriCoreState *env, gen_cmpswap(ctx, r1, temp2); gen_helper_circ_update(cpu_gpr_a[r2+1], cpu_gpr_a[r2+1], temp3); break; + case OPC2_32_BO_SWAPMSK_W_BR: + gen_swapmsk(ctx, r1, temp2); + gen_helper_br_update(cpu_gpr_a[r2+1], cpu_gpr_a[r2+1]); + break; + case OPC2_32_BO_SWAPMSK_W_CIRC: + gen_swapmsk(ctx, r1, temp2); + gen_helper_circ_update(cpu_gpr_a[r2+1], cpu_gpr_a[r2+1], temp3); + break; } tcg_temp_free(temp); diff --git a/target-tricore/tricore-opcodes.h b/target-tricore/tricore-opcodes.h index 95837aa370..7ad6df9bd6 100644 --- a/target-tricore/tricore-opcodes.h +++ b/target-tricore/tricore-opcodes.h @@ -766,6 +766,9 @@ enum { OPC2_32_BO_CMPSWAP_W_SHORTOFF = 0x23, OPC2_32_BO_CMPSWAP_W_POSTINC = 0x03, OPC2_32_BO_CMPSWAP_W_PREINC = 0x13, + OPC2_32_BO_SWAPMSK_W_SHORTOFF = 0x22, + OPC2_32_BO_SWAPMSK_W_POSTINC = 0x02, + OPC2_32_BO_SWAPMSK_W_PREINC = 0x12, }; /*OPCM_32_BO_ADDRMODE_LDMST_BITREVERSE_CIRCULAR */ enum { @@ -775,6 +778,8 @@ enum { OPC2_32_BO_SWAP_W_CIRC = 0x10, OPC2_32_BO_CMPSWAP_W_BR = 0x03, OPC2_32_BO_CMPSWAP_W_CIRC = 0x13, + OPC2_32_BO_SWAPMSK_W_BR = 0x02, + OPC2_32_BO_SWAPMSK_W_CIRC = 0x12, }; /* * BRC Format From e5c96c82bc529674b61eacd221734abc2674e264 Mon Sep 17 00:00:00 2001 From: Bastian Koppelmann Date: Thu, 7 May 2015 19:55:37 +0200 Subject: [PATCH 06/10] target-tricore: add RR_CRC32 instruction of the v1.6.1 ISA This instruction was introduced by the new Aurix platform. Signed-off-by: Bastian Koppelmann Reviewed-by: Richard Henderson --- target-tricore/helper.h | 2 ++ target-tricore/op_helper.c | 11 +++++++++++ target-tricore/translate.c | 5 +++++ target-tricore/tricore-opcodes.h | 1 + 4 files changed, 19 insertions(+) diff --git a/target-tricore/helper.h b/target-tricore/helper.h index 1a49b00ccb..842506c5f9 100644 --- a/target-tricore/helper.h +++ b/target-tricore/helper.h @@ -117,6 +117,8 @@ DEF_HELPER_FLAGS_2(dvstep_u, TCG_CALL_NO_RWG_SE, i64, i64, i32) DEF_HELPER_FLAGS_5(mul_h, TCG_CALL_NO_RWG_SE, i64, i32, i32, i32, i32, i32) DEF_HELPER_FLAGS_5(mulm_h, TCG_CALL_NO_RWG_SE, i64, i32, i32, i32, i32, i32) DEF_HELPER_FLAGS_5(mulr_h, TCG_CALL_NO_RWG_SE, i32, i32, i32, i32, i32, i32) +/* crc32 */ +DEF_HELPER_FLAGS_2(crc32, TCG_CALL_NO_RWG_SE, i32, i32, i32) /* CSA */ DEF_HELPER_2(call, void, env, i32) DEF_HELPER_1(ret, void, env) diff --git a/target-tricore/op_helper.c b/target-tricore/op_helper.c index 9919b5b17b..7aa1f8e40e 100644 --- a/target-tricore/op_helper.c +++ b/target-tricore/op_helper.c @@ -19,6 +19,7 @@ #include "qemu/host-utils.h" #include "exec/helper-proto.h" #include "exec/cpu_ldst.h" +#include /* for crc32 */ /* Addressing mode helper */ @@ -2165,6 +2166,16 @@ uint32_t helper_mulr_h(uint32_t arg00, uint32_t arg01, return (result1 & 0xffff0000) | (result0 >> 16); } +uint32_t helper_crc32(uint32_t arg0, uint32_t arg1) +{ + uint8_t buf[4]; + uint32_t ret; + stl_be_p(buf, arg0); + + ret = crc32(arg1, buf, 4); + return ret; +} + /* context save area (CSA) related helpers */ static int cdc_increment(target_ulong *psw) diff --git a/target-tricore/translate.c b/target-tricore/translate.c index b2e25e7c7f..52f474ba9f 100644 --- a/target-tricore/translate.c +++ b/target-tricore/translate.c @@ -6449,6 +6449,11 @@ static void decode_rr_divide(CPUTriCoreState *env, DisasContext *ctx) case OPC2_32_RR_UNPACK: gen_unpack(cpu_gpr_d[r3], cpu_gpr_d[r3+1], cpu_gpr_d[r1]); break; + case OPC2_32_RR_CRC32: + if (tricore_feature(env, TRICORE_FEATURE_161)) { + gen_helper_crc32(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]); + } /* TODO: else raise illegal opcode trap */ + break; } } diff --git a/target-tricore/tricore-opcodes.h b/target-tricore/tricore-opcodes.h index 7ad6df9bd6..440c7fefed 100644 --- a/target-tricore/tricore-opcodes.h +++ b/target-tricore/tricore-opcodes.h @@ -1120,6 +1120,7 @@ enum { OPC2_32_RR_DVINIT_U = 0x0a, OPC2_32_RR_PARITY = 0x02, OPC2_32_RR_UNPACK = 0x08, + OPC2_32_RR_CRC32 = 0x03, }; /* OPCM_32_RR_IDIRECT */ enum { From bc3551c43308dd77bc1cc9a4e39962b2afd4dffc Mon Sep 17 00:00:00 2001 From: Bastian Koppelmann Date: Thu, 7 May 2015 21:25:42 +0200 Subject: [PATCH 07/10] target-tricore: add SYS_RESTORE instruction of the v1.6 ISA Signed-off-by: Bastian Koppelmann Reviewed-by: Richard Henderson --- target-tricore/translate.c | 10 ++++++++++ target-tricore/tricore-opcodes.h | 1 + 2 files changed, 11 insertions(+) diff --git a/target-tricore/translate.c b/target-tricore/translate.c index 52f474ba9f..4aea0c632a 100644 --- a/target-tricore/translate.c +++ b/target-tricore/translate.c @@ -7792,10 +7792,12 @@ static void decode_rrrw_extract_insert(CPUTriCoreState *env, DisasContext *ctx) static void decode_sys_interrupts(CPUTriCoreState *env, DisasContext *ctx) { uint32_t op2; + uint32_t r1; TCGLabel *l1; TCGv tmp; op2 = MASK_OP_SYS_OP2(ctx->opcode); + r1 = MASK_OP_SYS_S1D(ctx->opcode); switch (op2) { case OPC2_32_SYS_DEBUG: @@ -7844,6 +7846,14 @@ static void decode_sys_interrupts(CPUTriCoreState *env, DisasContext *ctx) case OPC2_32_SYS_SVLCX: gen_helper_svlcx(cpu_env); break; + case OPC2_32_SYS_RESTORE: + if (tricore_feature(env, TRICORE_FEATURE_16)) { + if ((ctx->hflags & TRICORE_HFLAG_KUU) == TRICORE_HFLAG_SM || + (ctx->hflags & TRICORE_HFLAG_KUU) == TRICORE_HFLAG_UM1) { + tcg_gen_deposit_tl(cpu_ICR, cpu_ICR, cpu_gpr_d[r1], 8, 1); + } /* else raise privilege trap */ + } /* else raise illegal opcode trap */ + break; case OPC2_32_SYS_TRAPSV: /* TODO: raise sticky overflow trap */ break; diff --git a/target-tricore/tricore-opcodes.h b/target-tricore/tricore-opcodes.h index 440c7fefed..d1506a9429 100644 --- a/target-tricore/tricore-opcodes.h +++ b/target-tricore/tricore-opcodes.h @@ -1434,4 +1434,5 @@ enum { OPC2_32_SYS_SVLCX = 0x08, OPC2_32_SYS_TRAPSV = 0x15, OPC2_32_SYS_TRAPV = 0x14, + OPC2_32_SYS_RESTORE = 0x0e, }; From 9e14a7b24f4cff93da664fdcfecad41fbd229e2b Mon Sep 17 00:00:00 2001 From: Bastian Koppelmann Date: Thu, 7 May 2015 22:38:16 +0200 Subject: [PATCH 08/10] target-tricore: add FCALL instructions of the v1.6 ISA Signed-off-by: Bastian Koppelmann Reviewed-by: Richard Henderson --- target-tricore/translate.c | 26 ++++++++++++++++++++++++++ target-tricore/tricore-opcodes.h | 3 +++ 2 files changed, 29 insertions(+) diff --git a/target-tricore/translate.c b/target-tricore/translate.c index 4aea0c632a..76bab8e5de 100644 --- a/target-tricore/translate.c +++ b/target-tricore/translate.c @@ -3275,6 +3275,18 @@ static void gen_loop(DisasContext *ctx, int r1, int32_t offset) gen_goto_tb(ctx, 0, ctx->next_pc); } +static void gen_fcall_save_ctx(DisasContext *ctx) +{ + TCGv temp = tcg_temp_new(); + + tcg_gen_addi_tl(temp, cpu_gpr_a[10], -4); + tcg_gen_qemu_st_tl(cpu_gpr_a[11], temp, ctx->mem_idx, MO_LESL); + tcg_gen_movi_tl(cpu_gpr_a[11], ctx->next_pc); + tcg_gen_mov_tl(cpu_gpr_a[10], temp); + + tcg_temp_free(temp); +} + static void gen_compute_branch(DisasContext *ctx, uint32_t opc, int r1, int r2 , int32_t constant , int32_t offset) { @@ -3369,6 +3381,14 @@ static void gen_compute_branch(DisasContext *ctx, uint32_t opc, int r1, gen_helper_1arg(call, ctx->next_pc); gen_goto_tb(ctx, 0, EA_B_ABSOLUT(offset)); break; + case OPC1_32_B_FCALL: + gen_fcall_save_ctx(ctx); + gen_goto_tb(ctx, 0, ctx->pc + offset * 2); + break; + case OPC1_32_B_FCALLA: + gen_fcall_save_ctx(ctx); + gen_goto_tb(ctx, 0, EA_B_ABSOLUT(offset)); + break; case OPC1_32_B_JLA: tcg_gen_movi_tl(cpu_gpr_a[11], ctx->next_pc); /* fall through */ @@ -6311,6 +6331,10 @@ static void decode_rr_idirect(CPUTriCoreState *env, DisasContext *ctx) gen_helper_1arg(call, ctx->next_pc); tcg_gen_andi_tl(cpu_PC, cpu_gpr_a[r1], ~0x1); break; + case OPC2_32_RR_FCALLI: + gen_fcall_save_ctx(ctx); + tcg_gen_andi_tl(cpu_PC, cpu_gpr_a[r1], ~0x1); + break; } tcg_gen_exit_tb(0); ctx->bstate = BS_BRANCH; @@ -7946,6 +7970,8 @@ static void decode_32Bit_opc(CPUTriCoreState *env, DisasContext *ctx) /* B-format */ case OPC1_32_B_CALL: case OPC1_32_B_CALLA: + case OPC1_32_B_FCALL: + case OPC1_32_B_FCALLA: case OPC1_32_B_J: case OPC1_32_B_JA: case OPC1_32_B_JL: diff --git a/target-tricore/tricore-opcodes.h b/target-tricore/tricore-opcodes.h index d1506a9429..bb1939cb65 100644 --- a/target-tricore/tricore-opcodes.h +++ b/target-tricore/tricore-opcodes.h @@ -428,6 +428,8 @@ enum { /* B Format */ OPC1_32_B_CALL = 0x6d, OPC1_32_B_CALLA = 0xed, + OPC1_32_B_FCALL = 0x61, + OPC1_32_B_FCALLA = 0xe1, OPC1_32_B_J = 0x1d, OPC1_32_B_JA = 0x9d, OPC1_32_B_JL = 0x5d, @@ -1127,6 +1129,7 @@ enum { OPC2_32_RR_JI = 0x03, OPC2_32_RR_JLI = 0x02, OPC2_32_RR_CALLI = 0x00, + OPC2_32_RR_FCALLI = 0x01, }; /* * RR1 Format From 0e045f43c45f675711c3f6836118dc7eabcc2411 Mon Sep 17 00:00:00 2001 From: Bastian Koppelmann Date: Thu, 7 May 2015 22:46:50 +0200 Subject: [PATCH 09/10] target-tricore: add FRET instructions of the v1.6 ISA Signed-off-by: Bastian Koppelmann Reviewed-by: Richard Henderson --- target-tricore/translate.c | 19 +++++++++++++++++++ target-tricore/tricore-opcodes.h | 2 ++ 2 files changed, 21 insertions(+) diff --git a/target-tricore/translate.c b/target-tricore/translate.c index 76bab8e5de..d4e4226f69 100644 --- a/target-tricore/translate.c +++ b/target-tricore/translate.c @@ -3287,6 +3287,20 @@ static void gen_fcall_save_ctx(DisasContext *ctx) tcg_temp_free(temp); } +static void gen_fret(DisasContext *ctx) +{ + TCGv temp = tcg_temp_new(); + + tcg_gen_andi_tl(temp, cpu_gpr_a[11], ~0x1); + tcg_gen_qemu_ld_tl(cpu_gpr_a[11], cpu_gpr_a[10], ctx->mem_idx, MO_LESL); + tcg_gen_addi_tl(cpu_gpr_a[10], cpu_gpr_a[10], 4); + tcg_gen_mov_tl(cpu_PC, temp); + tcg_gen_exit_tb(0); + ctx->bstate = BS_BRANCH; + + tcg_temp_free(temp); +} + static void gen_compute_branch(DisasContext *ctx, uint32_t opc, int r1, int r2 , int32_t constant , int32_t offset) { @@ -3869,6 +3883,8 @@ static void decode_sr_system(CPUTriCoreState *env, DisasContext *ctx) case OPC2_16_SR_DEBUG: /* raise EXCP_DEBUG */ break; + case OPC2_16_SR_FRET: + gen_fret(ctx); } } @@ -7842,6 +7858,9 @@ static void decode_sys_interrupts(CPUTriCoreState *env, DisasContext *ctx) case OPC2_32_SYS_RET: gen_compute_branch(ctx, op2, 0, 0, 0, 0); break; + case OPC2_32_SYS_FRET: + gen_fret(ctx); + break; case OPC2_32_SYS_RFE: gen_helper_rfe(cpu_env); tcg_gen_exit_tb(0); diff --git a/target-tricore/tricore-opcodes.h b/target-tricore/tricore-opcodes.h index bb1939cb65..22c79f570f 100644 --- a/target-tricore/tricore-opcodes.h +++ b/target-tricore/tricore-opcodes.h @@ -399,6 +399,7 @@ enum { OPC2_16_SR_RET = 0x09, OPC2_16_SR_RFE = 0x08, OPC2_16_SR_DEBUG = 0x0a, + OPC2_16_SR_FRET = 0x07, }; /* OPCM_16_SR_ACCU */ enum { @@ -1438,4 +1439,5 @@ enum { OPC2_32_SYS_TRAPSV = 0x15, OPC2_32_SYS_TRAPV = 0x14, OPC2_32_SYS_RESTORE = 0x0e, + OPC2_32_SYS_FRET = 0x03, }; From 9371557115a734412974f8d4096cbe8a62ca2731 Mon Sep 17 00:00:00 2001 From: Bastian Koppelmann Date: Mon, 11 May 2015 14:59:55 +0200 Subject: [PATCH 10/10] target-tricore: add RR_DIV and RR_DIV_U instructions of the v1.6 ISA Signed-off-by: Bastian Koppelmann Reviewed-by: Richard Henderson --- target-tricore/helper.h | 2 ++ target-tricore/op_helper.c | 49 ++++++++++++++++++++++++++++++++ target-tricore/translate.c | 21 ++++++++++++++ target-tricore/tricore-opcodes.h | 2 ++ 4 files changed, 74 insertions(+) diff --git a/target-tricore/helper.h b/target-tricore/helper.h index 842506c5f9..cc221f1a9b 100644 --- a/target-tricore/helper.h +++ b/target-tricore/helper.h @@ -113,6 +113,8 @@ DEF_HELPER_3(dvinit_h_131, i64, env, i32, i32) DEF_HELPER_FLAGS_2(dvadj, TCG_CALL_NO_RWG_SE, i64, i64, i32) DEF_HELPER_FLAGS_2(dvstep, TCG_CALL_NO_RWG_SE, i64, i64, i32) DEF_HELPER_FLAGS_2(dvstep_u, TCG_CALL_NO_RWG_SE, i64, i64, i32) +DEF_HELPER_3(divide, i64, env, i32, i32) +DEF_HELPER_3(divide_u, i64, env, i32, i32) /* mulh */ DEF_HELPER_FLAGS_5(mul_h, TCG_CALL_NO_RWG_SE, i64, i32, i32, i32, i32, i32) DEF_HELPER_FLAGS_5(mulm_h, TCG_CALL_NO_RWG_SE, i64, i32, i32, i32, i32, i32) diff --git a/target-tricore/op_helper.c b/target-tricore/op_helper.c index 7aa1f8e40e..10ed541dfd 100644 --- a/target-tricore/op_helper.c +++ b/target-tricore/op_helper.c @@ -2094,6 +2094,55 @@ uint64_t helper_dvstep_u(uint64_t r1, uint32_t r2) return ((uint64_t)remainder << 32) | (uint32_t)dividend_quotient; } +uint64_t helper_divide(CPUTriCoreState *env, uint32_t r1, uint32_t r2) +{ + int32_t quotient, remainder; + int32_t dividend = (int32_t)r1; + int32_t divisor = (int32_t)r2; + + if (divisor == 0) { + if (dividend >= 0) { + quotient = 0x7fffffff; + remainder = 0; + } else { + quotient = 0x80000000; + remainder = 0; + } + env->PSW_USB_V = (1 << 31); + } else if ((divisor == 0xffffffff) && (dividend == 0x80000000)) { + quotient = 0x7fffffff; + remainder = 0; + env->PSW_USB_V = (1 << 31); + } else { + remainder = dividend % divisor; + quotient = (dividend - remainder)/divisor; + env->PSW_USB_V = 0; + } + env->PSW_USB_SV |= env->PSW_USB_V; + env->PSW_USB_AV = 0; + return ((uint64_t)remainder << 32) | (uint32_t)quotient; +} + +uint64_t helper_divide_u(CPUTriCoreState *env, uint32_t r1, uint32_t r2) +{ + uint32_t quotient, remainder; + uint32_t dividend = r1; + uint32_t divisor = r2; + + if (divisor == 0) { + quotient = 0xffffffff; + remainder = 0; + env->PSW_USB_V = (1 << 31); + } else { + remainder = dividend % divisor; + quotient = (dividend - remainder)/divisor; + env->PSW_USB_V = 0; + } + env->PSW_USB_SV |= env->PSW_USB_V; + env->PSW_USB_AV = 0; + return ((uint64_t)remainder << 32) | quotient; +} + uint64_t helper_mul_h(uint32_t arg00, uint32_t arg01, uint32_t arg10, uint32_t arg11, uint32_t n) { diff --git a/target-tricore/translate.c b/target-tricore/translate.c index d4e4226f69..5f8eff04fa 100644 --- a/target-tricore/translate.c +++ b/target-tricore/translate.c @@ -201,6 +201,15 @@ void tricore_cpu_dump_state(CPUState *cs, FILE *f, tcg_temp_free_i64(arg1); \ } while (0) +#define GEN_HELPER_RR(name, rl, rh, arg1, arg2) do { \ + TCGv_i64 ret = tcg_temp_new_i64(); \ + \ + gen_helper_##name(ret, cpu_env, arg1, arg2); \ + tcg_gen_extr_i64_i32(rl, rh, ret); \ + \ + tcg_temp_free_i64(ret); \ +} while (0) + #define EA_ABS_FORMAT(con) (((con & 0x3C000) << 14) + (con & 0x3FFF)) #define EA_B_ABSOLUT(con) (((offset & 0xf00000) << 8) | \ ((offset & 0x0fffff) << 1)) @@ -6494,6 +6503,18 @@ static void decode_rr_divide(CPUTriCoreState *env, DisasContext *ctx) gen_helper_crc32(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]); } /* TODO: else raise illegal opcode trap */ break; + case OPC2_32_RR_DIV: + if (tricore_feature(env, TRICORE_FEATURE_16)) { + GEN_HELPER_RR(divide, cpu_gpr_d[r3], cpu_gpr_d[r3+1], cpu_gpr_d[r1], + cpu_gpr_d[r2]); + } /* TODO: else raise illegal opcode trap */ + break; + case OPC2_32_RR_DIV_U: + if (tricore_feature(env, TRICORE_FEATURE_16)) { + GEN_HELPER_RR(divide_u, cpu_gpr_d[r3], cpu_gpr_d[r3+1], + cpu_gpr_d[r1], cpu_gpr_d[r2]); + } /* TODO: else raise illegal opcode trap */ + break; } } diff --git a/target-tricore/tricore-opcodes.h b/target-tricore/tricore-opcodes.h index 22c79f570f..1bfed0ce48 100644 --- a/target-tricore/tricore-opcodes.h +++ b/target-tricore/tricore-opcodes.h @@ -1124,6 +1124,8 @@ enum { OPC2_32_RR_PARITY = 0x02, OPC2_32_RR_UNPACK = 0x08, OPC2_32_RR_CRC32 = 0x03, + OPC2_32_RR_DIV = 0x20, + OPC2_32_RR_DIV_U = 0x21, }; /* OPCM_32_RR_IDIRECT */ enum {