1 /* Definitions and declarations to support the MIPS R3000 emulation. 2 Copyright 2001, 2003 Brian R. Gaeke. 3 4 This file is part of VMIPS. 5 6 VMIPS is free software; you can redistribute it and/or modify it 7 under the terms of the GNU General Public License as published by the 8 Free Software Foundation; either version 2 of the License, or (at your 9 option) any later version. 10 11 VMIPS is distributed in the hope that it will be useful, but 12 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 13 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 for more details. 15 16 You should have received a copy of the GNU General Public License along 17 with VMIPS; if not, write to the Free Software Foundation, Inc., 18 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ 19 20 #ifndef _CPU_H_ 21 #define _CPU_H_ 22 23 #include "deviceexc.h" 24 #include <cstdio> 25 #include <deque> 26 #include <map> 27 #include <vector> 28 class CPZero; 29 class FPU; 30 class Mapper; 31 class IntCtrl; 32 33 /* Exception priority information -- see exception_priority(). */ 34 struct excPriority { 35 int priority; 36 int excCode; 37 int mode; 38 }; 39 40 struct last_change { 41 uint32 pc; 42 uint32 instr; 43 uint32 old_value; last_changelast_change44 last_change () { } last_changelast_change45 last_change (uint32 pc_, uint32 instr_, uint32 old_value_) : 46 pc(pc_), instr(instr_), old_value(old_value_) { } makelast_change47 static last_change make (uint32 pc_, uint32 instr_, uint32 old_value_) { 48 last_change rv (pc_, instr_, old_value_); 49 return rv; 50 } 51 }; 52 53 class Trace { 54 public: 55 struct Operand { 56 const char *tag; 57 int regno; 58 uint32 val; OperandOperand59 Operand () : regno (-1) { } OperandOperand60 Operand (const char *tag_, int regno_, uint32 val_) : 61 tag(tag_), regno(regno_), val(val_) { } makeOperand62 static Operand make (const char *tag_, int regno_, uint32 val_) { 63 Operand rv (tag_, regno_, val_); 64 return rv; 65 } OperandOperand66 Operand (const char *tag_, uint32 val_) : 67 tag(tag_), regno(-1), val(val_) { } makeOperand68 static Operand make (const char *tag_, uint32 val_) { 69 Operand rv (tag_, val_); 70 return rv; 71 } 72 }; 73 struct Record { 74 typedef std::vector<Operand> OperandListType; 75 OperandListType inputs; 76 OperandListType outputs; 77 uint32 pc; 78 uint32 instr; 79 uint32 saved_reg[32]; inputs_push_back_opRecord80 void inputs_push_back_op (const char *tag, int regno, uint32 val) { 81 inputs.push_back(Operand::make(tag, regno, val)); 82 } inputs_push_back_opRecord83 void inputs_push_back_op (const char *tag, uint32 val) { 84 inputs.push_back(Operand::make(tag, val)); 85 } outputs_push_back_opRecord86 void outputs_push_back_op (const char *tag, int regno, uint32 val) { 87 outputs.push_back(Operand::make(tag, regno, val)); 88 } outputs_push_back_opRecord89 void outputs_push_back_op (const char *tag, uint32 val) { 90 outputs.push_back(Operand::make(tag, val)); 91 } clearRecord92 void clear () { inputs.clear (); outputs.clear (); pc = 0; instr = 0; } 93 }; 94 typedef std::deque<Record> RecordListType; 95 typedef RecordListType::iterator record_iterator; 96 private: 97 RecordListType records; 98 public: 99 std::map <int, last_change> last_change_for_reg; rbegin()100 record_iterator rbegin () { return records.begin (); } rend()101 record_iterator rend () { return records.end (); } clear()102 void clear () { records.clear (); last_change_for_reg.clear (); } record_size()103 size_t record_size () const { return records.size (); } pop_front_record()104 void pop_front_record () { records.pop_front (); } push_back_record(Trace::Record & r)105 void push_back_record (Trace::Record &r) { records.push_back (r); } 106 bool exception_happened; 107 int last_exception_code; 108 }; 109 110 class CPU : public DeviceExc { 111 // Tracing data. 112 bool tracing; 113 Trace current_trace; 114 Trace::Record current_trace_record; 115 FILE *traceout; 116 117 // Tracing support methods. 118 void open_trace_file (); 119 void close_trace_file (); 120 void start_tracing (); 121 void write_trace_to_file (); 122 void write_trace_instr_inputs (uint32 instr); 123 void write_trace_instr_outputs (uint32 instr); 124 void write_trace_record_1 (uint32 pc, uint32 instr); 125 void write_trace_record_2 (uint32 pc, uint32 instr); 126 void stop_tracing (); 127 128 // Important registers: 129 uint32 pc; // Program counter 130 uint32 reg[32]; // General-purpose registers 131 uint32 instr; // The current instruction 132 uint32 hi, lo; // Division and multiplication results 133 134 // Exception bookkeeping data. 135 uint32 last_epc; 136 int last_prio; 137 uint32 next_epc; 138 139 // Other components of the VMIPS machine. 140 Mapper *mem; 141 CPZero *cpzero; 142 FPU *fpu; 143 144 // Delay slot handling. 145 int delay_state; 146 uint32 delay_pc; 147 148 // Cached option values that we use in the CPU core. 149 bool opt_fpu; 150 bool opt_excmsg; 151 bool opt_reportirq; 152 bool opt_excpriomsg; 153 bool opt_haltbreak; 154 bool opt_haltibe; 155 bool opt_haltjrra; 156 bool opt_instdump; 157 bool opt_tracing; 158 uint32 opt_tracesize; 159 uint32 opt_tracestartpc; 160 uint32 opt_traceendpc; 161 bool opt_bigendian; // True if CPU in big endian mode. 162 163 // Miscellaneous shared code. 164 void control_transfer(uint32 new_pc); 165 void jump(uint32 instr, uint32 pc); 166 uint32 calc_jump_target(uint32 instr, uint32 pc); 167 uint32 calc_branch_target(uint32 instr, uint32 pc); 168 void mult64(uint32 *hi, uint32 *lo, uint32 n, uint32 m); 169 void mult64s(uint32 *hi, uint32 *lo, int32 n, int32 m); 170 void cop_unimpl (int coprocno, uint32 instr, uint32 pc); 171 172 // Unaligned load/store support. 173 uint32 lwr(uint32 regval, uint32 memval, uint8 offset); 174 uint32 lwl(uint32 regval, uint32 memval, uint8 offset); 175 uint32 swl(uint32 regval, uint32 memval, uint8 offset); 176 uint32 swr(uint32 regval, uint32 memval, uint8 offset); 177 178 // Emulation of specific instructions. 179 void funct_emulate(uint32 instr, uint32 pc); 180 void regimm_emulate(uint32 instr, uint32 pc); 181 void j_emulate(uint32 instr, uint32 pc); 182 void jal_emulate(uint32 instr, uint32 pc); 183 void beq_emulate(uint32 instr, uint32 pc); 184 void bne_emulate(uint32 instr, uint32 pc); 185 void blez_emulate(uint32 instr, uint32 pc); 186 void bgtz_emulate(uint32 instr, uint32 pc); 187 void addi_emulate(uint32 instr, uint32 pc); 188 void addiu_emulate(uint32 instr, uint32 pc); 189 void slti_emulate(uint32 instr, uint32 pc); 190 void sltiu_emulate(uint32 instr, uint32 pc); 191 void andi_emulate(uint32 instr, uint32 pc); 192 void ori_emulate(uint32 instr, uint32 pc); 193 void xori_emulate(uint32 instr, uint32 pc); 194 void lui_emulate(uint32 instr, uint32 pc); 195 void cpzero_emulate(uint32 instr, uint32 pc); 196 void cpone_emulate(uint32 instr, uint32 pc); 197 void cptwo_emulate(uint32 instr, uint32 pc); 198 void cpthree_emulate(uint32 instr, uint32 pc); 199 void lb_emulate(uint32 instr, uint32 pc); 200 void lh_emulate(uint32 instr, uint32 pc); 201 void lwl_emulate(uint32 instr, uint32 pc); 202 void lw_emulate(uint32 instr, uint32 pc); 203 void lbu_emulate(uint32 instr, uint32 pc); 204 void lhu_emulate(uint32 instr, uint32 pc); 205 void lwr_emulate(uint32 instr, uint32 pc); 206 void sb_emulate(uint32 instr, uint32 pc); 207 void sh_emulate(uint32 instr, uint32 pc); 208 void swl_emulate(uint32 instr, uint32 pc); 209 void sw_emulate(uint32 instr, uint32 pc); 210 void swr_emulate(uint32 instr, uint32 pc); 211 void lwc1_emulate(uint32 instr, uint32 pc); 212 void lwc2_emulate(uint32 instr, uint32 pc); 213 void lwc3_emulate(uint32 instr, uint32 pc); 214 void swc1_emulate(uint32 instr, uint32 pc); 215 void swc2_emulate(uint32 instr, uint32 pc); 216 void swc3_emulate(uint32 instr, uint32 pc); 217 void sll_emulate(uint32 instr, uint32 pc); 218 void srl_emulate(uint32 instr, uint32 pc); 219 void sra_emulate(uint32 instr, uint32 pc); 220 void sllv_emulate(uint32 instr, uint32 pc); 221 void srlv_emulate(uint32 instr, uint32 pc); 222 void srav_emulate(uint32 instr, uint32 pc); 223 void jr_emulate(uint32 instr, uint32 pc); 224 void jalr_emulate(uint32 instr, uint32 pc); 225 void syscall_emulate(uint32 instr, uint32 pc); 226 void break_emulate(uint32 instr, uint32 pc); 227 void mfhi_emulate(uint32 instr, uint32 pc); 228 void mthi_emulate(uint32 instr, uint32 pc); 229 void mflo_emulate(uint32 instr, uint32 pc); 230 void mtlo_emulate(uint32 instr, uint32 pc); 231 void mult_emulate(uint32 instr, uint32 pc); 232 void multu_emulate(uint32 instr, uint32 pc); 233 void div_emulate(uint32 instr, uint32 pc); 234 void divu_emulate(uint32 instr, uint32 pc); 235 void add_emulate(uint32 instr, uint32 pc); 236 void addu_emulate(uint32 instr, uint32 pc); 237 void sub_emulate(uint32 instr, uint32 pc); 238 void subu_emulate(uint32 instr, uint32 pc); 239 void and_emulate(uint32 instr, uint32 pc); 240 void or_emulate(uint32 instr, uint32 pc); 241 void xor_emulate(uint32 instr, uint32 pc); 242 void nor_emulate(uint32 instr, uint32 pc); 243 void slt_emulate(uint32 instr, uint32 pc); 244 void sltu_emulate(uint32 instr, uint32 pc); 245 void bltz_emulate(uint32 instr, uint32 pc); 246 void bgez_emulate(uint32 instr, uint32 pc); 247 void bltzal_emulate(uint32 instr, uint32 pc); 248 void bgezal_emulate(uint32 instr, uint32 pc); 249 void RI_emulate(uint32 instr, uint32 pc); 250 251 // Exception prioritization. 252 int exception_priority(uint16 excCode, int mode) const; 253 254 public: 255 // Instruction decoding. opcode(const uint32 i)256 static uint16 opcode(const uint32 i) { return (i >> 26) & 0x03f; } rs(const uint32 i)257 static uint16 rs(const uint32 i) { return (i >> 21) & 0x01f; } rt(const uint32 i)258 static uint16 rt(const uint32 i) { return (i >> 16) & 0x01f; } rd(const uint32 i)259 static uint16 rd(const uint32 i) { return (i >> 11) & 0x01f; } immed(const uint32 i)260 static uint16 immed(const uint32 i) { return i & 0x0ffff; } s_immed(const uint32 i)261 static short s_immed(const uint32 i) { return i & 0x0ffff; } shamt(const uint32 i)262 static uint16 shamt(const uint32 i) { return (i >> 6) & 0x01f; } funct(const uint32 i)263 static uint16 funct(const uint32 i) { return i & 0x03f; } jumptarg(const uint32 i)264 static uint32 jumptarg(const uint32 i) { return i & 0x03ffffff; } 265 266 // Constructor & destructor. 267 CPU (Mapper &m, IntCtrl &i); 268 virtual ~CPU (); 269 270 // For printing out the register file, stack, CP0 registers, and TLB 271 // per user request. 272 void dump_regs (FILE *f); 273 void dump_stack (FILE *f); 274 void dump_mem (FILE *f, uint32 addr); 275 void dis_mem (FILE *f, uint32 addr); 276 void cpzero_dump_regs_and_tlb (FILE *f); 277 278 // Register file accessors. get_reg(const unsigned regno)279 uint32 get_reg (const unsigned regno) { return reg[regno]; } put_reg(const unsigned regno,const uint32 new_data)280 void put_reg (const unsigned regno, const uint32 new_data) { 281 reg[regno] = new_data; 282 } 283 284 // Control-flow methods. 285 void step (); 286 void reset (); 287 288 // Methods which are only for use by the CPU and its coprocessors. 289 void branch (uint32 instr, uint32 pc); 290 void exception (uint16 excCode, int mode = ANY, int coprocno = -1); 291 292 // Public tracing support method. 293 void flush_trace (); 294 295 // Debugger interface support methods. 296 char *debug_registers_to_packet (); 297 void debug_packet_to_registers (char *packet); 298 uint8 pending_exception (); 299 uint32 debug_get_pc (); 300 void debug_set_pc (uint32 newpc); 301 void debug_packet_push_word (char *packet, uint32 n); 302 void debug_packet_push_byte (char *packet, uint8 n); 303 int debug_fetch_region (uint32 addr, uint32 len, char *packet, 304 DeviceExc *client); 305 int debug_store_region (uint32 addr, uint32 len, char *packet, 306 DeviceExc *client); 307 is_bigendian()308 bool is_bigendian() const { return opt_bigendian; } 309 }; 310 311 #endif /* _CPU_H_ */ 312