Statistics
| Branch: | Revision:

root / target-m68k / cpu.c @ 5b50e790

History | View | Annotate | Download (6.2 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
    M68kCPU *cpu = M68K_CPU(dev);
147
    M68kCPUClass *mcc = M68K_CPU_GET_CLASS(dev);
148

    
149
    m68k_cpu_init_gdb(cpu);
150

    
151
    cpu_reset(CPU(cpu));
152

    
153
    mcc->parent_realize(dev, errp);
154
}
155

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

    
163
    cs->env_ptr = env;
164
    cpu_exec_init(env);
165

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

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

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

    
183
    mcc->parent_realize = dc->realize;
184
    dc->realize = m68k_cpu_realizefn;
185

    
186
    mcc->parent_reset = cc->reset;
187
    cc->reset = m68k_cpu_reset;
188

    
189
    cc->class_by_name = m68k_cpu_class_by_name;
190
    cc->do_interrupt = m68k_cpu_do_interrupt;
191
    cc->dump_state = m68k_cpu_dump_state;
192
    cc->set_pc = m68k_cpu_set_pc;
193
    cc->gdb_read_register = m68k_cpu_gdb_read_register;
194
    cc->gdb_write_register = m68k_cpu_gdb_write_register;
195
#ifndef CONFIG_USER_ONLY
196
    cc->get_phys_page_debug = m68k_cpu_get_phys_page_debug;
197
#endif
198
    dc->vmsd = &vmstate_m68k_cpu;
199
    cc->gdb_num_core_regs = 18;
200
}
201

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

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

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

    
224
static void m68k_cpu_register_types(void)
225
{
226
    int i;
227

    
228
    type_register_static(&m68k_cpu_type_info);
229
    for (i = 0; i < ARRAY_SIZE(m68k_cpus); i++) {
230
        register_cpu_type(&m68k_cpus[i]);
231
    }
232
}
233

    
234
type_init(m68k_cpu_register_types)