void Instruction::setArg2Mode(AccessMode mode) { if (type == InsType::DAT) throw instruction_error("Canot set source access mode for DAT type"); if((uint8_t)mode > 1) throw instruction_error("Invalid source access mode"); data &= 0xFEFF; // 1111 1110 1111 1111 data |= ((uint16_t)mode) << 8; }
void Instruction::setArg1Mode(AccessMode mode) { if (type == InsType::DAT) throw instruction_error("Canot set destination access mode for DAT type"); if((uint8_t)mode > 1) throw instruction_error("Invalid destination access mode"); data &= 0xFDFF; // 1111 1101 1111 1111 data |= ((uint16_t)mode) << 9; }
void Instruction::setOPCode(OPCode code) { if(type == InsType::DAT) throw instruction_error("Cannot set opcode for DAT type"); data &= 0x03FF; // 0000 0011 1111 1111 data |= ((uint16_t)code) << 10; }
OPCode Instruction::getOPCode() const { if(type == InsType::DAT) throw instruction_error("Cannot retrieve opcode from DAT type"); //16bits, the first 6 are what we want, so shift right 10, and then convert to //an unsigned value and cast to uint8_t return (OPCode)(data >> 10); }
void Instruction::setRoute(Location arg1, Location arg2) { if(type == InsType::DAT) throw instruction_error("Cannot set route for DAT type"); data &= 0xFF00; //1111 1111 0000 0000 data |= (uint16_t)routeToBinary(arg1, arg2); //update imd_count imd_count = 0; if(arg1 == Location::IMD || arg1 == Location::PIMD) ++imd_count; if(arg2 == Location::IMD || arg2 == Location::PIMD) ++imd_count; }
uint8_t Instruction::routeToBinary(Location arg1, Location arg2) { int8_t arg1v = Location_Vals.at(arg1).first; int8_t arg2v = Location_Vals.at(arg2).second; if(arg1v < -1) throw instruction_error("Invalid destination argument"); if(arg2v < -1) throw instruction_error("Invalid source argument"); uint8_t route = 0x00; if(arg1v == -1) { //special cases // currently no special cases } else route |= (uint8_t)arg1v; if(arg2v == -1) { //special cases //NONE is currently the only thing that qualifies // so leave arg2 as 0 since it does not matter } else if(arg2v == -2) {/* D o n o t h i n g*/} else route |= ((uint8_t)arg2v) << 4; return route; }
std::pair<Location, Location> Instruction::binaryToRoute(uint8_t binary) { std::pair<Location, Location> dstsrc(Location::NONE, Location::NONE); Location& arg1 = dstsrc.first; Location& arg2 = dstsrc.second; //Normal case int8_t arg1v = (int8_t)(binary & 0x0F); int8_t arg2v = (int8_t)(binary >> 4); //Find the destination and source, invalid if not found for(const auto& loc : Location_Vals) { if(loc.second.first == arg1v) arg1 = loc.first; if(loc.second.second == arg2v) arg2 = loc.first; } if(arg1 == Location::NONE && arg2 == Location::NONE) throw instruction_error("Invalid route " + std::bitset<8>(binary).to_string()); return dstsrc; }
void Instruction::write(FILE* fd) const { //while it would be faster to just go through all of them in one call, // there is a potential of the class being changed in a way which causes // problems uint16_t t = boost::endian::native_to_big(data); fwrite((void*)&t, 2, 1, fd); //don't need to do anything more if(type == InsType::DAT) return; if(imd_count > 2) throw instruction_error("Arg count cannot be greater than 2"); //make sure to write only what is actually relevent if(imd_count > 0) { t = boost::endian::native_to_big(imd1); fwrite((void*)&t, 2, 1, fd); } if(imd_count > 1) { t = boost::endian::native_to_big(imd2); fwrite((void*)&t, 2, 1, fd); } }
void emulate_debug(BOOL dis_TLCS900h, BOOL dis_Z80) { _u32 storePC = pc; debug_abort_memory = FALSE; debug_abort_instruction = FALSE; system_debug_history_add(); //For the debugger if (dis_TLCS900h) { char* s; //Disassemble TLCS-900h _u32 oldpc = pc; s = disassemble(); system_debug_message(s); system_debug_message_associate_address(oldpc); free(s); pc = oldpc; } if (dis_Z80) { //Disassemble Z80 if (Z80ACTIVE) { char* s; _u16 pc = Z80_getReg(Z80_REG_PC); _u16 store_pc = pc; //Disassemble s = Z80_disassemble(&pc); system_debug_message(s); system_debug_message_associate_address(store_pc + 0x7000); free(s); } } debug_abort_memory = FALSE; debug_abort_instruction = FALSE; //================== // EMULATE //================== { //TLCS900h instruction updateTimers(TLCS900h_interpret()); //Z80 Instruction if (Z80ACTIVE) Z80EMULATE; } //Check register code error if (rErr != RERR_VALUE) instruction_error("Invalid register code used."); //Memory Exception if (debug_abort_memory && filter_mem) { _u32 oldpc = pc; char* s; debug_abort_memory = FALSE; //Try to disassemble the erroneous instruction pc = storePC; debug_mask_memory_error_messages = TRUE; s = disassemble(); debug_mask_memory_error_messages = FALSE; if (debug_abort_memory == FALSE) { system_debug_message("Stopped due to memory exception caused by"); system_debug_message(" %s", s); system_debug_message_associate_address(storePC); system_debug_message("\n"); } else { system_debug_message("Stopped due to memory exception caused at %06X", storePC); system_debug_message_associate_address(storePC); } free(s); pc = oldpc; system_debug_stop(); system_debug_refresh(); return; } //Unimplemented Instruction if (debug_abort_instruction) { _u32 oldpc = pc; char* s; debug_abort_memory = FALSE; //Try to disassemble the erroneous instruction pc = storePC; debug_mask_memory_error_messages = TRUE; s = disassemble(); debug_mask_memory_error_messages = FALSE; if (debug_abort_memory == FALSE) { system_debug_message("Stopped due to instruction"); system_debug_message(" %s", s); system_debug_message_associate_address(storePC); system_debug_message("\n"); } else { system_debug_message("Stopped due to instruction at %06X", storePC); system_debug_message_associate_address(storePC); } free(s); pc = oldpc; system_debug_stop(); system_debug_refresh(); return; } }
void Instruction::setData(uint16_t d) { if(type != InsType::DAT) throw instruction_error("Data is specific to a DAT type value"); data = d; }
std::pair<Location, Location> Instruction::getRoute() const { if(type == InsType::DAT) throw instruction_error("Cannot get route for DAT type"); return binaryToRoute((uint8_t)(data & 0x00FF)); }
AccessMode Instruction::getArg2Mode() const { if(type == InsType::DAT) throw instruction_error("Cannot retrieve source access mode from type DAT type"); return (AccessMode)((data & 0x0100) >> 8); }
AccessMode Instruction::getArg1Mode() const { if(type == InsType::DAT) throw instruction_error("Cannot retrieve destination access mode from DAT type"); return (AccessMode)((data & 0x0200) >> 9); }