Implement preliminary SAM Coupé emulation
[qemu/z80.git] / target-z80 / translate.c
blob178088dd5ec432284af5f8fbb2f72d12be42ed00
1 /*
2 * Z80 translation
4 * Copyright (c) 2007-2009 Stuart Brady <stuart.brady@gmail.com>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library 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.
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 * Library General Public License for more details.
16 * You should have received a copy of the GNU Library General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA
21 #include <stdarg.h>
22 #include <stdlib.h>
23 #include <stdio.h>
24 #include <string.h>
25 #include <inttypes.h>
26 #include <signal.h>
28 #include "cpu.h"
29 #include "exec-all.h"
30 #include "disas.h"
31 #include "tcg-op.h"
33 #include "helper.h"
34 #define GEN_HELPER 1
35 #include "helper.h"
37 #define PREFIX_CB 0x01
38 #define PREFIX_DD 0x02
39 #define PREFIX_ED 0x04
40 #define PREFIX_FD 0x08
42 #define MODE_NORMAL 0
43 #define MODE_DD 1
44 #define MODE_FD 2
46 #define zprintf(...)
47 //#define zprintf printf
49 /* global register indexes */
50 static TCGv cpu_env, cpu_T[3], cpu_A0;
52 #include "gen-icount.h"
54 #define MEM_INDEX 0
56 typedef struct DisasContext {
57 /* current insn context */
58 int override; /* -1 if no override */
59 int prefix;
60 uint16_t pc; /* pc = pc + cs_base */
61 int is_jmp; /* 1 = means jump (stop translation), 2 means CPU
62 static state change (stop translation) */
63 int model;
64 /* current block context */
65 target_ulong cs_base; /* base of CS segment */
66 int singlestep_enabled; /* "hardware" single step enabled */
67 int jmp_opt; /* use direct block chaining for direct jumps */
68 int flags; /* all execution flags */
69 struct TranslationBlock *tb;
70 } DisasContext;
72 static void gen_eob(DisasContext *s);
73 static void gen_jmp(DisasContext *s, target_ulong pc);
74 static void gen_jmp_tb(DisasContext *s, target_ulong pc, int tb_num);
76 enum {
77 /* 8-bit registers */
78 OR_B,
79 OR_C,
80 OR_D,
81 OR_E,
82 OR_H,
83 OR_L,
84 OR_HLmem,
85 OR_A,
87 OR_IXh,
88 OR_IXl,
90 OR_IYh,
91 OR_IYl,
93 OR_IXmem,
94 OR_IYmem,
97 static const char *const regnames[] = {
98 [OR_B] = "b",
99 [OR_C] = "c",
100 [OR_D] = "d",
101 [OR_E] = "e",
102 [OR_H] = "h",
103 [OR_L] = "l",
104 [OR_HLmem] = "(hl)",
105 [OR_A] = "a",
107 [OR_IXh] = "ixh",
108 [OR_IXl] = "ixl",
110 [OR_IYh] = "iyh",
111 [OR_IYl] = "iyl",
113 [OR_IXmem] = "(ix+d)",
114 [OR_IYmem] = "(iy+d)",
117 static const char *const idxnames[] = {
118 [OR_IXmem] = "ix",
119 [OR_IYmem] = "iy",
122 /* signed hex byte value for printf */
123 #define shexb(val) (val < 0 ? '-' : '+'), (abs(val))
125 /* Register accessor functions */
127 #if defined(WORDS_BIGENDIAN)
128 #define UNIT_OFFSET(type, units, num) (sizeof(type) - ((num + 1) * units))
129 #else
130 #define UNIT_OFFSET(type, units, num) (num * units)
131 #endif
133 #define BYTE_OFFSET(type, num) UNIT_OFFSET(type, 1, num)
134 #define WORD_OFFSET(type, num) UNIT_OFFSET(type, 2, num)
136 #define REGPAIR AF
137 #define REGHIGH A
138 #define REGLOW F
139 #include "genreg_template_af.h"
140 #undef REGPAIR
141 #undef REGHIGH
142 #undef REGLOW
144 #define REGPAIR BC
145 #define REGHIGH B
146 #define REGLOW C
147 #include "genreg_template.h"
148 #undef REGPAIR
149 #undef REGHIGH
150 #undef REGLOW
152 #define REGPAIR DE
153 #define REGHIGH D
154 #define REGLOW E
155 #include "genreg_template.h"
156 #undef REGPAIR
157 #undef REGHIGH
158 #undef REGLOW
160 #define REGPAIR HL
161 #define REGHIGH H
162 #define REGLOW L
163 #include "genreg_template.h"
164 #undef REGPAIR
165 #undef REGHIGH
166 #undef REGLOW
168 #define REGPAIR IX
169 #define REGHIGH IXh
170 #define REGLOW IXl
171 #include "genreg_template.h"
172 #undef REGPAIR
173 #undef REGHIGH
174 #undef REGLOW
176 #define REGPAIR IY
177 #define REGHIGH IYh
178 #define REGLOW IYl
179 #include "genreg_template.h"
180 #undef REGPAIR
181 #undef REGHIGH
182 #undef REGLOW
184 #define REGPAIR AFX
185 #define REGHIGH AX
186 #define REGLOW FX
187 #include "genreg_template_af.h"
188 #undef REGPAIR
189 #undef REGHIGH
190 #undef REGLOW
192 #define REGPAIR BCX
193 #define REGHIGH BX
194 #define REGLOW CX
195 #include "genreg_template.h"
196 #undef REGPAIR
197 #undef REGHIGH
198 #undef REGLOW
200 #define REGPAIR DEX
201 #define REGHIGH DX
202 #define REGLOW EX
203 #include "genreg_template.h"
204 #undef REGPAIR
205 #undef REGHIGH
206 #undef REGLOW
208 #define REGPAIR HLX
209 #define REGHIGH HX
210 #define REGLOW LX
211 #include "genreg_template.h"
212 #undef REGPAIR
213 #undef REGHIGH
214 #undef REGLOW
216 #define REGPAIR SP
217 #include "genreg_template.h"
218 #undef REGPAIR
220 typedef void (gen_mov_func)(TCGv v);
221 typedef void (gen_mov_func_idx)(TCGv v, uint16_t ofs);
223 static inline void gen_movb_v_HLmem(TCGv v)
225 TCGv addr = tcg_temp_new();
226 gen_movw_v_HL(addr);
227 tcg_gen_qemu_ld8u(v, addr, MEM_INDEX);
228 tcg_temp_free(addr);
231 static inline void gen_movb_HLmem_v(TCGv v)
233 TCGv addr = tcg_temp_new();
234 gen_movw_v_HL(addr);
235 tcg_gen_qemu_st8(v, addr, MEM_INDEX);
236 tcg_temp_free(addr);
239 static inline void gen_movb_v_IXmem(TCGv v, uint16_t ofs)
241 TCGv addr = tcg_temp_new();
242 gen_movw_v_IX(addr);
243 tcg_gen_addi_tl(addr, addr, ofs);
244 tcg_gen_ext16u_tl(addr, addr);
245 tcg_gen_qemu_ld8u(v, addr, MEM_INDEX);
246 tcg_temp_free(addr);
249 static inline void gen_movb_v_IYmem(TCGv v, uint16_t ofs)
251 TCGv addr = tcg_temp_new();
252 gen_movw_v_IY(addr);
253 tcg_gen_addi_tl(addr, addr, ofs);
254 tcg_gen_ext16u_tl(addr, addr);
255 tcg_gen_qemu_ld8u(v, addr, MEM_INDEX);
256 tcg_temp_free(addr);
259 static inline void gen_movb_IXmem_v(TCGv v, uint16_t ofs)
261 TCGv addr = tcg_temp_new();
262 gen_movw_v_IX(addr);
263 tcg_gen_addi_tl(addr, addr, ofs);
264 tcg_gen_ext16u_tl(addr, addr);
265 tcg_gen_qemu_st8(v, addr, MEM_INDEX);
266 tcg_temp_free(addr);
269 static inline void gen_movb_IYmem_v(TCGv v, uint16_t ofs)
271 TCGv addr = tcg_temp_new();
272 gen_movw_v_IY(addr);
273 tcg_gen_addi_tl(addr, addr, ofs);
274 tcg_gen_ext16u_tl(addr, addr);
275 tcg_gen_qemu_st8(v, addr, MEM_INDEX);
276 tcg_temp_free(addr);
279 static inline void gen_pushw(TCGv v)
281 TCGv addr = tcg_temp_new();
282 gen_movw_v_SP(addr);
283 tcg_gen_subi_i32(addr, addr, 2);
284 tcg_gen_ext16u_i32(addr, addr);
285 gen_movw_SP_v(addr);
286 tcg_gen_qemu_st16(v, addr, MEM_INDEX);
287 tcg_temp_free(addr);
290 static inline void gen_popw(TCGv v)
292 TCGv addr = tcg_temp_new();
293 gen_movw_v_SP(addr);
294 tcg_gen_qemu_ld16u(v, addr, MEM_INDEX);
295 tcg_gen_addi_i32(addr, addr, 2);
296 tcg_gen_ext16u_i32(addr, addr);
297 gen_movw_SP_v(addr);
298 tcg_temp_free(addr);
301 static gen_mov_func *const gen_movb_v_reg_tbl[] = {
302 [OR_B] = gen_movb_v_B,
303 [OR_C] = gen_movb_v_C,
304 [OR_D] = gen_movb_v_D,
305 [OR_E] = gen_movb_v_E,
306 [OR_H] = gen_movb_v_H,
307 [OR_L] = gen_movb_v_L,
308 [OR_HLmem] = gen_movb_v_HLmem,
309 [OR_A] = gen_movb_v_A,
311 [OR_IXh] = gen_movb_v_IXh,
312 [OR_IXl] = gen_movb_v_IXl,
314 [OR_IYh] = gen_movb_v_IYh,
315 [OR_IYl] = gen_movb_v_IYl,
318 static inline void gen_movb_v_reg(TCGv v, int reg)
320 gen_movb_v_reg_tbl[reg](v);
323 static gen_mov_func_idx *const gen_movb_v_idx_tbl[] = {
324 [OR_IXmem] = gen_movb_v_IXmem,
325 [OR_IYmem] = gen_movb_v_IYmem,
328 static inline void gen_movb_v_idx(TCGv v, int idx, int ofs)
330 gen_movb_v_idx_tbl[idx](v, ofs);
333 static gen_mov_func *const gen_movb_reg_v_tbl[] = {
334 [OR_B] = gen_movb_B_v,
335 [OR_C] = gen_movb_C_v,
336 [OR_D] = gen_movb_D_v,
337 [OR_E] = gen_movb_E_v,
338 [OR_H] = gen_movb_H_v,
339 [OR_L] = gen_movb_L_v,
340 [OR_HLmem] = gen_movb_HLmem_v,
341 [OR_A] = gen_movb_A_v,
343 [OR_IXh] = gen_movb_IXh_v,
344 [OR_IXl] = gen_movb_IXl_v,
346 [OR_IYh] = gen_movb_IYh_v,
347 [OR_IYl] = gen_movb_IYl_v,
350 static inline void gen_movb_reg_v(int reg, TCGv v)
352 gen_movb_reg_v_tbl[reg](v);
355 static gen_mov_func_idx *const gen_movb_idx_v_tbl[] = {
356 [OR_IXmem] = gen_movb_IXmem_v,
357 [OR_IYmem] = gen_movb_IYmem_v,
360 static inline void gen_movb_idx_v(int idx, TCGv v, int ofs)
362 gen_movb_idx_v_tbl[idx](v, ofs);
365 static inline int regmap(int reg, int m)
367 switch (m) {
368 case MODE_DD:
369 switch (reg) {
370 case OR_H:
371 return OR_IXh;
372 case OR_L:
373 return OR_IXl;
374 case OR_HLmem:
375 return OR_IXmem;
376 default:
377 return reg;
379 case MODE_FD:
380 switch (reg) {
381 case OR_H:
382 return OR_IYh;
383 case OR_L:
384 return OR_IYl;
385 case OR_HLmem:
386 return OR_IYmem;
387 default:
388 return reg;
390 case MODE_NORMAL:
391 default:
392 return reg;
396 static inline int is_indexed(int reg)
398 if (reg == OR_IXmem || reg == OR_IYmem) {
399 return 1;
400 } else {
401 return 0;
405 static const int reg[8] = {
406 OR_B,
407 OR_C,
408 OR_D,
409 OR_E,
410 OR_H,
411 OR_L,
412 OR_HLmem,
413 OR_A,
416 enum {
417 /* 16-bit registers and register pairs */
418 OR2_AF,
419 OR2_BC,
420 OR2_DE,
421 OR2_HL,
423 OR2_IX,
424 OR2_IY,
425 OR2_SP,
427 OR2_AFX,
428 OR2_BCX,
429 OR2_DEX,
430 OR2_HLX,
433 static const char *const regpairnames[] = {
434 [OR2_AF] = "af",
435 [OR2_BC] = "bc",
436 [OR2_DE] = "de",
437 [OR2_HL] = "hl",
439 [OR2_IX] = "ix",
440 [OR2_IY] = "iy",
441 [OR2_SP] = "sp",
443 [OR2_AFX] = "afx",
444 [OR2_BCX] = "bcx",
445 [OR2_DEX] = "dex",
446 [OR2_HLX] = "hlx",
449 static gen_mov_func *const gen_movw_v_reg_tbl[] = {
450 [OR2_AF] = gen_movw_v_AF,
451 [OR2_BC] = gen_movw_v_BC,
452 [OR2_DE] = gen_movw_v_DE,
453 [OR2_HL] = gen_movw_v_HL,
455 [OR2_IX] = gen_movw_v_IX,
456 [OR2_IY] = gen_movw_v_IY,
457 [OR2_SP] = gen_movw_v_SP,
459 [OR2_AFX] = gen_movw_v_AFX,
460 [OR2_BCX] = gen_movw_v_BCX,
461 [OR2_DEX] = gen_movw_v_DEX,
462 [OR2_HLX] = gen_movw_v_HLX,
465 static inline void gen_movw_v_reg(TCGv v, int regpair)
467 gen_movw_v_reg_tbl[regpair](v);
470 static gen_mov_func *const gen_movw_reg_v_tbl[] = {
471 [OR2_AF] = gen_movw_AF_v,
472 [OR2_BC] = gen_movw_BC_v,
473 [OR2_DE] = gen_movw_DE_v,
474 [OR2_HL] = gen_movw_HL_v,
476 [OR2_IX] = gen_movw_IX_v,
477 [OR2_IY] = gen_movw_IY_v,
478 [OR2_SP] = gen_movw_SP_v,
480 [OR2_AFX] = gen_movw_AFX_v,
481 [OR2_BCX] = gen_movw_BCX_v,
482 [OR2_DEX] = gen_movw_DEX_v,
483 [OR2_HLX] = gen_movw_HLX_v,
486 static inline void gen_movw_reg_v(int regpair, TCGv v)
488 gen_movw_reg_v_tbl[regpair](v);
491 static inline int regpairmap(int regpair, int m)
493 switch (regpair) {
494 case OR2_HL:
495 switch (m) {
496 case MODE_DD:
497 return OR2_IX;
498 case MODE_FD:
499 return OR2_IY;
500 case MODE_NORMAL:
501 default:
502 return OR2_HL;
504 default:
505 return regpair;
509 static const int regpair[4] = {
510 OR2_BC,
511 OR2_DE,
512 OR2_HL,
513 OR2_SP,
516 static const int regpair2[4] = {
517 OR2_BC,
518 OR2_DE,
519 OR2_HL,
520 OR2_AF,
523 static inline void gen_jmp_im(target_ulong pc)
525 gen_helper_movl_pc_im(tcg_const_tl(pc));
528 static void gen_debug(DisasContext *s, target_ulong cur_pc)
530 gen_jmp_im(cur_pc);
531 gen_helper_debug();
532 s->is_jmp = 3;
535 static void gen_eob(DisasContext *s)
537 if (s->tb->flags & HF_INHIBIT_IRQ_MASK) {
538 gen_helper_reset_inhibit_irq();
540 if (s->singlestep_enabled) {
541 gen_helper_debug();
542 } else {
543 tcg_gen_exit_tb(0);
545 s->is_jmp = 3;
548 static void gen_exception(DisasContext *s, int trapno, target_ulong cur_pc)
550 gen_jmp_im(cur_pc);
551 gen_helper_raise_exception(trapno);
552 s->is_jmp = 3;
555 /* Conditions */
557 static const char *const cc[8] = {
558 "nz",
559 "z",
560 "nc",
561 "c",
562 "po",
563 "pe",
564 "p",
565 "m",
568 enum {
569 COND_NZ = 0,
570 COND_Z,
571 COND_NC,
572 COND_C,
573 COND_PO,
574 COND_PE,
575 COND_P,
576 COND_M,
579 static const int cc_flags[4] = {
580 CC_Z,
581 CC_C,
582 CC_P,
583 CC_S,
586 /* Arithmetic/logic operations */
588 static const char *const alu[8] = {
589 "add a,",
590 "adc a,",
591 "sub ",
592 "sbc a,",
593 "and ",
594 "xor ",
595 "or ",
596 "cp ",
599 typedef void (alu_helper_func)(void);
601 static alu_helper_func *const gen_alu[8] = {
602 gen_helper_add_cc,
603 gen_helper_adc_cc,
604 gen_helper_sub_cc,
605 gen_helper_sbc_cc,
606 gen_helper_and_cc,
607 gen_helper_xor_cc,
608 gen_helper_or_cc,
609 gen_helper_cp_cc,
612 /* Rotation/shift operations */
614 static const char *const rot[8] = {
615 "rlc",
616 "rrc",
617 "rl",
618 "rr",
619 "sla",
620 "sra",
621 "sll",
622 "srl",
625 typedef void (rot_helper_func)(void);
627 static rot_helper_func *const gen_rot_T0[8] = {
628 gen_helper_rlc_T0_cc,
629 gen_helper_rrc_T0_cc,
630 gen_helper_rl_T0_cc,
631 gen_helper_rr_T0_cc,
632 gen_helper_sla_T0_cc,
633 gen_helper_sra_T0_cc,
634 gen_helper_sll_T0_cc,
635 gen_helper_srl_T0_cc,
638 /* Block instructions */
640 static const char *const bli[4][4] = {
641 { "ldi", "cpi", "ini", "outi", },
642 { "ldd", "cpd", "ind", "outd", },
643 { "ldir", "cpir", "inir", "otir", },
644 { "lddr", "cpdr", "indr", "otdr", },
647 static const int imode[8] = {
648 0, 0, 1, 2, 0, 0, 1, 2,
651 static inline void gen_goto_tb(DisasContext *s, int tb_num, target_ulong pc)
653 gen_jmp_im(pc);
654 gen_eob(s);
657 static inline void gen_cond_jump(int cc, int l1)
659 gen_movb_v_F(cpu_T[0]);
661 tcg_gen_andi_tl(cpu_T[0], cpu_T[0], cc_flags[cc >> 1]);
663 tcg_gen_brcondi_tl((cc & 1) ? TCG_COND_NE : TCG_COND_EQ, cpu_T[0], 0, l1);
666 static inline void gen_jcc(DisasContext *s, int cc,
667 target_ulong val, target_ulong next_pc)
669 TranslationBlock *tb;
670 int l1;
672 tb = s->tb;
674 l1 = gen_new_label();
676 gen_cond_jump(cc, l1);
678 gen_goto_tb(s, 0, next_pc);
680 gen_set_label(l1);
681 gen_goto_tb(s, 1, val);
683 s->is_jmp = 3;
686 static inline void gen_callcc(DisasContext *s, int cc,
687 target_ulong val, target_ulong next_pc)
689 TranslationBlock *tb;
690 int l1;
692 tb = s->tb;
694 l1 = gen_new_label();
696 gen_cond_jump(cc, l1);
698 gen_goto_tb(s, 0, next_pc);
700 gen_set_label(l1);
701 tcg_gen_movi_tl(cpu_T[0], next_pc);
702 gen_pushw(cpu_T[0]);
703 gen_goto_tb(s, 1, val);
705 s->is_jmp = 3;
708 static inline void gen_retcc(DisasContext *s, int cc,
709 target_ulong next_pc)
711 TranslationBlock *tb;
712 int l1;
714 tb = s->tb;
716 l1 = gen_new_label();
718 gen_cond_jump(cc, l1);
720 gen_goto_tb(s, 0, next_pc);
722 gen_set_label(l1);
723 gen_popw(cpu_T[0]);
724 gen_helper_jmp_T0();
725 gen_eob(s);
727 s->is_jmp = 3;
730 static inline void gen_ex(int regpair1, int regpair2)
732 TCGv tmp1 = tcg_temp_new();
733 TCGv tmp2 = tcg_temp_new();
734 gen_movw_v_reg(tmp1, regpair1);
735 gen_movw_v_reg(tmp2, regpair2);
736 gen_movw_reg_v(regpair2, tmp1);
737 gen_movw_reg_v(regpair1, tmp2);
738 tcg_temp_free(tmp1);
739 tcg_temp_free(tmp2);
742 /* TODO: condition code optimisation */
744 /* micro-ops that modify condition codes should end in _cc */
746 /* convert one instruction. s->is_jmp is set if the translation must
747 be stopped. Return the next pc value */
748 static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
750 int b, prefixes;
751 int rex_w, rex_r;
752 int m;
754 s->pc = pc_start;
755 prefixes = 0;
756 s->override = -1;
757 rex_w = -1;
758 rex_r = 0;
760 //printf("PC = %04x: ", s->pc);
761 next_byte:
762 s->prefix = prefixes;
764 /* START */
766 if (prefixes & PREFIX_DD) {
767 m = MODE_DD;
768 } else if (prefixes & PREFIX_FD) {
769 m = MODE_FD;
770 } else {
771 m = MODE_NORMAL;
774 /* unprefixed opcodes */
776 if ((prefixes & (PREFIX_CB | PREFIX_ED)) == 0) {
777 b = ldub_code(s->pc);
778 s->pc++;
780 int x, y, z, p, q;
781 int n, d;
782 int r1, r2;
784 x = (b >> 6) & 0x03;
785 y = (b >> 3) & 0x07;
786 z = b & 0x07;
787 p = y >> 1;
788 q = y & 0x01;
790 switch (x) {
791 case 0:
792 switch (z) {
794 case 0:
795 switch (y) {
796 case 0:
797 zprintf("nop\n");
798 break;
799 case 1:
800 gen_ex(OR2_AF, OR2_AFX);
801 zprintf("ex af,af'\n");
802 break;
803 case 2:
804 n = ldsb_code(s->pc);
805 s->pc++;
806 gen_helper_djnz(tcg_const_tl(s->pc + n), tcg_const_tl(s->pc));
807 gen_eob(s);
808 s->is_jmp = 3;
809 zprintf("djnz $%02x\n", n);
810 break;
811 case 3:
812 n = ldsb_code(s->pc);
813 s->pc++;
814 gen_jmp_im(s->pc + n);
815 gen_eob(s);
816 s->is_jmp = 3;
817 zprintf("jr $%02x\n", n);
818 break;
819 case 4:
820 case 5:
821 case 6:
822 case 7:
823 n = ldsb_code(s->pc);
824 s->pc++;
825 zprintf("jr %s,$%04x\n", cc[y-4], (s->pc + n) & 0xffff);
826 gen_jcc(s, y-4, s->pc + n, s->pc);
827 break;
829 break;
831 case 1:
832 switch (q) {
833 case 0:
834 n = lduw_code(s->pc);
835 s->pc += 2;
836 tcg_gen_movi_tl(cpu_T[0], n);
837 r1 = regpairmap(regpair[p], m);
838 gen_movw_reg_v(r1, cpu_T[0]);
839 zprintf("ld %s,$%04x\n", regpairnames[r1], n);
840 break;
841 case 1:
842 r1 = regpairmap(regpair[p], m);
843 r2 = regpairmap(OR2_HL, m);
844 gen_movw_v_reg(cpu_T[0], r1);
845 gen_movw_v_reg(cpu_T[1], r2);
846 gen_helper_addw_T0_T1_cc();
847 gen_movw_reg_v(r2, cpu_T[0]);
848 zprintf("add %s,%s\n", regpairnames[r2], regpairnames[r1]);
849 break;
851 break;
853 case 2:
854 switch (q) {
855 case 0:
856 switch (p) {
857 case 0:
858 gen_movb_v_A(cpu_T[0]);
859 gen_movw_v_BC(cpu_A0);
860 tcg_gen_qemu_st8(cpu_T[0], cpu_A0, MEM_INDEX);
861 zprintf("ld (bc),a\n");
862 break;
863 case 1:
864 gen_movb_v_A(cpu_T[0]);
865 gen_movw_v_DE(cpu_A0);
866 tcg_gen_qemu_st8(cpu_T[0], cpu_A0, MEM_INDEX);
867 zprintf("ld (de),a\n");
868 break;
869 case 2:
870 n = lduw_code(s->pc);
871 s->pc += 2;
872 r1 = regpairmap(OR2_HL, m);
873 gen_movw_v_reg(cpu_T[0], r1);
874 tcg_gen_movi_i32(cpu_A0, n);
875 tcg_gen_qemu_st16(cpu_T[0], cpu_A0, MEM_INDEX);
876 zprintf("ld ($%04x),%s\n", n, regpairnames[r1]);
877 break;
878 case 3:
879 n = lduw_code(s->pc);
880 s->pc += 2;
881 gen_movb_v_A(cpu_T[0]);
882 tcg_gen_movi_i32(cpu_A0, n);
883 tcg_gen_qemu_st8(cpu_T[0], cpu_A0, MEM_INDEX);
884 zprintf("ld ($%04x),a\n", n);
885 break;
887 break;
888 case 1:
889 switch (p) {
890 case 0:
891 gen_movw_v_BC(cpu_A0);
892 tcg_gen_qemu_ld8u(cpu_T[0], cpu_A0, MEM_INDEX);
893 gen_movb_A_v(cpu_T[0]);
894 zprintf("ld a,(bc)\n");
895 break;
896 case 1:
897 gen_movw_v_DE(cpu_A0);
898 tcg_gen_qemu_ld8u(cpu_T[0], cpu_A0, MEM_INDEX);
899 gen_movb_A_v(cpu_T[0]);
900 zprintf("ld a,(de)\n");
901 break;
902 case 2:
903 n = lduw_code(s->pc);
904 s->pc += 2;
905 r1 = regpairmap(OR2_HL, m);
906 tcg_gen_movi_i32(cpu_A0, n);
907 tcg_gen_qemu_ld16u(cpu_T[0], cpu_A0, MEM_INDEX);
908 gen_movw_reg_v(r1, cpu_T[0]);
909 zprintf("ld %s,($%04x)\n", regpairnames[r1], n);
910 break;
911 case 3:
912 n = lduw_code(s->pc);
913 s->pc += 2;
914 tcg_gen_movi_i32(cpu_A0, n);
915 tcg_gen_qemu_ld8u(cpu_T[0], cpu_A0, MEM_INDEX);
916 gen_movb_A_v(cpu_T[0]);
917 zprintf("ld a,($%04x)\n", n);
918 break;
920 break;
922 break;
924 case 3:
925 switch (q) {
926 case 0:
927 r1 = regpairmap(regpair[p], m);
928 gen_movw_v_reg(cpu_T[0], r1);
929 tcg_gen_addi_tl(cpu_T[0], cpu_T[0], 1);
930 gen_movw_reg_v(r1, cpu_T[0]);
931 zprintf("inc %s\n", regpairnames[r1]);
932 break;
933 case 1:
934 r1 = regpairmap(regpair[p], m);
935 gen_movw_v_reg(cpu_T[0], r1);
936 tcg_gen_subi_tl(cpu_T[0], cpu_T[0], 1);
937 gen_movw_reg_v(r1, cpu_T[0]);
938 zprintf("dec %s\n", regpairnames[r1]);
939 break;
941 break;
943 case 4:
944 r1 = regmap(reg[y], m);
945 if (is_indexed(r1)) {
946 d = ldsb_code(s->pc);
947 s->pc++;
948 gen_movb_v_idx(cpu_T[0], r1, d);
949 } else {
950 gen_movb_v_reg(cpu_T[0], r1);
952 gen_helper_incb_T0_cc();
953 if (is_indexed(r1)) {
954 gen_movb_idx_v(r1, cpu_T[0], d);
955 } else {
956 gen_movb_reg_v(r1, cpu_T[0]);
958 if (is_indexed(r1)) {
959 zprintf("inc (%s%c$%02x)\n", idxnames[r1], shexb(d));
960 } else {
961 zprintf("inc %s\n", regnames[r1]);
963 break;
965 case 5:
966 r1 = regmap(reg[y], m);
967 if (is_indexed(r1)) {
968 d = ldsb_code(s->pc);
969 s->pc++;
970 gen_movb_v_idx(cpu_T[0], r1, d);
971 } else {
972 gen_movb_v_reg(cpu_T[0], r1);
974 gen_helper_decb_T0_cc();
975 if (is_indexed(r1)) {
976 gen_movb_idx_v(r1, cpu_T[0], d);
977 } else {
978 gen_movb_reg_v(r1, cpu_T[0]);
980 if (is_indexed(r1)) {
981 zprintf("dec (%s%c$%02x)\n", idxnames[r1], shexb(d));
982 } else {
983 zprintf("dec %s\n", regnames[r1]);
985 break;
987 case 6:
988 r1 = regmap(reg[y], m);
989 if (is_indexed(r1)) {
990 d = ldsb_code(s->pc);
991 s->pc++;
993 n = ldub_code(s->pc);
994 s->pc++;
995 tcg_gen_movi_tl(cpu_T[0], n);
996 if (is_indexed(r1)) {
997 gen_movb_idx_v(r1, cpu_T[0], d);
998 } else {
999 gen_movb_reg_v(r1, cpu_T[0]);
1001 if (is_indexed(r1)) {
1002 zprintf("ld (%s%c$%02x),$%02x\n", idxnames[r1], shexb(d), n);
1003 } else {
1004 zprintf("ld %s,$%02x\n", regnames[r1], n);
1006 break;
1008 case 7:
1009 switch (y) {
1010 case 0:
1011 gen_helper_rlca_cc();
1012 zprintf("rlca\n");
1013 break;
1014 case 1:
1015 gen_helper_rrca_cc();
1016 zprintf("rrca\n");
1017 break;
1018 case 2:
1019 gen_helper_rla_cc();
1020 zprintf("rla\n");
1021 break;
1022 case 3:
1023 gen_helper_rra_cc();
1024 zprintf("rra\n");
1025 break;
1026 case 4:
1027 gen_helper_daa_cc();
1028 zprintf("daa\n");
1029 break;
1030 case 5:
1031 gen_helper_cpl_cc();
1032 zprintf("cpl\n");
1033 break;
1034 case 6:
1035 gen_helper_scf_cc();
1036 zprintf("scf\n");
1037 break;
1038 case 7:
1039 gen_helper_ccf_cc();
1040 zprintf("ccf\n");
1041 break;
1043 break;
1045 break;
1047 case 1:
1048 if (z == 6 && y == 6) {
1049 gen_jmp_im(s->pc);
1050 gen_helper_halt();
1051 zprintf("halt\n");
1052 } else {
1053 if (z == 6) {
1054 r1 = regmap(reg[z], m);
1055 r2 = regmap(reg[y], 0);
1056 } else if (y == 6) {
1057 r1 = regmap(reg[z], 0);
1058 r2 = regmap(reg[y], m);
1059 } else {
1060 r1 = regmap(reg[z], m);
1061 r2 = regmap(reg[y], m);
1063 if (is_indexed(r1) || is_indexed(r2)) {
1064 d = ldsb_code(s->pc);
1065 s->pc++;
1067 if (is_indexed(r1)) {
1068 gen_movb_v_idx(cpu_T[0], r1, d);
1069 } else {
1070 gen_movb_v_reg(cpu_T[0], r1);
1072 if (is_indexed(r2)) {
1073 gen_movb_idx_v(r2, cpu_T[0], d);
1074 } else {
1075 gen_movb_reg_v(r2, cpu_T[0]);
1077 if (is_indexed(r1)) {
1078 zprintf("ld %s,(%s%c$%02x)\n", regnames[r2], idxnames[r1], shexb(d));
1079 } else if (is_indexed(r2)) {
1080 zprintf("ld (%s%c$%02x),%s\n", idxnames[r2], shexb(d), regnames[r1]);
1081 } else {
1082 zprintf("ld %s,%s\n", regnames[r2], regnames[r1]);
1085 break;
1087 case 2:
1088 r1 = regmap(reg[z], m);
1089 if (is_indexed(r1)) {
1090 d = ldsb_code(s->pc);
1091 s->pc++;
1092 gen_movb_v_idx(cpu_T[0], r1, d);
1093 } else {
1094 gen_movb_v_reg(cpu_T[0], r1);
1096 gen_alu[y](); /* places output in A */
1097 if (is_indexed(r1)) {
1098 zprintf("%s(%s%c$%02x)\n", alu[y], idxnames[r1], shexb(d));
1099 } else {
1100 zprintf("%s%s\n", alu[y], regnames[r1]);
1102 break;
1104 case 3:
1105 switch (z) {
1106 case 0:
1107 gen_retcc(s, y, s->pc);
1108 zprintf("ret %s\n", cc[y]);
1109 break;
1111 case 1:
1112 switch (q) {
1113 case 0:
1114 r1 = regpairmap(regpair2[p], m);
1115 gen_popw(cpu_T[0]);
1116 gen_movw_reg_v(r1, cpu_T[0]);
1117 zprintf("pop %s\n", regpairnames[r1]);
1118 break;
1119 case 1:
1120 switch (p) {
1121 case 0:
1122 gen_popw(cpu_T[0]);
1123 gen_helper_jmp_T0();
1124 zprintf("ret\n");
1125 gen_eob(s);
1126 s->is_jmp = 3;
1127 // s->is_ei = 1;
1128 break;
1129 case 1:
1130 gen_ex(OR2_BC, OR2_BCX);
1131 gen_ex(OR2_DE, OR2_DEX);
1132 gen_ex(OR2_HL, OR2_HLX);
1133 zprintf("exx\n");
1134 break;
1135 case 2:
1136 r1 = regpairmap(OR2_HL, m);
1137 gen_movw_v_reg(cpu_T[0], r1);
1138 gen_helper_jmp_T0();
1139 zprintf("jp %s\n", regpairnames[r1]);
1140 gen_eob(s);
1141 s->is_jmp = 3;
1142 break;
1143 case 3:
1144 r1 = regpairmap(OR2_HL, m);
1145 gen_movw_v_reg(cpu_T[0], r1);
1146 gen_movw_SP_v(cpu_T[0]);
1147 zprintf("ld sp,%s\n", regpairnames[r1]);
1148 break;
1150 break;
1152 break;
1154 case 2:
1155 n = lduw_code(s->pc);
1156 s->pc += 2;
1157 gen_jcc(s, y, n, s->pc);
1158 zprintf("jp %s,$%04x\n", cc[y], n);
1159 break;
1161 case 3:
1162 switch (y) {
1163 case 0:
1164 n = lduw_code(s->pc);
1165 s->pc += 2;
1166 gen_jmp_im(n);
1167 zprintf("jp $%04x\n", n);
1168 gen_eob(s);
1169 s->is_jmp = 3;
1170 break;
1171 case 1:
1172 zprintf("cb prefix\n");
1173 prefixes |= PREFIX_CB;
1174 goto next_byte;
1175 break;
1176 case 2:
1177 n = ldub_code(s->pc);
1178 s->pc++;
1179 gen_movb_v_A(cpu_T[0]);
1180 if (use_icount) {
1181 gen_io_start();
1183 gen_helper_out_T0_im(tcg_const_tl(n));
1184 if (use_icount) {
1185 gen_io_end();
1186 gen_jmp_im(s->pc);
1188 zprintf("out ($%02x),a\n", n);
1189 break;
1190 case 3:
1191 n = ldub_code(s->pc);
1192 s->pc++;
1193 if (use_icount) {
1194 gen_io_start();
1196 gen_helper_in_T0_im(tcg_const_tl(n));
1197 gen_movb_A_v(cpu_T[0]);
1198 if (use_icount) {
1199 gen_io_end();
1200 gen_jmp_im(s->pc);
1202 zprintf("in a,($%02x)\n", n);
1203 break;
1204 case 4:
1205 r1 = regpairmap(OR2_HL, m);
1206 gen_popw(cpu_T[1]);
1207 gen_movw_v_reg(cpu_T[0], r1);
1208 gen_pushw(cpu_T[0]);
1209 gen_movw_reg_v(r1, cpu_T[1]);
1210 zprintf("ex (sp),%s\n", regpairnames[r1]);
1211 break;
1212 case 5:
1213 gen_ex(OR2_DE, OR2_HL);
1214 zprintf("ex de,hl\n");
1215 break;
1216 case 6:
1217 gen_helper_di();
1218 zprintf("di\n");
1219 break;
1220 case 7:
1221 gen_helper_ei();
1222 zprintf("ei\n");
1223 // gen_eob(s);
1224 // s->is_ei = 1;
1225 break;
1227 break;
1229 case 4:
1230 n = lduw_code(s->pc);
1231 s->pc += 2;
1232 gen_callcc(s, y, n, s->pc);
1233 zprintf("call %s,$%04x\n", cc[y], n);
1234 break;
1236 case 5:
1237 switch (q) {
1238 case 0:
1239 r1 = regpairmap(regpair2[p], m);
1240 gen_movw_v_reg(cpu_T[0], r1);
1241 gen_pushw(cpu_T[0]);
1242 zprintf("push %s\n", regpairnames[r1]);
1243 break;
1244 case 1:
1245 switch (p) {
1246 case 0:
1247 n = lduw_code(s->pc);
1248 s->pc += 2;
1249 tcg_gen_movi_tl(cpu_T[0], s->pc);
1250 gen_pushw(cpu_T[0]);
1251 gen_jmp_im(n);
1252 zprintf("call $%04x\n", n);
1253 gen_eob(s);
1254 s->is_jmp = 3;
1255 break;
1256 case 1:
1257 zprintf("dd prefix\n");
1258 prefixes |= PREFIX_DD;
1259 goto next_byte;
1260 break;
1261 case 2:
1262 zprintf("ed prefix\n");
1263 prefixes |= PREFIX_ED;
1264 goto next_byte;
1265 break;
1266 case 3:
1267 zprintf("fd prefix\n");
1268 prefixes |= PREFIX_FD;
1269 goto next_byte;
1270 break;
1272 break;
1274 break;
1276 case 6:
1277 n = ldub_code(s->pc);
1278 s->pc++;
1279 tcg_gen_movi_tl(cpu_T[0], n);
1280 gen_alu[y](); /* places output in A */
1281 zprintf("%s$%02x\n", alu[y], n);
1282 break;
1284 case 7:
1285 tcg_gen_movi_tl(cpu_T[0], s->pc);
1286 gen_pushw(cpu_T[0]);
1287 gen_jmp_im(y*8);
1288 zprintf("rst $%02x\n", y*8);
1289 gen_eob(s);
1290 s->is_jmp = 3;
1291 break;
1293 break;
1295 } else if (prefixes & PREFIX_CB) {
1296 /* cb mode: */
1298 int x, y, z, p, q;
1299 int d;
1300 int r1, r2;
1302 if (m != MODE_NORMAL) {
1303 d = ldsb_code(s->pc);
1304 s->pc++;
1307 b = ldub_code(s->pc);
1308 s->pc++;
1310 x = (b >> 6) & 0x03;
1311 y = (b >> 3) & 0x07;
1312 z = b & 0x07;
1313 p = y >> 1;
1314 q = y & 0x01;
1316 if (m != MODE_NORMAL) {
1317 r1 = regmap(OR_HLmem, m);
1318 gen_movb_v_idx(cpu_T[0], r1, d);
1319 if (z != 6) {
1320 r2 = regmap(reg[z], 0);
1322 } else {
1323 r1 = regmap(reg[z], m);
1324 gen_movb_v_reg(cpu_T[0], r1);
1327 switch (x) {
1328 case 0:
1329 /* TODO: TST instead of SLL for R800 */
1330 gen_rot_T0[y]();
1331 if (m != MODE_NORMAL) {
1332 gen_movb_idx_v(r1, cpu_T[0], d);
1333 if (z != 6) {
1334 gen_movb_reg_v(r2, cpu_T[0]);
1336 } else {
1337 gen_movb_reg_v(r1, cpu_T[0]);
1339 zprintf("%s %s\n", rot[y], regnames[r1]);
1340 break;
1341 case 1:
1342 gen_helper_bit_T0(tcg_const_tl(1 << y));
1343 zprintf("bit %i,%s\n", y, regnames[r1]);
1344 break;
1345 case 2:
1346 tcg_gen_andi_tl(cpu_T[0], cpu_T[0], ~(1 << y));
1347 if (m != MODE_NORMAL) {
1348 gen_movb_idx_v(r1, cpu_T[0], d);
1349 if (z != 6) {
1350 gen_movb_reg_v(r2, cpu_T[0]);
1352 } else {
1353 gen_movb_reg_v(r1, cpu_T[0]);
1355 zprintf("res %i,%s\n", y, regnames[r1]);
1356 break;
1357 case 3:
1358 tcg_gen_ori_tl(cpu_T[0], cpu_T[0], 1 << y);
1359 if (m != MODE_NORMAL) {
1360 gen_movb_idx_v(r1, cpu_T[0], d);
1361 if (z != 6) {
1362 gen_movb_reg_v(r2, cpu_T[0]);
1364 } else {
1365 gen_movb_reg_v(r1, cpu_T[0]);
1367 zprintf("set %i,%s\n", y, regnames[r1]);
1368 break;
1371 } else if (prefixes & PREFIX_ED) {
1372 /* ed mode: */
1374 b = ldub_code(s->pc);
1375 s->pc++;
1377 int x, y, z, p, q;
1378 int n;
1379 int r1, r2;
1381 x = (b >> 6) & 0x03;
1382 y = (b >> 3) & 0x07;
1383 z = b & 0x07;
1384 p = y >> 1;
1385 q = y & 0x01;
1387 switch (x) {
1388 case 0:
1389 zprintf("nop\n");
1390 break;
1391 case 3:
1392 if (s->model == Z80_CPU_R800) {
1393 switch (z) {
1394 case 1:
1395 /* does mulub work with r1 == h, l, (hl) or a? */
1396 r1 = regmap(reg[y], m);
1397 gen_movb_v_reg(cpu_T[0], r1);
1398 gen_helper_mulub_cc();
1399 zprintf("mulub a,%s\n", regnames[r1]);
1400 break;
1401 case 3:
1402 if (q == 0) {
1403 /* does muluw work with r1 == de or hl? */
1404 /* what is the effect of DD/FD prefixes here? */
1405 r1 = regpairmap(regpair[p], m);
1406 gen_movw_v_reg(cpu_T[0], r1);
1407 gen_helper_muluw_cc();
1408 zprintf("muluw hl,%s\n", regpairnames[r1]);
1409 } else {
1410 zprintf("nop\n");
1412 break;
1413 default:
1414 zprintf("nop\n");
1415 break;
1417 } else {
1418 zprintf("nop\n");
1420 break;
1422 case 1:
1423 switch (z) {
1424 case 0:
1425 if (use_icount) {
1426 gen_io_start();
1428 gen_helper_in_T0_bc_cc();
1429 if (y != 6) {
1430 r1 = regmap(reg[y], m);
1431 gen_movb_reg_v(r1, cpu_T[0]);
1432 zprintf("in %s,(c)\n", regnames[r1]);
1433 } else {
1434 zprintf("in (c)\n");
1436 if (use_icount) {
1437 gen_io_end();
1438 gen_jmp_im(s->pc);
1440 break;
1441 case 1:
1442 if (y != 6) {
1443 r1 = regmap(reg[y], m);
1444 gen_movb_v_reg(cpu_T[0], r1);
1445 zprintf("out (c),%s\n", regnames[r1]);
1446 } else {
1447 tcg_gen_movi_tl(cpu_T[0], 0);
1448 zprintf("out (c),0\n");
1450 if (use_icount) {
1451 gen_io_start();
1453 gen_helper_out_T0_bc();
1454 if (use_icount) {
1455 gen_io_end();
1456 gen_jmp_im(s->pc);
1458 break;
1459 case 2:
1460 r1 = regpairmap(OR2_HL, m);
1461 r2 = regpairmap(regpair[p], m);
1462 gen_movw_v_reg(cpu_T[0], r1);
1463 gen_movw_v_reg(cpu_T[1], r2);
1464 if (q == 0) {
1465 zprintf("sbc %s,%s\n", regpairnames[r1], regpairnames[r2]);
1466 gen_helper_sbcw_T0_T1_cc();
1467 } else {
1468 zprintf("adc %s,%s\n", regpairnames[r1], regpairnames[r2]);
1469 gen_helper_adcw_T0_T1_cc();
1471 gen_movw_reg_v(r1, cpu_T[0]);
1472 break;
1473 case 3:
1474 n = lduw_code(s->pc);
1475 s->pc += 2;
1476 r1 = regpairmap(regpair[p], m);
1477 if (q == 0) {
1478 gen_movw_v_reg(cpu_T[0], r1);
1479 tcg_gen_movi_i32(cpu_A0, n);
1480 tcg_gen_qemu_st16(cpu_T[0], cpu_A0, MEM_INDEX);
1481 zprintf("ld ($%02x),%s\n", n, regpairnames[r1]);
1482 } else {
1483 tcg_gen_movi_i32(cpu_A0, n);
1484 tcg_gen_qemu_ld16u(cpu_T[0], cpu_A0, MEM_INDEX);
1485 gen_movw_reg_v(r1, cpu_T[0]);
1486 zprintf("ld %s,($%02x)\n", regpairnames[r1], n);
1488 break;
1489 case 4:
1490 zprintf("neg\n");
1491 gen_helper_neg_cc();
1492 break;
1493 case 5:
1494 /* FIXME */
1495 gen_popw(cpu_T[0]);
1496 gen_helper_jmp_T0();
1497 gen_helper_ri();
1498 if (q == 0) {
1499 zprintf("retn\n");
1500 } else {
1501 zprintf("reti\n");
1503 gen_eob(s);
1504 s->is_jmp = 3;
1505 // s->is_ei = 1;
1506 break;
1507 case 6:
1508 gen_helper_imode(tcg_const_tl(imode[y]));
1509 zprintf("im im[%i]\n", imode[y]);
1510 // gen_eob(s);
1511 // s->is_ei = 1;
1512 break;
1513 case 7:
1514 switch (y) {
1515 case 0:
1516 gen_helper_ld_I_A();
1517 zprintf("ld i,a\n");
1518 break;
1519 case 1:
1520 gen_helper_ld_R_A();
1521 zprintf("ld r,a\n");
1522 break;
1523 case 2:
1524 gen_helper_ld_A_I();
1525 zprintf("ld a,i\n");
1526 break;
1527 case 3:
1528 gen_helper_ld_A_R();
1529 zprintf("ld a,r\n");
1530 break;
1531 case 4:
1532 gen_movb_v_HLmem(cpu_T[0]);
1533 gen_helper_rrd_cc();
1534 gen_movb_HLmem_v(cpu_T[0]);
1535 zprintf("rrd\n");
1536 break;
1537 case 5:
1538 gen_movb_v_HLmem(cpu_T[0]);
1539 gen_helper_rld_cc();
1540 gen_movb_HLmem_v(cpu_T[0]);
1541 zprintf("rld\n");
1542 break;
1543 case 6:
1544 case 7:
1545 zprintf("nop2\n");
1546 /* nop */
1547 break;
1549 break;
1551 break;
1553 case 2:
1554 /* FIXME */
1555 if (y >= 4) {
1556 switch (z) {
1557 case 0: /* ldi/ldd/ldir/lddr */
1558 gen_movw_v_HL(cpu_A0);
1559 tcg_gen_qemu_ld8u(cpu_T[0], cpu_A0, MEM_INDEX);
1560 gen_movw_v_DE(cpu_A0);
1561 tcg_gen_qemu_st8(cpu_T[0], cpu_A0, MEM_INDEX);
1563 if (!(y & 1)) {
1564 gen_helper_bli_ld_inc_cc();
1565 } else {
1566 gen_helper_bli_ld_dec_cc();
1568 if ((y & 2)) {
1569 gen_helper_bli_ld_rep(tcg_const_tl(s->pc));
1570 gen_eob(s);
1571 s->is_jmp = 3;
1573 break;
1575 case 1: /* cpi/cpd/cpir/cpdr */
1576 gen_movw_v_HL(cpu_A0);
1577 tcg_gen_qemu_ld8u(cpu_T[0], cpu_A0, MEM_INDEX);
1578 gen_helper_bli_cp_cc();
1580 if (!(y & 1)) {
1581 gen_helper_bli_cp_inc_cc();
1582 } else {
1583 gen_helper_bli_cp_dec_cc();
1585 if ((y & 2)) {
1586 gen_helper_bli_cp_rep(tcg_const_tl(s->pc));
1587 gen_eob(s);
1588 s->is_jmp = 3;
1590 break;
1592 case 2: /* ini/ind/inir/indr */
1593 if (use_icount) {
1594 gen_io_start();
1596 gen_helper_in_T0_bc_cc();
1597 if (use_icount) {
1598 gen_io_end();
1600 gen_movw_v_HL(cpu_A0);
1601 tcg_gen_qemu_st8(cpu_T[0], cpu_A0, MEM_INDEX);
1602 if (!(y & 1)) {
1603 gen_helper_bli_io_T0_inc(0);
1604 } else {
1605 gen_helper_bli_io_T0_dec(0);
1607 if ((y & 2)) {
1608 gen_helper_bli_io_rep(tcg_const_tl(s->pc));
1609 gen_eob(s);
1610 s->is_jmp = 3;
1611 } else if (use_icount) {
1612 gen_jmp_im(s->pc);
1614 break;
1616 case 3: /* outi/outd/otir/otdr */
1617 gen_movw_v_HL(cpu_A0);
1618 tcg_gen_qemu_ld8u(cpu_T[0], cpu_A0, MEM_INDEX);
1619 if (use_icount) {
1620 gen_io_start();
1622 gen_helper_out_T0_bc();
1623 if (use_icount) {
1624 gen_io_end();
1626 if (!(y & 1)) {
1627 gen_helper_bli_io_T0_inc(1);
1628 } else {
1629 gen_helper_bli_io_T0_dec(1);
1631 if ((y & 2)) {
1632 gen_helper_bli_io_rep(tcg_const_tl(s->pc));
1633 gen_eob(s);
1634 s->is_jmp = 3;
1635 } else if (use_icount) {
1636 gen_jmp_im(s->pc);
1638 break;
1641 zprintf("%s\n", bli[y-4][z]);
1642 break;
1647 prefixes = 0;
1649 /* now check op code */
1650 // switch (b) {
1651 // default:
1652 // goto illegal_op;
1653 // }
1654 /* lock generation */
1655 return s->pc;
1656 illegal_op:
1657 /* XXX: ensure that no lock was generated */
1658 gen_exception(s, EXCP06_ILLOP, pc_start - s->cs_base);
1659 return s->pc;
1662 #define CC_SZHPNC (CC_S | CC_Z | CC_H | CC_P | CC_N | CC_C)
1663 #define CC_SZHPN (CC_S | CC_Z | CC_H | CC_P | CC_N)
1665 void z80_translate_init(void)
1667 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
1669 #if TARGET_LONG_BITS > HOST_LONG_BITS
1670 cpu_T[0] = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUState, t0), "T0");
1671 cpu_T[1] = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUState, t1), "T1");
1672 #else
1673 cpu_T[0] = tcg_global_reg_new_i32(TCG_AREG1, "T0");
1674 cpu_T[1] = tcg_global_reg_new_i32(TCG_AREG2, "T1");
1675 #endif
1676 cpu_A0 = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUState, a0), "A0");
1678 /* register helpers */
1679 #define GEN_HELPER 2
1680 #include "helper.h"
1683 /* generate intermediate code in gen_opc_buf and gen_opparam_buf for
1684 basic block 'tb'. If search_pc is TRUE, also generate PC
1685 information for each intermediate instruction. */
1686 static inline int gen_intermediate_code_internal(CPUState *env,
1687 TranslationBlock *tb,
1688 int search_pc)
1690 DisasContext dc1, *dc = &dc1;
1691 target_ulong pc_ptr;
1692 uint16_t *gen_opc_end;
1693 CPUBreakpoint *bp;
1694 int flags, j, lj, cflags;
1695 target_ulong pc_start;
1696 target_ulong cs_base;
1697 int num_insns;
1698 int max_insns;
1700 /* generate intermediate code */
1701 pc_start = tb->pc;
1702 cs_base = tb->cs_base;
1703 flags = tb->flags;
1704 cflags = tb->cflags;
1706 dc->singlestep_enabled = env->singlestep_enabled;
1707 dc->cs_base = cs_base;
1708 dc->tb = tb;
1709 dc->flags = flags;
1710 dc->jmp_opt = !(env->singlestep_enabled ||
1711 (flags & HF_INHIBIT_IRQ_MASK)
1712 #ifndef CONFIG_SOFTMMU
1713 || (flags & HF_SOFTMMU_MASK)
1714 #endif
1717 gen_opc_ptr = gen_opc_buf;
1718 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
1719 gen_opparam_ptr = gen_opparam_buf;
1721 dc->is_jmp = DISAS_NEXT;
1722 pc_ptr = pc_start;
1723 lj = -1;
1724 dc->model = env->model;
1726 num_insns = 0;
1727 max_insns = tb->cflags & CF_COUNT_MASK;
1728 if (max_insns == 0) {
1729 max_insns = CF_COUNT_MASK;
1732 gen_icount_start();
1733 for (;;) {
1734 if (unlikely(!TAILQ_EMPTY(&env->breakpoints))) {
1735 TAILQ_FOREACH(bp, &env->breakpoints, entry) {
1736 if (bp->pc == pc_ptr) {
1737 gen_debug(dc, pc_ptr - dc->cs_base);
1738 break;
1742 if (search_pc) {
1743 j = gen_opc_ptr - gen_opc_buf;
1744 if (lj < j) {
1745 lj++;
1746 while (lj < j) {
1747 gen_opc_instr_start[lj++] = 0;
1750 gen_opc_pc[lj] = pc_ptr;
1751 gen_opc_instr_start[lj] = 1;
1752 gen_opc_icount[lj] = num_insns;
1754 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO)) {
1755 gen_io_start();
1758 pc_ptr = disas_insn(dc, pc_ptr);
1759 num_insns++;
1760 /* stop translation if indicated */
1761 if (dc->is_jmp) {
1762 break;
1764 /* if single step mode, we generate only one instruction and
1765 generate an exception */
1766 /* if irq were inhibited with HF_INHIBIT_IRQ_MASK, we clear
1767 the flag and abort the translation to give the irqs a
1768 change to be happen */
1769 if (dc->singlestep_enabled ||
1770 (flags & HF_INHIBIT_IRQ_MASK)) {
1771 gen_jmp_im(pc_ptr - dc->cs_base);
1772 gen_eob(dc);
1773 break;
1775 /* if too long translation, stop generation too */
1776 if (gen_opc_ptr >= gen_opc_end ||
1777 (pc_ptr - pc_start) >= (TARGET_PAGE_SIZE - 32) ||
1778 num_insns >= max_insns) {
1779 gen_jmp_im(pc_ptr - dc->cs_base);
1780 gen_eob(dc);
1781 break;
1783 if (singlestep) {
1784 gen_jmp_im(pc_ptr - dc->cs_base);
1785 gen_eob(dc);
1786 break;
1789 if (tb->cflags & CF_LAST_IO) {
1790 gen_io_end();
1792 gen_icount_end(tb, num_insns);
1793 *gen_opc_ptr = INDEX_op_end;
1794 /* we don't forget to fill the last values */
1795 if (search_pc) {
1796 j = gen_opc_ptr - gen_opc_buf;
1797 lj++;
1798 while (lj <= j) {
1799 gen_opc_instr_start[lj++] = 0;
1803 #ifdef DEBUG_DISAS
1804 log_cpu_state_mask(CPU_LOG_TB_CPU, env, 0);
1805 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
1806 qemu_log("----------------\n");
1807 qemu_log("IN: %s\n", lookup_symbol(pc_start));
1808 log_target_disas(pc_start, pc_ptr - pc_start, 0);
1809 qemu_log("\n");
1811 #endif
1813 if (!search_pc) {
1814 tb->size = pc_ptr - pc_start;
1815 tb->icount = num_insns;
1817 return 0;
1820 void gen_intermediate_code(CPUState *env, TranslationBlock *tb)
1822 gen_intermediate_code_internal(env, tb, 0);
1825 void gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb)
1827 gen_intermediate_code_internal(env, tb, 1);
1830 void gen_pc_load(CPUState *env, TranslationBlock *tb,
1831 unsigned long searched_pc, int pc_pos, void *puc)
1833 env->pc = gen_opc_pc[pc_pos];