Statistics
| Branch: | Revision:

root / target-sparc / op_helper.c @ af7bf89b

History | View | Annotate | Download (4.8 kB)

1
#include <math.h>
2
#include <fenv.h>
3
#include "exec.h"
4

    
5
//#define DEBUG_MMU
6

    
7
#ifdef USE_INT_TO_FLOAT_HELPERS
8
void do_fitos(void)
9
{
10
    FT0 = (float) *((int32_t *)&FT1);
11
}
12

    
13
void do_fitod(void)
14
{
15
    DT0 = (double) *((int32_t *)&FT1);
16
}
17
#endif
18

    
19
void do_fabss(void)
20
{
21
    FT0 = fabsf(FT1);
22
}
23

    
24
void do_fsqrts(void)
25
{
26
    FT0 = sqrtf(FT1);
27
}
28

    
29
void do_fsqrtd(void)
30
{
31
    DT0 = sqrt(DT1);
32
}
33

    
34
void do_fcmps (void)
35
{
36
    if (isnan(FT0) || isnan(FT1)) {
37
        T0 = FSR_FCC1 | FSR_FCC0;
38
        env->fsr &= ~(FSR_FCC1 | FSR_FCC0);
39
        env->fsr |= T0;
40
        if (env->fsr & FSR_NVM) {
41
            raise_exception(TT_FP_EXCP);
42
        } else {
43
            env->fsr |= FSR_NVA;
44
        }
45
    } else if (FT0 < FT1) {
46
        T0 = FSR_FCC0;
47
    } else if (FT0 > FT1) {
48
        T0 = FSR_FCC1;
49
    } else {
50
        T0 = 0;
51
    }
52
    env->fsr = T0;
53
}
54

    
55
void do_fcmpd (void)
56
{
57
    if (isnan(DT0) || isnan(DT1)) {
58
        T0 = FSR_FCC1 | FSR_FCC0;
59
        env->fsr &= ~(FSR_FCC1 | FSR_FCC0);
60
        env->fsr |= T0;
61
        if (env->fsr & FSR_NVM) {
62
            raise_exception(TT_FP_EXCP);
63
        } else {
64
            env->fsr |= FSR_NVA;
65
        }
66
    } else if (DT0 < DT1) {
67
        T0 = FSR_FCC0;
68
    } else if (DT0 > DT1) {
69
        T0 = FSR_FCC1;
70
    } else {
71
        T0 = 0;
72
    }
73
    env->fsr = T0;
74
}
75

    
76
void helper_ld_asi(int asi, int size, int sign)
77
{
78
    uint32_t ret;
79

    
80
    switch (asi) {
81
    case 3: /* MMU probe */
82
        {
83
            int mmulev;
84

    
85
            mmulev = (T0 >> 8) & 15;
86
            if (mmulev > 4)
87
                ret = 0;
88
            else {
89
                ret = mmu_probe(T0, mmulev);
90
                //bswap32s(&ret);
91
            }
92
#ifdef DEBUG_MMU
93
            printf("mmu_probe: 0x%08x (lev %d) -> 0x%08x\n", T0, mmulev, ret);
94
#endif
95
        }
96
        break;
97
    case 4: /* read MMU regs */
98
        {
99
            int reg = (T0 >> 8) & 0xf;
100
            
101
            ret = env->mmuregs[reg];
102
            if (reg == 3 || reg == 4) /* Fault status, addr cleared on read*/
103
                env->mmuregs[4] = 0;
104
        }
105
        break;
106
    case 0x20 ... 0x2f: /* MMU passthrough */
107
        cpu_physical_memory_read(T0, (void *) &ret, size);
108
        if (size == 4)
109
            tswap32s(&ret);
110
        else if (size == 2)
111
            tswap16s((uint16_t *)&ret);
112
        break;
113
    default:
114
        ret = 0;
115
        break;
116
    }
117
    T1 = ret;
118
}
119

    
120
void helper_st_asi(int asi, int size, int sign)
121
{
122
    switch(asi) {
123
    case 3: /* MMU flush */
124
        {
125
            int mmulev;
126

    
127
            mmulev = (T0 >> 8) & 15;
128
            switch (mmulev) {
129
            case 0: // flush page
130
                tlb_flush_page(cpu_single_env, T0 & 0xfffff000);
131
                break;
132
            case 1: // flush segment (256k)
133
            case 2: // flush region (16M)
134
            case 3: // flush context (4G)
135
            case 4: // flush entire
136
                tlb_flush(cpu_single_env, 1);
137
                break;
138
            default:
139
                break;
140
            }
141
            dump_mmu();
142
            return;
143
        }
144
    case 4: /* write MMU regs */
145
        {
146
            int reg = (T0 >> 8) & 0xf, oldreg;
147
            
148
            oldreg = env->mmuregs[reg];
149
            if (reg == 0) {
150
                env->mmuregs[reg] &= ~(MMU_E | MMU_NF);
151
                env->mmuregs[reg] |= T1 & (MMU_E | MMU_NF);
152
            } else
153
                env->mmuregs[reg] = T1;
154
            if (oldreg != env->mmuregs[reg]) {
155
#if 0
156
                // XXX: Only if MMU mapping change, we may need to flush?
157
                tlb_flush(cpu_single_env, 1);
158
                cpu_loop_exit();
159
                FORCE_RET();
160
#endif
161
            }
162
            dump_mmu();
163
            return;
164
        }
165
    case 0x17: /* Block copy, sta access */
166
        {
167
            // value (T1) = src
168
            // address (T0) = dst
169
            // copy 32 bytes
170
            int src = T1, dst = T0;
171
            uint8_t temp[32];
172
            
173
            tswap32s(&src);
174

    
175
            cpu_physical_memory_read(src, (void *) &temp, 32);
176
            cpu_physical_memory_write(dst, (void *) &temp, 32);
177
        }
178
        return;
179
    case 0x1f: /* Block fill, stda access */
180
        {
181
            // value (T1, T2)
182
            // address (T0) = dst
183
            // fill 32 bytes
184
            int i, dst = T0;
185
            uint64_t val;
186
            
187
            val = (((uint64_t)T1) << 32) | T2;
188
            tswap64s(&val);
189

    
190
            for (i = 0; i < 32; i += 8, dst += 8) {
191
                cpu_physical_memory_write(dst, (void *) &val, 8);
192
            }
193
        }
194
        return;
195
    case 0x20 ... 0x2f: /* MMU passthrough */
196
        {
197
            int temp = T1;
198
            if (size == 4)
199
                tswap32s(&temp);
200
            else if (size == 2)
201
                tswap16s((uint16_t *)&temp);
202
            cpu_physical_memory_write(T0, (void *) &temp, size);
203
        }
204
        return;
205
    default:
206
        return;
207
    }
208
}
209

    
210
void helper_rett()
211
{
212
    unsigned int cwp;
213

    
214
    env->psret = 1;
215
    cwp = (env->cwp + 1) & (NWINDOWS - 1); 
216
    if (env->wim & (1 << cwp)) {
217
        raise_exception(TT_WIN_UNF);
218
    }
219
    set_cwp(cwp);
220
    env->psrs = env->psrps;
221
}
222

    
223
void helper_ldfsr(void)
224
{
225
    switch (env->fsr & FSR_RD_MASK) {
226
    case FSR_RD_NEAREST:
227
        fesetround(FE_TONEAREST);
228
        break;
229
    case FSR_RD_ZERO:
230
        fesetround(FE_TOWARDZERO);
231
        break;
232
    case FSR_RD_POS:
233
        fesetround(FE_UPWARD);
234
        break;
235
    case FSR_RD_NEG:
236
        fesetround(FE_DOWNWARD);
237
        break;
238
    }
239
}
240

    
241
void cpu_get_fp64(uint64_t *pmant, uint16_t *pexp, double f)
242
{
243
    int exptemp;
244

    
245
    *pmant = ldexp(frexp(f, &exptemp), 53);
246
    *pexp = exptemp;
247
}
248

    
249
double cpu_put_fp64(uint64_t mant, uint16_t exp)
250
{
251
    return ldexp((double) mant, exp - 53);
252
}
253

    
254
void helper_debug()
255
{
256
    env->exception_index = EXCP_DEBUG;
257
    cpu_loop_exit();
258
}
259

    
260
void do_wrpsr()
261
{
262
    PUT_PSR(env, T0);
263
}
264

    
265
void do_rdpsr()
266
{
267
    T0 = GET_PSR(env);
268
}