Statistics
| Branch: | Revision:

root / target-unicore32 / helper.c @ 8141905a

History | View | Annotate | Download (10.7 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

    
9
#include "cpu.h"
10
#include "gdbstub.h"
11
#include "helper.h"
12
#include "host-utils.h"
13

    
14
static inline void set_feature(CPUState *env, int feature)
15
{
16
    env->features |= feature;
17
}
18

    
19
struct uc32_cpu_t {
20
    uint32_t id;
21
    const char *name;
22
};
23

    
24
static const struct uc32_cpu_t uc32_cpu_names[] = {
25
    { UC32_CPUID_UCV2, "UniCore-II"},
26
    { UC32_CPUID_ANY, "any"},
27
    { 0, NULL}
28
};
29

    
30
/* return 0 if not found */
31
static uint32_t uc32_cpu_find_by_name(const char *name)
32
{
33
    int i;
34
    uint32_t id;
35

    
36
    id = 0;
37
    for (i = 0; uc32_cpu_names[i].name; i++) {
38
        if (strcmp(name, uc32_cpu_names[i].name) == 0) {
39
            id = uc32_cpu_names[i].id;
40
            break;
41
        }
42
    }
43
    return id;
44
}
45

    
46
CPUState *uc32_cpu_init(const char *cpu_model)
47
{
48
    CPUState *env;
49
    uint32_t id;
50
    static int inited = 1;
51

    
52
    env = g_malloc0(sizeof(CPUState));
53
    cpu_exec_init(env);
54

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

    
72
    env->cpu_model_str = cpu_model;
73
    env->cp0.c0_cpuid = id;
74
    env->uncached_asr = ASR_MODE_USER;
75
    env->regs[31] = 0;
76

    
77
    if (inited) {
78
        inited = 0;
79
        uc32_translate_init();
80
    }
81

    
82
    tlb_flush(env, 1);
83
    qemu_init_vcpu(env);
84
    return env;
85
}
86

    
87
uint32_t HELPER(clo)(uint32_t x)
88
{
89
    return clo32(x);
90
}
91

    
92
uint32_t HELPER(clz)(uint32_t x)
93
{
94
    return clz32(x);
95
}
96

    
97
void do_interrupt(CPUState *env)
98
{
99
    env->exception_index = -1;
100
}
101

    
102
int uc32_cpu_handle_mmu_fault(CPUState *env, target_ulong address, int rw,
103
                              int mmu_idx)
104
{
105
    env->exception_index = UC32_EXCP_TRAP;
106
    env->cp0.c4_faultaddr = address;
107
    return 1;
108
}
109

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

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

    
125
void HELPER(set_cp0)(CPUState *env, uint32_t insn, uint32_t val)
126
{
127
    cpu_abort(env, "cp0 insn %08x\n", insn);
128
}
129

    
130
uint32_t HELPER(get_cp0)(CPUState *env, uint32_t insn)
131
{
132
    cpu_abort(env, "cp0 insn %08x\n", insn);
133
    return 0;
134
}
135

    
136
void switch_mode(CPUState *env, int mode)
137
{
138
    if (mode != ASR_MODE_USER) {
139
        cpu_abort(env, "Tried to switch out of user mode\n");
140
    }
141
}
142

    
143
void HELPER(set_r29_banked)(CPUState *env, uint32_t mode, uint32_t val)
144
{
145
    cpu_abort(env, "banked r29 write\n");
146
}
147

    
148
uint32_t HELPER(get_r29_banked)(CPUState *env, uint32_t mode)
149
{
150
    cpu_abort(env, "banked r29 read\n");
151
    return 0;
152
}
153

    
154
/* UniCore-F64 support.  We follow the convention used for F64 instrunctions:
155
   Single precition routines have a "s" suffix, double precision a
156
   "d" suffix.  */
157

    
158
/* Convert host exception flags to f64 form.  */
159
static inline int ucf64_exceptbits_from_host(int host_bits)
160
{
161
    int target_bits = 0;
162

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

    
181
uint32_t HELPER(ucf64_get_fpscr)(CPUState *env)
182
{
183
    int i;
184
    uint32_t fpscr;
185

    
186
    fpscr = (env->ucf64.xregs[UC32_UCF64_FPSCR] & UCF64_FPSCR_MASK);
187
    i = get_float_exception_flags(&env->ucf64.fp_status);
188
    fpscr |= ucf64_exceptbits_from_host(i);
189
    return fpscr;
190
}
191

    
192
/* Convert ucf64 exception flags to target form.  */
193
static inline int ucf64_exceptbits_to_host(int target_bits)
194
{
195
    int host_bits = 0;
196

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

    
215
void HELPER(ucf64_set_fpscr)(CPUState *env, uint32_t val)
216
{
217
    int i;
218
    uint32_t changed;
219

    
220
    changed = env->ucf64.xregs[UC32_UCF64_FPSCR];
221
    env->ucf64.xregs[UC32_UCF64_FPSCR] = (val & UCF64_FPSCR_MASK);
222

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

    
245
    i = ucf64_exceptbits_to_host(UCF64_FPSCR_TRAPEN(val));
246
    set_float_exception_flags(i, &env->ucf64.fp_status);
247
}
248

    
249
float32 HELPER(ucf64_adds)(float32 a, float32 b, CPUState *env)
250
{
251
    return float32_add(a, b, &env->ucf64.fp_status);
252
}
253

    
254
float64 HELPER(ucf64_addd)(float64 a, float64 b, CPUState *env)
255
{
256
    return float64_add(a, b, &env->ucf64.fp_status);
257
}
258

    
259
float32 HELPER(ucf64_subs)(float32 a, float32 b, CPUState *env)
260
{
261
    return float32_sub(a, b, &env->ucf64.fp_status);
262
}
263

    
264
float64 HELPER(ucf64_subd)(float64 a, float64 b, CPUState *env)
265
{
266
    return float64_sub(a, b, &env->ucf64.fp_status);
267
}
268

    
269
float32 HELPER(ucf64_muls)(float32 a, float32 b, CPUState *env)
270
{
271
    return float32_mul(a, b, &env->ucf64.fp_status);
272
}
273

    
274
float64 HELPER(ucf64_muld)(float64 a, float64 b, CPUState *env)
275
{
276
    return float64_mul(a, b, &env->ucf64.fp_status);
277
}
278

    
279
float32 HELPER(ucf64_divs)(float32 a, float32 b, CPUState *env)
280
{
281
    return float32_div(a, b, &env->ucf64.fp_status);
282
}
283

    
284
float64 HELPER(ucf64_divd)(float64 a, float64 b, CPUState *env)
285
{
286
    return float64_div(a, b, &env->ucf64.fp_status);
287
}
288

    
289
float32 HELPER(ucf64_negs)(float32 a)
290
{
291
    return float32_chs(a);
292
}
293

    
294
float64 HELPER(ucf64_negd)(float64 a)
295
{
296
    return float64_chs(a);
297
}
298

    
299
float32 HELPER(ucf64_abss)(float32 a)
300
{
301
    return float32_abs(a);
302
}
303

    
304
float64 HELPER(ucf64_absd)(float64 a)
305
{
306
    return float64_abs(a);
307
}
308

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

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

    
406
/* Helper routines to perform bitwise copies between float and int.  */
407
static inline float32 ucf64_itos(uint32_t i)
408
{
409
    union {
410
        uint32_t i;
411
        float32 s;
412
    } v;
413

    
414
    v.i = i;
415
    return v.s;
416
}
417

    
418
static inline uint32_t ucf64_stoi(float32 s)
419
{
420
    union {
421
        uint32_t i;
422
        float32 s;
423
    } v;
424

    
425
    v.s = s;
426
    return v.i;
427
}
428

    
429
static inline float64 ucf64_itod(uint64_t i)
430
{
431
    union {
432
        uint64_t i;
433
        float64 d;
434
    } v;
435

    
436
    v.i = i;
437
    return v.d;
438
}
439

    
440
static inline uint64_t ucf64_dtoi(float64 d)
441
{
442
    union {
443
        uint64_t i;
444
        float64 d;
445
    } v;
446

    
447
    v.d = d;
448
    return v.i;
449
}
450

    
451
/* Integer to float conversion.  */
452
float32 HELPER(ucf64_si2sf)(float32 x, CPUState *env)
453
{
454
    return int32_to_float32(ucf64_stoi(x), &env->ucf64.fp_status);
455
}
456

    
457
float64 HELPER(ucf64_si2df)(float32 x, CPUState *env)
458
{
459
    return int32_to_float64(ucf64_stoi(x), &env->ucf64.fp_status);
460
}
461

    
462
/* Float to integer conversion.  */
463
float32 HELPER(ucf64_sf2si)(float32 x, CPUState *env)
464
{
465
    return ucf64_itos(float32_to_int32(x, &env->ucf64.fp_status));
466
}
467

    
468
float32 HELPER(ucf64_df2si)(float64 x, CPUState *env)
469
{
470
    return ucf64_itos(float64_to_int32(x, &env->ucf64.fp_status));
471
}
472

    
473
/* floating point conversion */
474
float64 HELPER(ucf64_sf2df)(float32 x, CPUState *env)
475
{
476
    return float32_to_float64(x, &env->ucf64.fp_status);
477
}
478

    
479
float32 HELPER(ucf64_df2sf)(float64 x, CPUState *env)
480
{
481
    return float64_to_float32(x, &env->ucf64.fp_status);
482
}