Statistics
| Branch: | Revision:

root / target-sparc / op_helper.c @ 55754d9e

History | View | Annotate | Download (5.6 kB)

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

    
5
//#define DEBUG_MMU
6

    
7
void raise_exception(int tt)
8
{
9
    env->exception_index = tt;
10
    cpu_loop_exit();
11
}   
12

    
13
#ifdef USE_INT_TO_FLOAT_HELPERS
14
void do_fitos(void)
15
{
16
    FT0 = (float) *((int32_t *)&FT1);
17
}
18

    
19
void do_fitod(void)
20
{
21
    DT0 = (double) *((int32_t *)&FT1);
22
}
23
#endif
24

    
25
void do_fabss(void)
26
{
27
    FT0 = fabsf(FT1);
28
}
29

    
30
void do_fsqrts(void)
31
{
32
    FT0 = sqrtf(FT1);
33
}
34

    
35
void do_fsqrtd(void)
36
{
37
    DT0 = sqrt(DT1);
38
}
39

    
40
void do_fcmps (void)
41
{
42
    if (isnan(FT0) || isnan(FT1)) {
43
        T0 = FSR_FCC1 | FSR_FCC0;
44
        env->fsr &= ~(FSR_FCC1 | FSR_FCC0);
45
        env->fsr |= T0;
46
        if (env->fsr & FSR_NVM) {
47
            raise_exception(TT_FP_EXCP);
48
        } else {
49
            env->fsr |= FSR_NVA;
50
        }
51
    } else if (FT0 < FT1) {
52
        T0 = FSR_FCC0;
53
    } else if (FT0 > FT1) {
54
        T0 = FSR_FCC1;
55
    } else {
56
        T0 = 0;
57
    }
58
    env->fsr = T0;
59
}
60

    
61
void do_fcmpd (void)
62
{
63
    if (isnan(DT0) || isnan(DT1)) {
64
        T0 = FSR_FCC1 | FSR_FCC0;
65
        env->fsr &= ~(FSR_FCC1 | FSR_FCC0);
66
        env->fsr |= T0;
67
        if (env->fsr & FSR_NVM) {
68
            raise_exception(TT_FP_EXCP);
69
        } else {
70
            env->fsr |= FSR_NVA;
71
        }
72
    } else if (DT0 < DT1) {
73
        T0 = FSR_FCC0;
74
    } else if (DT0 > DT1) {
75
        T0 = FSR_FCC1;
76
    } else {
77
        T0 = 0;
78
    }
79
    env->fsr = T0;
80
}
81

    
82
void helper_ld_asi(int asi, int size, int sign)
83
{
84
    uint32_t ret;
85

    
86
    switch (asi) {
87
    case 3: /* MMU probe */
88
        {
89
            int mmulev;
90

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

    
129
void helper_st_asi(int asi, int size, int sign)
130
{
131
    switch(asi) {
132
    case 3: /* MMU flush */
133
        {
134
            int mmulev;
135

    
136
            mmulev = (T0 >> 8) & 15;
137
#ifdef DEBUG_MMU
138
            printf("mmu flush level %d\n", mmulev);
139
#endif
140
            switch (mmulev) {
141
            case 0: // flush page
142
                tlb_flush_page(env, T0 & 0xfffff000);
143
                break;
144
            case 1: // flush segment (256k)
145
            case 2: // flush region (16M)
146
            case 3: // flush context (4G)
147
            case 4: // flush entire
148
                tlb_flush(env, 1);
149
                break;
150
            default:
151
                break;
152
            }
153
#ifdef DEBUG_MMU
154
            dump_mmu();
155
#endif
156
            return;
157
        }
158
    case 4: /* write MMU regs */
159
        {
160
            int reg = (T0 >> 8) & 0xf, oldreg;
161
            
162
            oldreg = env->mmuregs[reg];
163
            switch(reg) {
164
            case 0:
165
                env->mmuregs[reg] &= ~(MMU_E | MMU_NF);
166
                env->mmuregs[reg] |= T1 & (MMU_E | MMU_NF);
167
                if ((oldreg & MMU_E) != (env->mmuregs[reg] & MMU_E))
168
                    tlb_flush(env, 1);
169
                break;
170
            case 2:
171
                env->mmuregs[reg] = T1;
172
                if (oldreg != env->mmuregs[reg]) {
173
                    /* we flush when the MMU context changes because
174
                       QEMU has no MMU context support */
175
                    tlb_flush(env, 1);
176
                }
177
                break;
178
            case 3:
179
            case 4:
180
                break;
181
            default:
182
                env->mmuregs[reg] = T1;
183
                break;
184
            }
185
#ifdef DEBUG_MMU
186
            if (oldreg != env->mmuregs[reg]) {
187
                printf("mmu change reg[%d]: 0x%08x -> 0x%08x\n", reg, oldreg, env->mmuregs[reg]);
188
            }
189
            dump_mmu();
190
#endif
191
            return;
192
        }
193
    case 0x17: /* Block copy, sta access */
194
        {
195
            // value (T1) = src
196
            // address (T0) = dst
197
            // copy 32 bytes
198
            int src = T1, dst = T0;
199
            uint8_t temp[32];
200
            
201
            tswap32s(&src);
202

    
203
            cpu_physical_memory_read(src, (void *) &temp, 32);
204
            cpu_physical_memory_write(dst, (void *) &temp, 32);
205
        }
206
        return;
207
    case 0x1f: /* Block fill, stda access */
208
        {
209
            // value (T1, T2)
210
            // address (T0) = dst
211
            // fill 32 bytes
212
            int i, dst = T0;
213
            uint64_t val;
214
            
215
            val = (((uint64_t)T1) << 32) | T2;
216
            tswap64s(&val);
217

    
218
            for (i = 0; i < 32; i += 8, dst += 8) {
219
                cpu_physical_memory_write(dst, (void *) &val, 8);
220
            }
221
        }
222
        return;
223
    case 0x20 ... 0x2f: /* MMU passthrough */
224
        {
225
            int temp = T1;
226
            if (size == 4)
227
                tswap32s(&temp);
228
            else if (size == 2)
229
                tswap16s((uint16_t *)&temp);
230
            cpu_physical_memory_write(T0, (void *) &temp, size);
231
        }
232
        return;
233
    default:
234
        return;
235
    }
236
}
237

    
238
void helper_rett()
239
{
240
    unsigned int cwp;
241

    
242
    env->psret = 1;
243
    cwp = (env->cwp + 1) & (NWINDOWS - 1); 
244
    if (env->wim & (1 << cwp)) {
245
        raise_exception(TT_WIN_UNF);
246
    }
247
    set_cwp(cwp);
248
    env->psrs = env->psrps;
249
}
250

    
251
void helper_ldfsr(void)
252
{
253
    switch (env->fsr & FSR_RD_MASK) {
254
    case FSR_RD_NEAREST:
255
        fesetround(FE_TONEAREST);
256
        break;
257
    case FSR_RD_ZERO:
258
        fesetround(FE_TOWARDZERO);
259
        break;
260
    case FSR_RD_POS:
261
        fesetround(FE_UPWARD);
262
        break;
263
    case FSR_RD_NEG:
264
        fesetround(FE_DOWNWARD);
265
        break;
266
    }
267
}
268

    
269
void cpu_get_fp64(uint64_t *pmant, uint16_t *pexp, double f)
270
{
271
    int exptemp;
272

    
273
    *pmant = ldexp(frexp(f, &exptemp), 53);
274
    *pexp = exptemp;
275
}
276

    
277
double cpu_put_fp64(uint64_t mant, uint16_t exp)
278
{
279
    return ldexp((double) mant, exp - 53);
280
}
281

    
282
void helper_debug()
283
{
284
    env->exception_index = EXCP_DEBUG;
285
    cpu_loop_exit();
286
}
287

    
288
void do_wrpsr()
289
{
290
    PUT_PSR(env, T0);
291
}
292

    
293
void do_rdpsr()
294
{
295
    T0 = GET_PSR(env);
296
}