target-tricore: Add instructions of SR opcode format
Add instructions of SR opcode format. Add micro-op generator functions for saturate. Add helper return from exception (rfe). Signed-off-by: Bastian Koppelmann <kbastian@mail.uni-paderborn.de> Message-id: 1409572800-4116-16-git-send-email-kbastian@mail.uni-paderborn.de Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
		
							parent
							
								
									5a7634a28c
								
							
						
					
					
						commit
						44ea34309e
					
				@ -22,3 +22,4 @@ DEF_HELPER_3(sub_ssov, i32, env, i32, i32)
 | 
			
		||||
DEF_HELPER_2(call, void, env, i32)
 | 
			
		||||
DEF_HELPER_1(ret, void, env)
 | 
			
		||||
DEF_HELPER_2(bisr, void, env, i32)
 | 
			
		||||
DEF_HELPER_1(rfe, void, env)
 | 
			
		||||
 | 
			
		||||
@ -99,6 +99,21 @@ static int cdc_decrement(target_ulong *psw)
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static bool cdc_zero(target_ulong *psw)
 | 
			
		||||
{
 | 
			
		||||
    int cdc = *psw & MASK_PSW_CDC;
 | 
			
		||||
    /* Returns TRUE if PSW.CDC.COUNT == 0 or if PSW.CDC ==
 | 
			
		||||
       7'b1111111, otherwise returns FALSE. */
 | 
			
		||||
    if (cdc == 0x7f) {
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
    /* find CDC.COUNT */
 | 
			
		||||
    int lo = clo32((*psw & MASK_PSW_CDC) << (32 - 7));
 | 
			
		||||
    int mask = (1u << (7 - lo)) - 1;
 | 
			
		||||
    int count = *psw & mask;
 | 
			
		||||
    return count == 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void save_context_upper(CPUTriCoreState *env, int ea,
 | 
			
		||||
                               target_ulong *new_FCX)
 | 
			
		||||
{
 | 
			
		||||
@ -302,6 +317,43 @@ void helper_bisr(CPUTriCoreState *env, uint32_t const9)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void helper_rfe(CPUTriCoreState *env)
 | 
			
		||||
{
 | 
			
		||||
    target_ulong ea;
 | 
			
		||||
    target_ulong new_PCXI;
 | 
			
		||||
    target_ulong new_PSW;
 | 
			
		||||
    /* if (PCXI[19: 0] == 0) then trap(CSU); */
 | 
			
		||||
    if ((env->PCXI & 0xfffff) == 0) {
 | 
			
		||||
        /* raise csu trap */
 | 
			
		||||
    }
 | 
			
		||||
    /* if (PCXI.UL == 0) then trap(CTYP); */
 | 
			
		||||
    if ((env->PCXI & MASK_PCXI_UL) == 0) {
 | 
			
		||||
        /* raise CTYP trap */
 | 
			
		||||
    }
 | 
			
		||||
    /* if (!cdc_zero() AND PSW.CDE) then trap(NEST); */
 | 
			
		||||
    if (!cdc_zero(&(env->PSW)) && (env->PSW & MASK_PSW_CDE)) {
 | 
			
		||||
        /* raise MNG trap */
 | 
			
		||||
    }
 | 
			
		||||
    /* ICR.IE = PCXI.PIE; */
 | 
			
		||||
    env->ICR = (env->ICR & ~MASK_ICR_IE) + ((env->PCXI & MASK_PCXI_PIE) >> 15);
 | 
			
		||||
    /* ICR.CCPN = PCXI.PCPN; */
 | 
			
		||||
    env->ICR = (env->ICR & ~MASK_ICR_CCPN) +
 | 
			
		||||
               ((env->PCXI & MASK_PCXI_PCPN) >> 24);
 | 
			
		||||
    /*EA = {PCXI.PCXS, 6'b0, PCXI.PCXO, 6'b0};*/
 | 
			
		||||
    ea = ((env->PCXI & MASK_PCXI_PCXS) << 12) +
 | 
			
		||||
         ((env->PCXI & MASK_PCXI_PCXO) << 6);
 | 
			
		||||
    /*{new_PCXI, PSW, A[10], A[11], D[8], D[9], D[10], D[11], A[12],
 | 
			
		||||
      A[13], A[14], A[15], D[12], D[13], D[14], D[15]} = M(EA, 16 * word);
 | 
			
		||||
      M(EA, word) = FCX;*/
 | 
			
		||||
    restore_context_upper(env, ea, &new_PCXI, &new_PSW);
 | 
			
		||||
    /* FCX[19: 0] = PCXI[19: 0]; */
 | 
			
		||||
    env->FCX = (env->FCX & 0xfff00000) + (env->PCXI & 0x000fffff);
 | 
			
		||||
    /* PCXI = new_PCXI; */
 | 
			
		||||
    env->PCXI = new_PCXI;
 | 
			
		||||
    /* write psw */
 | 
			
		||||
    psw_write(env, new_PSW);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void QEMU_NORETURN do_raise_exception_err(CPUTriCoreState *env,
 | 
			
		||||
                                                        uint32_t exception,
 | 
			
		||||
                                                        int error_code,
 | 
			
		||||
 | 
			
		||||
@ -262,6 +262,29 @@ static inline void gen_mul_i32s(TCGv ret, TCGv r1, TCGv r2)
 | 
			
		||||
    tcg_temp_free(low);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void gen_saturate(TCGv ret, TCGv arg, int32_t up, int32_t low)
 | 
			
		||||
{
 | 
			
		||||
    TCGv sat_neg = tcg_const_i32(low);
 | 
			
		||||
    TCGv temp = tcg_const_i32(up);
 | 
			
		||||
 | 
			
		||||
    /* sat_neg = (arg < low ) ? low : arg; */
 | 
			
		||||
    tcg_gen_movcond_tl(TCG_COND_LT, sat_neg, arg, sat_neg, sat_neg, arg);
 | 
			
		||||
 | 
			
		||||
    /* ret = (sat_neg > up ) ? up  : sat_neg; */
 | 
			
		||||
    tcg_gen_movcond_tl(TCG_COND_GT, ret, sat_neg, temp, temp, sat_neg);
 | 
			
		||||
 | 
			
		||||
    tcg_temp_free(sat_neg);
 | 
			
		||||
    tcg_temp_free(temp);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void gen_saturate_u(TCGv ret, TCGv arg, int32_t up)
 | 
			
		||||
{
 | 
			
		||||
    TCGv temp = tcg_const_i32(up);
 | 
			
		||||
    /* sat_neg = (arg > up ) ? up : arg; */
 | 
			
		||||
    tcg_gen_movcond_tl(TCG_COND_GTU, ret, arg, temp, temp, arg);
 | 
			
		||||
    tcg_temp_free(temp);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void gen_shi(TCGv ret, TCGv r1, int32_t shift_count)
 | 
			
		||||
{
 | 
			
		||||
    if (shift_count == -32) {
 | 
			
		||||
@ -477,6 +500,15 @@ static void gen_compute_branch(DisasContext *ctx, uint32_t opc, int r1,
 | 
			
		||||
    case OPC1_16_SBR_LOOP:
 | 
			
		||||
        gen_loop(ctx, r1, offset * 2 - 32);
 | 
			
		||||
        break;
 | 
			
		||||
/* SR-format jumps */
 | 
			
		||||
    case OPC1_16_SR_JI:
 | 
			
		||||
        tcg_gen_andi_tl(cpu_PC, cpu_gpr_a[r1], 0xfffffffe);
 | 
			
		||||
        tcg_gen_exit_tb(0);
 | 
			
		||||
        break;
 | 
			
		||||
    case OPC2_16_SR_RET:
 | 
			
		||||
        gen_helper_ret(cpu_env);
 | 
			
		||||
        tcg_gen_exit_tb(0);
 | 
			
		||||
        break;
 | 
			
		||||
    default:
 | 
			
		||||
        printf("Branch Error at %x\n", ctx->pc);
 | 
			
		||||
    }
 | 
			
		||||
@ -794,6 +826,70 @@ static void decode_sro_opc(DisasContext *ctx, int op1)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void decode_sr_system(CPUTriCoreState *env, DisasContext *ctx)
 | 
			
		||||
{
 | 
			
		||||
    uint32_t op2;
 | 
			
		||||
    op2 = MASK_OP_SR_OP2(ctx->opcode);
 | 
			
		||||
 | 
			
		||||
    switch (op2) {
 | 
			
		||||
    case OPC2_16_SR_NOP:
 | 
			
		||||
        break;
 | 
			
		||||
    case OPC2_16_SR_RET:
 | 
			
		||||
        gen_compute_branch(ctx, op2, 0, 0, 0, 0);
 | 
			
		||||
        break;
 | 
			
		||||
    case OPC2_16_SR_RFE:
 | 
			
		||||
        gen_helper_rfe(cpu_env);
 | 
			
		||||
        tcg_gen_exit_tb(0);
 | 
			
		||||
        ctx->bstate = BS_BRANCH;
 | 
			
		||||
        break;
 | 
			
		||||
    case OPC2_16_SR_DEBUG:
 | 
			
		||||
        /* raise EXCP_DEBUG */
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void decode_sr_accu(CPUTriCoreState *env, DisasContext *ctx)
 | 
			
		||||
{
 | 
			
		||||
    uint32_t op2;
 | 
			
		||||
    uint32_t r1;
 | 
			
		||||
    TCGv temp;
 | 
			
		||||
 | 
			
		||||
    r1 = MASK_OP_SR_S1D(ctx->opcode);
 | 
			
		||||
    op2 = MASK_OP_SR_OP2(ctx->opcode);
 | 
			
		||||
 | 
			
		||||
    switch (op2) {
 | 
			
		||||
    case OPC2_16_SR_RSUB:
 | 
			
		||||
        /* overflow only if r1 = -0x80000000 */
 | 
			
		||||
        temp = tcg_const_i32(-0x80000000);
 | 
			
		||||
        /* calc V bit */
 | 
			
		||||
        tcg_gen_setcond_tl(TCG_COND_EQ, cpu_PSW_V, cpu_gpr_d[r1], temp);
 | 
			
		||||
        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);
 | 
			
		||||
        /* sub */
 | 
			
		||||
        tcg_gen_neg_tl(cpu_gpr_d[r1], cpu_gpr_d[r1]);
 | 
			
		||||
        /* calc av */
 | 
			
		||||
        tcg_gen_add_tl(cpu_PSW_AV, cpu_gpr_d[r1], cpu_gpr_d[r1]);
 | 
			
		||||
        tcg_gen_xor_tl(cpu_PSW_AV, cpu_gpr_d[r1], cpu_PSW_AV);
 | 
			
		||||
        /* calc sav */
 | 
			
		||||
        tcg_gen_or_tl(cpu_PSW_SAV, cpu_PSW_SAV, cpu_PSW_AV);
 | 
			
		||||
        tcg_temp_free(temp);
 | 
			
		||||
        break;
 | 
			
		||||
    case OPC2_16_SR_SAT_B:
 | 
			
		||||
        gen_saturate(cpu_gpr_d[r1], cpu_gpr_d[r1], 0x7f, -0x80);
 | 
			
		||||
        break;
 | 
			
		||||
    case OPC2_16_SR_SAT_BU:
 | 
			
		||||
        gen_saturate_u(cpu_gpr_d[r1], cpu_gpr_d[r1], 0xff);
 | 
			
		||||
        break;
 | 
			
		||||
    case OPC2_16_SR_SAT_H:
 | 
			
		||||
        gen_saturate(cpu_gpr_d[r1], cpu_gpr_d[r1], 0x7fff, -0x8000);
 | 
			
		||||
        break;
 | 
			
		||||
    case OPC2_16_SR_SAT_HU:
 | 
			
		||||
        gen_saturate_u(cpu_gpr_d[r1], cpu_gpr_d[r1], 0xffff);
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void decode_16Bit_opc(CPUTriCoreState *env, DisasContext *ctx)
 | 
			
		||||
{
 | 
			
		||||
    int op1;
 | 
			
		||||
@ -985,6 +1081,21 @@ static void decode_16Bit_opc(CPUTriCoreState *env, DisasContext *ctx)
 | 
			
		||||
        const16 = MASK_OP_SSRO_OFF4(ctx->opcode);
 | 
			
		||||
        gen_offset_st(ctx, cpu_gpr_d[r1], cpu_gpr_a[15], const16 * 4, MO_LESL);
 | 
			
		||||
        break;
 | 
			
		||||
/* SR-format */
 | 
			
		||||
    case OPCM_16_SR_SYSTEM:
 | 
			
		||||
        decode_sr_system(env, ctx);
 | 
			
		||||
        break;
 | 
			
		||||
    case OPCM_16_SR_ACCU:
 | 
			
		||||
        decode_sr_accu(env, ctx);
 | 
			
		||||
        break;
 | 
			
		||||
    case OPC1_16_SR_JI:
 | 
			
		||||
        r1 = MASK_OP_SR_S1D(ctx->opcode);
 | 
			
		||||
        gen_compute_branch(ctx, op1, r1, 0, 0, 0);
 | 
			
		||||
        break;
 | 
			
		||||
    case OPC1_16_SR_NOT:
 | 
			
		||||
        r1 = MASK_OP_SR_S1D(ctx->opcode);
 | 
			
		||||
        tcg_gen_not_tl(cpu_gpr_d[r1], cpu_gpr_d[r1]);
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user