Statistics
| Branch: | Revision:

root / target-sparc / op_helper.c @ 7a0e1f41

History | View | Annotate | Download (5.8 kB)

1
#include "exec.h"
2

    
3
//#define DEBUG_MMU
4

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

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

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

    
23
void do_fabss(void)
24
{
25
    FT0 = float32_abs(FT1);
26
}
27

    
28
void do_fsqrts(void)
29
{
30
    FT0 = float32_sqrt(FT1, &env->fp_status);
31
}
32

    
33
void do_fsqrtd(void)
34
{
35
    DT0 = float64_sqrt(DT1, &env->fp_status);
36
}
37

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

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

    
80
void helper_ld_asi(int asi, int size, int sign)
81
{
82
    uint32_t ret;
83

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

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

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

    
134
            mmulev = (T0 >> 8) & 15;
135
#ifdef DEBUG_MMU
136
            printf("mmu flush level %d\n", mmulev);
137
#endif
138
            switch (mmulev) {
139
            case 0: // flush page
140
                tlb_flush_page(env, T0 & 0xfffff000);
141
                break;
142
            case 1: // flush segment (256k)
143
            case 2: // flush region (16M)
144
            case 3: // flush context (4G)
145
            case 4: // flush entire
146
                tlb_flush(env, 1);
147
                break;
148
            default:
149
                break;
150
            }
151
#ifdef DEBUG_MMU
152
            dump_mmu();
153
#endif
154
            return;
155
        }
156
    case 4: /* write MMU regs */
157
        {
158
            int reg = (T0 >> 8) & 0xf, oldreg;
159
            
160
            oldreg = env->mmuregs[reg];
161
            switch(reg) {
162
            case 0:
163
                env->mmuregs[reg] &= ~(MMU_E | MMU_NF);
164
                env->mmuregs[reg] |= T1 & (MMU_E | MMU_NF);
165
                // Mappings generated during no-fault mode or MMU
166
                // disabled mode are invalid in normal mode
167
                if (oldreg != env->mmuregs[reg])
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
    int rnd_mode;
254
    switch (env->fsr & FSR_RD_MASK) {
255
    case FSR_RD_NEAREST:
256
        rnd_mode = float_round_nearest_even;
257
        break;
258
    case FSR_RD_ZERO:
259
        rnd_mode = float_round_to_zero;
260
        break;
261
    case FSR_RD_POS:
262
        rnd_mode = float_round_up;
263
        break;
264
    case FSR_RD_NEG:
265
        rnd_mode = float_round_down;
266
        break;
267
    }
268
    set_float_rounding_mode(rnd_mode, &env->fp_status);
269
}
270

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

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

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

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

    
290
void do_wrpsr()
291
{
292
    PUT_PSR(env, T0);
293
}
294

    
295
void do_rdpsr()
296
{
297
    T0 = GET_PSR(env);
298
}