Statistics
| Branch: | Revision:

root / target-unicore32 / helper.c @ 51fb256a

History | View | Annotate | Download (6.1 kB)

1
/*
2
 * Copyright (C) 2010-2012 Guan Xuetao
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
 * Contributions from 2012-04-01 on are considered under GPL version 2,
9
 * or (at your option) any later version.
10
 */
11

    
12
#include "cpu.h"
13
#include "exec/gdbstub.h"
14
#include "helper.h"
15
#include "qemu/host-utils.h"
16
#ifndef CONFIG_USER_ONLY
17
#include "ui/console.h"
18
#endif
19

    
20
#undef DEBUG_UC32
21

    
22
#ifdef DEBUG_UC32
23
#define DPRINTF(fmt, ...) printf("%s: " fmt , __func__, ## __VA_ARGS__)
24
#else
25
#define DPRINTF(fmt, ...) do {} while (0)
26
#endif
27

    
28
CPUUniCore32State *uc32_cpu_init(const char *cpu_model)
29
{
30
    UniCore32CPU *cpu;
31
    CPUUniCore32State *env;
32
    ObjectClass *oc;
33

    
34
    oc = cpu_class_by_name(TYPE_UNICORE32_CPU, cpu_model);
35
    if (oc == NULL) {
36
        return NULL;
37
    }
38
    cpu = UNICORE32_CPU(object_new(object_class_get_name(oc)));
39
    env = &cpu->env;
40

    
41
    object_property_set_bool(OBJECT(cpu), true, "realized", NULL);
42

    
43
    return env;
44
}
45

    
46
uint32_t HELPER(clo)(uint32_t x)
47
{
48
    return clo32(x);
49
}
50

    
51
uint32_t HELPER(clz)(uint32_t x)
52
{
53
    return clz32(x);
54
}
55

    
56
#ifndef CONFIG_USER_ONLY
57
void helper_cp0_set(CPUUniCore32State *env, uint32_t val, uint32_t creg,
58
        uint32_t cop)
59
{
60
    /*
61
     * movc pp.nn, rn, #imm9
62
     *      rn: UCOP_REG_D
63
     *      nn: UCOP_REG_N
64
     *          1: sys control reg.
65
     *          2: page table base reg.
66
     *          3: data fault status reg.
67
     *          4: insn fault status reg.
68
     *          5: cache op. reg.
69
     *          6: tlb op. reg.
70
     *      imm9: split UCOP_IMM10 with bit5 is 0
71
     */
72
    switch (creg) {
73
    case 1:
74
        if (cop != 0) {
75
            goto unrecognized;
76
        }
77
        env->cp0.c1_sys = val;
78
        break;
79
    case 2:
80
        if (cop != 0) {
81
            goto unrecognized;
82
        }
83
        env->cp0.c2_base = val;
84
        break;
85
    case 3:
86
        if (cop != 0) {
87
            goto unrecognized;
88
        }
89
        env->cp0.c3_faultstatus = val;
90
        break;
91
    case 4:
92
        if (cop != 0) {
93
            goto unrecognized;
94
        }
95
        env->cp0.c4_faultaddr = val;
96
        break;
97
    case 5:
98
        switch (cop) {
99
        case 28:
100
            DPRINTF("Invalidate Entire I&D cache\n");
101
            return;
102
        case 20:
103
            DPRINTF("Invalidate Entire Icache\n");
104
            return;
105
        case 12:
106
            DPRINTF("Invalidate Entire Dcache\n");
107
            return;
108
        case 10:
109
            DPRINTF("Clean Entire Dcache\n");
110
            return;
111
        case 14:
112
            DPRINTF("Flush Entire Dcache\n");
113
            return;
114
        case 13:
115
            DPRINTF("Invalidate Dcache line\n");
116
            return;
117
        case 11:
118
            DPRINTF("Clean Dcache line\n");
119
            return;
120
        case 15:
121
            DPRINTF("Flush Dcache line\n");
122
            return;
123
        }
124
        break;
125
    case 6:
126
        if ((cop <= 6) && (cop >= 2)) {
127
            /* invalid all tlb */
128
            tlb_flush(env, 1);
129
            return;
130
        }
131
        break;
132
    default:
133
        goto unrecognized;
134
    }
135
    return;
136
unrecognized:
137
    DPRINTF("Wrong register (%d) or wrong operation (%d) in cp0_set!\n",
138
            creg, cop);
139
}
140

    
141
uint32_t helper_cp0_get(CPUUniCore32State *env, uint32_t creg, uint32_t cop)
142
{
143
    /*
144
     * movc rd, pp.nn, #imm9
145
     *      rd: UCOP_REG_D
146
     *      nn: UCOP_REG_N
147
     *          0: cpuid and cachetype
148
     *          1: sys control reg.
149
     *          2: page table base reg.
150
     *          3: data fault status reg.
151
     *          4: insn fault status reg.
152
     *      imm9: split UCOP_IMM10 with bit5 is 0
153
     */
154
    switch (creg) {
155
    case 0:
156
        switch (cop) {
157
        case 0:
158
            return env->cp0.c0_cpuid;
159
        case 1:
160
            return env->cp0.c0_cachetype;
161
        }
162
        break;
163
    case 1:
164
        if (cop == 0) {
165
            return env->cp0.c1_sys;
166
        }
167
        break;
168
    case 2:
169
        if (cop == 0) {
170
            return env->cp0.c2_base;
171
        }
172
        break;
173
    case 3:
174
        if (cop == 0) {
175
            return env->cp0.c3_faultstatus;
176
        }
177
        break;
178
    case 4:
179
        if (cop == 0) {
180
            return env->cp0.c4_faultaddr;
181
        }
182
        break;
183
    }
184
    DPRINTF("Wrong register (%d) or wrong operation (%d) in cp0_set!\n",
185
            creg, cop);
186
    return 0;
187
}
188

    
189
#ifdef CONFIG_CURSES
190
/*
191
 * FIXME:
192
 *     1. curses windows will be blank when switching back
193
 *     2. backspace is not handled yet
194
 */
195
static void putc_on_screen(unsigned char ch)
196
{
197
    static WINDOW *localwin;
198
    static int init;
199

    
200
    if (!init) {
201
        /* Assume 80 * 30 screen to minimize the implementation */
202
        localwin = newwin(30, 80, 0, 0);
203
        scrollok(localwin, TRUE);
204
        init = TRUE;
205
    }
206

    
207
    if (isprint(ch)) {
208
        wprintw(localwin, "%c", ch);
209
    } else {
210
        switch (ch) {
211
        case '\n':
212
            wprintw(localwin, "%c", ch);
213
            break;
214
        case '\r':
215
            /* If '\r' is put before '\n', the curses window will destroy the
216
             * last print line. And meanwhile, '\n' implifies '\r' inside. */
217
            break;
218
        default: /* Not handled, so just print it hex code */
219
            wprintw(localwin, "-- 0x%x --", ch);
220
        }
221
    }
222

    
223
    wrefresh(localwin);
224
}
225
#else
226
#define putc_on_screen(c)               do { } while (0)
227
#endif
228

    
229
void helper_cp1_putc(target_ulong x)
230
{
231
    putc_on_screen((unsigned char)x);   /* Output to screen */
232
    DPRINTF("%c", x);                   /* Output to stdout */
233
}
234
#endif
235

    
236
#ifdef CONFIG_USER_ONLY
237
void switch_mode(CPUUniCore32State *env, int mode)
238
{
239
    if (mode != ASR_MODE_USER) {
240
        cpu_abort(env, "Tried to switch out of user mode\n");
241
    }
242
}
243

    
244
void uc32_cpu_do_interrupt(CPUState *cs)
245
{
246
    UniCore32CPU *cpu = UNICORE32_CPU(cs);
247
    CPUUniCore32State *env = &cpu->env;
248

    
249
    cpu_abort(env, "NO interrupt in user mode\n");
250
}
251

    
252
int uc32_cpu_handle_mmu_fault(CPUUniCore32State *env, target_ulong address,
253
                              int access_type, int mmu_idx)
254
{
255
    cpu_abort(env, "NO mmu fault in user mode\n");
256
    return 1;
257
}
258
#endif