TriCore v1.6.1 ISA and missing v1.6 instructions

-----BEGIN PGP SIGNATURE-----
 Version: GnuPG v2
 
 iQIcBAABCgAGBQJVX0UVAAoJEArSxjlracoUHboP/1Ajq0KCGYuyTeOLcZbfSqgR
 frvtEl4Js2VqJ69p3XipZ8j16Co0U+gDm6Hu7/wytGXOSAplXwvlDe+556778MpV
 xVdsXoeh5X5xPMtoU3qEy6sK4bLxxmjAJtj4Ij1NojqRbRr1ZuvxxaUgB5ud1eWE
 Th/HQEhquAiZTfSilqu+xAMeFfRrpPlqIKFhHHOcctEZw03v0kTEfBMXw0AR5UW2
 /ytvoBtiWnME2WYIkP6odWh96RthqigKhrCPbfnTFjD5amYeeeI0R8DeRKiDEWmY
 eEyddC5UcODIBfioj+aUbCf2jzu7LClu4MkyiFe0yK/SU2/Yz6v7GdgUhKsCoGAw
 noYbKOgilQtMBjs6hKbfxVIMmtkfz9dJ2y62H2PUzjCnFPhluZURE96T3p/e8HUo
 z3G+bTPZ69+7r4GxFMq8HpQE8hzC5xTZ8jA3bT+/8gYTyN8c0si4EF2XRBFhUm3H
 cjqSg8HTmoCQAPRkF29F1BrDyH/oPji2S5xLvtI4tG/Kk13ZhOcVxKky3wcK8Onf
 srCHdEsIThlMUCnAmphfqSCjliPXYmnZoGymeLfLRISPZrB4PmctTSbYdjdQU1kN
 ac5xa0NsL1wmFPLl2yk7TNFFpw0v1sH0SfpdxAjjVnj8B4jNRK6hleGFjpfjzpEE
 gl1/hij9FtqJPrx1Zgkz
 =NjJ8
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/bkoppelmann/tags/pull-tricore-20150522' into staging

TriCore v1.6.1 ISA and missing v1.6 instructions

# gpg: Signature made Fri May 22 16:02:45 2015 BST using RSA key ID 6B69CA14
# gpg: Good signature from "Bastian Koppelmann <kbastian@mail.uni-paderborn.de>"

* remotes/bkoppelmann/tags/pull-tricore-20150522:
  target-tricore: add RR_DIV and RR_DIV_U instructions of the v1.6 ISA
  target-tricore: add FRET instructions of the v1.6 ISA
  target-tricore: add FCALL instructions of the v1.6 ISA
  target-tricore: add SYS_RESTORE instruction of the v1.6 ISA
  target-tricore: add RR_CRC32 instruction of the v1.6.1 ISA
  target-tricore: add SWAPMSK instructions of the v1.6.1 ISA
  target-tricore: add CMPSWP instructions of the v1.6.1 ISA
  target-tricore: Add SRC_MOV_E instruction of the v1.6 ISA
  target-tricore: introduce ISA v1.6.1 feature
  target-tricore: Add ISA v1.3.1 cpu and fix tc1796 to using v1.3

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2015-05-22 16:22:42 +01:00
commit bb2fa17f18
6 changed files with 264 additions and 6 deletions

View File

@ -68,6 +68,10 @@ static void tricore_cpu_realizefn(DeviceState *dev, Error **errp)
CPUTriCoreState *env = &cpu->env; CPUTriCoreState *env = &cpu->env;
/* Some features automatically imply others */ /* 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)) { if (tricore_feature(env, TRICORE_FEATURE_16)) {
set_feature(env, TRICORE_FEATURE_131); set_feature(env, TRICORE_FEATURE_131);
} }
@ -118,14 +122,21 @@ static void tc1796_initfn(Object *obj)
{ {
TriCoreCPU *cpu = TRICORE_CPU(obj); TriCoreCPU *cpu = TRICORE_CPU(obj);
set_feature(&cpu->env, TRICORE_FEATURE_131); set_feature(&cpu->env, TRICORE_FEATURE_13);
} }
static void aurix_initfn(Object *obj) static void tc1797_initfn(Object *obj)
{ {
TriCoreCPU *cpu = TRICORE_CPU(obj); TriCoreCPU *cpu = TRICORE_CPU(obj);
set_feature(&cpu->env, TRICORE_FEATURE_16); set_feature(&cpu->env, TRICORE_FEATURE_131);
}
static void tc27x_initfn(Object *obj)
{
TriCoreCPU *cpu = TRICORE_CPU(obj);
set_feature(&cpu->env, TRICORE_FEATURE_161);
} }
typedef struct TriCoreCPUInfo { typedef struct TriCoreCPUInfo {
@ -136,7 +147,8 @@ typedef struct TriCoreCPUInfo {
static const TriCoreCPUInfo tricore_cpus[] = { static const TriCoreCPUInfo tricore_cpus[] = {
{ .name = "tc1796", .initfn = tc1796_initfn }, { .name = "tc1796", .initfn = tc1796_initfn },
{ .name = "aurix", .initfn = aurix_initfn }, { .name = "tc1797", .initfn = tc1797_initfn },
{ .name = "tc27x", .initfn = tc27x_initfn },
{ .name = NULL } { .name = NULL }
}; };

View File

@ -254,6 +254,7 @@ enum tricore_features {
TRICORE_FEATURE_13, TRICORE_FEATURE_13,
TRICORE_FEATURE_131, TRICORE_FEATURE_131,
TRICORE_FEATURE_16, TRICORE_FEATURE_16,
TRICORE_FEATURE_161,
}; };
static inline int tricore_feature(CPUTriCoreState *env, int feature) static inline int tricore_feature(CPUTriCoreState *env, int feature)

View File

@ -113,10 +113,14 @@ 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(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, TCG_CALL_NO_RWG_SE, i64, i64, i32)
DEF_HELPER_FLAGS_2(dvstep_u, 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 */ /* mulh */
DEF_HELPER_FLAGS_5(mul_h, TCG_CALL_NO_RWG_SE, i64, i32, i32, i32, i32, 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(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) 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 */ /* CSA */
DEF_HELPER_2(call, void, env, i32) DEF_HELPER_2(call, void, env, i32)
DEF_HELPER_1(ret, void, env) DEF_HELPER_1(ret, void, env)

View File

@ -19,6 +19,7 @@
#include "qemu/host-utils.h" #include "qemu/host-utils.h"
#include "exec/helper-proto.h" #include "exec/helper-proto.h"
#include "exec/cpu_ldst.h" #include "exec/cpu_ldst.h"
#include <zlib.h> /* for crc32 */
/* Addressing mode helper */ /* Addressing mode helper */
@ -2093,6 +2094,55 @@ uint64_t helper_dvstep_u(uint64_t r1, uint32_t r2)
return ((uint64_t)remainder << 32) | (uint32_t)dividend_quotient; 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, uint64_t helper_mul_h(uint32_t arg00, uint32_t arg01,
uint32_t arg10, uint32_t arg11, uint32_t n) uint32_t arg10, uint32_t arg11, uint32_t n)
{ {
@ -2165,6 +2215,16 @@ uint32_t helper_mulr_h(uint32_t arg00, uint32_t arg01,
return (result1 & 0xffff0000) | (result0 >> 16); 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 */ /* context save area (CSA) related helpers */
static int cdc_increment(target_ulong *psw) static int cdc_increment(target_ulong *psw)

View File

@ -201,6 +201,15 @@ void tricore_cpu_dump_state(CPUState *cs, FILE *f,
tcg_temp_free_i64(arg1); \ tcg_temp_free_i64(arg1); \
} while (0) } 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_ABS_FORMAT(con) (((con & 0x3C000) << 14) + (con & 0x3FFF))
#define EA_B_ABSOLUT(con) (((offset & 0xf00000) << 8) | \ #define EA_B_ABSOLUT(con) (((offset & 0xf00000) << 8) | \
((offset & 0x0fffff) << 1)) ((offset & 0x0fffff) << 1))
@ -319,6 +328,39 @@ static void gen_swap(DisasContext *ctx, int reg, TCGv ea)
tcg_temp_free(temp); 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);
}
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 /* 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 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. makros R, A and E, which allow read-only, all and endinit protected access.
@ -3242,6 +3284,32 @@ static void gen_loop(DisasContext *ctx, int r1, int32_t offset)
gen_goto_tb(ctx, 0, ctx->next_pc); 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_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, static void gen_compute_branch(DisasContext *ctx, uint32_t opc, int r1,
int r2 , int32_t constant , int32_t offset) int r2 , int32_t constant , int32_t offset)
{ {
@ -3336,6 +3404,14 @@ static void gen_compute_branch(DisasContext *ctx, uint32_t opc, int r1,
gen_helper_1arg(call, ctx->next_pc); gen_helper_1arg(call, ctx->next_pc);
gen_goto_tb(ctx, 0, EA_B_ABSOLUT(offset)); gen_goto_tb(ctx, 0, EA_B_ABSOLUT(offset));
break; 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: case OPC1_32_B_JLA:
tcg_gen_movi_tl(cpu_gpr_a[11], ctx->next_pc); tcg_gen_movi_tl(cpu_gpr_a[11], ctx->next_pc);
/* fall through */ /* fall through */
@ -3485,7 +3561,7 @@ static void gen_compute_branch(DisasContext *ctx, uint32_t opc, int r1,
* Functions for decoding instructions * 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; int r1;
int32_t const4; int32_t const4;
@ -3546,6 +3622,12 @@ static void decode_src_opc(DisasContext *ctx, int op1)
const4 = MASK_OP_SRC_CONST4(ctx->opcode); const4 = MASK_OP_SRC_CONST4(ctx->opcode);
tcg_gen_movi_tl(cpu_gpr_a[r1], const4); tcg_gen_movi_tl(cpu_gpr_a[r1], const4);
break; 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: case OPC1_16_SRC_SH:
gen_shi(cpu_gpr_d[r1], cpu_gpr_d[r1], const4); gen_shi(cpu_gpr_d[r1], cpu_gpr_d[r1], const4);
break; break;
@ -3810,6 +3892,8 @@ static void decode_sr_system(CPUTriCoreState *env, DisasContext *ctx)
case OPC2_16_SR_DEBUG: case OPC2_16_SR_DEBUG:
/* raise EXCP_DEBUG */ /* raise EXCP_DEBUG */
break; break;
case OPC2_16_SR_FRET:
gen_fret(ctx);
} }
} }
@ -3883,9 +3967,10 @@ static void decode_16Bit_opc(CPUTriCoreState *env, DisasContext *ctx)
case OPC1_16_SRC_LT: case OPC1_16_SRC_LT:
case OPC1_16_SRC_MOV: case OPC1_16_SRC_MOV:
case OPC1_16_SRC_MOV_A: case OPC1_16_SRC_MOV_A:
case OPC1_16_SRC_MOV_E:
case OPC1_16_SRC_SH: case OPC1_16_SRC_SH:
case OPC1_16_SRC_SHA: case OPC1_16_SRC_SHA:
decode_src_opc(ctx, op1); decode_src_opc(env, ctx, op1);
break; break;
/* SRR-format */ /* SRR-format */
case OPC1_16_SRR_ADD: case OPC1_16_SRR_ADD:
@ -5039,6 +5124,30 @@ static void decode_bo_addrmode_stctx_post_pre_base(CPUTriCoreState *env,
tcg_gen_addi_tl(cpu_gpr_a[r2], cpu_gpr_a[r2], off10); tcg_gen_addi_tl(cpu_gpr_a[r2], cpu_gpr_a[r2], off10);
gen_swap(ctx, r1, cpu_gpr_a[r2]); gen_swap(ctx, r1, cpu_gpr_a[r2]);
break; 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;
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(temp);
tcg_temp_free(temp2); tcg_temp_free(temp2);
@ -5082,7 +5191,24 @@ static void decode_bo_addrmode_ldmst_bitreverse_circular(CPUTriCoreState *env,
gen_swap(ctx, r1, temp2); gen_swap(ctx, r1, temp2);
gen_helper_circ_update(cpu_gpr_a[r2+1], cpu_gpr_a[r2+1], temp3); gen_helper_circ_update(cpu_gpr_a[r2+1], cpu_gpr_a[r2+1], temp3);
break; 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;
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); tcg_temp_free(temp);
tcg_temp_free(temp2); tcg_temp_free(temp2);
tcg_temp_free(temp3); tcg_temp_free(temp3);
@ -6230,6 +6356,10 @@ static void decode_rr_idirect(CPUTriCoreState *env, DisasContext *ctx)
gen_helper_1arg(call, ctx->next_pc); gen_helper_1arg(call, ctx->next_pc);
tcg_gen_andi_tl(cpu_PC, cpu_gpr_a[r1], ~0x1); tcg_gen_andi_tl(cpu_PC, cpu_gpr_a[r1], ~0x1);
break; 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); tcg_gen_exit_tb(0);
ctx->bstate = BS_BRANCH; ctx->bstate = BS_BRANCH;
@ -6368,6 +6498,23 @@ static void decode_rr_divide(CPUTriCoreState *env, DisasContext *ctx)
case OPC2_32_RR_UNPACK: case OPC2_32_RR_UNPACK:
gen_unpack(cpu_gpr_d[r3], cpu_gpr_d[r3+1], cpu_gpr_d[r1]); gen_unpack(cpu_gpr_d[r3], cpu_gpr_d[r3+1], cpu_gpr_d[r1]);
break; 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;
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;
} }
} }
@ -7706,10 +7853,12 @@ static void decode_rrrw_extract_insert(CPUTriCoreState *env, DisasContext *ctx)
static void decode_sys_interrupts(CPUTriCoreState *env, DisasContext *ctx) static void decode_sys_interrupts(CPUTriCoreState *env, DisasContext *ctx)
{ {
uint32_t op2; uint32_t op2;
uint32_t r1;
TCGLabel *l1; TCGLabel *l1;
TCGv tmp; TCGv tmp;
op2 = MASK_OP_SYS_OP2(ctx->opcode); op2 = MASK_OP_SYS_OP2(ctx->opcode);
r1 = MASK_OP_SYS_S1D(ctx->opcode);
switch (op2) { switch (op2) {
case OPC2_32_SYS_DEBUG: case OPC2_32_SYS_DEBUG:
@ -7730,6 +7879,9 @@ static void decode_sys_interrupts(CPUTriCoreState *env, DisasContext *ctx)
case OPC2_32_SYS_RET: case OPC2_32_SYS_RET:
gen_compute_branch(ctx, op2, 0, 0, 0, 0); gen_compute_branch(ctx, op2, 0, 0, 0, 0);
break; break;
case OPC2_32_SYS_FRET:
gen_fret(ctx);
break;
case OPC2_32_SYS_RFE: case OPC2_32_SYS_RFE:
gen_helper_rfe(cpu_env); gen_helper_rfe(cpu_env);
tcg_gen_exit_tb(0); tcg_gen_exit_tb(0);
@ -7758,6 +7910,14 @@ static void decode_sys_interrupts(CPUTriCoreState *env, DisasContext *ctx)
case OPC2_32_SYS_SVLCX: case OPC2_32_SYS_SVLCX:
gen_helper_svlcx(cpu_env); gen_helper_svlcx(cpu_env);
break; 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: case OPC2_32_SYS_TRAPSV:
/* TODO: raise sticky overflow trap */ /* TODO: raise sticky overflow trap */
break; break;
@ -7850,6 +8010,8 @@ static void decode_32Bit_opc(CPUTriCoreState *env, DisasContext *ctx)
/* B-format */ /* B-format */
case OPC1_32_B_CALL: case OPC1_32_B_CALL:
case OPC1_32_B_CALLA: case OPC1_32_B_CALLA:
case OPC1_32_B_FCALL:
case OPC1_32_B_FCALLA:
case OPC1_32_B_J: case OPC1_32_B_J:
case OPC1_32_B_JA: case OPC1_32_B_JA:
case OPC1_32_B_JL: case OPC1_32_B_JL:

View File

@ -399,6 +399,7 @@ enum {
OPC2_16_SR_RET = 0x09, OPC2_16_SR_RET = 0x09,
OPC2_16_SR_RFE = 0x08, OPC2_16_SR_RFE = 0x08,
OPC2_16_SR_DEBUG = 0x0a, OPC2_16_SR_DEBUG = 0x0a,
OPC2_16_SR_FRET = 0x07,
}; };
/* OPCM_16_SR_ACCU */ /* OPCM_16_SR_ACCU */
enum { enum {
@ -428,6 +429,8 @@ enum {
/* B Format */ /* B Format */
OPC1_32_B_CALL = 0x6d, OPC1_32_B_CALL = 0x6d,
OPC1_32_B_CALLA = 0xed, OPC1_32_B_CALLA = 0xed,
OPC1_32_B_FCALL = 0x61,
OPC1_32_B_FCALLA = 0xe1,
OPC1_32_B_J = 0x1d, OPC1_32_B_J = 0x1d,
OPC1_32_B_JA = 0x9d, OPC1_32_B_JA = 0x9d,
OPC1_32_B_JL = 0x5d, OPC1_32_B_JL = 0x5d,
@ -763,6 +766,12 @@ enum {
OPC2_32_BO_SWAP_W_SHORTOFF = 0x20, OPC2_32_BO_SWAP_W_SHORTOFF = 0x20,
OPC2_32_BO_SWAP_W_POSTINC = 0x00, OPC2_32_BO_SWAP_W_POSTINC = 0x00,
OPC2_32_BO_SWAP_W_PREINC = 0x10, 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,
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 */ /*OPCM_32_BO_ADDRMODE_LDMST_BITREVERSE_CIRCULAR */
enum { enum {
@ -770,6 +779,10 @@ enum {
OPC2_32_BO_LDMST_CIRC = 0x11, OPC2_32_BO_LDMST_CIRC = 0x11,
OPC2_32_BO_SWAP_W_BR = 0x00, OPC2_32_BO_SWAP_W_BR = 0x00,
OPC2_32_BO_SWAP_W_CIRC = 0x10, 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 * BRC Format
@ -1110,12 +1123,16 @@ enum {
OPC2_32_RR_DVINIT_U = 0x0a, OPC2_32_RR_DVINIT_U = 0x0a,
OPC2_32_RR_PARITY = 0x02, OPC2_32_RR_PARITY = 0x02,
OPC2_32_RR_UNPACK = 0x08, 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 */ /* OPCM_32_RR_IDIRECT */
enum { enum {
OPC2_32_RR_JI = 0x03, OPC2_32_RR_JI = 0x03,
OPC2_32_RR_JLI = 0x02, OPC2_32_RR_JLI = 0x02,
OPC2_32_RR_CALLI = 0x00, OPC2_32_RR_CALLI = 0x00,
OPC2_32_RR_FCALLI = 0x01,
}; };
/* /*
* RR1 Format * RR1 Format
@ -1423,4 +1440,6 @@ enum {
OPC2_32_SYS_SVLCX = 0x08, OPC2_32_SYS_SVLCX = 0x08,
OPC2_32_SYS_TRAPSV = 0x15, OPC2_32_SYS_TRAPSV = 0x15,
OPC2_32_SYS_TRAPV = 0x14, OPC2_32_SYS_TRAPV = 0x14,
OPC2_32_SYS_RESTORE = 0x0e,
OPC2_32_SYS_FRET = 0x03,
}; };