Statistics
| Branch: | Revision:

root / target-m68k / cpu.c @ 14a10fc3

History | View | Annotate | Download (6.3 kB)

1
/*
2
 * QEMU Motorola 68k CPU
3
 *
4
 * Copyright (c) 2012 SUSE LINUX Products GmbH
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.1 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
18
 * <http://www.gnu.org/licenses/lgpl-2.1.html>
19
 */
20

    
21
#include "cpu.h"
22
#include "qemu-common.h"
23
#include "migration/vmstate.h"
24

    
25

    
26
static void m68k_cpu_set_pc(CPUState *cs, vaddr value)
27
{
28
    M68kCPU *cpu = M68K_CPU(cs);
29

    
30
    cpu->env.pc = value;
31
}
32

    
33
static void m68k_set_feature(CPUM68KState *env, int feature)
34
{
35
    env->features |= (1u << feature);
36
}
37

    
38
/* CPUClass::reset() */
39
static void m68k_cpu_reset(CPUState *s)
40
{
41
    M68kCPU *cpu = M68K_CPU(s);
42
    M68kCPUClass *mcc = M68K_CPU_GET_CLASS(cpu);
43
    CPUM68KState *env = &cpu->env;
44

    
45
    mcc->parent_reset(s);
46

    
47
    memset(env, 0, offsetof(CPUM68KState, breakpoints));
48
#if !defined(CONFIG_USER_ONLY)
49
    env->sr = 0x2700;
50
#endif
51
    m68k_switch_sp(env);
52
    /* ??? FP regs should be initialized to NaN.  */
53
    env->cc_op = CC_OP_FLAGS;
54
    /* TODO: We should set PC from the interrupt vector.  */
55
    env->pc = 0;
56
    tlb_flush(env, 1);
57
}
58

    
59
/* CPU models */
60

    
61
static ObjectClass *m68k_cpu_class_by_name(const char *cpu_model)
62
{
63
    ObjectClass *oc;
64
    char *typename;
65

    
66
    if (cpu_model == NULL) {
67
        return NULL;
68
    }
69

    
70
    typename = g_strdup_printf("%s-" TYPE_M68K_CPU, cpu_model);
71
    oc = object_class_by_name(typename);
72
    g_free(typename);
73
    if (oc != NULL && (object_class_dynamic_cast(oc, TYPE_M68K_CPU) == NULL ||
74
                       object_class_is_abstract(oc))) {
75
        return NULL;
76
    }
77
    return oc;
78
}
79

    
80
static void m5206_cpu_initfn(Object *obj)
81
{
82
    M68kCPU *cpu = M68K_CPU(obj);
83
    CPUM68KState *env = &cpu->env;
84

    
85
    m68k_set_feature(env, M68K_FEATURE_CF_ISA_A);
86
}
87

    
88
static void m5208_cpu_initfn(Object *obj)
89
{
90
    M68kCPU *cpu = M68K_CPU(obj);
91
    CPUM68KState *env = &cpu->env;
92

    
93
    m68k_set_feature(env, M68K_FEATURE_CF_ISA_A);
94
    m68k_set_feature(env, M68K_FEATURE_CF_ISA_APLUSC);
95
    m68k_set_feature(env, M68K_FEATURE_BRAL);
96
    m68k_set_feature(env, M68K_FEATURE_CF_EMAC);
97
    m68k_set_feature(env, M68K_FEATURE_USP);
98
}
99

    
100
static void cfv4e_cpu_initfn(Object *obj)
101
{
102
    M68kCPU *cpu = M68K_CPU(obj);
103
    CPUM68KState *env = &cpu->env;
104

    
105
    m68k_set_feature(env, M68K_FEATURE_CF_ISA_A);
106
    m68k_set_feature(env, M68K_FEATURE_CF_ISA_B);
107
    m68k_set_feature(env, M68K_FEATURE_BRAL);
108
    m68k_set_feature(env, M68K_FEATURE_CF_FPU);
109
    m68k_set_feature(env, M68K_FEATURE_CF_EMAC);
110
    m68k_set_feature(env, M68K_FEATURE_USP);
111
}
112

    
113
static void any_cpu_initfn(Object *obj)
114
{
115
    M68kCPU *cpu = M68K_CPU(obj);
116
    CPUM68KState *env = &cpu->env;
117

    
118
    m68k_set_feature(env, M68K_FEATURE_CF_ISA_A);
119
    m68k_set_feature(env, M68K_FEATURE_CF_ISA_B);
120
    m68k_set_feature(env, M68K_FEATURE_CF_ISA_APLUSC);
121
    m68k_set_feature(env, M68K_FEATURE_BRAL);
122
    m68k_set_feature(env, M68K_FEATURE_CF_FPU);
123
    /* MAC and EMAC are mututally exclusive, so pick EMAC.
124
       It's mostly backwards compatible.  */
125
    m68k_set_feature(env, M68K_FEATURE_CF_EMAC);
126
    m68k_set_feature(env, M68K_FEATURE_CF_EMAC_B);
127
    m68k_set_feature(env, M68K_FEATURE_USP);
128
    m68k_set_feature(env, M68K_FEATURE_EXT_FULL);
129
    m68k_set_feature(env, M68K_FEATURE_WORD_INDEX);
130
}
131

    
132
typedef struct M68kCPUInfo {
133
    const char *name;
134
    void (*instance_init)(Object *obj);
135
} M68kCPUInfo;
136

    
137
static const M68kCPUInfo m68k_cpus[] = {
138
    { .name = "m5206", .instance_init = m5206_cpu_initfn },
139
    { .name = "m5208", .instance_init = m5208_cpu_initfn },
140
    { .name = "cfv4e", .instance_init = cfv4e_cpu_initfn },
141
    { .name = "any",   .instance_init = any_cpu_initfn },
142
};
143

    
144
static void m68k_cpu_realizefn(DeviceState *dev, Error **errp)
145
{
146
    CPUState *cs = CPU(dev);
147
    M68kCPU *cpu = M68K_CPU(dev);
148
    M68kCPUClass *mcc = M68K_CPU_GET_CLASS(dev);
149

    
150
    m68k_cpu_init_gdb(cpu);
151

    
152
    cpu_reset(cs);
153
    qemu_init_vcpu(cs);
154

    
155
    mcc->parent_realize(dev, errp);
156
}
157

    
158
static void m68k_cpu_initfn(Object *obj)
159
{
160
    CPUState *cs = CPU(obj);
161
    M68kCPU *cpu = M68K_CPU(obj);
162
    CPUM68KState *env = &cpu->env;
163
    static bool inited;
164

    
165
    cs->env_ptr = env;
166
    cpu_exec_init(env);
167

    
168
    if (tcg_enabled() && !inited) {
169
        inited = true;
170
        m68k_tcg_init();
171
    }
172
}
173

    
174
static const VMStateDescription vmstate_m68k_cpu = {
175
    .name = "cpu",
176
    .unmigratable = 1,
177
};
178

    
179
static void m68k_cpu_class_init(ObjectClass *c, void *data)
180
{
181
    M68kCPUClass *mcc = M68K_CPU_CLASS(c);
182
    CPUClass *cc = CPU_CLASS(c);
183
    DeviceClass *dc = DEVICE_CLASS(c);
184

    
185
    mcc->parent_realize = dc->realize;
186
    dc->realize = m68k_cpu_realizefn;
187

    
188
    mcc->parent_reset = cc->reset;
189
    cc->reset = m68k_cpu_reset;
190

    
191
    cc->class_by_name = m68k_cpu_class_by_name;
192
    cc->do_interrupt = m68k_cpu_do_interrupt;
193
    cc->dump_state = m68k_cpu_dump_state;
194
    cc->set_pc = m68k_cpu_set_pc;
195
    cc->gdb_read_register = m68k_cpu_gdb_read_register;
196
    cc->gdb_write_register = m68k_cpu_gdb_write_register;
197
#ifndef CONFIG_USER_ONLY
198
    cc->get_phys_page_debug = m68k_cpu_get_phys_page_debug;
199
#endif
200
    dc->vmsd = &vmstate_m68k_cpu;
201
    cc->gdb_num_core_regs = 18;
202
    cc->gdb_core_xml_file = "cf-core.xml";
203
}
204

    
205
static void register_cpu_type(const M68kCPUInfo *info)
206
{
207
    TypeInfo type_info = {
208
        .parent = TYPE_M68K_CPU,
209
        .instance_init = info->instance_init,
210
    };
211

    
212
    type_info.name = g_strdup_printf("%s-" TYPE_M68K_CPU, info->name);
213
    type_register(&type_info);
214
    g_free((void *)type_info.name);
215
}
216

    
217
static const TypeInfo m68k_cpu_type_info = {
218
    .name = TYPE_M68K_CPU,
219
    .parent = TYPE_CPU,
220
    .instance_size = sizeof(M68kCPU),
221
    .instance_init = m68k_cpu_initfn,
222
    .abstract = true,
223
    .class_size = sizeof(M68kCPUClass),
224
    .class_init = m68k_cpu_class_init,
225
};
226

    
227
static void m68k_cpu_register_types(void)
228
{
229
    int i;
230

    
231
    type_register_static(&m68k_cpu_type_info);
232
    for (i = 0; i < ARRAY_SIZE(m68k_cpus); i++) {
233
        register_cpu_type(&m68k_cpus[i]);
234
    }
235
}
236

    
237
type_init(m68k_cpu_register_types)