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
37 #define PREFIX_CB 0x01
38 #define PREFIX_DD 0x02
39 #define PREFIX_ED 0x04
40 #define PREFIX_FD 0x08
47 //#define zprintf printf
49 /* global register indexes */
50 static TCGv cpu_env
, cpu_T
[3], cpu_A0
;
52 #include "gen-icount.h"
56 typedef struct DisasContext
{
57 /* current insn context */
58 int override
; /* -1 if no override */
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) */
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
;
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
);
97 static const char *const regnames
[] = {
113 [OR_IXmem
] = "(ix+d)",
114 [OR_IYmem
] = "(iy+d)",
117 static const char *const idxnames
[] = {
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))
130 #define UNIT_OFFSET(type, units, num) (num * units)
133 #define BYTE_OFFSET(type, num) UNIT_OFFSET(type, 1, num)
134 #define WORD_OFFSET(type, num) UNIT_OFFSET(type, 2, num)
139 #include "genreg_template_af.h"
147 #include "genreg_template.h"
155 #include "genreg_template.h"
163 #include "genreg_template.h"
171 #include "genreg_template.h"
179 #include "genreg_template.h"
187 #include "genreg_template_af.h"
195 #include "genreg_template.h"
203 #include "genreg_template.h"
211 #include "genreg_template.h"
217 #include "genreg_template.h"
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();
227 tcg_gen_qemu_ld8u(v
, addr
, MEM_INDEX
);
231 static inline void gen_movb_HLmem_v(TCGv v
)
233 TCGv addr
= tcg_temp_new();
235 tcg_gen_qemu_st8(v
, addr
, MEM_INDEX
);
239 static inline void gen_movb_v_IXmem(TCGv v
, uint16_t ofs
)
241 TCGv addr
= tcg_temp_new();
243 tcg_gen_addi_tl(addr
, addr
, ofs
);
244 tcg_gen_ext16u_tl(addr
, addr
);
245 tcg_gen_qemu_ld8u(v
, addr
, MEM_INDEX
);
249 static inline void gen_movb_v_IYmem(TCGv v
, uint16_t ofs
)
251 TCGv addr
= tcg_temp_new();
253 tcg_gen_addi_tl(addr
, addr
, ofs
);
254 tcg_gen_ext16u_tl(addr
, addr
);
255 tcg_gen_qemu_ld8u(v
, addr
, MEM_INDEX
);
259 static inline void gen_movb_IXmem_v(TCGv v
, uint16_t ofs
)
261 TCGv addr
= tcg_temp_new();
263 tcg_gen_addi_tl(addr
, addr
, ofs
);
264 tcg_gen_ext16u_tl(addr
, addr
);
265 tcg_gen_qemu_st8(v
, addr
, MEM_INDEX
);
269 static inline void gen_movb_IYmem_v(TCGv v
, uint16_t ofs
)
271 TCGv addr
= tcg_temp_new();
273 tcg_gen_addi_tl(addr
, addr
, ofs
);
274 tcg_gen_ext16u_tl(addr
, addr
);
275 tcg_gen_qemu_st8(v
, addr
, MEM_INDEX
);
279 static inline void gen_pushw(TCGv v
)
281 TCGv addr
= tcg_temp_new();
283 tcg_gen_subi_i32(addr
, addr
, 2);
284 tcg_gen_ext16u_i32(addr
, addr
);
286 tcg_gen_qemu_st16(v
, addr
, MEM_INDEX
);
290 static inline void gen_popw(TCGv v
)
292 TCGv addr
= tcg_temp_new();
294 tcg_gen_qemu_ld16u(v
, addr
, MEM_INDEX
);
295 tcg_gen_addi_i32(addr
, addr
, 2);
296 tcg_gen_ext16u_i32(addr
, 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
)
396 static inline int is_indexed(int reg
)
398 if (reg
== OR_IXmem
|| reg
== OR_IYmem
) {
405 static const int reg
[8] = {
417 /* 16-bit registers and register pairs */
433 static const char *const regpairnames
[] = {
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
)
509 static const int regpair
[4] = {
516 static const int regpair2
[4] = {
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
)
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
) {
548 static void gen_exception(DisasContext
*s
, int trapno
, target_ulong cur_pc
)
551 gen_helper_raise_exception(trapno
);
557 static const char *const cc
[8] = {
579 static const int cc_flags
[4] = {
586 /* Arithmetic/logic operations */
588 static const char *const alu
[8] = {
599 typedef void (alu_helper_func
)(void);
601 static alu_helper_func
*const gen_alu
[8] = {
612 /* Rotation/shift operations */
614 static const char *const rot
[8] = {
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
,
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
)
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
;
674 l1
= gen_new_label();
676 gen_cond_jump(cc
, l1
);
678 gen_goto_tb(s
, 0, next_pc
);
681 gen_goto_tb(s
, 1, val
);
686 static inline void gen_callcc(DisasContext
*s
, int cc
,
687 target_ulong val
, target_ulong next_pc
)
689 TranslationBlock
*tb
;
694 l1
= gen_new_label();
696 gen_cond_jump(cc
, l1
);
698 gen_goto_tb(s
, 0, next_pc
);
701 tcg_gen_movi_tl(cpu_T
[0], next_pc
);
703 gen_goto_tb(s
, 1, val
);
708 static inline void gen_retcc(DisasContext
*s
, int cc
,
709 target_ulong next_pc
)
711 TranslationBlock
*tb
;
716 l1
= gen_new_label();
718 gen_cond_jump(cc
, l1
);
720 gen_goto_tb(s
, 0, next_pc
);
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
);
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
)
760 //printf("PC = %04x: ", s->pc);
762 s
->prefix
= prefixes
;
766 if (prefixes
& PREFIX_DD
) {
768 } else if (prefixes
& PREFIX_FD
) {
774 /* unprefixed opcodes */
776 if ((prefixes
& (PREFIX_CB
| PREFIX_ED
)) == 0) {
777 b
= ldub_code(s
->pc
);
800 gen_ex(OR2_AF
, OR2_AFX
);
801 zprintf("ex af,af'\n");
804 n
= ldsb_code(s
->pc
);
806 gen_helper_djnz(tcg_const_tl(s
->pc
+ n
), tcg_const_tl(s
->pc
));
809 zprintf("djnz $%02x\n", n
);
812 n
= ldsb_code(s
->pc
);
814 gen_jmp_im(s
->pc
+ n
);
817 zprintf("jr $%02x\n", n
);
823 n
= ldsb_code(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
);
834 n
= lduw_code(s
->pc
);
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
);
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
]);
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");
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");
870 n
= lduw_code(s
->pc
);
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
]);
879 n
= lduw_code(s
->pc
);
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
);
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");
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");
903 n
= lduw_code(s
->pc
);
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
);
912 n
= lduw_code(s
->pc
);
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
);
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
]);
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
]);
944 r1
= regmap(reg
[y
], m
);
945 if (is_indexed(r1
)) {
946 d
= ldsb_code(s
->pc
);
948 gen_movb_v_idx(cpu_T
[0], r1
, d
);
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
);
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
));
961 zprintf("inc %s\n", regnames
[r1
]);
966 r1
= regmap(reg
[y
], m
);
967 if (is_indexed(r1
)) {
968 d
= ldsb_code(s
->pc
);
970 gen_movb_v_idx(cpu_T
[0], r1
, d
);
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
);
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
));
983 zprintf("dec %s\n", regnames
[r1
]);
988 r1
= regmap(reg
[y
], m
);
989 if (is_indexed(r1
)) {
990 d
= ldsb_code(s
->pc
);
993 n
= ldub_code(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
);
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
);
1004 zprintf("ld %s,$%02x\n", regnames
[r1
], n
);
1011 gen_helper_rlca_cc();
1015 gen_helper_rrca_cc();
1019 gen_helper_rla_cc();
1023 gen_helper_rra_cc();
1027 gen_helper_daa_cc();
1031 gen_helper_cpl_cc();
1035 gen_helper_scf_cc();
1039 gen_helper_ccf_cc();
1048 if (z
== 6 && y
== 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
);
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
);
1067 if (is_indexed(r1
)) {
1068 gen_movb_v_idx(cpu_T
[0], r1
, d
);
1070 gen_movb_v_reg(cpu_T
[0], r1
);
1072 if (is_indexed(r2
)) {
1073 gen_movb_idx_v(r2
, cpu_T
[0], d
);
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
]);
1082 zprintf("ld %s,%s\n", regnames
[r2
], regnames
[r1
]);
1088 r1
= regmap(reg
[z
], m
);
1089 if (is_indexed(r1
)) {
1090 d
= ldsb_code(s
->pc
);
1092 gen_movb_v_idx(cpu_T
[0], r1
, d
);
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
));
1100 zprintf("%s%s\n", alu
[y
], regnames
[r1
]);
1107 gen_retcc(s
, y
, s
->pc
);
1108 zprintf("ret %s\n", cc
[y
]);
1114 r1
= regpairmap(regpair2
[p
], m
);
1116 gen_movw_reg_v(r1
, cpu_T
[0]);
1117 zprintf("pop %s\n", regpairnames
[r1
]);
1123 gen_helper_jmp_T0();
1130 gen_ex(OR2_BC
, OR2_BCX
);
1131 gen_ex(OR2_DE
, OR2_DEX
);
1132 gen_ex(OR2_HL
, OR2_HLX
);
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
]);
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
]);
1155 n
= lduw_code(s
->pc
);
1157 gen_jcc(s
, y
, n
, s
->pc
);
1158 zprintf("jp %s,$%04x\n", cc
[y
], n
);
1164 n
= lduw_code(s
->pc
);
1167 zprintf("jp $%04x\n", n
);
1172 zprintf("cb prefix\n");
1173 prefixes
|= PREFIX_CB
;
1177 n
= ldub_code(s
->pc
);
1179 gen_movb_v_A(cpu_T
[0]);
1183 gen_helper_out_T0_im(tcg_const_tl(n
));
1188 zprintf("out ($%02x),a\n", n
);
1191 n
= ldub_code(s
->pc
);
1196 gen_helper_in_T0_im(tcg_const_tl(n
));
1197 gen_movb_A_v(cpu_T
[0]);
1202 zprintf("in a,($%02x)\n", n
);
1205 r1
= regpairmap(OR2_HL
, m
);
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
]);
1213 gen_ex(OR2_DE
, OR2_HL
);
1214 zprintf("ex de,hl\n");
1230 n
= lduw_code(s
->pc
);
1232 gen_callcc(s
, y
, n
, s
->pc
);
1233 zprintf("call %s,$%04x\n", cc
[y
], n
);
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
]);
1247 n
= lduw_code(s
->pc
);
1249 tcg_gen_movi_tl(cpu_T
[0], s
->pc
);
1250 gen_pushw(cpu_T
[0]);
1252 zprintf("call $%04x\n", n
);
1257 zprintf("dd prefix\n");
1258 prefixes
|= PREFIX_DD
;
1262 zprintf("ed prefix\n");
1263 prefixes
|= PREFIX_ED
;
1267 zprintf("fd prefix\n");
1268 prefixes
|= PREFIX_FD
;
1277 n
= ldub_code(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
);
1285 tcg_gen_movi_tl(cpu_T
[0], s
->pc
);
1286 gen_pushw(cpu_T
[0]);
1288 zprintf("rst $%02x\n", y
*8);
1295 } else if (prefixes
& PREFIX_CB
) {
1302 if (m
!= MODE_NORMAL
) {
1303 d
= ldsb_code(s
->pc
);
1307 b
= ldub_code(s
->pc
);
1310 x
= (b
>> 6) & 0x03;
1311 y
= (b
>> 3) & 0x07;
1316 if (m
!= MODE_NORMAL
) {
1317 r1
= regmap(OR_HLmem
, m
);
1318 gen_movb_v_idx(cpu_T
[0], r1
, d
);
1320 r2
= regmap(reg
[z
], 0);
1323 r1
= regmap(reg
[z
], m
);
1324 gen_movb_v_reg(cpu_T
[0], r1
);
1329 /* TODO: TST instead of SLL for R800 */
1331 if (m
!= MODE_NORMAL
) {
1332 gen_movb_idx_v(r1
, cpu_T
[0], d
);
1334 gen_movb_reg_v(r2
, cpu_T
[0]);
1337 gen_movb_reg_v(r1
, cpu_T
[0]);
1339 zprintf("%s %s\n", rot
[y
], regnames
[r1
]);
1342 gen_helper_bit_T0(tcg_const_tl(1 << y
));
1343 zprintf("bit %i,%s\n", y
, regnames
[r1
]);
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
);
1350 gen_movb_reg_v(r2
, cpu_T
[0]);
1353 gen_movb_reg_v(r1
, cpu_T
[0]);
1355 zprintf("res %i,%s\n", y
, regnames
[r1
]);
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
);
1362 gen_movb_reg_v(r2
, cpu_T
[0]);
1365 gen_movb_reg_v(r1
, cpu_T
[0]);
1367 zprintf("set %i,%s\n", y
, regnames
[r1
]);
1371 } else if (prefixes
& PREFIX_ED
) {
1374 b
= ldub_code(s
->pc
);
1381 x
= (b
>> 6) & 0x03;
1382 y
= (b
>> 3) & 0x07;
1392 if (s
->model
== Z80_CPU_R800
) {
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
]);
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
]);
1428 gen_helper_in_T0_bc_cc();
1430 r1
= regmap(reg
[y
], m
);
1431 gen_movb_reg_v(r1
, cpu_T
[0]);
1432 zprintf("in %s,(c)\n", regnames
[r1
]);
1434 zprintf("in (c)\n");
1443 r1
= regmap(reg
[y
], m
);
1444 gen_movb_v_reg(cpu_T
[0], r1
);
1445 zprintf("out (c),%s\n", regnames
[r1
]);
1447 tcg_gen_movi_tl(cpu_T
[0], 0);
1448 zprintf("out (c),0\n");
1453 gen_helper_out_T0_bc();
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
);
1465 zprintf("sbc %s,%s\n", regpairnames
[r1
], regpairnames
[r2
]);
1466 gen_helper_sbcw_T0_T1_cc();
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]);
1474 n
= lduw_code(s
->pc
);
1476 r1
= regpairmap(regpair
[p
], m
);
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
]);
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
);
1491 gen_helper_neg_cc();
1496 gen_helper_jmp_T0();
1508 gen_helper_imode(tcg_const_tl(imode
[y
]));
1509 zprintf("im im[%i]\n", imode
[y
]);
1516 gen_helper_ld_I_A();
1517 zprintf("ld i,a\n");
1520 gen_helper_ld_R_A();
1521 zprintf("ld r,a\n");
1524 gen_helper_ld_A_I();
1525 zprintf("ld a,i\n");
1528 gen_helper_ld_A_R();
1529 zprintf("ld a,r\n");
1532 gen_movb_v_HLmem(cpu_T
[0]);
1533 gen_helper_rrd_cc();
1534 gen_movb_HLmem_v(cpu_T
[0]);
1538 gen_movb_v_HLmem(cpu_T
[0]);
1539 gen_helper_rld_cc();
1540 gen_movb_HLmem_v(cpu_T
[0]);
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
);
1564 gen_helper_bli_ld_inc_cc();
1566 gen_helper_bli_ld_dec_cc();
1569 gen_helper_bli_ld_rep(tcg_const_tl(s
->pc
));
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();
1581 gen_helper_bli_cp_inc_cc();
1583 gen_helper_bli_cp_dec_cc();
1586 gen_helper_bli_cp_rep(tcg_const_tl(s
->pc
));
1592 case 2: /* ini/ind/inir/indr */
1596 gen_helper_in_T0_bc_cc();
1600 gen_movw_v_HL(cpu_A0
);
1601 tcg_gen_qemu_st8(cpu_T
[0], cpu_A0
, MEM_INDEX
);
1603 gen_helper_bli_io_T0_inc(0);
1605 gen_helper_bli_io_T0_dec(0);
1608 gen_helper_bli_io_rep(tcg_const_tl(s
->pc
));
1611 } else if (use_icount
) {
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
);
1622 gen_helper_out_T0_bc();
1627 gen_helper_bli_io_T0_inc(1);
1629 gen_helper_bli_io_T0_dec(1);
1632 gen_helper_bli_io_rep(tcg_const_tl(s
->pc
));
1635 } else if (use_icount
) {
1641 zprintf("%s\n", bli
[y
-4][z
]);
1649 /* now check op code */
1654 /* lock generation */
1657 /* XXX: ensure that no lock was generated */
1658 gen_exception(s
, EXCP06_ILLOP
, pc_start
- s
->cs_base
);
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");
1673 cpu_T
[0] = tcg_global_reg_new_i32(TCG_AREG1
, "T0");
1674 cpu_T
[1] = tcg_global_reg_new_i32(TCG_AREG2
, "T1");
1676 cpu_A0
= tcg_global_mem_new_i32(TCG_AREG0
, offsetof(CPUState
, a0
), "A0");
1678 /* register helpers */
1679 #define GEN_HELPER 2
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
,
1690 DisasContext dc1
, *dc
= &dc1
;
1691 target_ulong pc_ptr
;
1692 uint16_t *gen_opc_end
;
1694 int flags
, j
, lj
, cflags
;
1695 target_ulong pc_start
;
1696 target_ulong cs_base
;
1700 /* generate intermediate code */
1702 cs_base
= tb
->cs_base
;
1704 cflags
= tb
->cflags
;
1706 dc
->singlestep_enabled
= env
->singlestep_enabled
;
1707 dc
->cs_base
= cs_base
;
1710 dc
->jmp_opt
= !(env
->singlestep_enabled
||
1711 (flags
& HF_INHIBIT_IRQ_MASK
)
1712 #ifndef CONFIG_SOFTMMU
1713 || (flags
& HF_SOFTMMU_MASK
)
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
;
1724 dc
->model
= env
->model
;
1727 max_insns
= tb
->cflags
& CF_COUNT_MASK
;
1728 if (max_insns
== 0) {
1729 max_insns
= CF_COUNT_MASK
;
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
);
1743 j
= gen_opc_ptr
- gen_opc_buf
;
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
)) {
1758 pc_ptr
= disas_insn(dc
, pc_ptr
);
1760 /* stop translation if indicated */
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
);
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
);
1784 gen_jmp_im(pc_ptr
- dc
->cs_base
);
1789 if (tb
->cflags
& CF_LAST_IO
) {
1792 gen_icount_end(tb
, num_insns
);
1793 *gen_opc_ptr
= INDEX_op_end
;
1794 /* we don't forget to fill the last values */
1796 j
= gen_opc_ptr
- gen_opc_buf
;
1799 gen_opc_instr_start
[lj
++] = 0;
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);
1814 tb
->size
= pc_ptr
- pc_start
;
1815 tb
->icount
= num_insns
;
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
];