using System; using System.Collections.Generic; namespace BizHawk.Emulation.CPUs.M68000 { partial class MC68000 { void BuildOpcodeTable() { // NOTE: Do not change the order of these assigns without testing. There is // some overwriting of less-specific opcodes with more-specific opcodes. // TODO: should really come up with means of only assigning to applicable addressing modes, // instead of this lame overwriting business. Assign("move", MOVE, "00", "Size2_0", "XnAm", "AmXn"); Assign("movea", MOVEA, "00", "Size2_0", "Xn", "001", "AmXn"); Assign("moveq", MOVEQ, "0111", "Xn", "0", "Data8"); Assign("movem", MOVEM0,"010010001", "Size1", "AmXn"); Assign("movem", MOVEM1,"010011001", "Size1", "AmXn"); Assign("lea", LEA, "0100", "Xn", "111", "AmXn"); Assign("clr", CLR, "01000010", "Size2_1", "AmXn"); Assign("ext", EXT, "010010001", "Size1", "000", "Xn"); Assign("pea", PEA, "0100100001", "AmXn"); Assign("andi", ANDI, "00000010", "Size2_1", "AmXn"); Assign("eori", EORI, "00001010", "Size2_1", "AmXn"); Assign("ori", ORI, "00000000", "Size2_1", "AmXn"); Assign("asl", ASLd, "1110", "Data3", "1", "Size2_1", "Data1", "00", "Xn"); Assign("asr", ASRd, "1110", "Data3", "0", "Size2_1", "Data1", "00", "Xn"); Assign("lsl", LSLd, "1110", "Data3", "1", "Size2_1", "Data1", "01", "Xn"); Assign("lsr", LSRd, "1110", "Data3", "0", "Size2_1", "Data1", "01", "Xn"); Assign("roxl", ROXLd, "1110", "Data3", "1", "Size2_1", "Data1", "10", "Xn"); Assign("roxr", ROXRd, "1110", "Data3", "0", "Size2_1", "Data1", "10", "Xn"); Assign("rol", ROLd, "1110", "Data3", "1", "Size2_1", "Data1", "11", "Xn"); Assign("ror", RORd, "1110", "Data3", "0", "Size2_1", "Data1", "11", "Xn"); Assign("swap", SWAP, "0100100001000","Xn"); Assign("and", AND0, "1100", "Xn", "0", "Size2_1", "AmXn"); Assign("and", AND1, "1100", "Xn", "1", "Size2_1", "AmXn"); Assign("eor", EOR, "1011", "Xn", "1", "Size2_1", "AmXn"); Assign("or", OR0, "1000", "Xn", "0", "Size2_1", "AmXn"); Assign("or", OR1, "1000", "Xn", "1", "Size2_1", "AmXn"); Assign("not", NOT, "01000110", "Size2_1", "AmXn"); Assign("neg", NEG, "01000100", "Size2_1", "AmXn"); Assign("jmp", JMP, "0100111011", "AmXn"); Assign("jsr", JSR, "0100111010", "AmXn"); Assign("bcc", Bcc, "0110", "CondMain", "Data8"); Assign("bra", BRA, "01100000", "Data8"); Assign("bsr", BSR, "01100001", "Data8"); Assign("scc", Scc, "0101", "CondAll", "11","AmXn"); Assign("dbcc", DBcc, "0101", "CondAll", "11001", "Xn"); Assign("rte", RTE, "0100111001110011"); Assign("rts", RTS, "0100111001110101"); Assign("rtr", RTR, "0100111001110111"); Assign("tst", TST, "01001010", "Size2_1", "AmXn"); Assign("btst", BTSTi, "0000100000", "AmXn"); Assign("btst", BTSTr, "0000", "Xn", "100", "AmXn"); Assign("bchg", BCHGi, "0000100001", "AmXn"); Assign("bchg", BCHGr, "0000", "Xn", "101", "AmXn"); Assign("bclr", BCLRi, "0000100010", "AmXn"); Assign("bclr", BCLRr, "0000", "Xn", "110", "AmXn"); Assign("bset", BSETi, "0000100011", "AmXn"); Assign("bset", BSETr, "0000", "Xn", "111", "AmXn"); Assign("link", LINK, "0100111001010", "Xn"); Assign("unlk", UNLK, "0100111001011", "Xn"); Assign("nop", NOP, "0100111001110001"); Assign("add", ADD0, "1101", "Xn", "0", "Size2_1", "AmXn"); Assign("add", ADD1, "1101", "Xn", "1", "Size2_1", "AmXn"); Assign("adda", ADDA, "1101", "Xn", "Size1", "11", "AmXn"); Assign("addi", ADDI, "00000110", "Size2_1", "AmXn"); Assign("addq", ADDQ, "0101", "Data3", "0", "Size2_1", "AmXn"); Assign("sub", SUB0, "1001", "Xn", "0", "Size2_1", "AmXn"); Assign("sub", SUB1, "1001", "Xn", "1", "Size2_1", "AmXn"); Assign("suba", SUBA, "1001", "Xn", "Size1", "11", "AmXn"); Assign("subi", SUBI, "00000100", "Size2_1", "AmXn"); Assign("subq", SUBQ, "0101", "Data3", "1", "Size2_1", "AmXn"); Assign("cmp", CMP, "1011", "Xn", "0", "Size2_1", "AmXn"); Assign("cmpm", CMPM, "1011", "Xn", "1", "Size2_1", "001", "Xn"); Assign("cmpa", CMPA, "1011", "Xn", "Size1", "11", "AmXn"); Assign("cmpi", CMPI, "00001100", "Size2_1", "AmXn"); Assign("mulu", MULU, "1100", "Xn", "011", "AmXn"); // TODO accurate timing Assign("muls", MULS, "1100", "Xn", "111", "AmXn"); // TODO accurate timing Assign("divu", DIVU, "1000", "Xn", "011", "AmXn"); // TODO accurate timing Assign("divs", DIVS, "1000", "Xn", "111", "AmXn"); // TODO accurate timing Assign("move2sr", MOVEtSR, "0100011011", "AmXn"); Assign("movefsr", MOVEfSR, "0100000011", "AmXn"); Assign("moveusp", MOVEUSP, "010011100110", "Data1", "Xn"); Assign("andi2sr", ANDI_SR, "0000001001111100"); Assign("eori2sr", EORI_SR, "0000101001111100"); Assign("ori2sr", ORI_SR, "0000000001111100"); Assign("moveccr", MOVECCR, "0100010011", "AmXn"); Assign("trap", TRAP, "010011100100", "Data4"); } void Assign(string instr, Action exec, string root, params string[] bitfield) { List opList = new List(); opList.Add(root); foreach (var component in bitfield) { if (component.IsBinary()) AppendConstant(opList, component); else if (component == "Size1") opList = AppendPermutations(opList, Size1); else if (component == "Size2_0") opList = AppendPermutations(opList, Size2_0); else if (component == "Size2_1") opList = AppendPermutations(opList, Size2_1); else if (component == "XnAm") opList = AppendPermutations(opList, Xn3Am3); else if (component == "AmXn") opList = AppendPermutations(opList, Am3Xn3); else if (component == "Xn") opList = AppendPermutations(opList, Xn3); else if (component == "CondMain") opList = AppendPermutations(opList, ConditionMain); else if (component == "CondAll") opList = AppendPermutations(opList, ConditionAll); else if (component == "Data1") opList = AppendData(opList, 1); else if (component == "Data4") opList = AppendData(opList, 4); else if (component == "Data3") opList = AppendData(opList, 3); else if (component == "Data8") opList = AppendData(opList, 8); } foreach (var opcode in opList) { int opc = Convert.ToInt32(opcode, 2); if (Opcodes[opc] != null && instr.NotIn("movea","andi2sr","eori2sr","ori2sr","ext","dbcc","swap","cmpm")) Console.WriteLine("Setting opcode for {0}, a handler is already set. overwriting. {1:X4}", instr, opc); Opcodes[opc] = exec; } } void AppendConstant(List ops, string constant) { for (int i=0; i AppendPermutations(List ops, string[] permutations) { List output = new List(); foreach (var input in ops) foreach (var perm in permutations) output.Add(input + perm); return output; } List AppendData(List ops, int bits) { List output = new List(); foreach (var input in ops) for (int i = 0; i < BinaryExp(bits); i++) output.Add(input+Convert.ToString(i, 2).PadLeft(bits, '0')); return output; } int BinaryExp(int bits) { int res = 1; for (int i = 0; i < bits; i++) res *= 2; return res; } #region Tables static readonly string[] Size2_0 = {"01", "11", "10"}; static readonly string[] Size2_1 = {"00", "01", "10"}; static readonly string[] Size1 = {"0", "1" }; static readonly string[] Xn3 = {"000","001","010","011","100","101","110","111"}; static readonly string[] Xn3Am3 = { "000000", // Dn Data register "001000", "010000", "011000", "100000", "101000", "110000", "111000", "000001", // An Address register "001001", "010001", "011001", "100001", "101001", "110001", "111001", "000010", // (An) Address "001010", "010010", "011010", "100010", "101010", "110010", "111010", "000011", // (An)+ Address with Postincrement "001011", "010011", "011011", "100011", "101011", "110011", "111011", "000100", // -(An) Address with Predecrement "001100", "010100", "011100", "100100", "101100", "110100", "111100", "000101", // (d16, An) Address with Displacement "001101", "010101", "011101", "100101", "101101", "110101", "111101", "000110", // (d8, An, Xn) Address with Index "001110", "010110", "011110", "100110", "101110", "110110", "111110", "010111", // (d16, PC) PC with Displacement "011111", // (d8, PC, Xn) PC with Index "000111", // (xxx).W Absolute Short "001111", // (xxx).L Absolute Long "100111", // #imm Immediate }; static readonly string[] Am3Xn3 = { "000000", // Dn Data register "000001", "000010", "000011", "000100", "000101", "000110", "000111", "001000", // An Address register "001001", "001010", "001011", "001100", "001101", "001110", "001111", "010000", // (An) Address "010001", "010010", "010011", "010100", "010101", "010110", "010111", "011000", // (An)+ Address with Postincrement "011001", "011010", "011011", "011100", "011101", "011110", "011111", "100000", // -(An) Address with Predecrement "100001", "100010", "100011", "100100", "100101", "100110", "100111", "101000", // (d16, An) Address with Displacement "101001", "101010", "101011", "101100", "101101", "101110", "101111", "110000", // (d8, An, Xn) Address with Index "110001", "110010", "110011", "110100", "110101", "110110", "110111", "111010", // (d16, PC) PC with Displacement "111011", // (d8, PC, Xn) PC with Index "111000", // (xxx).W Absolute Short "111001", // (xxx).L Absolute Long "111100", // #imm Immediate }; static readonly string[] ConditionMain = { "0010", // HI Higher (unsigned) "0011", // LS Lower or Same (unsigned) "0100", // CC Carry Clear (aka Higher or Same, unsigned) "0101", // CS Carry Set (aka Lower, unsigned) "0110", // NE Not Equal "0111", // EQ Equal "1000", // VC Overflow Clear "1001", // VS Overflow Set "1010", // PL Plus "1011", // MI Minus "1100", // GE Greater or Equal (signed) "1101", // LT Less Than (signed) "1110", // GT Greater Than (signed) "1111" // LE Less or Equal (signed) }; static readonly string[] ConditionAll = { "0000", // T True "0001", // F False "0010", // HI Higher (unsigned) "0011", // LS Lower or Same (unsigned) "0100", // CC Carry Clear (aka Higher or Same, unsigned) "0101", // CS Carry Set (aka Lower, unsigned) "0110", // NE Not Equal "0111", // EQ Equal "1000", // VC Overflow Clear "1001", // VS Overflow Set "1010", // PL Plus "1011", // MI Minus "1100", // GE Greater or Equal (signed) "1101", // LT Less Than (signed) "1110", // GT Greater Than (signed) "1111" // LE Less or Equal (signed) }; #endregion } }