target-tricore: Add instructions of RR opcode format, that have 0xf as the first opcode
Add instructions of RR opcode format, that have 0xf as the first opcode. Add helper functions: * clo/z/s: Counts leading ones/zeros/signs. * clo/z/s_h: Count leading ones/zeros/signs in two haflwords. * sh/_h: Shifts one/two word/hwords. * sha/_h: Shifts one/two word/hwords arithmeticly. Signed-off-by: Bastian Koppelmann <kbastian@mail.uni-paderborn.de> Reviewed-by: Richard Henderson <rth@twiddle.net>
This commit is contained in:
parent
d5de7839d7
commit
0b79a78169
@ -64,6 +64,18 @@ DEF_HELPER_FLAGS_2(min_b, TCG_CALL_NO_RWG_SE, i32, i32, i32)
|
||||
DEF_HELPER_FLAGS_2(min_bu, TCG_CALL_NO_RWG_SE, i32, i32, i32)
|
||||
DEF_HELPER_FLAGS_2(min_h, TCG_CALL_NO_RWG_SE, i32, i32, i32)
|
||||
DEF_HELPER_FLAGS_2(min_hu, TCG_CALL_NO_RWG_SE, i32, i32, i32)
|
||||
/* count leading ... */
|
||||
DEF_HELPER_FLAGS_1(clo, TCG_CALL_NO_RWG_SE, i32, i32)
|
||||
DEF_HELPER_FLAGS_1(clo_h, TCG_CALL_NO_RWG_SE, i32, i32)
|
||||
DEF_HELPER_FLAGS_1(clz, TCG_CALL_NO_RWG_SE, i32, i32)
|
||||
DEF_HELPER_FLAGS_1(clz_h, TCG_CALL_NO_RWG_SE, i32, i32)
|
||||
DEF_HELPER_FLAGS_1(cls, TCG_CALL_NO_RWG_SE, i32, i32)
|
||||
DEF_HELPER_FLAGS_1(cls_h, TCG_CALL_NO_RWG_SE, i32, i32)
|
||||
/* sh */
|
||||
DEF_HELPER_FLAGS_2(sh, TCG_CALL_NO_RWG_SE, i32, i32, i32)
|
||||
DEF_HELPER_FLAGS_2(sh_h, TCG_CALL_NO_RWG_SE, i32, i32, i32)
|
||||
DEF_HELPER_3(sha, i32, env, i32, i32)
|
||||
DEF_HELPER_2(sha_h, i32, i32, i32)
|
||||
/* CSA */
|
||||
DEF_HELPER_2(call, void, env, i32)
|
||||
DEF_HELPER_1(ret, void, env)
|
||||
|
@ -873,6 +873,166 @@ EXTREMA_H_B(min, <)
|
||||
|
||||
#undef EXTREMA_H_B
|
||||
|
||||
uint32_t helper_clo(target_ulong r1)
|
||||
{
|
||||
return clo32(r1);
|
||||
}
|
||||
|
||||
uint32_t helper_clo_h(target_ulong r1)
|
||||
{
|
||||
uint32_t ret_hw0 = extract32(r1, 0, 16);
|
||||
uint32_t ret_hw1 = extract32(r1, 16, 16);
|
||||
|
||||
ret_hw0 = clo32(ret_hw0 << 16);
|
||||
ret_hw1 = clo32(ret_hw1 << 16);
|
||||
|
||||
if (ret_hw0 > 16) {
|
||||
ret_hw0 = 16;
|
||||
}
|
||||
if (ret_hw1 > 16) {
|
||||
ret_hw1 = 16;
|
||||
}
|
||||
|
||||
return ret_hw0 | (ret_hw1 << 16);
|
||||
}
|
||||
|
||||
uint32_t helper_clz(target_ulong r1)
|
||||
{
|
||||
return clz32(r1);
|
||||
}
|
||||
|
||||
uint32_t helper_clz_h(target_ulong r1)
|
||||
{
|
||||
uint32_t ret_hw0 = extract32(r1, 0, 16);
|
||||
uint32_t ret_hw1 = extract32(r1, 16, 16);
|
||||
|
||||
ret_hw0 = clz32(ret_hw0 << 16);
|
||||
ret_hw1 = clz32(ret_hw1 << 16);
|
||||
|
||||
if (ret_hw0 > 16) {
|
||||
ret_hw0 = 16;
|
||||
}
|
||||
if (ret_hw1 > 16) {
|
||||
ret_hw1 = 16;
|
||||
}
|
||||
|
||||
return ret_hw0 | (ret_hw1 << 16);
|
||||
}
|
||||
|
||||
uint32_t helper_cls(target_ulong r1)
|
||||
{
|
||||
return clrsb32(r1);
|
||||
}
|
||||
|
||||
uint32_t helper_cls_h(target_ulong r1)
|
||||
{
|
||||
uint32_t ret_hw0 = extract32(r1, 0, 16);
|
||||
uint32_t ret_hw1 = extract32(r1, 16, 16);
|
||||
|
||||
ret_hw0 = clrsb32(ret_hw0 << 16);
|
||||
ret_hw1 = clrsb32(ret_hw1 << 16);
|
||||
|
||||
if (ret_hw0 > 15) {
|
||||
ret_hw0 = 15;
|
||||
}
|
||||
if (ret_hw1 > 15) {
|
||||
ret_hw1 = 15;
|
||||
}
|
||||
|
||||
return ret_hw0 | (ret_hw1 << 16);
|
||||
}
|
||||
|
||||
uint32_t helper_sh(target_ulong r1, target_ulong r2)
|
||||
{
|
||||
int32_t shift_count = sextract32(r2, 0, 6);
|
||||
|
||||
if (shift_count == -32) {
|
||||
return 0;
|
||||
} else if (shift_count < 0) {
|
||||
return r1 >> -shift_count;
|
||||
} else {
|
||||
return r1 << shift_count;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t helper_sh_h(target_ulong r1, target_ulong r2)
|
||||
{
|
||||
int32_t ret_hw0, ret_hw1;
|
||||
int32_t shift_count;
|
||||
|
||||
shift_count = sextract32(r2, 0, 5);
|
||||
|
||||
if (shift_count == -16) {
|
||||
return 0;
|
||||
} else if (shift_count < 0) {
|
||||
ret_hw0 = extract32(r1, 0, 16) >> -shift_count;
|
||||
ret_hw1 = extract32(r1, 16, 16) >> -shift_count;
|
||||
return (ret_hw0 & 0xffff) | (ret_hw1 << 16);
|
||||
} else {
|
||||
ret_hw0 = extract32(r1, 0, 16) << shift_count;
|
||||
ret_hw1 = extract32(r1, 16, 16) << shift_count;
|
||||
return (ret_hw0 & 0xffff) | (ret_hw1 << 16);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t helper_sha(CPUTriCoreState *env, target_ulong r1, target_ulong r2)
|
||||
{
|
||||
int32_t shift_count;
|
||||
int64_t result, t1;
|
||||
uint32_t ret;
|
||||
|
||||
shift_count = sextract32(r2, 0, 6);
|
||||
t1 = sextract32(r1, 0, 32);
|
||||
|
||||
if (shift_count == 0) {
|
||||
env->PSW_USB_C = env->PSW_USB_V = 0;
|
||||
ret = r1;
|
||||
} else if (shift_count == -32) {
|
||||
env->PSW_USB_C = r1;
|
||||
env->PSW_USB_V = 0;
|
||||
ret = t1 >> 31;
|
||||
} else if (shift_count > 0) {
|
||||
result = t1 << shift_count;
|
||||
/* calc carry */
|
||||
env->PSW_USB_C = ((result & 0xffffffff00000000) != 0);
|
||||
/* calc v */
|
||||
env->PSW_USB_V = (((result > 0x7fffffffLL) ||
|
||||
(result < -0x80000000LL)) << 31);
|
||||
/* calc sv */
|
||||
env->PSW_USB_SV |= env->PSW_USB_V;
|
||||
ret = (uint32_t)result;
|
||||
} else {
|
||||
env->PSW_USB_V = 0;
|
||||
env->PSW_USB_C = (r1 & ((1 << -shift_count) - 1));
|
||||
ret = t1 >> -shift_count;
|
||||
}
|
||||
|
||||
env->PSW_USB_AV = ret ^ ret * 2u;
|
||||
env->PSW_USB_SAV |= env->PSW_USB_AV;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint32_t helper_sha_h(target_ulong r1, target_ulong r2)
|
||||
{
|
||||
int32_t shift_count;
|
||||
int32_t ret_hw0, ret_hw1;
|
||||
|
||||
shift_count = sextract32(r2, 0, 5);
|
||||
|
||||
if (shift_count == 0) {
|
||||
return r1;
|
||||
} else if (shift_count < 0) {
|
||||
ret_hw0 = sextract32(r1, 0, 16) >> -shift_count;
|
||||
ret_hw1 = sextract32(r1, 16, 16) >> -shift_count;
|
||||
return (ret_hw0 & 0xffff) | (ret_hw1 << 16);
|
||||
} else {
|
||||
ret_hw0 = sextract32(r1, 0, 16) << shift_count;
|
||||
ret_hw1 = sextract32(r1, 16, 16) << shift_count;
|
||||
return (ret_hw0 & 0xffff) | (ret_hw1 << 16);
|
||||
}
|
||||
}
|
||||
|
||||
/* context save area (CSA) related helpers */
|
||||
|
||||
static int cdc_increment(target_ulong *psw)
|
||||
|
@ -4196,6 +4196,81 @@ static void decode_rr_accumulator(CPUTriCoreState *env, DisasContext *ctx)
|
||||
}
|
||||
}
|
||||
|
||||
static void decode_rr_logical_shift(CPUTriCoreState *env, DisasContext *ctx)
|
||||
{
|
||||
uint32_t op2;
|
||||
int r3, r2, r1;
|
||||
TCGv temp;
|
||||
|
||||
r3 = MASK_OP_RR_D(ctx->opcode);
|
||||
r2 = MASK_OP_RR_S2(ctx->opcode);
|
||||
r1 = MASK_OP_RR_S1(ctx->opcode);
|
||||
|
||||
temp = tcg_temp_new();
|
||||
op2 = MASK_OP_RR_OP2(ctx->opcode);
|
||||
|
||||
switch (op2) {
|
||||
case OPC2_32_RR_AND:
|
||||
tcg_gen_and_tl(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
|
||||
break;
|
||||
case OPC2_32_RR_ANDN:
|
||||
tcg_gen_andc_tl(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
|
||||
break;
|
||||
case OPC2_32_RR_CLO:
|
||||
gen_helper_clo(cpu_gpr_d[r3], cpu_gpr_d[r1]);
|
||||
break;
|
||||
case OPC2_32_RR_CLO_H:
|
||||
gen_helper_clo_h(cpu_gpr_d[r3], cpu_gpr_d[r1]);
|
||||
break;
|
||||
case OPC2_32_RR_CLS:
|
||||
gen_helper_cls(cpu_gpr_d[r3], cpu_gpr_d[r1]);
|
||||
break;
|
||||
case OPC2_32_RR_CLS_H:
|
||||
gen_helper_cls_h(cpu_gpr_d[r3], cpu_gpr_d[r1]);
|
||||
break;
|
||||
case OPC2_32_RR_CLZ:
|
||||
gen_helper_clz(cpu_gpr_d[r3], cpu_gpr_d[r1]);
|
||||
break;
|
||||
case OPC2_32_RR_CLZ_H:
|
||||
gen_helper_clz_h(cpu_gpr_d[r3], cpu_gpr_d[r1]);
|
||||
break;
|
||||
case OPC2_32_RR_NAND:
|
||||
tcg_gen_nand_tl(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
|
||||
break;
|
||||
case OPC2_32_RR_NOR:
|
||||
tcg_gen_nor_tl(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
|
||||
break;
|
||||
case OPC2_32_RR_OR:
|
||||
tcg_gen_or_tl(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
|
||||
break;
|
||||
case OPC2_32_RR_ORN:
|
||||
tcg_gen_orc_tl(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
|
||||
break;
|
||||
case OPC2_32_RR_SH:
|
||||
gen_helper_sh(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
|
||||
break;
|
||||
case OPC2_32_RR_SH_H:
|
||||
gen_helper_sh_h(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
|
||||
break;
|
||||
case OPC2_32_RR_SHA:
|
||||
gen_helper_sha(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r1], cpu_gpr_d[r2]);
|
||||
break;
|
||||
case OPC2_32_RR_SHA_H:
|
||||
gen_helper_sha_h(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
|
||||
break;
|
||||
case OPC2_32_RR_SHAS:
|
||||
gen_shas(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
|
||||
break;
|
||||
case OPC2_32_RR_XNOR:
|
||||
tcg_gen_eqv_tl(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
|
||||
break;
|
||||
case OPC2_32_RR_XOR:
|
||||
tcg_gen_xor_tl(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
|
||||
break;
|
||||
}
|
||||
tcg_temp_free(temp);
|
||||
}
|
||||
|
||||
static void decode_32Bit_opc(CPUTriCoreState *env, DisasContext *ctx)
|
||||
{
|
||||
int op1;
|
||||
@ -4431,6 +4506,9 @@ static void decode_32Bit_opc(CPUTriCoreState *env, DisasContext *ctx)
|
||||
case OPCM_32_RR_ACCUMULATOR:
|
||||
decode_rr_accumulator(env, ctx);
|
||||
break;
|
||||
case OPCM_32_RR_LOGICAL_SHIFT:
|
||||
decode_rr_logical_shift(env, ctx);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user