Statistics
| Branch: | Revision:

root / target-alpha / helper.c @ 352e48b0

History | View | Annotate | Download (13.8 kB)

1
/*
2
 *  Alpha emulation cpu helpers for qemu.
3
 *
4
 *  Copyright (c) 2007 Jocelyn Mayer
5
 *
6
 * This library is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU Lesser General Public
8
 * License as published by the Free Software Foundation; either
9
 * version 2 of the License, or (at your option) any later version.
10
 *
11
 * This library is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
 * Lesser General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU Lesser General Public
17
 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18
 */
19

    
20
#include <stdint.h>
21
#include <stdlib.h>
22
#include <stdio.h>
23

    
24
#include "cpu.h"
25
#include "exec-all.h"
26
#include "softfloat.h"
27

    
28
uint64_t cpu_alpha_load_fpcr (CPUState *env)
29
{
30
    uint64_t r = 0;
31
    uint8_t t;
32

    
33
    t = env->fpcr_exc_status;
34
    if (t) {
35
        r = FPCR_SUM;
36
        if (t & float_flag_invalid) {
37
            r |= FPCR_INV;
38
        }
39
        if (t & float_flag_divbyzero) {
40
            r |= FPCR_DZE;
41
        }
42
        if (t & float_flag_overflow) {
43
            r |= FPCR_OVF;
44
        }
45
        if (t & float_flag_underflow) {
46
            r |= FPCR_UNF;
47
        }
48
        if (t & float_flag_inexact) {
49
            r |= FPCR_INE;
50
        }
51
    }
52

    
53
    t = env->fpcr_exc_mask;
54
    if (t & float_flag_invalid) {
55
        r |= FPCR_INVD;
56
    }
57
    if (t & float_flag_divbyzero) {
58
        r |= FPCR_DZED;
59
    }
60
    if (t & float_flag_overflow) {
61
        r |= FPCR_OVFD;
62
    }
63
    if (t & float_flag_underflow) {
64
        r |= FPCR_UNFD;
65
    }
66
    if (t & float_flag_inexact) {
67
        r |= FPCR_INED;
68
    }
69

    
70
    switch (env->fpcr_dyn_round) {
71
    case float_round_nearest_even:
72
        r |= FPCR_DYN_NORMAL;
73
        break;
74
    case float_round_down:
75
        r |= FPCR_DYN_MINUS;
76
        break;
77
    case float_round_up:
78
        r |= FPCR_DYN_PLUS;
79
        break;
80
    case float_round_to_zero:
81
        r |= FPCR_DYN_CHOPPED;
82
        break;
83
    }
84

    
85
    if (env->fpcr_dnz) {
86
        r |= FPCR_DNZ;
87
    }
88
    if (env->fpcr_dnod) {
89
        r |= FPCR_DNOD;
90
    }
91
    if (env->fpcr_undz) {
92
        r |= FPCR_UNDZ;
93
    }
94

    
95
    return r;
96
}
97

    
98
void cpu_alpha_store_fpcr (CPUState *env, uint64_t val)
99
{
100
    uint8_t t;
101

    
102
    t = 0;
103
    if (val & FPCR_INV) {
104
        t |= float_flag_invalid;
105
    }
106
    if (val & FPCR_DZE) {
107
        t |= float_flag_divbyzero;
108
    }
109
    if (val & FPCR_OVF) {
110
        t |= float_flag_overflow;
111
    }
112
    if (val & FPCR_UNF) {
113
        t |= float_flag_underflow;
114
    }
115
    if (val & FPCR_INE) {
116
        t |= float_flag_inexact;
117
    }
118
    env->fpcr_exc_status = t;
119

    
120
    t = 0;
121
    if (val & FPCR_INVD) {
122
        t |= float_flag_invalid;
123
    }
124
    if (val & FPCR_DZED) {
125
        t |= float_flag_divbyzero;
126
    }
127
    if (val & FPCR_OVFD) {
128
        t |= float_flag_overflow;
129
    }
130
    if (val & FPCR_UNFD) {
131
        t |= float_flag_underflow;
132
    }
133
    if (val & FPCR_INED) {
134
        t |= float_flag_inexact;
135
    }
136
    env->fpcr_exc_mask = t;
137

    
138
    switch (val & FPCR_DYN_MASK) {
139
    case FPCR_DYN_CHOPPED:
140
        t = float_round_to_zero;
141
        break;
142
    case FPCR_DYN_MINUS:
143
        t = float_round_down;
144
        break;
145
    case FPCR_DYN_NORMAL:
146
        t = float_round_nearest_even;
147
        break;
148
    case FPCR_DYN_PLUS:
149
        t = float_round_up;
150
        break;
151
    }
152
    env->fpcr_dyn_round = t;
153

    
154
    env->fpcr_flush_to_zero
155
      = (val & (FPCR_UNDZ|FPCR_UNFD)) == (FPCR_UNDZ|FPCR_UNFD);
156

    
157
    env->fpcr_dnz = (val & FPCR_DNZ) != 0;
158
    env->fpcr_dnod = (val & FPCR_DNOD) != 0;
159
    env->fpcr_undz = (val & FPCR_UNDZ) != 0;
160
}
161

    
162
#if defined(CONFIG_USER_ONLY)
163

    
164
int cpu_alpha_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
165
                                int mmu_idx, int is_softmmu)
166
{
167
    if (rw == 2)
168
        env->exception_index = EXCP_ITB_MISS;
169
    else
170
        env->exception_index = EXCP_DFAULT;
171
    env->ipr[IPR_EXC_ADDR] = address;
172

    
173
    return 1;
174
}
175

    
176
void do_interrupt (CPUState *env)
177
{
178
    env->exception_index = -1;
179
}
180

    
181
#else
182

    
183
target_phys_addr_t cpu_get_phys_page_debug (CPUState *env, target_ulong addr)
184
{
185
    return -1;
186
}
187

    
188
int cpu_alpha_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
189
                                int mmu_idx, int is_softmmu)
190
{
191
    uint32_t opc;
192

    
193
    if (rw == 2) {
194
        /* Instruction translation buffer miss */
195
        env->exception_index = EXCP_ITB_MISS;
196
    } else {
197
        if (env->ipr[IPR_EXC_ADDR] & 1)
198
            env->exception_index = EXCP_DTB_MISS_PAL;
199
        else
200
            env->exception_index = EXCP_DTB_MISS_NATIVE;
201
        opc = (ldl_code(env->pc) >> 21) << 4;
202
        if (rw) {
203
            opc |= 0x9;
204
        } else {
205
            opc |= 0x4;
206
        }
207
        env->ipr[IPR_MM_STAT] = opc;
208
    }
209

    
210
    return 1;
211
}
212

    
213
int cpu_alpha_mfpr (CPUState *env, int iprn, uint64_t *valp)
214
{
215
    uint64_t hwpcb;
216
    int ret = 0;
217

    
218
    hwpcb = env->ipr[IPR_PCBB];
219
    switch (iprn) {
220
    case IPR_ASN:
221
        if (env->features & FEATURE_ASN)
222
            *valp = env->ipr[IPR_ASN];
223
        else
224
            *valp = 0;
225
        break;
226
    case IPR_ASTEN:
227
        *valp = ((int64_t)(env->ipr[IPR_ASTEN] << 60)) >> 60;
228
        break;
229
    case IPR_ASTSR:
230
        *valp = ((int64_t)(env->ipr[IPR_ASTSR] << 60)) >> 60;
231
        break;
232
    case IPR_DATFX:
233
        /* Write only */
234
        ret = -1;
235
        break;
236
    case IPR_ESP:
237
        if (env->features & FEATURE_SPS)
238
            *valp = env->ipr[IPR_ESP];
239
        else
240
            *valp = ldq_raw(hwpcb + 8);
241
        break;
242
    case IPR_FEN:
243
        *valp = ((int64_t)(env->ipr[IPR_FEN] << 63)) >> 63;
244
        break;
245
    case IPR_IPIR:
246
        /* Write-only */
247
        ret = -1;
248
        break;
249
    case IPR_IPL:
250
        *valp = ((int64_t)(env->ipr[IPR_IPL] << 59)) >> 59;
251
        break;
252
    case IPR_KSP:
253
        if (!(env->ipr[IPR_EXC_ADDR] & 1)) {
254
            ret = -1;
255
        } else {
256
            if (env->features & FEATURE_SPS)
257
                *valp = env->ipr[IPR_KSP];
258
            else
259
                *valp = ldq_raw(hwpcb + 0);
260
        }
261
        break;
262
    case IPR_MCES:
263
        *valp = ((int64_t)(env->ipr[IPR_MCES] << 59)) >> 59;
264
        break;
265
    case IPR_PERFMON:
266
        /* Implementation specific */
267
        *valp = 0;
268
        break;
269
    case IPR_PCBB:
270
        *valp = ((int64_t)env->ipr[IPR_PCBB] << 16) >> 16;
271
        break;
272
    case IPR_PRBR:
273
        *valp = env->ipr[IPR_PRBR];
274
        break;
275
    case IPR_PTBR:
276
        *valp = env->ipr[IPR_PTBR];
277
        break;
278
    case IPR_SCBB:
279
        *valp = (int64_t)((int32_t)env->ipr[IPR_SCBB]);
280
        break;
281
    case IPR_SIRR:
282
        /* Write-only */
283
        ret = -1;
284
        break;
285
    case IPR_SISR:
286
        *valp = (int64_t)((int16_t)env->ipr[IPR_SISR]);
287
    case IPR_SSP:
288
        if (env->features & FEATURE_SPS)
289
            *valp = env->ipr[IPR_SSP];
290
        else
291
            *valp = ldq_raw(hwpcb + 16);
292
        break;
293
    case IPR_SYSPTBR:
294
        if (env->features & FEATURE_VIRBND)
295
            *valp = env->ipr[IPR_SYSPTBR];
296
        else
297
            ret = -1;
298
        break;
299
    case IPR_TBCHK:
300
        if ((env->features & FEATURE_TBCHK)) {
301
            /* XXX: TODO */
302
            *valp = 0;
303
            ret = -1;
304
        } else {
305
            ret = -1;
306
        }
307
        break;
308
    case IPR_TBIA:
309
        /* Write-only */
310
        ret = -1;
311
        break;
312
    case IPR_TBIAP:
313
        /* Write-only */
314
        ret = -1;
315
        break;
316
    case IPR_TBIS:
317
        /* Write-only */
318
        ret = -1;
319
        break;
320
    case IPR_TBISD:
321
        /* Write-only */
322
        ret = -1;
323
        break;
324
    case IPR_TBISI:
325
        /* Write-only */
326
        ret = -1;
327
        break;
328
    case IPR_USP:
329
        if (env->features & FEATURE_SPS)
330
            *valp = env->ipr[IPR_USP];
331
        else
332
            *valp = ldq_raw(hwpcb + 24);
333
        break;
334
    case IPR_VIRBND:
335
        if (env->features & FEATURE_VIRBND)
336
            *valp = env->ipr[IPR_VIRBND];
337
        else
338
            ret = -1;
339
        break;
340
    case IPR_VPTB:
341
        *valp = env->ipr[IPR_VPTB];
342
        break;
343
    case IPR_WHAMI:
344
        *valp = env->ipr[IPR_WHAMI];
345
        break;
346
    default:
347
        /* Invalid */
348
        ret = -1;
349
        break;
350
    }
351

    
352
    return ret;
353
}
354

    
355
int cpu_alpha_mtpr (CPUState *env, int iprn, uint64_t val, uint64_t *oldvalp)
356
{
357
    uint64_t hwpcb, tmp64;
358
    uint8_t tmp8;
359
    int ret = 0;
360

    
361
    hwpcb = env->ipr[IPR_PCBB];
362
    switch (iprn) {
363
    case IPR_ASN:
364
        /* Read-only */
365
        ret = -1;
366
        break;
367
    case IPR_ASTEN:
368
        tmp8 = ((int8_t)(env->ipr[IPR_ASTEN] << 4)) >> 4;
369
        *oldvalp = tmp8;
370
        tmp8 &= val & 0xF;
371
        tmp8 |= (val >> 4) & 0xF;
372
        env->ipr[IPR_ASTEN] &= ~0xF;
373
        env->ipr[IPR_ASTEN] |= tmp8;
374
        ret = 1;
375
        break;
376
    case IPR_ASTSR:
377
        tmp8 = ((int8_t)(env->ipr[IPR_ASTSR] << 4)) >> 4;
378
        *oldvalp = tmp8;
379
        tmp8 &= val & 0xF;
380
        tmp8 |= (val >> 4) & 0xF;
381
        env->ipr[IPR_ASTSR] &= ~0xF;
382
        env->ipr[IPR_ASTSR] |= tmp8;
383
        ret = 1;
384
    case IPR_DATFX:
385
        env->ipr[IPR_DATFX] &= ~0x1;
386
        env->ipr[IPR_DATFX] |= val & 1;
387
        tmp64 = ldq_raw(hwpcb + 56);
388
        tmp64 &= ~0x8000000000000000ULL;
389
        tmp64 |= (val & 1) << 63;
390
        stq_raw(hwpcb + 56, tmp64);
391
        break;
392
    case IPR_ESP:
393
        if (env->features & FEATURE_SPS)
394
            env->ipr[IPR_ESP] = val;
395
        else
396
            stq_raw(hwpcb + 8, val);
397
        break;
398
    case IPR_FEN:
399
        env->ipr[IPR_FEN] = val & 1;
400
        tmp64 = ldq_raw(hwpcb + 56);
401
        tmp64 &= ~1;
402
        tmp64 |= val & 1;
403
        stq_raw(hwpcb + 56, tmp64);
404
        break;
405
    case IPR_IPIR:
406
        /* XXX: TODO: Send IRQ to CPU #ir[16] */
407
        break;
408
    case IPR_IPL:
409
        *oldvalp = ((int64_t)(env->ipr[IPR_IPL] << 59)) >> 59;
410
        env->ipr[IPR_IPL] &= ~0x1F;
411
        env->ipr[IPR_IPL] |= val & 0x1F;
412
        /* XXX: may issue an interrupt or ASR _now_ */
413
        ret = 1;
414
        break;
415
    case IPR_KSP:
416
        if (!(env->ipr[IPR_EXC_ADDR] & 1)) {
417
            ret = -1;
418
        } else {
419
            if (env->features & FEATURE_SPS)
420
                env->ipr[IPR_KSP] = val;
421
            else
422
                stq_raw(hwpcb + 0, val);
423
        }
424
        break;
425
    case IPR_MCES:
426
        env->ipr[IPR_MCES] &= ~((val & 0x7) | 0x18);
427
        env->ipr[IPR_MCES] |= val & 0x18;
428
        break;
429
    case IPR_PERFMON:
430
        /* Implementation specific */
431
        *oldvalp = 0;
432
        ret = 1;
433
        break;
434
    case IPR_PCBB:
435
        /* Read-only */
436
        ret = -1;
437
        break;
438
    case IPR_PRBR:
439
        env->ipr[IPR_PRBR] = val;
440
        break;
441
    case IPR_PTBR:
442
        /* Read-only */
443
        ret = -1;
444
        break;
445
    case IPR_SCBB:
446
        env->ipr[IPR_SCBB] = (uint32_t)val;
447
        break;
448
    case IPR_SIRR:
449
        if (val & 0xF) {
450
            env->ipr[IPR_SISR] |= 1 << (val & 0xF);
451
            /* XXX: request a software interrupt _now_ */
452
        }
453
        break;
454
    case IPR_SISR:
455
        /* Read-only */
456
        ret = -1;
457
        break;
458
    case IPR_SSP:
459
        if (env->features & FEATURE_SPS)
460
            env->ipr[IPR_SSP] = val;
461
        else
462
            stq_raw(hwpcb + 16, val);
463
        break;
464
    case IPR_SYSPTBR:
465
        if (env->features & FEATURE_VIRBND)
466
            env->ipr[IPR_SYSPTBR] = val;
467
        else
468
            ret = -1;
469
        break;
470
    case IPR_TBCHK:
471
        /* Read-only */
472
        ret = -1;
473
        break;
474
    case IPR_TBIA:
475
        tlb_flush(env, 1);
476
        break;
477
    case IPR_TBIAP:
478
        tlb_flush(env, 1);
479
        break;
480
    case IPR_TBIS:
481
        tlb_flush_page(env, val);
482
        break;
483
    case IPR_TBISD:
484
        tlb_flush_page(env, val);
485
        break;
486
    case IPR_TBISI:
487
        tlb_flush_page(env, val);
488
        break;
489
    case IPR_USP:
490
        if (env->features & FEATURE_SPS)
491
            env->ipr[IPR_USP] = val;
492
        else
493
            stq_raw(hwpcb + 24, val);
494
        break;
495
    case IPR_VIRBND:
496
        if (env->features & FEATURE_VIRBND)
497
            env->ipr[IPR_VIRBND] = val;
498
        else
499
            ret = -1;
500
        break;
501
    case IPR_VPTB:
502
        env->ipr[IPR_VPTB] = val;
503
        break;
504
    case IPR_WHAMI:
505
        /* Read-only */
506
        ret = -1;
507
        break;
508
    default:
509
        /* Invalid */
510
        ret = -1;
511
        break;
512
    }
513

    
514
    return ret;
515
}
516

    
517
void do_interrupt (CPUState *env)
518
{
519
    int excp;
520

    
521
    env->ipr[IPR_EXC_ADDR] = env->pc | 1;
522
    excp = env->exception_index;
523
    env->exception_index = -1;
524
    env->error_code = 0;
525
    /* XXX: disable interrupts and memory mapping */
526
    if (env->ipr[IPR_PAL_BASE] != -1ULL) {
527
        /* We use native PALcode */
528
        env->pc = env->ipr[IPR_PAL_BASE] + excp;
529
    } else {
530
        /* We use emulated PALcode */
531
        abort();
532
        /* Emulate REI */
533
        env->pc = env->ipr[IPR_EXC_ADDR] & ~7;
534
        env->ipr[IPR_EXC_ADDR] = env->ipr[IPR_EXC_ADDR] & 1;
535
        /* XXX: re-enable interrupts and memory mapping */
536
    }
537
}
538
#endif
539

    
540
void cpu_dump_state (CPUState *env, FILE *f, fprintf_function cpu_fprintf,
541
                     int flags)
542
{
543
    static const char *linux_reg_names[] = {
544
        "v0 ", "t0 ", "t1 ", "t2 ", "t3 ", "t4 ", "t5 ", "t6 ",
545
        "t7 ", "s0 ", "s1 ", "s2 ", "s3 ", "s4 ", "s5 ", "fp ",
546
        "a0 ", "a1 ", "a2 ", "a3 ", "a4 ", "a5 ", "t8 ", "t9 ",
547
        "t10", "t11", "ra ", "t12", "at ", "gp ", "sp ", "zero",
548
    };
549
    int i;
550

    
551
    cpu_fprintf(f, "     PC  " TARGET_FMT_lx "      PS  " TARGET_FMT_lx "\n",
552
                env->pc, env->ps);
553
    for (i = 0; i < 31; i++) {
554
        cpu_fprintf(f, "IR%02d %s " TARGET_FMT_lx " ", i,
555
                    linux_reg_names[i], env->ir[i]);
556
        if ((i % 3) == 2)
557
            cpu_fprintf(f, "\n");
558
    }
559

    
560
    cpu_fprintf(f, "lock_a   " TARGET_FMT_lx " lock_v   " TARGET_FMT_lx "\n",
561
                env->lock_addr, env->lock_value);
562

    
563
    for (i = 0; i < 31; i++) {
564
        cpu_fprintf(f, "FIR%02d    " TARGET_FMT_lx " ", i,
565
                    *((uint64_t *)(&env->fir[i])));
566
        if ((i % 3) == 2)
567
            cpu_fprintf(f, "\n");
568
    }
569
    cpu_fprintf(f, "\n");
570
}