1 // sh.cxx - Implementations of hand-written functions for the sh
2 // simulator. -*- C++ -*-
4 // Copyright (C) 2006 Red Hat.
5 // This file is part of SID and is licensed under the GPL.
6 // See the file COPYING.SID for conditions for redistribution.
18 using namespace sidutil;
21 template<class CGEN_CPU>
22 sh_cpu<CGEN_CPU>::sh_cpu () :
26 for (unsigned i = 0; i < 16; ++i)
28 string name = string ("GR") + make_numeric_attribute (i);
29 SI* value = & this->hardware.h_gr[i];
30 this->add_watchable_register (name, value);
33 // add syscall registers
34 this->add_watchable_register (string("syscall-arg0"), &syscall_arg0);
35 this->add_watchable_register (string("syscall-arg1"), &syscall_arg1);
36 this->add_watchable_register (string("syscall-arg2"), &syscall_arg2);
37 this->add_watchable_register (string("syscall-arg3"), &syscall_arg3);
38 this->add_watchable_register (string("syscall-result"), &syscall_result);
39 this->add_watchable_register (string("syscall-error"), &syscall_error);
40 syscall_trap_num = 34;
41 this->add_attribute (string("syscall-trap"), &syscall_trap_num, "setting");
43 add_watchable_pin ("cache-prefetch", &cache_prefetch_pin);
45 #if 0 // customize this
46 this->create_gdb_register_attrs (17, "", & this->hardware.h_pc);
50 template<class CGEN_CPU>
52 sh_cpu<CGEN_CPU>::reset()
54 this->hardware.h_sr = 0xf0;
55 write_stacks_reset ();
56 if (UNLIKELY (this->trace_counter_p || this->final_insn_count_p))
57 this->set_total_latency (2); // Initial IF + ID
59 this->set_total_latency (0);
62 template<class CGEN_CPU>
64 sh_cpu<CGEN_CPU>::set_eflags(sid::host_int_4 flags)
69 static int ef_to_bfd_mach_table [] = { EF_SH_BFD_TABLE };
71 template<class CGEN_CPU>
73 sh_cpu<CGEN_CPU>::bfd_machine () const
75 return ef_to_bfd_mach_table[elf_machine ()];
78 template<class CGEN_CPU>
80 sh_cpu<CGEN_CPU>::invalid_insn (PCADDR pc)
84 cpu_trap_disposition whatnext = this->signal_trap (cpu_trap_invalid_insn, pc);
88 case cpu_trap_unhandled:
89 cerr << "sh: unhandled invalid insn, pc=" << pc << endl;
94 PCADDR npc = pc + insn_size (pc);
99 case cpu_trap_handled:
100 case cpu_trap_reissue:
108 throw cpu_exception ();
111 // Memory trap(/fault) handling.
112 template<class CGEN_CPU>
114 sh_cpu<CGEN_CPU>::memory_trap (const cpu_memory_fault& t)
116 this->h_pc_set (t.pc);
118 cpu_trap_disposition whatnext = this->signal_trap (cpu_trap_memory_fault, t.address);
122 case cpu_trap_unhandled:
123 cerr << "sh: unhandled memory trap, pc=" << t.pc << endl;
128 PCADDR pc = t.pc + insn_size (pc);
133 case cpu_trap_handled:
134 case cpu_trap_reissue:
144 template<class CGEN_CPU>
146 sh_cpu<CGEN_CPU>::dbg_get_reg (host_int_4 reg)
150 int size = reg < 16 ? 2 : 4;
151 #if 0 // customize this
154 val = h_gr_get (reg);
161 // Change to "target endian".
162 little_int_4 v = val;
163 for (unsigned i = 0; i < size; i++)
164 attr += v.read_byte (i);
169 template<class CGEN_CPU>
171 sh_cpu<CGEN_CPU>::dbg_set_reg (host_int_4 reg, const string& attr)
173 // change from "target endian"
175 int size = reg < 16 ? 2 : 4;
176 for (unsigned i = 0; i < size; i++)
177 v.write_byte (i, attr[i]);
180 #if 0 // customize this
188 return component::bad_value;
190 return component::ok;
193 // C++ implementations of instructions follow here
194 template<class CGEN_CPU>
196 sh_cpu<CGEN_CPU>::sh64_break (PCADDR pc)
199 throw cpu_exception ();
202 template<class CGEN_CPU>
204 sh_cpu<CGEN_CPU>::sh64_fldi0 ()
206 return this->fpu.ops->floatsisf (& this->fpu, 0);
209 template<class CGEN_CPU>
211 sh_cpu<CGEN_CPU>::sh64_fldi1 ()
213 return this->fpu.ops->floatsisf (& this->fpu, 1);
216 template<class CGEN_CPU>
218 sh_cpu<CGEN_CPU>::sh64_fabsd(DF drgh)
220 return this->fpu.ops->absdf (& this->fpu, drgh);
223 template<class CGEN_CPU>
225 sh_cpu<CGEN_CPU>::sh64_fabss(SF frgh)
227 return this->fpu.ops->abssf (& this->fpu, frgh);
230 template<class CGEN_CPU>
232 sh_cpu<CGEN_CPU>::sh64_faddd(DF drg, DF drh)
234 return this->fpu.ops->adddf (& this->fpu, drg, drh);
237 template<class CGEN_CPU>
239 sh_cpu<CGEN_CPU>::sh64_fadds(SF frg, SF frh)
241 return this->fpu.ops->addsf (& this->fpu, frg, frh);
244 template<class CGEN_CPU>
246 sh_cpu<CGEN_CPU>::sh64_fcmpeqd(DF drg, DF drh)
248 return this->fpu.ops->eqdf (& this->fpu, drg, drh);
251 template<class CGEN_CPU>
253 sh_cpu<CGEN_CPU>::sh64_fcmpeqs(SF frg, SF frh)
255 return this->fpu.ops->eqsf (& this->fpu, frg, frh);
258 template<class CGEN_CPU>
260 sh_cpu<CGEN_CPU>::sh64_fcmpged(DF drg, DF drh)
262 return this->fpu.ops->gedf (& this->fpu, drg, drh);
265 template<class CGEN_CPU>
267 sh_cpu<CGEN_CPU>::sh64_fcmpges(SF frg, SF frh)
269 return this->fpu.ops->gesf (& this->fpu, frg, frh);
272 template<class CGEN_CPU>
274 sh_cpu<CGEN_CPU>::sh64_fcmpgtd(DF drg, DF drh)
276 return this->fpu.ops->gtdf (& this->fpu, drg, drh);
279 template<class CGEN_CPU>
281 sh_cpu<CGEN_CPU>::sh64_fcmpgts(SF frg, SF frh)
283 return this->fpu.ops->gtsf (& this->fpu, frg, frh);
286 template<class CGEN_CPU>
288 sh_cpu<CGEN_CPU>::sh64_fcmpund(DF drg, DF drh)
290 return this->fpu.ops->unordereddf (& this->fpu, drg, drh);
293 template<class CGEN_CPU>
295 sh_cpu<CGEN_CPU>::sh64_fcmpuns(SF frg, SF frh)
297 return this->fpu.ops->unorderedsf (& this->fpu, frg, frh);
300 template<class CGEN_CPU>
302 sh_cpu<CGEN_CPU>::sh64_fcnvds(DF drgh)
304 return this->fpu.ops->ftruncdfsf (& this->fpu, drgh);
307 template<class CGEN_CPU>
309 sh_cpu<CGEN_CPU>::sh64_fcnvsd(SF frgh)
311 return this->fpu.ops->fextsfdf (& this->fpu, frgh);
314 template<class CGEN_CPU>
316 sh_cpu<CGEN_CPU>::sh64_fdivd(DF drg, DF drh)
318 return this->fpu.ops->divdf (& this->fpu, drg, drh);
321 template<class CGEN_CPU>
323 sh_cpu<CGEN_CPU>::sh64_fdivs(SF frg, SF frh)
325 return this->fpu.ops->divsf (& this->fpu, frg, frh);
328 template<class CGEN_CPU>
330 sh_cpu<CGEN_CPU>::sh64_floatld(SF frgh)
332 return this->fpu.ops->floatsidf (& this->fpu, frgh);
335 template<class CGEN_CPU>
337 sh_cpu<CGEN_CPU>::sh64_floatls(SF frgh)
339 return this->fpu.ops->floatsisf (& this->fpu, frgh);
342 template<class CGEN_CPU>
344 sh_cpu<CGEN_CPU>::sh64_floatqd(DF drgh)
346 return this->fpu.ops->floatdidf (& this->fpu, drgh);
349 template<class CGEN_CPU>
351 sh_cpu<CGEN_CPU>::sh64_floatqs(DF drgh)
353 return this->fpu.ops->floatdisf (& this->fpu, drgh);
356 template<class CGEN_CPU>
358 sh_cpu<CGEN_CPU>::sh64_fmacs(SF fr0, SF frm, SF frn)
360 SF result = this->fpu.ops->mulsf (& this->fpu, fr0, frm);
361 result = this->fpu.ops->addsf (& this->fpu, result, frn);
365 template<class CGEN_CPU>
367 sh_cpu<CGEN_CPU>::sh64_fmuld(DF drg, DF drh)
369 return this->fpu.ops->muldf (& this->fpu, drg, drh);
372 template<class CGEN_CPU>
374 sh_cpu<CGEN_CPU>::sh64_fmuls(SF frg, SF frh)
376 return this->fpu.ops->mulsf (& this->fpu, frg, frh);
379 template<class CGEN_CPU>
381 sh_cpu<CGEN_CPU>::sh64_fnegd(DF drgh)
383 return this->fpu.ops->negdf (& this->fpu, drgh);
386 template<class CGEN_CPU>
388 sh_cpu<CGEN_CPU>::sh64_fnegs(SF frgh)
390 return this->fpu.ops->negsf (& this->fpu, frgh);
393 template<class CGEN_CPU>
395 sh_cpu<CGEN_CPU>::sh64_fsqrtd(DF drgh)
397 return this->fpu.ops->sqrtdf (& this->fpu, drgh);
400 template<class CGEN_CPU>
402 sh_cpu<CGEN_CPU>::sh64_fsqrts(SF frgh)
404 return this->fpu.ops->sqrtsf (& this->fpu, frgh);
407 template<class CGEN_CPU>
409 sh_cpu<CGEN_CPU>::sh64_fsubd(DF drg, DF drh)
411 return this->fpu.ops->subdf (& this->fpu, drg, drh);
414 template<class CGEN_CPU>
416 sh_cpu<CGEN_CPU>::sh64_fsubs(SF frg, SF frh)
418 return this->fpu.ops->subsf (& this->fpu, frg, frh);
421 template<class CGEN_CPU>
423 sh_cpu<CGEN_CPU>::sh64_ftrcdl(DF drgh)
425 return this->fpu.ops->fixdfsi (& this->fpu, drgh);
428 template<class CGEN_CPU>
430 sh_cpu<CGEN_CPU>::sh64_ftrcsl(SF frgh)
432 return this->fpu.ops->fixsfsi (& this->fpu, frgh);
435 template<class CGEN_CPU>
437 sh_cpu<CGEN_CPU>::sh64_ftrcdq(DF drgh)
439 return this->fpu.ops->fixdfdi (& this->fpu, drgh);
442 template<class CGEN_CPU>
444 sh_cpu<CGEN_CPU>::sh64_ftrcsq(SF frgh)
446 return this->fpu.ops->fixsfdi (& this->fpu, frgh);
449 template<class CGEN_CPU>
451 sh_cpu<CGEN_CPU>::sh64_ftrvs(unsigned g, unsigned h, unsigned f)
454 SF zero = this->fpu.ops->floatsisf (& this->fpu, 0);
455 for (i = 0; i < 4; i++)
458 for (j = 0; j < 4; j++)
461 f1 = this->h_fr_get ((g + i) + (j * 4));
462 f2 = this->h_fr_get (h + j);
463 temp = this->fpu.ops->mulsf (& this->fpu, f1, f2);
464 result = this->fpu.ops->addsf (& this->fpu, result, temp);
466 this->h_fr_set (f + i, result);
470 template<class CGEN_CPU>
472 sh_cpu<CGEN_CPU>::sh64_pref (DI addr)
474 cache_prefetch_pin.drive (addr);
477 template <class CGEN_CPU>
479 sh_cpu<CGEN_CPU>::sh64_movua (PCADDR pc, SI rn)
481 // Move the data one byte at a time to avoid alignment problems.
482 // Be aware of endianness.
483 if (this->current_endianness() == endian_big)
486 for (int i = 0; i < 4; ++i)
487 v.write_byte (i, GETMEMQI (pc, rn + i));
488 return v.integer_value ();
492 for (int i = 0; i < 4; ++i)
493 v.write_byte (i, GETMEMQI (pc, rn + i));
494 return v.integer_value ();
497 // Explicit instantiations
498 template class sh_cpu<sh2_cpu_cgen>;
499 template class sh_cpu<sh2e_cpu_cgen>;
500 template class sh_cpu<sh2a_fpu_cpu_cgen>;
501 template class sh_cpu<sh2a_nofpu_cpu_cgen>;
502 template class sh_cpu<sh3_cpu_cgen>;
503 template class sh_cpu<sh3e_cpu_cgen>;
504 template class sh_cpu<sh4_nofpu_cpu_cgen>;
505 template class sh_cpu<sh4_cpu_cgen>;
506 template class sh_cpu<sh4a_nofpu_cpu_cgen>;
507 template class sh_cpu<sh4a_cpu_cgen>;
508 template class sh_cpu<sh4al_cpu_cgen>;
509 template class sh_cpu<sh5_cpu_cgen>;
511 template class sh_cpu_impl<sh2_cpu_cgen>;
512 template class sh_cpu_impl<sh2e_cpu_cgen>;
513 template class sh_cpu_impl<sh2a_fpu_cpu_cgen>;
514 template class sh_cpu_impl<sh2a_nofpu_cpu_cgen>;
515 template class sh_cpu_impl<sh3_cpu_cgen>;
516 template class sh_cpu_impl<sh3e_cpu_cgen>;
517 template class sh_cpu_impl<sh4_nofpu_cpu_cgen>;
518 template class sh_cpu_impl<sh4_cpu_cgen>;
519 template class sh_cpu_impl<sh4a_nofpu_cpu_cgen>;
520 template class sh_cpu_impl<sh4a_cpu_cgen>;
521 template class sh_cpu_impl<sh4al_cpu_cgen>;
522 template class sh_cpu_impl<sh5_cpu_cgen>;
524 // Used by the disassembler. The real definitions are in opcodes/sh-opc.h
525 // which we don't pull in here.
526 #define MASK(LO,HI) ( LO < 1 ? ((1 << (HI + 1)) - 1) \
527 : HI > 30 ? (-1 << LO) \
528 : LO == HI ? (1 << LO) \
529 : (((1 << (HI + 1)) - 1) & (-1 << LO)))
530 #define arch_sh1_base (1 << 0)
531 #define arch_sh2_base (1 << 1)
532 #define arch_sh2a_sh3_base (1 << 2)
533 #define arch_sh3_base (1 << 3)
534 #define arch_sh2a_sh4_base (1 << 4)
535 #define arch_sh4_base (1 << 5)
536 #define arch_sh4a_base (1 << 6)
537 #define arch_sh2a_base (1 << 7)
538 #define arch_sh_base_mask MASK (0, 7)
540 /* Bits 8 ... 24 are currently free. */
542 /* This is an annotation on instruction types, but we
543 abuse the arch field in instructions to denote it. */
544 #define arch_op32 (1 << 25) /* This is a 32-bit opcode. */
545 #define arch_opann_mask MASK (25, 25)
547 #define arch_sh_no_mmu (1 << 26)
548 #define arch_sh_has_mmu (1 << 27)
549 #define arch_sh_mmu_mask MASK (26, 27)
551 #define arch_sh_no_co (1 << 28) /* Neither FPU nor DSP co-processor. */
552 #define arch_sh_sp_fpu (1 << 29) /* Single precision FPU. */
553 #define arch_sh_dp_fpu (1 << 30) /* Double precision FPU. */
554 #define arch_sh_has_dsp (1 << 31)
555 #define arch_sh_co_mask MASK (28, 31)
558 #define arch_sh1 (arch_sh1_base |arch_sh_no_mmu |arch_sh_no_co)
559 #define arch_sh2 (arch_sh2_base |arch_sh_no_mmu |arch_sh_no_co)
560 #define arch_sh2a (arch_sh2a_base |arch_sh_no_mmu |arch_sh_dp_fpu)
561 #define arch_sh2a_nofpu (arch_sh2a_base |arch_sh_no_mmu |arch_sh_no_co)
562 #define arch_sh2e (arch_sh2_base |arch_sh_no_mmu |arch_sh_sp_fpu)
563 #define arch_sh_dsp (arch_sh2_base |arch_sh_no_mmu |arch_sh_has_dsp)
564 #define arch_sh3_nommu (arch_sh3_base |arch_sh_no_mmu |arch_sh_no_co)
565 #define arch_sh3 (arch_sh3_base |arch_sh_has_mmu|arch_sh_no_co)
566 #define arch_sh3e (arch_sh3_base |arch_sh_has_mmu|arch_sh_sp_fpu)
567 #define arch_sh3_dsp (arch_sh3_base |arch_sh_has_mmu|arch_sh_has_dsp)
568 #define arch_sh4 (arch_sh4_base |arch_sh_has_mmu|arch_sh_dp_fpu)
569 #define arch_sh4a (arch_sh4a_base |arch_sh_has_mmu|arch_sh_dp_fpu)
570 #define arch_sh4al_dsp (arch_sh4a_base |arch_sh_has_mmu|arch_sh_has_dsp)
571 #define arch_sh4_nofpu (arch_sh4_base |arch_sh_has_mmu|arch_sh_no_co)
572 #define arch_sh4a_nofpu (arch_sh4a_base |arch_sh_has_mmu|arch_sh_no_co)
573 #define arch_sh4_nommu_nofpu (arch_sh4_base |arch_sh_no_mmu |arch_sh_no_co)
574 #define arch_sh2a_nofpu_or_sh4_nommu_nofpu (arch_sh2a_sh4_base|arch_sh_no_mmu |arch_sh_no_co)
575 #define arch_sh2a_nofpu_or_sh3_nommu (arch_sh2a_sh3_base|arch_sh_no_mmu |arch_sh_no_co)
576 #define arch_sh2a_or_sh3e (arch_sh2a_sh4_base|arch_sh_no_mmu |arch_sh_sp_fpu)
577 #define arch_sh2a_or_sh4 (arch_sh2a_sh4_base|arch_sh_no_mmu |arch_sh_dp_fpu)
579 #define SH_ARCH_UNKNOWN_ARCH 0xffffffff
581 // Used by the disassembler. The real version is in bfd/cpu-sh.c
582 // which we don't pull in here.
583 static struct { unsigned long bfd_mach, arch; } bfd_to_arch_table[] =
585 { bfd_mach_sh, arch_sh1 },
586 { bfd_mach_sh2, arch_sh2 },
587 { bfd_mach_sh2e, arch_sh2e },
588 { bfd_mach_sh_dsp, arch_sh_dsp },
589 { bfd_mach_sh2a, arch_sh2a },
590 { bfd_mach_sh2a_nofpu, arch_sh2a_nofpu },
592 { bfd_mach_sh2a_nofpu_or_sh4_nommu_nofpu, arch_sh2a_nofpu_or_sh4_nommu_nofpu },
593 { bfd_mach_sh2a_nofpu_or_sh3_nommu, arch_sh2a_nofpu_or_sh3_nommu },
594 { bfd_mach_sh2a_or_sh4, arch_sh2a_or_sh4 },
595 { bfd_mach_sh2a_or_sh3e, arch_sh2a_or_sh3e },
597 { bfd_mach_sh3, arch_sh3 },
598 { bfd_mach_sh3_nommu, arch_sh3_nommu },
599 { bfd_mach_sh3_dsp, arch_sh3_dsp },
600 { bfd_mach_sh3e, arch_sh3e },
601 { bfd_mach_sh4, arch_sh4 },
602 { bfd_mach_sh4a, arch_sh4a },
603 { bfd_mach_sh4al_dsp, arch_sh4al_dsp },
604 { bfd_mach_sh4_nofpu, arch_sh4_nofpu },
605 { bfd_mach_sh4_nommu_nofpu, arch_sh4_nommu_nofpu },
606 { bfd_mach_sh4a_nofpu, arch_sh4a_nofpu },
607 { 0, 0 } /* Terminator. */
610 // Convert a BFD mach number into the right opcodes arch flags
611 // using the table above.
614 sh_get_arch_from_bfd_mach (unsigned long mach)
618 while (bfd_to_arch_table[i].bfd_mach != 0)
620 if (bfd_to_arch_table[i].bfd_mach == mach)
621 return bfd_to_arch_table[i].arch;
625 return SH_ARCH_UNKNOWN_ARCH;