Statistics
| Branch: | Revision:

root / target-alpha / helper.c @ b5f1aa64

History | View | Annotate | Download (5.3 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
    env->exception_index = EXCP_MMFAULT;
168
    env->trap_arg0 = address;
169
    return 1;
170
}
171

    
172
void do_interrupt (CPUState *env)
173
{
174
    env->exception_index = -1;
175
}
176

    
177
#else
178

    
179
target_phys_addr_t cpu_get_phys_page_debug (CPUState *env, target_ulong addr)
180
{
181
    return -1;
182
}
183

    
184
int cpu_alpha_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
185
                                int mmu_idx, int is_softmmu)
186
{
187
    return 0;
188
}
189

    
190
void do_interrupt (CPUState *env)
191
{
192
    abort();
193
}
194
#endif
195

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

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

    
216
    cpu_fprintf(f, "lock_a   " TARGET_FMT_lx " lock_v   " TARGET_FMT_lx "\n",
217
                env->lock_addr, env->lock_value);
218

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