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