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