Statistics
| Branch: | Revision:

root / target-unicore32 / helper.c @ 7267c094

History | View | Annotate | Download (10.8 kB)

1
/*
2
 * Copyright (C) 2010-2011 GUAN Xue-tao
3
 *
4
 * This program is free software; you can redistribute it and/or modify
5
 * it under the terms of the GNU General Public License version 2 as
6
 * published by the Free Software Foundation.
7
 */
8
#include <stdio.h>
9
#include <stdlib.h>
10
#include <string.h>
11

    
12
#include "cpu.h"
13
#include "gdbstub.h"
14
#include "helper.h"
15
#include "qemu-common.h"
16
#include "host-utils.h"
17

    
18
static inline void set_feature(CPUState *env, int feature)
19
{
20
    env->features |= feature;
21
}
22

    
23
struct uc32_cpu_t {
24
    uint32_t id;
25
    const char *name;
26
};
27

    
28
static const struct uc32_cpu_t uc32_cpu_names[] = {
29
    { UC32_CPUID_UCV2, "UniCore-II"},
30
    { UC32_CPUID_ANY, "any"},
31
    { 0, NULL}
32
};
33

    
34
/* return 0 if not found */
35
static uint32_t uc32_cpu_find_by_name(const char *name)
36
{
37
    int i;
38
    uint32_t id;
39

    
40
    id = 0;
41
    for (i = 0; uc32_cpu_names[i].name; i++) {
42
        if (strcmp(name, uc32_cpu_names[i].name) == 0) {
43
            id = uc32_cpu_names[i].id;
44
            break;
45
        }
46
    }
47
    return id;
48
}
49

    
50
CPUState *uc32_cpu_init(const char *cpu_model)
51
{
52
    CPUState *env;
53
    uint32_t id;
54
    static int inited = 1;
55

    
56
    env = g_malloc0(sizeof(CPUState));
57
    cpu_exec_init(env);
58

    
59
    id = uc32_cpu_find_by_name(cpu_model);
60
    switch (id) {
61
    case UC32_CPUID_UCV2:
62
        set_feature(env, UC32_HWCAP_CMOV);
63
        set_feature(env, UC32_HWCAP_UCF64);
64
        env->ucf64.xregs[UC32_UCF64_FPSCR] = 0;
65
        env->cp0.c0_cachetype = 0x1dd20d2;
66
        env->cp0.c1_sys = 0x00090078;
67
        break;
68
    case UC32_CPUID_ANY: /* For userspace emulation.  */
69
        set_feature(env, UC32_HWCAP_CMOV);
70
        set_feature(env, UC32_HWCAP_UCF64);
71
        break;
72
    default:
73
        cpu_abort(env, "Bad CPU ID: %x\n", id);
74
    }
75

    
76
    env->cpu_model_str = cpu_model;
77
    env->cp0.c0_cpuid = id;
78
    env->uncached_asr = ASR_MODE_USER;
79
    env->regs[31] = 0;
80

    
81
    if (inited) {
82
        inited = 0;
83
        uc32_translate_init();
84
    }
85

    
86
    tlb_flush(env, 1);
87
    qemu_init_vcpu(env);
88
    return env;
89
}
90

    
91
uint32_t HELPER(clo)(uint32_t x)
92
{
93
    return clo32(x);
94
}
95

    
96
uint32_t HELPER(clz)(uint32_t x)
97
{
98
    return clz32(x);
99
}
100

    
101
void do_interrupt(CPUState *env)
102
{
103
    env->exception_index = -1;
104
}
105

    
106
int uc32_cpu_handle_mmu_fault(CPUState *env, target_ulong address, int rw,
107
                              int mmu_idx)
108
{
109
    env->exception_index = UC32_EXCP_TRAP;
110
    env->cp0.c4_faultaddr = address;
111
    return 1;
112
}
113

    
114
/* These should probably raise undefined insn exceptions.  */
115
void HELPER(set_cp)(CPUState *env, uint32_t insn, uint32_t val)
116
{
117
    int op1 = (insn >> 8) & 0xf;
118
    cpu_abort(env, "cp%i insn %08x\n", op1, insn);
119
    return;
120
}
121

    
122
uint32_t HELPER(get_cp)(CPUState *env, uint32_t insn)
123
{
124
    int op1 = (insn >> 8) & 0xf;
125
    cpu_abort(env, "cp%i insn %08x\n", op1, insn);
126
    return 0;
127
}
128

    
129
void HELPER(set_cp0)(CPUState *env, uint32_t insn, uint32_t val)
130
{
131
    cpu_abort(env, "cp0 insn %08x\n", insn);
132
}
133

    
134
uint32_t HELPER(get_cp0)(CPUState *env, uint32_t insn)
135
{
136
    cpu_abort(env, "cp0 insn %08x\n", insn);
137
    return 0;
138
}
139

    
140
void switch_mode(CPUState *env, int mode)
141
{
142
    if (mode != ASR_MODE_USER) {
143
        cpu_abort(env, "Tried to switch out of user mode\n");
144
    }
145
}
146

    
147
void HELPER(set_r29_banked)(CPUState *env, uint32_t mode, uint32_t val)
148
{
149
    cpu_abort(env, "banked r29 write\n");
150
}
151

    
152
uint32_t HELPER(get_r29_banked)(CPUState *env, uint32_t mode)
153
{
154
    cpu_abort(env, "banked r29 read\n");
155
    return 0;
156
}
157

    
158
/* UniCore-F64 support.  We follow the convention used for F64 instrunctions:
159
   Single precition routines have a "s" suffix, double precision a
160
   "d" suffix.  */
161

    
162
/* Convert host exception flags to f64 form.  */
163
static inline int ucf64_exceptbits_from_host(int host_bits)
164
{
165
    int target_bits = 0;
166

    
167
    if (host_bits & float_flag_invalid) {
168
        target_bits |= UCF64_FPSCR_FLAG_INVALID;
169
    }
170
    if (host_bits & float_flag_divbyzero) {
171
        target_bits |= UCF64_FPSCR_FLAG_DIVZERO;
172
    }
173
    if (host_bits & float_flag_overflow) {
174
        target_bits |= UCF64_FPSCR_FLAG_OVERFLOW;
175
    }
176
    if (host_bits & float_flag_underflow) {
177
        target_bits |= UCF64_FPSCR_FLAG_UNDERFLOW;
178
    }
179
    if (host_bits & float_flag_inexact) {
180
        target_bits |= UCF64_FPSCR_FLAG_INEXACT;
181
    }
182
    return target_bits;
183
}
184

    
185
uint32_t HELPER(ucf64_get_fpscr)(CPUState *env)
186
{
187
    int i;
188
    uint32_t fpscr;
189

    
190
    fpscr = (env->ucf64.xregs[UC32_UCF64_FPSCR] & UCF64_FPSCR_MASK);
191
    i = get_float_exception_flags(&env->ucf64.fp_status);
192
    fpscr |= ucf64_exceptbits_from_host(i);
193
    return fpscr;
194
}
195

    
196
/* Convert ucf64 exception flags to target form.  */
197
static inline int ucf64_exceptbits_to_host(int target_bits)
198
{
199
    int host_bits = 0;
200

    
201
    if (target_bits & UCF64_FPSCR_FLAG_INVALID) {
202
        host_bits |= float_flag_invalid;
203
    }
204
    if (target_bits & UCF64_FPSCR_FLAG_DIVZERO) {
205
        host_bits |= float_flag_divbyzero;
206
    }
207
    if (target_bits & UCF64_FPSCR_FLAG_OVERFLOW) {
208
        host_bits |= float_flag_overflow;
209
    }
210
    if (target_bits & UCF64_FPSCR_FLAG_UNDERFLOW) {
211
        host_bits |= float_flag_underflow;
212
    }
213
    if (target_bits & UCF64_FPSCR_FLAG_INEXACT) {
214
        host_bits |= float_flag_inexact;
215
    }
216
    return host_bits;
217
}
218

    
219
void HELPER(ucf64_set_fpscr)(CPUState *env, uint32_t val)
220
{
221
    int i;
222
    uint32_t changed;
223

    
224
    changed = env->ucf64.xregs[UC32_UCF64_FPSCR];
225
    env->ucf64.xregs[UC32_UCF64_FPSCR] = (val & UCF64_FPSCR_MASK);
226

    
227
    changed ^= val;
228
    if (changed & (UCF64_FPSCR_RND_MASK)) {
229
        i = UCF64_FPSCR_RND(val);
230
        switch (i) {
231
        case 0:
232
            i = float_round_nearest_even;
233
            break;
234
        case 1:
235
            i = float_round_to_zero;
236
            break;
237
        case 2:
238
            i = float_round_up;
239
            break;
240
        case 3:
241
            i = float_round_down;
242
            break;
243
        default: /* 100 and 101 not implement */
244
            cpu_abort(env, "Unsupported UniCore-F64 round mode");
245
        }
246
        set_float_rounding_mode(i, &env->ucf64.fp_status);
247
    }
248

    
249
    i = ucf64_exceptbits_to_host(UCF64_FPSCR_TRAPEN(val));
250
    set_float_exception_flags(i, &env->ucf64.fp_status);
251
}
252

    
253
float32 HELPER(ucf64_adds)(float32 a, float32 b, CPUState *env)
254
{
255
    return float32_add(a, b, &env->ucf64.fp_status);
256
}
257

    
258
float64 HELPER(ucf64_addd)(float64 a, float64 b, CPUState *env)
259
{
260
    return float64_add(a, b, &env->ucf64.fp_status);
261
}
262

    
263
float32 HELPER(ucf64_subs)(float32 a, float32 b, CPUState *env)
264
{
265
    return float32_sub(a, b, &env->ucf64.fp_status);
266
}
267

    
268
float64 HELPER(ucf64_subd)(float64 a, float64 b, CPUState *env)
269
{
270
    return float64_sub(a, b, &env->ucf64.fp_status);
271
}
272

    
273
float32 HELPER(ucf64_muls)(float32 a, float32 b, CPUState *env)
274
{
275
    return float32_mul(a, b, &env->ucf64.fp_status);
276
}
277

    
278
float64 HELPER(ucf64_muld)(float64 a, float64 b, CPUState *env)
279
{
280
    return float64_mul(a, b, &env->ucf64.fp_status);
281
}
282

    
283
float32 HELPER(ucf64_divs)(float32 a, float32 b, CPUState *env)
284
{
285
    return float32_div(a, b, &env->ucf64.fp_status);
286
}
287

    
288
float64 HELPER(ucf64_divd)(float64 a, float64 b, CPUState *env)
289
{
290
    return float64_div(a, b, &env->ucf64.fp_status);
291
}
292

    
293
float32 HELPER(ucf64_negs)(float32 a)
294
{
295
    return float32_chs(a);
296
}
297

    
298
float64 HELPER(ucf64_negd)(float64 a)
299
{
300
    return float64_chs(a);
301
}
302

    
303
float32 HELPER(ucf64_abss)(float32 a)
304
{
305
    return float32_abs(a);
306
}
307

    
308
float64 HELPER(ucf64_absd)(float64 a)
309
{
310
    return float64_abs(a);
311
}
312

    
313
/* XXX: check quiet/signaling case */
314
void HELPER(ucf64_cmps)(float32 a, float32 b, uint32_t c, CPUState *env)
315
{
316
    int flag;
317
    flag = float32_compare_quiet(a, b, &env->ucf64.fp_status);
318
    env->CF = 0;
319
    switch (c & 0x7) {
320
    case 0: /* F */
321
        break;
322
    case 1: /* UN */
323
        if (flag == 2) {
324
            env->CF = 1;
325
        }
326
        break;
327
    case 2: /* EQ */
328
        if (flag == 0) {
329
            env->CF = 1;
330
        }
331
        break;
332
    case 3: /* UEQ */
333
        if ((flag == 0) || (flag == 2)) {
334
            env->CF = 1;
335
        }
336
        break;
337
    case 4: /* OLT */
338
        if (flag == -1) {
339
            env->CF = 1;
340
        }
341
        break;
342
    case 5: /* ULT */
343
        if ((flag == -1) || (flag == 2)) {
344
            env->CF = 1;
345
        }
346
        break;
347
    case 6: /* OLE */
348
        if ((flag == -1) || (flag == 0)) {
349
            env->CF = 1;
350
        }
351
        break;
352
    case 7: /* ULE */
353
        if (flag != 1) {
354
            env->CF = 1;
355
        }
356
        break;
357
    }
358
    env->ucf64.xregs[UC32_UCF64_FPSCR] = (env->CF << 29)
359
                    | (env->ucf64.xregs[UC32_UCF64_FPSCR] & 0x0fffffff);
360
}
361

    
362
void HELPER(ucf64_cmpd)(float64 a, float64 b, uint32_t c, CPUState *env)
363
{
364
    int flag;
365
    flag = float64_compare_quiet(a, b, &env->ucf64.fp_status);
366
    env->CF = 0;
367
    switch (c & 0x7) {
368
    case 0: /* F */
369
        break;
370
    case 1: /* UN */
371
        if (flag == 2) {
372
            env->CF = 1;
373
        }
374
        break;
375
    case 2: /* EQ */
376
        if (flag == 0) {
377
            env->CF = 1;
378
        }
379
        break;
380
    case 3: /* UEQ */
381
        if ((flag == 0) || (flag == 2)) {
382
            env->CF = 1;
383
        }
384
        break;
385
    case 4: /* OLT */
386
        if (flag == -1) {
387
            env->CF = 1;
388
        }
389
        break;
390
    case 5: /* ULT */
391
        if ((flag == -1) || (flag == 2)) {
392
            env->CF = 1;
393
        }
394
        break;
395
    case 6: /* OLE */
396
        if ((flag == -1) || (flag == 0)) {
397
            env->CF = 1;
398
        }
399
        break;
400
    case 7: /* ULE */
401
        if (flag != 1) {
402
            env->CF = 1;
403
        }
404
        break;
405
    }
406
    env->ucf64.xregs[UC32_UCF64_FPSCR] = (env->CF << 29)
407
                    | (env->ucf64.xregs[UC32_UCF64_FPSCR] & 0x0fffffff);
408
}
409

    
410
/* Helper routines to perform bitwise copies between float and int.  */
411
static inline float32 ucf64_itos(uint32_t i)
412
{
413
    union {
414
        uint32_t i;
415
        float32 s;
416
    } v;
417

    
418
    v.i = i;
419
    return v.s;
420
}
421

    
422
static inline uint32_t ucf64_stoi(float32 s)
423
{
424
    union {
425
        uint32_t i;
426
        float32 s;
427
    } v;
428

    
429
    v.s = s;
430
    return v.i;
431
}
432

    
433
static inline float64 ucf64_itod(uint64_t i)
434
{
435
    union {
436
        uint64_t i;
437
        float64 d;
438
    } v;
439

    
440
    v.i = i;
441
    return v.d;
442
}
443

    
444
static inline uint64_t ucf64_dtoi(float64 d)
445
{
446
    union {
447
        uint64_t i;
448
        float64 d;
449
    } v;
450

    
451
    v.d = d;
452
    return v.i;
453
}
454

    
455
/* Integer to float conversion.  */
456
float32 HELPER(ucf64_si2sf)(float32 x, CPUState *env)
457
{
458
    return int32_to_float32(ucf64_stoi(x), &env->ucf64.fp_status);
459
}
460

    
461
float64 HELPER(ucf64_si2df)(float32 x, CPUState *env)
462
{
463
    return int32_to_float64(ucf64_stoi(x), &env->ucf64.fp_status);
464
}
465

    
466
/* Float to integer conversion.  */
467
float32 HELPER(ucf64_sf2si)(float32 x, CPUState *env)
468
{
469
    return ucf64_itos(float32_to_int32(x, &env->ucf64.fp_status));
470
}
471

    
472
float32 HELPER(ucf64_df2si)(float64 x, CPUState *env)
473
{
474
    return ucf64_itos(float64_to_int32(x, &env->ucf64.fp_status));
475
}
476

    
477
/* floating point conversion */
478
float64 HELPER(ucf64_sf2df)(float32 x, CPUState *env)
479
{
480
    return float32_to_float64(x, &env->ucf64.fp_status);
481
}
482

    
483
float32 HELPER(ucf64_df2sf)(float64 x, CPUState *env)
484
{
485
    return float64_to_float32(x, &env->ucf64.fp_status);
486
}