target-tricore: Add instructions of SRR opcode format

Add instructions of SRR opcode format.
Add helper for add/sub_ssov.

Signed-off-by: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
Message-id: 1409572800-4116-8-git-send-email-kbastian@mail.uni-paderborn.de
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
master
Bastian Koppelmann 2014-09-01 12:59:52 +01:00 committed by Peter Maydell
parent 0707ec1bea
commit 2692802a37
3 changed files with 211 additions and 0 deletions

View File

@ -14,3 +14,7 @@
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
/* Arithmetic */
DEF_HELPER_3(add_ssov, i32, env, i32, i32)
DEF_HELPER_3(sub_ssov, i32, env, i32, i32)

View File

@ -20,6 +20,49 @@
#include "exec/helper-proto.h"
#include "exec/cpu_ldst.h"
#define SSOV(env, ret, arg, len) do { \
int64_t max_pos = INT##len ##_MAX; \
int64_t max_neg = INT##len ##_MIN; \
if (arg > max_pos) { \
env->PSW_USB_V = (1 << 31); \
env->PSW_USB_SV = (1 << 31); \
ret = (target_ulong)max_pos; \
} else { \
if (arg < max_neg) { \
env->PSW_USB_V = (1 << 31); \
env->PSW_USB_SV = (1 << 31); \
ret = (target_ulong)max_neg; \
} else { \
env->PSW_USB_V = 0; \
ret = (target_ulong)arg; \
} \
} \
env->PSW_USB_AV = arg ^ arg * 2u; \
env->PSW_USB_SAV |= env->PSW_USB_AV; \
} while (0)
target_ulong helper_add_ssov(CPUTriCoreState *env, target_ulong r1,
target_ulong r2)
{
target_ulong ret;
int64_t t1 = sextract64(r1, 0, 32);
int64_t t2 = sextract64(r2, 0, 32);
int64_t result = t1 + t2;
SSOV(env, ret, result, 32);
return ret;
}
target_ulong helper_sub_ssov(CPUTriCoreState *env, target_ulong r1,
target_ulong r2)
{
target_ulong ret;
int64_t t1 = sextract64(r1, 0, 32);
int64_t t2 = sextract64(r2, 0, 32);
int64_t result = t1 - t2;
SSOV(env, ret, result, 32);
return ret;
}
static inline void QEMU_NORETURN do_raise_exception_err(CPUTriCoreState *env,
uint32_t exception,
int error_code,

View File

@ -187,6 +187,53 @@ static inline void gen_condi_add(TCGCond cond, TCGv r1, int32_t r2,
tcg_temp_free(temp);
}
static inline void gen_sub_d(TCGv ret, TCGv r1, TCGv r2)
{
TCGv temp = tcg_temp_new_i32();
TCGv result = tcg_temp_new_i32();
tcg_gen_sub_tl(result, r1, r2);
/* calc V bit */
tcg_gen_xor_tl(cpu_PSW_V, result, r1);
tcg_gen_xor_tl(temp, r1, r2);
tcg_gen_and_tl(cpu_PSW_V, cpu_PSW_V, temp);
/* calc SV bit */
tcg_gen_or_tl(cpu_PSW_SV, cpu_PSW_SV, cpu_PSW_V);
/* Calc AV bit */
tcg_gen_add_tl(cpu_PSW_AV, result, result);
tcg_gen_xor_tl(cpu_PSW_AV, result, cpu_PSW_AV);
/* calc SAV bit */
tcg_gen_or_tl(cpu_PSW_SAV, cpu_PSW_SAV, cpu_PSW_AV);
/* write back result */
tcg_gen_mov_tl(ret, result);
tcg_temp_free(temp);
tcg_temp_free(result);
}
static inline void gen_mul_i32s(TCGv ret, TCGv r1, TCGv r2)
{
TCGv high = tcg_temp_new();
TCGv low = tcg_temp_new();
tcg_gen_muls2_tl(low, high, r1, r2);
tcg_gen_mov_tl(ret, low);
/* calc V bit */
tcg_gen_sari_tl(low, low, 31);
tcg_gen_setcond_tl(TCG_COND_NE, cpu_PSW_V, high, low);
tcg_gen_shli_tl(cpu_PSW_V, cpu_PSW_V, 31);
/* calc SV bit */
tcg_gen_or_tl(cpu_PSW_SV, cpu_PSW_SV, cpu_PSW_V);
/* Calc AV bit */
tcg_gen_add_tl(cpu_PSW_AV, ret, ret);
tcg_gen_xor_tl(cpu_PSW_AV, ret, cpu_PSW_AV);
/* calc SAV bit */
tcg_gen_or_tl(cpu_PSW_SAV, cpu_PSW_SAV, cpu_PSW_AV);
tcg_temp_free(high);
tcg_temp_free(low);
}
static void gen_shi(TCGv ret, TCGv r1, int32_t shift_count)
{
if (shift_count == -32) {
@ -257,6 +304,16 @@ static void gen_shaci(TCGv ret, TCGv r1, int32_t shift_count)
tcg_temp_free(t_0);
}
static inline void gen_adds(TCGv ret, TCGv r1, TCGv r2)
{
gen_helper_add_ssov(ret, cpu_env, r1, r2);
}
static inline void gen_subs(TCGv ret, TCGv r1, TCGv r2)
{
gen_helper_sub_ssov(ret, cpu_env, r1, r2);
}
/*
* Functions for decoding instructions
*/
@ -331,6 +388,89 @@ static void decode_src_opc(DisasContext *ctx, int op1)
}
}
static void decode_srr_opc(DisasContext *ctx, int op1)
{
int r1, r2;
TCGv temp;
r1 = MASK_OP_SRR_S1D(ctx->opcode);
r2 = MASK_OP_SRR_S2(ctx->opcode);
switch (op1) {
case OPC1_16_SRR_ADD:
gen_add_d(cpu_gpr_d[r1], cpu_gpr_d[r1], cpu_gpr_d[r2]);
break;
case OPC1_16_SRR_ADD_A15:
gen_add_d(cpu_gpr_d[r1], cpu_gpr_d[15], cpu_gpr_d[r2]);
break;
case OPC1_16_SRR_ADD_15A:
gen_add_d(cpu_gpr_d[15], cpu_gpr_d[r1], cpu_gpr_d[r2]);
break;
case OPC1_16_SRR_ADD_A:
tcg_gen_add_tl(cpu_gpr_a[r1], cpu_gpr_a[r1], cpu_gpr_a[r2]);
break;
case OPC1_16_SRR_ADDS:
gen_adds(cpu_gpr_d[r1], cpu_gpr_d[r1], cpu_gpr_d[r2]);
break;
case OPC1_16_SRR_AND:
tcg_gen_and_tl(cpu_gpr_d[r1], cpu_gpr_d[r1], cpu_gpr_d[r2]);
break;
case OPC1_16_SRR_CMOV:
temp = tcg_const_tl(0);
tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr_d[r1], cpu_gpr_d[15], temp,
cpu_gpr_d[r2], cpu_gpr_d[r1]);
tcg_temp_free(temp);
break;
case OPC1_16_SRR_CMOVN:
temp = tcg_const_tl(0);
tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr_d[r1], cpu_gpr_d[15], temp,
cpu_gpr_d[r2], cpu_gpr_d[r1]);
tcg_temp_free(temp);
break;
case OPC1_16_SRR_EQ:
tcg_gen_setcond_tl(TCG_COND_EQ, cpu_gpr_d[15], cpu_gpr_d[r1],
cpu_gpr_d[r2]);
break;
case OPC1_16_SRR_LT:
tcg_gen_setcond_tl(TCG_COND_LT, cpu_gpr_d[15], cpu_gpr_d[r1],
cpu_gpr_d[r2]);
break;
case OPC1_16_SRR_MOV:
tcg_gen_mov_tl(cpu_gpr_d[r1], cpu_gpr_d[r2]);
break;
case OPC1_16_SRR_MOV_A:
tcg_gen_mov_tl(cpu_gpr_a[r1], cpu_gpr_d[r2]);
break;
case OPC1_16_SRR_MOV_AA:
tcg_gen_mov_tl(cpu_gpr_a[r1], cpu_gpr_a[r2]);
break;
case OPC1_16_SRR_MOV_D:
tcg_gen_mov_tl(cpu_gpr_d[r1], cpu_gpr_a[r2]);
break;
case OPC1_16_SRR_MUL:
gen_mul_i32s(cpu_gpr_d[r1], cpu_gpr_d[r1], cpu_gpr_d[r2]);
break;
case OPC1_16_SRR_OR:
tcg_gen_or_tl(cpu_gpr_d[r1], cpu_gpr_d[r1], cpu_gpr_d[r2]);
break;
case OPC1_16_SRR_SUB:
gen_sub_d(cpu_gpr_d[r1], cpu_gpr_d[r1], cpu_gpr_d[r2]);
break;
case OPC1_16_SRR_SUB_A15B:
gen_sub_d(cpu_gpr_d[r1], cpu_gpr_d[15], cpu_gpr_d[r2]);
break;
case OPC1_16_SRR_SUB_15AB:
gen_sub_d(cpu_gpr_d[15], cpu_gpr_d[r1], cpu_gpr_d[r2]);
break;
case OPC1_16_SRR_SUBS:
gen_subs(cpu_gpr_d[r1], cpu_gpr_d[r1], cpu_gpr_d[r2]);
break;
case OPC1_16_SRR_XOR:
tcg_gen_xor_tl(cpu_gpr_d[r1], cpu_gpr_d[r1], cpu_gpr_d[r2]);
break;
}
}
static void decode_16Bit_opc(CPUTriCoreState *env, DisasContext *ctx)
{
int op1;
@ -354,6 +494,30 @@ static void decode_16Bit_opc(CPUTriCoreState *env, DisasContext *ctx)
case OPC1_16_SRC_SHA:
decode_src_opc(ctx, op1);
break;
/* SRR-format */
case OPC1_16_SRR_ADD:
case OPC1_16_SRR_ADD_A15:
case OPC1_16_SRR_ADD_15A:
case OPC1_16_SRR_ADD_A:
case OPC1_16_SRR_ADDS:
case OPC1_16_SRR_AND:
case OPC1_16_SRR_CMOV:
case OPC1_16_SRR_CMOVN:
case OPC1_16_SRR_EQ:
case OPC1_16_SRR_LT:
case OPC1_16_SRR_MOV:
case OPC1_16_SRR_MOV_A:
case OPC1_16_SRR_MOV_AA:
case OPC1_16_SRR_MOV_D:
case OPC1_16_SRR_MUL:
case OPC1_16_SRR_OR:
case OPC1_16_SRR_SUB:
case OPC1_16_SRR_SUB_A15B:
case OPC1_16_SRR_SUB_15AB:
case OPC1_16_SRR_SUBS:
case OPC1_16_SRR_XOR:
decode_srr_opc(ctx, op1);
break;
}
}