- Implement privilege levels for TriCore
- Fix missing REG_PAIR() for insns using two 32 regs - Fix erroneously saving PSW.CDC on CALL insns - Added some missing v1.6.2 insns -----BEGIN PGP SIGNATURE----- iQJTBAABCgA9FiEEbmNqfoPy3Qz6bm43CtLGOWtpyhQFAmSTIWsfHGtiYXN0aWFu QG1haWwudW5pLXBhZGVyYm9ybi5kZQAKCRAK0sY5a2nKFEVCEACQFRGj/7ADOWm3 lhkHGgkwpTgx+YKgeI4rfQ5/AKie9b7BUNljPVp1m2AvPFHU/r/0POzziCTDM+Ty M90h5gsEgxNRRVS1T+VkfFTKop7yImo48niDBF4mByP9DZGweCvGEvPD2g/FYvLP 0Up13F0NiWKMvocKp/jjI5qejpJqwtn1hjWHTpEXya3u+K/iEku1alI72Xo2oMKW pKW2iO/mC4cuEzOdpZt4LSzs9ZMsVpFzVn81VIda9CU2rlSpu+oQevgdWWJhgZGa 520JnIsrervsJumBWPxh9R0nrjuhHu34I4HXD38eGhD+Ioz2DQnHy2bA99pIVR7B qtHoDNhl7wqWgXBqntS9HvnvDAFyYdVM6aLqw9C7AxKXdRBuxy14R3/hrwMZghRs vYx3GUcFHSMJT1tkc8a/P14/mz5SB6/cdjVgPQtTCPBJccly4oc4EG3qn7wYqowZ Pbq48h+3+QZ7BsC9sT2AiPq+AmLjxRZRq7SE6YrYrjRDIJz/3IoTR600KW5XsFsj gZu/SYWdbNXAVr4c7CCg77lXXQ2/GhPHgCYFjL3djIKwlPP79bhT4cvLXK71yF/4 3RcCBt9kRggxDz6E/4I+u5cE4oMbyN1f6AoIn80GUheDstWMACYph5RhbIskxRhY PWwJ8ML0c7SOy0A74UbCT82gn1He1A== =IKrz -----END PGP SIGNATURE----- Merge tag 'pull-tricore-20230621-1' of https://github.com/bkoppelmann/qemu into staging - Implement privilege levels for TriCore - Fix missing REG_PAIR() for insns using two 32 regs - Fix erroneously saving PSW.CDC on CALL insns - Added some missing v1.6.2 insns # -----BEGIN PGP SIGNATURE----- # # iQJTBAABCgA9FiEEbmNqfoPy3Qz6bm43CtLGOWtpyhQFAmSTIWsfHGtiYXN0aWFu # QG1haWwudW5pLXBhZGVyYm9ybi5kZQAKCRAK0sY5a2nKFEVCEACQFRGj/7ADOWm3 # lhkHGgkwpTgx+YKgeI4rfQ5/AKie9b7BUNljPVp1m2AvPFHU/r/0POzziCTDM+Ty # M90h5gsEgxNRRVS1T+VkfFTKop7yImo48niDBF4mByP9DZGweCvGEvPD2g/FYvLP # 0Up13F0NiWKMvocKp/jjI5qejpJqwtn1hjWHTpEXya3u+K/iEku1alI72Xo2oMKW # pKW2iO/mC4cuEzOdpZt4LSzs9ZMsVpFzVn81VIda9CU2rlSpu+oQevgdWWJhgZGa # 520JnIsrervsJumBWPxh9R0nrjuhHu34I4HXD38eGhD+Ioz2DQnHy2bA99pIVR7B # qtHoDNhl7wqWgXBqntS9HvnvDAFyYdVM6aLqw9C7AxKXdRBuxy14R3/hrwMZghRs # vYx3GUcFHSMJT1tkc8a/P14/mz5SB6/cdjVgPQtTCPBJccly4oc4EG3qn7wYqowZ # Pbq48h+3+QZ7BsC9sT2AiPq+AmLjxRZRq7SE6YrYrjRDIJz/3IoTR600KW5XsFsj # gZu/SYWdbNXAVr4c7CCg77lXXQ2/GhPHgCYFjL3djIKwlPP79bhT4cvLXK71yF/4 # 3RcCBt9kRggxDz6E/4I+u5cE4oMbyN1f6AoIn80GUheDstWMACYph5RhbIskxRhY # PWwJ8ML0c7SOy0A74UbCT82gn1He1A== # =IKrz # -----END PGP SIGNATURE----- # gpg: Signature made Wed 21 Jun 2023 06:12:27 PM CEST # gpg: using RSA key 6E636A7E83F2DD0CFA6E6E370AD2C6396B69CA14 # gpg: issuer "kbastian@mail.uni-paderborn.de" # gpg: Good signature from "Bastian Koppelmann <kbastian@mail.uni-paderborn.de>" [undefined] # 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-20230621-1' of https://github.com/bkoppelmann/qemu: target/tricore: Fix ICR.IE offset in RESTORE insn target/tricore: Honour privilege changes on PSW write target/tricore: Implement privilege level for all insns target/tricore: Introduce priv tb flag target/tricore: Indirect jump insns use tcg_gen_lookup_and_goto_ptr() target/tricore: ENABLE exit to main-loop target/tricore: Introduce DISAS_TARGET_EXIT target/tricore: Fix RR_JLI clobbering reg A[11] target/tricore: Fix helper_ret() not correctly restoring PSW target/tricore: Add CHECK_REG_PAIR() for insn accessing 64 bit regs target/tricore: Correctly fix saving PSW.CDE to CSA on call target/tricore: Fix out-of-bounds index in imask instruction target/tricore: Add DISABLE insn variant target/tricore: Implement SYCSCALL insn target/tricore: Add shuffle insn target/tricore: Add crc32.b insn target/tricore: Add crc32l.w insn target/tricore: Add LHA insn target/tricore: Add popcnt.w insn target/tricore: Introduce ISA 1.6.2 feature Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
commit
67fe6ae41d
|
@ -104,6 +104,10 @@ static void tricore_cpu_realizefn(DeviceState *dev, Error **errp)
|
|||
}
|
||||
|
||||
/* Some features automatically imply others */
|
||||
if (tricore_feature(env, TRICORE_FEATURE_162)) {
|
||||
set_feature(env, TRICORE_FEATURE_161);
|
||||
}
|
||||
|
||||
if (tricore_feature(env, TRICORE_FEATURE_161)) {
|
||||
set_feature(env, TRICORE_FEATURE_16);
|
||||
}
|
||||
|
@ -164,6 +168,14 @@ static void tc27x_initfn(Object *obj)
|
|||
set_feature(&cpu->env, TRICORE_FEATURE_161);
|
||||
}
|
||||
|
||||
static void tc37x_initfn(Object *obj)
|
||||
{
|
||||
TriCoreCPU *cpu = TRICORE_CPU(obj);
|
||||
|
||||
set_feature(&cpu->env, TRICORE_FEATURE_162);
|
||||
}
|
||||
|
||||
|
||||
#include "hw/core/sysemu-cpu-ops.h"
|
||||
|
||||
static const struct SysemuCPUOps tricore_sysemu_ops = {
|
||||
|
@ -226,6 +238,7 @@ static const TypeInfo tricore_cpu_type_infos[] = {
|
|||
DEFINE_TRICORE_CPU_TYPE("tc1796", tc1796_initfn),
|
||||
DEFINE_TRICORE_CPU_TYPE("tc1797", tc1797_initfn),
|
||||
DEFINE_TRICORE_CPU_TYPE("tc27x", tc27x_initfn),
|
||||
DEFINE_TRICORE_CPU_TYPE("tc37x", tc37x_initfn),
|
||||
};
|
||||
|
||||
DEFINE_TYPES(tricore_cpu_type_infos)
|
||||
|
|
|
@ -263,16 +263,18 @@ void icr_set_ie(CPUTriCoreState *env, uint32_t val);
|
|||
#define MASK_DBGSR_PEVT 0x40
|
||||
#define MASK_DBGSR_EVTSRC 0x1f00
|
||||
|
||||
#define TRICORE_HFLAG_KUU 0x3
|
||||
#define TRICORE_HFLAG_UM0 0x00002 /* user mode-0 flag */
|
||||
#define TRICORE_HFLAG_UM1 0x00001 /* user mode-1 flag */
|
||||
#define TRICORE_HFLAG_SM 0x00000 /* kernel mode flag */
|
||||
enum tricore_priv_levels {
|
||||
TRICORE_PRIV_UM0 = 0x0, /* user mode-0 flag */
|
||||
TRICORE_PRIV_UM1 = 0x1, /* user mode-1 flag */
|
||||
TRICORE_PRIV_SM = 0x2, /* kernel mode flag */
|
||||
};
|
||||
|
||||
enum tricore_features {
|
||||
TRICORE_FEATURE_13,
|
||||
TRICORE_FEATURE_131,
|
||||
TRICORE_FEATURE_16,
|
||||
TRICORE_FEATURE_161,
|
||||
TRICORE_FEATURE_162,
|
||||
};
|
||||
|
||||
static inline int tricore_feature(CPUTriCoreState *env, int feature)
|
||||
|
@ -377,15 +379,21 @@ static inline int cpu_mmu_index(CPUTriCoreState *env, bool ifetch)
|
|||
|
||||
#include "exec/cpu-all.h"
|
||||
|
||||
FIELD(TB_FLAGS, PRIV, 0, 2)
|
||||
|
||||
void cpu_state_reset(CPUTriCoreState *s);
|
||||
void tricore_tcg_init(void);
|
||||
|
||||
static inline void cpu_get_tb_cpu_state(CPUTriCoreState *env, target_ulong *pc,
|
||||
target_ulong *cs_base, uint32_t *flags)
|
||||
{
|
||||
uint32_t new_flags = 0;
|
||||
*pc = env->PC;
|
||||
*cs_base = 0;
|
||||
*flags = 0;
|
||||
|
||||
new_flags |= FIELD_DP32(new_flags, TB_FLAGS, PRIV,
|
||||
extract32(env->PSW, 10, 2));
|
||||
*flags = new_flags;
|
||||
}
|
||||
|
||||
#define TRICORE_CPU_TYPE_SUFFIX "-" TYPE_TRICORE_CPU
|
||||
|
|
|
@ -131,7 +131,10 @@ 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)
|
||||
DEF_HELPER_FLAGS_2(crc32b, TCG_CALL_NO_RWG_SE, i32, i32, i32)
|
||||
DEF_HELPER_FLAGS_2(crc32_be, TCG_CALL_NO_RWG_SE, i32, i32, i32)
|
||||
DEF_HELPER_FLAGS_2(crc32_le, TCG_CALL_NO_RWG_SE, i32, i32, i32)
|
||||
DEF_HELPER_FLAGS_2(shuffle, TCG_CALL_NO_RWG_SE, i32, i32, i32)
|
||||
/* CSA */
|
||||
DEF_HELPER_2(call, void, env, i32)
|
||||
DEF_HELPER_1(ret, void, env)
|
||||
|
|
|
@ -2284,7 +2284,15 @@ 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)
|
||||
uint32_t helper_crc32b(uint32_t arg0, uint32_t arg1)
|
||||
{
|
||||
uint8_t buf[1] = { arg0 & 0xff };
|
||||
|
||||
return crc32(arg1, buf, 1);
|
||||
}
|
||||
|
||||
|
||||
uint32_t helper_crc32_be(uint32_t arg0, uint32_t arg1)
|
||||
{
|
||||
uint8_t buf[4];
|
||||
stl_be_p(buf, arg0);
|
||||
|
@ -2292,6 +2300,50 @@ uint32_t helper_crc32(uint32_t arg0, uint32_t arg1)
|
|||
return crc32(arg1, buf, 4);
|
||||
}
|
||||
|
||||
uint32_t helper_crc32_le(uint32_t arg0, uint32_t arg1)
|
||||
{
|
||||
uint8_t buf[4];
|
||||
stl_le_p(buf, arg0);
|
||||
|
||||
return crc32(arg1, buf, 4);
|
||||
}
|
||||
|
||||
uint32_t helper_shuffle(uint32_t arg0, uint32_t arg1)
|
||||
{
|
||||
uint32_t resb;
|
||||
uint32_t byte_select;
|
||||
uint32_t res = 0;
|
||||
|
||||
byte_select = arg1 & 0x3;
|
||||
resb = extract32(arg0, byte_select * 8, 8);
|
||||
res |= resb << 0;
|
||||
|
||||
byte_select = (arg1 >> 2) & 0x3;
|
||||
resb = extract32(arg0, byte_select * 8, 8);
|
||||
res |= resb << 8;
|
||||
|
||||
byte_select = (arg1 >> 4) & 0x3;
|
||||
resb = extract32(arg0, byte_select * 8, 8);
|
||||
res |= resb << 16;
|
||||
|
||||
byte_select = (arg1 >> 6) & 0x3;
|
||||
resb = extract32(arg0, byte_select * 8, 8);
|
||||
res |= resb << 24;
|
||||
|
||||
if (arg1 & 0x100) {
|
||||
/* Assign the correct nibble position. */
|
||||
res = ((res & 0xf0f0f0f0) >> 4)
|
||||
| ((res & 0x0f0f0f0f) << 4);
|
||||
/* Assign the correct bit position. */
|
||||
res = ((res & 0x88888888) >> 3)
|
||||
| ((res & 0x44444444) >> 1)
|
||||
| ((res & 0x22222222) << 1)
|
||||
| ((res & 0x11111111) << 3);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/* context save area (CSA) related helpers */
|
||||
|
||||
static int cdc_increment(target_ulong *psw)
|
||||
|
@ -2447,7 +2499,12 @@ void helper_call(CPUTriCoreState *env, uint32_t next_pc)
|
|||
}
|
||||
/* PSW.CDE = 1;*/
|
||||
psw |= MASK_PSW_CDE;
|
||||
psw_write(env, psw);
|
||||
/*
|
||||
* we need to save PSW.CDE and not PSW.CDC into the CSAs. psw already
|
||||
* contains the CDC from cdc_increment(), so we cannot call psw_write()
|
||||
* here.
|
||||
*/
|
||||
env->PSW |= MASK_PSW_CDE;
|
||||
|
||||
/* tmp_FCX = FCX; */
|
||||
tmp_FCX = env->FCX;
|
||||
|
@ -2527,12 +2584,12 @@ void helper_ret(CPUTriCoreState *env)
|
|||
/* PCXI = new_PCXI; */
|
||||
env->PCXI = new_PCXI;
|
||||
|
||||
if (tricore_feature(env, TRICORE_FEATURE_13)) {
|
||||
/* PSW = new_PSW */
|
||||
psw_write(env, new_PSW);
|
||||
} else {
|
||||
if (tricore_feature(env, TRICORE_FEATURE_131)) {
|
||||
/* PSW = {new_PSW[31:26], PSW[25:24], new_PSW[23:0]}; */
|
||||
psw_write(env, (new_PSW & ~(0x3000000)) + (psw & (0x3000000)));
|
||||
} else { /* TRICORE_FEATURE_13 only */
|
||||
/* PSW = new_PSW */
|
||||
psw_write(env, new_PSW);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -37,6 +37,9 @@
|
|||
#include "exec/helper-info.c.inc"
|
||||
#undef HELPER_H
|
||||
|
||||
#define DISAS_EXIT DISAS_TARGET_0
|
||||
#define DISAS_EXIT_UPDATE DISAS_TARGET_1
|
||||
#define DISAS_JUMP DISAS_TARGET_2
|
||||
|
||||
/*
|
||||
* TCG registers
|
||||
|
@ -73,9 +76,9 @@ typedef struct DisasContext {
|
|||
uint32_t opcode;
|
||||
/* Routine used to access memory */
|
||||
int mem_idx;
|
||||
uint32_t hflags, saved_hflags;
|
||||
int priv;
|
||||
uint64_t features;
|
||||
uint32_t icr_ie_mask;
|
||||
uint32_t icr_ie_mask, icr_ie_offset;
|
||||
} DisasContext;
|
||||
|
||||
static int has_feature(DisasContext *ctx, int feature)
|
||||
|
@ -309,6 +312,7 @@ static void gen_cmpswap(DisasContext *ctx, int reg, TCGv ea)
|
|||
{
|
||||
TCGv temp = tcg_temp_new();
|
||||
TCGv temp2 = tcg_temp_new();
|
||||
CHECK_REG_PAIR(reg);
|
||||
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);
|
||||
|
@ -321,7 +325,7 @@ 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();
|
||||
|
||||
CHECK_REG_PAIR(reg);
|
||||
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]);
|
||||
|
@ -330,7 +334,6 @@ static void gen_swapmsk(DisasContext *ctx, int reg, TCGv ea)
|
|||
tcg_gen_mov_tl(cpu_gpr_d[reg], temp);
|
||||
}
|
||||
|
||||
|
||||
/* 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.
|
||||
|
@ -374,17 +377,18 @@ static inline void gen_mfcr(DisasContext *ctx, TCGv ret, int32_t offset)
|
|||
static inline void gen_mtcr(DisasContext *ctx, TCGv r1,
|
||||
int32_t offset)
|
||||
{
|
||||
if ((ctx->hflags & TRICORE_HFLAG_KUU) == TRICORE_HFLAG_SM) {
|
||||
if (ctx->priv == TRICORE_PRIV_SM) {
|
||||
/* since we're caching PSW make this a special case */
|
||||
if (offset == 0xfe04) {
|
||||
gen_helper_psw_write(cpu_env, r1);
|
||||
ctx->base.is_jmp = DISAS_EXIT_UPDATE;
|
||||
} else {
|
||||
switch (offset) {
|
||||
#include "csfr.h.inc"
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* generate privilege trap */
|
||||
generate_trap(ctx, TRAPC_PROT, TIN1_PRIV);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2835,6 +2839,7 @@ static void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
|
|||
gen_save_pc(dest);
|
||||
tcg_gen_lookup_and_goto_ptr();
|
||||
}
|
||||
ctx->base.is_jmp = DISAS_NORETURN;
|
||||
}
|
||||
|
||||
static void generate_trap(DisasContext *ctx, int class, int tin)
|
||||
|
@ -2895,8 +2900,7 @@ static void gen_fret(DisasContext *ctx)
|
|||
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(NULL, 0);
|
||||
ctx->base.is_jmp = DISAS_NORETURN;
|
||||
ctx->base.is_jmp = DISAS_EXIT;
|
||||
}
|
||||
|
||||
static void gen_compute_branch(DisasContext *ctx, uint32_t opc, int r1,
|
||||
|
@ -2995,12 +2999,12 @@ static void gen_compute_branch(DisasContext *ctx, uint32_t opc, int r1,
|
|||
/* SR-format jumps */
|
||||
case OPC1_16_SR_JI:
|
||||
tcg_gen_andi_tl(cpu_PC, cpu_gpr_a[r1], 0xfffffffe);
|
||||
tcg_gen_exit_tb(NULL, 0);
|
||||
ctx->base.is_jmp = DISAS_EXIT;
|
||||
break;
|
||||
case OPC2_32_SYS_RET:
|
||||
case OPC2_16_SR_RET:
|
||||
gen_helper_ret(cpu_env);
|
||||
tcg_gen_exit_tb(NULL, 0);
|
||||
ctx->base.is_jmp = DISAS_EXIT;
|
||||
break;
|
||||
/* B-format */
|
||||
case OPC1_32_B_CALLA:
|
||||
|
@ -3152,7 +3156,6 @@ static void gen_compute_branch(DisasContext *ctx, uint32_t opc, int r1,
|
|||
default:
|
||||
generate_trap(ctx, TRAPC_INSN_ERR, TIN2_IOPC);
|
||||
}
|
||||
ctx->base.is_jmp = DISAS_NORETURN;
|
||||
}
|
||||
|
||||
|
||||
|
@ -3219,6 +3222,7 @@ static void decode_src_opc(DisasContext *ctx, int op1)
|
|||
break;
|
||||
case OPC1_16_SRC_MOV_E:
|
||||
if (has_feature(ctx, TRICORE_FEATURE_16)) {
|
||||
CHECK_REG_PAIR(r1);
|
||||
tcg_gen_movi_tl(cpu_gpr_d[r1], const4);
|
||||
tcg_gen_sari_tl(cpu_gpr_d[r1+1], cpu_gpr_d[r1], 31);
|
||||
} else {
|
||||
|
@ -3371,7 +3375,11 @@ static void decode_sc_opc(DisasContext *ctx, int op1)
|
|||
tcg_gen_andi_tl(cpu_gpr_d[15], cpu_gpr_d[15], const16);
|
||||
break;
|
||||
case OPC1_16_SC_BISR:
|
||||
gen_helper_1arg(bisr, const16 & 0xff);
|
||||
if (ctx->priv == TRICORE_PRIV_SM) {
|
||||
gen_helper_1arg(bisr, const16 & 0xff);
|
||||
} else {
|
||||
generate_trap(ctx, TRAPC_PROT, TIN1_PRIV);
|
||||
}
|
||||
break;
|
||||
case OPC1_16_SC_LD_A:
|
||||
gen_offset_ld(ctx, cpu_gpr_a[15], cpu_gpr_a[10], const16 * 4, MO_LESL);
|
||||
|
@ -3493,8 +3501,7 @@ static void decode_sr_system(DisasContext *ctx)
|
|||
break;
|
||||
case OPC2_16_SR_RFE:
|
||||
gen_helper_rfe(cpu_env);
|
||||
tcg_gen_exit_tb(NULL, 0);
|
||||
ctx->base.is_jmp = DISAS_NORETURN;
|
||||
ctx->base.is_jmp = DISAS_EXIT;
|
||||
break;
|
||||
case OPC2_16_SR_DEBUG:
|
||||
/* raise EXCP_DEBUG */
|
||||
|
@ -5011,6 +5018,14 @@ static void decode_rc_logical_shift(DisasContext *ctx)
|
|||
case OPC2_32_RC_XOR:
|
||||
tcg_gen_xori_tl(cpu_gpr_d[r2], cpu_gpr_d[r1], const9);
|
||||
break;
|
||||
case OPC2_32_RC_SHUFFLE:
|
||||
if (has_feature(ctx, TRICORE_FEATURE_162)) {
|
||||
TCGv temp = tcg_constant_i32(const9);
|
||||
gen_helper_shuffle(cpu_gpr_d[r2], cpu_gpr_d[r1], temp);
|
||||
} else {
|
||||
generate_trap(ctx, TRAPC_INSN_ERR, TIN2_IOPC);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
generate_trap(ctx, TRAPC_INSN_ERR, TIN2_IOPC);
|
||||
}
|
||||
|
@ -5225,10 +5240,14 @@ static void decode_rc_serviceroutine(DisasContext *ctx)
|
|||
|
||||
switch (op2) {
|
||||
case OPC2_32_RC_BISR:
|
||||
gen_helper_1arg(bisr, const9);
|
||||
if (ctx->priv == TRICORE_PRIV_SM) {
|
||||
gen_helper_1arg(bisr, const9);
|
||||
} else {
|
||||
generate_trap(ctx, TRAPC_PROT, TIN1_PRIV);
|
||||
}
|
||||
break;
|
||||
case OPC2_32_RC_SYSCALL:
|
||||
/* TODO: Add exception generation */
|
||||
generate_trap(ctx, TRAPC_SYSCALL, const9 & 0xff);
|
||||
break;
|
||||
default:
|
||||
generate_trap(ctx, TRAPC_INSN_ERR, TIN2_IOPC);
|
||||
|
@ -5331,6 +5350,7 @@ static void decode_rcrw_insert(DisasContext *ctx)
|
|||
|
||||
switch (op2) {
|
||||
case OPC2_32_RCRW_IMASK:
|
||||
CHECK_REG_PAIR(r4);
|
||||
tcg_gen_andi_tl(temp, cpu_gpr_d[r3], 0x1f);
|
||||
tcg_gen_movi_tl(temp2, (1 << width) - 1);
|
||||
tcg_gen_shl_tl(cpu_gpr_d[r4 + 1], temp2, temp);
|
||||
|
@ -6053,8 +6073,8 @@ static void decode_rr_idirect(DisasContext *ctx)
|
|||
tcg_gen_andi_tl(cpu_PC, cpu_gpr_a[r1], ~0x1);
|
||||
break;
|
||||
case OPC2_32_RR_JLI:
|
||||
tcg_gen_movi_tl(cpu_gpr_a[11], ctx->pc_succ_insn);
|
||||
tcg_gen_andi_tl(cpu_PC, cpu_gpr_a[r1], ~0x1);
|
||||
tcg_gen_movi_tl(cpu_gpr_a[11], ctx->pc_succ_insn);
|
||||
break;
|
||||
case OPC2_32_RR_CALLI:
|
||||
gen_helper_1arg(call, ctx->pc_succ_insn);
|
||||
|
@ -6066,9 +6086,9 @@ static void decode_rr_idirect(DisasContext *ctx)
|
|||
break;
|
||||
default:
|
||||
generate_trap(ctx, TRAPC_INSN_ERR, TIN2_IOPC);
|
||||
return;
|
||||
}
|
||||
tcg_gen_exit_tb(NULL, 0);
|
||||
ctx->base.is_jmp = DISAS_NORETURN;
|
||||
ctx->base.is_jmp = DISAS_JUMP;
|
||||
}
|
||||
|
||||
static void decode_rr_divide(DisasContext *ctx)
|
||||
|
@ -6171,6 +6191,7 @@ static void decode_rr_divide(DisasContext *ctx)
|
|||
tcg_gen_sari_tl(cpu_gpr_d[r3+1], cpu_gpr_d[r1], 31);
|
||||
break;
|
||||
case OPC2_32_RR_DVINIT_U:
|
||||
CHECK_REG_PAIR(r3);
|
||||
/* overflow = (D[b] == 0) */
|
||||
tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_PSW_V, cpu_gpr_d[r2], 0);
|
||||
tcg_gen_shli_tl(cpu_PSW_V, cpu_PSW_V, 31);
|
||||
|
@ -6190,15 +6211,38 @@ static void decode_rr_divide(DisasContext *ctx)
|
|||
CHECK_REG_PAIR(r3);
|
||||
gen_unpack(cpu_gpr_d[r3], cpu_gpr_d[r3+1], cpu_gpr_d[r1]);
|
||||
break;
|
||||
case OPC2_32_RR_CRC32:
|
||||
case OPC2_32_RR_CRC32_B:
|
||||
if (has_feature(ctx, TRICORE_FEATURE_162)) {
|
||||
gen_helper_crc32b(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
|
||||
} else {
|
||||
generate_trap(ctx, TRAPC_INSN_ERR, TIN2_IOPC);
|
||||
}
|
||||
break;
|
||||
case OPC2_32_RR_CRC32: /* CRC32B.W in 1.6.2 */
|
||||
if (has_feature(ctx, TRICORE_FEATURE_161)) {
|
||||
gen_helper_crc32(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
|
||||
gen_helper_crc32_be(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
|
||||
} else {
|
||||
generate_trap(ctx, TRAPC_INSN_ERR, TIN2_IOPC);
|
||||
}
|
||||
break;
|
||||
case OPC2_32_RR_CRC32L_W:
|
||||
if (has_feature(ctx, TRICORE_FEATURE_162)) {
|
||||
gen_helper_crc32_le(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
|
||||
} else {
|
||||
generate_trap(ctx, TRAPC_INSN_ERR, TIN2_IOPC);
|
||||
}
|
||||
break;
|
||||
|
||||
case OPC2_32_RR_POPCNT_W:
|
||||
if (has_feature(ctx, TRICORE_FEATURE_162)) {
|
||||
tcg_gen_ctpop_tl(cpu_gpr_d[r3], cpu_gpr_d[r1]);
|
||||
} else {
|
||||
generate_trap(ctx, TRAPC_INSN_ERR, TIN2_IOPC);
|
||||
}
|
||||
break;
|
||||
case OPC2_32_RR_DIV:
|
||||
if (has_feature(ctx, TRICORE_FEATURE_16)) {
|
||||
CHECK_REG_PAIR(r3);
|
||||
GEN_HELPER_RR(divide, cpu_gpr_d[r3], cpu_gpr_d[r3+1], cpu_gpr_d[r1],
|
||||
cpu_gpr_d[r2]);
|
||||
} else {
|
||||
|
@ -6207,6 +6251,7 @@ static void decode_rr_divide(DisasContext *ctx)
|
|||
break;
|
||||
case OPC2_32_RR_DIV_U:
|
||||
if (has_feature(ctx, TRICORE_FEATURE_16)) {
|
||||
CHECK_REG_PAIR(r3);
|
||||
GEN_HELPER_RR(divide_u, cpu_gpr_d[r3], cpu_gpr_d[r3+1],
|
||||
cpu_gpr_d[r1], cpu_gpr_d[r2]);
|
||||
} else {
|
||||
|
@ -6733,6 +6778,8 @@ static void decode_rrr2_msub(DisasContext *ctx)
|
|||
cpu_gpr_d[r3], cpu_gpr_d[r3+1], cpu_gpr_d[r2]);
|
||||
break;
|
||||
case OPC2_32_RRR2_MSUB_U_64:
|
||||
CHECK_REG_PAIR(r4);
|
||||
CHECK_REG_PAIR(r3);
|
||||
gen_msubu64_d(cpu_gpr_d[r4], cpu_gpr_d[r4+1], cpu_gpr_d[r1],
|
||||
cpu_gpr_d[r3], cpu_gpr_d[r3+1], cpu_gpr_d[r2]);
|
||||
break;
|
||||
|
@ -7816,7 +7863,7 @@ static void decode_rrrw_extract_insert(DisasContext *ctx)
|
|||
break;
|
||||
case OPC2_32_RRRW_IMASK:
|
||||
temp2 = tcg_temp_new();
|
||||
|
||||
CHECK_REG_PAIR(r4);
|
||||
tcg_gen_andi_tl(temp, cpu_gpr_d[r3], 0x1f);
|
||||
tcg_gen_movi_tl(temp2, (1 << width) - 1);
|
||||
tcg_gen_shl_tl(temp2, temp2, temp);
|
||||
|
@ -7851,12 +7898,33 @@ static void decode_sys_interrupts(DisasContext *ctx)
|
|||
/* raise EXCP_DEBUG */
|
||||
break;
|
||||
case OPC2_32_SYS_DISABLE:
|
||||
tcg_gen_andi_tl(cpu_ICR, cpu_ICR, ~ctx->icr_ie_mask);
|
||||
if (ctx->priv == TRICORE_PRIV_SM || ctx->priv == TRICORE_PRIV_UM1) {
|
||||
tcg_gen_andi_tl(cpu_ICR, cpu_ICR, ~ctx->icr_ie_mask);
|
||||
} else {
|
||||
generate_trap(ctx, TRAPC_PROT, TIN1_PRIV);
|
||||
}
|
||||
break;
|
||||
case OPC2_32_SYS_DISABLE_D:
|
||||
if (has_feature(ctx, TRICORE_FEATURE_16)) {
|
||||
if (ctx->priv == TRICORE_PRIV_SM || ctx->priv == TRICORE_PRIV_UM1) {
|
||||
tcg_gen_extract_tl(cpu_gpr_d[r1], cpu_ICR,
|
||||
ctx->icr_ie_offset, 1);
|
||||
tcg_gen_andi_tl(cpu_ICR, cpu_ICR, ~ctx->icr_ie_mask);
|
||||
} else {
|
||||
generate_trap(ctx, TRAPC_PROT, TIN1_PRIV);
|
||||
}
|
||||
} else {
|
||||
generate_trap(ctx, TRAPC_INSN_ERR, TIN2_IOPC);
|
||||
}
|
||||
case OPC2_32_SYS_DSYNC:
|
||||
break;
|
||||
case OPC2_32_SYS_ENABLE:
|
||||
tcg_gen_ori_tl(cpu_ICR, cpu_ICR, ctx->icr_ie_mask);
|
||||
if (ctx->priv == TRICORE_PRIV_SM || ctx->priv == TRICORE_PRIV_UM1) {
|
||||
tcg_gen_ori_tl(cpu_ICR, cpu_ICR, ctx->icr_ie_mask);
|
||||
ctx->base.is_jmp = DISAS_EXIT_UPDATE;
|
||||
} else {
|
||||
generate_trap(ctx, TRAPC_PROT, TIN1_PRIV);
|
||||
}
|
||||
break;
|
||||
case OPC2_32_SYS_ISYNC:
|
||||
break;
|
||||
|
@ -7870,11 +7938,10 @@ static void decode_sys_interrupts(DisasContext *ctx)
|
|||
break;
|
||||
case OPC2_32_SYS_RFE:
|
||||
gen_helper_rfe(cpu_env);
|
||||
tcg_gen_exit_tb(NULL, 0);
|
||||
ctx->base.is_jmp = DISAS_NORETURN;
|
||||
ctx->base.is_jmp = DISAS_EXIT;
|
||||
break;
|
||||
case OPC2_32_SYS_RFM:
|
||||
if ((ctx->hflags & TRICORE_HFLAG_KUU) == TRICORE_HFLAG_SM) {
|
||||
if (ctx->priv == TRICORE_PRIV_SM) {
|
||||
tmp = tcg_temp_new();
|
||||
l1 = gen_new_label();
|
||||
|
||||
|
@ -7883,10 +7950,9 @@ static void decode_sys_interrupts(DisasContext *ctx)
|
|||
tcg_gen_brcondi_tl(TCG_COND_NE, tmp, 1, l1);
|
||||
gen_helper_rfm(cpu_env);
|
||||
gen_set_label(l1);
|
||||
tcg_gen_exit_tb(NULL, 0);
|
||||
ctx->base.is_jmp = DISAS_NORETURN;
|
||||
ctx->base.is_jmp = DISAS_EXIT;
|
||||
} else {
|
||||
/* generate privilege trap */
|
||||
generate_trap(ctx, TRAPC_PROT, TIN1_PRIV);
|
||||
}
|
||||
break;
|
||||
case OPC2_32_SYS_RSLCX:
|
||||
|
@ -7897,10 +7963,13 @@ static void decode_sys_interrupts(DisasContext *ctx)
|
|||
break;
|
||||
case OPC2_32_SYS_RESTORE:
|
||||
if (has_feature(ctx, 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 */
|
||||
if (ctx->priv == TRICORE_PRIV_SM || ctx->priv == TRICORE_PRIV_UM1) {
|
||||
tcg_gen_deposit_tl(cpu_ICR, cpu_ICR, cpu_gpr_d[r1],
|
||||
ctx->icr_ie_offset, 1);
|
||||
ctx->base.is_jmp = DISAS_EXIT_UPDATE;
|
||||
} else {
|
||||
generate_trap(ctx, TRAPC_PROT, TIN1_PRIV);
|
||||
}
|
||||
} else {
|
||||
generate_trap(ctx, TRAPC_INSN_ERR, TIN2_IOPC);
|
||||
}
|
||||
|
@ -7924,7 +7993,7 @@ static void decode_sys_interrupts(DisasContext *ctx)
|
|||
|
||||
static void decode_32Bit_opc(DisasContext *ctx)
|
||||
{
|
||||
int op1;
|
||||
int op1, op2;
|
||||
int32_t r1, r2, r3;
|
||||
int32_t address, const16;
|
||||
int8_t b, const4;
|
||||
|
@ -7975,9 +8044,19 @@ static void decode_32Bit_opc(DisasContext *ctx)
|
|||
tcg_gen_qemu_ld_tl(cpu_gpr_d[r1], temp, ctx->mem_idx, MO_LEUW);
|
||||
tcg_gen_shli_tl(cpu_gpr_d[r1], cpu_gpr_d[r1], 16);
|
||||
break;
|
||||
case OPC1_32_ABS_LEA:
|
||||
case OPCM_32_ABS_LEA_LHA:
|
||||
address = MASK_OP_ABS_OFF18(ctx->opcode);
|
||||
r1 = MASK_OP_ABS_S1D(ctx->opcode);
|
||||
|
||||
if (has_feature(ctx, TRICORE_FEATURE_162)) {
|
||||
op2 = MASK_OP_ABS_OP2(ctx->opcode);
|
||||
if (op2 == OPC2_32_ABS_LHA) {
|
||||
tcg_gen_movi_tl(cpu_gpr_a[r1], address << 14);
|
||||
break;
|
||||
}
|
||||
/* otherwise translate regular LEA */
|
||||
}
|
||||
|
||||
tcg_gen_movi_tl(cpu_gpr_a[r1], EA_ABS_FORMAT(address));
|
||||
break;
|
||||
/* ABSB-format */
|
||||
|
@ -8258,12 +8337,17 @@ static void tricore_tr_init_disas_context(DisasContextBase *dcbase,
|
|||
DisasContext *ctx = container_of(dcbase, DisasContext, base);
|
||||
CPUTriCoreState *env = cs->env_ptr;
|
||||
ctx->mem_idx = cpu_mmu_index(env, false);
|
||||
ctx->hflags = (uint32_t)ctx->base.tb->flags;
|
||||
|
||||
uint32_t tb_flags = (uint32_t)ctx->base.tb->flags;
|
||||
ctx->priv = FIELD_EX32(tb_flags, TB_FLAGS, PRIV);
|
||||
|
||||
ctx->features = env->features;
|
||||
if (has_feature(ctx, TRICORE_FEATURE_161)) {
|
||||
ctx->icr_ie_mask = R_ICR_IE_161_MASK;
|
||||
ctx->icr_ie_offset = R_ICR_IE_161_SHIFT;
|
||||
} else {
|
||||
ctx->icr_ie_mask = R_ICR_IE_13_MASK;
|
||||
ctx->icr_ie_offset = R_ICR_IE_13_SHIFT;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -8334,6 +8418,15 @@ static void tricore_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
|
|||
case DISAS_TOO_MANY:
|
||||
gen_goto_tb(ctx, 0, ctx->base.pc_next);
|
||||
break;
|
||||
case DISAS_EXIT_UPDATE:
|
||||
gen_save_pc(ctx->base.pc_next);
|
||||
/* fall through */
|
||||
case DISAS_EXIT:
|
||||
tcg_gen_exit_tb(NULL, 0);
|
||||
break;
|
||||
case DISAS_JUMP:
|
||||
tcg_gen_lookup_and_goto_ptr();
|
||||
break;
|
||||
case DISAS_NORETURN:
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -430,7 +430,7 @@ enum {
|
|||
OPCM_32_ABS_STOREB_H = 0x25,
|
||||
OPC1_32_ABS_STOREQ = 0x65,
|
||||
OPC1_32_ABS_LD_Q = 0x45,
|
||||
OPC1_32_ABS_LEA = 0xc5,
|
||||
OPCM_32_ABS_LEA_LHA = 0xc5,
|
||||
/* ABSB Format */
|
||||
OPC1_32_ABSB_ST_T = 0xd5,
|
||||
/* B Format */
|
||||
|
@ -592,6 +592,13 @@ enum {
|
|||
OPC2_32_ABS_ST_B = 0x00,
|
||||
OPC2_32_ABS_ST_H = 0x02,
|
||||
};
|
||||
|
||||
/* OPCM_32_ABS_LEA_LHA */
|
||||
enum {
|
||||
OPC2_32_ABS_LEA = 0x00,
|
||||
OPC2_32_ABS_LHA = 0x01,
|
||||
};
|
||||
|
||||
/*
|
||||
* Bit Format
|
||||
*/
|
||||
|
@ -878,6 +885,7 @@ enum {
|
|||
OPC2_32_RC_SHAS = 0x02,
|
||||
OPC2_32_RC_XNOR = 0x0d,
|
||||
OPC2_32_RC_XOR = 0x0c,
|
||||
OPC2_32_RC_SHUFFLE = 0x07, /* v1.6.2 only */
|
||||
};
|
||||
/* OPCM_32_RC_ACCUMULATOR */
|
||||
enum {
|
||||
|
@ -1132,7 +1140,10 @@ enum {
|
|||
OPC2_32_RR_DVINIT_U = 0x0a,
|
||||
OPC2_32_RR_PARITY = 0x02,
|
||||
OPC2_32_RR_UNPACK = 0x08,
|
||||
OPC2_32_RR_CRC32 = 0x03,
|
||||
OPC2_32_RR_CRC32 = 0x03, /* CRC32B.W in 1.6.2 */
|
||||
OPC2_32_RR_CRC32_B = 0x06, /* 1.6.2 only */
|
||||
OPC2_32_RR_CRC32L_W = 0x07, /* 1.6.2 only */
|
||||
OPC2_32_RR_POPCNT_W = 0x22, /* 1.6.2 only */
|
||||
OPC2_32_RR_DIV = 0x20,
|
||||
OPC2_32_RR_DIV_U = 0x21,
|
||||
OPC2_32_RR_MUL_F = 0x04,
|
||||
|
@ -1456,6 +1467,7 @@ enum {
|
|||
enum {
|
||||
OPC2_32_SYS_DEBUG = 0x04,
|
||||
OPC2_32_SYS_DISABLE = 0x0d,
|
||||
OPC2_32_SYS_DISABLE_D = 0x0f, /* 1.6 up */
|
||||
OPC2_32_SYS_DSYNC = 0x12,
|
||||
OPC2_32_SYS_ENABLE = 0x0c,
|
||||
OPC2_32_SYS_ISYNC = 0x13,
|
||||
|
|
Loading…
Reference in New Issue