1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20#include "qemu/osdep.h"
21#include "cpu.h"
22#include "disas/disas.h"
23#include "exec/helper-proto.h"
24#include "exec/exec-all.h"
25#include "exec/translator.h"
26#include "tcg-op.h"
27
28#include "exec/cpu_ldst.h"
29#include "hw/lm32/lm32_pic.h"
30
31#include "exec/helper-gen.h"
32
33#include "trace-tcg.h"
34#include "exec/log.h"
35
36
37#define DISAS_LM32 0
38
39#define LOG_DIS(...) \
40 do { \
41 if (DISAS_LM32) { \
42 qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__); \
43 } \
44 } while (0)
45
46#define EXTRACT_FIELD(src, start, end) \
47 (((src) >> start) & ((1 << (end - start + 1)) - 1))
48
49#define MEM_INDEX 0
50
51
52#define DISAS_JUMP DISAS_TARGET_0
53#define DISAS_UPDATE DISAS_TARGET_1
54#define DISAS_TB_JUMP DISAS_TARGET_2
55
56static TCGv cpu_R[32];
57static TCGv cpu_pc;
58static TCGv cpu_ie;
59static TCGv cpu_icc;
60static TCGv cpu_dcc;
61static TCGv cpu_cc;
62static TCGv cpu_cfg;
63static TCGv cpu_eba;
64static TCGv cpu_dc;
65static TCGv cpu_deba;
66static TCGv cpu_bp[4];
67static TCGv cpu_wp[4];
68
69#include "exec/gen-icount.h"
70
71enum {
72 OP_FMT_RI,
73 OP_FMT_RR,
74 OP_FMT_CR,
75 OP_FMT_I
76};
77
78
79typedef struct DisasContext {
80 target_ulong pc;
81
82
83 int format;
84 uint32_t ir;
85 uint8_t opcode;
86 uint8_t r0, r1, r2, csr;
87 uint16_t imm5;
88 uint16_t imm16;
89 uint32_t imm26;
90
91 unsigned int delayed_branch;
92 unsigned int tb_flags, synced_flags;
93 int is_jmp;
94
95 struct TranslationBlock *tb;
96 int singlestep_enabled;
97
98 uint32_t features;
99 uint8_t num_breakpoints;
100 uint8_t num_watchpoints;
101} DisasContext;
102
103static const char *regnames[] = {
104 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
105 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
106 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
107 "r24", "r25", "r26/gp", "r27/fp", "r28/sp", "r29/ra",
108 "r30/ea", "r31/ba", "bp0", "bp1", "bp2", "bp3", "wp0",
109 "wp1", "wp2", "wp3"
110};
111
112static inline int zero_extend(unsigned int val, int width)
113{
114 return val & ((1 << width) - 1);
115}
116
117static inline int sign_extend(unsigned int val, int width)
118{
119 int sval;
120
121
122 val <<= 32 - width;
123 sval = val;
124
125 sval >>= 32 - width;
126
127 return sval;
128}
129
130static inline void t_gen_raise_exception(DisasContext *dc, uint32_t index)
131{
132 TCGv_i32 tmp = tcg_const_i32(index);
133
134 gen_helper_raise_exception(cpu_env, tmp);
135 tcg_temp_free_i32(tmp);
136}
137
138static inline void t_gen_illegal_insn(DisasContext *dc)
139{
140 tcg_gen_movi_tl(cpu_pc, dc->pc);
141 gen_helper_ill(cpu_env);
142}
143
144static inline bool use_goto_tb(DisasContext *dc, target_ulong dest)
145{
146 if (unlikely(dc->singlestep_enabled)) {
147 return false;
148 }
149
150#ifndef CONFIG_USER_ONLY
151 return (dc->tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
152#else
153 return true;
154#endif
155}
156
157static void gen_goto_tb(DisasContext *dc, int n, target_ulong dest)
158{
159 if (use_goto_tb(dc, dest)) {
160 tcg_gen_goto_tb(n);
161 tcg_gen_movi_tl(cpu_pc, dest);
162 tcg_gen_exit_tb(dc->tb, n);
163 } else {
164 tcg_gen_movi_tl(cpu_pc, dest);
165 if (dc->singlestep_enabled) {
166 t_gen_raise_exception(dc, EXCP_DEBUG);
167 }
168 tcg_gen_exit_tb(NULL, 0);
169 }
170}
171
172static void dec_add(DisasContext *dc)
173{
174 if (dc->format == OP_FMT_RI) {
175 if (dc->r0 == R_R0) {
176 if (dc->r1 == R_R0 && dc->imm16 == 0) {
177 LOG_DIS("nop\n");
178 } else {
179 LOG_DIS("mvi r%d, %d\n", dc->r1, sign_extend(dc->imm16, 16));
180 }
181 } else {
182 LOG_DIS("addi r%d, r%d, %d\n", dc->r1, dc->r0,
183 sign_extend(dc->imm16, 16));
184 }
185 } else {
186 LOG_DIS("add r%d, r%d, r%d\n", dc->r2, dc->r0, dc->r1);
187 }
188
189 if (dc->format == OP_FMT_RI) {
190 tcg_gen_addi_tl(cpu_R[dc->r1], cpu_R[dc->r0],
191 sign_extend(dc->imm16, 16));
192 } else {
193 tcg_gen_add_tl(cpu_R[dc->r2], cpu_R[dc->r0], cpu_R[dc->r1]);
194 }
195}
196
197static void dec_and(DisasContext *dc)
198{
199 if (dc->format == OP_FMT_RI) {
200 LOG_DIS("andi r%d, r%d, %d\n", dc->r1, dc->r0,
201 zero_extend(dc->imm16, 16));
202 } else {
203 LOG_DIS("and r%d, r%d, r%d\n", dc->r2, dc->r0, dc->r1);
204 }
205
206 if (dc->format == OP_FMT_RI) {
207 tcg_gen_andi_tl(cpu_R[dc->r1], cpu_R[dc->r0],
208 zero_extend(dc->imm16, 16));
209 } else {
210 if (dc->r0 == 0 && dc->r1 == 0 && dc->r2 == 0) {
211 tcg_gen_movi_tl(cpu_pc, dc->pc + 4);
212 gen_helper_hlt(cpu_env);
213 } else {
214 tcg_gen_and_tl(cpu_R[dc->r2], cpu_R[dc->r0], cpu_R[dc->r1]);
215 }
216 }
217}
218
219static void dec_andhi(DisasContext *dc)
220{
221 LOG_DIS("andhi r%d, r%d, %d\n", dc->r1, dc->r0, dc->imm16);
222
223 tcg_gen_andi_tl(cpu_R[dc->r1], cpu_R[dc->r0], (dc->imm16 << 16));
224}
225
226static void dec_b(DisasContext *dc)
227{
228 if (dc->r0 == R_RA) {
229 LOG_DIS("ret\n");
230 } else if (dc->r0 == R_EA) {
231 LOG_DIS("eret\n");
232 } else if (dc->r0 == R_BA) {
233 LOG_DIS("bret\n");
234 } else {
235 LOG_DIS("b r%d\n", dc->r0);
236 }
237
238
239 if (dc->r0 == R_EA) {
240 TCGv t0 = tcg_temp_new();
241 TCGLabel *l1 = gen_new_label();
242 tcg_gen_andi_tl(t0, cpu_ie, IE_EIE);
243 tcg_gen_ori_tl(cpu_ie, cpu_ie, IE_IE);
244 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, IE_EIE, l1);
245 tcg_gen_andi_tl(cpu_ie, cpu_ie, ~IE_IE);
246 gen_set_label(l1);
247 tcg_temp_free(t0);
248 } else if (dc->r0 == R_BA) {
249 TCGv t0 = tcg_temp_new();
250 TCGLabel *l1 = gen_new_label();
251 tcg_gen_andi_tl(t0, cpu_ie, IE_BIE);
252 tcg_gen_ori_tl(cpu_ie, cpu_ie, IE_IE);
253 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, IE_BIE, l1);
254 tcg_gen_andi_tl(cpu_ie, cpu_ie, ~IE_IE);
255 gen_set_label(l1);
256 tcg_temp_free(t0);
257 }
258 tcg_gen_mov_tl(cpu_pc, cpu_R[dc->r0]);
259
260 dc->is_jmp = DISAS_JUMP;
261}
262
263static void dec_bi(DisasContext *dc)
264{
265 LOG_DIS("bi %d\n", sign_extend(dc->imm26 << 2, 26));
266
267 gen_goto_tb(dc, 0, dc->pc + (sign_extend(dc->imm26 << 2, 26)));
268
269 dc->is_jmp = DISAS_TB_JUMP;
270}
271
272static inline void gen_cond_branch(DisasContext *dc, int cond)
273{
274 TCGLabel *l1 = gen_new_label();
275 tcg_gen_brcond_tl(cond, cpu_R[dc->r0], cpu_R[dc->r1], l1);
276 gen_goto_tb(dc, 0, dc->pc + 4);
277 gen_set_label(l1);
278 gen_goto_tb(dc, 1, dc->pc + (sign_extend(dc->imm16 << 2, 16)));
279 dc->is_jmp = DISAS_TB_JUMP;
280}
281
282static void dec_be(DisasContext *dc)
283{
284 LOG_DIS("be r%d, r%d, %d\n", dc->r1, dc->r0,
285 sign_extend(dc->imm16, 16) * 4);
286
287 gen_cond_branch(dc, TCG_COND_EQ);
288}
289
290static void dec_bg(DisasContext *dc)
291{
292 LOG_DIS("bg r%d, r%d, %d\n", dc->r1, dc->r0,
293 sign_extend(dc->imm16, 16 * 4));
294
295 gen_cond_branch(dc, TCG_COND_GT);
296}
297
298static void dec_bge(DisasContext *dc)
299{
300 LOG_DIS("bge r%d, r%d, %d\n", dc->r1, dc->r0,
301 sign_extend(dc->imm16, 16) * 4);
302
303 gen_cond_branch(dc, TCG_COND_GE);
304}
305
306static void dec_bgeu(DisasContext *dc)
307{
308 LOG_DIS("bgeu r%d, r%d, %d\n", dc->r1, dc->r0,
309 sign_extend(dc->imm16, 16) * 4);
310
311 gen_cond_branch(dc, TCG_COND_GEU);
312}
313
314static void dec_bgu(DisasContext *dc)
315{
316 LOG_DIS("bgu r%d, r%d, %d\n", dc->r1, dc->r0,
317 sign_extend(dc->imm16, 16) * 4);
318
319 gen_cond_branch(dc, TCG_COND_GTU);
320}
321
322static void dec_bne(DisasContext *dc)
323{
324 LOG_DIS("bne r%d, r%d, %d\n", dc->r1, dc->r0,
325 sign_extend(dc->imm16, 16) * 4);
326
327 gen_cond_branch(dc, TCG_COND_NE);
328}
329
330static void dec_call(DisasContext *dc)
331{
332 LOG_DIS("call r%d\n", dc->r0);
333
334 tcg_gen_movi_tl(cpu_R[R_RA], dc->pc + 4);
335 tcg_gen_mov_tl(cpu_pc, cpu_R[dc->r0]);
336
337 dc->is_jmp = DISAS_JUMP;
338}
339
340static void dec_calli(DisasContext *dc)
341{
342 LOG_DIS("calli %d\n", sign_extend(dc->imm26, 26) * 4);
343
344 tcg_gen_movi_tl(cpu_R[R_RA], dc->pc + 4);
345 gen_goto_tb(dc, 0, dc->pc + (sign_extend(dc->imm26 << 2, 26)));
346
347 dc->is_jmp = DISAS_TB_JUMP;
348}
349
350static inline void gen_compare(DisasContext *dc, int cond)
351{
352 int i;
353
354 if (dc->format == OP_FMT_RI) {
355 switch (cond) {
356 case TCG_COND_GEU:
357 case TCG_COND_GTU:
358 i = zero_extend(dc->imm16, 16);
359 break;
360 default:
361 i = sign_extend(dc->imm16, 16);
362 break;
363 }
364
365 tcg_gen_setcondi_tl(cond, cpu_R[dc->r1], cpu_R[dc->r0], i);
366 } else {
367 tcg_gen_setcond_tl(cond, cpu_R[dc->r2], cpu_R[dc->r0], cpu_R[dc->r1]);
368 }
369}
370
371static void dec_cmpe(DisasContext *dc)
372{
373 if (dc->format == OP_FMT_RI) {
374 LOG_DIS("cmpei r%d, r%d, %d\n", dc->r1, dc->r0,
375 sign_extend(dc->imm16, 16));
376 } else {
377 LOG_DIS("cmpe r%d, r%d, r%d\n", dc->r2, dc->r0, dc->r1);
378 }
379
380 gen_compare(dc, TCG_COND_EQ);
381}
382
383static void dec_cmpg(DisasContext *dc)
384{
385 if (dc->format == OP_FMT_RI) {
386 LOG_DIS("cmpgi r%d, r%d, %d\n", dc->r1, dc->r0,
387 sign_extend(dc->imm16, 16));
388 } else {
389 LOG_DIS("cmpg r%d, r%d, r%d\n", dc->r2, dc->r0, dc->r1);
390 }
391
392 gen_compare(dc, TCG_COND_GT);
393}
394
395static void dec_cmpge(DisasContext *dc)
396{
397 if (dc->format == OP_FMT_RI) {
398 LOG_DIS("cmpgei r%d, r%d, %d\n", dc->r1, dc->r0,
399 sign_extend(dc->imm16, 16));
400 } else {
401 LOG_DIS("cmpge r%d, r%d, r%d\n", dc->r2, dc->r0, dc->r1);
402 }
403
404 gen_compare(dc, TCG_COND_GE);
405}
406
407static void dec_cmpgeu(DisasContext *dc)
408{
409 if (dc->format == OP_FMT_RI) {
410 LOG_DIS("cmpgeui r%d, r%d, %d\n", dc->r1, dc->r0,
411 zero_extend(dc->imm16, 16));
412 } else {
413 LOG_DIS("cmpgeu r%d, r%d, r%d\n", dc->r2, dc->r0, dc->r1);
414 }
415
416 gen_compare(dc, TCG_COND_GEU);
417}
418
419static void dec_cmpgu(DisasContext *dc)
420{
421 if (dc->format == OP_FMT_RI) {
422 LOG_DIS("cmpgui r%d, r%d, %d\n", dc->r1, dc->r0,
423 zero_extend(dc->imm16, 16));
424 } else {
425 LOG_DIS("cmpgu r%d, r%d, r%d\n", dc->r2, dc->r0, dc->r1);
426 }
427
428 gen_compare(dc, TCG_COND_GTU);
429}
430
431static void dec_cmpne(DisasContext *dc)
432{
433 if (dc->format == OP_FMT_RI) {
434 LOG_DIS("cmpnei r%d, r%d, %d\n", dc->r1, dc->r0,
435 sign_extend(dc->imm16, 16));
436 } else {
437 LOG_DIS("cmpne r%d, r%d, r%d\n", dc->r2, dc->r0, dc->r1);
438 }
439
440 gen_compare(dc, TCG_COND_NE);
441}
442
443static void dec_divu(DisasContext *dc)
444{
445 TCGLabel *l1;
446
447 LOG_DIS("divu r%d, r%d, r%d\n", dc->r2, dc->r0, dc->r1);
448
449 if (!(dc->features & LM32_FEATURE_DIVIDE)) {
450 qemu_log_mask(LOG_GUEST_ERROR, "hardware divider is not available\n");
451 t_gen_illegal_insn(dc);
452 return;
453 }
454
455 l1 = gen_new_label();
456 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_R[dc->r1], 0, l1);
457 tcg_gen_movi_tl(cpu_pc, dc->pc);
458 t_gen_raise_exception(dc, EXCP_DIVIDE_BY_ZERO);
459 gen_set_label(l1);
460 tcg_gen_divu_tl(cpu_R[dc->r2], cpu_R[dc->r0], cpu_R[dc->r1]);
461}
462
463static void dec_lb(DisasContext *dc)
464{
465 TCGv t0;
466
467 LOG_DIS("lb r%d, (r%d+%d)\n", dc->r1, dc->r0, dc->imm16);
468
469 t0 = tcg_temp_new();
470 tcg_gen_addi_tl(t0, cpu_R[dc->r0], sign_extend(dc->imm16, 16));
471 tcg_gen_qemu_ld8s(cpu_R[dc->r1], t0, MEM_INDEX);
472 tcg_temp_free(t0);
473}
474
475static void dec_lbu(DisasContext *dc)
476{
477 TCGv t0;
478
479 LOG_DIS("lbu r%d, (r%d+%d)\n", dc->r1, dc->r0, dc->imm16);
480
481 t0 = tcg_temp_new();
482 tcg_gen_addi_tl(t0, cpu_R[dc->r0], sign_extend(dc->imm16, 16));
483 tcg_gen_qemu_ld8u(cpu_R[dc->r1], t0, MEM_INDEX);
484 tcg_temp_free(t0);
485}
486
487static void dec_lh(DisasContext *dc)
488{
489 TCGv t0;
490
491 LOG_DIS("lh r%d, (r%d+%d)\n", dc->r1, dc->r0, dc->imm16);
492
493 t0 = tcg_temp_new();
494 tcg_gen_addi_tl(t0, cpu_R[dc->r0], sign_extend(dc->imm16, 16));
495 tcg_gen_qemu_ld16s(cpu_R[dc->r1], t0, MEM_INDEX);
496 tcg_temp_free(t0);
497}
498
499static void dec_lhu(DisasContext *dc)
500{
501 TCGv t0;
502
503 LOG_DIS("lhu r%d, (r%d+%d)\n", dc->r1, dc->r0, dc->imm16);
504
505 t0 = tcg_temp_new();
506 tcg_gen_addi_tl(t0, cpu_R[dc->r0], sign_extend(dc->imm16, 16));
507 tcg_gen_qemu_ld16u(cpu_R[dc->r1], t0, MEM_INDEX);
508 tcg_temp_free(t0);
509}
510
511static void dec_lw(DisasContext *dc)
512{
513 TCGv t0;
514
515 LOG_DIS("lw r%d, (r%d+%d)\n", dc->r1, dc->r0, sign_extend(dc->imm16, 16));
516
517 t0 = tcg_temp_new();
518 tcg_gen_addi_tl(t0, cpu_R[dc->r0], sign_extend(dc->imm16, 16));
519 tcg_gen_qemu_ld32s(cpu_R[dc->r1], t0, MEM_INDEX);
520 tcg_temp_free(t0);
521}
522
523static void dec_modu(DisasContext *dc)
524{
525 TCGLabel *l1;
526
527 LOG_DIS("modu r%d, r%d, %d\n", dc->r2, dc->r0, dc->r1);
528
529 if (!(dc->features & LM32_FEATURE_DIVIDE)) {
530 qemu_log_mask(LOG_GUEST_ERROR, "hardware divider is not available\n");
531 t_gen_illegal_insn(dc);
532 return;
533 }
534
535 l1 = gen_new_label();
536 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_R[dc->r1], 0, l1);
537 tcg_gen_movi_tl(cpu_pc, dc->pc);
538 t_gen_raise_exception(dc, EXCP_DIVIDE_BY_ZERO);
539 gen_set_label(l1);
540 tcg_gen_remu_tl(cpu_R[dc->r2], cpu_R[dc->r0], cpu_R[dc->r1]);
541}
542
543static void dec_mul(DisasContext *dc)
544{
545 if (dc->format == OP_FMT_RI) {
546 LOG_DIS("muli r%d, r%d, %d\n", dc->r1, dc->r0,
547 sign_extend(dc->imm16, 16));
548 } else {
549 LOG_DIS("mul r%d, r%d, r%d\n", dc->r2, dc->r0, dc->r1);
550 }
551
552 if (!(dc->features & LM32_FEATURE_MULTIPLY)) {
553 qemu_log_mask(LOG_GUEST_ERROR,
554 "hardware multiplier is not available\n");
555 t_gen_illegal_insn(dc);
556 return;
557 }
558
559 if (dc->format == OP_FMT_RI) {
560 tcg_gen_muli_tl(cpu_R[dc->r1], cpu_R[dc->r0],
561 sign_extend(dc->imm16, 16));
562 } else {
563 tcg_gen_mul_tl(cpu_R[dc->r2], cpu_R[dc->r0], cpu_R[dc->r1]);
564 }
565}
566
567static void dec_nor(DisasContext *dc)
568{
569 if (dc->format == OP_FMT_RI) {
570 LOG_DIS("nori r%d, r%d, %d\n", dc->r1, dc->r0,
571 zero_extend(dc->imm16, 16));
572 } else {
573 LOG_DIS("nor r%d, r%d, r%d\n", dc->r2, dc->r0, dc->r1);
574 }
575
576 if (dc->format == OP_FMT_RI) {
577 TCGv t0 = tcg_temp_new();
578 tcg_gen_movi_tl(t0, zero_extend(dc->imm16, 16));
579 tcg_gen_nor_tl(cpu_R[dc->r1], cpu_R[dc->r0], t0);
580 tcg_temp_free(t0);
581 } else {
582 tcg_gen_nor_tl(cpu_R[dc->r2], cpu_R[dc->r0], cpu_R[dc->r1]);
583 }
584}
585
586static void dec_or(DisasContext *dc)
587{
588 if (dc->format == OP_FMT_RI) {
589 LOG_DIS("ori r%d, r%d, %d\n", dc->r1, dc->r0,
590 zero_extend(dc->imm16, 16));
591 } else {
592 if (dc->r1 == R_R0) {
593 LOG_DIS("mv r%d, r%d\n", dc->r2, dc->r0);
594 } else {
595 LOG_DIS("or r%d, r%d, r%d\n", dc->r2, dc->r0, dc->r1);
596 }
597 }
598
599 if (dc->format == OP_FMT_RI) {
600 tcg_gen_ori_tl(cpu_R[dc->r1], cpu_R[dc->r0],
601 zero_extend(dc->imm16, 16));
602 } else {
603 tcg_gen_or_tl(cpu_R[dc->r2], cpu_R[dc->r0], cpu_R[dc->r1]);
604 }
605}
606
607static void dec_orhi(DisasContext *dc)
608{
609 if (dc->r0 == R_R0) {
610 LOG_DIS("mvhi r%d, %d\n", dc->r1, dc->imm16);
611 } else {
612 LOG_DIS("orhi r%d, r%d, %d\n", dc->r1, dc->r0, dc->imm16);
613 }
614
615 tcg_gen_ori_tl(cpu_R[dc->r1], cpu_R[dc->r0], (dc->imm16 << 16));
616}
617
618static void dec_scall(DisasContext *dc)
619{
620 switch (dc->imm5) {
621 case 2:
622 LOG_DIS("break\n");
623 tcg_gen_movi_tl(cpu_pc, dc->pc);
624 t_gen_raise_exception(dc, EXCP_BREAKPOINT);
625 break;
626 case 7:
627 LOG_DIS("scall\n");
628 tcg_gen_movi_tl(cpu_pc, dc->pc);
629 t_gen_raise_exception(dc, EXCP_SYSTEMCALL);
630 break;
631 default:
632 qemu_log_mask(LOG_GUEST_ERROR, "invalid opcode @0x%x", dc->pc);
633 t_gen_illegal_insn(dc);
634 break;
635 }
636}
637
638static void dec_rcsr(DisasContext *dc)
639{
640 LOG_DIS("rcsr r%d, %d\n", dc->r2, dc->csr);
641
642 switch (dc->csr) {
643 case CSR_IE:
644 tcg_gen_mov_tl(cpu_R[dc->r2], cpu_ie);
645 break;
646 case CSR_IM:
647 gen_helper_rcsr_im(cpu_R[dc->r2], cpu_env);
648 break;
649 case CSR_IP:
650 gen_helper_rcsr_ip(cpu_R[dc->r2], cpu_env);
651 break;
652 case CSR_CC:
653 tcg_gen_mov_tl(cpu_R[dc->r2], cpu_cc);
654 break;
655 case CSR_CFG:
656 tcg_gen_mov_tl(cpu_R[dc->r2], cpu_cfg);
657 break;
658 case CSR_EBA:
659 tcg_gen_mov_tl(cpu_R[dc->r2], cpu_eba);
660 break;
661 case CSR_DC:
662 tcg_gen_mov_tl(cpu_R[dc->r2], cpu_dc);
663 break;
664 case CSR_DEBA:
665 tcg_gen_mov_tl(cpu_R[dc->r2], cpu_deba);
666 break;
667 case CSR_JTX:
668 gen_helper_rcsr_jtx(cpu_R[dc->r2], cpu_env);
669 break;
670 case CSR_JRX:
671 gen_helper_rcsr_jrx(cpu_R[dc->r2], cpu_env);
672 break;
673 case CSR_ICC:
674 case CSR_DCC:
675 case CSR_BP0:
676 case CSR_BP1:
677 case CSR_BP2:
678 case CSR_BP3:
679 case CSR_WP0:
680 case CSR_WP1:
681 case CSR_WP2:
682 case CSR_WP3:
683 qemu_log_mask(LOG_GUEST_ERROR, "invalid read access csr=%x\n", dc->csr);
684 break;
685 default:
686 qemu_log_mask(LOG_GUEST_ERROR, "read_csr: unknown csr=%x\n", dc->csr);
687 break;
688 }
689}
690
691static void dec_sb(DisasContext *dc)
692{
693 TCGv t0;
694
695 LOG_DIS("sb (r%d+%d), r%d\n", dc->r0, dc->imm16, dc->r1);
696
697 t0 = tcg_temp_new();
698 tcg_gen_addi_tl(t0, cpu_R[dc->r0], sign_extend(dc->imm16, 16));
699 tcg_gen_qemu_st8(cpu_R[dc->r1], t0, MEM_INDEX);
700 tcg_temp_free(t0);
701}
702
703static void dec_sextb(DisasContext *dc)
704{
705 LOG_DIS("sextb r%d, r%d\n", dc->r2, dc->r0);
706
707 if (!(dc->features & LM32_FEATURE_SIGN_EXTEND)) {
708 qemu_log_mask(LOG_GUEST_ERROR,
709 "hardware sign extender is not available\n");
710 t_gen_illegal_insn(dc);
711 return;
712 }
713
714 tcg_gen_ext8s_tl(cpu_R[dc->r2], cpu_R[dc->r0]);
715}
716
717static void dec_sexth(DisasContext *dc)
718{
719 LOG_DIS("sexth r%d, r%d\n", dc->r2, dc->r0);
720
721 if (!(dc->features & LM32_FEATURE_SIGN_EXTEND)) {
722 qemu_log_mask(LOG_GUEST_ERROR,
723 "hardware sign extender is not available\n");
724 t_gen_illegal_insn(dc);
725 return;
726 }
727
728 tcg_gen_ext16s_tl(cpu_R[dc->r2], cpu_R[dc->r0]);
729}
730
731static void dec_sh(DisasContext *dc)
732{
733 TCGv t0;
734
735 LOG_DIS("sh (r%d+%d), r%d\n", dc->r0, dc->imm16, dc->r1);
736
737 t0 = tcg_temp_new();
738 tcg_gen_addi_tl(t0, cpu_R[dc->r0], sign_extend(dc->imm16, 16));
739 tcg_gen_qemu_st16(cpu_R[dc->r1], t0, MEM_INDEX);
740 tcg_temp_free(t0);
741}
742
743static void dec_sl(DisasContext *dc)
744{
745 if (dc->format == OP_FMT_RI) {
746 LOG_DIS("sli r%d, r%d, %d\n", dc->r1, dc->r0, dc->imm5);
747 } else {
748 LOG_DIS("sl r%d, r%d, r%d\n", dc->r2, dc->r0, dc->r1);
749 }
750
751 if (!(dc->features & LM32_FEATURE_SHIFT)) {
752 qemu_log_mask(LOG_GUEST_ERROR, "hardware shifter is not available\n");
753 t_gen_illegal_insn(dc);
754 return;
755 }
756
757 if (dc->format == OP_FMT_RI) {
758 tcg_gen_shli_tl(cpu_R[dc->r1], cpu_R[dc->r0], dc->imm5);
759 } else {
760 TCGv t0 = tcg_temp_new();
761 tcg_gen_andi_tl(t0, cpu_R[dc->r1], 0x1f);
762 tcg_gen_shl_tl(cpu_R[dc->r2], cpu_R[dc->r0], t0);
763 tcg_temp_free(t0);
764 }
765}
766
767static void dec_sr(DisasContext *dc)
768{
769 if (dc->format == OP_FMT_RI) {
770 LOG_DIS("sri r%d, r%d, %d\n", dc->r1, dc->r0, dc->imm5);
771 } else {
772 LOG_DIS("sr r%d, r%d, r%d\n", dc->r2, dc->r0, dc->r1);
773 }
774
775
776
777 if (dc->format == OP_FMT_RI) {
778 if (!(dc->features & LM32_FEATURE_SHIFT) && (dc->imm5 != 1)) {
779 qemu_log_mask(LOG_GUEST_ERROR,
780 "hardware shifter is not available\n");
781 t_gen_illegal_insn(dc);
782 return;
783 }
784 tcg_gen_sari_tl(cpu_R[dc->r1], cpu_R[dc->r0], dc->imm5);
785 } else {
786 TCGLabel *l1 = gen_new_label();
787 TCGLabel *l2 = gen_new_label();
788 TCGv t0 = tcg_temp_local_new();
789 tcg_gen_andi_tl(t0, cpu_R[dc->r1], 0x1f);
790
791 if (!(dc->features & LM32_FEATURE_SHIFT)) {
792 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 1, l1);
793 t_gen_illegal_insn(dc);
794 tcg_gen_br(l2);
795 }
796
797 gen_set_label(l1);
798 tcg_gen_sar_tl(cpu_R[dc->r2], cpu_R[dc->r0], t0);
799 gen_set_label(l2);
800
801 tcg_temp_free(t0);
802 }
803}
804
805static void dec_sru(DisasContext *dc)
806{
807 if (dc->format == OP_FMT_RI) {
808 LOG_DIS("srui r%d, r%d, %d\n", dc->r1, dc->r0, dc->imm5);
809 } else {
810 LOG_DIS("sru r%d, r%d, r%d\n", dc->r2, dc->r0, dc->r1);
811 }
812
813 if (dc->format == OP_FMT_RI) {
814 if (!(dc->features & LM32_FEATURE_SHIFT) && (dc->imm5 != 1)) {
815 qemu_log_mask(LOG_GUEST_ERROR,
816 "hardware shifter is not available\n");
817 t_gen_illegal_insn(dc);
818 return;
819 }
820 tcg_gen_shri_tl(cpu_R[dc->r1], cpu_R[dc->r0], dc->imm5);
821 } else {
822 TCGLabel *l1 = gen_new_label();
823 TCGLabel *l2 = gen_new_label();
824 TCGv t0 = tcg_temp_local_new();
825 tcg_gen_andi_tl(t0, cpu_R[dc->r1], 0x1f);
826
827 if (!(dc->features & LM32_FEATURE_SHIFT)) {
828 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 1, l1);
829 t_gen_illegal_insn(dc);
830 tcg_gen_br(l2);
831 }
832
833 gen_set_label(l1);
834 tcg_gen_shr_tl(cpu_R[dc->r2], cpu_R[dc->r0], t0);
835 gen_set_label(l2);
836
837 tcg_temp_free(t0);
838 }
839}
840
841static void dec_sub(DisasContext *dc)
842{
843 LOG_DIS("sub r%d, r%d, r%d\n", dc->r2, dc->r0, dc->r1);
844
845 tcg_gen_sub_tl(cpu_R[dc->r2], cpu_R[dc->r0], cpu_R[dc->r1]);
846}
847
848static void dec_sw(DisasContext *dc)
849{
850 TCGv t0;
851
852 LOG_DIS("sw (r%d+%d), r%d\n", dc->r0, sign_extend(dc->imm16, 16), dc->r1);
853
854 t0 = tcg_temp_new();
855 tcg_gen_addi_tl(t0, cpu_R[dc->r0], sign_extend(dc->imm16, 16));
856 tcg_gen_qemu_st32(cpu_R[dc->r1], t0, MEM_INDEX);
857 tcg_temp_free(t0);
858}
859
860static void dec_user(DisasContext *dc)
861{
862 LOG_DIS("user");
863
864 qemu_log_mask(LOG_GUEST_ERROR, "user instruction undefined\n");
865 t_gen_illegal_insn(dc);
866}
867
868static void dec_wcsr(DisasContext *dc)
869{
870 int no;
871
872 LOG_DIS("wcsr %d, r%d\n", dc->csr, dc->r1);
873
874 switch (dc->csr) {
875 case CSR_IE:
876 tcg_gen_mov_tl(cpu_ie, cpu_R[dc->r1]);
877 tcg_gen_movi_tl(cpu_pc, dc->pc + 4);
878 dc->is_jmp = DISAS_UPDATE;
879 break;
880 case CSR_IM:
881
882 if (tb_cflags(dc->tb) & CF_USE_ICOUNT) {
883 gen_io_start();
884 }
885 gen_helper_wcsr_im(cpu_env, cpu_R[dc->r1]);
886 tcg_gen_movi_tl(cpu_pc, dc->pc + 4);
887 if (tb_cflags(dc->tb) & CF_USE_ICOUNT) {
888 gen_io_end();
889 }
890 dc->is_jmp = DISAS_UPDATE;
891 break;
892 case CSR_IP:
893
894 if (tb_cflags(dc->tb) & CF_USE_ICOUNT) {
895 gen_io_start();
896 }
897 gen_helper_wcsr_ip(cpu_env, cpu_R[dc->r1]);
898 tcg_gen_movi_tl(cpu_pc, dc->pc + 4);
899 if (tb_cflags(dc->tb) & CF_USE_ICOUNT) {
900 gen_io_end();
901 }
902 dc->is_jmp = DISAS_UPDATE;
903 break;
904 case CSR_ICC:
905
906 break;
907 case CSR_DCC:
908
909 break;
910 case CSR_EBA:
911 tcg_gen_mov_tl(cpu_eba, cpu_R[dc->r1]);
912 break;
913 case CSR_DEBA:
914 tcg_gen_mov_tl(cpu_deba, cpu_R[dc->r1]);
915 break;
916 case CSR_JTX:
917 gen_helper_wcsr_jtx(cpu_env, cpu_R[dc->r1]);
918 break;
919 case CSR_JRX:
920 gen_helper_wcsr_jrx(cpu_env, cpu_R[dc->r1]);
921 break;
922 case CSR_DC:
923 gen_helper_wcsr_dc(cpu_env, cpu_R[dc->r1]);
924 break;
925 case CSR_BP0:
926 case CSR_BP1:
927 case CSR_BP2:
928 case CSR_BP3:
929 no = dc->csr - CSR_BP0;
930 if (dc->num_breakpoints <= no) {
931 qemu_log_mask(LOG_GUEST_ERROR,
932 "breakpoint #%i is not available\n", no);
933 t_gen_illegal_insn(dc);
934 break;
935 }
936 gen_helper_wcsr_bp(cpu_env, cpu_R[dc->r1], tcg_const_i32(no));
937 break;
938 case CSR_WP0:
939 case CSR_WP1:
940 case CSR_WP2:
941 case CSR_WP3:
942 no = dc->csr - CSR_WP0;
943 if (dc->num_watchpoints <= no) {
944 qemu_log_mask(LOG_GUEST_ERROR,
945 "watchpoint #%i is not available\n", no);
946 t_gen_illegal_insn(dc);
947 break;
948 }
949 gen_helper_wcsr_wp(cpu_env, cpu_R[dc->r1], tcg_const_i32(no));
950 break;
951 case CSR_CC:
952 case CSR_CFG:
953 qemu_log_mask(LOG_GUEST_ERROR, "invalid write access csr=%x\n",
954 dc->csr);
955 break;
956 default:
957 qemu_log_mask(LOG_GUEST_ERROR, "write_csr: unknown csr=%x\n",
958 dc->csr);
959 break;
960 }
961}
962
963static void dec_xnor(DisasContext *dc)
964{
965 if (dc->format == OP_FMT_RI) {
966 LOG_DIS("xnori r%d, r%d, %d\n", dc->r1, dc->r0,
967 zero_extend(dc->imm16, 16));
968 } else {
969 if (dc->r1 == R_R0) {
970 LOG_DIS("not r%d, r%d\n", dc->r2, dc->r0);
971 } else {
972 LOG_DIS("xnor r%d, r%d, r%d\n", dc->r2, dc->r0, dc->r1);
973 }
974 }
975
976 if (dc->format == OP_FMT_RI) {
977 tcg_gen_xori_tl(cpu_R[dc->r1], cpu_R[dc->r0],
978 zero_extend(dc->imm16, 16));
979 tcg_gen_not_tl(cpu_R[dc->r1], cpu_R[dc->r1]);
980 } else {
981 tcg_gen_eqv_tl(cpu_R[dc->r2], cpu_R[dc->r0], cpu_R[dc->r1]);
982 }
983}
984
985static void dec_xor(DisasContext *dc)
986{
987 if (dc->format == OP_FMT_RI) {
988 LOG_DIS("xori r%d, r%d, %d\n", dc->r1, dc->r0,
989 zero_extend(dc->imm16, 16));
990 } else {
991 LOG_DIS("xor r%d, r%d, r%d\n", dc->r2, dc->r0, dc->r1);
992 }
993
994 if (dc->format == OP_FMT_RI) {
995 tcg_gen_xori_tl(cpu_R[dc->r1], cpu_R[dc->r0],
996 zero_extend(dc->imm16, 16));
997 } else {
998 tcg_gen_xor_tl(cpu_R[dc->r2], cpu_R[dc->r0], cpu_R[dc->r1]);
999 }
1000}
1001
1002static void dec_ill(DisasContext *dc)
1003{
1004 qemu_log_mask(LOG_GUEST_ERROR, "invalid opcode 0x%02x\n", dc->opcode);
1005 t_gen_illegal_insn(dc);
1006}
1007
1008typedef void (*DecoderInfo)(DisasContext *dc);
1009static const DecoderInfo decinfo[] = {
1010 dec_sru, dec_nor, dec_mul, dec_sh, dec_lb, dec_sr, dec_xor, dec_lh,
1011 dec_and, dec_xnor, dec_lw, dec_lhu, dec_sb, dec_add, dec_or, dec_sl,
1012 dec_lbu, dec_be, dec_bg, dec_bge, dec_bgeu, dec_bgu, dec_sw, dec_bne,
1013 dec_andhi, dec_cmpe, dec_cmpg, dec_cmpge, dec_cmpgeu, dec_cmpgu, dec_orhi,
1014 dec_cmpne,
1015 dec_sru, dec_nor, dec_mul, dec_divu, dec_rcsr, dec_sr, dec_xor, dec_ill,
1016 dec_and, dec_xnor, dec_ill, dec_scall, dec_sextb, dec_add, dec_or, dec_sl,
1017 dec_b, dec_modu, dec_sub, dec_user, dec_wcsr, dec_ill, dec_call, dec_sexth,
1018 dec_bi, dec_cmpe, dec_cmpg, dec_cmpge, dec_cmpgeu, dec_cmpgu, dec_calli,
1019 dec_cmpne
1020};
1021
1022static inline void decode(DisasContext *dc, uint32_t ir)
1023{
1024 dc->ir = ir;
1025 LOG_DIS("%8.8x\t", dc->ir);
1026
1027 dc->opcode = EXTRACT_FIELD(ir, 26, 31);
1028
1029 dc->imm5 = EXTRACT_FIELD(ir, 0, 4);
1030 dc->imm16 = EXTRACT_FIELD(ir, 0, 15);
1031 dc->imm26 = EXTRACT_FIELD(ir, 0, 25);
1032
1033 dc->csr = EXTRACT_FIELD(ir, 21, 25);
1034 dc->r0 = EXTRACT_FIELD(ir, 21, 25);
1035 dc->r1 = EXTRACT_FIELD(ir, 16, 20);
1036 dc->r2 = EXTRACT_FIELD(ir, 11, 15);
1037
1038
1039 if (ir & (1 << 31)) {
1040 dc->format = OP_FMT_RR;
1041 } else {
1042 dc->format = OP_FMT_RI;
1043 }
1044
1045 assert(ARRAY_SIZE(decinfo) == 64);
1046 assert(dc->opcode < 64);
1047
1048 decinfo[dc->opcode](dc);
1049}
1050
1051
1052void gen_intermediate_code(CPUState *cs, struct TranslationBlock *tb)
1053{
1054 CPULM32State *env = cs->env_ptr;
1055 LM32CPU *cpu = lm32_env_get_cpu(env);
1056 struct DisasContext ctx, *dc = &ctx;
1057 uint32_t pc_start;
1058 uint32_t page_start;
1059 int num_insns;
1060 int max_insns;
1061
1062 pc_start = tb->pc;
1063 dc->features = cpu->features;
1064 dc->num_breakpoints = cpu->num_breakpoints;
1065 dc->num_watchpoints = cpu->num_watchpoints;
1066 dc->tb = tb;
1067
1068 dc->is_jmp = DISAS_NEXT;
1069 dc->pc = pc_start;
1070 dc->singlestep_enabled = cs->singlestep_enabled;
1071
1072 if (pc_start & 3) {
1073 qemu_log_mask(LOG_GUEST_ERROR,
1074 "unaligned PC=%x. Ignoring lowest bits.\n", pc_start);
1075 pc_start &= ~3;
1076 }
1077
1078 page_start = pc_start & TARGET_PAGE_MASK;
1079 num_insns = 0;
1080 max_insns = tb_cflags(tb) & CF_COUNT_MASK;
1081 if (max_insns == 0) {
1082 max_insns = CF_COUNT_MASK;
1083 }
1084 if (max_insns > TCG_MAX_INSNS) {
1085 max_insns = TCG_MAX_INSNS;
1086 }
1087
1088 gen_tb_start(tb);
1089 do {
1090 tcg_gen_insn_start(dc->pc);
1091 num_insns++;
1092
1093 if (unlikely(cpu_breakpoint_test(cs, dc->pc, BP_ANY))) {
1094 tcg_gen_movi_tl(cpu_pc, dc->pc);
1095 t_gen_raise_exception(dc, EXCP_DEBUG);
1096 dc->is_jmp = DISAS_UPDATE;
1097
1098
1099
1100
1101 dc->pc += 4;
1102 break;
1103 }
1104
1105
1106 LOG_DIS("%8.8x:\t", dc->pc);
1107
1108 if (num_insns == max_insns && (tb_cflags(tb) & CF_LAST_IO)) {
1109 gen_io_start();
1110 }
1111
1112 decode(dc, cpu_ldl_code(env, dc->pc));
1113 dc->pc += 4;
1114 } while (!dc->is_jmp
1115 && !tcg_op_buf_full()
1116 && !cs->singlestep_enabled
1117 && !singlestep
1118 && (dc->pc - page_start < TARGET_PAGE_SIZE)
1119 && num_insns < max_insns);
1120
1121 if (tb_cflags(tb) & CF_LAST_IO) {
1122 gen_io_end();
1123 }
1124
1125 if (unlikely(cs->singlestep_enabled)) {
1126 if (dc->is_jmp == DISAS_NEXT) {
1127 tcg_gen_movi_tl(cpu_pc, dc->pc);
1128 }
1129 t_gen_raise_exception(dc, EXCP_DEBUG);
1130 } else {
1131 switch (dc->is_jmp) {
1132 case DISAS_NEXT:
1133 gen_goto_tb(dc, 1, dc->pc);
1134 break;
1135 default:
1136 case DISAS_JUMP:
1137 case DISAS_UPDATE:
1138
1139
1140 tcg_gen_exit_tb(NULL, 0);
1141 break;
1142 case DISAS_TB_JUMP:
1143
1144 break;
1145 }
1146 }
1147
1148 gen_tb_end(tb, num_insns);
1149
1150 tb->size = dc->pc - pc_start;
1151 tb->icount = num_insns;
1152
1153#ifdef DEBUG_DISAS
1154 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)
1155 && qemu_log_in_addr_range(pc_start)) {
1156 qemu_log_lock();
1157 qemu_log("\n");
1158 log_target_disas(cs, pc_start, dc->pc - pc_start);
1159 qemu_log_unlock();
1160 }
1161#endif
1162}
1163
1164void lm32_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
1165 int flags)
1166{
1167 LM32CPU *cpu = LM32_CPU(cs);
1168 CPULM32State *env = &cpu->env;
1169 int i;
1170
1171 if (!env || !f) {
1172 return;
1173 }
1174
1175 cpu_fprintf(f, "IN: PC=%x %s\n",
1176 env->pc, lookup_symbol(env->pc));
1177
1178 cpu_fprintf(f, "ie=%8.8x (IE=%x EIE=%x BIE=%x) im=%8.8x ip=%8.8x\n",
1179 env->ie,
1180 (env->ie & IE_IE) ? 1 : 0,
1181 (env->ie & IE_EIE) ? 1 : 0,
1182 (env->ie & IE_BIE) ? 1 : 0,
1183 lm32_pic_get_im(env->pic_state),
1184 lm32_pic_get_ip(env->pic_state));
1185 cpu_fprintf(f, "eba=%8.8x deba=%8.8x\n",
1186 env->eba,
1187 env->deba);
1188
1189 for (i = 0; i < 32; i++) {
1190 cpu_fprintf(f, "r%2.2d=%8.8x ", i, env->regs[i]);
1191 if ((i + 1) % 4 == 0) {
1192 cpu_fprintf(f, "\n");
1193 }
1194 }
1195 cpu_fprintf(f, "\n\n");
1196}
1197
1198void restore_state_to_opc(CPULM32State *env, TranslationBlock *tb,
1199 target_ulong *data)
1200{
1201 env->pc = data[0];
1202}
1203
1204void lm32_translate_init(void)
1205{
1206 int i;
1207
1208 for (i = 0; i < ARRAY_SIZE(cpu_R); i++) {
1209 cpu_R[i] = tcg_global_mem_new(cpu_env,
1210 offsetof(CPULM32State, regs[i]),
1211 regnames[i]);
1212 }
1213
1214 for (i = 0; i < ARRAY_SIZE(cpu_bp); i++) {
1215 cpu_bp[i] = tcg_global_mem_new(cpu_env,
1216 offsetof(CPULM32State, bp[i]),
1217 regnames[32+i]);
1218 }
1219
1220 for (i = 0; i < ARRAY_SIZE(cpu_wp); i++) {
1221 cpu_wp[i] = tcg_global_mem_new(cpu_env,
1222 offsetof(CPULM32State, wp[i]),
1223 regnames[36+i]);
1224 }
1225
1226 cpu_pc = tcg_global_mem_new(cpu_env,
1227 offsetof(CPULM32State, pc),
1228 "pc");
1229 cpu_ie = tcg_global_mem_new(cpu_env,
1230 offsetof(CPULM32State, ie),
1231 "ie");
1232 cpu_icc = tcg_global_mem_new(cpu_env,
1233 offsetof(CPULM32State, icc),
1234 "icc");
1235 cpu_dcc = tcg_global_mem_new(cpu_env,
1236 offsetof(CPULM32State, dcc),
1237 "dcc");
1238 cpu_cc = tcg_global_mem_new(cpu_env,
1239 offsetof(CPULM32State, cc),
1240 "cc");
1241 cpu_cfg = tcg_global_mem_new(cpu_env,
1242 offsetof(CPULM32State, cfg),
1243 "cfg");
1244 cpu_eba = tcg_global_mem_new(cpu_env,
1245 offsetof(CPULM32State, eba),
1246 "eba");
1247 cpu_dc = tcg_global_mem_new(cpu_env,
1248 offsetof(CPULM32State, dc),
1249 "dc");
1250 cpu_deba = tcg_global_mem_new(cpu_env,
1251 offsetof(CPULM32State, deba),
1252 "deba");
1253}
1254
1255