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:
Bastian Koppelmann 2014-11-28 17:07:26 +00:00
parent d5de7839d7
commit 0b79a78169
3 changed files with 250 additions and 0 deletions

View File

@ -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)

View File

@ -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)

View File

@ -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;
}
}