]> git.proxmox.com Git - mirror_qemu.git/blame - target/lm32/translate.c
target/cris: avoid integer overflow in next_page PC check
[mirror_qemu.git] / target / lm32 / translate.c
CommitLineData
17c0fa3d
MW
1/*
2 * LatticeMico32 main translation routines.
3 *
4 * Copyright (c) 2010 Michael Walle <michael@walle.cc>
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 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 <http://www.gnu.org/licenses/>.
18 */
19
ea99dde1 20#include "qemu/osdep.h"
17c0fa3d 21#include "cpu.h"
76cad711 22#include "disas/disas.h"
2ef6175a 23#include "exec/helper-proto.h"
63c91552 24#include "exec/exec-all.h"
77fc6f5e 25#include "exec/translator.h"
17c0fa3d 26#include "tcg-op.h"
17c0fa3d 27
f08b6170 28#include "exec/cpu_ldst.h"
0d09e41a 29#include "hw/lm32/lm32_pic.h"
17c0fa3d 30
2ef6175a 31#include "exec/helper-gen.h"
17c0fa3d 32
a7e30d84 33#include "trace-tcg.h"
508127e2 34#include "exec/log.h"
a7e30d84
LV
35
36
19f846b1
MW
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)
17c0fa3d
MW
45
46#define EXTRACT_FIELD(src, start, end) \
47 (((src) >> start) & ((1 << (end - start + 1)) - 1))
48
49#define MEM_INDEX 0
50
77fc6f5e
LV
51/* is_jmp field values */
52#define DISAS_JUMP DISAS_TARGET_0 /* only pc was modified dynamically */
53#define DISAS_UPDATE DISAS_TARGET_1 /* cpu state was modified dynamically */
54#define DISAS_TB_JUMP DISAS_TARGET_2 /* only pc was modified statically */
55
17c0fa3d
MW
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
022c62cb 69#include "exec/gen-icount.h"
17c0fa3d
MW
70
71enum {
72 OP_FMT_RI,
73 OP_FMT_RR,
74 OP_FMT_CR,
75 OP_FMT_I
76};
77
78/* This is the state at translation time. */
79typedef struct DisasContext {
17c0fa3d
MW
80 target_ulong pc;
81
82 /* Decoder. */
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; /* tb dependent flags. */
93 int is_jmp;
94
17c0fa3d
MW
95 struct TranslationBlock *tb;
96 int singlestep_enabled;
34f4aa83
MW
97
98 uint32_t features;
99 uint8_t num_breakpoints;
100 uint8_t num_watchpoints;
17c0fa3d
MW
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 /* LSL. */
122 val <<= 32 - width;
123 sval = val;
124 /* ASR. */
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
32ac0ca2 134 gen_helper_raise_exception(cpu_env, tmp);
17c0fa3d
MW
135 tcg_temp_free_i32(tmp);
136}
137
667ff961
MW
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
90aa39a1 144static inline bool use_goto_tb(DisasContext *dc, target_ulong dest)
17c0fa3d 145{
90aa39a1
SF
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}
17c0fa3d 156
90aa39a1
SF
157static void gen_goto_tb(DisasContext *dc, int n, target_ulong dest)
158{
159 if (use_goto_tb(dc, dest)) {
17c0fa3d
MW
160 tcg_gen_goto_tb(n);
161 tcg_gen_movi_tl(cpu_pc, dest);
90aa39a1 162 tcg_gen_exit_tb((uintptr_t)dc->tb + n);
17c0fa3d
MW
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(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);
32ac0ca2 212 gen_helper_hlt(cpu_env);
17c0fa3d
MW
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{
95f7983b 221 LOG_DIS("andhi r%d, r%d, %d\n", dc->r1, dc->r0, dc->imm16);
17c0fa3d
MW
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 /* restore IE.IE in case of an eret */
239 if (dc->r0 == R_EA) {
240 TCGv t0 = tcg_temp_new();
42a268c2 241 TCGLabel *l1 = gen_new_label();
17c0fa3d
MW
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();
42a268c2 250 TCGLabel *l1 = gen_new_label();
17c0fa3d
MW
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{
42a268c2 274 TCGLabel *l1 = gen_new_label();
17c0fa3d
MW
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{
95f7983b 284 LOG_DIS("be r%d, r%d, %d\n", dc->r1, dc->r0,
17c0fa3d
MW
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{
95f7983b 292 LOG_DIS("bg r%d, r%d, %d\n", dc->r1, dc->r0,
17c0fa3d
MW
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{
95f7983b 300 LOG_DIS("bge r%d, r%d, %d\n", dc->r1, dc->r0,
17c0fa3d
MW
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{
95f7983b 308 LOG_DIS("bgeu r%d, r%d, %d\n", dc->r1, dc->r0,
17c0fa3d
MW
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{
95f7983b 316 LOG_DIS("bgu r%d, r%d, %d\n", dc->r1, dc->r0,
17c0fa3d
MW
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{
95f7983b 324 LOG_DIS("bne r%d, r%d, %d\n", dc->r1, dc->r0,
17c0fa3d
MW
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{
df5eb7d2 352 int i;
17c0fa3d
MW
353
354 if (dc->format == OP_FMT_RI) {
df5eb7d2
MW
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
0a04e11f 365 tcg_gen_setcondi_tl(cond, cpu_R[dc->r1], cpu_R[dc->r0], i);
17c0fa3d 366 } else {
0a04e11f 367 tcg_gen_setcond_tl(cond, cpu_R[dc->r2], cpu_R[dc->r0], cpu_R[dc->r1]);
17c0fa3d
MW
368 }
369}
370
371static void dec_cmpe(DisasContext *dc)
372{
373 if (dc->format == OP_FMT_RI) {
95f7983b 374 LOG_DIS("cmpei r%d, r%d, %d\n", dc->r1, dc->r0,
17c0fa3d
MW
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) {
95f7983b 386 LOG_DIS("cmpgi r%d, r%d, %d\n", dc->r1, dc->r0,
17c0fa3d
MW
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) {
95f7983b 398 LOG_DIS("cmpgei r%d, r%d, %d\n", dc->r1, dc->r0,
17c0fa3d
MW
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) {
95f7983b 410 LOG_DIS("cmpgeui r%d, r%d, %d\n", dc->r1, dc->r0,
df5eb7d2 411 zero_extend(dc->imm16, 16));
17c0fa3d
MW
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) {
95f7983b 422 LOG_DIS("cmpgui r%d, r%d, %d\n", dc->r1, dc->r0,
df5eb7d2 423 zero_extend(dc->imm16, 16));
17c0fa3d
MW
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) {
95f7983b 434 LOG_DIS("cmpnei r%d, r%d, %d\n", dc->r1, dc->r0,
17c0fa3d
MW
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{
42a268c2 445 TCGLabel *l1;
17c0fa3d
MW
446
447 LOG_DIS("divu r%d, r%d, r%d\n", dc->r2, dc->r0, dc->r1);
448
34f4aa83 449 if (!(dc->features & LM32_FEATURE_DIVIDE)) {
3604a76f 450 qemu_log_mask(LOG_GUEST_ERROR, "hardware divider is not available\n");
667ff961 451 t_gen_illegal_insn(dc);
3604a76f 452 return;
17c0fa3d
MW
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{
42a268c2 525 TCGLabel *l1;
17c0fa3d
MW
526
527 LOG_DIS("modu r%d, r%d, %d\n", dc->r2, dc->r0, dc->r1);
528
34f4aa83 529 if (!(dc->features & LM32_FEATURE_DIVIDE)) {
3604a76f 530 qemu_log_mask(LOG_GUEST_ERROR, "hardware divider is not available\n");
667ff961 531 t_gen_illegal_insn(dc);
3604a76f 532 return;
17c0fa3d
MW
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) {
95f7983b 546 LOG_DIS("muli r%d, r%d, %d\n", dc->r1, dc->r0,
17c0fa3d
MW
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
34f4aa83 552 if (!(dc->features & LM32_FEATURE_MULTIPLY)) {
3604a76f
MW
553 qemu_log_mask(LOG_GUEST_ERROR,
554 "hardware multiplier is not available\n");
667ff961 555 t_gen_illegal_insn(dc);
3604a76f 556 return;
17c0fa3d
MW
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) {
95f7983b 570 LOG_DIS("nori r%d, r%d, %d\n", dc->r1, dc->r0,
17c0fa3d
MW
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
fcda9863 618static void dec_scall(DisasContext *dc)
17c0fa3d 619{
667ff961
MW
620 switch (dc->imm5) {
621 case 2:
17c0fa3d 622 LOG_DIS("break\n");
17c0fa3d
MW
623 tcg_gen_movi_tl(cpu_pc, dc->pc);
624 t_gen_raise_exception(dc, EXCP_BREAKPOINT);
667ff961
MW
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;
17c0fa3d
MW
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:
32ac0ca2 647 gen_helper_rcsr_im(cpu_R[dc->r2], cpu_env);
17c0fa3d
MW
648 break;
649 case CSR_IP:
32ac0ca2 650 gen_helper_rcsr_ip(cpu_R[dc->r2], cpu_env);
17c0fa3d
MW
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:
32ac0ca2 668 gen_helper_rcsr_jtx(cpu_R[dc->r2], cpu_env);
17c0fa3d
MW
669 break;
670 case CSR_JRX:
32ac0ca2 671 gen_helper_rcsr_jrx(cpu_R[dc->r2], cpu_env);
17c0fa3d
MW
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:
3604a76f 683 qemu_log_mask(LOG_GUEST_ERROR, "invalid read access csr=%x\n", dc->csr);
17c0fa3d
MW
684 break;
685 default:
3604a76f 686 qemu_log_mask(LOG_GUEST_ERROR, "read_csr: unknown csr=%x\n", dc->csr);
17c0fa3d
MW
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
34f4aa83 707 if (!(dc->features & LM32_FEATURE_SIGN_EXTEND)) {
3604a76f
MW
708 qemu_log_mask(LOG_GUEST_ERROR,
709 "hardware sign extender is not available\n");
667ff961 710 t_gen_illegal_insn(dc);
3604a76f 711 return;
17c0fa3d
MW
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
34f4aa83 721 if (!(dc->features & LM32_FEATURE_SIGN_EXTEND)) {
3604a76f
MW
722 qemu_log_mask(LOG_GUEST_ERROR,
723 "hardware sign extender is not available\n");
667ff961 724 t_gen_illegal_insn(dc);
3604a76f 725 return;
17c0fa3d
MW
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
34f4aa83 751 if (!(dc->features & LM32_FEATURE_SHIFT)) {
3604a76f 752 qemu_log_mask(LOG_GUEST_ERROR, "hardware shifter is not available\n");
667ff961 753 t_gen_illegal_insn(dc);
3604a76f 754 return;
17c0fa3d
MW
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
667ff961
MW
775 /* The real CPU (w/o hardware shifter) only supports right shift by exactly
776 * one bit */
17c0fa3d 777 if (dc->format == OP_FMT_RI) {
667ff961
MW
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 }
17c0fa3d
MW
784 tcg_gen_sari_tl(cpu_R[dc->r1], cpu_R[dc->r0], dc->imm5);
785 } else {
42a268c2
RH
786 TCGLabel *l1 = gen_new_label();
787 TCGLabel *l2 = gen_new_label();
667ff961 788 TCGv t0 = tcg_temp_local_new();
17c0fa3d 789 tcg_gen_andi_tl(t0, cpu_R[dc->r1], 0x1f);
667ff961
MW
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);
17c0fa3d 798 tcg_gen_sar_tl(cpu_R[dc->r2], cpu_R[dc->r0], t0);
667ff961
MW
799 gen_set_label(l2);
800
17c0fa3d
MW
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
17c0fa3d 813 if (dc->format == OP_FMT_RI) {
667ff961
MW
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 }
17c0fa3d
MW
820 tcg_gen_shri_tl(cpu_R[dc->r1], cpu_R[dc->r0], dc->imm5);
821 } else {
42a268c2
RH
822 TCGLabel *l1 = gen_new_label();
823 TCGLabel *l2 = gen_new_label();
667ff961 824 TCGv t0 = tcg_temp_local_new();
17c0fa3d 825 tcg_gen_andi_tl(t0, cpu_R[dc->r1], 0x1f);
667ff961
MW
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);
17c0fa3d 834 tcg_gen_shr_tl(cpu_R[dc->r2], cpu_R[dc->r0], t0);
667ff961
MW
835 gen_set_label(l2);
836
17c0fa3d
MW
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
3604a76f 864 qemu_log_mask(LOG_GUEST_ERROR, "user instruction undefined\n");
667ff961 865 t_gen_illegal_insn(dc);
17c0fa3d
MW
866}
867
868static void dec_wcsr(DisasContext *dc)
869{
870 int no;
871
49285e11 872 LOG_DIS("wcsr %d, r%d\n", dc->csr, dc->r1);
17c0fa3d
MW
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 /* mark as an io operation because it could cause an interrupt */
c5a49c63 882 if (tb_cflags(dc->tb) & CF_USE_ICOUNT) {
17c0fa3d
MW
883 gen_io_start();
884 }
32ac0ca2 885 gen_helper_wcsr_im(cpu_env, cpu_R[dc->r1]);
17c0fa3d 886 tcg_gen_movi_tl(cpu_pc, dc->pc + 4);
c5a49c63 887 if (tb_cflags(dc->tb) & CF_USE_ICOUNT) {
17c0fa3d
MW
888 gen_io_end();
889 }
890 dc->is_jmp = DISAS_UPDATE;
891 break;
892 case CSR_IP:
893 /* mark as an io operation because it could cause an interrupt */
c5a49c63 894 if (tb_cflags(dc->tb) & CF_USE_ICOUNT) {
17c0fa3d
MW
895 gen_io_start();
896 }
32ac0ca2 897 gen_helper_wcsr_ip(cpu_env, cpu_R[dc->r1]);
17c0fa3d 898 tcg_gen_movi_tl(cpu_pc, dc->pc + 4);
c5a49c63 899 if (tb_cflags(dc->tb) & CF_USE_ICOUNT) {
17c0fa3d
MW
900 gen_io_end();
901 }
902 dc->is_jmp = DISAS_UPDATE;
903 break;
904 case CSR_ICC:
905 /* TODO */
906 break;
907 case CSR_DCC:
908 /* TODO */
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:
32ac0ca2 917 gen_helper_wcsr_jtx(cpu_env, cpu_R[dc->r1]);
17c0fa3d
MW
918 break;
919 case CSR_JRX:
32ac0ca2 920 gen_helper_wcsr_jrx(cpu_env, cpu_R[dc->r1]);
17c0fa3d
MW
921 break;
922 case CSR_DC:
3dd3a2b9 923 gen_helper_wcsr_dc(cpu_env, cpu_R[dc->r1]);
17c0fa3d
MW
924 break;
925 case CSR_BP0:
926 case CSR_BP1:
927 case CSR_BP2:
928 case CSR_BP3:
929 no = dc->csr - CSR_BP0;
34f4aa83 930 if (dc->num_breakpoints <= no) {
3604a76f
MW
931 qemu_log_mask(LOG_GUEST_ERROR,
932 "breakpoint #%i is not available\n", no);
667ff961 933 t_gen_illegal_insn(dc);
3604a76f 934 break;
17c0fa3d 935 }
3dd3a2b9 936 gen_helper_wcsr_bp(cpu_env, cpu_R[dc->r1], tcg_const_i32(no));
17c0fa3d
MW
937 break;
938 case CSR_WP0:
939 case CSR_WP1:
940 case CSR_WP2:
941 case CSR_WP3:
942 no = dc->csr - CSR_WP0;
34f4aa83 943 if (dc->num_watchpoints <= no) {
3604a76f
MW
944 qemu_log_mask(LOG_GUEST_ERROR,
945 "watchpoint #%i is not available\n", no);
667ff961 946 t_gen_illegal_insn(dc);
3604a76f 947 break;
17c0fa3d 948 }
3dd3a2b9 949 gen_helper_wcsr_wp(cpu_env, cpu_R[dc->r1], tcg_const_i32(no));
17c0fa3d
MW
950 break;
951 case CSR_CC:
952 case CSR_CFG:
3604a76f
MW
953 qemu_log_mask(LOG_GUEST_ERROR, "invalid write access csr=%x\n",
954 dc->csr);
17c0fa3d
MW
955 break;
956 default:
3604a76f
MW
957 qemu_log_mask(LOG_GUEST_ERROR, "write_csr: unknown csr=%x\n",
958 dc->csr);
17c0fa3d
MW
959 break;
960 }
961}
962
963static void dec_xnor(DisasContext *dc)
964{
965 if (dc->format == OP_FMT_RI) {
95f7983b 966 LOG_DIS("xnori r%d, r%d, %d\n", dc->r1, dc->r0,
17c0fa3d
MW
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) {
95f7983b 988 LOG_DIS("xori r%d, r%d, %d\n", dc->r1, dc->r0,
17c0fa3d
MW
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
a5086f95
MW
1002static void dec_ill(DisasContext *dc)
1003{
3604a76f 1004 qemu_log_mask(LOG_GUEST_ERROR, "invalid opcode 0x%02x\n", dc->opcode);
667ff961 1005 t_gen_illegal_insn(dc);
a5086f95 1006}
17c0fa3d 1007
a5086f95 1008typedef void (*DecoderInfo)(DisasContext *dc);
17c0fa3d 1009static const DecoderInfo decinfo[] = {
a5086f95
MW
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
17c0fa3d
MW
1020};
1021
32ac0ca2 1022static inline void decode(DisasContext *dc, uint32_t ir)
17c0fa3d 1023{
32ac0ca2 1024 dc->ir = ir;
17c0fa3d
MW
1025 LOG_DIS("%8.8x\t", dc->ir);
1026
17c0fa3d
MW
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 /* bit 31 seems to indicate insn type. */
1039 if (ir & (1 << 31)) {
1040 dc->format = OP_FMT_RR;
1041 } else {
1042 dc->format = OP_FMT_RI;
1043 }
1044
a5086f95
MW
1045 assert(ARRAY_SIZE(decinfo) == 64);
1046 assert(dc->opcode < 64);
17c0fa3d 1047
a5086f95 1048 decinfo[dc->opcode](dc);
17c0fa3d
MW
1049}
1050
17c0fa3d 1051/* generate intermediate code for basic block 'tb'. */
9c489ea6 1052void gen_intermediate_code(CPUState *cs, struct TranslationBlock *tb)
17c0fa3d 1053{
9c489ea6 1054 CPULM32State *env = cs->env_ptr;
4e5e1215 1055 LM32CPU *cpu = lm32_env_get_cpu(env);
17c0fa3d 1056 struct DisasContext ctx, *dc = &ctx;
17c0fa3d 1057 uint32_t pc_start;
17c0fa3d
MW
1058 uint32_t next_page_start;
1059 int num_insns;
1060 int max_insns;
1061
17c0fa3d 1062 pc_start = tb->pc;
34f4aa83
MW
1063 dc->features = cpu->features;
1064 dc->num_breakpoints = cpu->num_breakpoints;
1065 dc->num_watchpoints = cpu->num_watchpoints;
17c0fa3d
MW
1066 dc->tb = tb;
1067
17c0fa3d
MW
1068 dc->is_jmp = DISAS_NEXT;
1069 dc->pc = pc_start;
ed2803da 1070 dc->singlestep_enabled = cs->singlestep_enabled;
17c0fa3d
MW
1071
1072 if (pc_start & 3) {
3604a76f
MW
1073 qemu_log_mask(LOG_GUEST_ERROR,
1074 "unaligned PC=%x. Ignoring lowest bits.\n", pc_start);
1075 pc_start &= ~3;
17c0fa3d
MW
1076 }
1077
17c0fa3d 1078 next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
17c0fa3d 1079 num_insns = 0;
c5a49c63 1080 max_insns = tb_cflags(tb) & CF_COUNT_MASK;
17c0fa3d
MW
1081 if (max_insns == 0) {
1082 max_insns = CF_COUNT_MASK;
1083 }
190ce7fb
RH
1084 if (max_insns > TCG_MAX_INSNS) {
1085 max_insns = TCG_MAX_INSNS;
1086 }
17c0fa3d 1087
cd42d5b2 1088 gen_tb_start(tb);
17c0fa3d 1089 do {
667b8e29 1090 tcg_gen_insn_start(dc->pc);
959082fc 1091 num_insns++;
17c0fa3d 1092
b933066a
RH
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;
522a0d4e
RH
1097 /* The address covered by the breakpoint must be included in
1098 [tb->pc, tb->pc + tb->size) in order to for it to be
1099 properly cleared -- thus we increment the PC here so that
1100 the logic setting tb->size below does the right thing. */
1101 dc->pc += 4;
b933066a
RH
1102 break;
1103 }
1104
17c0fa3d
MW
1105 /* Pretty disas. */
1106 LOG_DIS("%8.8x:\t", dc->pc);
1107
c5a49c63 1108 if (num_insns == max_insns && (tb_cflags(tb) & CF_LAST_IO)) {
17c0fa3d
MW
1109 gen_io_start();
1110 }
1111
32ac0ca2 1112 decode(dc, cpu_ldl_code(env, dc->pc));
17c0fa3d 1113 dc->pc += 4;
17c0fa3d 1114 } while (!dc->is_jmp
fe700adb 1115 && !tcg_op_buf_full()
ed2803da 1116 && !cs->singlestep_enabled
17c0fa3d
MW
1117 && !singlestep
1118 && (dc->pc < next_page_start)
1119 && num_insns < max_insns);
1120
c5a49c63 1121 if (tb_cflags(tb) & CF_LAST_IO) {
17c0fa3d
MW
1122 gen_io_end();
1123 }
1124
ed2803da 1125 if (unlikely(cs->singlestep_enabled)) {
17c0fa3d
MW
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 /* indicate that the hash table must be used
1139 to find the next TB */
1140 tcg_gen_exit_tb(0);
1141 break;
1142 case DISAS_TB_JUMP:
1143 /* nothing more to generate */
1144 break;
1145 }
1146 }
1147
806f352d 1148 gen_tb_end(tb, num_insns);
0a7df5da 1149
4e5e1215
RH
1150 tb->size = dc->pc - pc_start;
1151 tb->icount = num_insns;
17c0fa3d
MW
1152
1153#ifdef DEBUG_DISAS
4910e6e4
RH
1154 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)
1155 && qemu_log_in_addr_range(pc_start)) {
1ee73216 1156 qemu_log_lock();
17c0fa3d 1157 qemu_log("\n");
1d48474d 1158 log_target_disas(cs, pc_start, dc->pc - pc_start);
1ee73216 1159 qemu_log_unlock();
17c0fa3d
MW
1160 }
1161#endif
1162}
1163
878096ee
AF
1164void lm32_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
1165 int flags)
17c0fa3d 1166{
878096ee
AF
1167 LM32CPU *cpu = LM32_CPU(cs);
1168 CPULM32State *env = &cpu->env;
17c0fa3d
MW
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
bad729e2
RH
1198void restore_state_to_opc(CPULM32State *env, TranslationBlock *tb,
1199 target_ulong *data)
17c0fa3d 1200{
bad729e2 1201 env->pc = data[0];
17c0fa3d
MW
1202}
1203
1204void lm32_translate_init(void)
1205{
1206 int i;
1207
17c0fa3d 1208 for (i = 0; i < ARRAY_SIZE(cpu_R); i++) {
e1ccc054 1209 cpu_R[i] = tcg_global_mem_new(cpu_env,
6393c08d 1210 offsetof(CPULM32State, regs[i]),
17c0fa3d
MW
1211 regnames[i]);
1212 }
1213
1214 for (i = 0; i < ARRAY_SIZE(cpu_bp); i++) {
e1ccc054 1215 cpu_bp[i] = tcg_global_mem_new(cpu_env,
6393c08d 1216 offsetof(CPULM32State, bp[i]),
17c0fa3d
MW
1217 regnames[32+i]);
1218 }
1219
1220 for (i = 0; i < ARRAY_SIZE(cpu_wp); i++) {
e1ccc054 1221 cpu_wp[i] = tcg_global_mem_new(cpu_env,
6393c08d 1222 offsetof(CPULM32State, wp[i]),
17c0fa3d
MW
1223 regnames[36+i]);
1224 }
1225
e1ccc054 1226 cpu_pc = tcg_global_mem_new(cpu_env,
6393c08d 1227 offsetof(CPULM32State, pc),
17c0fa3d 1228 "pc");
e1ccc054 1229 cpu_ie = tcg_global_mem_new(cpu_env,
6393c08d 1230 offsetof(CPULM32State, ie),
17c0fa3d 1231 "ie");
e1ccc054 1232 cpu_icc = tcg_global_mem_new(cpu_env,
6393c08d 1233 offsetof(CPULM32State, icc),
17c0fa3d 1234 "icc");
e1ccc054 1235 cpu_dcc = tcg_global_mem_new(cpu_env,
6393c08d 1236 offsetof(CPULM32State, dcc),
17c0fa3d 1237 "dcc");
e1ccc054 1238 cpu_cc = tcg_global_mem_new(cpu_env,
6393c08d 1239 offsetof(CPULM32State, cc),
17c0fa3d 1240 "cc");
e1ccc054 1241 cpu_cfg = tcg_global_mem_new(cpu_env,
6393c08d 1242 offsetof(CPULM32State, cfg),
17c0fa3d 1243 "cfg");
e1ccc054 1244 cpu_eba = tcg_global_mem_new(cpu_env,
6393c08d 1245 offsetof(CPULM32State, eba),
17c0fa3d 1246 "eba");
e1ccc054 1247 cpu_dc = tcg_global_mem_new(cpu_env,
6393c08d 1248 offsetof(CPULM32State, dc),
17c0fa3d 1249 "dc");
e1ccc054 1250 cpu_deba = tcg_global_mem_new(cpu_env,
6393c08d 1251 offsetof(CPULM32State, deba),
17c0fa3d
MW
1252 "deba");
1253}
1254