--- BasiliskII/src/uae_cpu/readcpu.cpp 2001/03/19 13:11:40 1.3 +++ BasiliskII/src/uae_cpu/readcpu.cpp 2007/06/29 16:32:05 1.10 @@ -139,6 +139,9 @@ struct mnemolookup lookuptab[] = { { i_CPUSHA, "CPUSHA" }, { i_MOVE16, "MOVE16" }, + { i_EMULOP_RETURN, "EMULOP_RETURN" }, + { i_EMULOP, "EMULOP" }, + { i_MMUOP, "MMUOP" }, { i_ILLG, "" }, }; @@ -195,16 +198,34 @@ static void build_insn (int insn) int variants; struct instr_def id; const char *opcstr; - int i; + int i, n; int flaglive = 0, flagdead = 0; + int cflow = 0; id = defs68k[insn]; + // Control flow information + cflow = id.cflow; + + // Mask of flags set/used + unsigned char flags_set(0), flags_used(0); + + for (i = 0, n = 4; i < 5; i++, n--) { + switch (id.flaginfo[i].flagset) { + case fa_unset: case fa_isjmp: break; + default: flags_set |= (1 << n); + } + + switch (id.flaginfo[i].flaguse) { + case fu_unused: case fu_isjmp: break; + default: flags_used |= (1 << n); + } + } + for (i = 0; i < 5; i++) { switch (id.flaginfo[i].flagset){ case fa_unset: break; - case fa_isjmp: break; case fa_zero: flagdead |= 1 << i; break; case fa_one: flagdead |= 1 << i; break; case fa_dontcare: flagdead |= 1 << i; break; @@ -217,8 +238,6 @@ static void build_insn (int insn) for (i = 0; i < 5; i++) { switch (id.flaginfo[i].flaguse) { case fu_unused: break; - case fu_isjmp: flaglive |= 1 << i; break; - case fu_maybecc: flaglive |= 1 << i; break; case fu_unknown: flaglive = -1; goto out2; case fu_used: flaglive |= 1 << i; break; } @@ -236,7 +255,7 @@ static void build_insn (int insn) int pos = 0; int mnp = 0; int bitno = 0; - char mnemonic[10]; + char mnemonic[64]; wordsizes sz = sz_long; int srcgather = 0, dstgather = 0; @@ -273,6 +292,8 @@ static void build_insn (int insn) continue; if (bitcnt[bitI] && (bitval[bitI] == 0x00 || bitval[bitI] == 0xff)) continue; + if (bitcnt[bitE] && (bitval[bitE] == 0x00)) + continue; /* bitI and bitC get copied to biti and bitc */ if (bitcnt[bitI]) { @@ -311,6 +332,11 @@ static void build_insn (int insn) } } mnp++; + if ((unsigned)mnp >= sizeof(mnemonic) - 1) { + mnemonic[sizeof(mnemonic) - 1] = 0; + fprintf(stderr, "Instruction %s overflow\n", mnemonic); + abort(); + } } pos++; } @@ -339,7 +365,6 @@ static void build_insn (int insn) case 'A': srcmode = Areg; switch (opcstr[pos++]) { - case 'l': srcmode = absl; break; case 'r': srcreg = bitval[bitr]; srcgather = 1; srcpos = bitpos[bitr]; break; case 'R': srcreg = bitval[bitR]; srcgather = 1; srcpos = bitpos[bitR]; break; default: abort(); @@ -349,6 +374,9 @@ static void build_insn (int insn) case 'P': srcmode = Aipi; pos++; break; } break; + case 'L': + srcmode = absl; + break; case '#': switch (opcstr[pos++]) { case 'z': srcmode = imm; break; @@ -394,8 +422,16 @@ static void build_insn (int insn) srcpos = bitpos[bitK]; } break; - case 'p': srcmode = immi; srcreg = bitval[bitp]; + case 'E': srcmode = immi; srcreg = bitval[bitE]; if (CPU_EMU_SIZE < 5) { // gb-- what is CPU_EMU_SIZE used for ?? + /* 1..255 */ + srcgather = 1; + srctype = 6; + srcpos = bitpos[bitE]; + } + break; + case 'p': srcmode = immi; srcreg = bitval[bitp]; + if (CPU_EMU_SIZE < 5) { /* 0..3 */ srcgather = 1; srctype = 7; @@ -526,20 +562,27 @@ static void build_insn (int insn) case 'R': destreg = bitval[bitR]; dstgather = 1; dstpos = bitpos[bitR]; break; default: abort(); } + if (dstpos < 0 || dstpos >= 32) + abort(); break; case 'A': destmode = Areg; switch (opcstr[pos++]) { - case 'l': destmode = absl; break; case 'r': destreg = bitval[bitr]; dstgather = 1; dstpos = bitpos[bitr]; break; case 'R': destreg = bitval[bitR]; dstgather = 1; dstpos = bitpos[bitR]; break; + case 'x': destreg = 0; dstgather = 0; dstpos = 0; break; default: abort(); } + if (dstpos < 0 || dstpos >= 32) + abort(); switch (opcstr[pos]) { case 'p': destmode = Apdi; pos++; break; case 'P': destmode = Aipi; pos++; break; } break; + case 'L': + destmode = absl; + break; case '#': switch (opcstr[pos++]) { case 'z': destmode = imm; break; @@ -710,8 +753,44 @@ static void build_insn (int insn) table68k[opc].flaginfo[i].flaguse = id.flaginfo[i].flaguse; } #endif + + // Fix flags used information for Scc, Bcc, TRAPcc, DBcc instructions + if ( table68k[opc].mnemo == i_Scc + || table68k[opc].mnemo == i_Bcc + || table68k[opc].mnemo == i_DBcc + || table68k[opc].mnemo == i_TRAPcc + ) { + switch (table68k[opc].cc) { + // CC mask: XNZVC + // 8421 + case 0: flags_used = 0x00; break; /* T */ + case 1: flags_used = 0x00; break; /* F */ + case 2: flags_used = 0x05; break; /* HI */ + case 3: flags_used = 0x05; break; /* LS */ + case 4: flags_used = 0x01; break; /* CC */ + case 5: flags_used = 0x01; break; /* CS */ + case 6: flags_used = 0x04; break; /* NE */ + case 7: flags_used = 0x04; break; /* EQ */ + case 8: flags_used = 0x02; break; /* VC */ + case 9: flags_used = 0x02; break; /* VS */ + case 10:flags_used = 0x08; break; /* PL */ + case 11:flags_used = 0x08; break; /* MI */ + case 12:flags_used = 0x0A; break; /* GE */ + case 13:flags_used = 0x0A; break; /* LT */ + case 14:flags_used = 0x0E; break; /* GT */ + case 15:flags_used = 0x0E; break; /* LE */ + } + } + +#if 1 + /* gb-- flagdead and flaglive would not have correct information */ + table68k[opc].flagdead = flags_set; + table68k[opc].flaglive = flags_used; +#else table68k[opc].flagdead = flagdead; table68k[opc].flaglive = flaglive; +#endif + table68k[opc].cflow = cflow; nomatch: /* FOO! */; } @@ -757,6 +836,8 @@ static void handle_merges (long int opco smsk = 7; sbitdst = 8; break; case 5: smsk = 63; sbitdst = 64; break; + case 6: + smsk = 255; sbitdst = 256; break; case 7: smsk = 3; sbitdst = 4; break; default: @@ -827,3 +908,112 @@ int get_no_mismatches (void) { return mismatch; } + +const char *get_instruction_name (unsigned int opcode) +{ + struct instr *ins = &table68k[opcode]; + for (int i = 0; lookuptab[i].name[0]; i++) { + if (ins->mnemo == lookuptab[i].mnemo) + return lookuptab[i].name; + } + abort(); + return NULL; +} + +static char *get_ea_string (amodes mode, wordsizes size) +{ + static char buffer[80]; + + buffer[0] = 0; + switch (mode){ + case Dreg: + strcpy (buffer,"Dn"); + break; + case Areg: + strcpy (buffer,"An"); + break; + case Aind: + strcpy (buffer,"(An)"); + break; + case Aipi: + strcpy (buffer,"(An)+"); + break; + case Apdi: + strcpy (buffer,"-(An)"); + break; + case Ad16: + strcpy (buffer,"(d16,An)"); + break; + case Ad8r: + strcpy (buffer,"(d8,An,Xn)"); + break; + case PC16: + strcpy (buffer,"(d16,PC)"); + break; + case PC8r: + strcpy (buffer,"(d8,PC,Xn)"); + break; + case absw: + strcpy (buffer,"(xxx).W"); + break; + case absl: + strcpy (buffer,"(xxx).L"); + break; + case imm: + switch (size){ + case sz_byte: + strcpy (buffer,"#.B"); + break; + case sz_word: + strcpy (buffer,"#.W"); + break; + case sz_long: + strcpy (buffer,"#.L"); + break; + default: + break; + } + break; + case imm0: + strcpy (buffer,"#.B"); + break; + case imm1: + strcpy (buffer,"#.W"); + break; + case imm2: + strcpy (buffer,"#.L"); + break; + case immi: + strcpy (buffer,"#"); + break; + + default: + break; + } + return buffer; +} + +const char *get_instruction_string (unsigned int opcode) +{ + static char out[100]; + struct instr *ins; + + strcpy (out, get_instruction_name (opcode)); + + ins = &table68k[opcode]; + if (ins->size == sz_byte) + strcat (out,".B"); + if (ins->size == sz_word) + strcat (out,".W"); + if (ins->size == sz_long) + strcat (out,".L"); + strcat (out," "); + if (ins->suse) + strcat (out, get_ea_string (ins->smode, ins->size)); + if (ins->duse) { + if (ins->suse) + strcat (out,","); + strcat (out, get_ea_string (ins->dmode, ins->size)); + } + return out; +}