Statistics
| Branch: | Revision:

root / target-unicore32 / helper.c @ ff5928d0

History | View | Annotate | Download (5.9 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 "gdbstub.h"
14
#include "helper.h"
15
#include "host-utils.h"
16
#include "console.h"
17

    
18
#undef DEBUG_UC32
19

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

    
26
CPUUniCore32State *uc32_cpu_init(const char *cpu_model)
27
{
28
    UniCore32CPU *cpu;
29
    CPUUniCore32State *env;
30
    static int inited = 1;
31

    
32
    if (object_class_by_name(cpu_model) == NULL) {
33
        return NULL;
34
    }
35
    cpu = UNICORE32_CPU(object_new(cpu_model));
36
    env = &cpu->env;
37

    
38
    if (inited) {
39
        inited = 0;
40
        uc32_translate_init();
41
    }
42

    
43
    qemu_init_vcpu(env);
44
    return env;
45
}
46

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

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

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

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

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

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

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

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

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

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

    
245
void do_interrupt(CPUUniCore32State *env)
246
{
247
    cpu_abort(env, "NO interrupt in user mode\n");
248
}
249

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