Statistics
| Branch: | Revision:

root / target-alpha / helper.c @ c227f099

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, 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

    
27
#if defined(CONFIG_USER_ONLY)
28

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

    
38
    return 1;
39
}
40

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

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

    
51
#else
52

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

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

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

    
80
    return 1;
81
}
82

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

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

    
222
    return ret;
223
}
224

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

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

    
383
    return ret;
384
}
385

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

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

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

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