#include #include #include #include "emulator.h" #include "program_loader.h" #include "instruction.h" #include "program.h" #include "register_address.h" emulator::write::write( register_address addr, value * val) : m_addr(addr), m_val(val) { } emulator::emulator( program_loader * loader, int num_temp_regs, int num_const_regs, int num_out_regs, int num_input_regs) : m_loader(loader), m_temp_regs(num_temp_regs), m_const_regs(num_const_regs, new float_value()), m_out_regs(num_out_regs), m_input_regs(num_input_regs, new float_value()) { } bool emulator::run() { program * p = m_loader->load(); if (!p) { return false; } m_immediate_regs = p->m_immediate_regs; m_private_regs = std::vector(p->num_private_regs); std::vector::iterator it; for(it = p->m_instructions.begin(); it < p->m_instructions.end(); ++it) { (*it)->execute(*this); while (!m_write_queue.empty()) { write w = m_write_queue.front(); set_value(w.m_addr, w.m_val); m_write_queue.pop(); } } return true; } void emulator::set_constants(float value) { std::vector::iterator it; for(it = m_const_regs.begin(); it < m_const_regs.end(); ++it) { (*it)->set_value(value); } for(it = m_input_regs.begin(); it < m_input_regs.end(); ++it) { (*it)->set_value(value); } } value * emulator::get_value(register_address addr) { unsigned int index = addr.to_int(); switch(addr.m_type) { case REGISTER_TYPE_TEMP: if (index < m_temp_regs.size() && m_temp_regs[index]) { return m_temp_regs[index]->clone(); } else { /* The Temp register has never been written, which * means it is actually an input register */ return m_input_regs[index]->clone(); } break; case REGISTER_TYPE_CONST: return get_const_value(m_const_regs, index, addr); break; case REGISTER_TYPE_IN: return get_const_value(m_input_regs, index, addr); break; case REGISTER_TYPE_OUT: return m_out_regs[index]->clone(); case REGISTER_TYPE_IMMEDIATE: return m_immediate_regs[index]->clone(); case REGISTER_TYPE_PRIVATE: return m_private_regs[index]->clone(); case REGISTER_TYPE_NONE: return NULL; default: std::cerr << __FUNCTION__ << " unknown register type: " << addr.m_type << "\n"; return NULL; } } value * emulator::get_const_value( std::vector & registers, unsigned int index, register_address addr) { if (index >= registers.size()) { return NULL; } float_value * val = registers[index]; if (val->m_has_value) { return new float_value(*val); } else { return new const_value(addr, val); } } void emulator::set_value( register_address addr, value * val) { unsigned int index = addr.to_int(); switch(addr.m_type) { case REGISTER_TYPE_TEMP: set_value(m_temp_regs, index, val); break; case REGISTER_TYPE_OUT: set_value(m_out_regs, index, val); break; case REGISTER_TYPE_PRIVATE: /*In theory, these registers should only be written once. */ set_value(m_private_regs, index, val); break; case REGISTER_TYPE_NONE: /* Do nothing. */ break; default: assert(0); } } void emulator::set_value( std::vector & vector, unsigned int index, value * val) { if (index >= vector.size()) { std::cerr << __FUNCTION__ << ": Index out of bounds\n"; return; } delete vector[index]; vector[index] = val; } value * emulator::get_output_value(unsigned int index) { if (index >= m_out_regs.size() || !m_out_regs[index]) { return NULL; } return m_out_regs[index]->simplify(); } void emulator::queue_write( register_address addr, value * val) { m_write_queue.push(write(addr, val)); } void emulator::dump_regs() { dump_regs(m_temp_regs, REGISTER_TYPE_TEMP); dump_regs(m_const_regs, REGISTER_TYPE_CONST); dump_regs(m_out_regs, REGISTER_TYPE_OUT); dump_regs(m_private_regs, REGISTER_TYPE_PRIVATE); dump_regs(m_immediate_regs, REGISTER_TYPE_IMMEDIATE); dump_regs(m_input_regs, REGISTER_TYPE_IN); } void emulator::dump_regs( std::vector & registers, enum register_type type) { unsigned int i; for (i = 0; i < registers.size(); i++) { print_reg(type, i, registers[i]); } } void emulator::dump_regs( std::vector & registers, enum register_type type) { unsigned int i; for (i = 0; i < registers.size(); i++) { print_reg(type, i, registers[i]); } } void emulator::print_reg( enum register_type type, unsigned int index, value * val) { if (val) { fprintf(stderr, "%s=%s\n", register_address(type, index).to_string().c_str(), val->to_string().c_str()); } }