Statistics
| Branch: | Revision:

root / target-alpha / helper.c @ 129d8aa5

History | View | Annotate | Download (5.4 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->trap_arg0 = address;
172
    return 1;
173
}
174

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

    
180
#else
181

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

    
187
int cpu_alpha_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
188
                                int mmu_idx, int is_softmmu)
189
{
190
    return 0;
191
}
192

    
193
void do_interrupt (CPUState *env)
194
{
195
    abort();
196
}
197
#endif
198

    
199
void cpu_dump_state (CPUState *env, FILE *f, fprintf_function cpu_fprintf,
200
                     int flags)
201
{
202
    static const char *linux_reg_names[] = {
203
        "v0 ", "t0 ", "t1 ", "t2 ", "t3 ", "t4 ", "t5 ", "t6 ",
204
        "t7 ", "s0 ", "s1 ", "s2 ", "s3 ", "s4 ", "s5 ", "fp ",
205
        "a0 ", "a1 ", "a2 ", "a3 ", "a4 ", "a5 ", "t8 ", "t9 ",
206
        "t10", "t11", "ra ", "t12", "at ", "gp ", "sp ", "zero",
207
    };
208
    int i;
209

    
210
    cpu_fprintf(f, "     PC  " TARGET_FMT_lx "      PS  %02x\n",
211
                env->pc, env->ps);
212
    for (i = 0; i < 31; i++) {
213
        cpu_fprintf(f, "IR%02d %s " TARGET_FMT_lx " ", i,
214
                    linux_reg_names[i], env->ir[i]);
215
        if ((i % 3) == 2)
216
            cpu_fprintf(f, "\n");
217
    }
218

    
219
    cpu_fprintf(f, "lock_a   " TARGET_FMT_lx " lock_v   " TARGET_FMT_lx "\n",
220
                env->lock_addr, env->lock_value);
221

    
222
    for (i = 0; i < 31; i++) {
223
        cpu_fprintf(f, "FIR%02d    " TARGET_FMT_lx " ", i,
224
                    *((uint64_t *)(&env->fir[i])));
225
        if ((i % 3) == 2)
226
            cpu_fprintf(f, "\n");
227
    }
228
    cpu_fprintf(f, "\n");
229
}