Merge remote-tracking branch 'remotes/mst/tags/for_upstream' into staging
[qemu.git] / target-moxie / translate.c
bloba437e2ab60263e718830601d3ec607cba5e5408f
1 /*
2 * Moxie emulation for qemu: main translation routines.
4 * Copyright (c) 2009, 2013 Anthony Green
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public License
8 * as published by the Free Software Foundation; either version 2 of
9 * the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful, but
12 * 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.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 /* For information on the Moxie architecture, see
21 * http://moxielogic.org/wiki
24 #include "qemu/osdep.h"
26 #include "cpu.h"
27 #include "exec/exec-all.h"
28 #include "disas/disas.h"
29 #include "tcg-op.h"
30 #include "exec/cpu_ldst.h"
32 #include "exec/helper-proto.h"
33 #include "exec/helper-gen.h"
34 #include "exec/log.h"
36 /* This is the state at translation time. */
37 typedef struct DisasContext {
38 struct TranslationBlock *tb;
39 target_ulong pc, saved_pc;
40 uint32_t opcode;
41 uint32_t fp_status;
42 /* Routine used to access memory */
43 int memidx;
44 int bstate;
45 target_ulong btarget;
46 int singlestep_enabled;
47 } DisasContext;
49 enum {
50 BS_NONE = 0, /* We go out of the TB without reaching a branch or an
51 * exception condition */
52 BS_STOP = 1, /* We want to stop translation for any reason */
53 BS_BRANCH = 2, /* We reached a branch condition */
54 BS_EXCP = 3, /* We reached an exception condition */
57 static TCGv cpu_pc;
58 static TCGv cpu_gregs[16];
59 static TCGv_env cpu_env;
60 static TCGv cc_a, cc_b;
62 #include "exec/gen-icount.h"
64 #define REG(x) (cpu_gregs[x])
66 /* Extract the signed 10-bit offset from a 16-bit branch
67 instruction. */
68 static int extract_branch_offset(int opcode)
70 return (((signed short)((opcode & ((1 << 10) - 1)) << 6)) >> 6) << 1;
73 void moxie_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
74 int flags)
76 MoxieCPU *cpu = MOXIE_CPU(cs);
77 CPUMoxieState *env = &cpu->env;
78 int i;
79 cpu_fprintf(f, "pc=0x%08x\n", env->pc);
80 cpu_fprintf(f, "$fp=0x%08x $sp=0x%08x $r0=0x%08x $r1=0x%08x\n",
81 env->gregs[0], env->gregs[1], env->gregs[2], env->gregs[3]);
82 for (i = 4; i < 16; i += 4) {
83 cpu_fprintf(f, "$r%d=0x%08x $r%d=0x%08x $r%d=0x%08x $r%d=0x%08x\n",
84 i-2, env->gregs[i], i-1, env->gregs[i + 1],
85 i, env->gregs[i + 2], i+1, env->gregs[i + 3]);
87 for (i = 4; i < 16; i += 4) {
88 cpu_fprintf(f, "sr%d=0x%08x sr%d=0x%08x sr%d=0x%08x sr%d=0x%08x\n",
89 i-2, env->sregs[i], i-1, env->sregs[i + 1],
90 i, env->sregs[i + 2], i+1, env->sregs[i + 3]);
94 void moxie_translate_init(void)
96 int i;
97 static int done_init;
98 static const char * const gregnames[16] = {
99 "$fp", "$sp", "$r0", "$r1",
100 "$r2", "$r3", "$r4", "$r5",
101 "$r6", "$r7", "$r8", "$r9",
102 "$r10", "$r11", "$r12", "$r13"
105 if (done_init) {
106 return;
108 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
109 cpu_pc = tcg_global_mem_new_i32(cpu_env,
110 offsetof(CPUMoxieState, pc), "$pc");
111 for (i = 0; i < 16; i++)
112 cpu_gregs[i] = tcg_global_mem_new_i32(cpu_env,
113 offsetof(CPUMoxieState, gregs[i]),
114 gregnames[i]);
116 cc_a = tcg_global_mem_new_i32(cpu_env,
117 offsetof(CPUMoxieState, cc_a), "cc_a");
118 cc_b = tcg_global_mem_new_i32(cpu_env,
119 offsetof(CPUMoxieState, cc_b), "cc_b");
121 done_init = 1;
124 static inline void gen_goto_tb(CPUMoxieState *env, DisasContext *ctx,
125 int n, target_ulong dest)
127 TranslationBlock *tb;
128 tb = ctx->tb;
130 if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) &&
131 !ctx->singlestep_enabled) {
132 tcg_gen_goto_tb(n);
133 tcg_gen_movi_i32(cpu_pc, dest);
134 tcg_gen_exit_tb((uintptr_t)tb + n);
135 } else {
136 tcg_gen_movi_i32(cpu_pc, dest);
137 if (ctx->singlestep_enabled) {
138 gen_helper_debug(cpu_env);
140 tcg_gen_exit_tb(0);
144 static int decode_opc(MoxieCPU *cpu, DisasContext *ctx)
146 CPUMoxieState *env = &cpu->env;
148 /* Local cache for the instruction opcode. */
149 int opcode;
150 /* Set the default instruction length. */
151 int length = 2;
153 /* Examine the 16-bit opcode. */
154 opcode = ctx->opcode;
156 /* Decode instruction. */
157 if (opcode & (1 << 15)) {
158 if (opcode & (1 << 14)) {
159 /* This is a Form 3 instruction. */
160 int inst = (opcode >> 10 & 0xf);
162 #define BRANCH(cond) \
163 do { \
164 TCGLabel *l1 = gen_new_label(); \
165 tcg_gen_brcond_i32(cond, cc_a, cc_b, l1); \
166 gen_goto_tb(env, ctx, 1, ctx->pc+2); \
167 gen_set_label(l1); \
168 gen_goto_tb(env, ctx, 0, extract_branch_offset(opcode) + ctx->pc+2); \
169 ctx->bstate = BS_BRANCH; \
170 } while (0)
172 switch (inst) {
173 case 0x00: /* beq */
174 BRANCH(TCG_COND_EQ);
175 break;
176 case 0x01: /* bne */
177 BRANCH(TCG_COND_NE);
178 break;
179 case 0x02: /* blt */
180 BRANCH(TCG_COND_LT);
181 break;
182 case 0x03: /* bgt */
183 BRANCH(TCG_COND_GT);
184 break;
185 case 0x04: /* bltu */
186 BRANCH(TCG_COND_LTU);
187 break;
188 case 0x05: /* bgtu */
189 BRANCH(TCG_COND_GTU);
190 break;
191 case 0x06: /* bge */
192 BRANCH(TCG_COND_GE);
193 break;
194 case 0x07: /* ble */
195 BRANCH(TCG_COND_LE);
196 break;
197 case 0x08: /* bgeu */
198 BRANCH(TCG_COND_GEU);
199 break;
200 case 0x09: /* bleu */
201 BRANCH(TCG_COND_LEU);
202 break;
203 default:
205 TCGv temp = tcg_temp_new_i32();
206 tcg_gen_movi_i32(cpu_pc, ctx->pc);
207 tcg_gen_movi_i32(temp, MOXIE_EX_BAD);
208 gen_helper_raise_exception(cpu_env, temp);
209 tcg_temp_free_i32(temp);
211 break;
213 } else {
214 /* This is a Form 2 instruction. */
215 int inst = (opcode >> 12 & 0x3);
216 switch (inst) {
217 case 0x00: /* inc */
219 int a = (opcode >> 8) & 0xf;
220 unsigned int v = (opcode & 0xff);
221 tcg_gen_addi_i32(REG(a), REG(a), v);
223 break;
224 case 0x01: /* dec */
226 int a = (opcode >> 8) & 0xf;
227 unsigned int v = (opcode & 0xff);
228 tcg_gen_subi_i32(REG(a), REG(a), v);
230 break;
231 case 0x02: /* gsr */
233 int a = (opcode >> 8) & 0xf;
234 unsigned v = (opcode & 0xff);
235 tcg_gen_ld_i32(REG(a), cpu_env,
236 offsetof(CPUMoxieState, sregs[v]));
238 break;
239 case 0x03: /* ssr */
241 int a = (opcode >> 8) & 0xf;
242 unsigned v = (opcode & 0xff);
243 tcg_gen_st_i32(REG(a), cpu_env,
244 offsetof(CPUMoxieState, sregs[v]));
246 break;
247 default:
249 TCGv temp = tcg_temp_new_i32();
250 tcg_gen_movi_i32(cpu_pc, ctx->pc);
251 tcg_gen_movi_i32(temp, MOXIE_EX_BAD);
252 gen_helper_raise_exception(cpu_env, temp);
253 tcg_temp_free_i32(temp);
255 break;
258 } else {
259 /* This is a Form 1 instruction. */
260 int inst = opcode >> 8;
261 switch (inst) {
262 case 0x00: /* nop */
263 break;
264 case 0x01: /* ldi.l (immediate) */
266 int reg = (opcode >> 4) & 0xf;
267 int val = cpu_ldl_code(env, ctx->pc+2);
268 tcg_gen_movi_i32(REG(reg), val);
269 length = 6;
271 break;
272 case 0x02: /* mov (register-to-register) */
274 int dest = (opcode >> 4) & 0xf;
275 int src = opcode & 0xf;
276 tcg_gen_mov_i32(REG(dest), REG(src));
278 break;
279 case 0x03: /* jsra */
281 TCGv t1 = tcg_temp_new_i32();
282 TCGv t2 = tcg_temp_new_i32();
284 tcg_gen_movi_i32(t1, ctx->pc + 6);
286 /* Make space for the static chain and return address. */
287 tcg_gen_subi_i32(t2, REG(1), 8);
288 tcg_gen_mov_i32(REG(1), t2);
289 tcg_gen_qemu_st32(t1, REG(1), ctx->memidx);
291 /* Push the current frame pointer. */
292 tcg_gen_subi_i32(t2, REG(1), 4);
293 tcg_gen_mov_i32(REG(1), t2);
294 tcg_gen_qemu_st32(REG(0), REG(1), ctx->memidx);
296 /* Set the pc and $fp. */
297 tcg_gen_mov_i32(REG(0), REG(1));
299 gen_goto_tb(env, ctx, 0, cpu_ldl_code(env, ctx->pc+2));
301 tcg_temp_free_i32(t1);
302 tcg_temp_free_i32(t2);
304 ctx->bstate = BS_BRANCH;
305 length = 6;
307 break;
308 case 0x04: /* ret */
310 TCGv t1 = tcg_temp_new_i32();
312 /* The new $sp is the old $fp. */
313 tcg_gen_mov_i32(REG(1), REG(0));
315 /* Pop the frame pointer. */
316 tcg_gen_qemu_ld32u(REG(0), REG(1), ctx->memidx);
317 tcg_gen_addi_i32(t1, REG(1), 4);
318 tcg_gen_mov_i32(REG(1), t1);
321 /* Pop the return address and skip over the static chain
322 slot. */
323 tcg_gen_qemu_ld32u(cpu_pc, REG(1), ctx->memidx);
324 tcg_gen_addi_i32(t1, REG(1), 8);
325 tcg_gen_mov_i32(REG(1), t1);
327 tcg_temp_free_i32(t1);
329 /* Jump... */
330 tcg_gen_exit_tb(0);
332 ctx->bstate = BS_BRANCH;
334 break;
335 case 0x05: /* add.l */
337 int a = (opcode >> 4) & 0xf;
338 int b = opcode & 0xf;
340 tcg_gen_add_i32(REG(a), REG(a), REG(b));
342 break;
343 case 0x06: /* push */
345 int a = (opcode >> 4) & 0xf;
346 int b = opcode & 0xf;
348 TCGv t1 = tcg_temp_new_i32();
349 tcg_gen_subi_i32(t1, REG(a), 4);
350 tcg_gen_mov_i32(REG(a), t1);
351 tcg_gen_qemu_st32(REG(b), REG(a), ctx->memidx);
352 tcg_temp_free_i32(t1);
354 break;
355 case 0x07: /* pop */
357 int a = (opcode >> 4) & 0xf;
358 int b = opcode & 0xf;
359 TCGv t1 = tcg_temp_new_i32();
361 tcg_gen_qemu_ld32u(REG(b), REG(a), ctx->memidx);
362 tcg_gen_addi_i32(t1, REG(a), 4);
363 tcg_gen_mov_i32(REG(a), t1);
364 tcg_temp_free_i32(t1);
366 break;
367 case 0x08: /* lda.l */
369 int reg = (opcode >> 4) & 0xf;
371 TCGv ptr = tcg_temp_new_i32();
372 tcg_gen_movi_i32(ptr, cpu_ldl_code(env, ctx->pc+2));
373 tcg_gen_qemu_ld32u(REG(reg), ptr, ctx->memidx);
374 tcg_temp_free_i32(ptr);
376 length = 6;
378 break;
379 case 0x09: /* sta.l */
381 int val = (opcode >> 4) & 0xf;
383 TCGv ptr = tcg_temp_new_i32();
384 tcg_gen_movi_i32(ptr, cpu_ldl_code(env, ctx->pc+2));
385 tcg_gen_qemu_st32(REG(val), ptr, ctx->memidx);
386 tcg_temp_free_i32(ptr);
388 length = 6;
390 break;
391 case 0x0a: /* ld.l (register indirect) */
393 int src = opcode & 0xf;
394 int dest = (opcode >> 4) & 0xf;
396 tcg_gen_qemu_ld32u(REG(dest), REG(src), ctx->memidx);
398 break;
399 case 0x0b: /* st.l */
401 int dest = (opcode >> 4) & 0xf;
402 int val = opcode & 0xf;
404 tcg_gen_qemu_st32(REG(val), REG(dest), ctx->memidx);
406 break;
407 case 0x0c: /* ldo.l */
409 int a = (opcode >> 4) & 0xf;
410 int b = opcode & 0xf;
412 TCGv t1 = tcg_temp_new_i32();
413 TCGv t2 = tcg_temp_new_i32();
414 tcg_gen_addi_i32(t1, REG(b), cpu_ldl_code(env, ctx->pc+2));
415 tcg_gen_qemu_ld32u(t2, t1, ctx->memidx);
416 tcg_gen_mov_i32(REG(a), t2);
418 tcg_temp_free_i32(t1);
419 tcg_temp_free_i32(t2);
421 length = 6;
423 break;
424 case 0x0d: /* sto.l */
426 int a = (opcode >> 4) & 0xf;
427 int b = opcode & 0xf;
429 TCGv t1 = tcg_temp_new_i32();
430 TCGv t2 = tcg_temp_new_i32();
431 tcg_gen_addi_i32(t1, REG(a), cpu_ldl_code(env, ctx->pc+2));
432 tcg_gen_qemu_st32(REG(b), t1, ctx->memidx);
434 tcg_temp_free_i32(t1);
435 tcg_temp_free_i32(t2);
437 length = 6;
439 break;
440 case 0x0e: /* cmp */
442 int a = (opcode >> 4) & 0xf;
443 int b = opcode & 0xf;
445 tcg_gen_mov_i32(cc_a, REG(a));
446 tcg_gen_mov_i32(cc_b, REG(b));
448 break;
449 case 0x19: /* jsr */
451 int fnreg = (opcode >> 4) & 0xf;
453 /* Load the stack pointer into T0. */
454 TCGv t1 = tcg_temp_new_i32();
455 TCGv t2 = tcg_temp_new_i32();
457 tcg_gen_movi_i32(t1, ctx->pc+2);
459 /* Make space for the static chain and return address. */
460 tcg_gen_subi_i32(t2, REG(1), 8);
461 tcg_gen_mov_i32(REG(1), t2);
462 tcg_gen_qemu_st32(t1, REG(1), ctx->memidx);
464 /* Push the current frame pointer. */
465 tcg_gen_subi_i32(t2, REG(1), 4);
466 tcg_gen_mov_i32(REG(1), t2);
467 tcg_gen_qemu_st32(REG(0), REG(1), ctx->memidx);
469 /* Set the pc and $fp. */
470 tcg_gen_mov_i32(REG(0), REG(1));
471 tcg_gen_mov_i32(cpu_pc, REG(fnreg));
472 tcg_temp_free_i32(t1);
473 tcg_temp_free_i32(t2);
474 tcg_gen_exit_tb(0);
475 ctx->bstate = BS_BRANCH;
477 break;
478 case 0x1a: /* jmpa */
480 tcg_gen_movi_i32(cpu_pc, cpu_ldl_code(env, ctx->pc+2));
481 tcg_gen_exit_tb(0);
482 ctx->bstate = BS_BRANCH;
483 length = 6;
485 break;
486 case 0x1b: /* ldi.b (immediate) */
488 int reg = (opcode >> 4) & 0xf;
489 int val = cpu_ldl_code(env, ctx->pc+2);
490 tcg_gen_movi_i32(REG(reg), val);
491 length = 6;
493 break;
494 case 0x1c: /* ld.b (register indirect) */
496 int src = opcode & 0xf;
497 int dest = (opcode >> 4) & 0xf;
499 tcg_gen_qemu_ld8u(REG(dest), REG(src), ctx->memidx);
501 break;
502 case 0x1d: /* lda.b */
504 int reg = (opcode >> 4) & 0xf;
506 TCGv ptr = tcg_temp_new_i32();
507 tcg_gen_movi_i32(ptr, cpu_ldl_code(env, ctx->pc+2));
508 tcg_gen_qemu_ld8u(REG(reg), ptr, ctx->memidx);
509 tcg_temp_free_i32(ptr);
511 length = 6;
513 break;
514 case 0x1e: /* st.b */
516 int dest = (opcode >> 4) & 0xf;
517 int val = opcode & 0xf;
519 tcg_gen_qemu_st8(REG(val), REG(dest), ctx->memidx);
521 break;
522 case 0x1f: /* sta.b */
524 int val = (opcode >> 4) & 0xf;
526 TCGv ptr = tcg_temp_new_i32();
527 tcg_gen_movi_i32(ptr, cpu_ldl_code(env, ctx->pc+2));
528 tcg_gen_qemu_st8(REG(val), ptr, ctx->memidx);
529 tcg_temp_free_i32(ptr);
531 length = 6;
533 break;
534 case 0x20: /* ldi.s (immediate) */
536 int reg = (opcode >> 4) & 0xf;
537 int val = cpu_ldl_code(env, ctx->pc+2);
538 tcg_gen_movi_i32(REG(reg), val);
539 length = 6;
541 break;
542 case 0x21: /* ld.s (register indirect) */
544 int src = opcode & 0xf;
545 int dest = (opcode >> 4) & 0xf;
547 tcg_gen_qemu_ld16u(REG(dest), REG(src), ctx->memidx);
549 break;
550 case 0x22: /* lda.s */
552 int reg = (opcode >> 4) & 0xf;
554 TCGv ptr = tcg_temp_new_i32();
555 tcg_gen_movi_i32(ptr, cpu_ldl_code(env, ctx->pc+2));
556 tcg_gen_qemu_ld16u(REG(reg), ptr, ctx->memidx);
557 tcg_temp_free_i32(ptr);
559 length = 6;
561 break;
562 case 0x23: /* st.s */
564 int dest = (opcode >> 4) & 0xf;
565 int val = opcode & 0xf;
567 tcg_gen_qemu_st16(REG(val), REG(dest), ctx->memidx);
569 break;
570 case 0x24: /* sta.s */
572 int val = (opcode >> 4) & 0xf;
574 TCGv ptr = tcg_temp_new_i32();
575 tcg_gen_movi_i32(ptr, cpu_ldl_code(env, ctx->pc+2));
576 tcg_gen_qemu_st16(REG(val), ptr, ctx->memidx);
577 tcg_temp_free_i32(ptr);
579 length = 6;
581 break;
582 case 0x25: /* jmp */
584 int reg = (opcode >> 4) & 0xf;
585 tcg_gen_mov_i32(cpu_pc, REG(reg));
586 tcg_gen_exit_tb(0);
587 ctx->bstate = BS_BRANCH;
589 break;
590 case 0x26: /* and */
592 int a = (opcode >> 4) & 0xf;
593 int b = opcode & 0xf;
595 tcg_gen_and_i32(REG(a), REG(a), REG(b));
597 break;
598 case 0x27: /* lshr */
600 int a = (opcode >> 4) & 0xf;
601 int b = opcode & 0xf;
603 TCGv sv = tcg_temp_new_i32();
604 tcg_gen_andi_i32(sv, REG(b), 0x1f);
605 tcg_gen_shr_i32(REG(a), REG(a), sv);
606 tcg_temp_free_i32(sv);
608 break;
609 case 0x28: /* ashl */
611 int a = (opcode >> 4) & 0xf;
612 int b = opcode & 0xf;
614 TCGv sv = tcg_temp_new_i32();
615 tcg_gen_andi_i32(sv, REG(b), 0x1f);
616 tcg_gen_shl_i32(REG(a), REG(a), sv);
617 tcg_temp_free_i32(sv);
619 break;
620 case 0x29: /* sub.l */
622 int a = (opcode >> 4) & 0xf;
623 int b = opcode & 0xf;
625 tcg_gen_sub_i32(REG(a), REG(a), REG(b));
627 break;
628 case 0x2a: /* neg */
630 int a = (opcode >> 4) & 0xf;
631 int b = opcode & 0xf;
633 tcg_gen_neg_i32(REG(a), REG(b));
635 break;
636 case 0x2b: /* or */
638 int a = (opcode >> 4) & 0xf;
639 int b = opcode & 0xf;
641 tcg_gen_or_i32(REG(a), REG(a), REG(b));
643 break;
644 case 0x2c: /* not */
646 int a = (opcode >> 4) & 0xf;
647 int b = opcode & 0xf;
649 tcg_gen_not_i32(REG(a), REG(b));
651 break;
652 case 0x2d: /* ashr */
654 int a = (opcode >> 4) & 0xf;
655 int b = opcode & 0xf;
657 TCGv sv = tcg_temp_new_i32();
658 tcg_gen_andi_i32(sv, REG(b), 0x1f);
659 tcg_gen_sar_i32(REG(a), REG(a), sv);
660 tcg_temp_free_i32(sv);
662 break;
663 case 0x2e: /* xor */
665 int a = (opcode >> 4) & 0xf;
666 int b = opcode & 0xf;
668 tcg_gen_xor_i32(REG(a), REG(a), REG(b));
670 break;
671 case 0x2f: /* mul.l */
673 int a = (opcode >> 4) & 0xf;
674 int b = opcode & 0xf;
676 tcg_gen_mul_i32(REG(a), REG(a), REG(b));
678 break;
679 case 0x30: /* swi */
681 int val = cpu_ldl_code(env, ctx->pc+2);
683 TCGv temp = tcg_temp_new_i32();
684 tcg_gen_movi_i32(temp, val);
685 tcg_gen_st_i32(temp, cpu_env,
686 offsetof(CPUMoxieState, sregs[3]));
687 tcg_gen_movi_i32(cpu_pc, ctx->pc);
688 tcg_gen_movi_i32(temp, MOXIE_EX_SWI);
689 gen_helper_raise_exception(cpu_env, temp);
690 tcg_temp_free_i32(temp);
692 length = 6;
694 break;
695 case 0x31: /* div.l */
697 int a = (opcode >> 4) & 0xf;
698 int b = opcode & 0xf;
699 tcg_gen_movi_i32(cpu_pc, ctx->pc);
700 gen_helper_div(REG(a), cpu_env, REG(a), REG(b));
702 break;
703 case 0x32: /* udiv.l */
705 int a = (opcode >> 4) & 0xf;
706 int b = opcode & 0xf;
707 tcg_gen_movi_i32(cpu_pc, ctx->pc);
708 gen_helper_udiv(REG(a), cpu_env, REG(a), REG(b));
710 break;
711 case 0x33: /* mod.l */
713 int a = (opcode >> 4) & 0xf;
714 int b = opcode & 0xf;
715 tcg_gen_rem_i32(REG(a), REG(a), REG(b));
717 break;
718 case 0x34: /* umod.l */
720 int a = (opcode >> 4) & 0xf;
721 int b = opcode & 0xf;
722 tcg_gen_remu_i32(REG(a), REG(a), REG(b));
724 break;
725 case 0x35: /* brk */
727 TCGv temp = tcg_temp_new_i32();
728 tcg_gen_movi_i32(cpu_pc, ctx->pc);
729 tcg_gen_movi_i32(temp, MOXIE_EX_BREAK);
730 gen_helper_raise_exception(cpu_env, temp);
731 tcg_temp_free_i32(temp);
733 break;
734 case 0x36: /* ldo.b */
736 int a = (opcode >> 4) & 0xf;
737 int b = opcode & 0xf;
739 TCGv t1 = tcg_temp_new_i32();
740 TCGv t2 = tcg_temp_new_i32();
741 tcg_gen_addi_i32(t1, REG(b), cpu_ldl_code(env, ctx->pc+2));
742 tcg_gen_qemu_ld8u(t2, t1, ctx->memidx);
743 tcg_gen_mov_i32(REG(a), t2);
745 tcg_temp_free_i32(t1);
746 tcg_temp_free_i32(t2);
748 length = 6;
750 break;
751 case 0x37: /* sto.b */
753 int a = (opcode >> 4) & 0xf;
754 int b = opcode & 0xf;
756 TCGv t1 = tcg_temp_new_i32();
757 TCGv t2 = tcg_temp_new_i32();
758 tcg_gen_addi_i32(t1, REG(a), cpu_ldl_code(env, ctx->pc+2));
759 tcg_gen_qemu_st8(REG(b), t1, ctx->memidx);
761 tcg_temp_free_i32(t1);
762 tcg_temp_free_i32(t2);
764 length = 6;
766 break;
767 case 0x38: /* ldo.s */
769 int a = (opcode >> 4) & 0xf;
770 int b = opcode & 0xf;
772 TCGv t1 = tcg_temp_new_i32();
773 TCGv t2 = tcg_temp_new_i32();
774 tcg_gen_addi_i32(t1, REG(b), cpu_ldl_code(env, ctx->pc+2));
775 tcg_gen_qemu_ld16u(t2, t1, ctx->memidx);
776 tcg_gen_mov_i32(REG(a), t2);
778 tcg_temp_free_i32(t1);
779 tcg_temp_free_i32(t2);
781 length = 6;
783 break;
784 case 0x39: /* sto.s */
786 int a = (opcode >> 4) & 0xf;
787 int b = opcode & 0xf;
789 TCGv t1 = tcg_temp_new_i32();
790 TCGv t2 = tcg_temp_new_i32();
791 tcg_gen_addi_i32(t1, REG(a), cpu_ldl_code(env, ctx->pc+2));
792 tcg_gen_qemu_st16(REG(b), t1, ctx->memidx);
793 tcg_temp_free_i32(t1);
794 tcg_temp_free_i32(t2);
796 length = 6;
798 break;
799 default:
801 TCGv temp = tcg_temp_new_i32();
802 tcg_gen_movi_i32(cpu_pc, ctx->pc);
803 tcg_gen_movi_i32(temp, MOXIE_EX_BAD);
804 gen_helper_raise_exception(cpu_env, temp);
805 tcg_temp_free_i32(temp);
807 break;
811 return length;
814 /* generate intermediate code for basic block 'tb'. */
815 void gen_intermediate_code(CPUMoxieState *env, struct TranslationBlock *tb)
817 MoxieCPU *cpu = moxie_env_get_cpu(env);
818 CPUState *cs = CPU(cpu);
819 DisasContext ctx;
820 target_ulong pc_start;
821 int num_insns, max_insns;
823 pc_start = tb->pc;
824 ctx.pc = pc_start;
825 ctx.saved_pc = -1;
826 ctx.tb = tb;
827 ctx.memidx = 0;
828 ctx.singlestep_enabled = 0;
829 ctx.bstate = BS_NONE;
830 num_insns = 0;
831 max_insns = tb->cflags & CF_COUNT_MASK;
832 if (max_insns == 0) {
833 max_insns = CF_COUNT_MASK;
835 if (max_insns > TCG_MAX_INSNS) {
836 max_insns = TCG_MAX_INSNS;
839 gen_tb_start(tb);
840 do {
841 tcg_gen_insn_start(ctx.pc);
842 num_insns++;
844 if (unlikely(cpu_breakpoint_test(cs, ctx.pc, BP_ANY))) {
845 tcg_gen_movi_i32(cpu_pc, ctx.pc);
846 gen_helper_debug(cpu_env);
847 ctx.bstate = BS_EXCP;
848 /* The address covered by the breakpoint must be included in
849 [tb->pc, tb->pc + tb->size) in order to for it to be
850 properly cleared -- thus we increment the PC here so that
851 the logic setting tb->size below does the right thing. */
852 ctx.pc += 2;
853 goto done_generating;
856 ctx.opcode = cpu_lduw_code(env, ctx.pc);
857 ctx.pc += decode_opc(cpu, &ctx);
859 if (num_insns >= max_insns) {
860 break;
862 if (cs->singlestep_enabled) {
863 break;
865 if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0) {
866 break;
868 } while (ctx.bstate == BS_NONE && !tcg_op_buf_full());
870 if (cs->singlestep_enabled) {
871 tcg_gen_movi_tl(cpu_pc, ctx.pc);
872 gen_helper_debug(cpu_env);
873 } else {
874 switch (ctx.bstate) {
875 case BS_STOP:
876 case BS_NONE:
877 gen_goto_tb(env, &ctx, 0, ctx.pc);
878 break;
879 case BS_EXCP:
880 tcg_gen_exit_tb(0);
881 break;
882 case BS_BRANCH:
883 default:
884 break;
887 done_generating:
888 gen_tb_end(tb, num_insns);
890 tb->size = ctx.pc - pc_start;
891 tb->icount = num_insns;
894 void restore_state_to_opc(CPUMoxieState *env, TranslationBlock *tb,
895 target_ulong *data)
897 env->pc = data[0];