--- hatari/src/uae-cpu/gencpu.c 2019/04/09 08:47:23 1.1.1.11 +++ hatari/src/uae-cpu/gencpu.c 2019/04/09 08:49:40 1.1.1.13 @@ -59,6 +59,10 @@ /* can pair with a lsr) (Anomaly Demo Intro). */ /* 2008/04/26 [NP] Handle sz_byte for Areg in genamode, as 'move.b a1,(a0)' ($1089) is possible */ /* on ST (fix Blood Money on Superior 65) */ +/* 2010/04/05 [NP] On ST, d8(An,Xn) takes 2 cycles more (which can generate pairing). */ +/* Use BusCyclePenalty to properly handle the 2/4 cycles added in that case when */ +/* addressing mode is Ad8r or PC8r (ULM Demo Menu, Anomaly Demo Intro, DHS */ +/* Sommarhack 2010) (see m68000.h) */ const char GenCpu_fileid[] = "Hatari gencpu.c : " __DATE__ " " __TIME__; @@ -263,7 +267,8 @@ static void sync_m68k_pc (void) /* getv == 1: fetch data; getv != 0: check for odd address. If movem != 0, * the calling routine handles Apdi and Aipi modes. * gb-- movem == 2 means the same thing but for a MOVE16 instruction */ -static void genamode (amodes mode, char *reg, wordsizes size, char *name, int getv, int movem) +static void genamode (amodes mode, const char *reg, wordsizes size, + const char *name, int getv, int movem) { start_brace (); switch (mode) { @@ -344,6 +349,7 @@ static void genamode (amodes mode, char } else { printf ("\tuaecptr %sa = get_disp_ea_000(m68k_areg(regs, %s), %s);\n", name, reg, gen_nextiword ()); } + printf ("\tBusCyclePenalty += 2;\n"); break; case PC16: @@ -365,6 +371,7 @@ static void genamode (amodes mode, char printf ("\tuaecptr tmppc = m68k_getpc() + %d;\n", m68k_pc_offset); printf ("\tuaecptr %sa = get_disp_ea_000(tmppc, %s);\n", name, gen_nextiword ()); } + printf ("\tBusCyclePenalty += 2;\n"); break; case absw: @@ -422,7 +429,7 @@ static void genamode (amodes mode, char printf ("\t\tlast_fault_for_exception_3 = %sa;\n", name); printf ("\t\tlast_op_for_exception_3 = opcode;\n"); printf ("\t\tlast_addr_for_exception_3 = m68k_getpc() + %d;\n", m68k_pc_offset); - printf ("\t\tException(3, 0, M68000_EXCEPTION_SRC_CPU);\n"); + printf ("\t\tException(3, 0, M68000_EXC_SRC_CPU);\n"); printf ("\t\tgoto %s;\n", endlabelstr); printf ("\t}\n"); need_endlabel = 1; @@ -472,7 +479,8 @@ static void genamode (amodes mode, char } } -static void genastore (char *from, amodes mode, char *reg, wordsizes size, char *to) +static void genastore (const char *from, amodes mode, const char *reg, + wordsizes size, const char *to) { switch (mode) { case Dreg: @@ -654,7 +662,8 @@ typedef enum } flagtypes; -static void genflags_normal (flagtypes type, wordsizes size, char *value, char *src, char *dst) +static void genflags_normal (flagtypes type, wordsizes size, const char *value, + const char *src, const char *dst) { char vstr[100], sstr[100], dstr[100]; char usstr[100], udstr[100]; @@ -795,7 +804,8 @@ static void genflags_normal (flagtypes t } } -static void genflags (flagtypes type, wordsizes size, char *value, char *src, char *dst) +static void genflags (flagtypes type, wordsizes size, const char *value, + const char *src, const char *dst) { /* Temporarily deleted 68k/ARM flag optimizations. I'd prefer to have them in the appropriate m68k.h files and use just one copy of this @@ -937,14 +947,14 @@ static void gen_opcode (unsigned long in /* fall through */ case 2: /* priviledged */ - printf ("if (!regs.s) { Exception(8,0,M68000_EXCEPTION_SRC_CPU); goto %s; }\n", endlabelstr); + printf ("if (!regs.s) { Exception(8,0,M68000_EXC_SRC_CPU); goto %s; }\n", endlabelstr); need_endlabel = 1; start_brace (); break; case 3: /* privileged if size == word */ if (curi->size == sz_byte) break; - printf ("if (!regs.s) { Exception(8,0,M68000_EXCEPTION_SRC_CPU); goto %s; }\n", endlabelstr); + printf ("if (!regs.s) { Exception(8,0,M68000_EXC_SRC_CPU); goto %s; }\n", endlabelstr); need_endlabel = 1; start_brace (); break; @@ -1018,8 +1028,6 @@ static void gen_opcode (unsigned long in insn_n_cycles += 2; else insn_n_cycles += 4; - if( (curi->smode==Ad8r) || (curi->smode==PC8r) ) /* [NP] on 68000 ST, d8(An,Xn) takes 2 cycles more */ - insn_n_cycles += 2; break; case i_SUBX: genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); @@ -1082,8 +1090,6 @@ static void gen_opcode (unsigned long in insn_n_cycles += 2; else insn_n_cycles += 4; - if( (curi->smode==Ad8r) || (curi->smode==PC8r) ) /* [NP] on 68000 ST, d8(An,Xn) takes 2 cycles more */ - insn_n_cycles += 2; break; case i_ADDX: genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); @@ -1368,7 +1374,7 @@ static void gen_opcode (unsigned long in case i_TRAP: genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); sync_m68k_pc (); - printf ("\tException(src+32,0,M68000_EXCEPTION_SRC_CPU);\n"); + printf ("\tException(src+32,0,M68000_EXC_SRC_CPU);\n"); m68k_pc_offset = 0; break; case i_MVR2USP: @@ -1415,7 +1421,7 @@ static void gen_opcode (unsigned long in printf ("\telse if ((format & 0xF000) == 0x9000) { m68k_areg(regs, 7) += 12; break; }\n"); printf ("\telse if ((format & 0xF000) == 0xa000) { m68k_areg(regs, 7) += 24; break; }\n"); printf ("\telse if ((format & 0xF000) == 0xb000) { m68k_areg(regs, 7) += 84; break; }\n"); - printf ("\telse { Exception(14,0,M68000_EXCEPTION_SRC_CPU); goto %s; }\n", endlabelstr); + printf ("\telse { Exception(14,0,M68000_EXC_SRC_CPU); goto %s; }\n", endlabelstr); printf ("\tregs.sr = newsr; MakeFromSR();\n}\n"); pop_braces (old_brace_level); printf ("\tregs.sr = newsr; MakeFromSR();\n"); @@ -1458,7 +1464,7 @@ static void gen_opcode (unsigned long in break; case i_TRAPV: sync_m68k_pc (); - printf ("\tif (GET_VFLG) { Exception(7,m68k_getpc(),M68000_EXCEPTION_SRC_CPU); goto %s; }\n", endlabelstr); + printf ("\tif (GET_VFLG) { Exception(7,m68k_getpc(),M68000_EXC_SRC_CPU); goto %s; }\n", endlabelstr); need_endlabel = 1; break; case i_RTR: @@ -1474,6 +1480,15 @@ static void gen_opcode (unsigned long in break; case i_JSR: genamode (curi->smode, "srcreg", curi->size, "src", 0, 0); + printf ("\tuaecptr oldpc = m68k_getpc () + %d;\n", m68k_pc_offset); + if (using_exception_3) { + printf ("\tif (srca & 1) {\n"); + printf ("\t\tlast_addr_for_exception_3 = oldpc;\n"); + printf ("\t\tlast_fault_for_exception_3 = srca;\n"); + printf ("\t\tlast_op_for_exception_3 = opcode; Exception(3,0,M68000_EXC_SRC_CPU); goto %s;\n", endlabelstr); + printf ("\t}\n"); + need_endlabel = 1; + } printf ("\tm68k_do_jsr(m68k_getpc() + %d, srca);\n", m68k_pc_offset); fill_prefetch_0 (); m68k_pc_offset = 0; @@ -1490,6 +1505,14 @@ static void gen_opcode (unsigned long in break; case i_JMP: genamode (curi->smode, "srcreg", curi->size, "src", 0, 0); + if (using_exception_3) { + printf ("\tif (srca & 1) {\n"); + printf ("\t\tlast_addr_for_exception_3 = m68k_getpc() + 6;\n"); + printf ("\t\tlast_fault_for_exception_3 = srca;\n"); + printf ("\t\tlast_op_for_exception_3 = opcode; Exception(3,0,M68000_EXC_SRC_CPU); goto %s;\n", endlabelstr); + printf ("\t}\n"); + need_endlabel = 1; + } printf ("\tm68k_setpc(srca);\n"); fill_prefetch_0 (); m68k_pc_offset = 0; @@ -1509,9 +1532,9 @@ static void gen_opcode (unsigned long in printf ("\tuae_s32 s = (uae_s32)src + 2;\n"); if (using_exception_3) { printf ("\tif (src & 1) {\n"); - printf ("\tlast_addr_for_exception_3 = m68k_getpc() + 2;\n"); // [NP] FIXME should be +4, not +2 (same as DBcc) ? + printf ("\t\tlast_addr_for_exception_3 = m68k_getpc() + 2;\n"); // [NP] FIXME should be +4, not +2 (same as DBcc) ? printf ("\t\tlast_fault_for_exception_3 = m68k_getpc() + s;\n"); - printf ("\t\tlast_op_for_exception_3 = opcode; Exception(3,0,M68000_EXCEPTION_SRC_CPU); goto %s;\n", endlabelstr); + printf ("\t\tlast_op_for_exception_3 = opcode; Exception(3,0,M68000_EXC_SRC_CPU); goto %s;\n", endlabelstr); printf ("\t}\n"); need_endlabel = 1; } @@ -1527,7 +1550,7 @@ static void gen_opcode (unsigned long in printf ("\tif (!cctrue(%d)) goto %s;\n", curi->cc, endlabelstr); printf ("\t\tlast_addr_for_exception_3 = m68k_getpc() + 2;\n"); printf ("\t\tlast_fault_for_exception_3 = m68k_getpc() + 1;\n"); - printf ("\t\tlast_op_for_exception_3 = opcode; Exception(3,0,M68000_EXCEPTION_SRC_CPU); goto %s;\n", endlabelstr); + printf ("\t\tlast_op_for_exception_3 = opcode; Exception(3,0,M68000_EXC_SRC_CPU); goto %s;\n", endlabelstr); need_endlabel = 1; } else { if (next_cpu_level < 1) @@ -1540,7 +1563,7 @@ static void gen_opcode (unsigned long in printf ("\tif (src & 1) {\n"); printf ("\t\tlast_addr_for_exception_3 = m68k_getpc() + 2;\n"); // [NP] FIXME should be +4, not +2 (same as DBcc) ? printf ("\t\tlast_fault_for_exception_3 = m68k_getpc() + 2 + (uae_s32)src;\n"); - printf ("\t\tlast_op_for_exception_3 = opcode; Exception(3,0,M68000_EXCEPTION_SRC_CPU); goto %s;\n", endlabelstr); + printf ("\t\tlast_op_for_exception_3 = opcode; Exception(3,0,M68000_EXC_SRC_CPU); goto %s;\n", endlabelstr); printf ("\t}\n"); need_endlabel = 1; } @@ -1592,7 +1615,7 @@ static void gen_opcode (unsigned long in printf ("\t\t\tif (offs & 1) {\n"); printf ("\t\t\tlast_addr_for_exception_3 = m68k_getpc() + 2 + 2;\n"); // [NP] last_addr is pc+4, not pc+2 printf ("\t\t\tlast_fault_for_exception_3 = m68k_getpc() + 2 + (uae_s32)offs + 2;\n"); - printf ("\t\t\tlast_op_for_exception_3 = opcode; Exception(3,0,M68000_EXCEPTION_SRC_CPU); goto %s;\n", endlabelstr); + printf ("\t\t\tlast_op_for_exception_3 = opcode; Exception(3,0,M68000_EXC_SRC_CPU); goto %s;\n", endlabelstr); printf ("\t\t}\n"); need_endlabel = 1; } @@ -1629,7 +1652,7 @@ static void gen_opcode (unsigned long in sync_m68k_pc (); /* Clear V flag when dividing by zero - Alcatraz Odyssey demo depends * on this (actually, it's doing a DIVS). */ - printf ("\tif (src == 0) { SET_VFLG (0); Exception (5, oldpc,M68000_EXCEPTION_SRC_CPU); goto %s; } else {\n", endlabelstr); + printf ("\tif (src == 0) { SET_VFLG (0); Exception (5, oldpc,M68000_EXC_SRC_CPU); goto %s; } else {\n", endlabelstr); printf ("\tuae_u32 newv = (uae_u32)dst / (uae_u32)(uae_u16)src;\n"); printf ("\tuae_u32 rem = (uae_u32)dst %% (uae_u32)(uae_u16)src;\n"); /* The N flag appears to be set each time there is an overflow. @@ -1650,7 +1673,7 @@ static void gen_opcode (unsigned long in genamode (curi->smode, "srcreg", sz_word, "src", 1, 0); genamode (curi->dmode, "dstreg", sz_long, "dst", 1, 0); sync_m68k_pc (); - printf ("\tif (src == 0) { SET_VFLG (0); Exception(5,oldpc,M68000_EXCEPTION_SRC_CPU); goto %s; } else {\n", endlabelstr); + printf ("\tif (src == 0) { SET_VFLG (0); Exception(5,oldpc,M68000_EXC_SRC_CPU); goto %s; } else {\n", endlabelstr); printf ("\tuae_s32 newv = (uae_s32)dst / (uae_s32)(uae_s16)src;\n"); printf ("\tuae_u16 rem = (uae_s32)dst %% (uae_s32)(uae_s16)src;\n"); printf ("\tif ((newv & 0xffff8000) != 0 && (newv & 0xffff8000) != 0xffff8000) { SET_VFLG (1); SET_NFLG (1); SET_CFLG (0); } else\n\t{\n"); @@ -1696,8 +1719,8 @@ static void gen_opcode (unsigned long in genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0); sync_m68k_pc (); - printf ("\tif ((uae_s32)dst < 0) { SET_NFLG (1); Exception(6,oldpc,M68000_EXCEPTION_SRC_CPU); goto %s; }\n", endlabelstr); - printf ("\telse if (dst > src) { SET_NFLG (0); Exception(6,oldpc,M68000_EXCEPTION_SRC_CPU); goto %s; }\n", endlabelstr); + printf ("\tif ((uae_s32)dst < 0) { SET_NFLG (1); Exception(6,oldpc,M68000_EXC_SRC_CPU); goto %s; }\n", endlabelstr); + printf ("\telse if (dst > src) { SET_NFLG (0); Exception(6,oldpc,M68000_EXC_SRC_CPU); goto %s; }\n", endlabelstr); need_endlabel = 1; insn_n_cycles += 6; break; @@ -1725,7 +1748,7 @@ static void gen_opcode (unsigned long in printf ("\tSET_ZFLG (upper == reg || lower == reg);\n"); printf ("\tSET_CFLG (lower <= upper ? reg < lower || reg > upper : reg > upper || reg < lower);\n"); sync_m68k_pc (); - printf ("\tif ((extra & 0x800) && GET_CFLG) { Exception(6,oldpc,M68000_EXCEPTION_SRC_CPU); goto %s; }\n}\n", endlabelstr); + printf ("\tif ((extra & 0x800) && GET_CFLG) { Exception(6,oldpc,M68000_EXC_SRC_CPU); goto %s; }\n}\n", endlabelstr); need_endlabel = 1; break; @@ -2261,7 +2284,7 @@ static void gen_opcode (unsigned long in case i_TRAPcc: if (curi->smode != am_unknown && curi->smode != am_illg) genamode (curi->smode, "srcreg", curi->size, "dummy", 1, 0); - printf ("\tif (cctrue(%d)) { Exception(7,m68k_getpc(),M68000_EXCEPTION_SRC_CPU); goto %s; }\n", curi->cc, endlabelstr); + printf ("\tif (cctrue(%d)) { Exception(7,m68k_getpc(),M68000_EXC_SRC_CPU); goto %s; }\n", curi->cc, endlabelstr); need_endlabel = 1; break; case i_DIVL: