Revision 34f4aa83

b/target-lm32/cpu-qom.h
60 60
    /*< public >*/
61 61

  
62 62
    CPULM32State env;
63

  
64
    uint32_t revision;
65
    uint8_t num_interrupts;
66
    uint8_t num_breakpoints;
67
    uint8_t num_watchpoints;
68
    uint32_t features;
63 69
} LM32CPU;
64 70

  
65 71
static inline LM32CPU *lm32_env_get_cpu(CPULM32State *env)
b/target-lm32/cpu.c
29 29
    cpu->env.pc = value;
30 30
}
31 31

  
32
/* Sort alphabetically by type name. */
33
static gint lm32_cpu_list_compare(gconstpointer a, gconstpointer b)
34
{
35
    ObjectClass *class_a = (ObjectClass *)a;
36
    ObjectClass *class_b = (ObjectClass *)b;
37
    const char *name_a, *name_b;
38

  
39
    name_a = object_class_get_name(class_a);
40
    name_b = object_class_get_name(class_b);
41
    return strcmp(name_a, name_b);
42
}
43

  
44
static void lm32_cpu_list_entry(gpointer data, gpointer user_data)
45
{
46
    ObjectClass *oc = data;
47
    CPUListState *s = user_data;
48
    const char *typename = object_class_get_name(oc);
49
    char *name;
50

  
51
    name = g_strndup(typename, strlen(typename) - strlen("-" TYPE_LM32_CPU));
52
    (*s->cpu_fprintf)(s->file, "  %s\n", name);
53
    g_free(name);
54
}
55

  
56

  
57
void lm32_cpu_list(FILE *f, fprintf_function cpu_fprintf)
58
{
59
    CPUListState s = {
60
        .file = f,
61
        .cpu_fprintf = cpu_fprintf,
62
    };
63
    GSList *list;
64

  
65
    list = object_class_get_list(TYPE_LM32_CPU, false);
66
    list = g_slist_sort(list, lm32_cpu_list_compare);
67
    (*cpu_fprintf)(f, "Available CPUs:\n");
68
    g_slist_foreach(list, lm32_cpu_list_entry, &s);
69
    g_slist_free(list);
70
}
71

  
72
static void lm32_cpu_init_cfg_reg(LM32CPU *cpu)
73
{
74
    CPULM32State *env = &cpu->env;
75
    uint32_t cfg = 0;
76

  
77
    if (cpu->features & LM32_FEATURE_MULTIPLY) {
78
        cfg |= CFG_M;
79
    }
80

  
81
    if (cpu->features & LM32_FEATURE_DIVIDE) {
82
        cfg |= CFG_D;
83
    }
84

  
85
    if (cpu->features & LM32_FEATURE_SHIFT) {
86
        cfg |= CFG_S;
87
    }
88

  
89
    if (cpu->features & LM32_FEATURE_SIGN_EXTEND) {
90
        cfg |= CFG_X;
91
    }
92

  
93
    if (cpu->features & LM32_FEATURE_I_CACHE) {
94
        cfg |= CFG_IC;
95
    }
96

  
97
    if (cpu->features & LM32_FEATURE_D_CACHE) {
98
        cfg |= CFG_DC;
99
    }
100

  
101
    if (cpu->features & LM32_FEATURE_CYCLE_COUNT) {
102
        cfg |= CFG_CC;
103
    }
104

  
105
    cfg |= (cpu->num_interrupts << CFG_INT_SHIFT);
106
    cfg |= (cpu->num_breakpoints << CFG_BP_SHIFT);
107
    cfg |= (cpu->num_watchpoints << CFG_WP_SHIFT);
108
    cfg |= (cpu->revision << CFG_REV_SHIFT);
109

  
110
    env->cfg = cfg;
111
}
112

  
32 113
/* CPUClass::reset() */
33 114
static void lm32_cpu_reset(CPUState *s)
34 115
{
......
41 122
    /* reset cpu state */
42 123
    memset(env, 0, offsetof(CPULM32State, breakpoints));
43 124

  
125
    lm32_cpu_init_cfg_reg(cpu);
44 126
    tlb_flush(env, 1);
45 127
}
46 128

  
......
74 156
    }
75 157
}
76 158

  
159
static void lm32_basic_cpu_initfn(Object *obj)
160
{
161
    LM32CPU *cpu = LM32_CPU(obj);
162

  
163
    cpu->revision = 3;
164
    cpu->num_interrupts = 32;
165
    cpu->num_breakpoints = 4;
166
    cpu->num_watchpoints = 4;
167
    cpu->features = LM32_FEATURE_SHIFT
168
                  | LM32_FEATURE_SIGN_EXTEND
169
                  | LM32_FEATURE_CYCLE_COUNT;
170
}
171

  
172
static void lm32_standard_cpu_initfn(Object *obj)
173
{
174
    LM32CPU *cpu = LM32_CPU(obj);
175

  
176
    cpu->revision = 3;
177
    cpu->num_interrupts = 32;
178
    cpu->num_breakpoints = 4;
179
    cpu->num_watchpoints = 4;
180
    cpu->features = LM32_FEATURE_MULTIPLY
181
                  | LM32_FEATURE_DIVIDE
182
                  | LM32_FEATURE_SHIFT
183
                  | LM32_FEATURE_SIGN_EXTEND
184
                  | LM32_FEATURE_I_CACHE
185
                  | LM32_FEATURE_CYCLE_COUNT;
186
}
187

  
188
static void lm32_full_cpu_initfn(Object *obj)
189
{
190
    LM32CPU *cpu = LM32_CPU(obj);
191

  
192
    cpu->revision = 3;
193
    cpu->num_interrupts = 32;
194
    cpu->num_breakpoints = 4;
195
    cpu->num_watchpoints = 4;
196
    cpu->features = LM32_FEATURE_MULTIPLY
197
                  | LM32_FEATURE_DIVIDE
198
                  | LM32_FEATURE_SHIFT
199
                  | LM32_FEATURE_SIGN_EXTEND
200
                  | LM32_FEATURE_I_CACHE
201
                  | LM32_FEATURE_D_CACHE
202
                  | LM32_FEATURE_CYCLE_COUNT;
203
}
204

  
205
typedef struct LM32CPUInfo {
206
    const char *name;
207
    void (*initfn)(Object *obj);
208
} LM32CPUInfo;
209

  
210
static const LM32CPUInfo lm32_cpus[] = {
211
    {
212
        .name = "lm32-basic",
213
        .initfn = lm32_basic_cpu_initfn,
214
    },
215
    {
216
        .name = "lm32-standard",
217
        .initfn = lm32_standard_cpu_initfn,
218
    },
219
    {
220
        .name = "lm32-full",
221
        .initfn = lm32_full_cpu_initfn,
222
    },
223
};
224

  
225
static ObjectClass *lm32_cpu_class_by_name(const char *cpu_model)
226
{
227
    ObjectClass *oc;
228
    char *typename;
229

  
230
    if (cpu_model == NULL) {
231
        return NULL;
232
    }
233

  
234
    typename = g_strdup_printf("%s-" TYPE_LM32_CPU, cpu_model);
235
    oc = object_class_by_name(typename);
236
    g_free(typename);
237
    if (oc != NULL && (!object_class_dynamic_cast(oc, TYPE_LM32_CPU) ||
238
                       object_class_is_abstract(oc))) {
239
        oc = NULL;
240
    }
241
    return oc;
242
}
243

  
77 244
static void lm32_cpu_class_init(ObjectClass *oc, void *data)
78 245
{
79 246
    LM32CPUClass *lcc = LM32_CPU_CLASS(oc);
......
86 253
    lcc->parent_reset = cc->reset;
87 254
    cc->reset = lm32_cpu_reset;
88 255

  
256
    cc->class_by_name = lm32_cpu_class_by_name;
89 257
    cc->do_interrupt = lm32_cpu_do_interrupt;
90 258
    cc->dump_state = lm32_cpu_dump_state;
91 259
    cc->set_pc = lm32_cpu_set_pc;
......
98 266
    cc->gdb_num_core_regs = 32 + 7;
99 267
}
100 268

  
269
static void lm32_register_cpu_type(const LM32CPUInfo *info)
270
{
271
    TypeInfo type_info = {
272
        .parent = TYPE_LM32_CPU,
273
        .instance_init = info->initfn,
274
    };
275

  
276
    type_info.name = g_strdup_printf("%s-" TYPE_LM32_CPU, info->name);
277
    type_register(&type_info);
278
    g_free((void *)type_info.name);
279
}
280

  
101 281
static const TypeInfo lm32_cpu_type_info = {
102 282
    .name = TYPE_LM32_CPU,
103 283
    .parent = TYPE_CPU,
104 284
    .instance_size = sizeof(LM32CPU),
105 285
    .instance_init = lm32_cpu_initfn,
106
    .abstract = false,
286
    .abstract = true,
107 287
    .class_size = sizeof(LM32CPUClass),
108 288
    .class_init = lm32_cpu_class_init,
109 289
};
110 290

  
111 291
static void lm32_cpu_register_types(void)
112 292
{
293
    int i;
294

  
113 295
    type_register_static(&lm32_cpu_type_info);
296
    for (i = 0; i < ARRAY_SIZE(lm32_cpus); i++) {
297
        lm32_register_cpu_type(&lm32_cpus[i]);
298
    }
114 299
}
115 300

  
116 301
type_init(lm32_cpu_register_types)
b/target-lm32/cpu.h
177 177
    DeviceState *juart_state;
178 178

  
179 179
    /* processor core features */
180
    uint32_t features;
181 180
    uint32_t flags;
182
    uint8_t num_bps;
183
    uint8_t num_wps;
184 181

  
185 182
};
186 183

  
187 184
#include "cpu-qom.h"
188 185

  
189 186
LM32CPU *cpu_lm32_init(const char *cpu_model);
190
void cpu_lm32_list(FILE *f, fprintf_function cpu_fprintf);
191 187
int cpu_lm32_exec(CPULM32State *s);
192 188
/* you can call this signal handler from your SIGBUS and SIGSEGV
193 189
   signal handlers to inform the virtual CPU of exceptions. non zero
194 190
   is returned if the signal was handled by the virtual CPU.  */
195 191
int cpu_lm32_signal_handler(int host_signum, void *pinfo,
196 192
                          void *puc);
193
void lm32_cpu_list(FILE *f, fprintf_function cpu_fprintf);
197 194
void lm32_translate_init(void);
198 195
void cpu_lm32_set_phys_msb_ignore(CPULM32State *env, int value);
199 196

  
......
206 203
    return &cpu->env;
207 204
}
208 205

  
209
#define cpu_list cpu_lm32_list
206
#define cpu_list lm32_cpu_list
210 207
#define cpu_exec cpu_lm32_exec
211 208
#define cpu_gen_code cpu_lm32_gen_code
212 209
#define cpu_signal_handler cpu_lm32_signal_handler
b/target-lm32/helper.c
90 90
    }
91 91
}
92 92

  
93
typedef struct {
94
    const char *name;
95
    uint32_t revision;
96
    uint8_t num_interrupts;
97
    uint8_t num_breakpoints;
98
    uint8_t num_watchpoints;
99
    uint32_t features;
100
} LM32Def;
101

  
102
static const LM32Def lm32_defs[] = {
103
    {
104
        .name = "lm32-basic",
105
        .revision = 3,
106
        .num_interrupts = 32,
107
        .num_breakpoints = 4,
108
        .num_watchpoints = 4,
109
        .features = (LM32_FEATURE_SHIFT
110
                     | LM32_FEATURE_SIGN_EXTEND
111
                     | LM32_FEATURE_CYCLE_COUNT),
112
    },
113
    {
114
        .name = "lm32-standard",
115
        .revision = 3,
116
        .num_interrupts = 32,
117
        .num_breakpoints = 4,
118
        .num_watchpoints = 4,
119
        .features = (LM32_FEATURE_MULTIPLY
120
                     | LM32_FEATURE_DIVIDE
121
                     | LM32_FEATURE_SHIFT
122
                     | LM32_FEATURE_SIGN_EXTEND
123
                     | LM32_FEATURE_I_CACHE
124
                     | LM32_FEATURE_CYCLE_COUNT),
125
    },
126
    {
127
        .name = "lm32-full",
128
        .revision = 3,
129
        .num_interrupts = 32,
130
        .num_breakpoints = 4,
131
        .num_watchpoints = 4,
132
        .features = (LM32_FEATURE_MULTIPLY
133
                     | LM32_FEATURE_DIVIDE
134
                     | LM32_FEATURE_SHIFT
135
                     | LM32_FEATURE_SIGN_EXTEND
136
                     | LM32_FEATURE_I_CACHE
137
                     | LM32_FEATURE_D_CACHE
138
                     | LM32_FEATURE_CYCLE_COUNT),
139
    }
140
};
141

  
142
void cpu_lm32_list(FILE *f, fprintf_function cpu_fprintf)
143
{
144
    int i;
145

  
146
    cpu_fprintf(f, "Available CPUs:\n");
147
    for (i = 0; i < ARRAY_SIZE(lm32_defs); i++) {
148
        cpu_fprintf(f, "  %s\n", lm32_defs[i].name);
149
    }
150
}
151

  
152
static const LM32Def *cpu_lm32_find_by_name(const char *name)
153
{
154
    int i;
155

  
156
    for (i = 0; i < ARRAY_SIZE(lm32_defs); i++) {
157
        if (strcasecmp(name, lm32_defs[i].name) == 0) {
158
            return &lm32_defs[i];
159
        }
160
    }
161

  
162
    return NULL;
163
}
164

  
165
static uint32_t cfg_by_def(const LM32Def *def)
166
{
167
    uint32_t cfg = 0;
168

  
169
    if (def->features & LM32_FEATURE_MULTIPLY) {
170
        cfg |= CFG_M;
171
    }
172

  
173
    if (def->features & LM32_FEATURE_DIVIDE) {
174
        cfg |= CFG_D;
175
    }
176

  
177
    if (def->features & LM32_FEATURE_SHIFT) {
178
        cfg |= CFG_S;
179
    }
180

  
181
    if (def->features & LM32_FEATURE_SIGN_EXTEND) {
182
        cfg |= CFG_X;
183
    }
184

  
185
    if (def->features & LM32_FEATURE_I_CACHE) {
186
        cfg |= CFG_IC;
187
    }
188

  
189
    if (def->features & LM32_FEATURE_D_CACHE) {
190
        cfg |= CFG_DC;
191
    }
192

  
193
    if (def->features & LM32_FEATURE_CYCLE_COUNT) {
194
        cfg |= CFG_CC;
195
    }
196

  
197
    cfg |= (def->num_interrupts << CFG_INT_SHIFT);
198
    cfg |= (def->num_breakpoints << CFG_BP_SHIFT);
199
    cfg |= (def->num_watchpoints << CFG_WP_SHIFT);
200
    cfg |= (def->revision << CFG_REV_SHIFT);
201

  
202
    return cfg;
203
}
204

  
205 93
LM32CPU *cpu_lm32_init(const char *cpu_model)
206 94
{
207 95
    LM32CPU *cpu;
208
    CPULM32State *env;
209
    const LM32Def *def;
96
    ObjectClass *oc;
210 97

  
211
    def = cpu_lm32_find_by_name(cpu_model);
212
    if (!def) {
98
    oc = cpu_class_by_name(TYPE_LM32_CPU, cpu_model);
99
    if (oc == NULL) {
213 100
        return NULL;
214 101
    }
215

  
216
    cpu = LM32_CPU(object_new(TYPE_LM32_CPU));
217
    env = &cpu->env;
218

  
219
    env->features = def->features;
220
    env->num_bps = def->num_breakpoints;
221
    env->num_wps = def->num_watchpoints;
222
    env->cfg = cfg_by_def(def);
102
    cpu = LM32_CPU(object_new(object_class_get_name(oc)));
223 103

  
224 104
    object_property_set_bool(OBJECT(cpu), true, "realized", NULL);
225 105

  
b/target-lm32/translate.c
64 64

  
65 65
/* This is the state at translation time.  */
66 66
typedef struct DisasContext {
67
    CPULM32State *env;
68 67
    target_ulong pc;
69 68

  
70 69
    /* Decoder.  */
......
82 81

  
83 82
    struct TranslationBlock *tb;
84 83
    int singlestep_enabled;
84

  
85
    uint32_t features;
86
    uint8_t num_breakpoints;
87
    uint8_t num_watchpoints;
85 88
} DisasContext;
86 89

  
87 90
static const char *regnames[] = {
......
420 423

  
421 424
    LOG_DIS("divu r%d, r%d, r%d\n", dc->r2, dc->r0, dc->r1);
422 425

  
423
    if (!(dc->env->features & LM32_FEATURE_DIVIDE)) {
426
    if (!(dc->features & LM32_FEATURE_DIVIDE)) {
424 427
        qemu_log_mask(LOG_GUEST_ERROR, "hardware divider is not available\n");
425 428
        return;
426 429
    }
......
499 502

  
500 503
    LOG_DIS("modu r%d, r%d, %d\n", dc->r2, dc->r0, dc->r1);
501 504

  
502
    if (!(dc->env->features & LM32_FEATURE_DIVIDE)) {
505
    if (!(dc->features & LM32_FEATURE_DIVIDE)) {
503 506
        qemu_log_mask(LOG_GUEST_ERROR, "hardware divider is not available\n");
504 507
        return;
505 508
    }
......
521 524
        LOG_DIS("mul r%d, r%d, r%d\n", dc->r2, dc->r0, dc->r1);
522 525
    }
523 526

  
524
    if (!(dc->env->features & LM32_FEATURE_MULTIPLY)) {
527
    if (!(dc->features & LM32_FEATURE_MULTIPLY)) {
525 528
        qemu_log_mask(LOG_GUEST_ERROR,
526 529
                      "hardware multiplier is not available\n");
527 530
        return;
......
675 678
{
676 679
    LOG_DIS("sextb r%d, r%d\n", dc->r2, dc->r0);
677 680

  
678
    if (!(dc->env->features & LM32_FEATURE_SIGN_EXTEND)) {
681
    if (!(dc->features & LM32_FEATURE_SIGN_EXTEND)) {
679 682
        qemu_log_mask(LOG_GUEST_ERROR,
680 683
                      "hardware sign extender is not available\n");
681 684
        return;
......
688 691
{
689 692
    LOG_DIS("sexth r%d, r%d\n", dc->r2, dc->r0);
690 693

  
691
    if (!(dc->env->features & LM32_FEATURE_SIGN_EXTEND)) {
694
    if (!(dc->features & LM32_FEATURE_SIGN_EXTEND)) {
692 695
        qemu_log_mask(LOG_GUEST_ERROR,
693 696
                      "hardware sign extender is not available\n");
694 697
        return;
......
717 720
        LOG_DIS("sl r%d, r%d, r%d\n", dc->r2, dc->r0, dc->r1);
718 721
    }
719 722

  
720
    if (!(dc->env->features & LM32_FEATURE_SHIFT)) {
723
    if (!(dc->features & LM32_FEATURE_SHIFT)) {
721 724
        qemu_log_mask(LOG_GUEST_ERROR, "hardware shifter is not available\n");
722 725
        return;
723 726
    }
......
740 743
        LOG_DIS("sr r%d, r%d, r%d\n", dc->r2, dc->r0, dc->r1);
741 744
    }
742 745

  
743
    if (!(dc->env->features & LM32_FEATURE_SHIFT)) {
746
    if (!(dc->features & LM32_FEATURE_SHIFT)) {
744 747
        if (dc->format == OP_FMT_RI) {
745 748
            /* TODO: check r1 == 1 during runtime */
746 749
        } else {
......
770 773
        LOG_DIS("sru r%d, r%d, r%d\n", dc->r2, dc->r0, dc->r1);
771 774
    }
772 775

  
773
    if (!(dc->env->features & LM32_FEATURE_SHIFT)) {
776
    if (!(dc->features & LM32_FEATURE_SHIFT)) {
774 777
        if (dc->format == OP_FMT_RI) {
775 778
            /* TODO: check r1 == 1 during runtime */
776 779
        } else {
......
880 883
    case CSR_BP2:
881 884
    case CSR_BP3:
882 885
        no = dc->csr - CSR_BP0;
883
        if (dc->env->num_bps <= no) {
886
        if (dc->num_breakpoints <= no) {
884 887
            qemu_log_mask(LOG_GUEST_ERROR,
885 888
                          "breakpoint #%i is not available\n", no);
886 889
            break;
......
892 895
    case CSR_WP2:
893 896
    case CSR_WP3:
894 897
        no = dc->csr - CSR_WP0;
895
        if (dc->env->num_wps <= no) {
898
        if (dc->num_watchpoints <= no) {
896 899
            qemu_log_mask(LOG_GUEST_ERROR,
897 900
                          "watchpoint #%i is not available\n", no);
898 901
            break;
......
1033 1036
    int max_insns;
1034 1037

  
1035 1038
    pc_start = tb->pc;
1036
    dc->env = env;
1039
    dc->features = cpu->features;
1040
    dc->num_breakpoints = cpu->num_breakpoints;
1041
    dc->num_watchpoints = cpu->num_watchpoints;
1037 1042
    dc->tb = tb;
1038 1043

  
1039 1044
    gen_opc_end = tcg_ctx.gen_opc_buf + OPC_MAX_SIZE;

Also available in: Unified diff