mirror of
				https://github.com/TomHarte/CLK.git
				synced 2025-11-04 00:16:26 +00:00 
			
		
		
		
	Compare commits
	
		
			26 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					f8eb7dd015 | ||
| 
						 | 
					716153cf0a | ||
| 
						 | 
					821b5358ea | ||
| 
						 | 
					fa1139acb3 | ||
| 
						 | 
					3a42b0ac3d | ||
| 
						 | 
					14ff3162cf | ||
| 
						 | 
					768f47198f | ||
| 
						 | 
					b4bb7cdaf9 | ||
| 
						 | 
					3673f931b8 | ||
| 
						 | 
					3dce673b37 | ||
| 
						 | 
					f7932d8583 | ||
| 
						 | 
					b6c91035f4 | ||
| 
						 | 
					7f030bc282 | ||
| 
						 | 
					32f946b3f0 | ||
| 
						 | 
					939f015007 | ||
| 
						 | 
					20d54c0397 | ||
| 
						 | 
					950fddebf9 | ||
| 
						 | 
					47d5d65633 | ||
| 
						 | 
					be1cec8f55 | ||
| 
						 | 
					6207f2ab41 | ||
| 
						 | 
					e30a02a0c0 | ||
| 
						 | 
					c7097274c9 | ||
| 
						 | 
					e82f2a3810 | ||
| 
						 | 
					cbf6ae81d0 | ||
| 
						 | 
					7a6fab72fe | ||
| 
						 | 
					4005506e42 | 
@@ -31,6 +31,8 @@ namespace MC68000 {
 | 
			
		||||
#define d8PCXn	0x13
 | 
			
		||||
#define Imm		0x14
 | 
			
		||||
 | 
			
		||||
#define Quick	0x20
 | 
			
		||||
 | 
			
		||||
struct ProcessorStorageConstructor {
 | 
			
		||||
	ProcessorStorageConstructor(ProcessorStorage &storage) : storage_(storage) {}
 | 
			
		||||
 | 
			
		||||
@@ -479,6 +481,7 @@ struct ProcessorStorageConstructor {
 | 
			
		||||
		assert(value == values.end());
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	/*!
 | 
			
		||||
		Disassembles the instruction @c instruction and inserts it into the
 | 
			
		||||
		appropriate lookup tables.
 | 
			
		||||
@@ -837,14 +840,331 @@ struct ProcessorStorageConstructor {
 | 
			
		||||
#define bw(x)		(x)
 | 
			
		||||
#define l(x)		(0x10000 | (x))
 | 
			
		||||
 | 
			
		||||
#define NoOperand ~0
 | 
			
		||||
		struct InstructionDumper {
 | 
			
		||||
			public:
 | 
			
		||||
				InstructionDumper(uint16_t opcode) :
 | 
			
		||||
					opcode_(opcode) {}
 | 
			
		||||
 | 
			
		||||
				~InstructionDumper() {
 | 
			
		||||
					const char *opname = "???";
 | 
			
		||||
					if(opcode_ == 0x4e71) {
 | 
			
		||||
						opname = "NOP";
 | 
			
		||||
					} else {
 | 
			
		||||
						switch(operation_) {
 | 
			
		||||
							default:
 | 
			
		||||
								printf("%d\n", int(operation_));
 | 
			
		||||
								assert(false);
 | 
			
		||||
							break;
 | 
			
		||||
#define DirectMap(x)	case Operation::x:	opname = #x;	break
 | 
			
		||||
 | 
			
		||||
							DirectMap(None);
 | 
			
		||||
							DirectMap(ABCD);
 | 
			
		||||
							DirectMap(SBCD);
 | 
			
		||||
							DirectMap(NBCD);
 | 
			
		||||
 | 
			
		||||
							case Operation::ADDQb:
 | 
			
		||||
							case Operation::ADDb:	opname = "ADD.b";	break;
 | 
			
		||||
							case Operation::ADDQw:
 | 
			
		||||
							case Operation::ADDw:	opname = "ADD.w";	break;
 | 
			
		||||
							case Operation::ADDQl:
 | 
			
		||||
							case Operation::ADDl:	opname = "ADD.l";	break;
 | 
			
		||||
							case Operation::ADDQAw:
 | 
			
		||||
							case Operation::ADDAw:	opname = "ADDA.w";	break;
 | 
			
		||||
							case Operation::ADDQAl:
 | 
			
		||||
							case Operation::ADDAl:	opname = "ADDA.l";	break;
 | 
			
		||||
							case Operation::ADDXb:	opname = "ADDX.b";	break;
 | 
			
		||||
							case Operation::ADDXw:	opname = "ADDX.w";	break;
 | 
			
		||||
							case Operation::ADDXl:	opname = "ADDX.l";	break;
 | 
			
		||||
 | 
			
		||||
							case Operation::SUBQb:
 | 
			
		||||
							case Operation::SUBb:	opname = "SUB.b";	break;
 | 
			
		||||
							case Operation::SUBQw:
 | 
			
		||||
							case Operation::SUBw:	opname = "SUB.w";	break;
 | 
			
		||||
							case Operation::SUBQl:
 | 
			
		||||
							case Operation::SUBl:	opname = "SUB.l";	break;
 | 
			
		||||
							case Operation::SUBQAw:
 | 
			
		||||
							case Operation::SUBAw:	opname = "SUBA.w";	break;
 | 
			
		||||
							case Operation::SUBQAl:
 | 
			
		||||
							case Operation::SUBAl:	opname = "SUBA.l";	break;
 | 
			
		||||
							case Operation::SUBXb:	opname = "SUBX.b";	break;
 | 
			
		||||
							case Operation::SUBXw:	opname = "SUBX.w";	break;
 | 
			
		||||
							case Operation::SUBXl:	opname = "SUBX.l";	break;
 | 
			
		||||
 | 
			
		||||
							case Operation::MOVEb:	opname = "MOVE.b";	break;
 | 
			
		||||
							case Operation::MOVEw:	opname = "MOVE.w";	break;
 | 
			
		||||
							case Operation::MOVEl:	opname = "MOVE.l";	break;
 | 
			
		||||
							case Operation::MOVEq:	opname = "MOVE.q";	break;
 | 
			
		||||
 | 
			
		||||
							case Operation::MOVEAw:	opname = "MOVEA.w";	break;
 | 
			
		||||
							case Operation::MOVEAl:
 | 
			
		||||
								// A bunch of things are multiplexed onto MOVEA.l;
 | 
			
		||||
								// disambiguate here.
 | 
			
		||||
								if((opcode_ & 0xf1c0) == 0x41c0) {
 | 
			
		||||
									opname = "LEA";
 | 
			
		||||
								} else if ((opcode_ & 0xfff8) == 0x4e68) {
 | 
			
		||||
									opname = "MOVEfromUSP";
 | 
			
		||||
								} else if ((opcode_ & 0xfff8) == 0x4e60) {
 | 
			
		||||
									opname = "MOVEtoUSP";
 | 
			
		||||
								} else {
 | 
			
		||||
									opname = "MOVEA.l";
 | 
			
		||||
								}
 | 
			
		||||
							break;
 | 
			
		||||
 | 
			
		||||
							case Operation::PEA:	opname = "PEA";		break;
 | 
			
		||||
 | 
			
		||||
							DirectMap(MOVEtoSR);
 | 
			
		||||
							DirectMap(MOVEfromSR);
 | 
			
		||||
							DirectMap(MOVEtoCCR);
 | 
			
		||||
 | 
			
		||||
							DirectMap(ORItoSR);
 | 
			
		||||
							DirectMap(ORItoCCR);
 | 
			
		||||
							DirectMap(ANDItoSR);
 | 
			
		||||
							DirectMap(ANDItoCCR);
 | 
			
		||||
							DirectMap(EORItoSR);
 | 
			
		||||
							DirectMap(EORItoCCR);
 | 
			
		||||
 | 
			
		||||
							case Operation::BTSTb:	opname = "BTST";	break;
 | 
			
		||||
							case Operation::BTSTl:	opname = "BTST";	break;
 | 
			
		||||
							case Operation::BCLRb:	opname = "BCLR";	break;
 | 
			
		||||
							case Operation::BCLRl:	opname = "BCLR";	break;
 | 
			
		||||
 | 
			
		||||
							case Operation::CMPb:	opname = "CMP.b";	break;
 | 
			
		||||
							case Operation::CMPw:
 | 
			
		||||
								opname = "CMP.w";
 | 
			
		||||
							break;
 | 
			
		||||
							case Operation::CMPl:
 | 
			
		||||
								opname = (dest_ == An) ? "CMPA.l" : "CMP.l";
 | 
			
		||||
							break;
 | 
			
		||||
							case Operation::CMPAw:	opname = "CMPA.w";	break;
 | 
			
		||||
							case Operation::TSTb:	opname = "TST.b";	break;
 | 
			
		||||
							case Operation::TSTw:	opname = "TST.w";	break;
 | 
			
		||||
							case Operation::TSTl:	opname = "TST.l";	break;
 | 
			
		||||
 | 
			
		||||
							case Operation::JMP:
 | 
			
		||||
								if(opcode_ & 0x40) {
 | 
			
		||||
									opname = "JMP";
 | 
			
		||||
								} else {
 | 
			
		||||
									opname = "JSR";
 | 
			
		||||
								}
 | 
			
		||||
							break;
 | 
			
		||||
							case Operation::Bcc:
 | 
			
		||||
								if((opcode_ & 0xf00) == 0x100) {
 | 
			
		||||
									opname = "BSR";
 | 
			
		||||
								} else {
 | 
			
		||||
									opname = "Bcc";
 | 
			
		||||
								}
 | 
			
		||||
							break;
 | 
			
		||||
 | 
			
		||||
							DirectMap(RTS);
 | 
			
		||||
							DirectMap(BRA);
 | 
			
		||||
							DirectMap(DBcc);
 | 
			
		||||
							DirectMap(Scc);
 | 
			
		||||
 | 
			
		||||
							case Operation::CLRb:	opname = "CLR.b";	break;
 | 
			
		||||
							case Operation::CLRw:	opname = "CLR.w";	break;
 | 
			
		||||
							case Operation::CLRl:	opname = "CLR.l";	break;
 | 
			
		||||
 | 
			
		||||
							case Operation::NEGXb:	opname = "NEGX.b";	break;
 | 
			
		||||
							case Operation::NEGXw:	opname = "NEGX.w";	break;
 | 
			
		||||
							case Operation::NEGXl:	opname = "NEGX.l";	break;
 | 
			
		||||
 | 
			
		||||
							case Operation::NEGb:	opname = "NEG.b";	break;
 | 
			
		||||
							case Operation::NEGw:	opname = "NEG.w";	break;
 | 
			
		||||
							case Operation::NEGl:	opname = "NEG.l";	break;
 | 
			
		||||
 | 
			
		||||
							case Operation::ASLb:	opname = "ASL.b";	break;
 | 
			
		||||
							case Operation::ASLm:
 | 
			
		||||
							case Operation::ASLw:	opname = "ASL.w";	break;
 | 
			
		||||
							case Operation::ASLl:	opname = "ASL.l";	break;
 | 
			
		||||
 | 
			
		||||
							case Operation::ASRb:	opname = "ASR.b";	break;
 | 
			
		||||
							case Operation::ASRm:
 | 
			
		||||
							case Operation::ASRw:	opname = "ASR.w";	break;
 | 
			
		||||
							case Operation::ASRl:	opname = "ASR.l";	break;
 | 
			
		||||
 | 
			
		||||
							case Operation::LSLb:	opname = "LSL.b";	break;
 | 
			
		||||
							case Operation::LSLm:
 | 
			
		||||
							case Operation::LSLw:	opname = "LSL.w";	break;
 | 
			
		||||
							case Operation::LSLl:	opname = "LSL.l";	break;
 | 
			
		||||
 | 
			
		||||
							case Operation::LSRb:	opname = "LSR.b";	break;
 | 
			
		||||
							case Operation::LSRm:
 | 
			
		||||
							case Operation::LSRw:	opname = "LSR.w";	break;
 | 
			
		||||
							case Operation::LSRl:	opname = "LSR.l";	break;
 | 
			
		||||
 | 
			
		||||
							case Operation::ROLb:	opname = "ROL.b";	break;
 | 
			
		||||
							case Operation::ROLm:
 | 
			
		||||
							case Operation::ROLw:	opname = "ROL.w";	break;
 | 
			
		||||
							case Operation::ROLl:	opname = "ROL.l";	break;
 | 
			
		||||
 | 
			
		||||
							case Operation::RORb:	opname = "ROR.b";	break;
 | 
			
		||||
							case Operation::RORm:
 | 
			
		||||
							case Operation::RORw:	opname = "ROR.w";	break;
 | 
			
		||||
							case Operation::RORl:	opname = "ROR.l";	break;
 | 
			
		||||
 | 
			
		||||
							case Operation::ROXLb:	opname = "ROXL.b";	break;
 | 
			
		||||
							case Operation::ROXLm:
 | 
			
		||||
							case Operation::ROXLw:	opname = "ROXL.w";	break;
 | 
			
		||||
							case Operation::ROXLl:	opname = "ROXL.l";	break;
 | 
			
		||||
 | 
			
		||||
							case Operation::ROXRb:	opname = "ROXR.b";	break;
 | 
			
		||||
							case Operation::ROXRm:
 | 
			
		||||
							case Operation::ROXRw:	opname = "ROXR.w";	break;
 | 
			
		||||
							case Operation::ROXRl:	opname = "ROXR.l";	break;
 | 
			
		||||
 | 
			
		||||
							case Operation::MOVEMtoMl:
 | 
			
		||||
							case Operation::MOVEMtoRl:	opname = "MOVEM.l";	break;
 | 
			
		||||
							case Operation::MOVEMtoMw:
 | 
			
		||||
							case Operation::MOVEMtoRw:	opname = "MOVEM.w";	break;
 | 
			
		||||
 | 
			
		||||
							case Operation::MOVEPtoMl:
 | 
			
		||||
							case Operation::MOVEPtoRl:	opname = "MOVEP.l";	break;
 | 
			
		||||
							case Operation::MOVEPtoMw:
 | 
			
		||||
							case Operation::MOVEPtoRw:	opname = "MOVEP.w";	break;
 | 
			
		||||
 | 
			
		||||
	//						DirectMap(MOVEMtoRl);
 | 
			
		||||
	//						DirectMap(MOVEMtoRw);
 | 
			
		||||
	//						DirectMap(MOVEMtoMl);
 | 
			
		||||
	//						DirectMap(MOVEMtoMw);
 | 
			
		||||
 | 
			
		||||
							case Operation::ANDb:	opname = "AND.b";	break;
 | 
			
		||||
							case Operation::ANDw:	opname = "AND.w";	break;
 | 
			
		||||
							case Operation::ANDl:	opname = "AND.l";	break;
 | 
			
		||||
 | 
			
		||||
							case Operation::EORb:	opname = "EOR.b";	break;
 | 
			
		||||
							case Operation::EORw:	opname = "EOR.w";	break;
 | 
			
		||||
							case Operation::EORl:	opname = "EOR.l";	break;
 | 
			
		||||
 | 
			
		||||
							case Operation::NOTb:	opname = "NOT.b";	break;
 | 
			
		||||
							case Operation::NOTw:	opname = "NOT.w";	break;
 | 
			
		||||
							case Operation::NOTl:	opname = "NOT.l";	break;
 | 
			
		||||
 | 
			
		||||
							case Operation::ORb:	opname = "OR.b";	break;
 | 
			
		||||
							case Operation::ORw:	opname = "OR.w";	break;
 | 
			
		||||
							case Operation::ORl:	opname = "OR.l";	break;
 | 
			
		||||
 | 
			
		||||
							DirectMap(MULU);
 | 
			
		||||
							DirectMap(MULS);
 | 
			
		||||
							DirectMap(DIVU);
 | 
			
		||||
							DirectMap(DIVS);
 | 
			
		||||
 | 
			
		||||
							case Operation::RTE_RTR:
 | 
			
		||||
								opname = (opcode_ == 0x4e77) ? "RTR" : "RTE";
 | 
			
		||||
							break;
 | 
			
		||||
 | 
			
		||||
							DirectMap(TRAP);
 | 
			
		||||
							DirectMap(TRAPV);
 | 
			
		||||
							DirectMap(CHK);
 | 
			
		||||
							DirectMap(EXG);
 | 
			
		||||
							DirectMap(SWAP);
 | 
			
		||||
 | 
			
		||||
							case Operation::BCHGb:	opname = "BCHG";	break;
 | 
			
		||||
							case Operation::BCHGl:	opname = "BCHG";	break;
 | 
			
		||||
							case Operation::BSETb:	opname = "BSET";	break;
 | 
			
		||||
							case Operation::BSETl:	opname = "BSET";	break;
 | 
			
		||||
 | 
			
		||||
							DirectMap(TAS);
 | 
			
		||||
							case Operation::EXTbtow:	opname = "EXT.w";	break;
 | 
			
		||||
							case Operation::EXTwtol:	opname = "EXT.l";	break;
 | 
			
		||||
							DirectMap(LINK);
 | 
			
		||||
							DirectMap(UNLINK);
 | 
			
		||||
							DirectMap(STOP);
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
#undef DirectMap
 | 
			
		||||
 | 
			
		||||
					printf("\"%04x\": \"%s", opcode_, opname);
 | 
			
		||||
					if(source_ != NoOperand) {
 | 
			
		||||
						printf(" %s", modename(source_, source_reg_));
 | 
			
		||||
					}
 | 
			
		||||
					if(dest_ != NoOperand) {
 | 
			
		||||
						printf(", %s", modename(dest_, dest_reg_));
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					printf("\",\n");
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				void set_operation(Operation op)		{ operation_ = op;						}
 | 
			
		||||
				void set_source(int type, int reg = 0)	{ source_ = type; source_reg_ = reg;	}
 | 
			
		||||
				void set_dest(int type, int reg = 0) 	{ dest_ = type;	dest_reg_ = reg;		}
 | 
			
		||||
				void set_source_dest(int s, int sr, int d, int dr)	{
 | 
			
		||||
					set_source(s, sr);
 | 
			
		||||
					set_dest(d, dr);
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				void reset() {
 | 
			
		||||
					operation_ = Operation::None;
 | 
			
		||||
					source_ = dest_ = NoOperand;
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
			private:
 | 
			
		||||
				uint16_t opcode_ = 0;
 | 
			
		||||
				Operation operation_ = Operation::None;
 | 
			
		||||
 | 
			
		||||
				int source_ = NoOperand;
 | 
			
		||||
				int dest_ = NoOperand;
 | 
			
		||||
				int source_reg_ = 0;
 | 
			
		||||
				int dest_reg_ = 0;
 | 
			
		||||
 | 
			
		||||
				char tbuf[20];
 | 
			
		||||
				const char *modename(int mode, int reg) {
 | 
			
		||||
					switch(mode) {
 | 
			
		||||
						default:
 | 
			
		||||
							assert(false);
 | 
			
		||||
							return "?";
 | 
			
		||||
						case XXXl:		return "(xxx).l";
 | 
			
		||||
						case XXXw:		return "(xxx).w";
 | 
			
		||||
						case d16PC:		return "(d16, PC)";
 | 
			
		||||
						case d8PCXn:	return "(d8, PC, Xn)";
 | 
			
		||||
						case Imm:		return "#";
 | 
			
		||||
						case Dn:		sprintf(tbuf, "D%d", reg);				break;
 | 
			
		||||
						case An:		sprintf(tbuf, "A%d", reg);				break;
 | 
			
		||||
						case Ind:		sprintf(tbuf, "(A%d)", reg);			break;
 | 
			
		||||
						case PostInc:	sprintf(tbuf, "(A%d)+", reg);			break;
 | 
			
		||||
						case PreDec:	sprintf(tbuf, "-(A%d)", reg);			break;
 | 
			
		||||
						case d16An:		sprintf(tbuf, "(d16, A%d)", reg);		break;
 | 
			
		||||
						case d8AnXn:	sprintf(tbuf, "(d8, A%d, Xn)", reg);	break;
 | 
			
		||||
						case Quick:
 | 
			
		||||
							if(operation_ == Operation::MOVEq) {
 | 
			
		||||
								sprintf(tbuf, "%d", int8_t(opcode_));
 | 
			
		||||
							} else if(operation_ == Operation::Bcc || operation_ == Operation::BRA) {
 | 
			
		||||
								const int8_t val = int8_t(opcode_);
 | 
			
		||||
								if(!val) {
 | 
			
		||||
									return "#";
 | 
			
		||||
								} else {
 | 
			
		||||
									sprintf(tbuf, "%d", val);
 | 
			
		||||
								}
 | 
			
		||||
							} else if(operation_ == Operation::TRAP) {
 | 
			
		||||
								sprintf(tbuf, "%d", opcode_ & 15);
 | 
			
		||||
							} else {
 | 
			
		||||
								const auto val = ((opcode_ >> 9)&7);
 | 
			
		||||
								sprintf(tbuf, "%d", val ? val : 8);
 | 
			
		||||
							}
 | 
			
		||||
						break;
 | 
			
		||||
					}
 | 
			
		||||
					return tbuf;
 | 
			
		||||
				}
 | 
			
		||||
		};
 | 
			
		||||
 | 
			
		||||
#undef NoOperand
 | 
			
		||||
 | 
			
		||||
		// Perform a linear search of the mappings above for this instruction.
 | 
			
		||||
		for(ssize_t instruction = 65535; instruction >= 0; --instruction)	{
 | 
			
		||||
			if(instruction == 0x54c8) {
 | 
			
		||||
				printf("");
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			InstructionDumper dumper{uint16_t(instruction)};
 | 
			
		||||
#ifndef NDEBUG
 | 
			
		||||
			int hits = 0;
 | 
			
		||||
#endif
 | 
			
		||||
			for(const auto &mapping: mappings) {
 | 
			
		||||
				dumper.reset();
 | 
			
		||||
 | 
			
		||||
				if((instruction & mapping.mask) == mapping.value) {
 | 
			
		||||
					auto operation = mapping.operation;
 | 
			
		||||
					dumper.set_operation(operation);
 | 
			
		||||
					const auto micro_op_start = storage_.all_micro_ops_.size();
 | 
			
		||||
 | 
			
		||||
					// The following fields are used commonly enough to be worth pulling out here.
 | 
			
		||||
@@ -868,17 +1188,21 @@ struct ProcessorStorageConstructor {
 | 
			
		||||
					switch(mapping.decoder) {
 | 
			
		||||
						case Decoder::STOP: {
 | 
			
		||||
							program.set_requires_supervisor(true);
 | 
			
		||||
							dumper.set_source(Imm);
 | 
			
		||||
							op(Action::None, seq("n"));
 | 
			
		||||
							op(Action::PerformOperation);
 | 
			
		||||
						} break;
 | 
			
		||||
 | 
			
		||||
						case Decoder::LINK: {
 | 
			
		||||
							program.set_source(storage_, An, ea_register);
 | 
			
		||||
							dumper.set_source(An, ea_register);
 | 
			
		||||
							dumper.set_dest(Imm);
 | 
			
		||||
							op(Action::PerformOperation, seq("np nW+ nw np", { ea(1), ea(1) }));
 | 
			
		||||
						} break;
 | 
			
		||||
 | 
			
		||||
						case Decoder::UNLINK: {
 | 
			
		||||
							program.set_destination(storage_, An, ea_register);
 | 
			
		||||
							dumper.set_source(An, ea_register);
 | 
			
		||||
							op(int(Action::CopyToEffectiveAddress) | MicroOp::DestinationMask, seq("nRd+ nrd np", { ea(1), ea(1) }));
 | 
			
		||||
							op(Action::PerformOperation);
 | 
			
		||||
						} break;
 | 
			
		||||
@@ -886,6 +1210,8 @@ struct ProcessorStorageConstructor {
 | 
			
		||||
						case Decoder::TAS: {
 | 
			
		||||
							const int mode = combined_mode(ea_mode, ea_register);
 | 
			
		||||
							program.set_destination(storage_, ea_mode, ea_register);
 | 
			
		||||
 | 
			
		||||
							dumper.set_source(mode, ea_register);
 | 
			
		||||
							switch(mode) {
 | 
			
		||||
								default: continue;
 | 
			
		||||
 | 
			
		||||
@@ -932,10 +1258,12 @@ struct ProcessorStorageConstructor {
 | 
			
		||||
							if(instruction & 0x100) {
 | 
			
		||||
								// The bit is nominated by a register.
 | 
			
		||||
								program.set_source(storage_, Dn, data_register);
 | 
			
		||||
								dumper.set_source_dest(Dn, data_register, mode, ea_register);
 | 
			
		||||
							} else {
 | 
			
		||||
								// The bit is nominated by a constant, that will be obtained right here.
 | 
			
		||||
								program.set_source(storage_, Imm, 0);
 | 
			
		||||
								op(int(Action::AssembleWordDataFromPrefetch) | MicroOp::SourceMask, seq("np"));
 | 
			
		||||
								dumper.set_source_dest(Imm, 0, mode, ea_register);
 | 
			
		||||
							}
 | 
			
		||||
 | 
			
		||||
							switch(mode) {
 | 
			
		||||
@@ -978,11 +1306,13 @@ struct ProcessorStorageConstructor {
 | 
			
		||||
							program.set_requires_supervisor(!!(instruction & 0x40));
 | 
			
		||||
							op(Action::None, seq("np nn nn"));
 | 
			
		||||
							op(Action::PerformOperation, seq("np np"));
 | 
			
		||||
							dumper.set_source(Imm);
 | 
			
		||||
						} break;
 | 
			
		||||
 | 
			
		||||
						case Decoder::EXT_SWAP: {
 | 
			
		||||
							program.set_destination(storage_, Dn, ea_register);
 | 
			
		||||
							op(Action::PerformOperation, seq("np"));
 | 
			
		||||
							dumper.set_source(Dn, ea_register);
 | 
			
		||||
						} break;
 | 
			
		||||
 | 
			
		||||
						case Decoder::EXG: {
 | 
			
		||||
@@ -992,16 +1322,19 @@ struct ProcessorStorageConstructor {
 | 
			
		||||
								case 0x08:
 | 
			
		||||
									program.set_source(storage_, Dn, data_register);
 | 
			
		||||
									program.set_destination(storage_, Dn, ea_register);
 | 
			
		||||
									dumper.set_source_dest(Dn, data_register, Dn, ea_register);
 | 
			
		||||
								break;
 | 
			
		||||
 | 
			
		||||
								case 0x09:
 | 
			
		||||
									program.set_source(storage_, An, data_register);
 | 
			
		||||
									program.set_destination(storage_, An, ea_register);
 | 
			
		||||
									dumper.set_source_dest(An, data_register, An, ea_register);
 | 
			
		||||
								break;
 | 
			
		||||
 | 
			
		||||
								case 0x11:
 | 
			
		||||
									program.set_source(storage_, Dn, data_register);
 | 
			
		||||
									program.set_destination(storage_, An, ea_register);
 | 
			
		||||
									dumper.set_source_dest(Dn, data_register, An, ea_register);
 | 
			
		||||
								break;
 | 
			
		||||
							}
 | 
			
		||||
 | 
			
		||||
@@ -1037,6 +1370,7 @@ struct ProcessorStorageConstructor {
 | 
			
		||||
							if(to_ea) {
 | 
			
		||||
								program.set_destination(storage_, ea_mode, ea_register);
 | 
			
		||||
								program.set_source(storage_, Dn, data_register);
 | 
			
		||||
								dumper.set_source_dest(Dn, data_register, mode, ea_register);
 | 
			
		||||
 | 
			
		||||
								// Only EOR takes Dn as a destination effective address.
 | 
			
		||||
								if(!is_eor && mode == Dn) continue;
 | 
			
		||||
@@ -1104,6 +1438,7 @@ struct ProcessorStorageConstructor {
 | 
			
		||||
 | 
			
		||||
								program.set_source(storage_, ea_mode, ea_register);
 | 
			
		||||
								program.set_destination(storage_, Dn, data_register);
 | 
			
		||||
								dumper.set_source_dest(mode, ea_register, Dn, data_register);
 | 
			
		||||
 | 
			
		||||
								switch(is_long_word_access ? l(mode) : bw(mode)) {
 | 
			
		||||
									default: continue;
 | 
			
		||||
@@ -1185,6 +1520,7 @@ struct ProcessorStorageConstructor {
 | 
			
		||||
							program.set_destination(storage_, Dn, data_register);
 | 
			
		||||
 | 
			
		||||
							const int mode = combined_mode(ea_mode, ea_register);
 | 
			
		||||
							dumper.set_source_dest(mode, ea_register, Dn, data_register);
 | 
			
		||||
							switch(mode) {
 | 
			
		||||
								default: continue;
 | 
			
		||||
 | 
			
		||||
@@ -1232,6 +1568,7 @@ struct ProcessorStorageConstructor {
 | 
			
		||||
							program.set_destination(storage_, Dn, data_register);
 | 
			
		||||
 | 
			
		||||
							const int mode = combined_mode(ea_mode, ea_register);
 | 
			
		||||
							dumper.set_source_dest(mode, ea_register, Dn, data_register);
 | 
			
		||||
							switch(mode) {
 | 
			
		||||
								default: continue;
 | 
			
		||||
 | 
			
		||||
@@ -1281,6 +1618,7 @@ struct ProcessorStorageConstructor {
 | 
			
		||||
							// destination is going to be in the write address unit.
 | 
			
		||||
							program.set_source(storage_, Imm, 0);
 | 
			
		||||
							program.set_destination(storage_, mode, ea_register);
 | 
			
		||||
							dumper.set_source_dest(Imm, 0, mode, ea_register);
 | 
			
		||||
 | 
			
		||||
							switch(is_long_word_access ? l(mode) : bw(mode)) {
 | 
			
		||||
								default: continue;
 | 
			
		||||
@@ -1378,6 +1716,7 @@ struct ProcessorStorageConstructor {
 | 
			
		||||
							if(reverse_source_destination) {
 | 
			
		||||
								program.set_destination(storage_, Dn, data_register);
 | 
			
		||||
								program.set_source(storage_, Imm, ea_register);
 | 
			
		||||
								dumper.set_source_dest(mode, ea_register, Dn, data_register);
 | 
			
		||||
 | 
			
		||||
								// Perform [ADD/SUB].blw <ea>, Dn
 | 
			
		||||
								switch(is_long_word_access ? l(mode) : bw(mode)) {
 | 
			
		||||
@@ -1482,6 +1821,7 @@ struct ProcessorStorageConstructor {
 | 
			
		||||
								const auto destination_register = ea_register;
 | 
			
		||||
								program.set_destination(storage_, Ind, destination_register);
 | 
			
		||||
								program.set_source(storage_, Dn, data_register);
 | 
			
		||||
								dumper.set_source_dest(Dn, data_register, mode, ea_register);
 | 
			
		||||
 | 
			
		||||
								// Perform [ADD/SUB].blw Dn, <ea>
 | 
			
		||||
								switch(is_long_word_access ? l(mode) : bw(mode)) {
 | 
			
		||||
@@ -1550,6 +1890,7 @@ struct ProcessorStorageConstructor {
 | 
			
		||||
 | 
			
		||||
							const int mode = combined_mode(ea_mode, ea_register);
 | 
			
		||||
							is_long_word_access = op_mode_high_bit;
 | 
			
		||||
							dumper.set_source_dest(mode, ea_register, An, data_register);
 | 
			
		||||
 | 
			
		||||
							switch(is_long_word_access ? l(mode) : bw(mode)) {
 | 
			
		||||
								default: continue;
 | 
			
		||||
@@ -1634,6 +1975,7 @@ struct ProcessorStorageConstructor {
 | 
			
		||||
							program.set_destination(storage_, ea_mode, ea_register);
 | 
			
		||||
 | 
			
		||||
							const int mode = combined_mode(ea_mode, ea_register);
 | 
			
		||||
							dumper.set_source_dest(Quick, 0, mode, ea_register);
 | 
			
		||||
 | 
			
		||||
							// If the destination is an address register then byte mode isn't allowed, and
 | 
			
		||||
							// flags shouldn't be affected (so, a different operation is used).
 | 
			
		||||
@@ -1713,8 +2055,9 @@ struct ProcessorStorageConstructor {
 | 
			
		||||
						case Decoder::ADDX_SUBX: {
 | 
			
		||||
							if(instruction & 0x8) {
 | 
			
		||||
								// Use predecrementing address registers.
 | 
			
		||||
								program.set_source(storage_, Ind, ea_register);
 | 
			
		||||
								program.set_destination(storage_, Ind, data_register);
 | 
			
		||||
								program.set_source(storage_, PreDec, ea_register);
 | 
			
		||||
								program.set_destination(storage_, PreDec, data_register);
 | 
			
		||||
								dumper.set_source_dest(PreDec, ea_register, PreDec, data_register);
 | 
			
		||||
 | 
			
		||||
								if(is_long_word_access) {
 | 
			
		||||
									// Access order is very atypical here: it's lower parts each for both words,
 | 
			
		||||
@@ -1740,6 +2083,7 @@ struct ProcessorStorageConstructor {
 | 
			
		||||
								// Use data registers.
 | 
			
		||||
								program.set_source(storage_, Dn, ea_register);
 | 
			
		||||
								program.set_destination(storage_, Dn, data_register);
 | 
			
		||||
								dumper.set_source_dest(Dn, ea_register, Dn, data_register);
 | 
			
		||||
 | 
			
		||||
								if(is_long_word_access) {
 | 
			
		||||
									op(Action::PerformOperation, seq("np nn"));
 | 
			
		||||
@@ -1753,6 +2097,7 @@ struct ProcessorStorageConstructor {
 | 
			
		||||
						// This decoder actually decodes nothing; it just schedules a PerformOperation followed by an empty step.
 | 
			
		||||
						case Decoder::Bcc_BSR: {
 | 
			
		||||
							const int condition = (instruction >> 8) & 0xf;
 | 
			
		||||
							dumper.set_source(Quick);
 | 
			
		||||
							if(condition == 1) {
 | 
			
		||||
								// This is BSR, which is unconditional and means pushing a return address to the stack first.
 | 
			
		||||
 | 
			
		||||
@@ -1768,6 +2113,7 @@ struct ProcessorStorageConstructor {
 | 
			
		||||
						// A little artificial, there's nothing really to decode for BRA.
 | 
			
		||||
						case Decoder::BRA: {
 | 
			
		||||
							op(Action::PerformOperation, seq("n np np"));
 | 
			
		||||
							dumper.set_source(Quick);
 | 
			
		||||
						} break;
 | 
			
		||||
 | 
			
		||||
						// Decodes a BTST, potential mutating the operation into a BTSTl,
 | 
			
		||||
@@ -1780,6 +2126,7 @@ struct ProcessorStorageConstructor {
 | 
			
		||||
							program.set_destination(storage_, ea_mode, ea_register);
 | 
			
		||||
 | 
			
		||||
							const int mode = combined_mode(ea_mode, ea_register);
 | 
			
		||||
							dumper.set_source_dest(Dn, data_register, mode, ea_register);
 | 
			
		||||
							switch(mode) {
 | 
			
		||||
								default: continue;
 | 
			
		||||
 | 
			
		||||
@@ -1842,6 +2189,7 @@ struct ProcessorStorageConstructor {
 | 
			
		||||
							program.set_destination(storage_, ea_mode, ea_register);
 | 
			
		||||
 | 
			
		||||
							const int mode = combined_mode(ea_mode, ea_register);
 | 
			
		||||
							dumper.set_source_dest(Imm, 0, mode, ea_register);
 | 
			
		||||
							switch(mode) {
 | 
			
		||||
								default: continue;
 | 
			
		||||
 | 
			
		||||
@@ -1905,17 +2253,25 @@ struct ProcessorStorageConstructor {
 | 
			
		||||
								op(MicroOp::SourceMask | dec(ea_register), seq("n nr", { a(ea_register) }, false ));
 | 
			
		||||
								op(MicroOp::DestinationMask | dec(data_register), seq("nrd np", { a(data_register) }, false ));
 | 
			
		||||
								op(Action::PerformOperation, seq("nw", { a(data_register) }, false));
 | 
			
		||||
								dumper.set_source_dest(PreDec, ea_register, PreDec, data_register);
 | 
			
		||||
							} else {
 | 
			
		||||
								// [A/S]BCD Dn, Dn
 | 
			
		||||
								program.set_source(storage_, Dn, ea_register);
 | 
			
		||||
								program.set_destination(storage_, Dn, data_register);
 | 
			
		||||
 | 
			
		||||
								op(Action::PerformOperation, seq("np n"));
 | 
			
		||||
								dumper.set_source_dest(Dn, ea_register, Dn, data_register);
 | 
			
		||||
							}
 | 
			
		||||
						} break;
 | 
			
		||||
 | 
			
		||||
						case Decoder::ASLR_LSLR_ROLR_ROXLRr: {
 | 
			
		||||
							program.set_destination(storage_, 0, ea_register);
 | 
			
		||||
							dumper.set_dest(Dn, ea_register);
 | 
			
		||||
							if(instruction & 0x20) {
 | 
			
		||||
								dumper.set_source(Dn, data_register);
 | 
			
		||||
							} else {
 | 
			
		||||
								dumper.set_source(Quick);
 | 
			
		||||
							}
 | 
			
		||||
 | 
			
		||||
							// All further decoding occurs at runtime; that's also when the proper number of
 | 
			
		||||
							// no-op cycles will be scheduled.
 | 
			
		||||
@@ -1933,6 +2289,7 @@ struct ProcessorStorageConstructor {
 | 
			
		||||
							program.set_destination(storage_, ea_mode, ea_register);
 | 
			
		||||
 | 
			
		||||
							const int mode = combined_mode(ea_mode, ea_register);
 | 
			
		||||
							dumper.set_source(mode, ea_register);
 | 
			
		||||
							switch(mode) {
 | 
			
		||||
								default: continue;
 | 
			
		||||
 | 
			
		||||
@@ -1967,6 +2324,7 @@ struct ProcessorStorageConstructor {
 | 
			
		||||
							program.set_destination(storage_, ea_mode, ea_register);
 | 
			
		||||
 | 
			
		||||
							const int mode = combined_mode(ea_mode, ea_register);
 | 
			
		||||
							dumper.set_source(mode, ea_register);
 | 
			
		||||
							switch(is_long_word_access ? l(mode) : bw(mode)) {
 | 
			
		||||
								default: continue;
 | 
			
		||||
 | 
			
		||||
@@ -2043,6 +2401,7 @@ struct ProcessorStorageConstructor {
 | 
			
		||||
							}
 | 
			
		||||
 | 
			
		||||
							const int mode = combined_mode(ea_mode, ea_register);
 | 
			
		||||
							dumper.set_source_dest(mode, ea_register, Dn, data_register);
 | 
			
		||||
							switch(is_long_word_access ? l(mode) : bw(mode)) {
 | 
			
		||||
								default: continue;
 | 
			
		||||
 | 
			
		||||
@@ -2135,6 +2494,7 @@ struct ProcessorStorageConstructor {
 | 
			
		||||
							program.set_destination(storage_, An, data_register);
 | 
			
		||||
 | 
			
		||||
							const int mode = combined_mode(ea_mode, ea_register, true);
 | 
			
		||||
							dumper.set_source_dest(combined_mode(ea_mode, ea_register), ea_register, An, data_register);
 | 
			
		||||
							switch(is_long_word_access ? l(mode) : bw(mode)) {
 | 
			
		||||
								default: continue;
 | 
			
		||||
 | 
			
		||||
@@ -2219,6 +2579,7 @@ struct ProcessorStorageConstructor {
 | 
			
		||||
							program.set_destination(storage_, destination_mode, destination_register);
 | 
			
		||||
 | 
			
		||||
							const int mode = combined_mode(destination_mode, destination_register);
 | 
			
		||||
							dumper.set_source_dest(Imm, 0, mode, destination_register);
 | 
			
		||||
							switch(is_long_word_access ? l(mode) : bw(mode)) {
 | 
			
		||||
								default: continue;
 | 
			
		||||
 | 
			
		||||
@@ -2308,6 +2669,7 @@ struct ProcessorStorageConstructor {
 | 
			
		||||
						case Decoder::CMPM: {
 | 
			
		||||
							program.set_source(storage_, PostInc, ea_register);
 | 
			
		||||
							program.set_destination(storage_, PostInc, data_register);
 | 
			
		||||
							dumper.set_source_dest(PostInc, ea_register, PostInc, data_register);
 | 
			
		||||
 | 
			
		||||
							const bool is_byte_operation = operation == Operation::CMPb;
 | 
			
		||||
 | 
			
		||||
@@ -2340,6 +2702,9 @@ struct ProcessorStorageConstructor {
 | 
			
		||||
								// This is a DBcc. Decode as such.
 | 
			
		||||
								operation = Operation::DBcc;
 | 
			
		||||
								program.set_source(storage_, Dn, ea_register);
 | 
			
		||||
								dumper.set_source(Dn, ea_register);
 | 
			
		||||
								dumper.set_dest(Imm);
 | 
			
		||||
								dumper.set_operation(operation);
 | 
			
		||||
 | 
			
		||||
								// Jump straight into deciding what steps to take next,
 | 
			
		||||
								// which will be selected dynamically.
 | 
			
		||||
@@ -2357,6 +2722,7 @@ struct ProcessorStorageConstructor {
 | 
			
		||||
								is_long_word_access = false;
 | 
			
		||||
 | 
			
		||||
								const int mode = combined_mode(ea_mode, ea_register);
 | 
			
		||||
								dumper.set_source(mode, ea_register);
 | 
			
		||||
								switch(mode) {
 | 
			
		||||
									default: continue;
 | 
			
		||||
 | 
			
		||||
@@ -2404,6 +2770,7 @@ struct ProcessorStorageConstructor {
 | 
			
		||||
							// calculation that might be a function of A7 needs to be done before PrepareJSR.
 | 
			
		||||
 | 
			
		||||
							const int mode = combined_mode(ea_mode, ea_register);
 | 
			
		||||
							dumper.set_source(mode, ea_register);
 | 
			
		||||
							switch(mode) {
 | 
			
		||||
								default: continue;
 | 
			
		||||
								case Ind:		// JSR (An)
 | 
			
		||||
@@ -2445,6 +2812,7 @@ struct ProcessorStorageConstructor {
 | 
			
		||||
						case Decoder::JMP: {
 | 
			
		||||
							program.set_source(storage_, ea_mode, ea_register);
 | 
			
		||||
							const int mode = combined_mode(ea_mode, ea_register);
 | 
			
		||||
							dumper.set_source(mode, ea_register);
 | 
			
		||||
							switch(mode) {
 | 
			
		||||
								default: continue;
 | 
			
		||||
								case Ind:		// JMP (An)
 | 
			
		||||
@@ -2478,6 +2846,7 @@ struct ProcessorStorageConstructor {
 | 
			
		||||
							program.set_destination(storage_, Imm, 7);	// Immediate destination => store to the destination bus latch.
 | 
			
		||||
 | 
			
		||||
							const int mode = combined_mode(ea_mode, ea_register);
 | 
			
		||||
							dumper.set_source(mode, ea_register);
 | 
			
		||||
							switch(mode) {
 | 
			
		||||
								default: continue;
 | 
			
		||||
 | 
			
		||||
@@ -2518,6 +2887,7 @@ struct ProcessorStorageConstructor {
 | 
			
		||||
									&storage_.address_[ea_register] :
 | 
			
		||||
									&storage_.effective_address_[0]);
 | 
			
		||||
 | 
			
		||||
							dumper.set_source_dest(mode, ea_register, An, data_register);
 | 
			
		||||
							switch(mode) {
 | 
			
		||||
								default: continue;
 | 
			
		||||
								case Ind:		// LEA (An), An		(i.e. MOVEA)
 | 
			
		||||
@@ -2549,6 +2919,7 @@ struct ProcessorStorageConstructor {
 | 
			
		||||
							is_long_word_access = false;
 | 
			
		||||
 | 
			
		||||
							const int mode = combined_mode(ea_mode, ea_register);
 | 
			
		||||
							dumper.set_source(mode, ea_register);
 | 
			
		||||
							switch(mode) {
 | 
			
		||||
								default: continue;
 | 
			
		||||
 | 
			
		||||
@@ -2593,6 +2964,7 @@ struct ProcessorStorageConstructor {
 | 
			
		||||
							/* DEVIATION FROM YACHT.TXT: it has all of these reading an extra word from the PC;
 | 
			
		||||
							this looks like a mistake so I've padded with nil cycles in the middle. */
 | 
			
		||||
							const int mode = combined_mode(ea_mode, ea_register);
 | 
			
		||||
							dumper.set_source(mode, ea_register);
 | 
			
		||||
							switch(mode) {
 | 
			
		||||
								default: continue;
 | 
			
		||||
 | 
			
		||||
@@ -2636,6 +3008,7 @@ struct ProcessorStorageConstructor {
 | 
			
		||||
						case Decoder::MOVEq: {
 | 
			
		||||
							program.set_destination(storage_, Dn, data_register);
 | 
			
		||||
							op(Action::PerformOperation, seq("np"));
 | 
			
		||||
							dumper.set_source_dest(Quick, 0, Dn, data_register);
 | 
			
		||||
						} break;
 | 
			
		||||
 | 
			
		||||
						case Decoder::MOVEP: {
 | 
			
		||||
@@ -2650,22 +3023,26 @@ struct ProcessorStorageConstructor {
 | 
			
		||||
								case Operation::MOVEPtoMw:
 | 
			
		||||
									op(Action::PerformOperation);
 | 
			
		||||
									op(int(Action::CalcD16An) | MicroOp::DestinationMask, seq("np nW+ nw np", { ea(1), ea(1) }, false));
 | 
			
		||||
									dumper.set_source_dest(Dn, data_register, d16An, ea_register);
 | 
			
		||||
								break;
 | 
			
		||||
 | 
			
		||||
								case Operation::MOVEPtoMl:
 | 
			
		||||
									op(Action::PerformOperation);
 | 
			
		||||
									op(int(Action::CalcD16An) | MicroOp::DestinationMask, seq("np nW+ nWr+ nw+ nwr np", { ea(1), ea(1), ea(1), ea(1) }, false));
 | 
			
		||||
									dumper.set_source_dest(Dn, data_register, d16An, ea_register);
 | 
			
		||||
								break;
 | 
			
		||||
 | 
			
		||||
								case Operation::MOVEPtoRw:
 | 
			
		||||
									op(int(Action::CalcD16An) | MicroOp::DestinationMask, seq("np nRd+ nrd np", { ea(1), ea(1) }, false));
 | 
			
		||||
									op(Action::PerformOperation);
 | 
			
		||||
									dumper.set_source_dest(d16An, ea_register, Dn, data_register);
 | 
			
		||||
								break;
 | 
			
		||||
 | 
			
		||||
								case Operation::MOVEPtoRl:
 | 
			
		||||
									// TODO: nR+ increments EA(0), not EA(1). Fix.
 | 
			
		||||
									op(int(Action::CalcD16An) | MicroOp::DestinationMask, seq("np nRd+ nR+ nrd+ nr np", { ea(1), ea(1), ea(1), ea(1) }, false));
 | 
			
		||||
									op(Action::PerformOperation);
 | 
			
		||||
									dumper.set_source_dest(d16An, ea_register, Dn, data_register);
 | 
			
		||||
								break;
 | 
			
		||||
							}
 | 
			
		||||
						} break;
 | 
			
		||||
@@ -2682,6 +3059,14 @@ struct ProcessorStorageConstructor {
 | 
			
		||||
							// Do whatever is necessary to calculate the proper start address.
 | 
			
		||||
							const int mode = combined_mode(ea_mode, ea_register);
 | 
			
		||||
							const bool is_to_m = (operation == Operation::MOVEMtoMl || operation == Operation::MOVEMtoMw);
 | 
			
		||||
 | 
			
		||||
							if(is_to_m) {
 | 
			
		||||
								dumper.set_source(Imm);
 | 
			
		||||
								dumper.set_dest(mode, ea_register);
 | 
			
		||||
							} else {
 | 
			
		||||
								dumper.set_source(mode, ea_register);
 | 
			
		||||
								dumper.set_dest(Imm);
 | 
			
		||||
							}
 | 
			
		||||
							switch(mode) {
 | 
			
		||||
								default: continue;
 | 
			
		||||
 | 
			
		||||
@@ -2717,6 +3102,7 @@ struct ProcessorStorageConstructor {
 | 
			
		||||
 | 
			
		||||
						case Decoder::MOVEUSP: {
 | 
			
		||||
							program.set_requires_supervisor(true);
 | 
			
		||||
							dumper.set_source(An, ea_register);
 | 
			
		||||
 | 
			
		||||
							// Observation here: because this is a privileged instruction, the user stack pointer
 | 
			
		||||
							// definitely isn't currently [copied into] A7.
 | 
			
		||||
@@ -2751,18 +3137,22 @@ struct ProcessorStorageConstructor {
 | 
			
		||||
									continue;
 | 
			
		||||
								}
 | 
			
		||||
								operation = is_long_word_access ? Operation::MOVEAl : Operation::MOVEAw;
 | 
			
		||||
								dumper.set_operation(operation);
 | 
			
		||||
							}
 | 
			
		||||
 | 
			
		||||
							// ... there are also no byte moves from address registers.
 | 
			
		||||
							if(ea_mode == An && is_byte_access) continue;
 | 
			
		||||
 | 
			
		||||
							// Perform the MOVE[A]'s fetch..
 | 
			
		||||
							const int combined_source_mode = combined_mode(ea_mode, ea_register, true);
 | 
			
		||||
							// Perform the MOVE[A]'s fetch...
 | 
			
		||||
							const int combined_source_mode = combined_mode(ea_mode, ea_register);
 | 
			
		||||
							dumper.set_source(combined_source_mode, ea_register);
 | 
			
		||||
							switch(is_long_word_access ? l(combined_source_mode) : bw(combined_source_mode)) {
 | 
			
		||||
								default: continue;
 | 
			
		||||
 | 
			
		||||
								case l(Dn):			// MOVE[A].l [An/Dn], <ea>
 | 
			
		||||
								case bw(Dn):		// MOVE[A].bw [An/Dn], <ea>
 | 
			
		||||
								case l(An):			// MOVE[A].l [An/Dn], <ea>
 | 
			
		||||
								case bw(An):		// MOVE[A].bw [An/Dn], <ea>
 | 
			
		||||
								break;
 | 
			
		||||
 | 
			
		||||
								case bw(PreDec):	// MOVE[A].bw -(An), <ea>
 | 
			
		||||
@@ -2826,6 +3216,9 @@ struct ProcessorStorageConstructor {
 | 
			
		||||
 | 
			
		||||
							// Perform the MOVE[A]'s store.
 | 
			
		||||
							const int combined_destination_mode = combined_mode(destination_mode, data_register, true);
 | 
			
		||||
							dumper.set_dest(
 | 
			
		||||
								(combined_destination_mode == Dn && destination_mode == An) ? An : combined_destination_mode,
 | 
			
		||||
								data_register);
 | 
			
		||||
							switch(is_long_word_access ? l(combined_destination_mode) : bw(combined_destination_mode)) {
 | 
			
		||||
								default: continue;
 | 
			
		||||
 | 
			
		||||
@@ -2923,6 +3316,7 @@ struct ProcessorStorageConstructor {
 | 
			
		||||
						break;
 | 
			
		||||
 | 
			
		||||
						case Decoder::TRAP: {
 | 
			
		||||
							dumper.set_source(Quick);
 | 
			
		||||
							// TRAP involves some oddly-sequenced stack writes, so is calculated
 | 
			
		||||
							// at runtime; also the same sequence is used for illegal instructions.
 | 
			
		||||
							// So the entirety is scheduled at runtime.
 | 
			
		||||
@@ -2941,6 +3335,7 @@ struct ProcessorStorageConstructor {
 | 
			
		||||
							program.set_source(storage_, ea_mode, ea_register);
 | 
			
		||||
 | 
			
		||||
							const int mode = combined_mode(ea_mode, ea_register);
 | 
			
		||||
							dumper.set_source_dest(mode, ea_register, Dn, data_register);
 | 
			
		||||
							switch(mode) {
 | 
			
		||||
								default: continue;
 | 
			
		||||
 | 
			
		||||
@@ -2985,6 +3380,7 @@ struct ProcessorStorageConstructor {
 | 
			
		||||
							program.set_source(storage_, ea_mode, ea_register);
 | 
			
		||||
 | 
			
		||||
							const int mode = combined_mode(ea_mode, ea_register);
 | 
			
		||||
							dumper.set_source(mode, ea_register);
 | 
			
		||||
							switch(is_long_word_access ? l(mode) : bw(mode)) {
 | 
			
		||||
								default: continue;
 | 
			
		||||
 | 
			
		||||
@@ -3086,12 +3482,12 @@ struct ProcessorStorageConstructor {
 | 
			
		||||
 | 
			
		||||
					// Don't search further through the list of possibilities, unless this is a debugging build,
 | 
			
		||||
					// in which case verify there are no double mappings.
 | 
			
		||||
#ifndef NDEBUG
 | 
			
		||||
					++hits;
 | 
			
		||||
					assert(hits == 1);
 | 
			
		||||
#else
 | 
			
		||||
//#ifndef NDEBUG
 | 
			
		||||
//					++hits;
 | 
			
		||||
//					assert(hits == 1);
 | 
			
		||||
//#else
 | 
			
		||||
					break;
 | 
			
		||||
#endif
 | 
			
		||||
//#endif
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user