Statistics
| Branch: | Revision:

root / target-alpha / helper.c @ 8bb6e981

History | View | Annotate | Download (11.1 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, write to the Free Software
18
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19
 */
20

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

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

    
28
#if defined(CONFIG_USER_ONLY)
29

    
30
int cpu_alpha_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
31
                                int mmu_idx, int is_softmmu)
32
{
33
    if (rw == 2)
34
        env->exception_index = EXCP_ITB_MISS;
35
    else
36
        env->exception_index = EXCP_DFAULT;
37
    env->ipr[IPR_EXC_ADDR] = address;
38

    
39
    return 1;
40
}
41

    
42
target_phys_addr_t cpu_get_phys_page_debug (CPUState *env, target_ulong addr)
43
{
44
    return addr;
45
}
46

    
47
void do_interrupt (CPUState *env)
48
{
49
    env->exception_index = -1;
50
}
51

    
52
#else
53

    
54
target_phys_addr_t cpu_get_phys_page_debug (CPUState *env, target_ulong addr)
55
{
56
    return -1;
57
}
58

    
59
int cpu_alpha_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
60
                                int mmu_idx, int is_softmmu)
61
{
62
    uint32_t opc;
63

    
64
    if (rw == 2) {
65
        /* Instruction translation buffer miss */
66
        env->exception_index = EXCP_ITB_MISS;
67
    } else {
68
        if (env->ipr[IPR_EXC_ADDR] & 1)
69
            env->exception_index = EXCP_DTB_MISS_PAL;
70
        else
71
            env->exception_index = EXCP_DTB_MISS_NATIVE;
72
        opc = (ldl_code(env->pc) >> 21) << 4;
73
        if (rw) {
74
            opc |= 0x9;
75
        } else {
76
            opc |= 0x4;
77
        }
78
        env->ipr[IPR_MM_STAT] = opc;
79
    }
80

    
81
    return 1;
82
}
83

    
84
int cpu_alpha_mfpr (CPUState *env, int iprn, uint64_t *valp)
85
{
86
    uint64_t hwpcb;
87
    int ret = 0;
88

    
89
    hwpcb = env->ipr[IPR_PCBB];
90
    switch (iprn) {
91
    case IPR_ASN:
92
        if (env->features & FEATURE_ASN)
93
            *valp = env->ipr[IPR_ASN];
94
        else
95
            *valp = 0;
96
        break;
97
    case IPR_ASTEN:
98
        *valp = ((int64_t)(env->ipr[IPR_ASTEN] << 60)) >> 60;
99
        break;
100
    case IPR_ASTSR:
101
        *valp = ((int64_t)(env->ipr[IPR_ASTSR] << 60)) >> 60;
102
        break;
103
    case IPR_DATFX:
104
        /* Write only */
105
        ret = -1;
106
        break;
107
    case IPR_ESP:
108
        if (env->features & FEATURE_SPS)
109
            *valp = env->ipr[IPR_ESP];
110
        else
111
            *valp = ldq_raw(hwpcb + 8);
112
        break;
113
    case IPR_FEN:
114
        *valp = ((int64_t)(env->ipr[IPR_FEN] << 63)) >> 63;
115
        break;
116
    case IPR_IPIR:
117
        /* Write-only */
118
        ret = -1;
119
        break;
120
    case IPR_IPL:
121
        *valp = ((int64_t)(env->ipr[IPR_IPL] << 59)) >> 59;
122
        break;
123
    case IPR_KSP:
124
        if (!(env->ipr[IPR_EXC_ADDR] & 1)) {
125
            ret = -1;
126
        } else {
127
            if (env->features & FEATURE_SPS)
128
                *valp = env->ipr[IPR_KSP];
129
            else
130
                *valp = ldq_raw(hwpcb + 0);
131
        }
132
        break;
133
    case IPR_MCES:
134
        *valp = ((int64_t)(env->ipr[IPR_MCES] << 59)) >> 59;
135
        break;
136
    case IPR_PERFMON:
137
        /* Implementation specific */
138
        *valp = 0;
139
        break;
140
    case IPR_PCBB:
141
        *valp = ((int64_t)env->ipr[IPR_PCBB] << 16) >> 16;
142
        break;
143
    case IPR_PRBR:
144
        *valp = env->ipr[IPR_PRBR];
145
        break;
146
    case IPR_PTBR:
147
        *valp = env->ipr[IPR_PTBR];
148
        break;
149
    case IPR_SCBB:
150
        *valp = (int64_t)((int32_t)env->ipr[IPR_SCBB]);
151
        break;
152
    case IPR_SIRR:
153
        /* Write-only */
154
        ret = -1;
155
        break;
156
    case IPR_SISR:
157
        *valp = (int64_t)((int16_t)env->ipr[IPR_SISR]);
158
    case IPR_SSP:
159
        if (env->features & FEATURE_SPS)
160
            *valp = env->ipr[IPR_SSP];
161
        else
162
            *valp = ldq_raw(hwpcb + 16);
163
        break;
164
    case IPR_SYSPTBR:
165
        if (env->features & FEATURE_VIRBND)
166
            *valp = env->ipr[IPR_SYSPTBR];
167
        else
168
            ret = -1;
169
        break;
170
    case IPR_TBCHK:
171
        if ((env->features & FEATURE_TBCHK)) {
172
            /* XXX: TODO */
173
            *valp = 0;
174
            ret = -1;
175
        } else {
176
            ret = -1;
177
        }
178
        break;
179
    case IPR_TBIA:
180
        /* Write-only */
181
        ret = -1;
182
        break;
183
    case IPR_TBIAP:
184
        /* Write-only */
185
        ret = -1;
186
        break;
187
    case IPR_TBIS:
188
        /* Write-only */
189
        ret = -1;
190
        break;
191
    case IPR_TBISD:
192
        /* Write-only */
193
        ret = -1;
194
        break;
195
    case IPR_TBISI:
196
        /* Write-only */
197
        ret = -1;
198
        break;
199
    case IPR_USP:
200
        if (env->features & FEATURE_SPS)
201
            *valp = env->ipr[IPR_USP];
202
        else
203
            *valp = ldq_raw(hwpcb + 24);
204
        break;
205
    case IPR_VIRBND:
206
        if (env->features & FEATURE_VIRBND)
207
            *valp = env->ipr[IPR_VIRBND];
208
        else
209
            ret = -1;
210
        break;
211
    case IPR_VPTB:
212
        *valp = env->ipr[IPR_VPTB];
213
        break;
214
    case IPR_WHAMI:
215
        *valp = env->ipr[IPR_WHAMI];
216
        break;
217
    default:
218
        /* Invalid */
219
        ret = -1;
220
        break;
221
    }
222

    
223
    return ret;
224
}
225

    
226
int cpu_alpha_mtpr (CPUState *env, int iprn, uint64_t val, uint64_t *oldvalp)
227
{
228
    uint64_t hwpcb, tmp64;
229
    uint8_t tmp8;
230
    int ret = 0;
231

    
232
    hwpcb = env->ipr[IPR_PCBB];
233
    switch (iprn) {
234
    case IPR_ASN:
235
        /* Read-only */
236
        ret = -1;
237
        break;
238
    case IPR_ASTEN:
239
        tmp8 = ((int8_t)(env->ipr[IPR_ASTEN] << 4)) >> 4;
240
        *oldvalp = tmp8;
241
        tmp8 &= val & 0xF;
242
        tmp8 |= (val >> 4) & 0xF;
243
        env->ipr[IPR_ASTEN] &= ~0xF;
244
        env->ipr[IPR_ASTEN] |= tmp8;
245
        ret = 1;
246
        break;
247
    case IPR_ASTSR:
248
        tmp8 = ((int8_t)(env->ipr[IPR_ASTSR] << 4)) >> 4;
249
        *oldvalp = tmp8;
250
        tmp8 &= val & 0xF;
251
        tmp8 |= (val >> 4) & 0xF;
252
        env->ipr[IPR_ASTSR] &= ~0xF;
253
        env->ipr[IPR_ASTSR] |= tmp8;
254
        ret = 1;
255
    case IPR_DATFX:
256
        env->ipr[IPR_DATFX] &= ~0x1;
257
        env->ipr[IPR_DATFX] |= val & 1;
258
        tmp64 = ldq_raw(hwpcb + 56);
259
        tmp64 &= ~0x8000000000000000ULL;
260
        tmp64 |= (val & 1) << 63;
261
        stq_raw(hwpcb + 56, tmp64);
262
        break;
263
    case IPR_ESP:
264
        if (env->features & FEATURE_SPS)
265
            env->ipr[IPR_ESP] = val;
266
        else
267
            stq_raw(hwpcb + 8, val);
268
        break;
269
    case IPR_FEN:
270
        env->ipr[IPR_FEN] = val & 1;
271
        tmp64 = ldq_raw(hwpcb + 56);
272
        tmp64 &= ~1;
273
        tmp64 |= val & 1;
274
        stq_raw(hwpcb + 56, tmp64);
275
        break;
276
    case IPR_IPIR:
277
        /* XXX: TODO: Send IRQ to CPU #ir[16] */
278
        break;
279
    case IPR_IPL:
280
        *oldvalp = ((int64_t)(env->ipr[IPR_IPL] << 59)) >> 59;
281
        env->ipr[IPR_IPL] &= ~0x1F;
282
        env->ipr[IPR_IPL] |= val & 0x1F;
283
        /* XXX: may issue an interrupt or ASR _now_ */
284
        ret = 1;
285
        break;
286
    case IPR_KSP:
287
        if (!(env->ipr[IPR_EXC_ADDR] & 1)) {
288
            ret = -1;
289
        } else {
290
            if (env->features & FEATURE_SPS)
291
                env->ipr[IPR_KSP] = val;
292
            else
293
                stq_raw(hwpcb + 0, val);
294
        }
295
        break;
296
    case IPR_MCES:
297
        env->ipr[IPR_MCES] &= ~((val & 0x7) | 0x18);
298
        env->ipr[IPR_MCES] |= val & 0x18;
299
        break;
300
    case IPR_PERFMON:
301
        /* Implementation specific */
302
        *oldvalp = 0;
303
        ret = 1;
304
        break;
305
    case IPR_PCBB:
306
        /* Read-only */
307
        ret = -1;
308
        break;
309
    case IPR_PRBR:
310
        env->ipr[IPR_PRBR] = val;
311
        break;
312
    case IPR_PTBR:
313
        /* Read-only */
314
        ret = -1;
315
        break;
316
    case IPR_SCBB:
317
        env->ipr[IPR_SCBB] = (uint32_t)val;
318
        break;
319
    case IPR_SIRR:
320
        if (val & 0xF) {
321
            env->ipr[IPR_SISR] |= 1 << (val & 0xF);
322
            /* XXX: request a software interrupt _now_ */
323
        }
324
        break;
325
    case IPR_SISR:
326
        /* Read-only */
327
        ret = -1;
328
        break;
329
    case IPR_SSP:
330
        if (env->features & FEATURE_SPS)
331
            env->ipr[IPR_SSP] = val;
332
        else
333
            stq_raw(hwpcb + 16, val);
334
        break;
335
    case IPR_SYSPTBR:
336
        if (env->features & FEATURE_VIRBND)
337
            env->ipr[IPR_SYSPTBR] = val;
338
        else
339
            ret = -1;
340
    case IPR_TBCHK:
341
        /* Read-only */
342
        ret = -1;
343
        break;
344
    case IPR_TBIA:
345
        tlb_flush(env, 1);
346
        break;
347
    case IPR_TBIAP:
348
        tlb_flush(env, 1);
349
        break;
350
    case IPR_TBIS:
351
        tlb_flush_page(env, val);
352
        break;
353
    case IPR_TBISD:
354
        tlb_flush_page(env, val);
355
        break;
356
    case IPR_TBISI:
357
        tlb_flush_page(env, val);
358
        break;
359
    case IPR_USP:
360
        if (env->features & FEATURE_SPS)
361
            env->ipr[IPR_USP] = val;
362
        else
363
            stq_raw(hwpcb + 24, val);
364
        break;
365
    case IPR_VIRBND:
366
        if (env->features & FEATURE_VIRBND)
367
            env->ipr[IPR_VIRBND] = val;
368
        else
369
            ret = -1;
370
        break;
371
    case IPR_VPTB:
372
        env->ipr[IPR_VPTB] = val;
373
        break;
374
    case IPR_WHAMI:
375
        /* Read-only */
376
        ret = -1;
377
        break;
378
    default:
379
        /* Invalid */
380
        ret = -1;
381
        break;
382
    }
383

    
384
    return ret;
385
}
386

    
387
void do_interrupt (CPUState *env)
388
{
389
    int excp;
390

    
391
    env->ipr[IPR_EXC_ADDR] = env->pc | 1;
392
    excp = env->exception_index;
393
    env->exception_index = 0;
394
    env->error_code = 0;
395
    /* XXX: disable interrupts and memory mapping */
396
    if (env->ipr[IPR_PAL_BASE] != -1ULL) {
397
        /* We use native PALcode */
398
        env->pc = env->ipr[IPR_PAL_BASE] + excp;
399
    } else {
400
        /* We use emulated PALcode */
401
        call_pal(env);
402
        /* Emulate REI */
403
        env->pc = env->ipr[IPR_EXC_ADDR] & ~7;
404
        env->ipr[IPR_EXC_ADDR] = env->ipr[IPR_EXC_ADDR] & 1;
405
        /* XXX: re-enable interrupts and memory mapping */
406
    }
407
}
408
#endif
409

    
410
void cpu_dump_state (CPUState *env, FILE *f,
411
                     int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
412
                     int flags)
413
{
414
    static const char *linux_reg_names[] = {
415
        "v0 ", "t0 ", "t1 ", "t2 ", "t3 ", "t4 ", "t5 ", "t6 ",
416
        "t7 ", "s0 ", "s1 ", "s2 ", "s3 ", "s4 ", "s5 ", "fp ",
417
        "a0 ", "a1 ", "a2 ", "a3 ", "a4 ", "a5 ", "t8 ", "t9 ",
418
        "t10", "t11", "ra ", "t12", "at ", "gp ", "sp ", "zero",
419
    };
420
    int i;
421

    
422
    cpu_fprintf(f, "     PC  " TARGET_FMT_lx "      PS  " TARGET_FMT_lx "\n",
423
                env->pc, env->ps);
424
    for (i = 0; i < 31; i++) {
425
        cpu_fprintf(f, "IR%02d %s " TARGET_FMT_lx " ", i,
426
                    linux_reg_names[i], env->ir[i]);
427
        if ((i % 3) == 2)
428
            cpu_fprintf(f, "\n");
429
    }
430
    cpu_fprintf(f, "\n");
431
    for (i = 0; i < 31; i++) {
432
        cpu_fprintf(f, "FIR%02d    " TARGET_FMT_lx " ", i,
433
                    *((uint64_t *)(&env->fir[i])));
434
        if ((i % 3) == 2)
435
            cpu_fprintf(f, "\n");
436
    }
437
}
438