1 // sidcpuutil.h - Elements common to CPU models. -*- C++ -*-
3 // Copyright (C) 1999-2004 Red Hat.
4 // This file is part of SID and is licensed under the GPL.
5 // See the file COPYING.SID for conditions for redistribution.
10 #include <sidattrutil.h>
11 #include <sidpinutil.h>
12 #include <sidbusutil.h>
13 #include <sidcomputil.h>
14 #include <sidmiscutil.h>
15 #include <sidwatchutil.h>
16 #include <sidschedutil.h>
22 // kinds of endianness
31 std::ostream& operator << (std::ostream& o, const endian& e)
36 case endian_unknown: o << "unknown"; break;
37 case endian_big: o << "big"; break;
38 case endian_little: o << "little"; break;
45 std::istream& operator >> (std::istream& i, endian& e)
49 if (s == "unknown" || s == "0") { e = endian_unknown; }
50 else if (s == "big" || s == "1") { e = endian_big; }
51 else if (s == "little" || s == "2") { e = endian_little; }
52 else { i.setstate(std::ios::badbit); e = endian_unknown; }
56 // ------------------------------------------------------------------------
58 class cpu_exception {};
60 class cpu_memory_fault: public cpu_exception
64 sid::host_int_4 address;
65 sid::bus::status status;
66 const char* operation;
68 cpu_memory_fault (sid::host_int_4 p, sid::host_int_4 a, sid::bus::status s, const char* o):
69 pc(p), address(a), status(s), operation(o)
74 // ------------------------------------------------------------------------
77 // Values travelling through the trap-type pin.
78 // Additional "arguments" are sent through the trap-code pin.
80 cpu_trap_software = 1, // trap instruction hit
81 cpu_trap_breakpoint = 2, // breakpoint instruction hit
82 cpu_trap_syscall = 3, // system call instruction hit
83 cpu_trap_invalid_insn = 4, // invalid instruction hit
84 cpu_trap_memory_fault = 5, // memory fault encountered
85 cpu_trap_overflow = 6, // arithmetic overflow
86 cpu_trap_stepped = 7, // single-step completed
90 // Possible trap disposition codes
91 enum cpu_trap_disposition
93 cpu_trap_unhandled = 0, // dispatch to hardware fault handling
94 cpu_trap_handled = 1, // supervisor handled faulting instruction
95 cpu_trap_reissue = 2, // rerun faulting instruction
96 cpu_trap_skip = 3, // skip faulting instruction
100 // ------------------------------------------------------------------------
103 class basic_cpu: public virtual sid::component,
104 protected virtual fixed_pin_map_component,
105 protected virtual fixed_accessor_map_component,
106 protected virtual fixed_attribute_map_component,
107 protected virtual fixed_relation_map_component,
108 protected virtual fixed_bus_map_component
110 // custom memory allocators for poisioning freshly-allocated memory
112 void* operator new (size_t sz)
114 void* p = ::operator new (sz);
115 // Initialize the object with garbage, to ease detection of missing initialization.
117 char deadbeef[] = { 0xde, 0xad, 0xbe, 0xef };
118 for (unsigned i=0; i<sz; i++)
119 *q++ = deadbeef[i % 4];
122 void operator delete (void* p)
124 ::operator delete (p);
127 // recursion protection
129 recursion_limited step_limit;
131 // scheduler querying
133 friend class scheduler_time_query<basic_cpu>;
134 scheduler_time_query<basic_cpu> sched_query;
136 // triggerpoint support
138 friend class self_watcher<basic_cpu>;
139 self_watcher<basic_cpu> triggerpoint_manager;
140 // Virtual pin interfaces between self_watcher and fixed_pin_map_component
141 sid::component::status pin_factory (const std::string& name)
143 return this->triggerpoint_manager.create_virtual_pin (name);
145 void pin_junkyard (const std::string& name)
147 return this->triggerpoint_manager.destroy_virtual_pin (name);
149 // Helper functions for target view support
150 template <class PinType>
151 void add_watchable_pin (const std::string& name, PinType* pin)
153 this->add_pin (name, pin);
154 this->add_attribute (name, pin, "pin");
155 this->triggerpoint_manager.add_watchable_attribute (name);
156 this->categorize (name, "watchable");
159 template <class ValueType>
160 void add_watchable_register (const std::string& name, ValueType* value)
162 this->add_attribute (name, value, "register");
163 this->triggerpoint_manager.add_watchable_value (name, value);
164 this->categorize (name, "watchable");
167 template <class Class, typename Getter, typename Setter>
168 void add_watchable_register (const std::string& name,
173 this->add_attribute_virtual (name, receiver, getter, setter, "register");
174 this->triggerpoint_manager.add_watchable_attribute (name);
175 this->categorize (name, "watchable");
178 template <class Class, typename Getter, typename Setter, typename Parameter>
179 void add_watchable_register (const std::string& name,
185 this->add_attribute_virtual_parameterized (name, param, receiver,
186 getter, setter, "register");
187 this->triggerpoint_manager.add_watchable_attribute (name);
188 this->categorize (name, "watchable");
191 template <class ValueType>
192 void add_watchable_ro_register (const std::string& name, ValueType* value)
194 this->add_attribute_ro (name, value, "register");
195 this->triggerpoint_manager.add_watchable_attribute (name);
196 this->categorize (name, "watchable");
199 // step/yield control pins
201 callback_pin<basic_cpu> step_pin;
202 callback_pin<basic_cpu> yield_pin;
203 callback_pin<basic_cpu> print_insn_summary_pin;
205 sid::host_int_4 step_insn_count;
206 sid::host_int_8 total_insn_count;
207 mutable sid::host_int_8 total_latency;
208 sid::host_int_4 current_step_insn_count;
209 output_pin step_cycles_pin;
210 output_pin cg_caller_pin;
211 output_pin cg_callee_pin;
215 string trace_filename;
216 callback_pin<basic_cpu> trace_pin;
217 class cpu_trace_stream: public std::ofstream
222 cpu_trace_stream (const std::string& filename)
223 :std::ofstream (filename.c_str ()), cout_p (false) {}
224 void divert_to_file () { cout_p = false; }
225 void divert_to_cout () { cout_p = true; }
226 void open (const std::string& filename)
228 std::ofstream::open (filename.c_str (), std::ios::app);
234 std::cout << std::endl;
241 template <typename T> friend
242 basic_cpu::cpu_trace_stream& operator<< (basic_cpu::cpu_trace_stream& s, T t);
245 template <typename T> friend
246 cpu_trace_stream& operator<< (cpu_trace_stream& s, T t);
248 void trace_pin_handler (sid::host_int_4 value)
250 trace_stream << static_cast<char> (value);
254 bool trace_extract_p;
257 bool trace_semantics_p;
258 bool trace_counter_p;
259 bool final_insn_count_p;
260 bool enable_step_trap_p;
261 cpu_trace_stream trace_stream;
263 virtual void step_pin_handler (sid::host_int_4)
265 recursion_record limit (& this->step_limit);
266 if (UNLIKELY(! limit.ok())) return;
268 this->current_step_insn_count = 0;
269 this->yield_p = false;
271 // Check for triggerpoints due right now; may set yield_p!
272 this->triggerpoint_manager.check_and_dispatch ();
274 // Enter insn loop. Poll continue_after_insn_p after each instruction
275 sid::host_int_8 prev_latency = this->total_latency;
276 sid::host_int_8 prev_insn_count = this->total_insn_count;
279 sid::host_int_8 num_insns = this->total_insn_count - prev_insn_count;
280 sid::host_int_8 latency = this->total_latency - prev_latency;
283 const sid::host_int_4 min_num_cycles = 1;
284 const sid::host_int_4 max_num_cycles = 0x7FFFFFFF;
285 sid::host_int_8 insn_cycles = num_insns + latency_to_cycles (latency);
286 sid::host_int_4 num_cycles =
287 insn_cycles <= min_num_cycles ? min_num_cycles :
288 insn_cycles >= max_num_cycles ? max_num_cycles :
290 this->stepped (num_cycles);
294 this->yield_p = true;
295 // A subsequent continue_after_insns_p should return false.
297 void yield_pin_handler (sid::host_int_4)
301 virtual void print_insn_summary (sid::host_int_4)
303 std::cerr << "instruction count: " << this->total_insn_count << " "
304 << "simulated cycles: " << this->total_latency + this->total_insn_count << std::endl;
306 virtual void stepped (sid::host_int_4 n)
308 this->step_cycles_pin.drive (n);
310 void cg_profile (sid::host_int_4 caller, sid::host_int_4 callee)
312 // The drive sequence is important: see sw-profile-gprof
313 this->cg_caller_pin.drive (caller);
314 this->cg_callee_pin.drive (callee);
316 if (UNLIKELY(this->trace_result_p))
318 this->trace_stream << "cg-profile "
319 << make_numeric_attribute (caller,
320 std::ios::hex|std::ios::showbase)
322 << make_numeric_attribute (callee,
323 std::ios::hex|std::ios::showbase)
329 void set_total_latency (sid::host_int_8 latency) { this->total_latency = latency; }
330 void update_total_latency (sid::host_int_8 latency) { this->total_latency += latency; }
331 sid::host_int_8 get_total_latency () const { return this->total_latency; }
334 virtual sid::host_int_8 latency_to_cycles (sid::host_int_8 num)
336 // Identity relationship: 1 latency unit = 1 cycle.
340 virtual void step_insns () = 0;
341 bool stop_after_insns_p (sid::host_int_4 num)
343 this->current_step_insn_count += num;
344 if (UNLIKELY(this->yield_p ||
345 (this->current_step_insn_count >= this->step_insn_count)))
347 // Batch updates to total_insn_count to avoid long-long
348 // arithmetic overhead in the inner insn-stepping loops.
349 this->total_insn_count += this->current_step_insn_count;
350 this->current_step_insn_count = 0;
360 update_trace_destination ()
362 if (trace_filename == "-")
363 trace_stream.divert_to_cout ();
366 trace_stream.close ();
367 trace_stream.open (trace_filename);
368 trace_stream << "start of trace" << std::endl;
369 if (trace_stream.good ())
370 trace_stream.divert_to_file ();
372 trace_filename = "io-error!";
376 // Infer a change to trace_result_p after one of the other general
377 // trace flags are changed.
379 update_trace_result_p ()
381 this->trace_result_p = (this->trace_semantics_p || this->trace_disass_p);
385 // Reset the processor model to power-up state.
387 callback_pin<basic_cpu> reset_pin;
388 virtual void reset () = 0;
389 void reset_pin_handler(sid::host_int_4 v) { this->reset (); this->stepped(1); }
391 // Flush internal abstract icache (if any)
393 callback_pin<basic_cpu> flush_icache_pin;
394 void flush_icache_pin_handler(sid::host_int_4 v) { this->flush_icache(); }
396 virtual void flush_icache () = 0;
397 virtual void flush_icache (sid::host_int_4 pc) { this->flush_icache (); }
399 // Set the initial PC after reset
401 callback_pin<basic_cpu> pc_set_pin;
402 virtual void set_pc(sid::host_int_4) = 0;
403 void pc_set_pin_handler(sid::host_int_4 v) { this->set_pc (v); }
405 // Set the initial endianness after reset
407 callback_pin<basic_cpu> endian_set_pin;
408 virtual void set_endian(sid::host_int_4) = 0;
409 void endian_set_pin_handler(sid::host_int_4 v) { this->set_endian (v); }
410 callback_pin<basic_cpu> eflags_set_pin;
411 virtual void set_eflags(sid::host_int_4) {}
412 void eflags_set_pin_handler(sid::host_int_4 v) { this->set_eflags (v); }
414 // Signal trap type code and argument
416 output_pin trap_type_pin;
417 output_pin trap_code_pin;
418 input_pin trap_disposition_pin;
420 cpu_trap_disposition signal_trap (cpu_trap_type p, sid::host_int_4 param = 0)
422 // Prepare disposition pin in case we get no signal back
423 this->trap_disposition_pin.driven (sid::host_int_4(cpu_trap_unhandled));
424 this->trap_code_pin.drive (param);
425 this->trap_type_pin.drive (sid::host_int_4(p));
426 return static_cast<cpu_trap_disposition>(trap_disposition_pin.sense ());
430 // state save/restore: Override these in derived classes, but
431 // include a call up to this base implementation.
433 virtual void stream_state(std::ostream& o) const
437 << " " << this->step_insn_count
438 << " " << this->enable_step_trap_p
439 << " " << this->total_insn_count
440 << " " << this->total_latency
441 << " " << this->trace_extract_p
442 << " " << this->trace_result_p
443 << " " << this->trace_disass_p
444 << " " << this->trace_semantics_p
445 << " " << this->trace_counter_p
446 << " " << this->final_insn_count_p
448 << " " << this->step_cycles_pin
449 << " " << this->trap_type_pin
450 << " " << this->trap_code_pin;
453 virtual void destream_state(std::istream& i)
457 if (key != "basic-cpu")
459 i.setstate (std::ios::badbit);
462 i >> this->step_insn_count
463 >> this->enable_step_trap_p
464 >> this->total_insn_count
465 >> this->total_latency
466 >> this->trace_extract_p
467 >> this->trace_result_p
468 >> this->trace_disass_p
469 >> this->trace_semantics_p
470 >> this->trace_counter_p
471 >> this->final_insn_count_p
473 >> this->step_cycles_pin
474 >> this->trap_type_pin
475 >> this->trap_code_pin;
480 friend std::ostream& operator << (std::ostream& o, const basic_cpu& c);
481 friend std::istream& operator >> (std::istream& i, basic_cpu& c);
482 std::string save_state() { return make_attribute(*this); }
483 sid::component::status restore_state(const std::string& s)
484 { return parse_attribute(s, *this); }
487 // ------------------------------------------------------------------------
488 // debugger access functions
490 passthrough_bus debugger_bus;
491 virtual std::string dbg_get_reg (sid::host_int_4 n) = 0;
492 virtual sid::component::status dbg_set_reg (sid::host_int_4 n, const std::string& s) = 0;
495 template <typename PC>
496 void create_gdb_register_attrs (sid::host_int_4 count,
497 const std::string& expedited_regno_list,
500 this->add_watchable_register ("gdb-register-pc", pc);
501 this->add_attribute_ro_value ("gdb-num-registers", count, "debugger");
503 // The "expedited" register list string is the semi-colon-delimited list of
504 // register numbers that should be sent to gdb immediately
505 // every time sid stops, rather than let gdb ask for it
506 // subsequently. Usually, the PC, frame and stack pointer,
507 // and status register should be included in the list. It
508 // makes gdb step operations much faster.
509 // The register numbering scheme is that decided by gdb.
511 this->add_attribute_ro_value ("gdb-exp-registers", expedited_regno_list, "debugger");
512 for (sid::host_int_4 i=0; i<count; i++)
514 std::string name = std::string ("gdb-register-") + make_numeric_attribute (i);
515 attribute_coder_base* coder =
516 new attribute_coder_virtual_parameterized<basic_cpu,sid::host_int_4>
517 (this, & basic_cpu::dbg_get_reg, & basic_cpu::dbg_set_reg, i);
518 this->add_attribute_coder (name, coder, "debugger");
523 // ------------------------------------------------------------------------
524 // memory access functions
529 sid::bus* disassembler_bus;
532 template <typename BigOrLittleInt>
533 BigOrLittleInt read_insn_memory (sid::host_int_4 pc, sid::host_int_4 address, BigOrLittleInt);
534 template <typename BigOrLittleInt>
535 BigOrLittleInt write_insn_memory (sid::host_int_4 pc, sid::host_int_4 address, BigOrLittleInt value);
536 template <typename BigOrLittleInt>
537 BigOrLittleInt read_data_memory (sid::host_int_4 pc, sid::host_int_4 address, BigOrLittleInt);
538 template <typename BigOrLittleInt>
539 BigOrLittleInt write_data_memory (sid::host_int_4 pc, sid::host_int_4 address, BigOrLittleInt value);
541 virtual bool handle_insn_memory_read_error (sid::bus::status s, sid::host_int_4 & address) { return false; }
542 virtual bool handle_insn_memory_write_error (sid::bus::status s, sid::host_int_4 & address) { return false; }
543 virtual bool handle_data_memory_read_error (sid::bus::status s, sid::host_int_4 & address) { return false; }
544 virtual bool handle_data_memory_write_error (sid::bus::status s, sid::host_int_4 & address) { return false; }
546 virtual void record_insn_memory_read_latency (sid::bus::status s) { total_latency += s.latency; }
547 virtual void record_insn_memory_write_latency (sid::bus::status s) { total_latency += s.latency; }
548 virtual void record_data_memory_read_latency (sid::bus::status s) { total_latency += s.latency; }
549 virtual void record_data_memory_write_latency (sid::bus::status s) { total_latency += s.latency; }
551 // ------------------------------------------------------------------------
556 step_limit ("instruction stepping", 1),
558 triggerpoint_manager (this),
559 step_pin (this, & basic_cpu::step_pin_handler),
560 yield_pin (this, & basic_cpu::yield_pin_handler),
561 reset_pin (this, & basic_cpu::reset_pin_handler),
562 print_insn_summary_pin (this, & basic_cpu::print_insn_summary),
563 flush_icache_pin (this, & basic_cpu::flush_icache_pin_handler),
564 pc_set_pin (this, & basic_cpu::pc_set_pin_handler),
565 endian_set_pin (this, & basic_cpu::endian_set_pin_handler),
566 eflags_set_pin (this, & basic_cpu::eflags_set_pin_handler),
567 debugger_bus (& this->data_bus),
569 trace_filename ("-"), // standard output
570 trace_pin (this, & basic_cpu::trace_pin_handler)
574 add_accessor ("data-memory", & this->data_bus);
576 add_accessor ("insn-memory", & this->insn_bus);
577 this->disassembler_bus = 0;
578 add_accessor ("disassembler-memory", & this->disassembler_bus);
579 add_bus ("debugger-bus", & this->debugger_bus);
582 add_pin ("step!", & this->step_pin);
583 add_watchable_pin ("step-cycles", & this->step_cycles_pin);
584 add_pin ("flush-icache", & this->flush_icache_pin);
585 add_pin ("reset!", & this->reset_pin);
586 add_pin ("yield", & this->yield_pin);
587 add_pin ("start-pc-set!", & this->pc_set_pin);
588 add_pin ("cg-caller", & this->cg_caller_pin);
589 add_pin ("cg-callee", & this->cg_callee_pin);
590 add_pin ("print-insn-summary!", & this->print_insn_summary_pin);
591 add_pin ("endian-set!", & this->endian_set_pin);
592 add_pin ("eflags-set!", & this->eflags_set_pin);
593 add_watchable_pin ("trap", & this->trap_type_pin); // output side
594 add_watchable_pin ("trap-code", & this->trap_code_pin);
595 add_pin ("trap", & this->trap_disposition_pin); // input side
596 add_pin ("trace", & this->trace_pin);
599 this->step_insn_count = 1;
600 add_attribute ("step-insn-count", & this->step_insn_count, "setting");
601 this->enable_step_trap_p = false;
602 add_attribute ("enable-step-trap?", & this->enable_step_trap_p, "setting");
603 this->total_insn_count = 0;
604 add_watchable_register ("insn-count", & this->total_insn_count);
605 add_attribute_virtual ("state-snapshot", this,
606 & basic_cpu::save_state,
607 & basic_cpu::restore_state);
608 add_attribute_notify ("trace-filename", & this->trace_filename, this,
609 & basic_cpu::update_trace_destination,
611 this->trace_extract_p = false;
612 add_attribute ("trace-extract?", & trace_extract_p, "setting");
613 this->trace_semantics_p = false;
614 add_attribute_notify ("trace-semantics?", & this->trace_semantics_p, this,
615 & basic_cpu::update_trace_result_p,
617 this->trace_disass_p = false;
618 add_attribute_notify ("trace-disassemble?", & this->trace_disass_p, this,
619 & basic_cpu::update_trace_result_p,
621 // `trace-result?' should go away after all simulators are updated to
622 // use `trace-semantics?'.
623 this->trace_result_p = false;
624 add_attribute ("trace-result?", & this->trace_result_p, "setting");
625 this->trace_counter_p = false;
626 add_attribute ("trace-counter?", & this->trace_counter_p, "setting");
627 this->final_insn_count_p = false;
628 add_attribute ("final-insn-count?", & this->final_insn_count_p, "setting");
631 virtual ~basic_cpu() throw() {}
635 inline std::ostream& operator << (std::ostream& o, const basic_cpu& c) {
639 inline std::istream& operator >> (std::istream& i, basic_cpu& c) {
640 c.destream_state (i);
644 template <typename T>
645 basic_cpu::cpu_trace_stream& operator<< (basic_cpu::cpu_trace_stream& s, T t)
647 if (LIKELY (s.cout_p))
650 static_cast <std::ofstream&> (s) << t;
654 template <typename BigOrLittleInt>
655 BigOrLittleInt basic_cpu::read_insn_memory (sid::host_int_4 pc, sid::host_int_4 address, BigOrLittleInt)
660 BigOrLittleInt value;
661 if (LIKELY(this->insn_bus))
663 s = this->insn_bus->read (address, value);
664 if (LIKELY(s == sid::bus::ok))
666 if (UNLIKELY ((trace_counter_p || final_insn_count_p) && s.latency))
667 record_insn_memory_read_latency (s);
672 s = sid::bus::unmapped;
674 while (UNLIKELY (handle_insn_memory_read_error (s, address)));
676 throw cpu_memory_fault (pc, address, s, "insn read");
679 template <typename BigOrLittleInt>
680 BigOrLittleInt basic_cpu::write_insn_memory (sid::host_int_4 pc, sid::host_int_4 address, BigOrLittleInt value)
685 if (LIKELY(this->insn_bus))
687 s = this->insn_bus->write (address, value);
688 if (LIKELY(s == sid::bus::ok))
690 if (UNLIKELY ((trace_counter_p || final_insn_count_p) && s.latency))
691 record_insn_memory_write_latency (s);
696 s = sid::bus::unmapped;
698 while (UNLIKELY (handle_insn_memory_read_error (s, address)));
700 throw cpu_memory_fault (pc, address, s, "insn write");
703 template <typename BigOrLittleInt>
704 BigOrLittleInt basic_cpu::read_data_memory (sid::host_int_4 pc, sid::host_int_4 address, BigOrLittleInt)
709 BigOrLittleInt value;
710 if (LIKELY(this->data_bus))
712 s = this->data_bus->read (address, value);
713 if (LIKELY(s == sid::bus::ok))
715 if (UNLIKELY ((trace_counter_p || final_insn_count_p) && s.latency))
716 record_data_memory_read_latency (s);
721 s = sid::bus::unmapped;
723 while (UNLIKELY (handle_insn_memory_read_error (s, address)));
725 throw cpu_memory_fault (pc, address, s, "data read");
728 template <typename BigOrLittleInt>
729 BigOrLittleInt basic_cpu::write_data_memory (sid::host_int_4 pc, sid::host_int_4 address, BigOrLittleInt value)
734 if (LIKELY(this->data_bus))
736 s = this->data_bus->write (address, value);
737 if (LIKELY(s == sid::bus::ok))
739 if (UNLIKELY ((trace_counter_p || final_insn_count_p) && s.latency))
740 record_data_memory_write_latency (s);
745 s = sid::bus::unmapped;
747 while (UNLIKELY (handle_insn_memory_read_error (s, address)));
749 throw cpu_memory_fault (pc, address, s, "data write");
754 // ------------------------------------------------------------------------
755 // Derived classes for memory access functions of various endianness
757 class basic_big_endian_cpu: public basic_cpu
759 void set_endian(sid::host_int_4) {}
760 void set_eflags(sid::host_int_4) {}
764 basic_big_endian_cpu ()
766 add_attribute_ro_value ("endian", endian_big, "register");
768 ~basic_big_endian_cpu () throw() {}
770 sid::host_int_1 read_insn_memory_1 (sid::host_int_4 pc, sid::host_int_4 address)
772 return this->read_insn_memory (pc, address, sid::big_int_1());
775 sid::host_int_2 read_insn_memory_2 (sid::host_int_4 pc, sid::host_int_4 address)
777 return this->read_insn_memory (pc, address, sid::big_int_2());
780 sid::host_int_4 read_insn_memory_4 (sid::host_int_4 pc, sid::host_int_4 address)
782 return this->read_insn_memory (pc, address, sid::big_int_4());
785 sid::host_int_8 read_insn_memory_8 (sid::host_int_4 pc, sid::host_int_4 address)
787 return this->read_insn_memory (pc, address, sid::big_int_8());
790 void write_insn_memory_1 (sid::host_int_4 pc, sid::host_int_4 address, sid::host_int_1 value)
792 this->write_insn_memory (pc, address, sid::big_int_1(value));
795 void write_insn_memory_2 (sid::host_int_4 pc, sid::host_int_4 address, sid::host_int_2 value)
797 this->write_insn_memory (pc, address, sid::big_int_2(value));
800 void write_insn_memory_4 (sid::host_int_4 pc, sid::host_int_4 address, sid::host_int_4 value)
802 this->write_insn_memory (pc, address, sid::big_int_4(value));
805 void write_insn_memory_8 (sid::host_int_4 pc, sid::host_int_4 address, sid::host_int_8 value)
807 this->write_insn_memory (pc, address, sid::big_int_8(value));
810 sid::host_int_1 read_data_memory_1 (sid::host_int_4 pc, sid::host_int_4 address)
812 return this->read_data_memory (pc, address, sid::big_int_1());
815 sid::host_int_2 read_data_memory_2 (sid::host_int_4 pc, sid::host_int_4 address)
817 return this->read_data_memory (pc, address, sid::big_int_2());
820 sid::host_int_4 read_data_memory_4 (sid::host_int_4 pc, sid::host_int_4 address)
822 return this->read_data_memory (pc, address, sid::big_int_4());
825 sid::host_int_8 read_data_memory_8 (sid::host_int_4 pc, sid::host_int_4 address)
827 return this->read_data_memory (pc, address, sid::big_int_8());
830 void write_data_memory_1 (sid::host_int_4 pc, sid::host_int_4 address, sid::host_int_1 value)
832 this->write_data_memory (pc, address, sid::big_int_1(value));
835 void write_data_memory_2 (sid::host_int_4 pc, sid::host_int_4 address, sid::host_int_2 value)
837 this->write_data_memory (pc, address, sid::big_int_2(value));
840 void write_data_memory_4 (sid::host_int_4 pc, sid::host_int_4 address, sid::host_int_4 value)
842 this->write_data_memory (pc, address, sid::big_int_4(value));
845 void write_data_memory_8 (sid::host_int_4 pc, sid::host_int_4 address, sid::host_int_8 value)
847 this->write_data_memory (pc, address, sid::big_int_8(value));
852 // ----------------------------------------------------------------------------
854 class basic_little_endian_cpu: public basic_cpu
856 void set_endian(sid::host_int_4) {}
857 void set_eflags(sid::host_int_4) {}
860 basic_little_endian_cpu ()
862 add_attribute_ro_value ("endian", endian_little, "register");
864 ~basic_little_endian_cpu () throw() {}
866 sid::host_int_1 read_insn_memory_1 (sid::host_int_4 pc, sid::host_int_4 address)
868 return this->read_insn_memory (pc, address, sid::little_int_1());
871 sid::host_int_2 read_insn_memory_2 (sid::host_int_4 pc, sid::host_int_4 address)
873 return this->read_insn_memory (pc, address, sid::little_int_2());
876 sid::host_int_4 read_insn_memory_4 (sid::host_int_4 pc, sid::host_int_4 address)
878 return this->read_insn_memory (pc, address, sid::little_int_4());
881 sid::host_int_8 read_insn_memory_8 (sid::host_int_4 pc, sid::host_int_4 address)
883 return this->read_insn_memory (pc, address, sid::little_int_8());
886 void write_insn_memory_1 (sid::host_int_4 pc, sid::host_int_4 address, sid::host_int_1 value)
888 this->write_insn_memory (pc, address, sid::little_int_1(value));
891 void write_insn_memory_2 (sid::host_int_4 pc, sid::host_int_4 address, sid::host_int_2 value)
893 this->write_insn_memory (pc, address, sid::little_int_2(value));
896 void write_insn_memory_4 (sid::host_int_4 pc, sid::host_int_4 address, sid::host_int_4 value)
898 this->write_insn_memory (pc, address, sid::little_int_4(value));
901 void write_insn_memory_8 (sid::host_int_4 pc, sid::host_int_4 address, sid::host_int_8 value)
903 this->write_insn_memory (pc, address, sid::little_int_8(value));
906 sid::host_int_1 read_data_memory_1 (sid::host_int_4 pc, sid::host_int_4 address)
908 return this->read_data_memory (pc, address, sid::little_int_1());
911 sid::host_int_2 read_data_memory_2 (sid::host_int_4 pc, sid::host_int_4 address)
913 return this->read_data_memory (pc, address, sid::little_int_2());
916 sid::host_int_4 read_data_memory_4 (sid::host_int_4 pc, sid::host_int_4 address)
918 return this->read_data_memory (pc, address, sid::little_int_4());
921 sid::host_int_8 read_data_memory_8 (sid::host_int_4 pc, sid::host_int_4 address)
923 return this->read_data_memory (pc, address, sid::little_int_8());
926 void write_data_memory_1 (sid::host_int_4 pc, sid::host_int_4 address, sid::host_int_1 value)
928 this->write_data_memory (pc, address, sid::little_int_1(value));
931 void write_data_memory_2 (sid::host_int_4 pc, sid::host_int_4 address, sid::host_int_2 value)
933 this->write_data_memory (pc, address, sid::little_int_2(value));
936 void write_data_memory_4 (sid::host_int_4 pc, sid::host_int_4 address, sid::host_int_4 value)
938 this->write_data_memory (pc, address, sid::little_int_4(value));
941 void write_data_memory_8 (sid::host_int_4 pc, sid::host_int_4 address, sid::host_int_8 value)
943 this->write_data_memory (pc, address, sid::little_int_8(value));
948 // ----------------------------------------------------------------------------
951 class basic_bi_endian_cpu: public basic_cpu
953 endian _current_endianness;
955 endian current_endianness() const { return this->_current_endianness; }
958 basic_bi_endian_cpu ()
960 this->_current_endianness = endian_big;
961 add_attribute ("endian", & this->_current_endianness, "register");
963 ~basic_bi_endian_cpu () throw() {}
965 void set_endian(sid::host_int_4 v)
970 this->_current_endianness = endian_big;
973 this->_current_endianness = endian_little;
976 // XXX: warning message?
981 void stream_state(std::ostream& o) const
983 basic_cpu::stream_state(o);
984 o << " " << this->_current_endianness;
987 void destream_state(std::istream& i)
989 basic_cpu::destream_state(i);
990 i >> this->_current_endianness;
994 sid::host_int_1 read_insn_memory_1 (sid::host_int_4 pc, sid::host_int_4 address)
996 if (this->_current_endianness == endian_little)
997 return this->read_insn_memory (pc, address, sid::little_int_1());
998 else // endian_big or endian_unknown
999 return this->read_insn_memory (pc, address, sid::big_int_1());
1002 sid::host_int_2 read_insn_memory_2 (sid::host_int_4 pc, sid::host_int_4 address)
1004 if (this->_current_endianness == endian_little)
1005 return this->read_insn_memory (pc, address, sid::little_int_2());
1006 else // endian_big or endian_unknown
1007 return this->read_insn_memory (pc, address, sid::big_int_2());
1010 sid::host_int_4 read_insn_memory_4 (sid::host_int_4 pc, sid::host_int_4 address)
1012 if (this->_current_endianness == endian_little)
1013 return this->read_insn_memory (pc, address, sid::little_int_4());
1014 else // endian_big or endian_unknown
1015 return this->read_insn_memory (pc, address, sid::big_int_4());
1018 sid::host_int_8 read_insn_memory_8 (sid::host_int_4 pc, sid::host_int_4 address)
1020 if (this->_current_endianness == endian_little)
1021 return this->read_insn_memory (pc, address, sid::little_int_8());
1022 else // endian_big or endian_unknown
1023 return this->read_insn_memory (pc, address, sid::big_int_8());
1026 void write_insn_memory_1 (sid::host_int_4 pc, sid::host_int_4 address, sid::host_int_1 value)
1028 if (this->_current_endianness == endian_little)
1029 this->write_insn_memory (pc, address, sid::little_int_1(value));
1030 else // endian_big or endian_unknown
1031 this->write_insn_memory (pc, address, sid::big_int_1(value));
1034 void write_insn_memory_2 (sid::host_int_4 pc, sid::host_int_4 address, sid::host_int_2 value)
1036 if (this->_current_endianness == endian_little)
1037 this->write_insn_memory (pc, address, sid::little_int_2(value));
1038 else // endian_big or endian_unknown
1039 this->write_insn_memory (pc, address, sid::big_int_2(value));
1042 void write_insn_memory_4 (sid::host_int_4 pc, sid::host_int_4 address, sid::host_int_4 value)
1044 if (this->_current_endianness == endian_little)
1045 this->write_insn_memory (pc, address, sid::little_int_4(value));
1046 else // endian_big or endian_unknown
1047 this->write_insn_memory (pc, address, sid::big_int_4(value));
1050 void write_insn_memory_8 (sid::host_int_4 pc, sid::host_int_4 address, sid::host_int_8 value)
1052 if (this->_current_endianness == endian_little)
1053 this->write_insn_memory (pc, address, sid::little_int_8(value));
1054 else // endian_big or endian_unknown
1055 this->write_insn_memory (pc, address, sid::big_int_8(value));
1058 sid::host_int_1 read_data_memory_1 (sid::host_int_4 pc, sid::host_int_4 address)
1060 if (this->_current_endianness == endian_little)
1061 return this->read_data_memory (pc, address, sid::little_int_1());
1062 else // endian_big or endian_unknown
1063 return this->read_data_memory (pc, address, sid::big_int_1());
1066 sid::host_int_2 read_data_memory_2 (sid::host_int_4 pc, sid::host_int_4 address)
1068 if (this->_current_endianness == endian_little)
1069 return this->read_data_memory (pc, address, sid::little_int_2());
1070 else // endian_big or endian_unknown
1071 return this->read_data_memory (pc, address, sid::big_int_2());
1074 sid::host_int_4 read_data_memory_4 (sid::host_int_4 pc, sid::host_int_4 address)
1076 if (this->_current_endianness == endian_little)
1077 return this->read_data_memory (pc, address, sid::little_int_4());
1078 else // endian_big or endian_unknown
1079 return this->read_data_memory (pc, address, sid::big_int_4());
1082 sid::host_int_8 read_data_memory_8 (sid::host_int_4 pc, sid::host_int_4 address)
1084 if (this->_current_endianness == endian_little)
1085 return this->read_data_memory (pc, address, sid::little_int_8());
1086 else // endian_big or endian_unknown
1087 return this->read_data_memory (pc, address, sid::big_int_8());
1090 void write_data_memory_1 (sid::host_int_4 pc, sid::host_int_4 address, sid::host_int_1 value)
1092 if (this->_current_endianness == endian_little)
1093 this->write_data_memory (pc, address, sid::little_int_1(value));
1094 else // endian_big or endian_unknown
1095 this->write_data_memory (pc, address, sid::big_int_1(value));
1098 void write_data_memory_2 (sid::host_int_4 pc, sid::host_int_4 address, sid::host_int_2 value)
1100 if (this->_current_endianness == endian_little)
1101 this->write_data_memory (pc, address, sid::little_int_2(value));
1102 else // endian_big or endian_unknown
1103 this->write_data_memory (pc, address, sid::big_int_2(value));
1106 void write_data_memory_4 (sid::host_int_4 pc, sid::host_int_4 address, sid::host_int_4 value)
1108 if (this->_current_endianness == endian_little)
1109 this->write_data_memory (pc, address, sid::little_int_4(value));
1110 else // endian_big or endian_unknown
1111 this->write_data_memory (pc, address, sid::big_int_4(value));
1114 void write_data_memory_8 (sid::host_int_4 pc, sid::host_int_4 address, sid::host_int_8 value)
1116 if (this->_current_endianness == endian_little)
1117 this->write_data_memory (pc, address, sid::little_int_8(value));
1118 else // endian_big or endian_unknown
1119 this->write_data_memory (pc, address, sid::big_int_8(value));
1124 } // end namespace sidutil
1127 #endif // SIDCPUUTIL_H