--- hatari/src/uae-cpu/gencpu.c 2019/04/01 07:09:16 1.1.1.1 +++ hatari/src/uae-cpu/gencpu.c 2019/04/01 07:09:28 1.1.1.2 @@ -1,5 +1,5 @@ /* - * UAE - The Un*x Amiga Emulator + * UAE - The Un*x Amiga Emulator - CPU core * * MC68000 emulation generator * @@ -16,15 +16,13 @@ * The source for the insn timings is Markt & Technik's Amiga Magazin 8/1992. * * Copyright 1995, 1996, 1997, 1998, 1999, 2000 Bernd Schmidt + * + * Adaptation to Hatari and better cpu timings by Thomas Huth + * */ #include -/* -#include "sysconfig.h" -#include "config.h" -#include "options.h" -*/ #include "sysdeps.h" #include "readcpu.h" @@ -37,6 +35,9 @@ static int using_prefetch; static int using_exception_3; static int cpu_level; +char exactCpuCycles[256]; /* Space to store return string for exact cpu cycles */ + + /* For the current opcode, the next lower level that will have different code. * Initialized to -1 for each opcode. If it remains unchanged, indicates we * are done with that opcode. */ @@ -230,20 +231,10 @@ static void genamode (amodes mode, char if (getv == 1) switch (size) { case sz_byte: -#if defined(AMIGA) && !defined(WARPUP) - /* sam: I don't know why gcc.2.7.2.1 produces a code worse */ - /* if it is not done like that: */ - printf ("\tuae_s8 %s = ((uae_u8*)&m68k_dreg(regs, %s))[3];\n", name, reg); -#else printf ("\tuae_s8 %s = m68k_dreg(regs, %s);\n", name, reg); -#endif break; case sz_word: -#if defined(AMIGA) && !defined(WARPUP) - printf ("\tuae_s16 %s = ((uae_s16*)&m68k_dreg(regs, %s))[1];\n", name, reg); -#else printf ("\tuae_s16 %s = m68k_dreg(regs, %s);\n", name, reg); -#endif break; case sz_long: printf ("\tuae_s32 %s = m68k_dreg(regs, %s);\n", name, reg); @@ -510,6 +501,7 @@ static void genastore (char *from, amode } } + static void genmovemel (uae_u16 opcode) { char getcode[100]; @@ -524,14 +516,37 @@ static void genmovemel (uae_u16 opcode) printf ("\tuae_u16 mask = %s;\n", gen_nextiword ()); printf ("\tunsigned int dmask = mask & 0xff, amask = (mask >> 8) & 0xff;\n"); genamode (table68k[opcode].dmode, "dstreg", table68k[opcode].size, "src", 2, 1); + printf ("\tretcycles = 0;\n"); start_brace (); - printf ("\twhile (dmask) { m68k_dreg(regs, movem_index1[dmask]) = %s; srca += %d; dmask = movem_next[dmask]; }\n", + printf ("\twhile (dmask) { m68k_dreg(regs, movem_index1[dmask]) = %s;" + " srca += %d; dmask = movem_next[dmask]; retcycles+=1; }\n", getcode, size); - printf ("\twhile (amask) { m68k_areg(regs, movem_index1[amask]) = %s; srca += %d; amask = movem_next[amask]; }\n", + printf ("\twhile (amask) { m68k_areg(regs, movem_index1[amask]) = %s;" + " srca += %d; amask = movem_next[amask]; retcycles+=1; }\n", getcode, size); if (table68k[opcode].dmode == Aipi) printf ("\tm68k_areg(regs, dstreg) = srca;\n"); + + /* Better cycles - experimental! (Thothy) */ + switch(table68k[opcode].dmode) + { + case Aind: insn_n_cycles=12; break; + case Aipi: insn_n_cycles=12; break; + case Ad16: insn_n_cycles=16; break; + case Ad8r: insn_n_cycles=18; break; + case absw: insn_n_cycles=16; break; + case absl: insn_n_cycles=20; break; + case PC16: insn_n_cycles=16; break; + case PC8r: insn_n_cycles=18; break; + } + /*I had some very stranges crashes when I included following code, so better leave it commented out* */ +#if 1 + if(table68k[opcode].size==sz_long) + sprintf(exactCpuCycles," return (%i+retcycles*8);", insn_n_cycles); + else + sprintf(exactCpuCycles," return (%i+retcycles*4);", insn_n_cycles); +#endif } static void genmovemle (uae_u16 opcode) @@ -549,23 +564,47 @@ static void genmovemle (uae_u16 opcode) if (using_prefetch) sync_m68k_pc (); + printf ("\tretcycles = 0;\n"); start_brace (); if (table68k[opcode].dmode == Apdi) { - printf ("\tuae_u16 amask = mask & 0xff, dmask = (mask >> 8) & 0xff;\n"); - printf ("\twhile (amask) { srca -= %d; %s m68k_areg(regs, movem_index2[amask])); amask = movem_next[amask]; }\n", - size, putcode); - printf ("\twhile (dmask) { srca -= %d; %s m68k_dreg(regs, movem_index2[dmask])); dmask = movem_next[dmask]; }\n", - size, putcode); - printf ("\tm68k_areg(regs, dstreg) = srca;\n"); + printf ("\tuae_u16 amask = mask & 0xff, dmask = (mask >> 8) & 0xff;\n"); + printf ("\twhile (amask) { srca -= %d; %s m68k_areg(regs, movem_index2[amask]));" + " amask = movem_next[amask]; retcycles+=1; }\n", + size, putcode); + printf ("\twhile (dmask) { srca -= %d; %s m68k_dreg(regs, movem_index2[dmask]));" + " dmask = movem_next[dmask]; retcycles+=1; }\n", + size, putcode); + printf ("\tm68k_areg(regs, dstreg) = srca;\n"); } else { - printf ("\tuae_u16 dmask = mask & 0xff, amask = (mask >> 8) & 0xff;\n"); - printf ("\twhile (dmask) { %s m68k_dreg(regs, movem_index1[dmask])); srca += %d; dmask = movem_next[dmask]; }\n", - putcode, size); - printf ("\twhile (amask) { %s m68k_areg(regs, movem_index1[amask])); srca += %d; amask = movem_next[amask]; }\n", - putcode, size); - } + printf ("\tuae_u16 dmask = mask & 0xff, amask = (mask >> 8) & 0xff;\n"); + printf ("\twhile (dmask) { %s m68k_dreg(regs, movem_index1[dmask])); srca += %d;" + " dmask = movem_next[dmask]; retcycles+=1; }\n", + putcode, size); + printf ("\twhile (amask) { %s m68k_areg(regs, movem_index1[amask])); srca += %d;" + " amask = movem_next[amask]; retcycles+=1; }\n", + putcode, size); + } + + /* Better cycles - experimental! (Thothy) */ + switch(table68k[opcode].dmode) + { + case Aind: insn_n_cycles=8; break; + case Apdi: insn_n_cycles=8; break; + case Ad16: insn_n_cycles=12; break; + case Ad8r: insn_n_cycles=14; break; + case absw: insn_n_cycles=12; break; + case absl: insn_n_cycles=16; break; + } + /*I had some very stranges crashes when I included following code, so better leave it commented out* */ +#if 1 + if(table68k[opcode].size==sz_long) + sprintf(exactCpuCycles," return (%i+retcycles*8);", insn_n_cycles); + else + sprintf(exactCpuCycles," return (%i+retcycles*4);", insn_n_cycles); +#endif } + static void duplicate_carry (void) { printf ("\tCOPY_CARRY;\n"); @@ -830,16 +869,21 @@ static int source_is_imm1_8 (struct inst return i->stype == 3; } + + static void gen_opcode (unsigned long int opcode) { +#if 0 + char *amodenames[] = { "Dreg", "Areg", "Aind", "Aipi", "Apdi", "Ad16", "Ad8r", + "absw", "absl", "PC16", "PC8r", "imm", "imm0", "imm1", "imm2", "immi", "am_unknown", "am_illg"}; +#endif + struct instr *curi = table68k + opcode; insn_n_cycles = 4; start_brace (); -#if 0 - printf ("uae_u8 *m68k_pc = regs.pc_p;\n"); -#endif m68k_pc_offset = 2; + switch (curi->plev) { case 0: /* not privileged */ break; @@ -863,41 +907,64 @@ static void gen_opcode (unsigned long in start_brace (); break; } + + /* Build the opcodes: */ switch (curi->mnemo) { case i_OR: case i_AND: case i_EOR: - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); - genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0); - printf ("\tsrc %c= dst;\n", curi->mnemo == i_OR ? '|' : curi->mnemo == i_AND ? '&' : '^'); - genflags (flag_logical, curi->size, "src", "", ""); - genastore ("src", curi->dmode, "dstreg", curi->size, "dst"); - break; + genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0); + printf ("\tsrc %c= dst;\n", curi->mnemo == i_OR ? '|' : curi->mnemo == i_AND ? '&' : '^'); + genflags (flag_logical, curi->size, "src", "", ""); + genastore ("src", curi->dmode, "dstreg", curi->size, "dst"); + if(curi->size==sz_long && curi->dmode==Dreg) + { + insn_n_cycles += 2; + if(curi->smode==Dreg || curi->smode==Areg || (curi->smode>=imm && curi->smode<=immi)) + insn_n_cycles += 2; + } +#if 0 + /* Output the CPU cycles: */ + fprintf(stderr,"MOVE, size %i: ",curi->size); + fprintf(stderr," %s ->",amodenames[curi->smode]); + fprintf(stderr," %s ",amodenames[curi->dmode]); + fprintf(stderr," Cycles: %i\n",insn_n_cycles); +#endif + break; case i_ORSR: case i_EORSR: - printf ("\tMakeSR();\n"); - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); - if (curi->size == sz_byte) { - printf ("\tsrc &= 0xFF;\n"); - } - printf ("\tregs.sr %c= src;\n", curi->mnemo == i_EORSR ? '^' : '|'); - printf ("\tMakeFromSR();\n"); - break; + printf ("\tMakeSR();\n"); + genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); + if (curi->size == sz_byte) { + printf ("\tsrc &= 0xFF;\n"); + } + printf ("\tregs.sr %c= src;\n", curi->mnemo == i_EORSR ? '^' : '|'); + printf ("\tMakeFromSR();\n"); + insn_n_cycles = 20; + break; case i_ANDSR: - printf ("\tMakeSR();\n"); - genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); - if (curi->size == sz_byte) { - printf ("\tsrc |= 0xFF00;\n"); - } - printf ("\tregs.sr &= src;\n"); - printf ("\tMakeFromSR();\n"); - break; + printf ("\tMakeSR();\n"); + genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); + if (curi->size == sz_byte) { + printf ("\tsrc |= 0xFF00;\n"); + } + printf ("\tregs.sr &= src;\n"); + printf ("\tMakeFromSR();\n"); + insn_n_cycles = 20; + break; case i_SUB: genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0); start_brace (); genflags (flag_sub, curi->size, "newv", "src", "dst"); genastore ("newv", curi->dmode, "dstreg", curi->size, "dst"); + if(curi->size==sz_long && curi->dmode==Dreg) + { + insn_n_cycles += 2; + if(curi->smode==Dreg || curi->smode==Areg || (curi->smode>=imm && curi->smode<=immi)) + insn_n_cycles += 2; + } break; case i_SUBA: genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); @@ -905,6 +972,10 @@ static void gen_opcode (unsigned long in start_brace (); printf ("\tuae_u32 newv = dst - src;\n"); genastore ("newv", curi->dmode, "dstreg", sz_long, "dst"); + if(curi->size==sz_long && curi->smode!=Dreg && curi->smode!=Areg && !(curi->smode>=imm && curi->smode<=immi)) + insn_n_cycles += 2; + else + insn_n_cycles += 4; break; case i_SUBX: genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); @@ -914,6 +985,15 @@ static void gen_opcode (unsigned long in genflags (flag_subx, curi->size, "newv", "src", "dst"); genflags (flag_zn, curi->size, "newv", "", ""); genastore ("newv", curi->dmode, "dstreg", curi->size, "dst"); + if(curi->smode==Dreg && curi->size==sz_long) + insn_n_cycles=8; + if(curi->smode==Apdi) + { + if(curi->size==sz_long) + insn_n_cycles=30; + else + insn_n_cycles=18; + } break; case i_SBCD: /* Let's hope this works... */ @@ -933,6 +1013,8 @@ static void gen_opcode (unsigned long in genflags (flag_zn, curi->size, "newv", "", ""); genflags (flag_sv, curi->size, "newv", "src", "dst"); genastore ("newv", curi->dmode, "dstreg", curi->size, "dst"); + if(curi->smode==Dreg) insn_n_cycles=6; + if(curi->smode==Apdi) insn_n_cycles=18; break; case i_ADD: genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); @@ -940,6 +1022,12 @@ static void gen_opcode (unsigned long in start_brace (); genflags (flag_add, curi->size, "newv", "src", "dst"); genastore ("newv", curi->dmode, "dstreg", curi->size, "dst"); + if(curi->size==sz_long && curi->dmode==Dreg) + { + insn_n_cycles += 2; + if(curi->smode==Dreg || curi->smode==Areg || (curi->smode>=imm && curi->smode<=immi)) + insn_n_cycles += 2; + } break; case i_ADDA: genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); @@ -947,6 +1035,10 @@ static void gen_opcode (unsigned long in start_brace (); printf ("\tuae_u32 newv = dst + src;\n"); genastore ("newv", curi->dmode, "dstreg", sz_long, "dst"); + if(curi->size==sz_long && curi->smode!=Dreg && curi->smode!=Areg && !(curi->smode>=imm && curi->smode<=immi)) + insn_n_cycles += 2; + else + insn_n_cycles += 4; break; case i_ADDX: genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); @@ -956,6 +1048,15 @@ static void gen_opcode (unsigned long in genflags (flag_addx, curi->size, "newv", "src", "dst"); genflags (flag_zn, curi->size, "newv", "", ""); genastore ("newv", curi->dmode, "dstreg", curi->size, "dst"); + if(curi->smode==Dreg && curi->size==sz_long) + insn_n_cycles=8; + if(curi->smode==Apdi) + { + if(curi->size==sz_long) + insn_n_cycles=30; + else + insn_n_cycles=18; + } break; case i_ABCD: genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); @@ -974,12 +1075,15 @@ static void gen_opcode (unsigned long in genflags (flag_zn, curi->size, "newv", "", ""); genflags (flag_sv, curi->size, "newv", "src", "dst"); genastore ("newv", curi->dmode, "dstreg", curi->size, "dst"); + if(curi->smode==Dreg) insn_n_cycles=6; + if(curi->smode==Apdi) insn_n_cycles=18; break; case i_NEG: genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); start_brace (); genflags (flag_sub, curi->size, "dst", "src", "0"); genastore ("dst", curi->smode, "srcreg", curi->size, "src"); + if(curi->size==sz_long && curi->smode==Dreg) insn_n_cycles += 2; break; case i_NEGX: genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); @@ -988,6 +1092,7 @@ static void gen_opcode (unsigned long in genflags (flag_subx, curi->size, "newv", "src", "0"); genflags (flag_zn, curi->size, "newv", "", ""); genastore ("newv", curi->smode, "srcreg", curi->size, "src"); + if(curi->size==sz_long && curi->smode==Dreg) insn_n_cycles += 2; break; case i_NBCD: genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); @@ -1004,11 +1109,19 @@ static void gen_opcode (unsigned long in printf ("\tif (cflg) newv -= 0x60;\n"); genflags (flag_zn, curi->size, "newv", "", ""); genastore ("newv", curi->smode, "srcreg", curi->size, "src"); + if(curi->smode==Dreg) insn_n_cycles += 2; break; case i_CLR: genamode (curi->smode, "srcreg", curi->size, "src", 2, 0); genflags (flag_logical, curi->size, "0", "", ""); genastore ("0", curi->smode, "srcreg", curi->size, "src"); + if(curi->size==sz_long) + if(curi->smode==Dreg) + insn_n_cycles += 2; + else + insn_n_cycles += 4; + if(curi->smode!=Dreg) + insn_n_cycles += 4; break; case i_NOT: genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); @@ -1016,6 +1129,7 @@ static void gen_opcode (unsigned long in printf ("\tuae_u32 dst = ~src;\n"); genflags (flag_logical, curi->size, "dst", "", ""); genastore ("dst", curi->smode, "srcreg", curi->size, "src"); + if(curi->size==sz_long && curi->smode==Dreg) insn_n_cycles += 2; break; case i_TST: genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); @@ -1029,6 +1143,7 @@ static void gen_opcode (unsigned long in else printf ("\tsrc &= 31;\n"); printf ("\tSET_ZFLG (1 ^ ((dst >> src) & 1));\n"); + if(curi->dmode==Dreg) insn_n_cycles += 2; break; case i_BCHG: genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); @@ -1040,6 +1155,7 @@ static void gen_opcode (unsigned long in printf ("\tdst ^= (1 << src);\n"); printf ("\tSET_ZFLG (((uae_u32)dst & (1 << src)) >> src);\n"); genastore ("dst", curi->dmode, "dstreg", curi->size, "dst"); + if(curi->dmode==Dreg) insn_n_cycles += 4; break; case i_BCLR: genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); @@ -1051,6 +1167,7 @@ static void gen_opcode (unsigned long in printf ("\tSET_ZFLG (1 ^ ((dst >> src) & 1));\n"); printf ("\tdst &= ~(1 << src);\n"); genastore ("dst", curi->dmode, "dstreg", curi->size, "dst"); + if(curi->dmode==Dreg) insn_n_cycles += 6; break; case i_BSET: genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); @@ -1062,6 +1179,7 @@ static void gen_opcode (unsigned long in printf ("\tSET_ZFLG (1 ^ ((dst >> src) & 1));\n"); printf ("\tdst |= (1 << src);\n"); genastore ("dst", curi->dmode, "dstreg", curi->size, "dst"); + if(curi->dmode==Dreg) insn_n_cycles += 4; break; case i_CMPM: case i_CMP: @@ -1069,12 +1187,15 @@ static void gen_opcode (unsigned long in genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0); start_brace (); genflags (flag_cmp, curi->size, "newv", "src", "dst"); + if(curi->size==sz_long && curi->dmode==Dreg) + insn_n_cycles += 2; break; case i_CMPA: genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); genamode (curi->dmode, "dstreg", sz_long, "dst", 1, 0); start_brace (); genflags (flag_cmp, sz_long, "newv", "src", "dst"); + insn_n_cycles += 2; break; /* The next two are coded a little unconventional, but they are doing * weird things... */ @@ -1088,6 +1209,7 @@ static void gen_opcode (unsigned long in printf ("\tput_byte(memp, src >> 24); put_byte(memp + 2, src >> 16);\n"); printf ("\tput_byte(memp + 4, src >> 8); put_byte(memp + 6, src);\n"); } + if(curi->size==sz_long) insn_n_cycles=24; else insn_n_cycles=16; break; case i_MVPMR: printf ("\tuaecptr memp = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)%s;\n", gen_nextiword ()); @@ -1099,6 +1221,7 @@ static void gen_opcode (unsigned long in printf (" + (get_byte(memp + 4) << 8) + get_byte(memp + 6);\n"); } genastore ("val", curi->dmode, "dstreg", curi->size, "dst"); + if(curi->size==sz_long) insn_n_cycles=24; else insn_n_cycles=16; break; case i_MOVE: genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); @@ -1116,15 +1239,16 @@ static void gen_opcode (unsigned long in } genastore ("val", curi->dmode, "dstreg", sz_long, "dst"); break; - case i_MVSR2: + case i_MVSR2: /* Move from SR */ genamode (curi->smode, "srcreg", sz_word, "src", 2, 0); printf ("\tMakeSR();\n"); if (curi->size == sz_byte) genastore ("regs.sr & 0xff", curi->smode, "srcreg", sz_word, "src"); else genastore ("regs.sr", curi->smode, "srcreg", sz_word, "src"); + if (curi->smode==Dreg) insn_n_cycles += 2; else insn_n_cycles += 4; break; - case i_MV2SR: + case i_MV2SR: /* Move to SR */ genamode (curi->smode, "srcreg", sz_word, "src", 1, 0); if (curi->size == sz_byte) printf ("\tMakeSR();\n\tregs.sr &= 0xFF00;\n\tregs.sr |= src & 0xFF;\n"); @@ -1132,6 +1256,7 @@ static void gen_opcode (unsigned long in printf ("\tregs.sr = src;\n"); } printf ("\tMakeFromSR();\n"); + insn_n_cycles += 8; break; case i_SWAP: genamode (curi->smode, "srcreg", sz_long, "src", 1, 0); @@ -1145,6 +1270,7 @@ static void gen_opcode (unsigned long in genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0); genastore ("dst", curi->smode, "srcreg", curi->size, "src"); genastore ("src", curi->dmode, "dstreg", curi->size, "dst"); + insn_n_cycles = 6; break; case i_EXT: genamode (curi->smode, "srcreg", sz_long, "src", 1, 0); @@ -1182,6 +1308,7 @@ static void gen_opcode (unsigned long in break; case i_RESET: printf ("\tcustomreset();\n"); + insn_n_cycles = 132; /* I am not so sure about this!? - Thothy */ break; case i_NOP: break; @@ -1190,6 +1317,7 @@ static void gen_opcode (unsigned long in printf ("\tregs.sr = src;\n"); printf ("\tMakeFromSR();\n"); printf ("\tm68k_setstopped(1);\n"); + insn_n_cycles = 4; break; case i_RTE: if (cpu_level == 0) { @@ -1224,6 +1352,7 @@ static void gen_opcode (unsigned long in } /* PC is set and prefetch filled. */ m68k_pc_offset = 0; + insn_n_cycles = 20; break; case i_RTD: printf ("\tcompiler_flush_jsr_stack();\n"); @@ -1253,6 +1382,7 @@ static void gen_opcode (unsigned long in printf ("\tm68k_do_rts();\n"); fill_prefetch_0 (); m68k_pc_offset = 0; + insn_n_cycles = 16; break; case i_TRAPV: sync_m68k_pc (); @@ -1269,18 +1399,39 @@ static void gen_opcode (unsigned long in fill_prefetch_0 (); printf ("\tMakeFromSR();\n"); m68k_pc_offset = 0; + insn_n_cycles = 20; break; case i_JSR: genamode (curi->smode, "srcreg", curi->size, "src", 0, 0); printf ("\tm68k_do_jsr(m68k_getpc() + %d, srca);\n", m68k_pc_offset); fill_prefetch_0 (); m68k_pc_offset = 0; + switch(curi->smode) + { + case Aind: insn_n_cycles=16; break; + case Ad16: insn_n_cycles=18; break; + case Ad8r: insn_n_cycles=22; break; + case absw: insn_n_cycles=18; break; + case absl: insn_n_cycles=20; break; + case PC16: insn_n_cycles=18; break; + case PC8r: insn_n_cycles=22; break; + } break; case i_JMP: genamode (curi->smode, "srcreg", curi->size, "src", 0, 0); printf ("\tm68k_setpc(srca);\n"); fill_prefetch_0 (); m68k_pc_offset = 0; + switch(curi->smode) + { + case Aind: insn_n_cycles=8; break; + case Ad16: insn_n_cycles=10; break; + case Ad8r: insn_n_cycles=14; break; + case absw: insn_n_cycles=10; break; + case absl: insn_n_cycles=12; break; + case PC16: insn_n_cycles=10; break; + case PC8r: insn_n_cycles=14; break; + } break; case i_BSR: genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); @@ -1296,6 +1447,7 @@ static void gen_opcode (unsigned long in printf ("\tm68k_do_bsr(m68k_getpc() + %d, s);\n", m68k_pc_offset); fill_prefetch_0 (); m68k_pc_offset = 0; + insn_n_cycles = 18; break; case i_Bcc: if (curi->size == sz_long) { @@ -1327,26 +1479,38 @@ static void gen_opcode (unsigned long in printf ("\tm68k_incpc ((uae_s32)src + 2);\n"); #endif fill_prefetch_0 (); - printf ("\treturn 5;\n"); + printf ("\treturn 10;\n"); printf ("didnt_jump:;\n"); need_endlabel = 1; - insn_n_cycles = curi->size == sz_byte ? 8 : 12; + insn_n_cycles = (curi->size == sz_byte) ? 8 : 12; break; case i_LEA: genamode (curi->smode, "srcreg", curi->size, "src", 0, 0); genamode (curi->dmode, "dstreg", curi->size, "dst", 2, 0); genastore ("srca", curi->dmode, "dstreg", curi->size, "dst"); + if(curi->smode==Ad8r || curi->smode==PC8r) + insn_n_cycles += 2; break; case i_PEA: genamode (curi->smode, "srcreg", curi->size, "src", 0, 0); genamode (Apdi, "7", sz_long, "dst", 2, 0); genastore ("srca", Apdi, "7", sz_long, "dst"); + switch(curi->smode) + { + case Aind: insn_n_cycles=12; break; + case Ad16: insn_n_cycles=16; break; + case Ad8r: insn_n_cycles=20; break; + case absw: insn_n_cycles=16; break; + case absl: insn_n_cycles=20; break; + case PC16: insn_n_cycles=16; break; + case PC8r: insn_n_cycles=20; break; + } break; case i_DBcc: genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); genamode (curi->dmode, "dstreg", curi->size, "offs", 1, 0); - printf ("\tif (!cctrue(%d)) {\n", curi->cc); + printf ("\tif (!cctrue(%d)) {\n\t", curi->cc); genastore ("(src-1)", curi->smode, "srcreg", curi->size, "src"); printf ("\t\tif (src) {\n"); @@ -1364,9 +1528,15 @@ static void gen_opcode (unsigned long in printf ("\t\t\tm68k_incpc((uae_s32)offs + 2);\n"); #endif fill_prefetch_0 (); - /* ??? Cycle count is a guess. */ - printf ("\t\treturn 6;\n"); - printf ("\t\t}\n"); + printf ("\t\t\treturn 10;\n"); + printf ("\t\t} else {\n\t\t\t"); + { + int tmp_offset = m68k_pc_offset; + sync_m68k_pc(); /* not so nice to call it here... */ + m68k_pc_offset = tmp_offset; + } + printf ("\t\t\treturn 14;\n"); + printf ("\t\t}\n"); printf ("\t}\n"); insn_n_cycles = 12; need_endlabel = 1; @@ -1376,6 +1546,7 @@ static void gen_opcode (unsigned long in start_brace (); printf ("\tint val = cctrue(%d) ? 0xff : 0;\n", curi->cc); genastore ("val", curi->smode, "srcreg", curi->size, "src"); + if(curi->smode!=Dreg) insn_n_cycles += 4; break; case i_DIVU: printf ("\tuaecptr oldpc = m68k_getpc();\n"); @@ -1441,6 +1612,7 @@ static void gen_opcode (unsigned long in printf ("\tif ((uae_s32)dst < 0) { SET_NFLG (1); Exception(6,oldpc); goto %s; }\n", endlabelstr); printf ("\telse if (dst > src) { SET_NFLG (0); Exception(6,oldpc); goto %s; }\n", endlabelstr); need_endlabel = 1; + insn_n_cycles += 6; break; case i_CHK2: @@ -1481,6 +1653,7 @@ static void gen_opcode (unsigned long in } printf ("\tuae_u32 sign = (%s & val) >> %d;\n", cmask (curi->size), bit_size (curi->size) - 1); printf ("\tcnt &= 63;\n"); + printf ("\tretcycles = cnt;\n"); printf ("\tCLEAR_CZNV;\n"); printf ("\tif (cnt >= %d) {\n", bit_size (curi->size)); printf ("\t\tval = %s & (uae_u32)-sign;\n", bit_mask (curi->size)); @@ -1501,6 +1674,10 @@ static void gen_opcode (unsigned long in printf ("\t}\n"); genflags (flag_logical_noclobber, curi->size, "val", "", ""); genastore ("val", curi->dmode, "dstreg", curi->size, "data"); + if(curi->size==sz_long) + strcpy(exactCpuCycles," return (8+retcycles*2);"); + else + strcpy(exactCpuCycles," return (6+retcycles*2);"); break; case i_ASL: genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0); @@ -1513,6 +1690,7 @@ static void gen_opcode (unsigned long in default: abort (); } printf ("\tcnt &= 63;\n"); + printf ("\tretcycles = cnt;\n"); printf ("\tCLEAR_CZNV;\n"); printf ("\tif (cnt >= %d) {\n", bit_size (curi->size)); printf ("\t\tSET_VFLG (val != 0);\n"); @@ -1537,6 +1715,10 @@ static void gen_opcode (unsigned long in printf ("\t}\n"); genflags (flag_logical_noclobber, curi->size, "val", "", ""); genastore ("val", curi->dmode, "dstreg", curi->size, "data"); + if(curi->size==sz_long) + strcpy(exactCpuCycles," return (8+retcycles*2);"); + else + strcpy(exactCpuCycles," return (6+retcycles*2);"); break; case i_LSR: genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0); @@ -1549,6 +1731,7 @@ static void gen_opcode (unsigned long in default: abort (); } printf ("\tcnt &= 63;\n"); + printf ("\tretcycles = cnt;\n"); printf ("\tCLEAR_CZNV;\n"); printf ("\tif (cnt >= %d) {\n", bit_size (curi->size)); printf ("\t\tSET_CFLG ((cnt == %d) & (val >> %d));\n", @@ -1566,6 +1749,10 @@ static void gen_opcode (unsigned long in printf ("\t}\n"); genflags (flag_logical_noclobber, curi->size, "val", "", ""); genastore ("val", curi->dmode, "dstreg", curi->size, "data"); + if(curi->size==sz_long) + strcpy(exactCpuCycles," return (8+retcycles*2);"); + else + strcpy(exactCpuCycles," return (6+retcycles*2);"); break; case i_LSL: genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0); @@ -1578,6 +1765,7 @@ static void gen_opcode (unsigned long in default: abort (); } printf ("\tcnt &= 63;\n"); + printf ("\tretcycles = cnt;\n"); printf ("\tCLEAR_CZNV;\n"); printf ("\tif (cnt >= %d) {\n", bit_size (curi->size)); printf ("\t\tSET_CFLG (cnt == %d ? val & 1 : 0);\n", @@ -1596,6 +1784,10 @@ static void gen_opcode (unsigned long in printf ("\t}\n"); genflags (flag_logical_noclobber, curi->size, "val", "", ""); genastore ("val", curi->dmode, "dstreg", curi->size, "data"); + if(curi->size==sz_long) + strcpy(exactCpuCycles," return (8+retcycles*2);"); + else + strcpy(exactCpuCycles," return (6+retcycles*2);"); break; case i_ROL: genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0); @@ -1608,6 +1800,7 @@ static void gen_opcode (unsigned long in default: abort (); } printf ("\tcnt &= 63;\n"); + printf ("\tretcycles = cnt;\n"); printf ("\tCLEAR_CZNV;\n"); if (source_is_imm1_8 (curi)) printf ("{"); @@ -1623,6 +1816,10 @@ static void gen_opcode (unsigned long in printf ("}\n"); genflags (flag_logical_noclobber, curi->size, "val", "", ""); genastore ("val", curi->dmode, "dstreg", curi->size, "data"); + if(curi->size==sz_long) + strcpy(exactCpuCycles," return (8+retcycles*2);"); + else + strcpy(exactCpuCycles," return (6+retcycles*2);"); break; case i_ROR: genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0); @@ -1635,6 +1832,7 @@ static void gen_opcode (unsigned long in default: abort (); } printf ("\tcnt &= 63;\n"); + printf ("\tretcycles = cnt;\n"); printf ("\tCLEAR_CZNV;\n"); if (source_is_imm1_8 (curi)) printf ("{"); @@ -1650,6 +1848,10 @@ static void gen_opcode (unsigned long in printf ("\t}\n"); genflags (flag_logical_noclobber, curi->size, "val", "", ""); genastore ("val", curi->dmode, "dstreg", curi->size, "data"); + if(curi->size==sz_long) + strcpy(exactCpuCycles," return (8+retcycles*2);"); + else + strcpy(exactCpuCycles," return (6+retcycles*2);"); break; case i_ROXL: genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0); @@ -1662,6 +1864,7 @@ static void gen_opcode (unsigned long in default: abort (); } printf ("\tcnt &= 63;\n"); + printf ("\tretcycles = cnt;\n"); printf ("\tCLEAR_CZNV;\n"); if (source_is_imm1_8 (curi)) printf ("{"); @@ -1680,6 +1883,10 @@ static void gen_opcode (unsigned long in printf ("\tSET_CFLG (GET_XFLG);\n"); genflags (flag_logical_noclobber, curi->size, "val", "", ""); genastore ("val", curi->dmode, "dstreg", curi->size, "data"); + if(curi->size==sz_long) + strcpy(exactCpuCycles," return (8+retcycles*2);"); + else + strcpy(exactCpuCycles," return (6+retcycles*2);"); break; case i_ROXR: genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0); @@ -1692,6 +1899,7 @@ static void gen_opcode (unsigned long in default: abort (); } printf ("\tcnt &= 63;\n"); + printf ("\tretcycles = cnt;\n"); printf ("\tCLEAR_CZNV;\n"); if (source_is_imm1_8 (curi)) printf ("{"); @@ -1713,6 +1921,10 @@ static void gen_opcode (unsigned long in printf ("\tSET_CFLG (GET_XFLG);\n"); genflags (flag_logical_noclobber, curi->size, "val", "", ""); genastore ("val", curi->dmode, "dstreg", curi->size, "data"); + if(curi->size==sz_long) + strcpy(exactCpuCycles," return (8+retcycles*2);"); + else + strcpy(exactCpuCycles," return (6+retcycles*2);"); break; case i_ASRW: genamode (curi->smode, "srcreg", curi->size, "data", 1, 0); @@ -2094,6 +2306,7 @@ static void gen_opcode (unsigned long in genflags (flag_logical, curi->size, "src", "", ""); printf ("\tsrc |= 0x80;\n"); genastore ("src", curi->smode, "srcreg", curi->size, "src"); + if( curi->smode!=Dreg ) insn_n_cycles += 2; break; case i_FPP: genamode (curi->smode, "srcreg", curi->size, "extra", 1, 0); @@ -2177,12 +2390,6 @@ static void generate_includes (FILE * f) fprintf (f, "#include \"newcpu.h\"\n"); fprintf (f, "#include \"compiler.h\"\n"); fprintf (f, "#include \"cputbl.h\"\n"); -/* - fprintf (f, "#include \"sysconfig.h\"\n"); - fprintf (f, "#include \"config.h\"\n"); - fprintf (f, "#include \"options.h\"\n"); - fprintf (f, "#include \"custom.h\"\n"); -*/ fprintf (f, "#define CPUFUNC(x) x##_ff\n" "#ifdef NOFLAGS\n" "#include \"noflags.h\"\n" @@ -2197,6 +2404,8 @@ static void generate_one_opcode (int rp) uae_u16 smsk, dmsk; long int opcode = opcode_map[rp]; + exactCpuCycles[0] = 0; /* Default: not used */ + if (table68k[opcode].mnemo == i_ILLG || table68k[opcode].clev > cpu_level) return; @@ -2287,10 +2496,17 @@ static void generate_one_opcode (int rp) need_endlabel = 0; endlabelno++; sprintf (endlabelstr, "endlabel%d", endlabelno); + if(table68k[opcode].mnemo==i_ASR || table68k[opcode].mnemo==i_ASL || table68k[opcode].mnemo==i_LSR || table68k[opcode].mnemo==i_LSL + || table68k[opcode].mnemo==i_ROL || table68k[opcode].mnemo==i_ROR || table68k[opcode].mnemo==i_ROXL || table68k[opcode].mnemo==i_ROXR + || table68k[opcode].mnemo==i_MVMEL || table68k[opcode].mnemo==i_MVMLE) + printf("\tunsigned int retcycles;\n"); gen_opcode (opcode); if (need_endlabel) printf ("%s: ;\n", endlabelstr); - printf ("return %d;\n", insn_n_cycles / 2); + if( strlen(exactCpuCycles) > 0 ) + printf("%s\n",exactCpuCycles); + else + printf ("return %d;\n", insn_n_cycles); printf ("}\n"); opcode_next_clev[rp] = next_cpu_level; opcode_last_postfix[rp] = postfix;