Revision d9bdab86

b/target-sparc/cpu.h
186 186
    target_ulong y;        /* multiply/divide register */
187 187

  
188 188
    /* emulator internal flags handling */
189
    target_ulong cc_src;
189
    target_ulong cc_src, cc_src2;
190 190
    target_ulong cc_dst;
191 191

  
192 192
    uint32_t psr;      /* processor state register */
b/target-sparc/op.c
195 195
    env->y = res >> 32;
196 196
}
197 197

  
198
void OPPROTO op_mulscc_T1_T0(void)
199
{
200
    unsigned int b1, N, V, b2;
201
    target_ulong src1;
202

  
203
    N = FLAG_SET(PSR_NEG);
204
    V = FLAG_SET(PSR_OVF);
205
    b1 = N ^ V;
206
    b2 = T0 & 1;
207
    T0 = (b1 << 31) | (T0 >> 1);
208
    if (!(env->y & 1))
209
        T1 = 0;
210
    /* do addition and update flags */
211
    src1 = T0;
212
    T0 += T1;
213
    env->psr = 0;
214
    if (!T0)
215
        env->psr |= PSR_ZERO;
216
    if ((int32_t) T0 < 0)
217
        env->psr |= PSR_NEG;
218
    if (T0 < src1)
219
        env->psr |= PSR_CARRY;
220
    if (((src1 ^ T1 ^ -1) & (src1 ^ T0)) & (1 << 31))
221
        env->psr |= PSR_OVF;
222
    env->y = (b2 << 31) | (env->y >> 1);
223
    FORCE_RET();
224
}
225

  
226 198
void OPPROTO op_udiv_T1_T0(void)
227 199
{
228 200
    uint64_t x0;
b/target-sparc/translate.c
46 46
                         according to jump_pc[T2] */
47 47

  
48 48
/* global register indexes */
49
static TCGv cpu_env, cpu_T[3], cpu_regwptr, cpu_cc_src, cpu_cc_dst;
49
static TCGv cpu_env, cpu_T[3], cpu_regwptr, cpu_cc_src, cpu_cc_src2, cpu_cc_dst;
50 50
static TCGv cpu_psr, cpu_fsr, cpu_gregs[8];
51 51
#ifdef TARGET_SPARC64
52 52
static TCGv cpu_xcc;
......
710 710
    gen_cc_C_sub(cpu_cc_src, cpu_T[1]);
711 711
}
712 712

  
713
static inline void gen_op_mulscc_T1_T0(void)
714
{
715
    TCGv r_temp;
716
    int l1, l2;
717

  
718
    l1 = gen_new_label();
719
    l2 = gen_new_label();
720
    r_temp = tcg_temp_new(TCG_TYPE_TL);
721

  
722
    /* old op:
723
    if (!(env->y & 1))
724
        T1 = 0;
725
    */
726
    tcg_gen_ld_i32(r_temp, cpu_env, offsetof(CPUSPARCState, y));
727
    tcg_gen_andi_i32(r_temp, r_temp, 0x1);
728
    tcg_gen_brcond_i32(TCG_COND_EQ, r_temp, tcg_const_tl(0), l1);
729
    tcg_gen_mov_tl(cpu_cc_src2, cpu_T[1]);
730
    gen_op_jmp_label(l2);
731
    gen_set_label(l1);
732
    tcg_gen_movi_tl(cpu_cc_src2, 0);
733
    gen_set_label(l2);
734

  
735
    // b2 = T0 & 1;
736
    // env->y = (b2 << 31) | (env->y >> 1);
737
    tcg_gen_shli_i32(r_temp, cpu_T[0], 31);
738
    tcg_gen_ld_i32(cpu_tmp0, cpu_env, offsetof(CPUSPARCState, y));
739
    tcg_gen_shri_i32(cpu_tmp0, cpu_tmp0, 1);
740
    tcg_gen_or_i32(cpu_tmp0, cpu_tmp0, r_temp);
741
    tcg_gen_st_i32(cpu_tmp0, cpu_env, offsetof(CPUSPARCState, y));
742

  
743
    // b1 = N ^ V;
744
    gen_mov_reg_N(cpu_tmp0, cpu_psr);
745
    gen_mov_reg_V(r_temp, cpu_psr);
746
    tcg_gen_xor_tl(cpu_tmp0, cpu_tmp0, r_temp);
747

  
748
    // T0 = (b1 << 31) | (T0 >> 1);
749
    // src1 = T0;
750
    tcg_gen_shli_tl(cpu_tmp0, cpu_tmp0, 31);
751
    tcg_gen_shri_tl(cpu_cc_src, cpu_T[0], 1);
752
    tcg_gen_or_tl(cpu_cc_src, cpu_cc_src, cpu_tmp0);
753

  
754
    /* do addition and update flags */
755
    tcg_gen_add_tl(cpu_T[0], cpu_cc_src, cpu_cc_src2);
756
    tcg_gen_discard_tl(r_temp);
757

  
758
    gen_cc_clear();
759
    gen_cc_NZ(cpu_T[0]);
760
    gen_cc_V_add(cpu_T[0], cpu_cc_src, cpu_cc_src2);
761
    gen_cc_C_add(cpu_T[0], cpu_cc_src);
762
}
763

  
713 764
#ifdef TARGET_SPARC64
714 765
static inline void gen_trap_ifdivzero_i64(TCGv divisor)
715 766
{
......
4627 4678
        cpu_cc_src = tcg_global_mem_new(TCG_TYPE_TL,
4628 4679
                                        TCG_AREG0, offsetof(CPUState, cc_src),
4629 4680
                                        "cc_src");
4681
        cpu_cc_src2 = tcg_global_mem_new(TCG_TYPE_TL, TCG_AREG0,
4682
                                         offsetof(CPUState, cc_src2),
4683
                                         "cc_src2");
4630 4684
        cpu_cc_dst = tcg_global_mem_new(TCG_TYPE_TL,
4631 4685
                                        TCG_AREG0, offsetof(CPUState, cc_dst),
4632 4686
                                        "cc_dst");

Also available in: Unified diff