From 9d42a9f991dc8f22c56a0e49694ac08546324f67 Mon Sep 17 00:00:00 2001 From: nobody <> Date: Thu, 16 Sep 2004 14:52:13 +0000 Subject: [PATCH] This commit was manufactured by cvs2svn to create branch 'drow_intercu-20040221-branch'. Cherrypick from master 2004-09-16 14:52:12 UTC Alan Modra ' * elf-bfd.h (struct elf_link_hash_entry): Replace elf_link_hash_flags': bfd/cpu-crx.c bfd/elf32-crx.c bfd/elf32-sh-symbian.c bfd/m88kopenbsd.c config/mh-ppc-darwin config/mt-gnu gdb/bsd-kvm.c gdb/bsd-kvm.h gdb/config/i386/i386.mt gdb/config/m68k/nbsd.mt gdb/config/m68k/nbsdelf.mh gdb/config/m68k/obsd.mh gdb/config/m68k/obsd.mt gdb/config/m88k/obsd.mh gdb/config/m88k/obsd.mt gdb/config/pa/linux.mh gdb/config/pa/linux.mt gdb/config/pa/nm-linux.h gdb/config/pa/obsd.mh gdb/config/pa/obsd.mt gdb/config/pa/tm-linux.h gdb/config/powerpc/obsd.mh gdb/config/powerpc/obsd.mt gdb/config/vax/nbsd.mt gdb/config/vax/nbsdaout.mh gdb/config/vax/nbsdelf.mh gdb/config/vax/nm-nbsdaout.h gdb/config/vax/obsd.mh gdb/config/vax/vax.mh gdb/gdb_ptrace.h gdb/hppa-linux-nat.c gdb/hppa-linux-tdep.c gdb/hppabsd-nat.c gdb/hppabsd-tdep.c gdb/i386nbsd-nat.c gdb/inf-child.c gdb/inf-child.h gdb/inf-ptrace.c gdb/inf-ptrace.h gdb/m68kbsd-nat.c gdb/m68kbsd-tdep.c gdb/m88k-tdep.c gdb/m88k-tdep.h gdb/m88kbsd-nat.c gdb/mi/gdb-mi.el gdb/observer.sh gdb/po/gdbtext gdb/ppcobsd-nat.c gdb/ppcobsd-tdep.c gdb/ppcobsd-tdep.h gdb/regset.c gdb/symfile-mem.c gdb/testsuite/gdb.ada/gnat_ada.gin gdb/testsuite/gdb.arch/e500-prologue.c gdb/testsuite/gdb.arch/e500-prologue.exp gdb/testsuite/gdb.arch/i386-cpuid.h gdb/testsuite/gdb.arch/i386-sse.c gdb/testsuite/gdb.arch/i386-sse.exp gdb/testsuite/gdb.arch/powerpc-aix-prologue.c gdb/testsuite/gdb.arch/powerpc-aix-prologue.exp gdb/testsuite/gdb.asm/pa.inc gdb/testsuite/gdb.base/call-sc.c gdb/testsuite/gdb.base/call-sc.exp gdb/testsuite/gdb.base/lineinc.c gdb/testsuite/gdb.base/lineinc.exp gdb/testsuite/gdb.base/lineinc1.h gdb/testsuite/gdb.base/lineinc2.h gdb/testsuite/gdb.base/lineinc3.h gdb/testsuite/gdb.base/sep-proc.c gdb/testsuite/gdb.base/sep.c gdb/testsuite/gdb.base/sep.exp gdb/testsuite/gdb.base/sigaltstack.c gdb/testsuite/gdb.base/sigaltstack.exp gdb/testsuite/gdb.base/sigbpt.c gdb/testsuite/gdb.base/sigbpt.exp gdb/testsuite/gdb.base/siginfo.c gdb/testsuite/gdb.base/siginfo.exp gdb/testsuite/gdb.base/signull.c gdb/testsuite/gdb.base/signull.exp gdb/testsuite/gdb.base/sigstep.c gdb/testsuite/gdb.base/sigstep.exp gdb/testsuite/gdb.base/unload.c gdb/testsuite/gdb.base/unload.exp gdb/testsuite/gdb.base/unloadshr.c gdb/testsuite/gdb.fortran/Makefile.in gdb/testsuite/gdb.gdb/selftest.exp gdb/testsuite/gdb.java/jmain.exp gdb/testsuite/gdb.java/jmain.java gdb/testsuite/gdb.stabs/exclfwd.exp gdb/testsuite/gdb.stabs/exclfwd.h gdb/testsuite/gdb.stabs/exclfwd1.c gdb/testsuite/gdb.stabs/exclfwd2.c gdb/testsuite/gdb.threads/bp_in_thread.exp gdb/testsuite/gdb.threads/manythreads.c gdb/testsuite/gdb.threads/manythreads.exp gdb/testsuite/gdb.threads/pthread_cond_wait.c gdb/testsuite/gdb.threads/pthread_cond_wait.exp gdb/testsuite/gdb.threads/staticthreads.c gdb/testsuite/gdb.threads/staticthreads.exp gdb/testsuite/gdb.threads/thread_check.c gdb/testsuite/gdb.threads/thread_check.exp gdb/testsuite/gdb.threads/watchthreads.exp gdb/testsuite/lib/cp-support.exp gdb/vax-nat.c gdb/vaxbsd-nat.c gdb/vaxnbsd-tdep.c include/elf/crx.h include/gdb/sim-ppc.h include/opcode/crx.h opcodes/crx-dis.c opcodes/crx-opc.c sim/mn10300/am33-2.igen sim/ppc/gdb-sim.c sim/testsuite/sim/mips/fpu64-ps-sb1.s sim/testsuite/sim/mips/fpu64-ps.s sim/testsuite/sim/mips/mdmx-ob-sb1.s sim/testsuite/sim/mips/mdmx-ob.s sim/testsuite/sim/mips/utils-fpu.inc sim/testsuite/sim/mips/utils-mdmx.inc sim/testsuite/sim/sh/bandor.s sim/testsuite/sim/sh/bandornot.s sim/testsuite/sim/sh/bclr.s sim/testsuite/sim/sh/bld.s sim/testsuite/sim/sh/bldnot.s sim/testsuite/sim/sh/bset.s sim/testsuite/sim/sh/bst.s sim/testsuite/sim/sh/bxor.s sim/testsuite/sim/sh/clip.s sim/testsuite/sim/sh/div.s sim/testsuite/sim/sh/fail.s sim/testsuite/sim/sh/fsca.s sim/testsuite/sim/sh/fsrra.s sim/testsuite/sim/sh/mov.s sim/testsuite/sim/sh/mulr.s sim/testsuite/sim/sh/pass.s sim/testsuite/sim/sh/pushpop.s sim/testsuite/sim/sh/resbank.s --- bfd/cpu-crx.c | 39 + bfd/elf32-crx.c | 1327 ++++++++++ bfd/elf32-sh-symbian.c | 627 +++++ bfd/m88kopenbsd.c | 33 + config/mh-ppc-darwin | 6 + config/mt-gnu | 1 + gdb/bsd-kvm.c | 307 +++ gdb/bsd-kvm.h | 35 + gdb/config/i386/i386.mt | 2 + gdb/config/m68k/nbsd.mt | 3 + gdb/config/m68k/nbsdelf.mh | 5 + gdb/config/m68k/obsd.mh | 6 + gdb/config/m68k/obsd.mt | 3 + gdb/config/m88k/obsd.mh | 3 + gdb/config/m88k/obsd.mt | 2 + gdb/config/pa/linux.mh | 8 + gdb/config/pa/linux.mt | 3 + gdb/config/pa/nm-linux.h | 32 + gdb/config/pa/obsd.mh | 3 + gdb/config/pa/obsd.mt | 3 + gdb/config/pa/tm-linux.h | 30 + gdb/config/powerpc/obsd.mh | 3 + gdb/config/powerpc/obsd.mt | 4 + gdb/config/vax/nbsd.mt | 3 + gdb/config/vax/nbsdaout.mh | 6 + gdb/config/vax/nbsdelf.mh | 5 + gdb/config/vax/nm-nbsdaout.h | 30 + gdb/config/vax/obsd.mh | 5 + gdb/config/vax/vax.mh | 4 + gdb/gdb_ptrace.h | 114 + gdb/hppa-linux-nat.c | 376 +++ gdb/hppa-linux-tdep.c | 592 +++++ gdb/hppabsd-nat.c | 119 + gdb/hppabsd-tdep.c | 137 + gdb/i386nbsd-nat.c | 82 + gdb/inf-child.c | 241 ++ gdb/inf-child.h | 30 + gdb/inf-ptrace.c | 685 +++++ gdb/inf-ptrace.h | 31 + gdb/m68kbsd-nat.c | 228 ++ gdb/m68kbsd-tdep.c | 228 ++ gdb/m88k-tdep.c | 895 +++++++ gdb/m88k-tdep.h | 49 + gdb/m88kbsd-nat.c | 94 + gdb/mi/gdb-mi.el | 568 ++++ gdb/observer.sh | 157 ++ gdb/po/gdbtext | 38 + gdb/ppcobsd-nat.c | 98 + gdb/ppcobsd-tdep.c | 178 ++ gdb/ppcobsd-tdep.h | 54 + gdb/regset.c | 46 + gdb/symfile-mem.c | 146 ++ gdb/testsuite/gdb.ada/gnat_ada.gin | 27 + gdb/testsuite/gdb.arch/e500-prologue.c | 54 + gdb/testsuite/gdb.arch/e500-prologue.exp | 82 + gdb/testsuite/gdb.arch/i386-cpuid.h | 77 + gdb/testsuite/gdb.arch/i386-sse.c | 90 + gdb/testsuite/gdb.arch/i386-sse.exp | 92 + gdb/testsuite/gdb.arch/powerpc-aix-prologue.c | 55 + .../gdb.arch/powerpc-aix-prologue.exp | 82 + gdb/testsuite/gdb.asm/pa.inc | 44 + gdb/testsuite/gdb.base/call-sc.c | 83 + gdb/testsuite/gdb.base/call-sc.exp | 500 ++++ gdb/testsuite/gdb.base/lineinc.c | 30 + gdb/testsuite/gdb.base/lineinc.exp | 126 + gdb/testsuite/gdb.base/lineinc1.h | 1 + gdb/testsuite/gdb.base/lineinc2.h | 2 + gdb/testsuite/gdb.base/lineinc3.h | 2 + gdb/testsuite/gdb.base/sep-proc.c | 26 + gdb/testsuite/gdb.base/sep.c | 35 + gdb/testsuite/gdb.base/sep.exp | 68 + gdb/testsuite/gdb.base/sigaltstack.c | 97 + gdb/testsuite/gdb.base/sigaltstack.exp | 105 + gdb/testsuite/gdb.base/sigbpt.c | 53 + gdb/testsuite/gdb.base/sigbpt.exp | 266 ++ gdb/testsuite/gdb.base/siginfo.c | 69 + gdb/testsuite/gdb.base/siginfo.exp | 98 + gdb/testsuite/gdb.base/signull.c | 88 + gdb/testsuite/gdb.base/signull.exp | 122 + gdb/testsuite/gdb.base/sigstep.c | 68 + gdb/testsuite/gdb.base/sigstep.exp | 423 +++ gdb/testsuite/gdb.base/unload.c | 58 + gdb/testsuite/gdb.base/unload.exp | 144 ++ gdb/testsuite/gdb.base/unloadshr.c | 24 + gdb/testsuite/gdb.fortran/Makefile.in | 34 + gdb/testsuite/gdb.gdb/selftest.exp | 523 ++++ gdb/testsuite/gdb.java/jmain.exp | 67 + gdb/testsuite/gdb.java/jmain.java | 7 + gdb/testsuite/gdb.stabs/exclfwd.exp | 72 + gdb/testsuite/gdb.stabs/exclfwd.h | 22 + gdb/testsuite/gdb.stabs/exclfwd1.c | 34 + gdb/testsuite/gdb.stabs/exclfwd2.c | 30 + gdb/testsuite/gdb.threads/bp_in_thread.exp | 49 + gdb/testsuite/gdb.threads/manythreads.c | 68 + gdb/testsuite/gdb.threads/manythreads.exp | 127 + gdb/testsuite/gdb.threads/pthread_cond_wait.c | 76 + .../gdb.threads/pthread_cond_wait.exp | 73 + gdb/testsuite/gdb.threads/staticthreads.c | 73 + gdb/testsuite/gdb.threads/staticthreads.exp | 95 + gdb/testsuite/gdb.threads/thread_check.c | 75 + gdb/testsuite/gdb.threads/thread_check.exp | 96 + gdb/testsuite/gdb.threads/watchthreads.exp | 125 + gdb/testsuite/lib/cp-support.exp | 469 ++++ gdb/vax-nat.c | 106 + gdb/vaxbsd-nat.c | 138 + gdb/vaxnbsd-tdep.c | 75 + include/elf/crx.h | 53 + include/gdb/sim-ppc.h | 771 ++++++ include/opcode/crx.h | 395 +++ opcodes/crx-dis.c | 700 +++++ opcodes/crx-opc.c | 675 +++++ sim/mn10300/am33-2.igen | 2285 +++++++++++++++++ sim/ppc/gdb-sim.c | 1295 ++++++++++ sim/testsuite/sim/mips/fpu64-ps-sb1.s | 72 + sim/testsuite/sim/mips/fpu64-ps.s | 367 +++ sim/testsuite/sim/mips/mdmx-ob-sb1.s | 102 + sim/testsuite/sim/mips/mdmx-ob.s | 631 +++++ sim/testsuite/sim/mips/utils-fpu.inc | 105 + sim/testsuite/sim/mips/utils-mdmx.inc | 72 + sim/testsuite/sim/sh/bandor.s | 120 + sim/testsuite/sim/sh/bandornot.s | 120 + sim/testsuite/sim/sh/bclr.s | 139 + sim/testsuite/sim/sh/bld.s | 121 + sim/testsuite/sim/sh/bldnot.s | 102 + sim/testsuite/sim/sh/bset.s | 139 + sim/testsuite/sim/sh/bst.s | 142 + sim/testsuite/sim/sh/bxor.s | 120 + sim/testsuite/sim/sh/clip.s | 89 + sim/testsuite/sim/sh/div.s | 199 ++ sim/testsuite/sim/sh/fail.s | 13 + sim/testsuite/sim/sh/fsca.s | 97 + sim/testsuite/sim/sh/fsrra.s | 62 + sim/testsuite/sim/sh/mov.s | 118 + sim/testsuite/sim/sh/mulr.s | 162 ++ sim/testsuite/sim/sh/pass.s | 14 + sim/testsuite/sim/sh/pushpop.s | 146 ++ sim/testsuite/sim/sh/resbank.s | 268 ++ 137 files changed, 22943 insertions(+) create mode 100644 bfd/cpu-crx.c create mode 100644 bfd/elf32-crx.c create mode 100644 bfd/elf32-sh-symbian.c create mode 100644 bfd/m88kopenbsd.c create mode 100644 config/mh-ppc-darwin create mode 100644 config/mt-gnu create mode 100644 gdb/bsd-kvm.c create mode 100644 gdb/bsd-kvm.h create mode 100644 gdb/config/i386/i386.mt create mode 100644 gdb/config/m68k/nbsd.mt create mode 100644 gdb/config/m68k/nbsdelf.mh create mode 100644 gdb/config/m68k/obsd.mh create mode 100644 gdb/config/m68k/obsd.mt create mode 100644 gdb/config/m88k/obsd.mh create mode 100644 gdb/config/m88k/obsd.mt create mode 100644 gdb/config/pa/linux.mh create mode 100644 gdb/config/pa/linux.mt create mode 100644 gdb/config/pa/nm-linux.h create mode 100644 gdb/config/pa/obsd.mh create mode 100644 gdb/config/pa/obsd.mt create mode 100644 gdb/config/pa/tm-linux.h create mode 100644 gdb/config/powerpc/obsd.mh create mode 100644 gdb/config/powerpc/obsd.mt create mode 100644 gdb/config/vax/nbsd.mt create mode 100644 gdb/config/vax/nbsdaout.mh create mode 100644 gdb/config/vax/nbsdelf.mh create mode 100644 gdb/config/vax/nm-nbsdaout.h create mode 100644 gdb/config/vax/obsd.mh create mode 100644 gdb/config/vax/vax.mh create mode 100644 gdb/gdb_ptrace.h create mode 100644 gdb/hppa-linux-nat.c create mode 100644 gdb/hppa-linux-tdep.c create mode 100644 gdb/hppabsd-nat.c create mode 100644 gdb/hppabsd-tdep.c create mode 100644 gdb/i386nbsd-nat.c create mode 100644 gdb/inf-child.c create mode 100644 gdb/inf-child.h create mode 100644 gdb/inf-ptrace.c create mode 100644 gdb/inf-ptrace.h create mode 100644 gdb/m68kbsd-nat.c create mode 100644 gdb/m68kbsd-tdep.c create mode 100644 gdb/m88k-tdep.c create mode 100644 gdb/m88k-tdep.h create mode 100644 gdb/m88kbsd-nat.c create mode 100644 gdb/mi/gdb-mi.el create mode 100755 gdb/observer.sh create mode 100755 gdb/po/gdbtext create mode 100644 gdb/ppcobsd-nat.c create mode 100644 gdb/ppcobsd-tdep.c create mode 100644 gdb/ppcobsd-tdep.h create mode 100644 gdb/regset.c create mode 100644 gdb/symfile-mem.c create mode 100644 gdb/testsuite/gdb.ada/gnat_ada.gin create mode 100644 gdb/testsuite/gdb.arch/e500-prologue.c create mode 100644 gdb/testsuite/gdb.arch/e500-prologue.exp create mode 100644 gdb/testsuite/gdb.arch/i386-cpuid.h create mode 100644 gdb/testsuite/gdb.arch/i386-sse.c create mode 100644 gdb/testsuite/gdb.arch/i386-sse.exp create mode 100644 gdb/testsuite/gdb.arch/powerpc-aix-prologue.c create mode 100644 gdb/testsuite/gdb.arch/powerpc-aix-prologue.exp create mode 100644 gdb/testsuite/gdb.asm/pa.inc create mode 100644 gdb/testsuite/gdb.base/call-sc.c create mode 100644 gdb/testsuite/gdb.base/call-sc.exp create mode 100644 gdb/testsuite/gdb.base/lineinc.c create mode 100644 gdb/testsuite/gdb.base/lineinc.exp create mode 100644 gdb/testsuite/gdb.base/lineinc1.h create mode 100644 gdb/testsuite/gdb.base/lineinc2.h create mode 100644 gdb/testsuite/gdb.base/lineinc3.h create mode 100644 gdb/testsuite/gdb.base/sep-proc.c create mode 100644 gdb/testsuite/gdb.base/sep.c create mode 100644 gdb/testsuite/gdb.base/sep.exp create mode 100644 gdb/testsuite/gdb.base/sigaltstack.c create mode 100644 gdb/testsuite/gdb.base/sigaltstack.exp create mode 100644 gdb/testsuite/gdb.base/sigbpt.c create mode 100644 gdb/testsuite/gdb.base/sigbpt.exp create mode 100644 gdb/testsuite/gdb.base/siginfo.c create mode 100644 gdb/testsuite/gdb.base/siginfo.exp create mode 100644 gdb/testsuite/gdb.base/signull.c create mode 100644 gdb/testsuite/gdb.base/signull.exp create mode 100644 gdb/testsuite/gdb.base/sigstep.c create mode 100644 gdb/testsuite/gdb.base/sigstep.exp create mode 100644 gdb/testsuite/gdb.base/unload.c create mode 100644 gdb/testsuite/gdb.base/unload.exp create mode 100644 gdb/testsuite/gdb.base/unloadshr.c create mode 100644 gdb/testsuite/gdb.fortran/Makefile.in create mode 100644 gdb/testsuite/gdb.gdb/selftest.exp create mode 100644 gdb/testsuite/gdb.java/jmain.exp create mode 100644 gdb/testsuite/gdb.java/jmain.java create mode 100644 gdb/testsuite/gdb.stabs/exclfwd.exp create mode 100644 gdb/testsuite/gdb.stabs/exclfwd.h create mode 100644 gdb/testsuite/gdb.stabs/exclfwd1.c create mode 100644 gdb/testsuite/gdb.stabs/exclfwd2.c create mode 100644 gdb/testsuite/gdb.threads/bp_in_thread.exp create mode 100644 gdb/testsuite/gdb.threads/manythreads.c create mode 100644 gdb/testsuite/gdb.threads/manythreads.exp create mode 100644 gdb/testsuite/gdb.threads/pthread_cond_wait.c create mode 100644 gdb/testsuite/gdb.threads/pthread_cond_wait.exp create mode 100644 gdb/testsuite/gdb.threads/staticthreads.c create mode 100644 gdb/testsuite/gdb.threads/staticthreads.exp create mode 100644 gdb/testsuite/gdb.threads/thread_check.c create mode 100644 gdb/testsuite/gdb.threads/thread_check.exp create mode 100644 gdb/testsuite/gdb.threads/watchthreads.exp create mode 100644 gdb/testsuite/lib/cp-support.exp create mode 100644 gdb/vax-nat.c create mode 100644 gdb/vaxbsd-nat.c create mode 100644 gdb/vaxnbsd-tdep.c create mode 100644 include/elf/crx.h create mode 100644 include/gdb/sim-ppc.h create mode 100644 include/opcode/crx.h create mode 100644 opcodes/crx-dis.c create mode 100644 opcodes/crx-opc.c create mode 100644 sim/mn10300/am33-2.igen create mode 100644 sim/ppc/gdb-sim.c create mode 100644 sim/testsuite/sim/mips/fpu64-ps-sb1.s create mode 100644 sim/testsuite/sim/mips/fpu64-ps.s create mode 100644 sim/testsuite/sim/mips/mdmx-ob-sb1.s create mode 100644 sim/testsuite/sim/mips/mdmx-ob.s create mode 100644 sim/testsuite/sim/mips/utils-fpu.inc create mode 100644 sim/testsuite/sim/mips/utils-mdmx.inc create mode 100644 sim/testsuite/sim/sh/bandor.s create mode 100644 sim/testsuite/sim/sh/bandornot.s create mode 100644 sim/testsuite/sim/sh/bclr.s create mode 100644 sim/testsuite/sim/sh/bld.s create mode 100644 sim/testsuite/sim/sh/bldnot.s create mode 100644 sim/testsuite/sim/sh/bset.s create mode 100644 sim/testsuite/sim/sh/bst.s create mode 100644 sim/testsuite/sim/sh/bxor.s create mode 100644 sim/testsuite/sim/sh/clip.s create mode 100644 sim/testsuite/sim/sh/div.s create mode 100644 sim/testsuite/sim/sh/fail.s create mode 100644 sim/testsuite/sim/sh/fsca.s create mode 100644 sim/testsuite/sim/sh/fsrra.s create mode 100644 sim/testsuite/sim/sh/mov.s create mode 100644 sim/testsuite/sim/sh/mulr.s create mode 100644 sim/testsuite/sim/sh/pass.s create mode 100644 sim/testsuite/sim/sh/pushpop.s create mode 100644 sim/testsuite/sim/sh/resbank.s diff --git a/bfd/cpu-crx.c b/bfd/cpu-crx.c new file mode 100644 index 00000000000..9636630113a --- /dev/null +++ b/bfd/cpu-crx.c @@ -0,0 +1,39 @@ +/* BFD support for the CRX processor. + Copyright 2004 Free Software Foundation, Inc. + + This file is part of BFD, the Binary File Descriptor library. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include "bfd.h" +#include "sysdep.h" +#include "libbfd.h" + + +const bfd_arch_info_type bfd_crx_arch = + { + 16, /* 16 bits in a word. */ + 32, /* 32 bits in an address. */ + 8, /* 8 bits in a byte. */ + bfd_arch_crx, /* enum bfd_architecture arch. */ + bfd_mach_crx, + "crx", /* Arch name. */ + "crx", /* Printable name. */ + 1, /* Unsigned int section alignment power. */ + TRUE, /* The one and only. */ + bfd_default_compatible, + bfd_default_scan , + 0, + }; diff --git a/bfd/elf32-crx.c b/bfd/elf32-crx.c new file mode 100644 index 00000000000..79b9c64feac --- /dev/null +++ b/bfd/elf32-crx.c @@ -0,0 +1,1327 @@ +/* BFD back-end for National Semiconductor's CRX ELF + Copyright 2004 Free Software Foundation, Inc. + Written by Tomer Levi, NSC, Israel. + + This file is part of BFD, the Binary File Descriptor library. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include "bfd.h" +#include "sysdep.h" +#include "bfdlink.h" +#include "libbfd.h" +#include "elf-bfd.h" +#include "elf/crx.h" + +static reloc_howto_type *elf_crx_reloc_type_lookup + (bfd *, bfd_reloc_code_real_type); +static void elf_crx_info_to_howto + (bfd *, arelent *, Elf_Internal_Rela *); +static bfd_boolean elf32_crx_relax_delete_bytes + (bfd *, asection *, bfd_vma, int); +static bfd_reloc_status_type crx_elf_final_link_relocate + (reloc_howto_type *, bfd *, bfd *, asection *, + bfd_byte *, bfd_vma, bfd_vma, bfd_vma, + struct bfd_link_info *, asection *, int); +static bfd_boolean elf32_crx_relocate_section + (bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *, + Elf_Internal_Rela *, Elf_Internal_Sym *, asection **); +static asection * elf32_crx_gc_mark_hook + (asection *, struct bfd_link_info *, Elf_Internal_Rela *, + struct elf_link_hash_entry *, Elf_Internal_Sym *); +static bfd_boolean elf32_crx_gc_sweep_hook + (bfd *, struct bfd_link_info *, asection *, + const Elf_Internal_Rela *); +static bfd_boolean elf32_crx_relax_section + (bfd *, asection *, struct bfd_link_info *, bfd_boolean *); +static bfd_byte * elf32_crx_get_relocated_section_contents + (bfd *, struct bfd_link_info *, struct bfd_link_order *, + bfd_byte *, bfd_boolean, asymbol **); + +/* crx_reloc_map array maps BFD relocation enum into a CRGAS relocation type. */ + +struct crx_reloc_map +{ + bfd_reloc_code_real_type bfd_reloc_enum; /* BFD relocation enum. */ + unsigned short crx_reloc_type; /* CRX relocation type. */ +}; + +static const struct crx_reloc_map crx_reloc_map[R_CRX_MAX] = +{ + {BFD_RELOC_NONE, R_CRX_NONE}, + {BFD_RELOC_CRX_REL4, R_CRX_REL4}, + {BFD_RELOC_CRX_REL8, R_CRX_REL8}, + {BFD_RELOC_CRX_REL8_CMP, R_CRX_REL8_CMP}, + {BFD_RELOC_CRX_REL16, R_CRX_REL16}, + {BFD_RELOC_CRX_REL24, R_CRX_REL24}, + {BFD_RELOC_CRX_REL32, R_CRX_REL32}, + {BFD_RELOC_CRX_REGREL12, R_CRX_REGREL12}, + {BFD_RELOC_CRX_REGREL22, R_CRX_REGREL22}, + {BFD_RELOC_CRX_REGREL28, R_CRX_REGREL28}, + {BFD_RELOC_CRX_REGREL32, R_CRX_REGREL32}, + {BFD_RELOC_CRX_ABS16, R_CRX_ABS16}, + {BFD_RELOC_CRX_ABS32, R_CRX_ABS32}, + {BFD_RELOC_CRX_NUM8, R_CRX_NUM8}, + {BFD_RELOC_CRX_NUM16, R_CRX_NUM16}, + {BFD_RELOC_CRX_NUM32, R_CRX_NUM32}, + {BFD_RELOC_CRX_IMM16, R_CRX_IMM16}, + {BFD_RELOC_CRX_IMM32, R_CRX_IMM32}, + {BFD_RELOC_CRX_SWITCH8, R_CRX_SWITCH8}, + {BFD_RELOC_CRX_SWITCH16, R_CRX_SWITCH16}, + {BFD_RELOC_CRX_SWITCH32, R_CRX_SWITCH32} +}; + +static reloc_howto_type crx_elf_howto_table[] = +{ + HOWTO (R_CRX_NONE, /* type */ + 0, /* rightshift */ + 2, /* size */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_CRX_NONE", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0, /* dst_mask */ + FALSE), /* pcrel_offset */ + + HOWTO (R_CRX_REL4, /* type */ + 1, /* rightshift */ + 0, /* size */ + 4, /* bitsize */ + TRUE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_bitfield,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_CRX_REL4", /* name */ + FALSE, /* partial_inplace */ + 0xf, /* src_mask */ + 0xf, /* dst_mask */ + FALSE), /* pcrel_offset */ + + HOWTO (R_CRX_REL8, /* type */ + 1, /* rightshift */ + 0, /* size */ + 8, /* bitsize */ + TRUE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_bitfield,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_CRX_REL8", /* name */ + FALSE, /* partial_inplace */ + 0xff, /* src_mask */ + 0xff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + HOWTO (R_CRX_REL8_CMP, /* type */ + 1, /* rightshift */ + 0, /* size */ + 8, /* bitsize */ + TRUE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_bitfield,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_CRX_REL8_CMP", /* name */ + FALSE, /* partial_inplace */ + 0xff, /* src_mask */ + 0xff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + HOWTO (R_CRX_REL16, /* type */ + 1, /* rightshift */ + 1, /* size */ + 16, /* bitsize */ + TRUE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_bitfield,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_CRX_REL16", /* name */ + FALSE, /* partial_inplace */ + 0xffff, /* src_mask */ + 0xffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + HOWTO (R_CRX_REL24, /* type */ + 1, /* rightshift */ + 2, /* size */ + 24, /* bitsize */ + TRUE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_bitfield,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_CRX_REL24", /* name */ + FALSE, /* partial_inplace */ + 0xffffff, /* src_mask */ + 0xffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + HOWTO (R_CRX_REL32, /* type */ + 1, /* rightshift */ + 2, /* size */ + 32, /* bitsize */ + TRUE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_bitfield,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_CRX_REL32", /* name */ + FALSE, /* partial_inplace */ + 0xffffffff, /* src_mask */ + 0xffffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + HOWTO (R_CRX_REGREL12, /* type */ + 0, /* rightshift */ + 1, /* size */ + 12, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_bitfield,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_CRX_REGREL12", /* name */ + FALSE, /* partial_inplace */ + 0xfff, /* src_mask */ + 0xfff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + HOWTO (R_CRX_REGREL22, /* type */ + 0, /* rightshift */ + 2, /* size */ + 22, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_bitfield,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_CRX_REGREL22", /* name */ + FALSE, /* partial_inplace */ + 0x3fffff, /* src_mask */ + 0x3fffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + HOWTO (R_CRX_REGREL28, /* type */ + 0, /* rightshift */ + 2, /* size */ + 28, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_bitfield,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_CRX_REGREL28", /* name */ + FALSE, /* partial_inplace */ + 0xfffffff, /* src_mask */ + 0xfffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + HOWTO (R_CRX_REGREL32, /* type */ + 0, /* rightshift */ + 2, /* size */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_bitfield,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_CRX_REGREL32", /* name */ + FALSE, /* partial_inplace */ + 0xffffffff, /* src_mask */ + 0xffffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + HOWTO (R_CRX_ABS16, /* type */ + 0, /* rightshift */ + 1, /* size */ + 16, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_bitfield,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_CRX_ABS16", /* name */ + FALSE, /* partial_inplace */ + 0xffff, /* src_mask */ + 0xffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + HOWTO (R_CRX_ABS32, /* type */ + 0, /* rightshift */ + 2, /* size */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_bitfield,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_CRX_ABS32", /* name */ + FALSE, /* partial_inplace */ + 0xffffffff, /* src_mask */ + 0xffffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + HOWTO (R_CRX_NUM8, /* type */ + 0, /* rightshift */ + 0, /* size */ + 8, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_bitfield,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_CRX_NUM8", /* name */ + FALSE, /* partial_inplace */ + 0xff, /* src_mask */ + 0xff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + HOWTO (R_CRX_NUM16, /* type */ + 0, /* rightshift */ + 1, /* size */ + 16, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_bitfield,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_CRX_NUM16", /* name */ + FALSE, /* partial_inplace */ + 0xffff, /* src_mask */ + 0xffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + HOWTO (R_CRX_NUM32, /* type */ + 0, /* rightshift */ + 2, /* size */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_bitfield,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_CRX_NUM32", /* name */ + FALSE, /* partial_inplace */ + 0xffffffff, /* src_mask */ + 0xffffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + HOWTO (R_CRX_IMM16, /* type */ + 0, /* rightshift */ + 1, /* size */ + 16, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_bitfield,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_CRX_IMM16", /* name */ + FALSE, /* partial_inplace */ + 0xffff, /* src_mask */ + 0xffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + HOWTO (R_CRX_IMM32, /* type */ + 0, /* rightshift */ + 2, /* size */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_bitfield,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_CRX_IMM32", /* name */ + FALSE, /* partial_inplace */ + 0xffffffff, /* src_mask */ + 0xffffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* An 8 bit switch table entry. This is generated for an expression + such as ``.byte L1 - L2''. The offset holds the difference + between the reloc address and L2. */ + HOWTO (R_CRX_SWITCH8, /* type */ + 0, /* rightshift */ + 0, /* size (0 = byte, 1 = short, 2 = long) */ + 8, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_unsigned, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_CRX_SWITCH8", /* name */ + FALSE, /* partial_inplace */ + 0xff, /* src_mask */ + 0xff, /* dst_mask */ + TRUE), /* pcrel_offset */ + + /* A 16 bit switch table entry. This is generated for an expression + such as ``.word L1 - L2''. The offset holds the difference + between the reloc address and L2. */ + HOWTO (R_CRX_SWITCH16, /* type */ + 0, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_unsigned, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_CRX_SWITCH16", /* name */ + FALSE, /* partial_inplace */ + 0xffff, /* src_mask */ + 0xffff, /* dst_mask */ + TRUE), /* pcrel_offset */ + + /* A 32 bit switch table entry. This is generated for an expression + such as ``.long L1 - L2''. The offset holds the difference + between the reloc address and L2. */ + HOWTO (R_CRX_SWITCH32, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_unsigned, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_CRX_SWITCH32", /* name */ + FALSE, /* partial_inplace */ + 0xffffffff, /* src_mask */ + 0xffffffff, /* dst_mask */ + TRUE) /* pcrel_offset */ +}; + +/* Retrieve a howto ptr using a BFD reloc_code. */ + +static reloc_howto_type * +elf_crx_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, + bfd_reloc_code_real_type code) +{ + unsigned int i; + + for (i = 0; i < R_CRX_MAX; i++) + if (code == crx_reloc_map[i].bfd_reloc_enum) + return &crx_elf_howto_table[crx_reloc_map[i].crx_reloc_type]; + + printf ("This relocation Type is not supported -0x%x\n", code); + return 0; +} + +/* Retrieve a howto ptr using an internal relocation entry. */ + +static void +elf_crx_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED, arelent *cache_ptr, + Elf_Internal_Rela *dst) +{ + unsigned int r_type = ELF32_R_TYPE (dst->r_info); + BFD_ASSERT (r_type < (unsigned int) R_CRX_MAX); + cache_ptr->howto = &crx_elf_howto_table[r_type]; +} + +/* Perform a relocation as part of a final link. */ + +static bfd_reloc_status_type +crx_elf_final_link_relocate (reloc_howto_type *howto, bfd *input_bfd, + bfd *output_bfd ATTRIBUTE_UNUSED, + asection *input_section, bfd_byte *contents, + bfd_vma offset, bfd_vma Rvalue, bfd_vma addend, + struct bfd_link_info *info ATTRIBUTE_UNUSED, + asection *sec ATTRIBUTE_UNUSED, + int is_local ATTRIBUTE_UNUSED) +{ + unsigned short r_type = howto->type; + bfd_byte *hit_data = contents + offset; + bfd_vma reloc_bits, check; + + switch (r_type) + { + case R_CRX_IMM16: + case R_CRX_IMM32: + case R_CRX_ABS16: + case R_CRX_ABS32: + case R_CRX_REL8_CMP: + case R_CRX_REL16: + case R_CRX_REL24: + case R_CRX_REL32: + case R_CRX_REGREL12: + case R_CRX_REGREL22: + case R_CRX_REGREL28: + case R_CRX_REGREL32: + /* 'hit_data' is relative to the start of the instruction, not the + relocation offset. Advance it to account for the exact offset. */ + hit_data += 2; + break; + + case R_CRX_REL4: + /* This relocation type is used only in 'Branch if Equal to 0' + instructions and requires special handling. */ + Rvalue -= 1; + break; + + case R_CRX_NONE: + return bfd_reloc_ok; + break; + + case R_CRX_SWITCH8: + case R_CRX_SWITCH16: + case R_CRX_SWITCH32: + /* We only care about the addend, where the difference between + expressions is kept. */ + Rvalue = 0; + + default: + break; + } + + if (howto->pc_relative) + { + /* Subtract the address of the section containing the location. */ + Rvalue -= (input_section->output_section->vma + + input_section->output_offset); + /* Subtract the position of the location within the section. */ + Rvalue -= offset; + } + + /* Add in supplied addend. */ + Rvalue += addend; + + /* Complain if the bitfield overflows, whether it is considered + as signed or unsigned. */ + check = Rvalue >> howto->rightshift; + + /* Assumes two's complement. This expression avoids + overflow if howto->bitsize is the number of bits in + bfd_vma. */ + reloc_bits = (((1 << (howto->bitsize - 1)) - 1) << 1) | 1; + + if (((bfd_vma) check & ~reloc_bits) != 0 + && (((bfd_vma) check & ~reloc_bits) + != (-(bfd_vma) 1 & ~reloc_bits))) + { + /* The above right shift is incorrect for a signed + value. See if turning on the upper bits fixes the + overflow. */ + if (howto->rightshift && (bfd_signed_vma) Rvalue < 0) + { + check |= ((bfd_vma) - 1 + & ~((bfd_vma) - 1 + >> howto->rightshift)); + if (((bfd_vma) check & ~reloc_bits) + != (-(bfd_vma) 1 & ~reloc_bits)) + return bfd_reloc_overflow; + } + else + return bfd_reloc_overflow; + } + + /* Drop unwanted bits from the value we are relocating to. */ + Rvalue >>= (bfd_vma) howto->rightshift; + + /* Apply dst_mask to select only relocatable part of the insn. */ + Rvalue &= howto->dst_mask; + + switch (howto->size) + { + case 0: + if (r_type == R_CRX_REL4) + { + Rvalue <<= 4; + Rvalue |= (bfd_get_8 (input_bfd, hit_data) & 0x0f); + } + + bfd_put_8 (input_bfd, (unsigned char) Rvalue, hit_data); + break; + + case 1: + if (r_type == R_CRX_REGREL12) + Rvalue |= (bfd_get_16 (input_bfd, hit_data) & 0xf000); + + bfd_put_16 (input_bfd, Rvalue, hit_data); + break; + + case 2: + if (r_type == R_CRX_REL24 + || r_type == R_CRX_REGREL22 + || r_type == R_CRX_REGREL28) + Rvalue |= (((bfd_get_16 (input_bfd, hit_data) << 16) | + bfd_get_16 (input_bfd, hit_data + 2)) & ~howto->dst_mask); + + if (r_type == R_CRX_NUM32 || r_type == R_CRX_SWITCH32) + /* Relocation on DATA is purely little-endian, that is, for a + multi-byte datum, the lowest address in memory contains the + little end of the datum, that is, the least significant byte. + Therefore we use BFD's byte Putting functions. */ + bfd_put_32 (input_bfd, Rvalue, hit_data); + else + /* Relocation on INSTRUCTIONS is different : Instructions are + word-addressable, that is, each word itself is arranged according + to little-endian convention, whereas the words are arranged with + respect to one another in BIG ENDIAN fashion. + When there is an immediate value that spans a word boundary, it is + split in a big-endian way with respect to the words. */ + { + bfd_put_16 (input_bfd, (Rvalue >> 16) & 0xffff, hit_data); + bfd_put_16 (input_bfd, Rvalue & 0xffff, hit_data + 2); + } + break; + + default: + return bfd_reloc_notsupported; + } + + return bfd_reloc_ok; +} + +/* Delete some bytes from a section while relaxing. */ + +static bfd_boolean +elf32_crx_relax_delete_bytes (bfd *abfd, asection *sec, + bfd_vma addr, int count) +{ + Elf_Internal_Shdr *symtab_hdr; + unsigned int sec_shndx; + bfd_byte *contents; + Elf_Internal_Rela *irel, *irelend; + Elf_Internal_Rela *irelalign; + bfd_vma toaddr; + Elf_Internal_Sym *isym; + Elf_Internal_Sym *isymend; + struct elf_link_hash_entry **sym_hashes; + struct elf_link_hash_entry **end_hashes; + unsigned int symcount; + + sec_shndx = _bfd_elf_section_from_bfd_section (abfd, sec); + + contents = elf_section_data (sec)->this_hdr.contents; + + /* The deletion must stop at the next ALIGN reloc for an aligment + power larger than the number of bytes we are deleting. */ + + irelalign = NULL; + toaddr = sec->size; + + irel = elf_section_data (sec)->relocs; + irelend = irel + sec->reloc_count; + + /* Actually delete the bytes. */ + memmove (contents + addr, contents + addr + count, + (size_t) (toaddr - addr - count)); + sec->size -= count; + + /* Adjust all the relocs. */ + for (irel = elf_section_data (sec)->relocs; irel < irelend; irel++) + { + /* Get the new reloc address. */ + if ((irel->r_offset > addr + && irel->r_offset < toaddr)) + irel->r_offset -= count; + } + + /* Adjust the local symbols defined in this section. */ + symtab_hdr = &elf_tdata (abfd)->symtab_hdr; + isym = (Elf_Internal_Sym *) symtab_hdr->contents; + for (isymend = isym + symtab_hdr->sh_info; isym < isymend; isym++) + { + if (isym->st_shndx == sec_shndx + && isym->st_value > addr + && isym->st_value < toaddr) + { + /* Adjust the addend of SWITCH relocations in this section, + which reference this local symbol. */ + for (irel = elf_section_data (sec)->relocs; irel < irelend; irel++) + { + unsigned long r_symndx; + Elf_Internal_Sym *rsym; + bfd_vma addsym, subsym; + + /* Skip if not a SWITCH relocation. */ + if (ELF32_R_TYPE (irel->r_info) != (int) R_CRX_SWITCH8 + && ELF32_R_TYPE (irel->r_info) != (int) R_CRX_SWITCH16 + && ELF32_R_TYPE (irel->r_info) != (int) R_CRX_SWITCH32) + continue; + + r_symndx = ELF32_R_SYM (irel->r_info); + rsym = (Elf_Internal_Sym *) symtab_hdr->contents + r_symndx; + + /* Skip if not the local adjusted symbol. */ + if (rsym != isym) + continue; + + addsym = isym->st_value; + subsym = addsym - irel->r_addend; + + /* Fix the addend only when -->> (addsym > addr >= subsym). */ + if (subsym <= addr) + irel->r_addend -= count; + else + continue; + } + + isym->st_value -= count; + } + } + + /* Now adjust the global symbols defined in this section. */ + symcount = (symtab_hdr->sh_size / sizeof (Elf32_External_Sym) + - symtab_hdr->sh_info); + sym_hashes = elf_sym_hashes (abfd); + end_hashes = sym_hashes + symcount; + + for (; sym_hashes < end_hashes; sym_hashes++) + { + struct elf_link_hash_entry *sym_hash = *sym_hashes; + + if ((sym_hash->root.type == bfd_link_hash_defined + || sym_hash->root.type == bfd_link_hash_defweak) + && sym_hash->root.u.def.section == sec + && sym_hash->root.u.def.value > addr + && sym_hash->root.u.def.value < toaddr) + sym_hash->root.u.def.value -= count; + } + + return TRUE; +} + +/* This is a version of bfd_generic_get_relocated_section_contents + which uses elf32_crx_relocate_section. */ + +static bfd_byte * +elf32_crx_get_relocated_section_contents (bfd *output_bfd, + struct bfd_link_info *link_info, + struct bfd_link_order *link_order, + bfd_byte *data, + bfd_boolean relocatable, + asymbol **symbols) +{ + Elf_Internal_Shdr *symtab_hdr; + asection *input_section = link_order->u.indirect.section; + bfd *input_bfd = input_section->owner; + asection **sections = NULL; + Elf_Internal_Rela *internal_relocs = NULL; + Elf_Internal_Sym *isymbuf = NULL; + + /* We only need to handle the case of relaxing, or of having a + particular set of section contents, specially. */ + if (relocatable + || elf_section_data (input_section)->this_hdr.contents == NULL) + return bfd_generic_get_relocated_section_contents (output_bfd, link_info, + link_order, data, + relocatable, + symbols); + + symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; + + memcpy (data, elf_section_data (input_section)->this_hdr.contents, + (size_t) input_section->size); + + if ((input_section->flags & SEC_RELOC) != 0 + && input_section->reloc_count > 0) + { + Elf_Internal_Sym *isym; + Elf_Internal_Sym *isymend; + asection **secpp; + bfd_size_type amt; + + internal_relocs = (_bfd_elf_link_read_relocs + (input_bfd, input_section, (PTR) NULL, + (Elf_Internal_Rela *) NULL, FALSE)); + if (internal_relocs == NULL) + goto error_return; + + if (symtab_hdr->sh_info != 0) + { + isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents; + if (isymbuf == NULL) + isymbuf = bfd_elf_get_elf_syms (input_bfd, symtab_hdr, + symtab_hdr->sh_info, 0, + NULL, NULL, NULL); + if (isymbuf == NULL) + goto error_return; + } + + amt = symtab_hdr->sh_info; + amt *= sizeof (asection *); + sections = bfd_malloc (amt); + if (sections == NULL && amt != 0) + goto error_return; + + isymend = isymbuf + symtab_hdr->sh_info; + for (isym = isymbuf, secpp = sections; isym < isymend; ++isym, ++secpp) + { + asection *isec; + + if (isym->st_shndx == SHN_UNDEF) + isec = bfd_und_section_ptr; + else if (isym->st_shndx == SHN_ABS) + isec = bfd_abs_section_ptr; + else if (isym->st_shndx == SHN_COMMON) + isec = bfd_com_section_ptr; + else + isec = bfd_section_from_elf_index (input_bfd, isym->st_shndx); + + *secpp = isec; + } + + if (! elf32_crx_relocate_section (output_bfd, link_info, input_bfd, + input_section, data, internal_relocs, + isymbuf, sections)) + goto error_return; + + if (sections != NULL) + free (sections); + if (isymbuf != NULL + && symtab_hdr->contents != (unsigned char *) isymbuf) + free (isymbuf); + if (elf_section_data (input_section)->relocs != internal_relocs) + free (internal_relocs); + } + + return data; + + error_return: + if (sections != NULL) + free (sections); + if (isymbuf != NULL + && symtab_hdr->contents != (unsigned char *) isymbuf) + free (isymbuf); + if (internal_relocs != NULL + && elf_section_data (input_section)->relocs != internal_relocs) + free (internal_relocs); + return NULL; +} + +/* Relocate a CRX ELF section. */ + +static bfd_boolean +elf32_crx_relocate_section (bfd *output_bfd, struct bfd_link_info *info, + bfd *input_bfd, asection *input_section, + bfd_byte *contents, Elf_Internal_Rela *relocs, + Elf_Internal_Sym *local_syms, + asection **local_sections) +{ + Elf_Internal_Shdr *symtab_hdr; + struct elf_link_hash_entry **sym_hashes; + Elf_Internal_Rela *rel, *relend; + + if (info->relocatable) + return TRUE; + + symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; + sym_hashes = elf_sym_hashes (input_bfd); + + rel = relocs; + relend = relocs + input_section->reloc_count; + for (; rel < relend; rel++) + { + int r_type; + reloc_howto_type *howto; + unsigned long r_symndx; + Elf_Internal_Sym *sym; + asection *sec; + struct elf_link_hash_entry *h; + bfd_vma relocation; + bfd_reloc_status_type r; + + r_symndx = ELF32_R_SYM (rel->r_info); + r_type = ELF32_R_TYPE (rel->r_info); + howto = crx_elf_howto_table + (r_type); + + h = NULL; + sym = NULL; + sec = NULL; + if (r_symndx < symtab_hdr->sh_info) + { + sym = local_syms + r_symndx; + sec = local_sections[r_symndx]; + relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel); + } + else + { + bfd_boolean unresolved_reloc, warned; + + RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel, + r_symndx, symtab_hdr, sym_hashes, + h, sec, relocation, + unresolved_reloc, warned); + } + + r = crx_elf_final_link_relocate (howto, input_bfd, output_bfd, + input_section, + contents, rel->r_offset, + relocation, rel->r_addend, + info, sec, h == NULL); + + if (r != bfd_reloc_ok) + { + const char *name; + const char *msg = (const char *) 0; + + if (h != NULL) + name = h->root.root.string; + else + { + name = (bfd_elf_string_from_elf_section + (input_bfd, symtab_hdr->sh_link, sym->st_name)); + if (name == NULL || *name == '\0') + name = bfd_section_name (input_bfd, sec); + } + + switch (r) + { + case bfd_reloc_overflow: + if (!((*info->callbacks->reloc_overflow) + (info, name, howto->name, (bfd_vma) 0, + input_bfd, input_section, rel->r_offset))) + return FALSE; + break; + + case bfd_reloc_undefined: + if (!((*info->callbacks->undefined_symbol) + (info, name, input_bfd, input_section, + rel->r_offset, TRUE))) + return FALSE; + break; + + case bfd_reloc_outofrange: + msg = _("internal error: out of range error"); + goto common_error; + + case bfd_reloc_notsupported: + msg = _("internal error: unsupported relocation error"); + goto common_error; + + case bfd_reloc_dangerous: + msg = _("internal error: dangerous error"); + goto common_error; + + default: + msg = _("internal error: unknown error"); + /* Fall through. */ + + common_error: + if (!((*info->callbacks->warning) + (info, msg, name, input_bfd, input_section, + rel->r_offset))) + return FALSE; + break; + } + } + } + + return TRUE; +} + +/* This function handles relaxing for the CRX. + + There's quite a few relaxing opportunites available on the CRX: + + * bal/bcond:32 -> bal/bcond:16 2 bytes + * bcond:16 -> bcond:8 2 bytes + * cmpbcond:24 -> cmpbcond:8 2 bytes + * arithmetic imm32 -> arithmetic imm16 2 bytes + + Symbol- and reloc-reading infrastructure copied from elf-m10200.c. */ + +static bfd_boolean +elf32_crx_relax_section (bfd *abfd, asection *sec, + struct bfd_link_info *link_info, bfd_boolean *again) +{ + Elf_Internal_Shdr *symtab_hdr; + Elf_Internal_Rela *internal_relocs; + Elf_Internal_Rela *irel, *irelend; + bfd_byte *contents = NULL; + Elf_Internal_Sym *isymbuf = NULL; + + /* Assume nothing changes. */ + *again = FALSE; + + /* We don't have to do anything for a relocatable link, if + this section does not have relocs, or if this is not a + code section. */ + if (link_info->relocatable + || (sec->flags & SEC_RELOC) == 0 + || sec->reloc_count == 0 + || (sec->flags & SEC_CODE) == 0) + return TRUE; + + symtab_hdr = &elf_tdata (abfd)->symtab_hdr; + + /* Get a copy of the native relocations. */ + internal_relocs = (_bfd_elf_link_read_relocs + (abfd, sec, (PTR) NULL, (Elf_Internal_Rela *) NULL, + link_info->keep_memory)); + if (internal_relocs == NULL) + goto error_return; + + /* Walk through them looking for relaxing opportunities. */ + irelend = internal_relocs + sec->reloc_count; + for (irel = internal_relocs; irel < irelend; irel++) + { + bfd_vma symval; + + /* If this isn't something that can be relaxed, then ignore + this reloc. */ + if (ELF32_R_TYPE (irel->r_info) != (int) R_CRX_REL32 + && ELF32_R_TYPE (irel->r_info) != (int) R_CRX_REL16 + && ELF32_R_TYPE (irel->r_info) != (int) R_CRX_REL24 + && ELF32_R_TYPE (irel->r_info) != (int) R_CRX_IMM32) + continue; + + /* Get the section contents if we haven't done so already. */ + if (contents == NULL) + { + /* Get cached copy if it exists. */ + if (elf_section_data (sec)->this_hdr.contents != NULL) + contents = elf_section_data (sec)->this_hdr.contents; + /* Go get them off disk. */ + else if (!bfd_malloc_and_get_section (abfd, sec, &contents)) + goto error_return; + } + + /* Read this BFD's local symbols if we haven't done so already. */ + if (isymbuf == NULL && symtab_hdr->sh_info != 0) + { + isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents; + if (isymbuf == NULL) + isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr, + symtab_hdr->sh_info, 0, + NULL, NULL, NULL); + if (isymbuf == NULL) + goto error_return; + } + + /* Get the value of the symbol referred to by the reloc. */ + if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info) + { + /* A local symbol. */ + Elf_Internal_Sym *isym; + asection *sym_sec; + + isym = isymbuf + ELF32_R_SYM (irel->r_info); + if (isym->st_shndx == SHN_UNDEF) + sym_sec = bfd_und_section_ptr; + else if (isym->st_shndx == SHN_ABS) + sym_sec = bfd_abs_section_ptr; + else if (isym->st_shndx == SHN_COMMON) + sym_sec = bfd_com_section_ptr; + else + sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx); + symval = (isym->st_value + + sym_sec->output_section->vma + + sym_sec->output_offset); + } + else + { + unsigned long indx; + struct elf_link_hash_entry *h; + + /* An external symbol. */ + indx = ELF32_R_SYM (irel->r_info) - symtab_hdr->sh_info; + h = elf_sym_hashes (abfd)[indx]; + BFD_ASSERT (h != NULL); + + if (h->root.type != bfd_link_hash_defined + && h->root.type != bfd_link_hash_defweak) + /* This appears to be a reference to an undefined + symbol. Just ignore it--it will be caught by the + regular reloc processing. */ + continue; + + symval = (h->root.u.def.value + + h->root.u.def.section->output_section->vma + + h->root.u.def.section->output_offset); + } + + /* For simplicity of coding, we are going to modify the section + contents, the section relocs, and the BFD symbol table. We + must tell the rest of the code not to free up this + information. It would be possible to instead create a table + of changes which have to be made, as is done in coff-mips.c; + that would be more work, but would require less memory when + the linker is run. */ + + /* Try to turn a 32bit pc-relative branch/call into + a 16bit pc-relative branch/call. */ + if (ELF32_R_TYPE (irel->r_info) == (int) R_CRX_REL32) + { + bfd_vma value = symval; + + /* Deal with pc-relative gunk. */ + value -= (sec->output_section->vma + sec->output_offset); + value -= irel->r_offset; + value += irel->r_addend; + + /* See if the value will fit in 16 bits, note the high value is + 0xfffe + 2 as the target will be two bytes closer if we are + able to relax. */ + if ((long) value < 0x10000 && (long) value > -0x10002) + { + unsigned short code; + + /* Get the opcode. */ + code = (unsigned short) bfd_get_16 (abfd, contents + irel->r_offset); + + /* Verify it's a 'bal'/'bcond' and fix the opcode. */ + if ((code & 0xfff0) == 0x3170) + bfd_put_8 (abfd, 0x30, contents + irel->r_offset + 1); + else if ((code & 0xf0ff) == 0x707f) + bfd_put_8 (abfd, 0x7e, contents + irel->r_offset); + else + continue; + + /* Note that we've changed the relocs, section contents, etc. */ + elf_section_data (sec)->relocs = internal_relocs; + elf_section_data (sec)->this_hdr.contents = contents; + symtab_hdr->contents = (unsigned char *) isymbuf; + + /* Fix the relocation's type. */ + irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info), + R_CRX_REL16); + + /* Delete two bytes of data. */ + if (!elf32_crx_relax_delete_bytes (abfd, sec, + irel->r_offset + 2, 2)) + goto error_return; + + /* That will change things, so, we should relax again. + Note that this is not required, and it may be slow. */ + *again = TRUE; + } + } + + /* Try to turn a 16bit pc-relative branch into an + 8bit pc-relative branch. */ + if (ELF32_R_TYPE (irel->r_info) == (int) R_CRX_REL16) + { + bfd_vma value = symval; + + /* Deal with pc-relative gunk. */ + value -= (sec->output_section->vma + sec->output_offset); + value -= irel->r_offset; + value += irel->r_addend; + + /* See if the value will fit in 8 bits, note the high value is + 0xfc + 2 as the target will be two bytes closer if we are + able to relax. */ + if ((long) value < 0xfe && (long) value > -0x100) + { + unsigned short code; + + /* Get the opcode. */ + code = (unsigned short) bfd_get_16 (abfd, contents + irel->r_offset); + + /* Verify it's a 'bcond' opcode. */ + if ((code & 0xf0ff) != 0x707e) + continue; + + /* Note that we've changed the relocs, section contents, etc. */ + elf_section_data (sec)->relocs = internal_relocs; + elf_section_data (sec)->this_hdr.contents = contents; + symtab_hdr->contents = (unsigned char *) isymbuf; + + /* Fix the relocation's type. */ + irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info), + R_CRX_REL8); + + /* Delete two bytes of data. */ + if (!elf32_crx_relax_delete_bytes (abfd, sec, + irel->r_offset + 2, 2)) + goto error_return; + + /* That will change things, so, we should relax again. + Note that this is not required, and it may be slow. */ + *again = TRUE; + } + } + + /* Try to turn a 24bit pc-relative cmp&branch into + an 8bit pc-relative cmp&branch. */ + if (ELF32_R_TYPE (irel->r_info) == (int) R_CRX_REL24) + { + bfd_vma value = symval; + + /* Deal with pc-relative gunk. */ + value -= (sec->output_section->vma + sec->output_offset); + value -= irel->r_offset; + value += irel->r_addend; + + /* See if the value will fit in 8 bits, note the high value is + 0x7e + 2 as the target will be two bytes closer if we are + able to relax. */ + if ((long) value < 0x100 && (long) value > -0x100) + { + unsigned short code; + + /* Get the opcode. */ + code = (unsigned short) bfd_get_16 (abfd, contents + irel->r_offset); + + /* Verify it's a 'cmp&branch' opcode. */ + if ((code & 0xfff0) != 0x3180 && (code & 0xfff0) != 0x3190 + && (code & 0xfff0) != 0x31a0 && (code & 0xfff0) != 0x31c0 + && (code & 0xfff0) != 0x31d0 && (code & 0xfff0) != 0x31e0) + continue; + + /* Note that we've changed the relocs, section contents, etc. */ + elf_section_data (sec)->relocs = internal_relocs; + elf_section_data (sec)->this_hdr.contents = contents; + symtab_hdr->contents = (unsigned char *) isymbuf; + + /* Fix the opcode. */ + bfd_put_8 (abfd, 0x30, contents + irel->r_offset + 1); + + /* Fix the relocation's type. */ + irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info), + R_CRX_REL8_CMP); + + /* Delete two bytes of data. */ + if (!elf32_crx_relax_delete_bytes (abfd, sec, + irel->r_offset + 4, 2)) + goto error_return; + + /* That will change things, so, we should relax again. + Note that this is not required, and it may be slow. */ + *again = TRUE; + } + } + + /* Try to turn a 32bit immediate address into + a 16bit immediate address. */ + if (ELF32_R_TYPE (irel->r_info) == (int) R_CRX_IMM32) + { + bfd_vma value = symval; + + /* See if the value will fit in 16 bits. */ + if ((long) value < 0x7fff && (long) value > -0x8000) + { + unsigned short code; + + /* Get the opcode. */ + code = (unsigned short) bfd_get_16 (abfd, contents + irel->r_offset); + + /* Verify it's a 'arithmetic double'. */ + if ((code & 0xf0f0) != 0x20f0) + continue; + + /* Note that we've changed the relocs, section contents, etc. */ + elf_section_data (sec)->relocs = internal_relocs; + elf_section_data (sec)->this_hdr.contents = contents; + symtab_hdr->contents = (unsigned char *) isymbuf; + + /* Fix the opcode. */ + bfd_put_8 (abfd, (code & 0xff) - 0x10, contents + irel->r_offset); + + /* Fix the relocation's type. */ + irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info), + R_CRX_IMM16); + + /* Delete two bytes of data. */ + if (!elf32_crx_relax_delete_bytes (abfd, sec, + irel->r_offset + 2, 2)) + goto error_return; + + /* That will change things, so, we should relax again. + Note that this is not required, and it may be slow. */ + *again = TRUE; + } + } + } + + if (isymbuf != NULL + && symtab_hdr->contents != (unsigned char *) isymbuf) + { + if (! link_info->keep_memory) + free (isymbuf); + else + { + /* Cache the symbols for elf_link_input_bfd. */ + symtab_hdr->contents = (unsigned char *) isymbuf; + } + } + + if (contents != NULL + && elf_section_data (sec)->this_hdr.contents != contents) + { + if (! link_info->keep_memory) + free (contents); + else + { + /* Cache the section contents for elf_link_input_bfd. */ + elf_section_data (sec)->this_hdr.contents = contents; + } + } + + if (internal_relocs != NULL + && elf_section_data (sec)->relocs != internal_relocs) + free (internal_relocs); + + return TRUE; + + error_return: + if (isymbuf != NULL + && symtab_hdr->contents != (unsigned char *) isymbuf) + free (isymbuf); + if (contents != NULL + && elf_section_data (sec)->this_hdr.contents != contents) + free (contents); + if (internal_relocs != NULL + && elf_section_data (sec)->relocs != internal_relocs) + free (internal_relocs); + + return FALSE; +} + +static asection * +elf32_crx_gc_mark_hook (asection *sec, + struct bfd_link_info *info ATTRIBUTE_UNUSED, + Elf_Internal_Rela *rel ATTRIBUTE_UNUSED, + struct elf_link_hash_entry *h, + Elf_Internal_Sym *sym) +{ + if (h == NULL) + return bfd_section_from_elf_index (sec->owner, sym->st_shndx); + + switch (h->root.type) + { + case bfd_link_hash_defined: + case bfd_link_hash_defweak: + return h->root.u.def.section; + + case bfd_link_hash_common: + return h->root.u.c.p->section; + + default: + return NULL; + } +} + +/* Update the got entry reference counts for the section being removed. */ + +static bfd_boolean +elf32_crx_gc_sweep_hook (bfd *abfd ATTRIBUTE_UNUSED, + struct bfd_link_info *info ATTRIBUTE_UNUSED, + asection *sec ATTRIBUTE_UNUSED, + const Elf_Internal_Rela *relocs ATTRIBUTE_UNUSED) +{ + /* We don't support garbage collection of GOT and PLT relocs yet. */ + return TRUE; +} + +/* Definitions for setting CRX target vector. */ +#define TARGET_LITTLE_SYM bfd_elf32_crx_vec +#define TARGET_LITTLE_NAME "elf32-crx" +#define ELF_ARCH bfd_arch_crx +#define ELF_MACHINE_CODE EM_CRX +#define ELF_MAXPAGESIZE 0x1 +#define elf_symbol_leading_char '_' + +#define bfd_elf32_bfd_reloc_type_lookup elf_crx_reloc_type_lookup +#define elf_info_to_howto elf_crx_info_to_howto +#define elf_info_to_howto_rel 0 +#define elf_backend_relocate_section elf32_crx_relocate_section +#define bfd_elf32_bfd_relax_section elf32_crx_relax_section +#define bfd_elf32_bfd_get_relocated_section_contents \ + elf32_crx_get_relocated_section_contents +#define elf_backend_gc_mark_hook elf32_crx_gc_mark_hook +#define elf_backend_gc_sweep_hook elf32_crx_gc_sweep_hook +#define elf_backend_can_gc_sections 1 +#define elf_backend_rela_normal 1 + +#include "elf32-target.h" diff --git a/bfd/elf32-sh-symbian.c b/bfd/elf32-sh-symbian.c new file mode 100644 index 00000000000..adce088cc4d --- /dev/null +++ b/bfd/elf32-sh-symbian.c @@ -0,0 +1,627 @@ +/* Renesas / SuperH specific support for Symbian 32-bit ELF files + Copyright 2004 + Free Software Foundation, Inc. + Contributed by Red Hat + + This file is part of BFD, the Binary File Descriptor library. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* Stop elf32-sh.c from defining any target vectors. */ +#define SH_TARGET_ALREADY_DEFINED +#define sh_find_elf_flags sh_symbian_find_elf_flags +#define sh_elf_get_flags_from_mach sh_symbian_elf_get_flags_from_mach +#include "elf32-sh.c" + + +//#define DEBUG 1 +#define DEBUG 0 + +#define DIRECTIVE_HEADER "##\n" +#define DIRECTIVE_IMPORT "IMPORT " +#define DIRECTIVE_EXPORT "EXPORT " +#define DIRECTIVE_AS "AS " + +/* Macro to advance 's' until either it reaches 'e' or the + character pointed to by 's' is equal to 'c'. If 'e' is + reached and DEBUG is enabled then the error message 'm' + is displayed. */ +#define SKIP_UNTIL(s,e,c,m) \ + do \ + { \ + while (s < e && *s != c) \ + ++ s; \ + if (s >= e) \ + { \ + if (DEBUG) \ + fprintf (stderr, "Corrupt directive: %s\n", m); \ + result = FALSE; \ + } \ + } \ + while (0); \ + if (!result) \ + break; + +/* Like SKIP_UNTIL except there are two terminator characters + c1 and c2. */ +#define SKIP_UNTIL2(s,e,c1,c2,m) \ + do \ + { \ + while (s < e && *s != c1 && *s != c2) \ + ++ s; \ + if (s >= e) \ + { \ + if (DEBUG) \ + fprintf (stderr, "Corrupt directive: %s\n", m); \ + result = FALSE; \ + } \ + } \ + while (0); \ + if (!result) \ + break; + +/* Macro to advance 's' until either it reaches 'e' or the + character pointed to by 's' is not equal to 'c'. If 'e' + is reached and DEBUG is enabled then the error message + 'm' is displayed. */ +#define SKIP_WHILE(s,e,c,m) \ + do \ + { \ + while (s < e && *s == c) \ + ++ s; \ + if (s >= e) \ + { \ + if (DEBUG) \ + fprintf (stderr, "Corrupt directive: %s\n", m); \ + result = FALSE; \ + } \ + } \ + while (0); \ + if (!result) \ + break; + + +typedef struct symbol_rename +{ + struct symbol_rename * next; + bfd_byte * current_name; + bfd_byte * new_name; + struct elf_link_hash_entry * current_hash; + unsigned long new_symndx; +} +symbol_rename; + +static symbol_rename * rename_list = NULL; + +/* Accumulate a list of symbols to be renamed. */ + +static bfd_boolean +sh_symbian_import_as (struct bfd_link_info *info, bfd * abfd, + bfd_byte * current_name, bfd_byte * new_name) +{ + struct elf_link_hash_entry * new_hash; + symbol_rename * node; + + if (DEBUG) + fprintf (stderr, "IMPORT '%s' AS '%s'\n", current_name, new_name); + + for (node = rename_list; node; node = node->next) + if (strcmp (node->current_name, current_name) == 0) + { + if (strcmp (node->new_name, new_name) == 0) + /* Already added to rename list. */ + return TRUE; + + bfd_set_error (bfd_error_invalid_operation); + _bfd_error_handler (_("%B: IMPORT AS directive for %s conceals previous IMPORT AS"), + abfd, current_name); + return FALSE; + } + + if ((node = bfd_malloc (sizeof * node)) == NULL) + { + if (DEBUG) + fprintf (stderr, "IMPORT AS: No mem for new rename node\n"); + return FALSE; + } + + if ((node->current_name = bfd_malloc (strlen (current_name) + 1)) == NULL) + { + if (DEBUG) + fprintf (stderr, "IMPORT AS: No mem for current name field in rename node\n"); + free (node); + return FALSE; + } + else + strcpy (node->current_name, current_name); + + if ((node->new_name = bfd_malloc (strlen (new_name) + 1)) == NULL) + { + if (DEBUG) + fprintf (stderr, "IMPORT AS: No mem for new name field in rename node\n"); + free (node->current_name); + free (node); + return FALSE; + } + else + strcpy (node->new_name, new_name); + + node->next = rename_list; + node->current_hash = NULL; + node->new_symndx = 0; + rename_list = node; + + new_hash = elf_link_hash_lookup (elf_hash_table (info), node->new_name, TRUE, FALSE, TRUE); + bfd_elf_link_record_dynamic_symbol (info, new_hash); + if (new_hash->root.type == bfd_link_hash_new) + new_hash->root.type = bfd_link_hash_undefined; + + return TRUE; +} + + +static bfd_boolean +sh_symbian_import (bfd * abfd ATTRIBUTE_UNUSED, bfd_byte * name) +{ + if (DEBUG) + fprintf (stderr, "IMPORT '%s'\n", name); + + /* XXX: Generate an import somehow ? */ + + return TRUE; +} + +static bfd_boolean +sh_symbian_export (bfd * abfd ATTRIBUTE_UNUSED, bfd_byte * name) +{ + if (DEBUG) + fprintf (stderr, "EXPORT '%s'\n", name); + + /* XXX: Generate an export somehow ? */ + + return TRUE; +} + +/* Process any magic embedded commands in the .directive. section. + Returns TRUE upon sucecss, but if it fails it sets bfd_error and + returns FALSE. */ + +static bfd_boolean +sh_symbian_process_embedded_commands (struct bfd_link_info *info, bfd * abfd, + asection * sec, bfd_byte * contents) +{ + bfd_byte *s; + bfd_byte *e; + bfd_boolean result = TRUE; + bfd_size_type sz = sec->rawsize ? sec->rawsize : sec->size; + + for (s = contents, e = s + sz; s < e;) + { + bfd_byte * directive = s; + + switch (*s) + { + /* I want to use "case DIRECTIVE_HEADER [0]:" here but gcc won't let me :-( */ + case '#': + if (strcmp (s, DIRECTIVE_HEADER)) + result = FALSE; + else + /* Just ignore the header. + XXX: Strictly speaking we ought to check that the header + is present and that it is the first thing in the file. */ + s += strlen (DIRECTIVE_HEADER) + 1; + break; + + case 'I': + if (strncmp (s, DIRECTIVE_IMPORT, strlen (DIRECTIVE_IMPORT))) + result = FALSE; + else + { + bfd_byte * new_name; + bfd_byte * new_name_end; + bfd_byte name_end_char; + + /* Skip the IMPORT directive. */ + s += strlen (DIRECTIVE_IMPORT); + + new_name = s; + /* Find the end of the new name. */ + while (s < e && *s != ' ' && *s != '\n') + ++ s; + if (s >= e) + { + /* We have reached the end of the .directive section + without encountering a string terminator. This is + allowed for IMPORT directives. */ + new_name_end = e - 1; + name_end_char = * new_name_end; + * new_name_end = 0; + result = sh_symbian_import (abfd, new_name); + * new_name_end = name_end_char; + break; + } + + /* Remember where the name ends. */ + new_name_end = s; + /* Skip any whitespace before the 'AS'. */ + SKIP_WHILE (s, e, ' ', "IMPORT: Name just followed by spaces"); + /* Terminate the new name. (Do this after skiping...) */ + name_end_char = * new_name_end; + * new_name_end = 0; + + /* Check to see if 'AS '... is present. If se we have an IMPORT AS + directive, otherwise we have an IMPORT directive. */ + if (strncmp (s, DIRECTIVE_AS, strlen (DIRECTIVE_AS))) + { + /* Skip the new-line at the end of the name. */ + if (DEBUG && name_end_char != '\n') + fprintf (stderr, "IMPORT: No newline at end of directive\n"); + else + s ++; + + result = sh_symbian_import (abfd, new_name); + + /* Skip past the NUL character. */ + if (* s ++ != 0) + { + if (DEBUG) + fprintf (stderr, "IMPORT: No NUL at end of directive\n"); + } + } + else + { + bfd_byte * current_name; + bfd_byte * current_name_end; + bfd_byte current_name_end_char; + + /* Skip the 'AS '. */ + s += strlen (DIRECTIVE_AS); + /* Skip any white space after the 'AS '. */ + SKIP_WHILE (s, e, ' ', "IMPORT AS: Nothing after AS"); + current_name = s; + /* Find the end of the current name. */ + SKIP_UNTIL2 (s, e, ' ', '\n', "IMPORT AS: No newline at the end of the current name"); + /* Skip (backwards) over spaces at the end of the current name. */ + current_name_end = s; + current_name_end_char = * current_name_end; + + SKIP_WHILE (s, e, ' ', "IMPORT AS: Current name just followed by spaces"); + /* Skip past the newline character. */ + if (* s ++ != '\n') + if (DEBUG) + fprintf (stderr, "IMPORT AS: No newline at end of directive\n"); + + /* Terminate the current name after having performed the skips. */ + * current_name_end = 0; + + result = sh_symbian_import_as (info, abfd, current_name, new_name); + + /* The next character should be a NUL. */ + if (* s != 0) + { + if (DEBUG) + fprintf (stderr, "IMPORT AS: Junk at end of directive\n"); + result = FALSE; + } + s ++; + + * current_name_end = current_name_end_char; + } + + /* Restore the characters we overwrote, since + the .directive section will be emitted. */ + * new_name_end = name_end_char; + } + break; + + case 'E': + if (strncmp (s, DIRECTIVE_EXPORT, strlen (DIRECTIVE_EXPORT))) + result = FALSE; + else + { + bfd_byte * name; + bfd_byte * name_end; + bfd_byte name_end_char; + + /* Skip the directive. */ + s += strlen (DIRECTIVE_EXPORT); + name = s; + /* Find the end of the name to be exported. */ + SKIP_UNTIL (s, e, '\n', "EXPORT: no newline at end of directive"); + /* Skip (backwards) over spaces at end of exported name. */ + for (name_end = s; name_end[-1] == ' '; name_end --) + ; + /* name_end now points at the first character after the + end of the exported name, so we can termiante it */ + name_end_char = * name_end; + * name_end = 0; + /* Skip passed the newline character. */ + s ++; + + result = sh_symbian_export (abfd, name); + + /* The next character should be a NUL. */ + if (* s != 0) + { + if (DEBUG) + fprintf (stderr, "EXPORT: Junk at end of directive\n"); + result = FALSE; + } + s++; + + /* Restore the character we deleted. */ + * name_end = name_end_char; + } + break; + + default: + result = FALSE; + break; + } + + if (! result) + { + if (DEBUG) + fprintf (stderr, "offset into .directive section: %d\n", directive - contents); + + bfd_set_error (bfd_error_invalid_operation); + _bfd_error_handler (_("%B: Unrecognised .directive command: %s"), + abfd, directive); + break; + } + } + + return result; +} + + +/* Scan a bfd for a .directive section, and if found process it. + Returns TRUE upon success, FALSE otherwise. */ +bfd_boolean bfd_elf32_sh_symbian_process_directives (struct bfd_link_info *info, bfd * abfd); + +bfd_boolean +bfd_elf32_sh_symbian_process_directives (struct bfd_link_info *info, bfd * abfd) +{ + bfd_boolean result = FALSE; + bfd_byte * contents; + asection * sec = bfd_get_section_by_name (abfd, ".directive"); + bfd_size_type sz; + + if (!sec) + return TRUE; + + sz = sec->rawsize ? sec->rawsize : sec->size; + contents = bfd_malloc (sz); + + if (!contents) + bfd_set_error (bfd_error_no_memory); + else + { + if (bfd_get_section_contents (abfd, sec, contents, 0, sz)) + result = sh_symbian_process_embedded_commands (info, abfd, sec, contents); + free (contents); + } + + return result; +} + +/* Intercept the normal sh_relocate_section() function + and magle the relocs to allow for symbol renaming. */ + +static bfd_boolean +sh_symbian_relocate_section (bfd * output_bfd, + struct bfd_link_info * info, + bfd * input_bfd, + asection * input_section, + bfd_byte * contents, + Elf_Internal_Rela * relocs, + Elf_Internal_Sym * local_syms, + asection ** local_sections) +{ + /* When performing a final link we implement the IMPORT AS directives. */ + if (!info->relocatable) + { + Elf_Internal_Rela * rel; + Elf_Internal_Rela * relend; + Elf_Internal_Shdr * symtab_hdr; + struct elf_link_hash_entry ** sym_hashes; + struct elf_link_hash_entry ** sym_hashes_end; + struct elf_link_hash_table * hash_table; + symbol_rename * ptr; + bfd_size_type num_global_syms; + unsigned long num_local_syms; + + BFD_ASSERT (! elf_bad_symtab (input_bfd)); + + symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr; + hash_table = elf_hash_table (info); + num_local_syms = symtab_hdr->sh_info; + num_global_syms = symtab_hdr->sh_size / sizeof (Elf32_External_Sym); + num_global_syms -= num_local_syms; + sym_hashes = elf_sym_hashes (input_bfd); + sym_hashes_end = sym_hashes + num_global_syms; + + /* First scan the rename table, caching the hash entry and the new index. */ + for (ptr = rename_list; ptr; ptr = ptr->next) + { + struct elf_link_hash_entry * new_hash; + struct elf_link_hash_entry ** h; + + ptr->current_hash = elf_link_hash_lookup (hash_table, ptr->current_name, FALSE, FALSE, TRUE); + + if (ptr->current_hash == NULL) + { + if (DEBUG) + fprintf (stderr, "IMPORT AS: current symbol '%s' does not exist\n", ptr->current_name); + continue; + } + + new_hash = elf_link_hash_lookup (hash_table, ptr->new_name, FALSE, FALSE, TRUE); + + /* If we could not find the symbol then it is a new, undefined symbol. + Symbian want this behaviour - ie they want to be able to rename the + reference in a reloc from one undefined symbol to another, new and + undefined symbol. So we create that symbol here. */ + if (new_hash == NULL) + { + asection * psec = bfd_und_section_ptr; + Elf_Internal_Sym new_sym; + bfd_vma new_value = 0; + bfd_boolean skip; + bfd_boolean override; + bfd_boolean type_change_ok; + bfd_boolean size_change_ok; + + new_sym.st_value = 0; + new_sym.st_size = 0; + new_sym.st_name = -1; + new_sym.st_info = ELF_ST_INFO (STB_GLOBAL, STT_FUNC); + new_sym.st_other = ELF_ST_VISIBILITY (STV_DEFAULT); + new_sym.st_shndx = SHN_UNDEF; + + if (! _bfd_elf_merge_symbol (input_bfd, info, ptr->new_name, & new_sym, & psec, + & new_value, & new_hash, & skip, & override, & type_change_ok, + & size_change_ok)) + { + _bfd_error_handler (_("%B: Failed to add renamed symbol %s"), + input_bfd, ptr->new_name); + continue; + } + /* XXX - should we check psec, skip, override etc ? */ + + new_hash->root.type = bfd_link_hash_undefined; + + /* Allow the symbol to become local if necessary. */ + if (new_hash->dynindx == -1) + new_hash->def_regular = 1; + + if (DEBUG) + fprintf (stderr, "Created new symbol %s\n", ptr->new_name); + } + + /* Convert the new_hash value into a index into the table of symbol hashes. */ + for (h = sym_hashes; h < sym_hashes_end; h ++) + { + if (* h == new_hash) + { + ptr->new_symndx = h - sym_hashes + num_local_syms; + if (DEBUG) + fprintf (stderr, "Converted new hash to index of %ld\n", ptr->new_symndx); + break; + } + } + /* If the new symbol is not in the hash table then it must be + because it is one of the newly created undefined symbols + manufactured above. So we extend the sym has table here to + include this extra symbol. */ + if (h == sym_hashes_end) + { + struct elf_link_hash_entry ** new_sym_hashes; + + /* This is not very efficient, but it works. */ + ++ num_global_syms; + new_sym_hashes = bfd_alloc (input_bfd, num_global_syms * sizeof * sym_hashes); + if (new_sym_hashes == NULL) + { + if (DEBUG) + fprintf (stderr, "Out of memory extending hash table\n"); + continue; + } + memcpy (new_sym_hashes, sym_hashes, (num_global_syms - 1) * sizeof * sym_hashes); + new_sym_hashes[num_global_syms - 1] = new_hash; + elf_sym_hashes (input_bfd) = sym_hashes = new_sym_hashes; + sym_hashes_end = sym_hashes + num_global_syms; + symtab_hdr->sh_size = (num_global_syms + num_local_syms) * sizeof (Elf32_External_Sym); + + ptr->new_symndx = num_global_syms - 1 + num_local_syms; + + if (DEBUG) + fprintf (stderr, "Extended symbol hash table to insert new symbol as index %ld\n", + ptr->new_symndx); + } + } + + /* Walk the reloc list looking for references to renamed symbols. + When we find one, we alter the index in the reloc to point to the new symbol. */ + for (rel = relocs, relend = relocs + input_section->reloc_count; + rel < relend; + rel ++) + { + int r_type; + unsigned long r_symndx; + struct elf_link_hash_entry * h; + + r_symndx = ELF32_R_SYM (rel->r_info); + r_type = ELF32_R_TYPE (rel->r_info); + + /* Ignore unused relocs. */ + if ((r_type >= (int) R_SH_GNU_VTINHERIT + && r_type <= (int) R_SH_LABEL) + || r_type == (int) R_SH_NONE + || r_type < 0 + || r_type >= R_SH_max) + continue; + + /* Ignore relocs against local symbols. */ + if (r_symndx < num_local_syms) + continue; + + BFD_ASSERT (r_symndx < (num_global_syms + num_local_syms)); + h = sym_hashes[r_symndx - num_local_syms]; + BFD_ASSERT (h != NULL); + + while ( h->root.type == bfd_link_hash_indirect + || h->root.type == bfd_link_hash_warning) + h = (struct elf_link_hash_entry *) h->root.u.i.link; + + /* If the symbol is defined there is no need to rename it. + XXX - is this true ? */ + if ( h->root.type == bfd_link_hash_defined + || h->root.type == bfd_link_hash_defweak + || h->root.type == bfd_link_hash_undefweak) + continue; + + for (ptr = rename_list; ptr; ptr = ptr->next) + if (h == ptr->current_hash) + { + BFD_ASSERT (ptr->new_symndx); + if (DEBUG) + fprintf (stderr, "convert reloc %lx from using index %ld to using index %ld\n", + (long) rel->r_info, (long) ELF32_R_SYM (rel->r_info), ptr->new_symndx); + rel->r_info = ELF32_R_INFO (ptr->new_symndx, r_type); + break; + } + } + } + + return sh_elf_relocate_section (output_bfd, info, input_bfd, input_section, + contents, relocs, local_syms, local_sections); +} + +static bfd_boolean +sh_symbian_check_directives (bfd *abfd, struct bfd_link_info *info) +{ + return bfd_elf32_sh_symbian_process_directives (info, abfd); +} + +#define TARGET_LITTLE_SYM bfd_elf32_shl_symbian_vec +#define TARGET_LITTLE_NAME "elf32-shl-symbian" + +#undef elf_backend_relocate_section +#define elf_backend_relocate_section sh_symbian_relocate_section +#undef elf_backend_check_directives +#define elf_backend_check_directives sh_symbian_check_directives + +#include "elf32-target.h" diff --git a/bfd/m88kopenbsd.c b/bfd/m88kopenbsd.c new file mode 100644 index 00000000000..459d3b2dd73 --- /dev/null +++ b/bfd/m88kopenbsd.c @@ -0,0 +1,33 @@ +/* BFD back-end for OpenBSD/m88k a.out binaries. + Copyright 2004 Free Software Foundation, Inc. + +This file is part of BFD, the Binary File Descriptor library. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#define TARGET_IS_BIG_ENDIAN_P + +#define TARGET_PAGE_SIZE 4096 + +#define DEFAULT_ARCH bfd_arch_m88k +#define DEFAULT_MID M_88K_OPENBSD + +/* Do not "beautify" the CONCAT* macro args. Traditional C will not + remove whitespace added here, and thus will fail to concatenate + the tokens. */ +#define MY(OP) CONCAT2 (m88kopenbsd_,OP) +#define TARGETNAME "a.out-m88k-openbsd" + +#include "netbsd.h" diff --git a/config/mh-ppc-darwin b/config/mh-ppc-darwin new file mode 100644 index 00000000000..44fd620b66e --- /dev/null +++ b/config/mh-ppc-darwin @@ -0,0 +1,6 @@ +# The -mdynamic-no-pic ensures that the compiler executable is built without +# position-independent-code -- the usual default on Darwin. This fix speeds +# compiles by 3-5%. + +BOOT_CFLAGS=-g -O2 -mdynamic-no-pic + diff --git a/config/mt-gnu b/config/mt-gnu new file mode 100644 index 00000000000..15bf4171603 --- /dev/null +++ b/config/mt-gnu @@ -0,0 +1 @@ +CXXFLAGS_FOR_TARGET = $(CXXFLAGS) -D_GNU_SOURCE diff --git a/gdb/bsd-kvm.c b/gdb/bsd-kvm.c new file mode 100644 index 00000000000..64869e5464c --- /dev/null +++ b/gdb/bsd-kvm.c @@ -0,0 +1,307 @@ +/* BSD Kernel Data Access Library (libkvm) interface. + + Copyright 2004 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include "defs.h" +#include "cli/cli-cmds.h" +#include "command.h" +#include "frame.h" +#include "regcache.h" +#include "target.h" +#include "value.h" +#include "gdbcore.h" /* for get_exec_file */ + +#include "gdb_assert.h" +#include +#include +#ifdef HAVE_NLIST_H +#include +#endif +#include "readline/readline.h" +#include +#include +#include + +#include "bsd-kvm.h" + +/* Kernel memory interface descriptor. */ +kvm_t *core_kd; + +/* Address of process control block. */ +struct pcb *bsd_kvm_paddr; + +/* Pointer to architecture-specific function that reconstructs the + register state from PCB and supplies it to REGCACHE. */ +int (*bsd_kvm_supply_pcb)(struct regcache *regcache, struct pcb *pcb); + +/* Target ops for libkvm interface. */ +struct target_ops bsd_kvm_ops; + +static void +bsd_kvm_open (char *filename, int from_tty) +{ + char errbuf[_POSIX2_LINE_MAX]; + char *execfile = NULL; + kvm_t *temp_kd; + + target_preopen (from_tty); + + if (filename) + { + char *temp; + + filename = tilde_expand (filename); + if (filename[0] != '/') + { + temp = concat (current_directory, "/", filename, NULL); + xfree (filename); + filename = temp; + } + } + + execfile = get_exec_file (0); + temp_kd = kvm_openfiles (execfile, filename, NULL, O_RDONLY, errbuf); + if (temp_kd == NULL) + error ("%s", errbuf); + + unpush_target (&bsd_kvm_ops); + core_kd = temp_kd; + push_target (&bsd_kvm_ops); + + target_fetch_registers (-1); + + flush_cached_frames (); + select_frame (get_current_frame ()); + print_stack_frame (get_selected_frame (), -1, 1); +} + +static void +bsd_kvm_close (int quitting) +{ + if (core_kd) + { + if (kvm_close (core_kd) == -1) + warning ("%s", kvm_geterr(core_kd)); + core_kd = NULL; + } +} + +static int +bsd_kvm_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, + int write, struct mem_attrib *attrib, + struct target_ops *ops) +{ + if (write) + return kvm_write (core_kd, memaddr, myaddr, len); + else + return kvm_read (core_kd, memaddr, myaddr, len); + + return -1; +} + +/* Fetch process control block at address PADDR. */ + +static int +bsd_kvm_fetch_pcb (struct pcb *paddr) +{ + struct pcb pcb; + + if (kvm_read (core_kd, (unsigned long) paddr, &pcb, sizeof pcb) == -1) + error ("%s", kvm_geterr (core_kd)); + + gdb_assert (bsd_kvm_supply_pcb); + return bsd_kvm_supply_pcb (current_regcache, &pcb); +} + +static void +bsd_kvm_fetch_registers (int regnum) +{ + struct nlist nl[2]; + + if (bsd_kvm_paddr) + { + bsd_kvm_fetch_pcb (bsd_kvm_paddr); + return; + } + + /* On dumping core, BSD kernels store the faulting context (PCB) + in the variable "dumppcb". */ + memset (nl, 0, sizeof nl); + nl[0].n_name = "_dumppcb"; + + if (kvm_nlist (core_kd, nl) == -1) + error ("%s", kvm_geterr (core_kd)); + + if (nl[0].n_value != 0) + { + /* Found dumppcb. If it contains a valid context, return + immediately. */ + if (bsd_kvm_fetch_pcb ((struct pcb *) nl[0].n_value)) + return; + } + + /* Traditional BSD kernels have a process proc0 that should always + be present. The address of proc0's PCB is stored in the variable + "proc0paddr". */ + + memset (nl, 0, sizeof nl); + nl[0].n_name = "_proc0paddr"; + + if (kvm_nlist (core_kd, nl) == -1) + error ("%s", kvm_geterr (core_kd)); + + if (nl[0].n_value != 0) + { + struct pcb *paddr; + + /* Found proc0paddr. */ + if (kvm_read (core_kd, nl[0].n_value, &paddr, sizeof paddr) == -1) + error ("%s", kvm_geterr (core_kd)); + + bsd_kvm_fetch_pcb (paddr); + return; + } + +#ifdef HAVE_STRUCT_THREAD_TD_PCB + /* In FreeBSD kernels for 5.0-RELEASE and later, the PCB no longer + lives in `struct proc' but in `struct thread'. The `struct + thread' for the initial thread for proc0 can be found in the + variable "thread0". */ + + memset (nl, 0, sizeof nl); + nl[0].n_name = "_thread0"; + + if (kvm_nlist (core_kd, nl) == -1) + error ("%s", kvm_geterr (core_kd)); + + if (nl[0].n_value != 0) + { + struct pcb *paddr; + + /* Found thread0. */ + nl[0].n_value += offsetof (struct thread, td_pcb); + if (kvm_read (core_kd, nl[0].n_value, &paddr, sizeof paddr) == -1) + error ("%s", kvm_geterr (core_kd)); + + bsd_kvm_fetch_pcb (paddr); + return; + } +#endif + + error ("Cannot find a valid PCB"); +} + + +/* Kernel memory interface commands. */ +struct cmd_list_element *bsd_kvm_cmdlist; + +static void +bsd_kvm_cmd (char *arg, int fromtty) +{ + /* ??? Should this become an alias for "target kvm"? */ +} + +#ifndef HAVE_STRUCT_THREAD_TD_PCB + +static void +bsd_kvm_proc_cmd (char *arg, int fromtty) +{ + CORE_ADDR addr; + + if (arg == NULL) + error_no_arg ("proc address"); + + if (core_kd == NULL) + error ("No kernel memory image."); + + addr = parse_and_eval_address (arg); +#ifdef HAVE_STRUCT_LWP + addr += offsetof (struct lwp, l_addr); +#else + addr += offsetof (struct proc, p_addr); +#endif + + if (kvm_read (core_kd, addr, &bsd_kvm_paddr, sizeof bsd_kvm_paddr) == -1) + error ("%s", kvm_geterr (core_kd)); + + target_fetch_registers (-1); + + flush_cached_frames (); + select_frame (get_current_frame ()); + print_stack_frame (get_selected_frame (), -1, 1); +} + +#endif + +static void +bsd_kvm_pcb_cmd (char *arg, int fromtty) +{ + if (arg == NULL) + error_no_arg ("pcb address"); + + if (core_kd == NULL) + error ("No kernel memory image."); + + bsd_kvm_paddr = (struct pcb *) parse_and_eval_address (arg); + + target_fetch_registers (-1); + + flush_cached_frames (); + select_frame (get_current_frame ()); + print_stack_frame (get_selected_frame (), -1, 1); +} + +/* Add the libkvm interface to the list of all possible targets and + register CUPPLY_PCB as the architecture-specific process control + block interpreter. */ + +void +bsd_kvm_add_target (int (*supply_pcb)(struct regcache *, struct pcb *)) +{ + gdb_assert (bsd_kvm_supply_pcb == NULL); + bsd_kvm_supply_pcb = supply_pcb; + + bsd_kvm_ops.to_shortname = "kvm"; + bsd_kvm_ops.to_longname = "Kernel memory interface"; + bsd_kvm_ops.to_doc = "Use a kernel virtual memory image as a target.\n\ +Optionally specify the filename of a core dump."; + bsd_kvm_ops.to_open = bsd_kvm_open; + bsd_kvm_ops.to_close = bsd_kvm_close; + bsd_kvm_ops.to_fetch_registers = bsd_kvm_fetch_registers; + bsd_kvm_ops.to_xfer_memory = bsd_kvm_xfer_memory; + bsd_kvm_ops.to_stratum = process_stratum; + bsd_kvm_ops.to_has_memory = 1; + bsd_kvm_ops.to_has_stack = 1; + bsd_kvm_ops.to_has_registers = 1; + bsd_kvm_ops.to_magic = OPS_MAGIC; + + add_target (&bsd_kvm_ops); + + add_prefix_cmd ("kvm", class_obscure, bsd_kvm_cmd, "\ +Generic command for manipulating the kernel memory interface.", + &bsd_kvm_cmdlist, "kvm ", 0, &cmdlist); + +#ifndef HAVE_STRUCT_THREAD_TD_PCB + add_cmd ("proc", class_obscure, bsd_kvm_proc_cmd, + "Set current context from proc address", &bsd_kvm_cmdlist); +#endif + add_cmd ("pcb", class_obscure, bsd_kvm_pcb_cmd, + "Set current context from pcb address", &bsd_kvm_cmdlist); +} diff --git a/gdb/bsd-kvm.h b/gdb/bsd-kvm.h new file mode 100644 index 00000000000..0660776cf43 --- /dev/null +++ b/gdb/bsd-kvm.h @@ -0,0 +1,35 @@ +/* BSD Kernel Data Access Library (libkvm) interface. + + Copyright 2004 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef BSD_KVM_H +#define BSD_KVM_H + +struct pcb; +struct regcache; + +/* Add the libkvm interface to the list of all possible targets and + register CUPPLY_PCB as the architecture-specific process control + block interpreter. */ + +extern void + bsd_kvm_add_target (int (*supply_pcb)(struct regcache *, struct pcb *)); + +#endif /* bsd-kvm.h */ diff --git a/gdb/config/i386/i386.mt b/gdb/config/i386/i386.mt new file mode 100644 index 00000000000..d2eab6d1e58 --- /dev/null +++ b/gdb/config/i386/i386.mt @@ -0,0 +1,2 @@ +# Target: i386 +TDEPFILES= i386-tdep.o i387-tdep.o diff --git a/gdb/config/m68k/nbsd.mt b/gdb/config/m68k/nbsd.mt new file mode 100644 index 00000000000..db3e3573d7f --- /dev/null +++ b/gdb/config/m68k/nbsd.mt @@ -0,0 +1,3 @@ +# Target: NetBSD/m68k +TDEPFILES= m68k-tdep.o m68kbsd-tdep.o corelow.o solib.o solib-svr4.o +DEPRECATED_TM_FILE= solib.h diff --git a/gdb/config/m68k/nbsdelf.mh b/gdb/config/m68k/nbsdelf.mh new file mode 100644 index 00000000000..c58e348be7e --- /dev/null +++ b/gdb/config/m68k/nbsdelf.mh @@ -0,0 +1,5 @@ +# Host: NetBSD/m68k ELF +NATDEPFILES= m68kbsd-nat.o bsd-kvm.o fork-child.o infptrace.o inftarg.o +NAT_FILE= config/nm-nbsd.h + +LOADLIBES= -lkvm diff --git a/gdb/config/m68k/obsd.mh b/gdb/config/m68k/obsd.mh new file mode 100644 index 00000000000..54e4e9d7c2b --- /dev/null +++ b/gdb/config/m68k/obsd.mh @@ -0,0 +1,6 @@ +# Host: OpenBSD/m68k +NATDEPFILES= m68kbsd-nat.o bsd-kvm.o fork-child.o infptrace.o inftarg.o \ + solib.o solib-sunos.o +NAT_FILE= nm-nbsdaout.h + +LOADLIBES= -lkvm diff --git a/gdb/config/m68k/obsd.mt b/gdb/config/m68k/obsd.mt new file mode 100644 index 00000000000..98531211fc2 --- /dev/null +++ b/gdb/config/m68k/obsd.mt @@ -0,0 +1,3 @@ +# Target: OpenBSD/m68k +TDEPFILES= m68k-tdep.o m68kbsd-tdep.o corelow.o solib.o solib-svr4.o +DEPRECATED_TM_FILE= solib.h diff --git a/gdb/config/m88k/obsd.mh b/gdb/config/m88k/obsd.mh new file mode 100644 index 00000000000..e9281bcecd7 --- /dev/null +++ b/gdb/config/m88k/obsd.mh @@ -0,0 +1,3 @@ +# Host: OpenBSD/m88k +NATDEPFILES= m88kbsd-nat.o fork-child.o infptrace.o inftarg.o +NAT_FILE= config/nm-bsd.h diff --git a/gdb/config/m88k/obsd.mt b/gdb/config/m88k/obsd.mt new file mode 100644 index 00000000000..36e61bbadac --- /dev/null +++ b/gdb/config/m88k/obsd.mt @@ -0,0 +1,2 @@ +# Target: OpenBSD/m88k +TDEPFILES= m88k-tdep.o corelow.o diff --git a/gdb/config/pa/linux.mh b/gdb/config/pa/linux.mh new file mode 100644 index 00000000000..596857c0b9c --- /dev/null +++ b/gdb/config/pa/linux.mh @@ -0,0 +1,8 @@ +# Host: Hewlett-Packard PA-RISC machine, running Linux +XDEPFILES= +NAT_FILE= nm-linux.h +NATDEPFILES= infptrace.o inftarg.o fork-child.o corelow.o gcore.o \ + core-regset.o hppa-linux-nat.o linux-proc.o \ + proc-service.o thread-db.o lin-lwp.o linux-nat.o + +LOADLIBES = -ldl -rdynamic diff --git a/gdb/config/pa/linux.mt b/gdb/config/pa/linux.mt new file mode 100644 index 00000000000..d2168668559 --- /dev/null +++ b/gdb/config/pa/linux.mt @@ -0,0 +1,3 @@ +# Target: HP PA-RISC running Linux +TDEPFILES= hppa-tdep.o hppa-linux-tdep.o glibc-tdep.o solib.o solib-svr4.o +DEPRECATED_TM_FILE=tm-linux.h diff --git a/gdb/config/pa/nm-linux.h b/gdb/config/pa/nm-linux.h new file mode 100644 index 00000000000..08b79156aab --- /dev/null +++ b/gdb/config/pa/nm-linux.h @@ -0,0 +1,32 @@ +/* Native support for GNU/Linux, for GDB, the GNU debugger. + Copyright (C) 2004 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef PA_NM_LINUX_H +#define PA_NM_LINUX_H + +#include "config/nm-linux.h" + +#define U_REGS_OFFSET 0 + +/* Override copies of {fetch,store}_inferior_registers in `infptrace.c'. */ +#define FETCH_INFERIOR_REGISTERS + +#endif + diff --git a/gdb/config/pa/obsd.mh b/gdb/config/pa/obsd.mh new file mode 100644 index 00000000000..2c3dba97f59 --- /dev/null +++ b/gdb/config/pa/obsd.mh @@ -0,0 +1,3 @@ +# Host: OpenBSD/hppa +NATDEPFILES= fork-child.o infptrace.o inftarg.o hppabsd-nat.o +NAT_FILE= config/nm-bsd.h diff --git a/gdb/config/pa/obsd.mt b/gdb/config/pa/obsd.mt new file mode 100644 index 00000000000..b7a6888b4fc --- /dev/null +++ b/gdb/config/pa/obsd.mt @@ -0,0 +1,3 @@ +# Target: OpenBSD/hppa +TDEPFILES= hppa-tdep.o hppabsd-tdep.o corelow.o solib.o solib-svr4.o +DEPRECATED_TM_FILE= solib.h diff --git a/gdb/config/pa/tm-linux.h b/gdb/config/pa/tm-linux.h new file mode 100644 index 00000000000..e8b31c57f3b --- /dev/null +++ b/gdb/config/pa/tm-linux.h @@ -0,0 +1,30 @@ +/* Definitions to target GDB to GNU/Linux on hppa-linux. + Copyright 2004 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef TM_LINUX_H +#define TM_LINUX_H + +#include "pa/tm-hppa.h" +#include "config/tm-linux.h" + +#undef IN_SOLIB_CALL_TRAMPOLINE +#undef SKIP_TRAMPOLINE_CODE + +#endif /* #ifndef TM_LINUX_H */ diff --git a/gdb/config/powerpc/obsd.mh b/gdb/config/powerpc/obsd.mh new file mode 100644 index 00000000000..0482d3d3c67 --- /dev/null +++ b/gdb/config/powerpc/obsd.mh @@ -0,0 +1,3 @@ +# Host: OpenBSD/powerpc +NATDEPFILES= ppcobsd-nat.o fork-child.o infptrace.o inftarg.o +NAT_FILE= config/nm-bsd.h diff --git a/gdb/config/powerpc/obsd.mt b/gdb/config/powerpc/obsd.mt new file mode 100644 index 00000000000..a0adcdb3738 --- /dev/null +++ b/gdb/config/powerpc/obsd.mt @@ -0,0 +1,4 @@ +# Target: OpenBSD/powerpc +TDEPFILES= rs6000-tdep.o ppc-sysv-tdep.o ppcobsd-tdep.o \ + corelow.o solib.o solib-svr4.o +DEPRECATED_TM_FILE= tm-nbsd.h diff --git a/gdb/config/vax/nbsd.mt b/gdb/config/vax/nbsd.mt new file mode 100644 index 00000000000..dfe746fd520 --- /dev/null +++ b/gdb/config/vax/nbsd.mt @@ -0,0 +1,3 @@ +# Target: NetBSD/vax +TDEPFILES= vax-tdep.o vaxnbsd-tdep.o corelow.o solib.o solib-svr4.o +DEPRECATED_TM_FILE= solib.h diff --git a/gdb/config/vax/nbsdaout.mh b/gdb/config/vax/nbsdaout.mh new file mode 100644 index 00000000000..688713530d0 --- /dev/null +++ b/gdb/config/vax/nbsdaout.mh @@ -0,0 +1,6 @@ +# Host: NetBSD/vax a.out +NATDEPFILES= vaxbsd-nat.o bsd-kvm.o fork-child.o infptrace.o inftarg.o \ + solib.o solib-sunos.o +NAT_FILE= nm-nbsdaout.h + +LOADLIBES= -lkvm diff --git a/gdb/config/vax/nbsdelf.mh b/gdb/config/vax/nbsdelf.mh new file mode 100644 index 00000000000..06dda18f70a --- /dev/null +++ b/gdb/config/vax/nbsdelf.mh @@ -0,0 +1,5 @@ +# Host: NetBSD/vax ELF +NATDEPFILES= vaxbsd-nat.o bsd-kvm.o fork-child.o infptrace.o inftarg.o +NAT_FILE= config/nm-nbsd.h + +LOADLIBES= -lkvm diff --git a/gdb/config/vax/nm-nbsdaout.h b/gdb/config/vax/nm-nbsdaout.h new file mode 100644 index 00000000000..02504f5e984 --- /dev/null +++ b/gdb/config/vax/nm-nbsdaout.h @@ -0,0 +1,30 @@ +/* Native-dependent definitions for NetBSD/vax a.out. + + Copyright 2004 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef NM_NBSDAOUT_H +#define NM_NBSDAOUT_H + +#include "config/nm-nbsd.h" + +/* Get generic NetBSD a.out native definitions. */ +#include "config/nm-nbsdaout.h" + +#endif /* nm-nbsdaout.h */ diff --git a/gdb/config/vax/obsd.mh b/gdb/config/vax/obsd.mh new file mode 100644 index 00000000000..416f2c62d14 --- /dev/null +++ b/gdb/config/vax/obsd.mh @@ -0,0 +1,5 @@ +# Host: OpenBSD/vax +NATDEPFILES= vaxbsd-nat.o bsd-kvm.o fork-child.o infptrace.o inftarg.o +NAT_FILE= config/nm-bsd.h + +LOADLIBES= -lkvm diff --git a/gdb/config/vax/vax.mh b/gdb/config/vax/vax.mh new file mode 100644 index 00000000000..341aa6bde38 --- /dev/null +++ b/gdb/config/vax/vax.mh @@ -0,0 +1,4 @@ +# Host: VAX running 4.2BSD or Ultrix +NATDEPFILES= vax-nat.o fork-child.o infptrace.o inftarg.o \ + corelow.o core-aout.o +NAT_FILE= nm-vax.h diff --git a/gdb/gdb_ptrace.h b/gdb/gdb_ptrace.h new file mode 100644 index 00000000000..62a9949d413 --- /dev/null +++ b/gdb/gdb_ptrace.h @@ -0,0 +1,114 @@ +/* Portable + + Copyright 2004 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef GDB_PTRACE_H +#define GDB_PTRACE_H + +/* The header was introduced with 4.4BSD, and provided + the PT_* symbolic constants for the ptrace(2) request numbers. The + ptrace(2) prototype was added later to the same header on BSD. + SunOS and GNU/Linux have slightly different symbolic names for the + constants that start with PTRACE_*. System V still doesn't have + (and probably never will have) a with symbolic + constants; the ptrace(2) prototype can be found in . + Fortunately all systems use the same numerical constants for the + common ptrace requests. */ + +#ifdef HAVE_PTRACE_H +# include +#elif defined(HAVE_SYS_PTRACE_H) +# include +#endif + +/* No need to include since it's already included by + "defs.h". */ + +#ifndef PT_READ_I +# define PT_READ_I 1 /* Read word in child's I space. */ +#endif + +#ifndef PT_READ_D +# define PT_READ_D 2 /* Read word in child's D space. */ +#endif + +#ifndef PT_READ_U +# define PT_READ_U 3 /* Read word in child's U space. */ +#endif + +#ifndef PT_WRITE_I +# define PT_WRITE_I 4 /* Write word in child's I space. */ +#endif + +#ifndef PT_WRITE_D +# define PT_WRITE_D 5 /* Write word in child's D space. */ +#endif + +#ifndef PT_WRITE_U +# define PT_WRITE_U 6 /* Write word in child's U space. */ +#endif + +/* HP-UX doesn't define PT_CONTINUE and PT_STEP. Instead of those two + ptrace requests, it has PT_CONTIN, PT_CONTIN1, PT_SINGLE and + PT_SINGLE1. PT_CONTIN1 and PT_SINGLE1 preserve pending signals, + which apparently is what is wanted by the HP-UX native code. */ + +#ifndef PT_CONTINUE +# ifdef PT_CONTIN1 +# define PT_CONTINUE PT_CONTIN1 +# else +# define PT_CONTINUE 7 /* Continue the child. */ +# endif +#endif + +#ifndef PT_KILL +# define PT_KILL 8 /* Kill the child process. */ +#endif + +#ifndef PT_STEP +# ifdef PT_SINGLE1 +# define PT_STEP PT_SINGLE1 +# else +# define PT_STEP 9 /* Single step the child. */ +# endif +#endif + +/* Not all systems support attaching and detaching. */ + +#ifndef PT_ATTCH +# ifdef PTRACE_DETACH +# define PT_ATTACH PTRACE_ATTACH +# endif +#endif + +#ifndef PT_DETACH +# ifdef PTRACE_DETACH +# define PT_DETACH PTRACE_DETACH +# endif +#endif + +/* Some systems, in particular DEC OSF/1, Digital Unix, Compaq Tru64 + or whatever it's called these days, don't provide a prototype for + ptrace. Provide one to silence compiler warnings. */ +#ifndef HAVE_DECL_PTRACE +extern PTRACE_TYPE_RET ptrace(); +#endif + +#endif /* gdb_ptrace.h */ diff --git a/gdb/hppa-linux-nat.c b/gdb/hppa-linux-nat.c new file mode 100644 index 00000000000..b6a4f2091a4 --- /dev/null +++ b/gdb/hppa-linux-nat.c @@ -0,0 +1,376 @@ +/* Functions specific to running GDB native on HPPA running GNU/Linux. + + Copyright 2004 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include "defs.h" +#include "gdbcore.h" +#include "regcache.h" +#include "gdb_string.h" +#include "inferior.h" + +#include +#include +#include + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,43) +#include +#else +#include +#endif + +#include "hppa-tdep.h" + +/* Prototypes for supply_gregset etc. */ +#include "gregset.h" + +/* These must match the order of the register names. + + Some sort of lookup table is needed because the offsets associated + with the registers are all over the board. */ + +static const int u_offsets[] = + { + /* general registers */ + -1, + PT_GR1, + PT_GR2, + PT_GR3, + PT_GR4, + PT_GR5, + PT_GR6, + PT_GR7, + PT_GR8, + PT_GR9, + PT_GR10, + PT_GR11, + PT_GR12, + PT_GR13, + PT_GR14, + PT_GR15, + PT_GR16, + PT_GR17, + PT_GR18, + PT_GR19, + PT_GR20, + PT_GR21, + PT_GR22, + PT_GR23, + PT_GR24, + PT_GR25, + PT_GR26, + PT_GR27, + PT_GR28, + PT_GR29, + PT_GR30, + PT_GR31, + + PT_SAR, + PT_IAOQ0, + PT_IASQ0, + PT_IAOQ1, + PT_IASQ1, + -1, /* eiem */ + PT_IIR, + PT_ISR, + PT_IOR, + PT_PSW, + -1, /* goto */ + + PT_SR4, + PT_SR0, + PT_SR1, + PT_SR2, + PT_SR3, + PT_SR5, + PT_SR6, + PT_SR7, + + -1, /* cr0 */ + -1, /* pid0 */ + -1, /* pid1 */ + -1, /* ccr */ + -1, /* pid2 */ + -1, /* pid3 */ + -1, /* cr24 */ + -1, /* cr25 */ + -1, /* cr26 */ + PT_CR27, + -1, /* cr28 */ + -1, /* cr29 */ + -1, /* cr30 */ + + /* Floating point regs. */ + PT_FR0, PT_FR0 + 4, + PT_FR1, PT_FR1 + 4, + PT_FR2, PT_FR2 + 4, + PT_FR3, PT_FR3 + 4, + PT_FR4, PT_FR4 + 4, + PT_FR5, PT_FR5 + 4, + PT_FR6, PT_FR6 + 4, + PT_FR7, PT_FR7 + 4, + PT_FR8, PT_FR8 + 4, + PT_FR9, PT_FR9 + 4, + PT_FR10, PT_FR10 + 4, + PT_FR11, PT_FR11 + 4, + PT_FR12, PT_FR12 + 4, + PT_FR13, PT_FR13 + 4, + PT_FR14, PT_FR14 + 4, + PT_FR15, PT_FR15 + 4, + PT_FR16, PT_FR16 + 4, + PT_FR17, PT_FR17 + 4, + PT_FR18, PT_FR18 + 4, + PT_FR19, PT_FR19 + 4, + PT_FR20, PT_FR20 + 4, + PT_FR21, PT_FR21 + 4, + PT_FR22, PT_FR22 + 4, + PT_FR23, PT_FR23 + 4, + PT_FR24, PT_FR24 + 4, + PT_FR25, PT_FR25 + 4, + PT_FR26, PT_FR26 + 4, + PT_FR27, PT_FR27 + 4, + PT_FR28, PT_FR28 + 4, + PT_FR29, PT_FR29 + 4, + PT_FR30, PT_FR30 + 4, + PT_FR31, PT_FR31 + 4, + }; + +CORE_ADDR +register_addr (int regno, CORE_ADDR blockend) +{ + CORE_ADDR addr; + + if ((unsigned) regno >= NUM_REGS) + error ("Invalid register number %d.", regno); + + if (u_offsets[regno] == -1) + addr = 0; + else + { + addr = (CORE_ADDR) u_offsets[regno]; + } + + return addr; +} + +/* + * Registers saved in a coredump: + * gr0..gr31 + * sr0..sr7 + * iaoq0..iaoq1 + * iasq0..iasq1 + * sar, iir, isr, ior, ipsw + * cr0, cr24..cr31 + * cr8,9,12,13 + * cr10, cr15 + */ +#define GR_REGNUM(_n) (HPPA_R0_REGNUM+_n) +#define TR_REGNUM(_n) (HPPA_TR0_REGNUM+_n) +static const int greg_map[] = + { + GR_REGNUM(0), GR_REGNUM(1), GR_REGNUM(2), GR_REGNUM(3), + GR_REGNUM(4), GR_REGNUM(5), GR_REGNUM(6), GR_REGNUM(7), + GR_REGNUM(8), GR_REGNUM(9), GR_REGNUM(10), GR_REGNUM(11), + GR_REGNUM(12), GR_REGNUM(13), GR_REGNUM(14), GR_REGNUM(15), + GR_REGNUM(16), GR_REGNUM(17), GR_REGNUM(18), GR_REGNUM(19), + GR_REGNUM(20), GR_REGNUM(21), GR_REGNUM(22), GR_REGNUM(23), + GR_REGNUM(24), GR_REGNUM(25), GR_REGNUM(26), GR_REGNUM(27), + GR_REGNUM(28), GR_REGNUM(29), GR_REGNUM(30), GR_REGNUM(31), + + HPPA_SR4_REGNUM+1, HPPA_SR4_REGNUM+2, HPPA_SR4_REGNUM+3, HPPA_SR4_REGNUM+4, + HPPA_SR4_REGNUM, HPPA_SR4_REGNUM+5, HPPA_SR4_REGNUM+6, HPPA_SR4_REGNUM+7, + + HPPA_PCOQ_HEAD_REGNUM, HPPA_PCOQ_TAIL_REGNUM, + HPPA_PCSQ_HEAD_REGNUM, HPPA_PCSQ_TAIL_REGNUM, + + HPPA_SAR_REGNUM, HPPA_IIR_REGNUM, HPPA_ISR_REGNUM, HPPA_IOR_REGNUM, + HPPA_IPSW_REGNUM, HPPA_RCR_REGNUM, + + TR_REGNUM(0), TR_REGNUM(1), TR_REGNUM(2), TR_REGNUM(3), + TR_REGNUM(4), TR_REGNUM(5), TR_REGNUM(6), TR_REGNUM(7), + + HPPA_PID0_REGNUM, HPPA_PID1_REGNUM, HPPA_PID2_REGNUM, HPPA_PID3_REGNUM, + HPPA_CCR_REGNUM, HPPA_EIEM_REGNUM, + }; + + + +/* Fetch one register. */ + +static void +fetch_register (int regno) +{ + int tid; + int val; + + if (CANNOT_FETCH_REGISTER (regno)) + { + regcache_raw_supply (current_regcache, regno, NULL); + return; + } + + /* GNU/Linux LWP ID's are process ID's. */ + tid = TIDGET (inferior_ptid); + if (tid == 0) + tid = PIDGET (inferior_ptid); /* Not a threaded program. */ + + errno = 0; + val = ptrace (PTRACE_PEEKUSER, tid, register_addr (regno, 0), 0); + if (errno != 0) + error ("Couldn't read register %s (#%d): %s.", REGISTER_NAME (regno), + regno, safe_strerror (errno)); + + regcache_raw_supply (current_regcache, regno, &val); +} + +/* Store one register. */ + +static void +store_register (int regno) +{ + int tid; + int val; + + if (CANNOT_STORE_REGISTER (regno)) + return; + + /* GNU/Linux LWP ID's are process ID's. */ + tid = TIDGET (inferior_ptid); + if (tid == 0) + tid = PIDGET (inferior_ptid); /* Not a threaded program. */ + + errno = 0; + regcache_raw_collect (current_regcache, regno, &val); + ptrace (PTRACE_POKEUSER, tid, register_addr (regno, 0), val); + if (errno != 0) + error ("Couldn't write register %s (#%d): %s.", REGISTER_NAME (regno), + regno, safe_strerror (errno)); +} + +/* Fetch registers from the child process. Fetch all registers if + regno == -1, otherwise fetch all general registers or all floating + point registers depending upon the value of regno. */ + +void +fetch_inferior_registers (int regno) +{ + if (-1 == regno) + { + for (regno = 0; regno < NUM_REGS; regno++) + fetch_register (regno); + } + else + { + fetch_register (regno); + } +} + +/* Store registers back into the inferior. Store all registers if + regno == -1, otherwise store all general registers or all floating + point registers depending upon the value of regno. */ + +void +store_inferior_registers (int regno) +{ + if (-1 == regno) + { + for (regno = 0; regno < NUM_REGS; regno++) + store_register (regno); + } + else + { + store_register (regno); + } +} + +/* Fill GDB's register array with the general-purpose register values + in *gregsetp. */ + +void +supply_gregset (gdb_gregset_t *gregsetp) +{ + int i; + greg_t *regp = (elf_greg_t *) gregsetp; + + for (i = 0; i < sizeof (greg_map) / sizeof (greg_map[0]); i++, regp++) + { + int regno = greg_map[i]; + regcache_raw_supply (current_regcache, regno, regp); + } +} + +/* Fill register regno (if it is a general-purpose register) in + *gregsetp with the appropriate value from GDB's register array. + If regno is -1, do this for all registers. */ + +void +fill_gregset (gdb_gregset_t *gregsetp, int regno) +{ + int i; + + for (i = 0; i < sizeof (greg_map) / sizeof (greg_map[0]); i++) + { + int mregno = greg_map[i]; + + if (regno == -1 || regno == mregno) + { + regcache_raw_collect(current_regcache, mregno, &(*gregsetp)[i]); + } + } +} + +/* Given a pointer to a floating point register set in /proc format + (fpregset_t *), unpack the register contents and supply them as gdb's + idea of the current floating point register values. */ + +void +supply_fpregset (gdb_fpregset_t *fpregsetp) +{ + int regi; + char *from; + + for (regi = 0; regi <= 31; regi++) + { + from = (char *) &((*fpregsetp)[regi]); + regcache_raw_supply (current_regcache, 2*regi + HPPA_FP0_REGNUM, from); + regcache_raw_supply (current_regcache, 2*regi + HPPA_FP0_REGNUM + 1, + from + 4); + } +} + +/* Given a pointer to a floating point register set in /proc format + (fpregset_t *), update the register specified by REGNO from gdb's idea + of the current floating point register set. If REGNO is -1, update + them all. */ + +void +fill_fpregset (gdb_fpregset_t *fpregsetp, int regno) +{ + int i; + + for (i = HPPA_FP0_REGNUM; i < HPPA_FP0_REGNUM + 32 * 2; i++) + { + /* Gross. fpregset_t is double, registers[x] has single + precision reg. */ + char *to = (char *) &((*fpregsetp)[(i - HPPA_FP0_REGNUM) / 2]); + if ((i - HPPA_FP0_REGNUM) & 1) + to += 4; + regcache_raw_collect (current_regcache, i, to); + } +} diff --git a/gdb/hppa-linux-tdep.c b/gdb/hppa-linux-tdep.c new file mode 100644 index 00000000000..7f32236274d --- /dev/null +++ b/gdb/hppa-linux-tdep.c @@ -0,0 +1,592 @@ +/* Target-dependent code for GNU/Linux running on PA-RISC, for GDB. + + Copyright 2004 Free Software Foundation, Inc. + +This file is part of GDB. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include "defs.h" +#include "gdbcore.h" +#include "osabi.h" +#include "target.h" +#include "objfiles.h" +#include "solib-svr4.h" +#include "glibc-tdep.h" +#include "frame-unwind.h" +#include "trad-frame.h" +#include "dwarf2-frame.h" +#include "value.h" +#include "hppa-tdep.h" + +#include "elf/common.h" + +#if 0 +/* Convert DWARF register number REG to the appropriate register + number used by GDB. */ +static int +hppa_dwarf_reg_to_regnum (int reg) +{ + /* registers 0 - 31 are the same in both sets */ + if (reg < 32) + return reg; + + /* dwarf regs 32 to 85 are fpregs 4 - 31 */ + if (reg >= 32 && reg <= 85) + return HPPA_FP4_REGNUM + (reg - 32); + + warning ("Unmapped DWARF Register #%d encountered\n", reg); + return -1; +} +#endif + +static void +hppa_linux_target_write_pc (CORE_ADDR v, ptid_t ptid) +{ + /* Probably this should be done by the kernel, but it isn't. */ + write_register_pid (HPPA_PCOQ_HEAD_REGNUM, v | 0x3, ptid); + write_register_pid (HPPA_PCOQ_TAIL_REGNUM, (v + 4) | 0x3, ptid); +} + +/* An instruction to match. */ +struct insn_pattern +{ + unsigned int data; /* See if it matches this.... */ + unsigned int mask; /* ... with this mask. */ +}; + +/* See bfd/elf32-hppa.c */ +static struct insn_pattern hppa_long_branch_stub[] = { + /* ldil LR'xxx,%r1 */ + { 0x20200000, 0xffe00000 }, + /* be,n RR'xxx(%sr4,%r1) */ + { 0xe0202002, 0xffe02002 }, + { 0, 0 } +}; + +static struct insn_pattern hppa_long_branch_pic_stub[] = { + /* b,l .+8, %r1 */ + { 0xe8200000, 0xffe00000 }, + /* addil LR'xxx - ($PIC_pcrel$0 - 4), %r1 */ + { 0x28200000, 0xffe00000 }, + /* be,n RR'xxxx - ($PIC_pcrel$0 - 8)(%sr4, %r1) */ + { 0xe0202002, 0xffe02002 }, + { 0, 0 } +}; + +static struct insn_pattern hppa_import_stub[] = { + /* addil LR'xxx, %dp */ + { 0x2b600000, 0xffe00000 }, + /* ldw RR'xxx(%r1), %r21 */ + { 0x48350000, 0xffffb000 }, + /* bv %r0(%r21) */ + { 0xeaa0c000, 0xffffffff }, + /* ldw RR'xxx+4(%r1), %r19 */ + { 0x48330000, 0xffffb000 }, + { 0, 0 } +}; + +static struct insn_pattern hppa_import_pic_stub[] = { + /* addil LR'xxx,%r19 */ + { 0x2a600000, 0xffe00000 }, + /* ldw RR'xxx(%r1),%r21 */ + { 0x48350000, 0xffffb000 }, + /* bv %r0(%r21) */ + { 0xeaa0c000, 0xffffffff }, + /* ldw RR'xxx+4(%r1),%r19 */ + { 0x48330000, 0xffffb000 }, + { 0, 0 }, +}; + +static struct insn_pattern hppa_plt_stub[] = { + /* b,l 1b, %r20 - 1b is 3 insns before here */ + { 0xea9f1fdd, 0xffffffff }, + /* depi 0,31,2,%r20 */ + { 0xd6801c1e, 0xffffffff }, + { 0, 0 } +}; + +static struct insn_pattern hppa_sigtramp[] = { + /* ldi 0, %r25 or ldi 1, %r25 */ + { 0x34190000, 0xfffffffd }, + /* ldi __NR_rt_sigreturn, %r20 */ + { 0x3414015a, 0xffffffff }, + /* be,l 0x100(%sr2, %r0), %sr0, %r31 */ + { 0xe4008200, 0xffffffff }, + /* nop */ + { 0x08000240, 0xffffffff }, + { 0, 0 } +}; + +#define HPPA_MAX_INSN_PATTERN_LEN (4) + +/* Return non-zero if the instructions at PC match the series + described in PATTERN, or zero otherwise. PATTERN is an array of + 'struct insn_pattern' objects, terminated by an entry whose mask is + zero. + + When the match is successful, fill INSN[i] with what PATTERN[i] + matched. */ +static int +insns_match_pattern (CORE_ADDR pc, + struct insn_pattern *pattern, + unsigned int *insn) +{ + int i; + CORE_ADDR npc = pc; + + for (i = 0; pattern[i].mask; i++) + { + char buf[4]; + + deprecated_read_memory_nobpt (npc, buf, 4); + insn[i] = extract_unsigned_integer (buf, 4); + if ((insn[i] & pattern[i].mask) == pattern[i].data) + npc += 4; + else + return 0; + } + return 1; +} + +static int +hppa_linux_in_dyncall (CORE_ADDR pc) +{ + return pc == hppa_symbol_address("$$dyncall"); +} + +/* There are several kinds of "trampolines" that we need to deal with: + - long branch stubs: these are inserted by the linker when a branch + target is too far away for a branch insn to reach + - plt stubs: these should go into the .plt section, so are easy to find + - import stubs: used to call from object to shared lib or shared lib to + shared lib; these go in regular text sections. In fact the linker tries + to put them throughout the code because branches have limited reachability. + We use the same mechanism as ppc64 to recognize the stub insn patterns. + - $$dyncall: similar to hpux, hppa-linux uses $$dyncall for indirect function + calls. $$dyncall is exported by libgcc.a */ +static int +hppa_linux_in_solib_call_trampoline (CORE_ADDR pc, char *name) +{ + unsigned int insn[HPPA_MAX_INSN_PATTERN_LEN]; + int r; + + r = in_plt_section (pc, name) + || hppa_linux_in_dyncall (pc) + || insns_match_pattern (pc, hppa_import_stub, insn) + || insns_match_pattern (pc, hppa_import_pic_stub, insn) + || insns_match_pattern (pc, hppa_long_branch_stub, insn) + || insns_match_pattern (pc, hppa_long_branch_pic_stub, insn); + + return r; +} + +static CORE_ADDR +hppa_linux_skip_trampoline_code (CORE_ADDR pc) +{ + unsigned int insn[HPPA_MAX_INSN_PATTERN_LEN]; + int dp_rel, pic_rel; + + /* dyncall handles both PLABELs and direct addresses */ + if (hppa_linux_in_dyncall (pc)) + { + pc = (CORE_ADDR) read_register (22); + + /* PLABELs have bit 30 set; if it's a PLABEL, then dereference it */ + if (pc & 0x2) + pc = (CORE_ADDR) read_memory_integer (pc & ~0x3, TARGET_PTR_BIT / 8); + + return pc; + } + + dp_rel = pic_rel = 0; + if ((dp_rel = insns_match_pattern (pc, hppa_import_stub, insn)) + || (pic_rel = insns_match_pattern (pc, hppa_import_pic_stub, insn))) + { + /* Extract the target address from the addil/ldw sequence. */ + pc = hppa_extract_21 (insn[0]) + hppa_extract_14 (insn[1]); + + if (dp_rel) + pc += (CORE_ADDR) read_register (27); + else + pc += (CORE_ADDR) read_register (19); + + /* fallthrough */ + } + + if (in_plt_section (pc, NULL)) + { + pc = (CORE_ADDR) read_memory_integer (pc, TARGET_PTR_BIT / 8); + + /* if the plt slot has not yet been resolved, the target will + be the plt stub */ + if (in_plt_section (pc, NULL)) + { + /* Sanity check: are we pointing to the plt stub? */ + if (insns_match_pattern (pc, hppa_plt_stub, insn)) + { + /* this should point to the fixup routine */ + pc = (CORE_ADDR) read_memory_integer (pc + 8, TARGET_PTR_BIT / 8); + } + else + { + error ("Cannot resolve plt stub at 0x%s\n", + paddr_nz (pc)); + pc = 0; + } + } + } + + return pc; +} + +/* Signal frames. */ + +/* (This is derived from MD_FALLBACK_FRAME_STATE_FOR in gcc.) + + Unfortunately, because of various bugs and changes to the kernel, + we have several cases to deal with. + + In 2.4, the signal trampoline is 4 bytes, and pc should point directly at + the beginning of the trampoline and struct rt_sigframe. + + In <= 2.6.5-rc2-pa3, the signal trampoline is 9 bytes, and pc points at + the 4th word in the trampoline structure. This is wrong, it should point + at the 5th word. This is fixed in 2.6.5-rc2-pa4. + + To detect these cases, we first take pc, align it to 64-bytes + to get the beginning of the signal frame, and then check offsets 0, 4 + and 5 to see if we found the beginning of the trampoline. This will + tell us how to locate the sigcontext structure. + + Note that with a 2.4 64-bit kernel, the signal context is not properly + passed back to userspace so the unwind will not work correctly. */ +static CORE_ADDR +hppa_linux_sigtramp_find_sigcontext (CORE_ADDR pc) +{ + unsigned int dummy[HPPA_MAX_INSN_PATTERN_LEN]; + int offs = 0; + int try; + /* offsets to try to find the trampoline */ + static int pcoffs[] = { 0, 4*4, 5*4 }; + /* offsets to the rt_sigframe structure */ + static int sfoffs[] = { 4*4, 10*4, 10*4 }; + CORE_ADDR sp; + + /* Most of the time, this will be correct. The one case when this will + fail is if the user defined an alternate stack, in which case the + beginning of the stack will not be align_down (pc, 64). */ + sp = align_down (pc, 64); + + /* rt_sigreturn trampoline: + 3419000x ldi 0, %r25 or ldi 1, %r25 (x = 0 or 2) + 3414015a ldi __NR_rt_sigreturn, %r20 + e4008200 be,l 0x100(%sr2, %r0), %sr0, %r31 + 08000240 nop */ + + for (try = 0; try < ARRAY_SIZE (pcoffs); try++) + { + if (insns_match_pattern (sp + pcoffs[try], hppa_sigtramp, dummy)) + { + offs = sfoffs[try]; + break; + } + } + + if (offs == 0) + { + if (insns_match_pattern (pc, hppa_sigtramp, dummy)) + { + /* sigaltstack case: we have no way of knowing which offset to + use in this case; default to new kernel handling. If this is + wrong the unwinding will fail. */ + try = 2; + sp = pc - pcoffs[try]; + } + else + { + return 0; + } + } + + /* sp + sfoffs[try] points to a struct rt_sigframe, which contains + a struct siginfo and a struct ucontext. struct ucontext contains + a struct sigcontext. Return an offset to this sigcontext here. Too + bad we cannot include system specific headers :-(. + sizeof(struct siginfo) == 128 + offsetof(struct ucontext, uc_mcontext) == 24. */ + return sp + sfoffs[try] + 128 + 24; +} + +struct hppa_linux_sigtramp_unwind_cache +{ + CORE_ADDR base; + struct trad_frame_saved_reg *saved_regs; +}; + +static struct hppa_linux_sigtramp_unwind_cache * +hppa_linux_sigtramp_frame_unwind_cache (struct frame_info *next_frame, + void **this_cache) +{ + struct gdbarch *gdbarch = get_frame_arch (next_frame); + struct hppa_linux_sigtramp_unwind_cache *info; + CORE_ADDR pc, scptr; + int i; + + if (*this_cache) + return *this_cache; + + info = FRAME_OBSTACK_ZALLOC (struct hppa_linux_sigtramp_unwind_cache); + *this_cache = info; + info->saved_regs = trad_frame_alloc_saved_regs (next_frame); + + pc = frame_pc_unwind (next_frame); + scptr = hppa_linux_sigtramp_find_sigcontext (pc); + + /* structure of struct sigcontext: + + struct sigcontext { + unsigned long sc_flags; + unsigned long sc_gr[32]; + unsigned long long sc_fr[32]; + unsigned long sc_iasq[2]; + unsigned long sc_iaoq[2]; + unsigned long sc_sar; */ + + /* Skip sc_flags. */ + scptr += 4; + + /* GR[0] is the psw, we don't restore that. */ + scptr += 4; + + /* General registers. */ + for (i = 1; i < 32; i++) + { + info->saved_regs[HPPA_R0_REGNUM + i].addr = scptr; + scptr += 4; + } + + /* Pad. */ + scptr += 4; + + /* FP regs; FP0-3 are not restored. */ + scptr += (8 * 4); + + for (i = 4; i < 32; i++) + { + info->saved_regs[HPPA_FP0_REGNUM + (i * 2)].addr = scptr; + scptr += 4; + info->saved_regs[HPPA_FP0_REGNUM + (i * 2) + 1].addr = scptr; + scptr += 4; + } + + /* IASQ/IAOQ. */ + info->saved_regs[HPPA_PCSQ_HEAD_REGNUM].addr = scptr; + scptr += 4; + info->saved_regs[HPPA_PCSQ_TAIL_REGNUM].addr = scptr; + scptr += 4; + + info->saved_regs[HPPA_PCOQ_HEAD_REGNUM].addr = scptr; + scptr += 4; + info->saved_regs[HPPA_PCOQ_TAIL_REGNUM].addr = scptr; + scptr += 4; + + info->base = frame_unwind_register_unsigned (next_frame, HPPA_SP_REGNUM); + + return info; +} + +static void +hppa_linux_sigtramp_frame_this_id (struct frame_info *next_frame, + void **this_prologue_cache, + struct frame_id *this_id) +{ + struct hppa_linux_sigtramp_unwind_cache *info + = hppa_linux_sigtramp_frame_unwind_cache (next_frame, this_prologue_cache); + *this_id = frame_id_build (info->base, frame_pc_unwind (next_frame)); +} + +static void +hppa_linux_sigtramp_frame_prev_register (struct frame_info *next_frame, + void **this_prologue_cache, + int regnum, int *optimizedp, + enum lval_type *lvalp, + CORE_ADDR *addrp, + int *realnump, void *valuep) +{ + struct hppa_linux_sigtramp_unwind_cache *info + = hppa_linux_sigtramp_frame_unwind_cache (next_frame, this_prologue_cache); + hppa_frame_prev_register_helper (next_frame, info->saved_regs, regnum, + optimizedp, lvalp, addrp, realnump, valuep); +} + +static const struct frame_unwind hppa_linux_sigtramp_frame_unwind = { + SIGTRAMP_FRAME, + hppa_linux_sigtramp_frame_this_id, + hppa_linux_sigtramp_frame_prev_register +}; + +/* hppa-linux always uses "new-style" rt-signals. The signal handler's return + address should point to a signal trampoline on the stack. The signal + trampoline is embedded in a rt_sigframe structure that is aligned on + the stack. We take advantage of the fact that sp must be 64-byte aligned, + and the trampoline is small, so by rounding down the trampoline address + we can find the beginning of the struct rt_sigframe. */ +static const struct frame_unwind * +hppa_linux_sigtramp_unwind_sniffer (struct frame_info *next_frame) +{ + CORE_ADDR pc = frame_pc_unwind (next_frame); + + if (hppa_linux_sigtramp_find_sigcontext (pc)) + return &hppa_linux_sigtramp_frame_unwind; + + return NULL; +} + +/* Attempt to find (and return) the global pointer for the given + function. + + This is a rather nasty bit of code searchs for the .dynamic section + in the objfile corresponding to the pc of the function we're trying + to call. Once it finds the addresses at which the .dynamic section + lives in the child process, it scans the Elf32_Dyn entries for a + DT_PLTGOT tag. If it finds one of these, the corresponding + d_un.d_ptr value is the global pointer. */ + +static CORE_ADDR +hppa_linux_find_global_pointer (struct value *function) +{ + struct obj_section *faddr_sect; + CORE_ADDR faddr; + + faddr = value_as_address (function); + + /* Is this a plabel? If so, dereference it to get the gp value. */ + if (faddr & 2) + { + int status; + char buf[4]; + + faddr &= ~3; + + status = target_read_memory (faddr + 4, buf, sizeof (buf)); + if (status == 0) + return extract_unsigned_integer (buf, sizeof (buf)); + } + + /* If the address is in the plt section, then the real function hasn't + yet been fixed up by the linker so we cannot determine the gp of + that function. */ + if (in_plt_section (faddr, NULL)) + return 0; + + faddr_sect = find_pc_section (faddr); + if (faddr_sect != NULL) + { + struct obj_section *osect; + + ALL_OBJFILE_OSECTIONS (faddr_sect->objfile, osect) + { + if (strcmp (osect->the_bfd_section->name, ".dynamic") == 0) + break; + } + + if (osect < faddr_sect->objfile->sections_end) + { + CORE_ADDR addr; + + addr = osect->addr; + while (addr < osect->endaddr) + { + int status; + LONGEST tag; + char buf[4]; + + status = target_read_memory (addr, buf, sizeof (buf)); + if (status != 0) + break; + tag = extract_signed_integer (buf, sizeof (buf)); + + if (tag == DT_PLTGOT) + { + CORE_ADDR global_pointer; + + status = target_read_memory (addr + 4, buf, sizeof (buf)); + if (status != 0) + break; + global_pointer = extract_unsigned_integer (buf, sizeof (buf)); + + /* The payoff... */ + return global_pointer; + } + + if (tag == DT_NULL) + break; + + addr += 8; + } + } + } + return 0; +} + +/* Forward declarations. */ +extern initialize_file_ftype _initialize_hppa_linux_tdep; + +static void +hppa_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) +{ + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + + /* GNU/Linux is always ELF. */ + tdep->is_elf = 1; + + tdep->find_global_pointer = hppa_linux_find_global_pointer; + + set_gdbarch_write_pc (gdbarch, hppa_linux_target_write_pc); + + frame_unwind_append_sniffer (gdbarch, hppa_linux_sigtramp_unwind_sniffer); + + /* GNU/Linux uses SVR4-style shared libraries. */ + set_solib_svr4_fetch_link_map_offsets + (gdbarch, svr4_ilp32_fetch_link_map_offsets); + + set_gdbarch_in_solib_call_trampoline + (gdbarch, hppa_linux_in_solib_call_trampoline); + set_gdbarch_skip_trampoline_code + (gdbarch, hppa_linux_skip_trampoline_code); + + /* GNU/Linux uses the dynamic linker included in the GNU C Library. */ + set_gdbarch_skip_solib_resolver (gdbarch, glibc_skip_solib_resolver); + + /* On hppa-linux, currently, sizeof(long double) == 8. There has been + some discussions to support 128-bit long double, but it requires some + more work in gcc and glibc first. */ + set_gdbarch_long_double_bit (gdbarch, 64); + +#if 0 + /* Dwarf-2 unwinding support. Not yet working. */ + set_gdbarch_dwarf_reg_to_regnum (gdbarch, hppa_dwarf_reg_to_regnum); + set_gdbarch_dwarf2_reg_to_regnum (gdbarch, hppa_dwarf_reg_to_regnum); + frame_unwind_append_sniffer (gdbarch, dwarf2_frame_sniffer); + frame_base_append_sniffer (gdbarch, dwarf2_frame_base_sniffer); +#endif +} + +void +_initialize_hppa_linux_tdep (void) +{ + gdbarch_register_osabi (bfd_arch_hppa, 0, GDB_OSABI_LINUX, hppa_linux_init_abi); +} diff --git a/gdb/hppabsd-nat.c b/gdb/hppabsd-nat.c new file mode 100644 index 00000000000..fb53c967558 --- /dev/null +++ b/gdb/hppabsd-nat.c @@ -0,0 +1,119 @@ +/* Native-dependent code for HP PA-RISC BSD's. + + Copyright 2004 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include "defs.h" +#include "inferior.h" +#include "regcache.h" + +#include +#include +#include + +#include "hppa-tdep.h" + +static int +hppabsd_gregset_supplies_p (int regnum) +{ + return (regnum >= HPPA_R0_REGNUM && regnum <= HPPA_PCOQ_TAIL_REGNUM); +} + +/* Supply the general-purpose registers stored in GREGS to REGCACHE. */ + +static void +hppabsd_supply_gregset (struct regcache *regcache, const void *gregs) +{ + const char *regs = gregs; + int regnum; + + for (regnum = HPPA_R1_REGNUM; regnum <= HPPA_R31_REGNUM; regnum++) + regcache_raw_supply (regcache, regnum, regs + regnum * 4); + + regcache_raw_supply (regcache, HPPA_SAR_REGNUM, regs); + regcache_raw_supply (regcache, HPPA_PCOQ_HEAD_REGNUM, regs + 32 * 4); + regcache_raw_supply (regcache, HPPA_PCOQ_TAIL_REGNUM, regs + 33 * 4); +} + +/* Collect the general-purpose registers from REGCACHE and store them + in GREGS. */ + +static void +hppabsd_collect_gregset (const struct regcache *regcache, + void *gregs, int regnum) +{ + char *regs = gregs; + int i; + + for (i = HPPA_R1_REGNUM; i <= HPPA_R31_REGNUM; i++) + { + if (regnum == -1 || regnum == i) + regcache_raw_collect (regcache, i, regs + i * 4); + } + + if (regnum == -1 || regnum == HPPA_SAR_REGNUM) + regcache_raw_collect (regcache, HPPA_SAR_REGNUM, regs); + if (regnum == -1 || regnum == HPPA_PCOQ_HEAD_REGNUM) + regcache_raw_collect (regcache, HPPA_PCOQ_HEAD_REGNUM, regs + 32 * 4); + if (regnum == -1 || regnum == HPPA_PCOQ_TAIL_REGNUM) + regcache_raw_collect (regcache, HPPA_PCOQ_TAIL_REGNUM, regs + 33 * 4); +} + + +/* Fetch register REGNUM from the inferior. If REGNUM is -1, do this + for all registers (including the floating-point registers). */ + +void +fetch_inferior_registers (int regnum) +{ + struct regcache *regcache = current_regcache; + + if (regnum == -1 || hppabsd_gregset_supplies_p (regnum)) + { + struct reg regs; + + if (ptrace (PT_GETREGS, PIDGET (inferior_ptid), + (PTRACE_TYPE_ARG3) ®s, 0) == -1) + perror_with_name ("Couldn't get registers"); + + hppabsd_supply_gregset (regcache, ®s); + } +} + +/* Store register REGNUM back into the inferior. If REGNUM is -1, do + this for all registers (including the floating-point registers). */ + +void +store_inferior_registers (int regnum) +{ + if (regnum == -1 || hppabsd_gregset_supplies_p (regnum)) + { + struct reg regs; + + if (ptrace (PT_GETREGS, PIDGET (inferior_ptid), + (PTRACE_TYPE_ARG3) ®s, 0) == -1) + perror_with_name ("Couldn't get registers"); + + hppabsd_collect_gregset (current_regcache, ®s, regnum); + + if (ptrace (PT_SETREGS, PIDGET (inferior_ptid), + (PTRACE_TYPE_ARG3) ®s, 0) == -1) + perror_with_name ("Couldn't write registers"); + } +} diff --git a/gdb/hppabsd-tdep.c b/gdb/hppabsd-tdep.c new file mode 100644 index 00000000000..0a54371527d --- /dev/null +++ b/gdb/hppabsd-tdep.c @@ -0,0 +1,137 @@ +/* Target-dependent code for HP PA-RISC BSD's. + + Copyright 2004 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include "defs.h" +#include "arch-utils.h" +#include "osabi.h" +#include "regcache.h" +#include "regset.h" + +#include "gdb_assert.h" +#include "gdb_string.h" + +#include "hppa-tdep.h" +#include "solib-svr4.h" + +/* Core file support. */ + +/* Sizeof `struct reg' in . */ +#define HPPABSD_SIZEOF_GREGS (34 * 4) + +/* Supply register REGNUM from the buffer specified by GREGS and LEN + in the general-purpose register set REGSET to register cache + REGCACHE. If REGNUM is -1, do this for all registers in REGSET. */ + +static void +hppabsd_supply_gregset (const struct regset *regset, struct regcache *regcache, + int regnum, const void *gregs, size_t len) +{ + const char *regs = gregs; + size_t offset; + int i; + + gdb_assert (len >= HPPABSD_SIZEOF_GREGS); + + for (i = HPPA_R1_REGNUM, offset = 4; i <= HPPA_R31_REGNUM; i++, offset += 4) + { + if (regnum == -1 || regnum == i) + regcache_raw_supply (regcache, i, regs + offset); + } + + if (regnum == -1 || regnum == HPPA_SAR_REGNUM) + regcache_raw_supply (regcache, HPPA_SAR_REGNUM, regs); + if (regnum == -1 || regnum == HPPA_PCOQ_HEAD_REGNUM) + regcache_raw_supply (regcache, HPPA_PCOQ_HEAD_REGNUM, regs + 32 * 4); + if (regnum == -1 || regnum == HPPA_PCOQ_TAIL_REGNUM) + regcache_raw_supply (regcache, HPPA_PCOQ_TAIL_REGNUM, regs + 33 * 4); +} + +/* OpenBSD/hppa register set. */ + +static struct regset hppabsd_gregset = +{ + NULL, + hppabsd_supply_gregset +}; + +/* Return the appropriate register set for the core section identified + by SECT_NAME and SECT_SIZE. */ + +static const struct regset * +hppabsd_regset_from_core_section (struct gdbarch *gdbarch, + const char *sect_name, size_t sect_size) +{ + if (strcmp (sect_name, ".reg") == 0 && sect_size >= HPPABSD_SIZEOF_GREGS) + return &hppabsd_gregset; + + return NULL; +} + + +static void +hppabsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) +{ + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + + /* Core file support. */ + set_gdbarch_regset_from_core_section + (gdbarch, hppabsd_regset_from_core_section); + + /* OpenBSD and NetBSD use ELF. */ + tdep->is_elf = 1; + + /* OpenBSD and NetBSD uses SVR4-style shared libraries. */ + set_gdbarch_in_solib_call_trampoline + (gdbarch, generic_in_solib_call_trampoline); + set_solib_svr4_fetch_link_map_offsets + (gdbarch, svr4_ilp32_fetch_link_map_offsets); +} + + +/* OpenBSD uses uses the traditional NetBSD core file format, even for + ports that use ELF. */ +#define GDB_OSABI_NETBSD_CORE GDB_OSABI_OPENBSD_ELF + +static enum gdb_osabi +hppabsd_core_osabi_sniffer (bfd *abfd) +{ + if (strcmp (bfd_get_target (abfd), "netbsd-core") == 0) + return GDB_OSABI_NETBSD_CORE; + + return GDB_OSABI_UNKNOWN; +} + + +/* Provide a prototype to silence -Wmissing-prototypes. */ +void _initialize_hppabsd_tdep (void); + +void +_initialize_hppabsd_tdep (void) +{ + /* BFD doesn't set a flavour for NetBSD style a.out core files. */ + gdbarch_register_osabi_sniffer (bfd_arch_hppa, bfd_target_unknown_flavour, + hppabsd_core_osabi_sniffer); + + gdbarch_register_osabi (bfd_arch_hppa, 0, GDB_OSABI_NETBSD_ELF, + hppabsd_init_abi); + gdbarch_register_osabi (bfd_arch_hppa, 0, GDB_OSABI_OPENBSD_ELF, + hppabsd_init_abi); +} diff --git a/gdb/i386nbsd-nat.c b/gdb/i386nbsd-nat.c new file mode 100644 index 00000000000..92da7e18dcd --- /dev/null +++ b/gdb/i386nbsd-nat.c @@ -0,0 +1,82 @@ +/* Native-dependent code for NetBSD/i386. + + Copyright 2004 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include "defs.h" +#include "gdbcore.h" +#include "regcache.h" + +#include "i386-tdep.h" + +/* Support for debugging kernel virtual memory images. */ + +#include +#include +#include + +#include "bsd-kvm.h" + +static int +i386nbsd_supply_pcb (struct regcache *regcache, struct pcb *pcb) +{ + struct switchframe sf; + + /* The following is true for NetBSD 1.6.2: + + The pcb contains %esp and %ebp at the point of the context switch + in cpu_switch(). At that point we have a stack frame as + described by `struct switchframe', which for NetBSD 1.6.2 has the + following layout: + + interrupt level + %edi + %esi + %ebx + %eip + + we reconstruct the register state as it would look when we just + returned from cpu_switch(). */ + + /* The stack pointer shouldn't be zero. */ + if (pcb->pcb_esp == 0) + return 0; + + read_memory (pcb->pcb_esp, (char *) &sf, sizeof sf); + pcb->pcb_esp += sizeof (struct switchframe); + regcache_raw_supply (regcache, I386_EDI_REGNUM, &sf.sf_edi); + regcache_raw_supply (regcache, I386_ESI_REGNUM, &sf.sf_esi); + regcache_raw_supply (regcache, I386_EBP_REGNUM, &pcb->pcb_ebp); + regcache_raw_supply (regcache, I386_ESP_REGNUM, &pcb->pcb_esp); + regcache_raw_supply (regcache, I386_EBX_REGNUM, &sf.sf_ebx); + regcache_raw_supply (regcache, I386_EIP_REGNUM, &sf.sf_eip); + + return 1; +} + + +/* Provide a prototype to silence -Wmissing-prototypes. */ +void _initialize_i386nbsd_nat (void); + +void +_initialize_i386nbsd_nat (void) +{ + /* Support debugging kernel virtual memory images. */ + bsd_kvm_add_target (i386nbsd_supply_pcb); +} diff --git a/gdb/inf-child.c b/gdb/inf-child.c new file mode 100644 index 00000000000..f729611173a --- /dev/null +++ b/gdb/inf-child.c @@ -0,0 +1,241 @@ +/* Default child (native) target interface, for GDB when running under + Unix. + + Copyright 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, + 1998, 1999, 2000, 2001, 2002, 2004 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include "defs.h" +#include "regcache.h" +#include "memattr.h" +#include "symtab.h" +#include "target.h" +#include "inferior.h" + +/* Fetch register REGNUM from the inferior. If REGNUM is -1, do this + for all registers. */ + +static void +inf_child_fetch_inferior_registers (int regnum) +{ + if (regnum == -1) + { + for (regnum = 0; regnum < NUM_REGS; regnum++) + regcache_raw_supply (current_regcache, regnum, NULL); + } + else + regcache_raw_supply (current_regcache, regnum, NULL); +} + +/* Store register REGNUM back into the inferior. If REGNUM is -1, do + this for all registers (including the floating point registers). */ + +static void +inf_child_store_inferior_registers (int regnum) +{ +} + +void +inf_child_post_wait (ptid_t ptid, int wait_status) +{ + /* This version of Unix doesn't require a meaningful "post wait" + operation. + */ +} + +static void +inf_child_post_attach (int pid) +{ + /* This version of Unix doesn't require a meaningful "post attach" + operation by a debugger. */ +} + +/* Get ready to modify the registers array. On machines which store + individual registers, this doesn't need to do anything. On + machines which store all the registers in one fell swoop, this + makes sure that registers contains all the registers from the + program being debugged. */ + +static void +inf_child_prepare_to_store (void) +{ +} + +static void +inf_child_open (char *arg, int from_tty) +{ + error ("Use the \"run\" command to start a Unix child process."); +} + +static void +inf_child_post_startup_inferior (ptid_t ptid) +{ + /* This version of Unix doesn't require a meaningful "post startup + inferior" operation by a debugger. */ +} + +static void +inf_child_acknowledge_created_inferior (int pid) +{ + /* This version of Unix doesn't require a meaningful "acknowledge + created inferior" operation by a debugger. */ +} + +static int +inf_child_insert_fork_catchpoint (int pid) +{ + /* This version of Unix doesn't support notification of fork + events. */ + return 0; +} + +static int +inf_child_remove_fork_catchpoint (int pid) +{ + /* This version of Unix doesn't support notification of fork + events. */ + return 0; +} + +static int +inf_child_insert_vfork_catchpoint (int pid) +{ + /* This version of Unix doesn't support notification of vfork + events. */ + return 0; +} + +static int +inf_child_remove_vfork_catchpoint (int pid) +{ + /* This version of Unix doesn't support notification of vfork + events. */ + return 0; +} + +static int +inf_child_follow_fork (int follow_child) +{ + /* This version of Unix doesn't support following fork or vfork + events. */ + return 0; +} + +static int +inf_child_insert_exec_catchpoint (int pid) +{ + /* This version of Unix doesn't support notification of exec + events. */ + return 0; +} + +static int +inf_child_remove_exec_catchpoint (int pid) +{ + /* This version of Unix doesn't support notification of exec + events. */ + return 0; +} + +static int +inf_child_reported_exec_events_per_exec_call (void) +{ + /* This version of Unix doesn't support notification of exec + events. */ + return 1; +} + +static int +inf_child_can_run (void) +{ + return 1; +} + +static struct symtab_and_line * +inf_child_enable_exception_callback (enum exception_event_kind kind, + int enable) +{ + return (struct symtab_and_line *) NULL; +} + +static struct exception_event_record * +inf_child_get_current_exception_event (void) +{ + return (struct exception_event_record *) NULL; +} + +static char * +inf_child_pid_to_exec_file (int pid) +{ + /* This version of Unix doesn't support translation of a process ID + to the filename of the executable file. */ + return NULL; +} + +static char * +inf_child_core_file_to_sym_file (char *core) +{ + /* The target stratum for a running executable need not support this + operation. */ + return NULL; +} + +struct target_ops * +inf_child_target (void) +{ + struct target_ops *t = XZALLOC (struct target_ops); + t->to_shortname = "child"; + t->to_longname = "Unix child process"; + t->to_doc = "Unix child process (started by the \"run\" command)."; + t->to_open = inf_child_open; + t->to_post_attach = inf_child_post_attach; + t->to_post_wait = inf_child_post_wait; + t->to_prepare_to_store = inf_child_prepare_to_store; + t->to_insert_breakpoint = memory_insert_breakpoint; + t->to_remove_breakpoint = memory_remove_breakpoint; + t->to_terminal_init = terminal_init_inferior; + t->to_terminal_inferior = terminal_inferior; + t->to_terminal_ours_for_output = terminal_ours_for_output; + t->to_terminal_save_ours = terminal_save_ours; + t->to_terminal_ours = terminal_ours; + t->to_terminal_info = child_terminal_info; + t->to_post_startup_inferior = inf_child_post_startup_inferior; + t->to_acknowledge_created_inferior = inf_child_acknowledge_created_inferior; + t->to_insert_fork_catchpoint = inf_child_insert_fork_catchpoint; + t->to_remove_fork_catchpoint = inf_child_remove_fork_catchpoint; + t->to_insert_vfork_catchpoint = inf_child_insert_vfork_catchpoint; + t->to_remove_vfork_catchpoint = inf_child_remove_vfork_catchpoint; + t->to_follow_fork = inf_child_follow_fork; + t->to_insert_exec_catchpoint = inf_child_insert_exec_catchpoint; + t->to_remove_exec_catchpoint = inf_child_remove_exec_catchpoint; + t->to_reported_exec_events_per_exec_call = + inf_child_reported_exec_events_per_exec_call; + t->to_can_run = inf_child_can_run; + t->to_enable_exception_callback = inf_child_enable_exception_callback; + t->to_get_current_exception_event = inf_child_get_current_exception_event; + t->to_pid_to_exec_file = inf_child_pid_to_exec_file; + t->to_stratum = process_stratum; + t->to_has_all_memory = 1; + t->to_has_memory = 1; + t->to_has_stack = 1; + t->to_has_registers = 1; + t->to_has_execution = 1; + t->to_magic = OPS_MAGIC; + return t; +} diff --git a/gdb/inf-child.h b/gdb/inf-child.h new file mode 100644 index 00000000000..5b6edec1052 --- /dev/null +++ b/gdb/inf-child.h @@ -0,0 +1,30 @@ +/* Low level Unix child interface, for GDB when running under Unix. + + Copyright 2004 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef INF_CHILD_H +#define INF_CHILD_H + +/* Create a prototype child target. The client can override it with + local methods. */ + +extern struct target_ops *inf_child_target (void); + +#endif diff --git a/gdb/inf-ptrace.c b/gdb/inf-ptrace.c new file mode 100644 index 00000000000..f79f7863ba6 --- /dev/null +++ b/gdb/inf-ptrace.c @@ -0,0 +1,685 @@ +/* Low level Unix child interface to ptrace, for GDB when running under Unix. + + Copyright 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, + 1998, 1999, 2000, 2001, 2002, 2004 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include "defs.h" +#include "observer.h" +#include "gdb_ptrace.h" +#include "inflow.h" +#include "inferior.h" +#include "regcache.h" +#include "command.h" +#include "gdbcore.h" +#include "inf-child.h" +#include "gdbcmd.h" + +#include +#include + +/* HACK: Save the ptrace ops returned by ptrace_target. */ +static struct target_ops *ptrace_ops_hack; + +static void +inf_ptrace_kill_inferior (void) +{ + int status; + int pid = PIDGET (inferior_ptid); + + if (pid == 0) + return; + + /* This once used to call "kill" to kill the inferior just in case + the inferior was still running. As others have noted in the past + (kingdon) there shouldn't be any way to get here if the inferior + is still running -- else there's a major problem elsewere in gdb + and it needs to be fixed. + + The kill call causes problems under hpux10, so it's been removed; + if this causes problems we'll deal with them as they arise. */ + call_ptrace (PT_KILL, pid, (PTRACE_TYPE_ARG3) 0, 0); + ptrace_wait (null_ptid, &status); + target_mourn_inferior (); +} + +/* Resume execution of the inferior process. If STEP is nonzero, + single-step it. If SIGNAL is nonzero, give it that signal. */ + +static void +inf_ptrace_resume (ptid_t ptid, int step, enum target_signal signal) +{ + int request = PT_CONTINUE; + int pid = PIDGET (ptid); + + if (pid == -1) + /* Resume all threads. */ + /* I think this only gets used in the non-threaded case, where + "resume all threads" and "resume inferior_ptid" are the + same. */ + pid = PIDGET (inferior_ptid); + + if (step) + { + /* If this system does not support PT_STEP, a higher level + function will have called single_step() to transmute the step + request into a continue request (by setting breakpoints on + all possible successor instructions), so we don't have to + worry about that here. */ + request = PT_STEP; + } + + /* An address of (PTRACE_TYPE_ARG3)1 tells ptrace to continue from + where it was. If GDB wanted it to start some other way, we have + already written a new PC value to the child. */ + errno = 0; + ptrace (request, pid, (PTRACE_TYPE_ARG3) 1, target_signal_to_host (signal)); + if (errno != 0) + perror_with_name ("ptrace"); +} + +/* Set an upper limit on alloca. */ +#define GDB_MAX_ALLOCA 0x1000 + +/* NOTE! I tried using PTRACE_READDATA, etc., to read and write memory + in the NEW_SUN_PTRACE case. It ought to be straightforward. But + it appears that writing did not write the data that I specified. I + cannot understand where it got the data that it actually did + write. */ + +/* Copy LEN bytes to or from inferior's memory starting at MEMADDR to + debugger memory starting at MYADDR. Copy to inferior if WRITE is + nonzero. TARGET is ignored. + + Returns the length copied, which is either the LEN argument or + zero. This xfer function does not do partial moves, since + ptrace_ops_hack doesn't allow memory operations to cross below us in the + target stack anyway. */ + +int +inf_ptrace_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int write, + struct mem_attrib *attrib, struct target_ops *target) +{ + int i; + /* Round starting address down to longword boundary. */ + CORE_ADDR addr = memaddr & -(CORE_ADDR) sizeof (PTRACE_TYPE_RET); + /* Round ending address up; get number of longwords that makes. */ + int count = ((((memaddr + len) - addr) + sizeof (PTRACE_TYPE_RET) - 1) + / sizeof (PTRACE_TYPE_RET)); + int alloc = count * sizeof (PTRACE_TYPE_RET); + PTRACE_TYPE_RET *buffer; + struct cleanup *old_chain = NULL; + +#ifdef PT_IO + /* OpenBSD 3.1, NetBSD 1.6 and FreeBSD 5.0 have a new PT_IO request + that promises to be much more efficient in reading and writing + data in the traced process's address space. */ + + { + struct ptrace_io_desc piod; + + /* NOTE: We assume that there are no distinct address spaces for + instruction and data. */ + piod.piod_op = write ? PIOD_WRITE_D : PIOD_READ_D; + piod.piod_offs = (void *) memaddr; + piod.piod_addr = myaddr; + piod.piod_len = len; + + if (ptrace (PT_IO, PIDGET (inferior_ptid), (caddr_t) & piod, 0) == -1) + { + /* If the PT_IO request is somehow not supported, fallback on + using PT_WRITE_D/PT_READ_D. Otherwise we will return zero + to indicate failure. */ + if (errno != EINVAL) + return 0; + } + else + { + /* Return the actual number of bytes read or written. */ + return piod.piod_len; + } + } +#endif + + /* Allocate buffer of that many longwords. */ + if (len < GDB_MAX_ALLOCA) + { + buffer = (PTRACE_TYPE_RET *) alloca (alloc); + } + else + { + buffer = (PTRACE_TYPE_RET *) xmalloc (alloc); + old_chain = make_cleanup (xfree, buffer); + } + + if (write) + { + /* Fill start and end extra bytes of buffer with existing memory + data. */ + if (addr != memaddr || len < (int) sizeof (PTRACE_TYPE_RET)) + { + /* Need part of initial word -- fetch it. */ + buffer[0] = ptrace (PT_READ_I, PIDGET (inferior_ptid), + (PTRACE_TYPE_ARG3) addr, 0); + } + + if (count > 1) /* FIXME, avoid if even boundary. */ + { + buffer[count - 1] = + ptrace (PT_READ_I, PIDGET (inferior_ptid), + ((PTRACE_TYPE_ARG3) + (addr + (count - 1) * sizeof (PTRACE_TYPE_RET))), 0); + } + + /* Copy data to be written over corresponding part of buffer. */ + memcpy ((char *) buffer + (memaddr & (sizeof (PTRACE_TYPE_RET) - 1)), + myaddr, len); + + /* Write the entire buffer. */ + for (i = 0; i < count; i++, addr += sizeof (PTRACE_TYPE_RET)) + { + errno = 0; + ptrace (PT_WRITE_D, PIDGET (inferior_ptid), + (PTRACE_TYPE_ARG3) addr, buffer[i]); + if (errno) + { + /* Using the appropriate one (I or D) is necessary for + Gould NP1, at least. */ + errno = 0; + ptrace (PT_WRITE_I, PIDGET (inferior_ptid), + (PTRACE_TYPE_ARG3) addr, buffer[i]); + } + if (errno) + return 0; + } + } + else + { + /* Read all the longwords. */ + for (i = 0; i < count; i++, addr += sizeof (PTRACE_TYPE_RET)) + { + errno = 0; + buffer[i] = ptrace (PT_READ_I, PIDGET (inferior_ptid), + (PTRACE_TYPE_ARG3) addr, 0); + if (errno) + return 0; + QUIT; + } + + /* Copy appropriate bytes out of the buffer. */ + memcpy (myaddr, + (char *) buffer + (memaddr & (sizeof (PTRACE_TYPE_RET) - 1)), + len); + } + + if (old_chain != NULL) + do_cleanups (old_chain); + return len; +} + +/* Wait for child to do something. Return pid of child, or -1 in case + of error; store status through argument pointer OURSTATUS. */ + +static ptid_t +inf_ptrace_wait (ptid_t ptid, struct target_waitstatus *ourstatus) +{ + int save_errno; + int status; + char *execd_pathname = NULL; + int exit_status; + int related_pid; + int syscall_id; + enum target_waitkind kind; + int pid; + + do + { + set_sigint_trap (); /* Causes SIGINT to be passed on to the + attached process. */ + set_sigio_trap (); + + pid = ptrace_wait (inferior_ptid, &status); + + save_errno = errno; + + clear_sigio_trap (); + + clear_sigint_trap (); + + if (pid == -1) + { + if (save_errno == EINTR) + continue; + + fprintf_unfiltered (gdb_stderr, + "Child process unexpectedly missing: %s.\n", + safe_strerror (save_errno)); + + /* Claim it exited with unknown signal. */ + ourstatus->kind = TARGET_WAITKIND_SIGNALLED; + ourstatus->value.sig = TARGET_SIGNAL_UNKNOWN; + return pid_to_ptid (-1); + } + + /* Did it exit? + */ + if (target_has_exited (pid, status, &exit_status)) + { + /* ??rehrauer: For now, ignore this. */ + continue; + } + + if (!target_thread_alive (pid_to_ptid (pid))) + { + ourstatus->kind = TARGET_WAITKIND_SPURIOUS; + return pid_to_ptid (pid); + } + } + while (pid != PIDGET (inferior_ptid)); /* Some other child died or stopped */ + + store_waitstatus (ourstatus, status); + return pid_to_ptid (pid); +} + +void +inf_ptrace_post_wait (ptid_t ptid, int wait_status) +{ + /* This version of Unix doesn't require a meaningful "post wait" + operation. + */ +} + +/* Check to see if the given thread is alive. + + FIXME: Is kill() ever the right way to do this? I doubt it, but + for now we're going to try and be compatable with the old thread + code. */ + +static int +inf_ptrace_thread_alive (ptid_t ptid) +{ + pid_t pid = PIDGET (ptid); + + return (kill (pid, 0) != -1); +} + +/* Attach to process PID, then initialize for debugging it. */ + +static void +inf_ptrace_attach (char *args, int from_tty) +{ + char *exec_file; + int pid; + char *dummy; + + if (!args) + error_no_arg ("process-id to attach"); + + dummy = args; + pid = strtol (args, &dummy, 0); + /* Some targets don't set errno on errors, grrr! */ + if ((pid == 0) && (args == dummy)) + error ("Illegal process-id: %s\n", args); + + if (pid == getpid ()) /* Trying to masturbate? */ + error ("I refuse to debug myself!"); + + if (from_tty) + { + exec_file = (char *) get_exec_file (0); + + if (exec_file) + printf_unfiltered ("Attaching to program: %s, %s\n", exec_file, + target_pid_to_str (pid_to_ptid (pid))); + else + printf_unfiltered ("Attaching to %s\n", + target_pid_to_str (pid_to_ptid (pid))); + + gdb_flush (gdb_stdout); + } + + attach (pid); + + inferior_ptid = pid_to_ptid (pid); + push_target (ptrace_ops_hack); +} + +static void +inf_ptrace_post_attach (int pid) +{ + /* This version of Unix doesn't require a meaningful "post attach" + operation by a debugger. */ +} + +/* Take a program previously attached to and detaches it. The program + resumes execution and will no longer stop on signals, etc. We'd + better not have left any breakpoints in the program or it'll die + when it hits one. For this to work, it may be necessary for the + process to have been previously attached. It *might* work if the + program was started via the normal ptrace (PTRACE_TRACEME). */ + +static void +inf_ptrace_detach (char *args, int from_tty) +{ + int siggnal = 0; + int pid = PIDGET (inferior_ptid); + + if (from_tty) + { + char *exec_file = get_exec_file (0); + if (exec_file == 0) + exec_file = ""; + printf_unfiltered ("Detaching from program: %s, %s\n", exec_file, + target_pid_to_str (pid_to_ptid (pid))); + gdb_flush (gdb_stdout); + } + if (args) + siggnal = atoi (args); + + detach (siggnal); + + inferior_ptid = null_ptid; + unpush_target (ptrace_ops_hack); +} + +/* Get ready to modify the registers array. On machines which store + individual registers, this doesn't need to do anything. On + machines which store all the registers in one fell swoop, this + makes sure that registers contains all the registers from the + program being debugged. */ + +static void +inf_ptrace_prepare_to_store (void) +{ +} + +/* Print status information about what we're accessing. */ + +static void +inf_ptrace_files_info (struct target_ops *ignore) +{ + printf_unfiltered ("\tUsing the running image of %s %s.\n", + attach_flag ? "attached" : "child", + target_pid_to_str (inferior_ptid)); +} + +static void +inf_ptrace_open (char *arg, int from_tty) +{ + error ("Use the \"run\" command to start a Unix child process."); +} + +/* Stub function which causes the inferior that runs it, to be ptrace-able + by its parent process. */ + +static void +inf_ptrace_me (void) +{ + /* "Trace me, Dr. Memory!" */ + call_ptrace (0, 0, (PTRACE_TYPE_ARG3) 0, 0); +} + +/* Stub function which causes the GDB that runs it, to start ptrace-ing + the child process. */ + +static void +inf_ptrace_him (int pid) +{ + push_target (ptrace_ops_hack); + + /* On some targets, there must be some explicit synchronization + between the parent and child processes after the debugger + forks, and before the child execs the debuggee program. This + call basically gives permission for the child to exec. + */ + + target_acknowledge_created_inferior (pid); + + /* START_INFERIOR_TRAPS_EXPECTED is defined in inferior.h, + * and will be 1 or 2 depending on whether we're starting + * without or with a shell. + */ + startup_inferior (START_INFERIOR_TRAPS_EXPECTED); + + /* On some targets, there must be some explicit actions taken after + the inferior has been started up. + */ + target_post_startup_inferior (pid_to_ptid (pid)); +} + +/* Start an inferior Unix child process and sets inferior_ptid to its + pid. EXEC_FILE is the file to run. ALLARGS is a string containing + the arguments to the program. ENV is the environment vector to + pass. Errors reported with error(). */ + +static void +inf_ptrace_create_inferior (char *exec_file, char *allargs, char **env, + int from_tty) +{ + fork_inferior (exec_file, allargs, env, inf_ptrace_me, inf_ptrace_him, + NULL, NULL); + /* We are at the first instruction we care about. */ + observer_notify_inferior_created (¤t_target, from_tty); + /* Pedal to the metal... */ + proceed ((CORE_ADDR) -1, TARGET_SIGNAL_0, 0); +} + +static void +inf_ptrace_post_startup_inferior (ptid_t ptid) +{ + /* This version of Unix doesn't require a meaningful "post startup inferior" + operation by a debugger. + */ +} + +static void +inf_ptrace_acknowledge_created_inferior (int pid) +{ + /* This version of Unix doesn't require a meaningful "acknowledge created inferior" + operation by a debugger. + */ +} + +static int +inf_ptrace_insert_fork_catchpoint (int pid) +{ + /* This version of Unix doesn't support notification of fork events. */ + return 0; +} + +static int +inf_ptrace_remove_fork_catchpoint (int pid) +{ + /* This version of Unix doesn't support notification of fork events. */ + return 0; +} + +static int +inf_ptrace_insert_vfork_catchpoint (int pid) +{ + /* This version of Unix doesn't support notification of vfork events. */ + return 0; +} + +static int +inf_ptrace_remove_vfork_catchpoint (int pid) +{ + /* This version of Unix doesn't support notification of vfork events. */ + return 0; +} + +static int +inf_ptrace_follow_fork (int follow_child) +{ + /* This version of Unix doesn't support following fork or vfork events. */ + return 0; +} + +static int +inf_ptrace_insert_exec_catchpoint (int pid) +{ + /* This version of Unix doesn't support notification of exec events. */ + return 0; +} + +static int +inf_ptrace_remove_exec_catchpoint (int pid) +{ + /* This version of Unix doesn't support notification of exec events. */ + return 0; +} + +static int +inf_ptrace_reported_exec_events_per_exec_call (void) +{ + /* This version of Unix doesn't support notification of exec events. + */ + return 1; +} + +static int +inf_ptrace_has_exited (int pid, int wait_status, int *exit_status) +{ + if (WIFEXITED (wait_status)) + { + *exit_status = WEXITSTATUS (wait_status); + return 1; + } + + if (WIFSIGNALED (wait_status)) + { + *exit_status = 0; /* ?? Don't know what else to say here. */ + return 1; + } + + /* ?? Do we really need to consult the event state, too? Assume the + wait_state alone suffices. + */ + return 0; +} + +static void +inf_ptrace_mourn_inferior (void) +{ + unpush_target (ptrace_ops_hack); + generic_mourn_inferior (); +} + +static int +inf_ptrace_can_run (void) +{ + return 1; +} + +/* Send a SIGINT to the process group. This acts just like the user + typed a ^C on the controlling terminal. + + XXX - This may not be correct for all systems. Some may want to + use killpg() instead of kill (-pgrp). */ + +static void +inf_ptrace_stop (void) +{ + kill (-inferior_process_group, SIGINT); +} + +/* Perform a partial transfer to/from the specified object. For + memory transfers, fall back to the old memory xfer functions. */ + +static LONGEST +inf_ptrace_xfer_partial (struct target_ops *ops, enum target_object object, + const char *annex, void *readbuf, + const void *writebuf, ULONGEST offset, LONGEST len) +{ + switch (object) + { + case TARGET_OBJECT_MEMORY: + if (readbuf) + return inf_ptrace_xfer_memory (offset, readbuf, len, 0 /*write */ , + NULL, ops); + if (writebuf) + return inf_ptrace_xfer_memory (offset, readbuf, len, 1 /*write */ , + NULL, ops); + return -1; + + case TARGET_OBJECT_UNWIND_TABLE: + return -1; + + case TARGET_OBJECT_AUXV: + return -1; + + case TARGET_OBJECT_WCOOKIE: + return -1; + + default: + return -1; + } +} + +static char * +inf_ptrace_pid_to_str (ptid_t ptid) +{ + return normal_pid_to_str (ptid); +} + +struct target_ops * +inf_ptrace_target (void) +{ + struct target_ops *t = inf_child_target (); + t->to_open = inf_ptrace_open; + t->to_attach = inf_ptrace_attach; + t->to_post_attach = inf_ptrace_post_attach; + t->to_detach = inf_ptrace_detach; + t->to_resume = inf_ptrace_resume; + t->to_wait = inf_ptrace_wait; + t->to_post_wait = inf_ptrace_post_wait; + t->to_prepare_to_store = inf_ptrace_prepare_to_store; + t->to_xfer_memory = inf_ptrace_xfer_memory; + t->to_xfer_partial = inf_ptrace_xfer_partial; + t->to_files_info = inf_ptrace_files_info; + t->to_kill = inf_ptrace_kill_inferior; + t->to_create_inferior = inf_ptrace_create_inferior; + t->to_post_startup_inferior = inf_ptrace_post_startup_inferior; + t->to_acknowledge_created_inferior = + inf_ptrace_acknowledge_created_inferior; + t->to_insert_fork_catchpoint = inf_ptrace_insert_fork_catchpoint; + t->to_remove_fork_catchpoint = inf_ptrace_remove_fork_catchpoint; + t->to_insert_vfork_catchpoint = inf_ptrace_insert_vfork_catchpoint; + t->to_remove_vfork_catchpoint = inf_ptrace_remove_vfork_catchpoint; + t->to_follow_fork = inf_ptrace_follow_fork; + t->to_insert_exec_catchpoint = inf_ptrace_insert_exec_catchpoint; + t->to_remove_exec_catchpoint = inf_ptrace_remove_exec_catchpoint; + t->to_reported_exec_events_per_exec_call = + inf_ptrace_reported_exec_events_per_exec_call; + t->to_has_exited = inf_ptrace_has_exited; + t->to_mourn_inferior = inf_ptrace_mourn_inferior; + t->to_can_run = inf_ptrace_can_run; + t->to_thread_alive = inf_ptrace_thread_alive; + t->to_pid_to_str = inf_ptrace_pid_to_str; + t->to_stop = inf_ptrace_stop; + t->to_stratum = process_stratum; + t->to_has_all_memory = 1; + t->to_has_memory = 1; + t->to_has_stack = 1; + t->to_has_registers = 1; + t->to_has_execution = 1; + t->to_magic = OPS_MAGIC; + ptrace_ops_hack = t; + return t; +} diff --git a/gdb/inf-ptrace.h b/gdb/inf-ptrace.h new file mode 100644 index 00000000000..e9ceae3c963 --- /dev/null +++ b/gdb/inf-ptrace.h @@ -0,0 +1,31 @@ +/* Low level Unix child interface to ptrace, for GDB when running + under Unix. + + Copyright 2004 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef INF_PTRACE_H +#define INF_PTRACE_H + +/* Create a prototype ptrace target. The client can override it with + local methods. */ + +extern struct target_ops *inf_ptrace_target (void); + +#endif diff --git a/gdb/m68kbsd-nat.c b/gdb/m68kbsd-nat.c new file mode 100644 index 00000000000..34e94b4e2f9 --- /dev/null +++ b/gdb/m68kbsd-nat.c @@ -0,0 +1,228 @@ +/* Native-dependent code for Motorola 68000 BSD's. + + Copyright 2004 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include "defs.h" +#include "gdbcore.h" +#include "inferior.h" +#include "regcache.h" + +#include "gdb_assert.h" +#include +#include +#include + +#include "m68k-tdep.h" + +static int +m68kbsd_gregset_supplies_p (int regnum) +{ + return (regnum >= M68K_D0_REGNUM && regnum <= M68K_PC_REGNUM); +} + +static int +m68kbsd_fpregset_supplies_p (int regnum) +{ + return (regnum >= M68K_FP0_REGNUM && regnum <= M68K_FPI_REGNUM); +} + +/* Supply the general-purpose registers stored in GREGS to REGCACHE. */ + +static void +m68kbsd_supply_gregset (struct regcache *regcache, const void *gregs) +{ + const char *regs = gregs; + int regnum; + + for (regnum = M68K_D0_REGNUM; regnum <= M68K_PC_REGNUM; regnum++) + regcache_raw_supply (regcache, regnum, regs + regnum * 4); +} + +/* Supply the floating-point registers stored in FPREGS to REGCACHE. */ + +static void +m68kbsd_supply_fpregset (struct regcache *regcache, const void *fpregs) +{ + const char *regs = fpregs; + int regnum; + + for (regnum = M68K_FP0_REGNUM; regnum <= M68K_FPI_REGNUM; regnum++) + regcache_raw_supply (regcache, regnum, + regs + m68kbsd_fpreg_offset (regnum)); +} + +/* Collect the general-purpose registers from REGCACHE and store them + in GREGS. */ + +static void +m68kbsd_collect_gregset (const struct regcache *regcache, + void *gregs, int regnum) +{ + char *regs = gregs; + int i; + + for (i = M68K_D0_REGNUM; i <= M68K_PC_REGNUM; i++) + { + if (regnum == -1 || regnum == i) + regcache_raw_collect (regcache, i, regs + i * 4); + } +} + +/* Collect the floating-point registers from REGCACHE and store them + in FPREGS. */ + +static void +m68kbsd_collect_fpregset (struct regcache *regcache, + void *fpregs, int regnum) +{ + char *regs = fpregs; + int i; + + for (i = M68K_FP0_REGNUM; i <= M68K_FPI_REGNUM; i++) + { + if (regnum == -1 || regnum == i) + regcache_raw_collect (regcache, i, regs + m68kbsd_fpreg_offset (i)); + } +} + + +/* Fetch register REGNUM from the inferior. If REGNUM is -1, do this + for all registers (including the floating-point registers). */ + +void +fetch_inferior_registers (int regnum) +{ + if (regnum == -1 || m68kbsd_gregset_supplies_p (regnum)) + { + struct reg regs; + + if (ptrace (PT_GETREGS, PIDGET (inferior_ptid), + (PTRACE_TYPE_ARG3) ®s, 0) == -1) + perror_with_name ("Couldn't get registers"); + + m68kbsd_supply_gregset (current_regcache, ®s); + } + + if (regnum == -1 || m68kbsd_fpregset_supplies_p (regnum)) + { + struct fpreg fpregs; + + if (ptrace (PT_GETFPREGS, PIDGET (inferior_ptid), + (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) + perror_with_name ("Couldn't get floating point status"); + + m68kbsd_supply_fpregset (current_regcache, &fpregs); + } +} + +/* Store register REGNUM back into the inferior. If REGNUM is -1, do + this for all registers (including the floating-point registers). */ + +void +store_inferior_registers (int regnum) +{ + if (regnum == -1 || m68kbsd_gregset_supplies_p (regnum)) + { + struct reg regs; + + if (ptrace (PT_GETREGS, PIDGET (inferior_ptid), + (PTRACE_TYPE_ARG3) ®s, 0) == -1) + perror_with_name ("Couldn't get registers"); + + m68kbsd_collect_gregset (current_regcache, ®s, regnum); + + if (ptrace (PT_SETREGS, PIDGET (inferior_ptid), + (PTRACE_TYPE_ARG3) ®s, 0) == -1) + perror_with_name ("Couldn't write registers"); + } + + if (regnum == -1 || m68kbsd_fpregset_supplies_p (regnum)) + { + struct fpreg fpregs; + + if (ptrace (PT_GETFPREGS, PIDGET (inferior_ptid), + (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) + perror_with_name ("Couldn't get floating point status"); + + m68kbsd_collect_fpregset (current_regcache, &fpregs, regnum); + + if (ptrace (PT_SETFPREGS, PIDGET (inferior_ptid), + (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) + perror_with_name ("Couldn't write floating point status"); + } +} + + +/* Support for debugging kernel virtual memory images. */ + +#include +#include + +#include "bsd-kvm.h" + +/* OpenBSD doesn't have these. */ +#ifndef PCB_REGS_FP +#define PCB_REGS_FP 10 +#endif +#ifndef PCB_REGS_SP +#define PCB_REGS_SP 11 +#endif + +static int +m68kbsd_supply_pcb (struct regcache *regcache, struct pcb *pcb) +{ + int regnum, tmp; + int i = 0; + + /* The following is true for NetBSD 1.6.2: + + The pcb contains %d2...%d7, %a2...%a7 and %ps. This accounts for + all callee-saved registers. From this information we reconstruct + the register state as it would look when we just returned from + cpu_switch(). */ + + /* The stack pointer shouldn't be zero. */ + if (pcb->pcb_regs[PCB_REGS_SP] == 0) + return 0; + + for (regnum = M68K_D2_REGNUM; regnum <= M68K_D7_REGNUM; regnum++) + regcache_raw_supply (regcache, regnum, &pcb->pcb_regs[i++]); + for (regnum = M68K_A2_REGNUM; regnum <= M68K_SP_REGNUM; regnum++) + regcache_raw_supply (regcache, regnum, &pcb->pcb_regs[i++]); + + tmp = pcb->pcb_ps & 0xffff; + regcache_raw_supply (regcache, M68K_PS_REGNUM, &tmp); + + read_memory (pcb->pcb_regs[PCB_REGS_FP] + 4, (char *) &tmp, sizeof tmp); + regcache_raw_supply (regcache, M68K_PC_REGNUM, &tmp); + + return 1; +} + + +/* Provide a prototype to silence -Wmissing-prototypes. */ +void _initialize_m68kbsd_nat (void); + +void +_initialize_m68kbsd_nat (void) +{ + /* Support debugging kernel virtual memory images. */ + bsd_kvm_add_target (m68kbsd_supply_pcb); +} diff --git a/gdb/m68kbsd-tdep.c b/gdb/m68kbsd-tdep.c new file mode 100644 index 00000000000..40606684537 --- /dev/null +++ b/gdb/m68kbsd-tdep.c @@ -0,0 +1,228 @@ +/* Target-dependent code for Motorola 68000 BSD's. + + Copyright 2004 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include "defs.h" +#include "arch-utils.h" +#include "osabi.h" +#include "regcache.h" +#include "regset.h" + +#include "gdb_assert.h" +#include "gdb_string.h" + +#include "m68k-tdep.h" +#include "solib-svr4.h" + +/* Core file support. */ + +/* Sizeof `struct reg' in . */ +#define M68KBSD_SIZEOF_GREGS (18 * 4) + +/* Sizeof `struct fpreg' in = M68K_FPC_REGNUM) + return 8 * 12 + (regnum - M68K_FPC_REGNUM) * 4; + + return (regnum - M68K_FP0_REGNUM) * 12; +} + +/* Supply register REGNUM from the buffer specified by FPREGS and LEN + in the floating-point register set REGSET to register cache + REGCACHE. If REGNUM is -1, do this for all registers in REGSET. */ + +static void +m68kbsd_supply_fpregset (const struct regset *regset, + struct regcache *regcache, + int regnum, const void *fpregs, size_t len) +{ + const char *regs = fpregs; + int i; + + gdb_assert (len >= M68KBSD_SIZEOF_FPREGS); + + for (i = M68K_FP0_REGNUM; i <= M68K_PC_REGNUM; i++) + { + if (regnum == i || regnum == -1) + regcache_raw_supply (regcache, i, regs + m68kbsd_fpreg_offset (i)); + } +} + +/* Supply register REGNUM from the buffer specified by GREGS and LEN + in the general-purpose register set REGSET to register cache + REGCACHE. If REGNUM is -1, do this for all registers in REGSET. */ + +static void +m68kbsd_supply_gregset (const struct regset *regset, + struct regcache *regcache, + int regnum, const void *gregs, size_t len) +{ + const char *regs = gregs; + int i; + + gdb_assert (len >= M68KBSD_SIZEOF_GREGS); + + for (i = M68K_D0_REGNUM; i <= M68K_PC_REGNUM; i++) + { + if (regnum == i || regnum == -1) + regcache_raw_supply (regcache, i, regs + i * 4); + } + + if (len >= M68KBSD_SIZEOF_GREGS + M68KBSD_SIZEOF_FPREGS) + { + regs += M68KBSD_SIZEOF_GREGS; + len -= M68KBSD_SIZEOF_GREGS; + m68kbsd_supply_fpregset (regset, regcache, regnum, regs, len); + } +} + +/* Motorola 68000 register sets. */ + +static struct regset m68kbsd_gregset = +{ + NULL, + m68kbsd_supply_gregset +}; + +static struct regset m68kbsd_fpregset = +{ + NULL, + m68kbsd_supply_fpregset +}; + +/* Return the appropriate register set for the core section identified + by SECT_NAME and SECT_SIZE. */ + +static const struct regset * +m68kbsd_regset_from_core_section (struct gdbarch *gdbarch, + const char *sect_name, size_t sect_size) +{ + if (strcmp (sect_name, ".reg") == 0 && sect_size >= M68KBSD_SIZEOF_GREGS) + return &m68kbsd_gregset; + + if (strcmp (sect_name, ".reg2") == 0 && sect_size >= M68KBSD_SIZEOF_FPREGS) + return &m68kbsd_fpregset; + + return NULL; +} + + +/* Support for shared libraries. */ + +/* Return non-zero if we are in a shared library trampoline code stub. */ + +int +m68kbsd_aout_in_solib_call_trampoline (CORE_ADDR pc, char *name) +{ + return (name && !strcmp (name, "_DYNAMIC")); +} + + +static void +m68kbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) +{ + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + + tdep->jb_pc = 5; + tdep->jb_elt_size = 4; + + set_gdbarch_regset_from_core_section + (gdbarch, m68kbsd_regset_from_core_section); +} + +/* OpenBSD and NetBSD a.out. */ + +static void +m68kbsd_aout_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) +{ + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + + m68kbsd_init_abi (info, gdbarch); + + tdep->struct_return = reg_struct_return; + + /* Assume SunOS-style shared libraries. */ + set_gdbarch_in_solib_call_trampoline + (gdbarch, m68kbsd_aout_in_solib_call_trampoline); +} + +/* NetBSD ELF. */ + +static void +m68kbsd_elf_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) +{ + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + + m68kbsd_init_abi (info, gdbarch); + + /* NetBSD ELF uses the SVR4 ABI. */ + m68k_svr4_init_abi (info, gdbarch); + tdep->struct_return = pcc_struct_return; + + /* NetBSD ELF uses SVR4-style shared libraries. */ + set_gdbarch_in_solib_call_trampoline + (gdbarch, generic_in_solib_call_trampoline); + set_solib_svr4_fetch_link_map_offsets + (gdbarch, svr4_ilp32_fetch_link_map_offsets); +} + + +static enum gdb_osabi +m68kbsd_aout_osabi_sniffer (bfd *abfd) +{ + if (strcmp (bfd_get_target (abfd), "a.out-m68k-netbsd") == 0 + || strcmp (bfd_get_target (abfd), "a.out-m68k4k-netbsd") == 0) + return GDB_OSABI_NETBSD_AOUT; + + return GDB_OSABI_UNKNOWN; +} + +static enum gdb_osabi +m68kbsd_core_osabi_sniffer (bfd *abfd) +{ + if (strcmp (bfd_get_target (abfd), "netbsd-core") == 0) + return GDB_OSABI_NETBSD_AOUT; + + return GDB_OSABI_UNKNOWN; +} + + +/* Provide a prototype to silence -Wmissing-prototypes. */ +void _initialize_m68kbsd_tdep (void); + +void +_initialize_m68kbsd_tdep (void) +{ + gdbarch_register_osabi_sniffer (bfd_arch_m68k, bfd_target_aout_flavour, + m68kbsd_aout_osabi_sniffer); + + /* BFD doesn't set a flavour for NetBSD style a.out core files. */ + gdbarch_register_osabi_sniffer (bfd_arch_m68k, bfd_target_unknown_flavour, + m68kbsd_core_osabi_sniffer); + + gdbarch_register_osabi (bfd_arch_m68k, 0, GDB_OSABI_NETBSD_AOUT, + m68kbsd_aout_init_abi); + gdbarch_register_osabi (bfd_arch_m68k, 0, GDB_OSABI_NETBSD_ELF, + m68kbsd_elf_init_abi); +} diff --git a/gdb/m88k-tdep.c b/gdb/m88k-tdep.c new file mode 100644 index 00000000000..70378080208 --- /dev/null +++ b/gdb/m88k-tdep.c @@ -0,0 +1,895 @@ +/* Target-dependent code for the Motorola 88000 series. + + Copyright 2004 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include "defs.h" +#include "arch-utils.h" +#include "dis-asm.h" +#include "frame.h" +#include "frame-base.h" +#include "frame-unwind.h" +#include "gdbcore.h" +#include "gdbtypes.h" +#include "regcache.h" +#include "regset.h" +#include "symtab.h" +#include "trad-frame.h" +#include "value.h" + +#include "gdb_assert.h" +#include "gdb_string.h" + +#include "m88k-tdep.h" + +/* Fetch the instruction at PC. */ + +static unsigned long +m88k_fetch_instruction (CORE_ADDR pc) +{ + return read_memory_unsigned_integer (pc, 4); +} + +/* Register information. */ + +/* Return the name of register REGNUM. */ + +static const char * +m88k_register_name (int regnum) +{ + static char *register_names[] = + { + "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", + "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", + "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", + "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31", + "epsr", "fpsr", "fpcr", "sxip", "snip", "sfip" + }; + + if (regnum >= 0 && regnum < ARRAY_SIZE (register_names)) + return register_names[regnum]; + + return NULL; +} + +/* Return the GDB type object for the "standard" data type of data in + register REGNUM. */ + +static struct type * +m88k_register_type (struct gdbarch *gdbarch, int regnum) +{ + /* SXIP, SNIP, SFIP and R1 contain code addresses. */ + if ((regnum >= M88K_SXIP_REGNUM && regnum <= M88K_SFIP_REGNUM) + || regnum == M88K_R1_REGNUM) + return builtin_type_void_func_ptr; + + /* R30 and R31 typically contains data addresses. */ + if (regnum == M88K_R30_REGNUM || regnum == M88K_R31_REGNUM) + return builtin_type_void_data_ptr; + + return builtin_type_int32; +} + + +static CORE_ADDR +m88k_addr_bits_remove (CORE_ADDR addr) +{ + /* All instructures are 4-byte aligned. The lower 2 bits of SXIP, + SNIP and SFIP are used for special purposes: bit 0 is the + exception bit and bit 1 is the valid bit. */ + return addr & ~0x3; +} + +/* Use the program counter to determine the contents and size of a + breakpoint instruction. Return a pointer to a string of bytes that + encode a breakpoint instruction, store the length of the string in + *LEN and optionally adjust *PC to point to the correct memory + location for inserting the breakpoint. */ + +static const unsigned char * +m88k_breakpoint_from_pc (CORE_ADDR *pc, int *len) +{ + /* tb 0,r0,511 */ + static unsigned char break_insn[] = { 0xf0, 0x00, 0xd1, 0xff }; + + *len = sizeof (break_insn); + return break_insn; +} + +static CORE_ADDR +m88k_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame) +{ + CORE_ADDR pc; + + pc = frame_unwind_register_unsigned (next_frame, M88K_SXIP_REGNUM); + return m88k_addr_bits_remove (pc); +} + +static void +m88k_write_pc (CORE_ADDR pc, ptid_t ptid) +{ + /* According to the MC88100 RISC Microprocessor User's Manual, + section 6.4.3.1.2: + + "... can be made to return to a particular instruction by placing + a valid instruction address in the SNIP and the next sequential + instruction address in the SFIP (with V bits set and E bits + clear). The rte resumes execution at the instruction pointed to + by the SNIP, then the SFIP." + + The E bit is the least significant bit (bit 0). The V (valid) + bit is bit 1. This is why we logical or 2 into the values we are + writing below. It turns out that SXIP plays no role when + returning from an exception so nothing special has to be done + with it. We could even (presumably) give it a totally bogus + value. */ + + write_register_pid (M88K_SXIP_REGNUM, pc, ptid); + write_register_pid (M88K_SNIP_REGNUM, pc | 2, ptid); + write_register_pid (M88K_SFIP_REGNUM, (pc + 4) | 2, ptid); +} + + +/* The functions on this page are intended to be used to classify + function arguments. */ + +/* Check whether TYPE is "Integral or Pointer". */ + +static int +m88k_integral_or_pointer_p (const struct type *type) +{ + switch (TYPE_CODE (type)) + { + case TYPE_CODE_INT: + case TYPE_CODE_BOOL: + case TYPE_CODE_CHAR: + case TYPE_CODE_ENUM: + case TYPE_CODE_RANGE: + { + /* We have byte, half-word, word and extended-word/doubleword + integral types. */ + int len = TYPE_LENGTH (type); + return (len == 1 || len == 2 || len == 4 || len == 8); + } + return 1; + case TYPE_CODE_PTR: + case TYPE_CODE_REF: + { + /* Allow only 32-bit pointers. */ + return (TYPE_LENGTH (type) == 4); + } + return 1; + default: + break; + } + + return 0; +} + +/* Check whether TYPE is "Floating". */ + +static int +m88k_floating_p (const struct type *type) +{ + switch (TYPE_CODE (type)) + { + case TYPE_CODE_FLT: + { + int len = TYPE_LENGTH (type); + return (len == 4 || len == 8); + } + default: + break; + } + + return 0; +} + +/* Check whether TYPE is "Structure or Union". */ + +static int +m88k_structure_or_union_p (const struct type *type) +{ + switch (TYPE_CODE (type)) + { + case TYPE_CODE_STRUCT: + case TYPE_CODE_UNION: + return 1; + default: + break; + } + + return 0; +} + +/* Check whether TYPE has 8-byte alignment. */ + +static int +m88k_8_byte_align_p (struct type *type) +{ + if (m88k_structure_or_union_p (type)) + { + int i; + + for (i = 0; i < TYPE_NFIELDS (type); i++) + { + struct type *subtype = check_typedef (TYPE_FIELD_TYPE (type, i)); + + if (m88k_8_byte_align_p (subtype)) + return 1; + } + } + + if (m88k_integral_or_pointer_p (type) || m88k_floating_p (type)) + return (TYPE_LENGTH (type) == 8); + + return 0; +} + +/* Check whether TYPE can be passed in a register. */ + +static int +m88k_in_register_p (struct type *type) +{ + if (m88k_integral_or_pointer_p (type) || m88k_floating_p (type)) + return 1; + + if (m88k_structure_or_union_p (type) && TYPE_LENGTH (type) == 4) + return 1; + + return 0; +} + +static CORE_ADDR +m88k_store_arguments (struct regcache *regcache, int nargs, + struct value **args, CORE_ADDR sp) +{ + int num_register_words = 0; + int num_stack_words = 0; + int i; + + for (i = 0; i < nargs; i++) + { + struct type *type = VALUE_TYPE (args[i]); + int len = TYPE_LENGTH (type); + + if (m88k_integral_or_pointer_p (type) && len < 4) + { + args[i] = value_cast (builtin_type_int32, args[i]); + type = VALUE_TYPE (args[i]); + len = TYPE_LENGTH (type); + } + + if (m88k_in_register_p (type)) + { + int num_words = 0; + + if (num_register_words % 2 == 1 && m88k_8_byte_align_p (type)) + num_words++; + + num_words += ((len + 3) / 4); + if (num_register_words + num_words <= 8) + { + num_register_words += num_words; + continue; + } + + /* We've run out of available registers. Pass the argument + on the stack. */ + } + + if (num_stack_words % 2 == 1 && m88k_8_byte_align_p (type)) + num_stack_words++; + + num_stack_words += ((len + 3) / 4); + } + + /* Allocate stack space. */ + sp = align_down (sp - 32 - num_stack_words * 4, 16); + num_stack_words = num_register_words = 0; + + for (i = 0; i < nargs; i++) + { + char *valbuf = VALUE_CONTENTS (args[i]); + struct type *type = VALUE_TYPE (args[i]); + int len = TYPE_LENGTH (type); + int stack_word = num_stack_words; + + if (m88k_in_register_p (type)) + { + int register_word = num_register_words; + + if (register_word % 2 == 1 && m88k_8_byte_align_p (type)) + register_word++; + + gdb_assert (len == 4 || len == 8); + + if (register_word + len / 8 < 8) + { + int regnum = M88K_R2_REGNUM + register_word; + + regcache_raw_write (regcache, regnum, valbuf); + if (len > 4) + regcache_raw_write (regcache, regnum + 1, valbuf + 4); + + num_register_words = (register_word + len / 4); + continue; + } + } + + if (stack_word % 2 == -1 && m88k_8_byte_align_p (type)) + stack_word++; + + write_memory (sp + stack_word * 4, valbuf, len); + num_stack_words = (stack_word + (len + 3) / 4); + } + + return sp; +} + +static CORE_ADDR +m88k_push_dummy_call (struct gdbarch *gdbarch, struct value *function, + struct regcache *regcache, CORE_ADDR bp_addr, int nargs, + struct value **args, CORE_ADDR sp, int struct_return, + CORE_ADDR struct_addr) +{ + /* Set up the function arguments. */ + sp = m88k_store_arguments (regcache, nargs, args, sp); + gdb_assert (sp % 16 == 0); + + /* Store return value address. */ + if (struct_return) + regcache_raw_write_unsigned (regcache, M88K_R12_REGNUM, struct_addr); + + /* Store the stack pointer and return address in the appropriate + registers. */ + regcache_raw_write_unsigned (regcache, M88K_R31_REGNUM, sp); + regcache_raw_write_unsigned (regcache, M88K_R1_REGNUM, bp_addr); + + /* Return the stack pointer. */ + return sp; +} + +static struct frame_id +m88k_unwind_dummy_id (struct gdbarch *arch, struct frame_info *next_frame) +{ + CORE_ADDR sp; + + sp = frame_unwind_register_unsigned (next_frame, M88K_R31_REGNUM); + return frame_id_build (sp, frame_pc_unwind (next_frame)); +} + + +/* Determine, for architecture GDBARCH, how a return value of TYPE + should be returned. If it is supposed to be returned in registers, + and READBUF is non-zero, read the appropriate value from REGCACHE, + and copy it into READBUF. If WRITEBUF is non-zero, write the value + from WRITEBUF into REGCACHE. */ + +static enum return_value_convention +m88k_return_value (struct gdbarch *gdbarch, struct type *type, + struct regcache *regcache, void *readbuf, + const void *writebuf) +{ + int len = TYPE_LENGTH (type); + char buf[8]; + + if (!m88k_integral_or_pointer_p (type) && !m88k_floating_p (type)) + return RETURN_VALUE_STRUCT_CONVENTION; + + if (readbuf) + { + /* Read the contents of R2 and (if necessary) R3. */ + regcache_cooked_read (regcache, M88K_R2_REGNUM, buf); + if (len > 4) + { + regcache_cooked_read (regcache, M88K_R3_REGNUM, buf + 4); + gdb_assert (len == 8); + memcpy (readbuf, buf, len); + } + else + { + /* Just stripping off any unused bytes should preserve the + signed-ness just fine. */ + memcpy (readbuf, buf + 4 - len, len); + } + } + + if (writebuf) + { + /* Read the contents to R2 and (if necessary) R3. */ + if (len > 4) + { + gdb_assert (len == 8); + memcpy (buf, writebuf, 8); + regcache_cooked_write (regcache, M88K_R3_REGNUM, buf + 4); + } + else + { + /* ??? Do we need to do any sign-extension here? */ + memcpy (buf + 4 - len, writebuf, len); + } + regcache_cooked_write (regcache, M88K_R2_REGNUM, buf); + } + + return RETURN_VALUE_REGISTER_CONVENTION; +} + +/* Default frame unwinder. */ + +struct m88k_frame_cache +{ + /* Base address. */ + CORE_ADDR base; + CORE_ADDR pc; + + int sp_offset; + int fp_offset; + + /* Table of saved registers. */ + struct trad_frame_saved_reg *saved_regs; +}; + +/* Prologue analysis. */ + +/* Macros for extracting fields from instructions. */ + +#define BITMASK(pos, width) (((0x1 << (width)) - 1) << (pos)) +#define EXTRACT_FIELD(val, pos, width) ((val) >> (pos) & BITMASK (0, width)) +#define SUBU_OFFSET(x) ((unsigned)(x & 0xFFFF)) +#define ST_OFFSET(x) ((unsigned)((x) & 0xFFFF)) +#define ST_SRC(x) EXTRACT_FIELD ((x), 21, 5) +#define ADDU_OFFSET(x) ((unsigned)(x & 0xFFFF)) + +/* Possible actions to be taken by the prologue analyzer for the + instructions it encounters. */ + +enum m88k_prologue_insn_action +{ + M88K_PIA_SKIP, /* Ignore. */ + M88K_PIA_NOTE_ST, /* Note register store. */ + M88K_PIA_NOTE_STD, /* Note register pair store. */ + M88K_PIA_NOTE_SP_ADJUSTMENT, /* Note stack pointer adjustment. */ + M88K_PIA_NOTE_FP_ASSIGNMENT, /* Note frame pointer assignment. */ + M88K_PIA_NOTE_BRANCH, /* Note branch. */ + M88K_PIA_NOTE_PROLOGUE_END /* Note end of prologue. */ +}; + +/* Table of instructions that may comprise a function prologue. */ + +struct m88k_prologue_insn +{ + unsigned long insn; + unsigned long mask; + enum m88k_prologue_insn_action action; +}; + +struct m88k_prologue_insn m88k_prologue_insn_table[] = +{ + /* Various register move instructions. */ + { 0x58000000, 0xf800ffff, M88K_PIA_SKIP }, /* or/or.u with immed of 0 */ + { 0xf4005800, 0xfc1fffe0, M88K_PIA_SKIP }, /* or rd,r0,rs */ + { 0xf4005800, 0xfc00ffff, M88K_PIA_SKIP }, /* or rd,rs,r0 */ + + /* Various other instructions. */ + { 0x58000000, 0xf8000000, M88K_PIA_SKIP }, /* or/or.u */ + + /* Stack pointer setup: "subu sp,sp,n" where n is a multiple of 8. */ + { 0x67ff0000, 0xffff0007, M88K_PIA_NOTE_SP_ADJUSTMENT }, + + /* Frame pointer assignment: "addu r30,r31,n". */ + { 0x63df0000, 0xffff0000, M88K_PIA_NOTE_FP_ASSIGNMENT }, + + /* Store to stack instructions; either "st rx,sp,n" or "st.d rx,sp,n". */ + { 0x241f0000, 0xfc1f0000, M88K_PIA_NOTE_ST }, /* st rx,sp,n */ + { 0x201f0000, 0xfc1f0000, M88K_PIA_NOTE_STD }, /* st.d rs,sp,n */ + + /* Instructions needed for setting up r25 for pic code. */ + { 0x5f200000, 0xffff0000, M88K_PIA_SKIP }, /* or.u r25,r0,offset_high */ + { 0xcc000002, 0xffffffff, M88K_PIA_SKIP }, /* bsr.n Lab */ + { 0x5b390000, 0xffff0000, M88K_PIA_SKIP }, /* or r25,r25,offset_low */ + { 0xf7396001, 0xffffffff, M88K_PIA_SKIP }, /* Lab: addu r25,r25,r1 */ + + /* Various branch or jump instructions which have a delay slot -- + these do not form part of the prologue, but the instruction in + the delay slot might be a store instruction which should be + noted. */ + { 0xc4000000, 0xe4000000, M88K_PIA_NOTE_BRANCH }, + /* br.n, bsr.n, bb0.n, or bb1.n */ + { 0xec000000, 0xfc000000, M88K_PIA_NOTE_BRANCH }, /* bcnd.n */ + { 0xf400c400, 0xfffff7e0, M88K_PIA_NOTE_BRANCH }, /* jmp.n or jsr.n */ + + /* Catch all. Ends prologue analysis. */ + { 0x00000000, 0x00000000, M88K_PIA_NOTE_PROLOGUE_END } +}; + +/* Do a full analysis of the function prologue at PC and update CACHE + accordingly. Bail out early if LIMIT is reached. Return the + address where the analysis stopped. If LIMIT points beyond the + function prologue, the return address should be the end of the + prologue. */ + +static CORE_ADDR +m88k_analyze_prologue (CORE_ADDR pc, CORE_ADDR limit, + struct m88k_frame_cache *cache) +{ + CORE_ADDR end = limit; + + /* Provide a dummy cache if necessary. */ + if (cache == NULL) + { + size_t sizeof_saved_regs = + (M88K_R31_REGNUM + 1) * sizeof (struct trad_frame_saved_reg); + + cache = alloca (sizeof (struct m88k_frame_cache)); + cache->saved_regs = alloca (sizeof_saved_regs); + + /* We only initialize the members we care about. */ + cache->saved_regs[M88K_R1_REGNUM].addr = -1; + cache->fp_offset = -1; + } + + while (pc < limit) + { + struct m88k_prologue_insn *pi = m88k_prologue_insn_table; + unsigned long insn = m88k_fetch_instruction (pc); + + while ((insn & pi->mask) != pi->insn) + pi++; + + switch (pi->action) + { + case M88K_PIA_SKIP: + /* If we have a frame pointer, and R1 has been saved, + consider this instruction as not being part of the + prologue. */ + if (cache->fp_offset != -1 + && cache->saved_regs[M88K_R1_REGNUM].addr != -1) + return min (pc, end); + break; + + case M88K_PIA_NOTE_ST: + case M88K_PIA_NOTE_STD: + /* If no frame has been allocated, the stores aren't part of + the prologue. */ + if (cache->sp_offset == 0) + return min (pc, end); + + /* Record location of saved registers. */ + { + int regnum = ST_SRC (insn) + M88K_R0_REGNUM; + ULONGEST offset = ST_OFFSET (insn); + + cache->saved_regs[regnum].addr = offset; + if (pi->action == M88K_PIA_NOTE_STD && regnum < M88K_R31_REGNUM) + cache->saved_regs[regnum + 1].addr = offset + 4; + } + break; + + case M88K_PIA_NOTE_SP_ADJUSTMENT: + /* A second stack pointer adjustment isn't part of the + prologue. */ + if (cache->sp_offset != 0) + return min (pc, end); + + /* Store stack pointer adjustment. */ + cache->sp_offset = -SUBU_OFFSET (insn); + break; + + case M88K_PIA_NOTE_FP_ASSIGNMENT: + /* A second frame pointer assignment isn't part of the + prologue. */ + if (cache->fp_offset != -1) + return min (pc, end); + + /* Record frame pointer assignment. */ + cache->fp_offset = ADDU_OFFSET (insn); + break; + + case M88K_PIA_NOTE_BRANCH: + /* The branch instruction isn't part of the prologue, but + the instruction in the delay slot might be. Limit the + prologue analysis to the delay slot and record the branch + instruction as the end of the prologue. */ + limit = min (limit, pc + 2 * M88K_INSN_SIZE); + end = pc; + break; + + case M88K_PIA_NOTE_PROLOGUE_END: + return min (pc, end); + } + + pc += M88K_INSN_SIZE; + } + + return end; +} + +/* An upper limit to the size of the prologue. */ +const int m88k_max_prologue_size = 128 * M88K_INSN_SIZE; + +/* Return the address of first real instruction of the function + starting at PC. */ + +static CORE_ADDR +m88k_skip_prologue (CORE_ADDR pc) +{ + struct symtab_and_line sal; + CORE_ADDR func_start, func_end; + + /* This is the preferred method, find the end of the prologue by + using the debugging information. */ + if (find_pc_partial_function (pc, NULL, &func_start, &func_end)) + { + sal = find_pc_line (func_start, 0); + + if (sal.end < func_end && pc <= sal.end) + return sal.end; + } + + return m88k_analyze_prologue (pc, pc + m88k_max_prologue_size, NULL); +} + +struct m88k_frame_cache * +m88k_frame_cache (struct frame_info *next_frame, void **this_cache) +{ + struct m88k_frame_cache *cache; + CORE_ADDR frame_sp; + + if (*this_cache) + return *this_cache; + + cache = FRAME_OBSTACK_ZALLOC (struct m88k_frame_cache); + cache->saved_regs = trad_frame_alloc_saved_regs (next_frame); + cache->fp_offset = -1; + + cache->pc = frame_func_unwind (next_frame); + if (cache->pc != 0) + { + CORE_ADDR addr_in_block = frame_unwind_address_in_block (next_frame); + m88k_analyze_prologue (cache->pc, addr_in_block, cache); + } + + /* Calculate the stack pointer used in the prologue. */ + if (cache->fp_offset != -1) + { + CORE_ADDR fp; + + fp = frame_unwind_register_unsigned (next_frame, M88K_R30_REGNUM); + frame_sp = fp - cache->fp_offset; + } + else + { + /* If we know where the return address is saved, we can take a + solid guess at what the frame pointer should be. */ + if (cache->saved_regs[M88K_R1_REGNUM].addr != -1) + cache->fp_offset = cache->saved_regs[M88K_R1_REGNUM].addr - 4; + frame_sp = frame_unwind_register_unsigned (next_frame, M88K_R31_REGNUM); + } + + /* Now that we know the stack pointer, adjust the location of the + saved registers. */ + { + int regnum; + + for (regnum = M88K_R0_REGNUM; regnum < M88K_R31_REGNUM; regnum ++) + if (cache->saved_regs[regnum].addr != -1) + cache->saved_regs[regnum].addr += frame_sp; + } + + /* Calculate the frame's base. */ + cache->base = frame_sp - cache->sp_offset; + trad_frame_set_value (cache->saved_regs, M88K_R31_REGNUM, cache->base); + + /* Identify SXIP with the return address in R1. */ + cache->saved_regs[M88K_SXIP_REGNUM] = cache->saved_regs[M88K_R1_REGNUM]; + + *this_cache = cache; + return cache; +} + +static void +m88k_frame_this_id (struct frame_info *next_frame, void **this_cache, + struct frame_id *this_id) +{ + struct m88k_frame_cache *cache = m88k_frame_cache (next_frame, this_cache); + + /* This marks the outermost frame. */ + if (cache->base == 0) + return; + + (*this_id) = frame_id_build (cache->base, cache->pc); +} + +static void +m88k_frame_prev_register (struct frame_info *next_frame, void **this_cache, + int regnum, int *optimizedp, + enum lval_type *lvalp, CORE_ADDR *addrp, + int *realnump, void *valuep) +{ + struct m88k_frame_cache *cache = m88k_frame_cache (next_frame, this_cache); + + if (regnum == M88K_SNIP_REGNUM || regnum == M88K_SFIP_REGNUM) + { + if (valuep) + { + CORE_ADDR pc; + + trad_frame_get_prev_register (next_frame, cache->saved_regs, + M88K_SXIP_REGNUM, optimizedp, + lvalp, addrp, realnump, valuep); + + pc = extract_unsigned_integer (valuep, 4); + if (regnum == M88K_SFIP_REGNUM) + pc += 4; + store_unsigned_integer (valuep, 4, pc + 4); + } + + /* It's a computed value. */ + *optimizedp = 0; + *lvalp = not_lval; + *addrp = 0; + *realnump = -1; + return; + } + + trad_frame_get_prev_register (next_frame, cache->saved_regs, regnum, + optimizedp, lvalp, addrp, realnump, valuep); +} + +static const struct frame_unwind m88k_frame_unwind = +{ + NORMAL_FRAME, + m88k_frame_this_id, + m88k_frame_prev_register +}; + +static const struct frame_unwind * +m88k_frame_sniffer (struct frame_info *next_frame) +{ + return &m88k_frame_unwind; +} + + +static CORE_ADDR +m88k_frame_base_address (struct frame_info *next_frame, void **this_cache) +{ + struct m88k_frame_cache *cache = m88k_frame_cache (next_frame, this_cache); + + if (cache->fp_offset != -1) + return cache->base + cache->sp_offset + cache->fp_offset; + + return 0; +} + +static const struct frame_base m88k_frame_base = +{ + &m88k_frame_unwind, + m88k_frame_base_address, + m88k_frame_base_address, + m88k_frame_base_address +}; + + +/* Core file support. */ + +/* Supply register REGNUM from the buffer specified by GREGS and LEN + in the general-purpose register set REGSET to register cache + REGCACHE. If REGNUM is -1, do this for all registers in REGSET. */ + +static void +m88k_supply_gregset (const struct regset *regset, + struct regcache *regcache, + int regnum, const void *gregs, size_t len) +{ + const char *regs = gregs; + int i; + + for (i = 0; i < M88K_NUM_REGS; i++) + { + if (regnum == i || regnum == -1) + regcache_raw_supply (regcache, i, regs + i * 4); + } +} + +/* Motorola 88000 register set. */ + +static struct regset m88k_gregset = +{ + NULL, + m88k_supply_gregset +}; + +/* Return the appropriate register set for the core section identified + by SECT_NAME and SECT_SIZE. */ + +static const struct regset * +m88k_regset_from_core_section (struct gdbarch *gdbarch, + const char *sect_name, size_t sect_size) +{ + if (strcmp (sect_name, ".reg") == 0 && sect_size >= M88K_NUM_REGS * 4) + return &m88k_gregset; + + return NULL; +} + + +static struct gdbarch * +m88k_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) +{ + struct gdbarch *gdbarch; + + /* If there is already a candidate, use it. */ + arches = gdbarch_list_lookup_by_info (arches, &info); + if (arches != NULL) + return arches->gdbarch; + + /* Allocate space for the new architecture. */ + gdbarch = gdbarch_alloc (&info, NULL); + + /* There is no real `long double'. */ + set_gdbarch_long_double_bit (gdbarch, 64); + set_gdbarch_long_double_format (gdbarch, &floatformat_ieee_double_big); + + set_gdbarch_num_regs (gdbarch, M88K_NUM_REGS); + set_gdbarch_register_name (gdbarch, m88k_register_name); + set_gdbarch_register_type (gdbarch, m88k_register_type); + + /* Register numbers of various important registers. */ + set_gdbarch_sp_regnum (gdbarch, M88K_R31_REGNUM); + set_gdbarch_pc_regnum (gdbarch, M88K_SXIP_REGNUM); + + /* Core file support. */ + set_gdbarch_regset_from_core_section + (gdbarch, m88k_regset_from_core_section); + + set_gdbarch_print_insn (gdbarch, print_insn_m88k); + + set_gdbarch_skip_prologue (gdbarch, m88k_skip_prologue); + + /* Stack grows downward. */ + set_gdbarch_inner_than (gdbarch, core_addr_lessthan); + + /* Call dummy code. */ + set_gdbarch_push_dummy_call (gdbarch, m88k_push_dummy_call); + set_gdbarch_unwind_dummy_id (gdbarch, m88k_unwind_dummy_id); + + /* Return value info */ + set_gdbarch_return_value (gdbarch, m88k_return_value); + + set_gdbarch_addr_bits_remove (gdbarch, m88k_addr_bits_remove); + set_gdbarch_breakpoint_from_pc (gdbarch, m88k_breakpoint_from_pc); + set_gdbarch_unwind_pc (gdbarch, m88k_unwind_pc); + set_gdbarch_write_pc (gdbarch, m88k_write_pc); + + frame_base_set_default (gdbarch, &m88k_frame_base); + frame_unwind_append_sniffer (gdbarch, m88k_frame_sniffer); + + return gdbarch; +} + + +/* Provide a prototype to silence -Wmissing-prototypes. */ +void _initialize_m88k_tdep (void); + +void +_initialize_m88k_tdep (void) +{ + gdbarch_register (bfd_arch_m88k, m88k_gdbarch_init, NULL); +} diff --git a/gdb/m88k-tdep.h b/gdb/m88k-tdep.h new file mode 100644 index 00000000000..1389bfc6e48 --- /dev/null +++ b/gdb/m88k-tdep.h @@ -0,0 +1,49 @@ +/* Target-dependent code for the Motorola 88000 series. + + Copyright 2004 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef M88K_TDEP_H +#define M88K_TDEP_H + +/* Register numbers of various important registers. */ + +enum m88k_regnum +{ + M88K_R0_REGNUM, + M88K_R1_REGNUM, /* Return address (hardware). */ + M88K_R2_REGNUM, + M88K_R3_REGNUM, + M88K_R12_REGNUM = 12, + M88K_R30_REGNUM = 30, /* Frame pointer. */ + M88K_R31_REGNUM, /* Stack pointer. */ + M88K_EPSR_REGNUM, + M88K_FPSR_REGNUM, + M88K_FPCR_REGNUM, + M88K_SXIP_REGNUM, + M88K_SNIP_REGNUM, + M88K_SFIP_REGNUM, + M88K_NUM_REGS /* Number of machine registers. */ + +}; + +/* Instruction size. */ +#define M88K_INSN_SIZE 4 + +#endif /* m88k-tdep.h */ diff --git a/gdb/m88kbsd-nat.c b/gdb/m88kbsd-nat.c new file mode 100644 index 00000000000..7553c19b1ee --- /dev/null +++ b/gdb/m88kbsd-nat.c @@ -0,0 +1,94 @@ +/* Native-dependent code for Motorola 88000 BSD's. + + Copyright 2004 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include "defs.h" +#include "inferior.h" +#include "regcache.h" + +#include +#include +#include + +#include "m88k-tdep.h" + +/* Supply the general-purpose registers stored in GREGS to REGCACHE. */ + +static void +m88kbsd_supply_gregset (struct regcache *regcache, const void *gregs) +{ + const char *regs = gregs; + int regnum; + + for (regnum = 0; regnum < M88K_NUM_REGS; regnum++) + regcache_raw_supply (regcache, regnum, regs + regnum * 4); +} + +/* Collect the general-purpose registers from REGCACHE and store them + in GREGS. */ + +static void +m88kbsd_collect_gregset (const struct regcache *regcache, + void *gregs, int regnum) +{ + char *regs = gregs; + int i; + + for (i = 0; i < M88K_NUM_REGS; i++) + { + if (regnum == -1 || regnum == i) + regcache_raw_collect (regcache, i, regs + i * 4); + } +} + + +/* Fetch register REGNUM from the inferior. If REGNUM is -1, do this + for all registers. */ + +void +fetch_inferior_registers (int regnum) +{ + struct reg regs; + + if (ptrace (PT_GETREGS, PIDGET (inferior_ptid), + (PTRACE_TYPE_ARG3) ®s, 0) == -1) + perror_with_name ("Couldn't get registers"); + + m88kbsd_supply_gregset (current_regcache, ®s); +} + +/* Store register REGNUM back into the inferior. If REGNUM is -1, do + this for all registers. */ + +void +store_inferior_registers (int regnum) +{ + struct reg regs; + + if (ptrace (PT_GETREGS, PIDGET (inferior_ptid), + (PTRACE_TYPE_ARG3) ®s, 0) == -1) + perror_with_name ("Couldn't get registers"); + + m88kbsd_collect_gregset (current_regcache, ®s, regnum); + + if (ptrace (PT_SETREGS, PIDGET (inferior_ptid), + (PTRACE_TYPE_ARG3) ®s, 0) == -1) + perror_with_name ("Couldn't write registers"); +} diff --git a/gdb/mi/gdb-mi.el b/gdb/mi/gdb-mi.el new file mode 100644 index 00000000000..8780e8aa4ae --- /dev/null +++ b/gdb/mi/gdb-mi.el @@ -0,0 +1,568 @@ +;;; gdb-mi.el (internally gdbmi6.el) - (24th May 2004) + +;; Run gdb with GDB/MI (-interp=mi) and access CLI using "cli-command" +;; (could use "-interpreter-exec console cli-command") + +;; Author: Nick Roberts +;; Maintainer: Nick Roberts +;; Keywords: unix, tools + +;; Copyright (C) 2004 Free Software Foundation, Inc. + +;; This file is part of GNU GDB. + +;; GNU GDB is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;;; Commentary: + +;; This mode acts as a graphical user interface to GDB and requires GDB 6.1 +;; onwards. You can interact with GDB through the GUD buffer in the usual way, +;; but there are also buffers which control the execution and describe the +;; state of your program. It separates the input/output of your program from +;; that of GDB and displays expressions and their current values in their own +;; buffers. It also uses features of Emacs 21 such as the fringe/display +;; margin for breakpoints, and the toolbar (see the GDB Graphical Interface +;; section in the Emacs info manual). + +;; Start the debugger with M-x gdbmi. + +;; This file uses GDB/MI as the primary interface to GDB. It is still under +;; development and is part of a process to migrate Emacs from annotations +;; (as used in gdb-ui.el) to GDB/MI. + +;; Known Bugs: +;; + +;;; Code: + +(require 'gud) +(require 'gdb-ui) + + +;;;###autoload +(defun gdbmi (command-line) + "Run gdb on program FILE in buffer *gud-FILE*. +The directory containing FILE becomes the initial working directory +and source-file directory for your debugger. + +If `gdb-many-windows' is nil (the default value) then gdb just +pops up the GUD buffer unless `gdb-show-main' is t. In this case +it starts with two windows: one displaying the GUD buffer and the +other with the source file with the main routine of the inferior. + +If `gdb-many-windows' is t, regardless of the value of +`gdb-show-main', the layout below will appear. Keybindings are +given in relevant buffer. + +Watch expressions appear in the speedbar/slowbar. + +The following interactive lisp functions help control operation : + +`gdb-many-windows' - Toggle the number of windows gdb uses. +`gdb-restore-windows' - To restore the window layout. + +See Info node `(emacs)GDB Graphical Interface' for a more +detailed description of this mode. + + +--------------------------------------------------------------------- + GDB Toolbar +--------------------------------------------------------------------- +GUD buffer (I/O of GDB) | Locals buffer + | + | + | +--------------------------------------------------------------------- + Source buffer | Input/Output (of inferior) buffer + | (comint-mode) + | + | + | + | + | + | +--------------------------------------------------------------------- + Stack buffer | Breakpoints buffer + RET gdb-frames-select | SPC gdb-toggle-breakpoint + | RET gdb-goto-breakpoint + | d gdb-delete-breakpoint +--------------------------------------------------------------------- +" + ;; + (interactive (list (gud-query-cmdline 'gdbmi))) + ;; + ;; Let's start with a basic gud-gdb buffer and then modify it a bit. + (gdb command-line) + ;; + (setq gdb-debug-log nil) + (set (make-local-variable 'gud-minor-mode) 'gdbmi) + (set (make-local-variable 'gud-marker-filter) 'gud-gdbmi-marker-filter) + ;; + (gud-def gud-break (if (not (string-equal mode-name "Machine")) + (gud-call "-break-insert %f:%l" arg) + (save-excursion + (beginning-of-line) + (forward-char 2) + (gud-call "-break-insert *%a" arg))) + "\C-b" "Set breakpoint at current line or address.") + ;; + (gud-def gud-remove (if (not (string-equal mode-name "Machine")) + (gud-call "clear %f:%l" arg) + (save-excursion + (beginning-of-line) + (forward-char 2) + (gud-call "clear *%a" arg))) + "\C-d" "Remove breakpoint at current line or address.") + ;; + (gud-def gud-until (if (not (string-equal mode-name "Machine")) + (gud-call "until %f:%l" arg) + (save-excursion + (beginning-of-line) + (forward-char 2) + (gud-call "until *%a" arg))) + "\C-u" "Continue to current line or address.") + + (define-key gud-minor-mode-map [left-margin mouse-1] + 'gdb-mouse-toggle-breakpoint) + (define-key gud-minor-mode-map [left-fringe mouse-1] + 'gdb-mouse-toggle-breakpoint) + + (setq comint-input-sender 'gdbmi-send) + ;; + ;; (re-)initialise + (setq gdb-main-file nil) + (setq gdb-current-address "main") + (setq gdb-previous-address nil) + (setq gdb-previous-frame nil) + (setq gdb-current-frame "main") + (setq gdb-view-source t) + (setq gdb-selected-view 'source) + (setq gdb-var-list nil) + (setq gdb-var-changed nil) + (setq gdb-prompting nil) + (setq gdb-current-item nil) + (setq gdb-pending-triggers nil) + (setq gdb-output-sink 'user) + (setq gdb-server-prefix nil) + ;; + (setq gdb-buffer-type 'gdbmi) + ;; + ;; FIXME: use tty command to separate io. + ;;(gdb-clear-inferior-io) + ;; + (if (eq window-system 'w32) + (gdb-enqueue-input (list "-gdb-set new-console off\n" 'ignore))) + ;; find source file and compilation directory here + (gdb-enqueue-input (list "list main\n" 'ignore)) ; C program + (gdb-enqueue-input (list "list MAIN__\n" 'ignore)) ; Fortran program + (gdb-enqueue-input (list "info source\n" 'gdbmi-source-info)) + ;; + (run-hooks 'gdbmi-mode-hook)) + +; Force nil till fixed. +(defconst gdbmi-use-inferior-io-buffer nil) + +; uses --all-values Needs GDB 6.1 onwards. +(defun gdbmi-var-list-children (varnum) + (gdb-enqueue-input + (list (concat "-var-update " varnum "\n") 'ignore)) + (gdb-enqueue-input + (list (concat "-var-list-children --all-values " + varnum "\n") + `(lambda () (gdbmi-var-list-children-handler ,varnum))))) + +(defconst gdbmi-var-list-children-regexp +"name=\"\\(.*?\\)\",exp=\"\\(.*?\\)\",numchild=\"\\(.*?\\)\",value=\"\\(.*?\\)\"" +) + +(defun gdbmi-var-list-children-handler (varnum) + (with-current-buffer (gdb-get-create-buffer 'gdb-partial-output-buffer) + (goto-char (point-min)) + (let ((var-list nil)) + (catch 'child-already-watched + (dolist (var gdb-var-list) + (if (string-equal varnum (cadr var)) + (progn + (push var var-list) + (while (re-search-forward gdbmi-var-list-children-regexp nil t) + (let ((varchild (list (match-string 2) + (match-string 1) + (match-string 3) + nil + (match-string 4) + nil))) + (if (looking-at ",type=\"\\(.*?\\)\"") + (setcar (nthcdr 3 varchild) (match-string 1))) + (dolist (var1 gdb-var-list) + (if (string-equal (cadr var1) (cadr varchild)) + (throw 'child-already-watched nil))) + (push varchild var-list)))) + (push var var-list))) + (setq gdb-var-changed t) + (setq gdb-var-list (nreverse var-list)))))) + +;(defun gdbmi-send (proc string) +; "A comint send filter for gdb." +; (setq gdb-output-sink 'user) +; (setq gdb-prompting nil) +; (process-send-string proc (concat "-interpreter-exec console \"" string "\""))) + +(defun gdbmi-send (proc string) + "A comint send filter for gdb." + (setq gdb-output-sink 'user) + (setq gdb-prompting nil) + (process-send-string proc (concat string "\n"))) + +(defcustom gud-gdbmi-command-name "~/gdb/gdb/gdb -interp=mi" + "Default command to execute an executable under the GDB-UI debugger." + :type 'string + :group 'gud) + +(defconst gdb-stopped-regexp + "\\((gdb) \n\\*stopped\\|^\\^done\\),reason=.*,file=\"\\(.*\\)\",line=\"\\(.*\\)\".*") + +(defconst gdb-console-regexp "~\"\\(.*\\)\\\\n\"") + +(defconst gdb-internals-regexp "&\".*\\n\"\n") + +(defconst gdb-gdb-regexp "(gdb) \n") + +(defconst gdb-running-regexp "^\\^running") + +(defun gdbmi-prompt () + "This handler terminates the any collection of output. It also + sends the next command (if any) to gdb." + (unless gdb-pending-triggers + (gdb-get-current-frame) + (gdbmi-invalidate-frames) + (gdbmi-invalidate-breakpoints) + (gdbmi-invalidate-locals) + (dolist (frame (frame-list)) + (when (string-equal (frame-parameter frame 'name) "Speedbar") + (setq gdb-var-changed t) ; force update + (dolist (var gdb-var-list) + (setcar (nthcdr 5 var) nil)))) + (gdb-var-update)) + (let ((sink gdb-output-sink)) + (when (eq sink 'emacs) + (let ((handler + (car (cdr gdb-current-item)))) + (with-current-buffer (gdb-get-create-buffer 'gdb-partial-output-buffer) + (funcall handler))))) + (let ((input (gdb-dequeue-input))) + (if input + (gdb-send-item input) + (progn + (setq gud-running nil) + (setq gdb-prompting t) + (gud-display-frame))))) + +(defun gud-gdbmi-marker-filter (string) + "Filter GDB/MI output." + (if gdb-enable-debug-log (push (cons 'recv string) gdb-debug-log)) + ;; Recall the left over gud-marker-acc from last time + (setq gud-marker-acc (concat gud-marker-acc string)) + ;; Start accumulating output for the GUD buffer + (let ((output "")) + + (if (string-match gdb-running-regexp gud-marker-acc) + (setq gud-marker-acc (substring gud-marker-acc (match-end 0)) + gud-running t)) + + ;; Remove the trimmings from the console stream. + (while (string-match gdb-console-regexp gud-marker-acc) + (setq + gud-marker-acc (concat (substring gud-marker-acc 0 (match-beginning 0)) + (match-string 1 gud-marker-acc) + (substring gud-marker-acc (match-end 0))))) + + ;; Remove log stream containing debugging messages being produced by GDB's + ;; internals. + (while (string-match gdb-internals-regexp gud-marker-acc) + (setq + gud-marker-acc (concat (substring gud-marker-acc 0 (match-beginning 0)) + (substring gud-marker-acc (match-end 0))))) + + (if (string-match gdb-stopped-regexp gud-marker-acc) + (setq + + ;; Extract the frame position from the marker. + gud-last-frame (cons (match-string 2 gud-marker-acc) + (string-to-int (match-string 3 gud-marker-acc))) + + ;; Append any text before the marker to the output we're going + ;; to return - we don't include the marker in this text. + output (gdbmi-concat-output output + (substring gud-marker-acc 0 (match-beginning 0))) + + ;; Set the accumulator to the remaining text. + gud-marker-acc (substring gud-marker-acc (match-end 0)))) + + (while (string-match gdb-gdb-regexp gud-marker-acc) + (setq + + ;; Append any text up to and including prompt less \n to the output. + output (gdbmi-concat-output output + (substring gud-marker-acc 0 (- (match-end 0) 1))) + + ;; Set the accumulator to the remaining text. + gud-marker-acc (substring gud-marker-acc (match-end 0))) + (gdbmi-prompt)) + + (setq output (gdbmi-concat-output output gud-marker-acc)) + (setq gud-marker-acc "") + output)) + +(defun gdbmi-concat-output (so-far new) + (let ((sink gdb-output-sink)) + (cond + ((eq sink 'user) (concat so-far new)) + ((eq sink 'emacs) + (gdb-append-to-partial-output new) + so-far) + ((eq sink 'inferior) + (gdb-append-to-inferior-io new) + so-far)))) + + +;; Breakpoint buffer : This displays the output of `-break-list'. +;; +(def-gdb-auto-updated-buffer gdb-breakpoints-buffer + ;; This defines the auto update rule for buffers of type + ;; `gdb-breakpoints-buffer'. + ;; + ;; It defines a function that queues the command below. That function is + ;; called: + gdbmi-invalidate-breakpoints + ;; + ;; To update the buffer, this command is sent to gdb. + "-break-list\n" + ;; + ;; This also defines a function to be the handler for the output + ;; from the command above. That function will copy the output into + ;; the appropriately typed buffer. That function will be called: + gdb-break-list-handler + ;; buffer specific functions + gdb-break-list-custom) + +(defconst gdb-break-list-regexp +"number=\"\\(.*?\\)\",type=\"\\(.*?\\)\",disp=\"\\(.*?\\)\",enabled=\"\\(.\\)\",addr=\"\\(.*?\\)\",func=\"\\(.*?\\)\",file=\"\\(.*?\\)\",line=\"\\(.*?\\)\"") + +(defun gdb-break-list-handler () + (setq gdb-pending-triggers (delq 'gdbmi-invalidate-breakpoints + gdb-pending-triggers)) + (let ((breakpoint nil) + (breakpoints-list nil)) + (with-current-buffer (gdb-get-create-buffer 'gdb-partial-output-buffer) + (goto-char (point-min)) + (while (re-search-forward gdb-break-list-regexp nil t) + (let ((breakpoint (list (match-string 1) + (match-string 2) + (match-string 3) + (match-string 4) + (match-string 5) + (match-string 6) + (match-string 7) + (match-string 8)))) + (push breakpoint breakpoints-list)))) + (let ((buf (gdb-get-buffer 'gdb-breakpoints-buffer))) + (and buf (with-current-buffer buf + (let ((p (point)) + (buffer-read-only nil)) + (erase-buffer) + (insert "Num Type Disp Enb Func\tFile:Line\tAddr\n") + (dolist (breakpoint breakpoints-list) + (insert (concat + (nth 0 breakpoint) " " + (nth 1 breakpoint) " " + (nth 2 breakpoint) " " + (nth 3 breakpoint) " " + (nth 5 breakpoint) "\t" + (nth 6 breakpoint) ":" (nth 7 breakpoint) "\t" + (nth 4 breakpoint) "\n"))) + (goto-char p)))))) + (gdb-break-list-custom)) + +;;-put breakpoint icons in relevant margins (even those set in the GUD buffer) +(defun gdb-break-list-custom () + (let ((flag)(address)) + ;; + ;; remove all breakpoint-icons in source buffers but not assembler buffer + (dolist (buffer (buffer-list)) + (with-current-buffer buffer + (if (and (eq gud-minor-mode 'gdbmi) + (not (string-match "\\`\\*.+\\*\\'" (buffer-name)))) + (gdb-remove-breakpoint-icons (point-min) (point-max))))) + (with-current-buffer (gdb-get-buffer 'gdb-breakpoints-buffer) + (save-excursion + (goto-char (point-min)) + (while (< (point) (- (point-max) 1)) + (forward-line 1) + (if (looking-at "[0-9]*\\s-*\\S-*\\s-*\\S-*\\s-*\\(.\\)\\s-*\\S-*\\s-*\\(\\S-*\\):\\([0-9]+\\)") + (progn + (setq flag (char-after (match-beginning 1))) + (let ((line (match-string 3)) (buffer-read-only nil) + (file (match-string 2))) + (add-text-properties (point-at-bol) (point-at-eol) + '(mouse-face highlight + help-echo "mouse-2, RET: visit breakpoint")) + (with-current-buffer + (find-file-noselect + (if (file-exists-p file) file + (expand-file-name file gdb-cdir))) + (save-current-buffer + (set (make-local-variable 'gud-minor-mode) 'gdbmi) + (set (make-local-variable 'tool-bar-map) + gud-tool-bar-map)) + ;; only want one breakpoint icon at each location + (save-excursion + (goto-line (string-to-number line)) + (gdb-put-breakpoint-icon (eq flag ?y))))))))) + (end-of-line))) + (if (gdb-get-buffer 'gdb-assembler-buffer) (gdb-assembler-custom))) + +;; Frames buffer. This displays a perpetually correct bactrack trace. +;; +(def-gdb-auto-updated-buffer gdb-stack-buffer + gdbmi-invalidate-frames + "-stack-list-frames\n" + gdb-stack-list-frames-handler + gdb-stack-list-frames-custom) + +(defconst gdb-stack-list-frames-regexp +"level=\"\\(.*?\\)\",addr=\"\\(.*?\\)\",func=\"\\(.*?\\)\",file=\"\\(.*?\\)\",line=\"\\(.*?\\)\"") + +(defun gdb-stack-list-frames-handler () + (setq gdb-pending-triggers (delq 'gdbmi-invalidate-frames + gdb-pending-triggers)) + (let ((frame nil) + (call-stack nil)) + (with-current-buffer (gdb-get-create-buffer 'gdb-partial-output-buffer) + (goto-char (point-min)) + (while (re-search-forward gdb-stack-list-frames-regexp nil t) + (let ((frame (list (match-string 1) + (match-string 2) + (match-string 3) + (match-string 4) + (match-string 5)))) + (push frame call-stack)))) + (let ((buf (gdb-get-buffer 'gdb-stack-buffer))) + (and buf (with-current-buffer buf + (let ((p (point)) + (buffer-read-only nil)) + (erase-buffer) + (insert "Level\tFunc\tFile:Line\tAddr\n") + (dolist (frame (nreverse call-stack)) + (insert (concat + (nth 0 frame) "\t" + (nth 2 frame) "\t" + (nth 3 frame) ":" (nth 4 frame) "\t" + (nth 1 frame) "\n"))) + (goto-char p)))))) + (gdb-stack-list-frames-custom)) + +(defun gdb-stack-list-frames-custom () + (with-current-buffer (gdb-get-buffer 'gdb-stack-buffer) + (save-excursion + (let ((buffer-read-only nil)) + (goto-char (point-min)) + (forward-line 1) + (while (< (point) (point-max)) + (add-text-properties (point-at-bol) (point-at-eol) + '(mouse-face highlight + help-echo "mouse-2, RET: Select frame")) + (beginning-of-line) + (when (and (or (looking-at "^#[0-9]*\\s-*\\S-* in \\(\\S-*\\)") + (looking-at "^#[0-9]*\\s-*\\(\\S-*\\)")) + (equal (match-string 1) gdb-current-frame)) + (put-text-property (point-at-bol) (point-at-eol) + 'face '(:inverse-video t))) + (forward-line 1)))))) + +;; Locals buffer. +;; uses "-stack-list-locals 2". Needs GDB 6.1 onwards. +(def-gdb-auto-updated-buffer gdb-locals-buffer + gdbmi-invalidate-locals + "-stack-list-locals 2\n" + gdb-stack-list-locals-handler + gdb-stack-list-locals-custom) + +(defconst gdb-stack-list-locals-regexp + (concat "name=\"\\(.*?\\)\",type=\"\\(.*?\\)\"")) + +;; Dont display values of arrays or structures. +;; These can be expanded using gud-watch. +(defun gdb-stack-list-locals-handler nil + (setq gdb-pending-triggers (delq 'gdbmi-invalidate-locals + gdb-pending-triggers)) + (let ((local nil) + (locals-list nil)) + (with-current-buffer (gdb-get-create-buffer 'gdb-partial-output-buffer) + (goto-char (point-min)) + (while (re-search-forward gdb-stack-list-locals-regexp nil t) + (let ((local (list (match-string 1) + (match-string 2) + nil))) + (if (looking-at ",value=\"\\(.*?\\)\"") + (setcar (nthcdr 2 local) (match-string 1))) + (push local locals-list)))) + (let ((buf (gdb-get-buffer 'gdb-locals-buffer))) + (and buf (with-current-buffer buf + (let ((p (point)) + (buffer-read-only nil)) + (erase-buffer) + (dolist (local locals-list) + (insert + (concat (car local) "\t" (nth 1 local) "\t" + (or (nth 2 local) + (if (string-match "struct" (nth 1 local)) + "(structure)" + "(array)")) + "\n"))) + (goto-char p))))))) + +(defun gdb-stack-list-locals-custom () + nil) + +(defun gdbmi-source-info () + "Find the source file where the program starts and displays it with related +buffers." + (goto-char (point-min)) + (if (search-forward "source file is " nil t) + (if (looking-at "\\S-*") + (setq gdb-main-file (match-string 0))) + (setq gdb-view-source nil)) + (if (search-forward "directory is " nil t) + (if (looking-at "\\S-*:\\(\\S-*\\)") + (setq gdb-cdir (match-string 1)) + (looking-at "\\S-*") + (setq gdb-cdir (match-string 0)))) + +;temporary heuristic + (if gdb-main-file + (setq gdb-main-file (expand-file-name gdb-main-file gdb-cdir))) + + (if gdb-many-windows + (gdb-setup-windows) + (gdb-get-create-buffer 'gdb-breakpoints-buffer) + (when gdb-show-main + (switch-to-buffer gud-comint-buffer) + (delete-other-windows) + (split-window) + (other-window 1) + (switch-to-buffer + (if gdb-view-source + (gud-find-file gdb-main-file) + (gdb-get-create-buffer 'gdb-assembler-buffer))) + (other-window 1)))) + +(provide 'gdb-mi) +;;; gdbmi.el ends here diff --git a/gdb/observer.sh b/gdb/observer.sh new file mode 100755 index 00000000000..b23f15e044a --- /dev/null +++ b/gdb/observer.sh @@ -0,0 +1,157 @@ +#!/bin/sh -e + +if test $# -ne 3 +then + echo "Usage: $0 " 1>&2 + exit 0 +fi + +lang=$1 ; shift +texi=$1 ; shift +o=$1 ; shift +echo "Creating ${o}-tmp" 1>&2 +rm -f ${o}-tmp + +# Can use any of the following: cat cmp cp diff echo egrep expr false +# grep install-info ln ls mkdir mv pwd rm rmdir sed sleep sort tar +# test touch true + +cat <>${o}-tmp +/* GDB Notifications to Observers. + + Copyright 2004 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + -- + + This file was generated using observer.sh and observer.texi. */ + +EOF + + +case $lang in + h) cat <>${o}-tmp +#ifndef OBSERVER_H +#define OBSERVER_H + +struct observer; +struct bpstats; +struct so_list; +EOF + ;; +esac + + +# generate a list of events that can be observed + +IFS=: +sed -n ' +/@deftypefun void/{ +# Save original line for later processing into the actual parameter + h +# Convert from: @deftypefun void EVENT (TYPE @var{PARAM},...) +# to event and formals: EVENT:TYPE PARAM, ...: + s/^.* void \([a-z_][a-z_]*\) (\(.*\))$/\1:\2/ + s/@var{//g + s/}//g +# Switch to held + x +# Convert from: @deftypefun void FUNC (TYPE @var{PARAM},...) +# to actuals: PARAM, ... + s/^[^{]*[{]*// + s/[}]*[^}]*$// + s/}[^{]*{/, /g +# Combine held (EVENT:TYPE PARAM, ...:) and pattern (PARAM, ...) into +# FUNC:TYPE PARAM, ...:PARAM, ... + H + x + s/\n/:/g + p +} +' $texi | while read event formal actual +do + case $lang in + h) cat <>${o}-tmp + +/* ${event} notifications. */ + +typedef void (observer_${event}_ftype) (${formal}); + +extern struct observer *observer_attach_${event} (observer_${event}_ftype *f); +extern void observer_detach_${event} (struct observer *observer); +extern void observer_notify_${event} (${formal}); +EOF + ;; + + inc) + cat <>${o}-tmp + +/* ${event} notifications. */ + +static struct observer_list *${event}_subject = NULL; + +struct ${event}_args { `echo "${formal}" | sed -e 's/,/;/g'`; }; + +static void +observer_${event}_notification_stub (const void *data, const void *args_data) +{ + observer_${event}_ftype *notify = (observer_${event}_ftype *) data; + const struct ${event}_args *args = args_data; + notify (`echo ${actual} | sed -e 's/\([a-z0-9_][a-z0-9_]*\)/args->\1/g'`); +} + +struct observer * +observer_attach_${event} (observer_${event}_ftype *f) +{ + return generic_observer_attach (&${event}_subject, + &observer_${event}_notification_stub, + (void *) f); +} + +void +observer_detach_${event} (struct observer *observer) +{ + generic_observer_detach (&${event}_subject, observer); +} + +void +observer_notify_${event} (${formal}) +{ + struct ${event}_args args; + `echo ${actual} | sed -e 's/\([a-z0-9_][a-z0-9_]*\)/args.\1 = \1/g'`; + if (observer_debug) + fprintf_unfiltered (gdb_stdlog, "observer_notify_${event}() called\n"); + generic_observer_notify (${event}_subject, &args); +} +EOF + ;; + esac +done + + +case $lang in + h) cat <>${o}-tmp + +#endif /* OBSERVER_H */ +EOF +esac + + +echo Moving ${o}-tmp to ${o} +mv ${o}-tmp ${o} diff --git a/gdb/po/gdbtext b/gdb/po/gdbtext new file mode 100755 index 00000000000..1f80cf9eadb --- /dev/null +++ b/gdb/po/gdbtext @@ -0,0 +1,38 @@ +#!/bin/sh -e + +if test $# -lt 3 +then + echo "Usage: $0 ..." 1>&2 + exit 0 +fi + +xgettext=$1 ; shift +package=$1 ; shift + +for d in "$@" +do + __directories="$__directories --directory=$d" +done + +for d in "$@" +do + ( + cd $d + find * \ + -name '*-stub.c' -prune -o \ + -name 'testsuite' -prune -o \ + -name 'init.c' -prune -o \ + -name '*.[hc]' -print + ) +done | ${xgettext} \ + --default-domain=${package} \ + --copyright-holder="Free Software Foundation, Inc." \ + --add-comments \ + --files-from=- \ + --force-po \ + --debug \ + --language=c \ + --keyword=_ \ + --keyword=N_ \ + ${__directories} \ + -o po/${package}.pot diff --git a/gdb/ppcobsd-nat.c b/gdb/ppcobsd-nat.c new file mode 100644 index 00000000000..c36c63f11d8 --- /dev/null +++ b/gdb/ppcobsd-nat.c @@ -0,0 +1,98 @@ +/* Native-dependent code for OpenBSD/powerpc. + + Copyright 2004 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include "defs.h" +#include "inferior.h" +#include "regcache.h" + +#include +#include +#include +#include + +#include "ppc-tdep.h" +#include "ppcobsd-tdep.h" + +/* OpenBSD/powerpc doesn't have PT_GETFPREGS/PT_SETFPREGS like + NetBSD/powerpc and FreeBSD/powerpc. */ + +/* Fetch register REGNUM from the inferior. If REGNUM is -1, do this + for all registers. */ + +void +fetch_inferior_registers (int regnum) +{ + struct reg regs; + + if (ptrace (PT_GETREGS, PIDGET (inferior_ptid), + (PTRACE_TYPE_ARG3) ®s, 0) == -1) + perror_with_name ("Couldn't get registers"); + + ppcobsd_supply_gregset (&ppcobsd_gregset, current_regcache, -1, + ®s, sizeof regs); +} + +/* Store register REGNUM back into the inferior. If REGNUM is -1, do + this for all registers. */ + +void +store_inferior_registers (int regnum) +{ + struct reg regs; + + if (ptrace (PT_GETREGS, PIDGET (inferior_ptid), + (PTRACE_TYPE_ARG3) ®s, 0) == -1) + perror_with_name ("Couldn't get registers"); + + ppcobsd_collect_gregset (&ppcobsd_gregset, current_regcache, + regnum, ®s, sizeof regs); + + if (ptrace (PT_SETREGS, PIDGET (inferior_ptid), + (PTRACE_TYPE_ARG3) ®s, 0) == -1) + perror_with_name ("Couldn't write registers"); +} + + +/* Provide a prototype to silence -Wmissing-prototypes. */ +void _initialize_ppcobsd_nat (void); + +void +_initialize_ppcobsd_nat (void) +{ + /* General-purpose registers. */ + ppcobsd_reg_offsets.r0_offset = offsetof (struct reg, gpr); + ppcobsd_reg_offsets.pc_offset = offsetof (struct reg, pc); + ppcobsd_reg_offsets.ps_offset = offsetof (struct reg, ps); + ppcobsd_reg_offsets.cr_offset = offsetof (struct reg, cnd); + ppcobsd_reg_offsets.lr_offset = offsetof (struct reg, lr); + ppcobsd_reg_offsets.ctr_offset = offsetof (struct reg, cnt); + ppcobsd_reg_offsets.xer_offset = offsetof (struct reg, xer); + ppcobsd_reg_offsets.mq_offset = offsetof (struct reg, mq); + + /* Floating-point registers. */ + ppcobsd_reg_offsets.f0_offset = offsetof (struct reg, fpr); + ppcobsd_reg_offsets.fpscr_offset = -1; + + /* AltiVec registers. */ + ppcobsd_reg_offsets.vr0_offset = offsetof (struct vreg, vreg); + ppcobsd_reg_offsets.vscr_offset = offsetof (struct vreg, vscr); + ppcobsd_reg_offsets.vrsave_offset = offsetof (struct vreg, vrsave); +} diff --git a/gdb/ppcobsd-tdep.c b/gdb/ppcobsd-tdep.c new file mode 100644 index 00000000000..49a8601409e --- /dev/null +++ b/gdb/ppcobsd-tdep.c @@ -0,0 +1,178 @@ +/* Target-dependent code for OpenBSD/powerpc. + + Copyright 2004 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include "defs.h" +#include "arch-utils.h" +#include "osabi.h" +#include "regcache.h" +#include "regset.h" +#include "gdb_assert.h" + +#include "gdb_string.h" + +#include "ppc-tdep.h" +#include "ppcobsd-tdep.h" +#include "solib-svr4.h" + +/* Register offsets from . */ +struct ppc_reg_offsets ppcobsd_reg_offsets; + + +/* Core file support. */ + +/* Supply register REGNUM in the general-purpose register set REGSET + from the buffer specified by GREGS and LEN to register cache + REGCACHE. If REGNUM is -1, do this for all registers in REGSET. */ + +void +ppcobsd_supply_gregset (const struct regset *regset, + struct regcache *regcache, int regnum, + const void *gregs, size_t len) +{ + /* FIXME: jimb/2004-05-05: Some PPC variants don't have floating + point registers. Traditionally, GDB's register set has still + listed the floating point registers for such machines, so this + code is harmless. However, the new E500 port actually omits the + floating point registers entirely from the register set --- they + don't even have register numbers assigned to them. + + It's not clear to me how best to update this code, so this assert + will alert the first person to encounter the OpenBSD/E500 + combination to the problem. */ + gdb_assert (ppc_floating_point_unit_p (current_gdbarch)); + + ppc_supply_gregset (regset, regcache, regnum, gregs, len); + ppc_supply_fpregset (regset, regcache, regnum, gregs, len); +} + +/* Collect register REGNUM in the general-purpose register set + REGSET. from register cache REGCACHE into the buffer specified by + GREGS and LEN. If REGNUM is -1, do this for all registers in + REGSET. */ + +void +ppcobsd_collect_gregset (const struct regset *regset, + const struct regcache *regcache, int regnum, + void *gregs, size_t len) +{ + /* FIXME: jimb/2004-05-05: Some PPC variants don't have floating + point registers. Traditionally, GDB's register set has still + listed the floating point registers for such machines, so this + code is harmless. However, the new E500 port actually omits the + floating point registers entirely from the register set --- they + don't even have register numbers assigned to them. + + It's not clear to me how best to update this code, so this assert + will alert the first person to encounter the OpenBSD/E500 + combination to the problem. */ + gdb_assert (ppc_floating_point_unit_p (current_gdbarch)); + + ppc_collect_gregset (regset, regcache, regnum, gregs, len); + ppc_collect_fpregset (regset, regcache, regnum, gregs, len); +} + +/* OpenBS/powerpc register set. */ + +struct regset ppcobsd_gregset = +{ + &ppcobsd_reg_offsets, + ppcobsd_supply_gregset +}; + +/* Return the appropriate register set for the core section identified + by SECT_NAME and SECT_SIZE. */ + +static const struct regset * +ppcobsd_regset_from_core_section (struct gdbarch *gdbarch, + const char *sect_name, size_t sect_size) +{ + if (strcmp (sect_name, ".reg") == 0 && sect_size >= 412) + return &ppcobsd_gregset; + + return NULL; +} + + +static void +ppcobsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) +{ + /* OpenBSD uses SVR4-style shared libraries. */ + set_gdbarch_in_solib_call_trampoline + (gdbarch, generic_in_solib_call_trampoline); + set_solib_svr4_fetch_link_map_offsets + (gdbarch, svr4_ilp32_fetch_link_map_offsets); + + set_gdbarch_regset_from_core_section + (gdbarch, ppcobsd_regset_from_core_section); +} + + +/* OpenBSD uses uses the traditional NetBSD core file format, even for + ports that use ELF. */ +#define GDB_OSABI_NETBSD_CORE GDB_OSABI_OPENBSD_ELF + +static enum gdb_osabi +ppcobsd_core_osabi_sniffer (bfd *abfd) +{ + if (strcmp (bfd_get_target (abfd), "netbsd-core") == 0) + return GDB_OSABI_NETBSD_CORE; + + return GDB_OSABI_UNKNOWN; +} + + +/* Provide a prototype to silence -Wmissing-prototypes. */ +void _initialize_ppcobsd_tdep (void); + +void +_initialize_ppcobsd_tdep (void) +{ + /* BFD doesn't set a flavour for NetBSD style a.out core files. */ + gdbarch_register_osabi_sniffer (bfd_arch_powerpc, bfd_target_unknown_flavour, + ppcobsd_core_osabi_sniffer); + + gdbarch_register_osabi (bfd_arch_powerpc, 0, GDB_OSABI_OPENBSD_ELF, + ppcobsd_init_abi); + + /* Avoid initializing the register offsets again if they were + already initailized by ppcobsd-nat.c. */ + if (ppcobsd_reg_offsets.pc_offset == 0) + { + /* General-purpose registers. */ + ppcobsd_reg_offsets.r0_offset = 0; + ppcobsd_reg_offsets.pc_offset = 384; + ppcobsd_reg_offsets.ps_offset = 388; + ppcobsd_reg_offsets.cr_offset = 392; + ppcobsd_reg_offsets.lr_offset = 396; + ppcobsd_reg_offsets.ctr_offset = 400; + ppcobsd_reg_offsets.xer_offset = 404; + ppcobsd_reg_offsets.mq_offset = 408; + + /* Floating-point registers. */ + ppcobsd_reg_offsets.f0_offset = 128; + ppcobsd_reg_offsets.fpscr_offset = -1; + + /* AltiVec registers. */ + ppcobsd_reg_offsets.vr0_offset = 0; + ppcobsd_reg_offsets.vscr_offset = 512; + ppcobsd_reg_offsets.vrsave_offset = 520; + } +} diff --git a/gdb/ppcobsd-tdep.h b/gdb/ppcobsd-tdep.h new file mode 100644 index 00000000000..8f29aaa32ea --- /dev/null +++ b/gdb/ppcobsd-tdep.h @@ -0,0 +1,54 @@ +/* Target-dependent code for OpenBSD/powerpc. + + Copyright 2004 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef PPCOBSD_TDEP_H +#define PPCOBSD_TDEP_H + +#include + +struct regset; +struct regcache; + +/* Register offsets for OpenBSD/powerpc. */ +extern struct ppc_reg_offsets ppcobsd_reg_offsets; + +/* Register sets for OpenBSD/powerpc. */ +extern struct regset ppcobsd_gregset; + + +/* Supply register REGNUM in the general-purpose register set REGSET + from the buffer specified by GREGS and LEN to register cache + REGCACHE. If REGNUM is -1, do this for all registers in REGSET. */ + +extern void ppcobsd_supply_gregset (const struct regset *regset, + struct regcache *regcache, int regnum, + const void *gregs, size_t len); + +/* Collect register REGNUM in the general-purpose register set + REGSET. from register cache REGCACHE into the buffer specified by + GREGS and LEN. If REGNUM is -1, do this for all registers in + REGSET. */ + +extern void ppcobsd_collect_gregset (const struct regset *regset, + const struct regcache *regcache, + int regnum, void *gregs, size_t len); + +#endif /* ppcobsd-tdep.h */ diff --git a/gdb/regset.c b/gdb/regset.c new file mode 100644 index 00000000000..d588b7d64bc --- /dev/null +++ b/gdb/regset.c @@ -0,0 +1,46 @@ +/* Manage register sets. + + Copyright 2004 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include "defs.h" +#include "regset.h" + +#include "gdb_assert.h" + +/* Allocate a fresh 'struct regset' whose supply_regset function is + SUPPLY_REGSET, and whose collect_regset function is COLLECT_REGSET. + If the regset has no collect_regset function, pass NULL for + COLLECT_REGSET. + + The object returned is allocated on ARCH's obstack. */ + +struct regset * +regset_alloc (struct gdbarch *arch, + supply_regset_ftype *supply_regset, + collect_regset_ftype *collect_regset) +{ + struct regset *regset = GDBARCH_OBSTACK_ZALLOC (arch, struct regset); + + regset->arch = arch; + regset->supply_regset = supply_regset; + regset->collect_regset = collect_regset; + + return regset; +} diff --git a/gdb/symfile-mem.c b/gdb/symfile-mem.c new file mode 100644 index 00000000000..71991cffdef --- /dev/null +++ b/gdb/symfile-mem.c @@ -0,0 +1,146 @@ +/* Reading symbol files from memory. + + Copyright 1986, 1987, 1989, 1991, 1994, 1995, 1996, 1998, 2000, + 2001, 2002, 2003, 2004 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* This file defines functions (and commands to exercise those + functions) for reading debugging information from object files + whose images are mapped directly into the inferior's memory. For + example, the Linux kernel maps a "syscall DSO" into each process's + address space; this DSO provides kernel-specific code for some + system calls. + + At the moment, BFD only has functions for parsing object files from + memory for the ELF format, even though the general idea isn't + ELF-specific. This means that BFD only provides the functions GDB + needs when configured for ELF-based targets. So these functions + may only be compiled on ELF-based targets. + + GDB has no idea whether it has been configured for an ELF-based + target or not: it just tries to handle whatever files it is given. + But this means there are no preprocessor symbols on which we could + make these functions' compilation conditional. + + So, for the time being, we put these functions alone in this file, + and have .mt files reference them as appropriate. In the future, I + hope BFD will provide a format-independent bfd_from_remote_memory + entry point. */ + + +#include "defs.h" +#include "symtab.h" +#include "gdbcore.h" +#include "objfiles.h" +#include "gdbcmd.h" +#include "target.h" +#include "value.h" +#include "symfile.h" + + +/* Read inferior memory at ADDR to find the header of a loaded object file + and read its in-core symbols out of inferior memory. TEMPL is a bfd + representing the target's format. */ +static struct objfile * +symbol_file_add_from_memory (struct bfd *templ, CORE_ADDR addr, int from_tty) +{ + struct objfile *objf; + struct bfd *nbfd; + struct bfd_section *sec; + bfd_vma loadbase; + struct section_addr_info *sai; + unsigned int i; + + if (bfd_get_flavour (templ) != bfd_target_elf_flavour) + error ("add-symbol-file-from-memory not supported for this target"); + + nbfd = bfd_elf_bfd_from_remote_memory (templ, addr, &loadbase, + target_read_memory); + if (nbfd == NULL) + error ("Failed to read a valid object file image from memory."); + + nbfd->filename = xstrdup ("shared object read from target memory"); + + if (!bfd_check_format (nbfd, bfd_object)) + { + /* FIXME: should be checking for errors from bfd_close (for one thing, + on error it does not free all the storage associated with the + bfd). */ + bfd_close (nbfd); + error ("Got object file from memory but can't read symbols: %s.", + bfd_errmsg (bfd_get_error ())); + } + + sai = alloc_section_addr_info (bfd_count_sections (nbfd)); + make_cleanup (xfree, sai); + i = 0; + for (sec = nbfd->sections; sec != NULL; sec = sec->next) + if ((bfd_get_section_flags (nbfd, sec) & (SEC_ALLOC|SEC_LOAD)) != 0) + { + sai->other[i].addr = bfd_get_section_vma (nbfd, sec) + loadbase; + sai->other[i].name = (char *) bfd_get_section_name (nbfd, sec); + sai->other[i].sectindex = sec->index; + ++i; + } + + objf = symbol_file_add_from_bfd (nbfd, from_tty, + sai, 0, OBJF_SHARED); + + /* This might change our ideas about frames already looked at. */ + reinit_frame_cache (); + + return objf; +} + + +static void +add_symbol_file_from_memory_command (char *args, int from_tty) +{ + CORE_ADDR addr; + struct bfd *templ; + + if (args == NULL) + error ("add-symbol-file-from-memory requires an expression argument"); + + addr = parse_and_eval_address (args); + + /* We need some representative bfd to know the target we are looking at. */ + if (symfile_objfile != NULL) + templ = symfile_objfile->obfd; + else + templ = exec_bfd; + if (templ == NULL) + error ("\ +Must use symbol-file or exec-file before add-symbol-file-from-memory."); + + symbol_file_add_from_memory (templ, addr, from_tty); +} + + +void +_initialize_symfile_mem (void) +{ + add_cmd ("add-symbol-file-from-memory", class_files, + add_symbol_file_from_memory_command, + "\ +Load the symbols out of memory from a dynamically loaded object file.\n\ +Give an expression for the address of the file's shared object file header.", + &cmdlist); + +} diff --git a/gdb/testsuite/gdb.ada/gnat_ada.gin b/gdb/testsuite/gdb.ada/gnat_ada.gin new file mode 100644 index 00000000000..23cd5586dab --- /dev/null +++ b/gdb/testsuite/gdb.ada/gnat_ada.gin @@ -0,0 +1,27 @@ +-- Copyright 2004 Free Software Foundation, Inc. +-- +-- This program is free software; you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation; either version 2 of the License, or +-- (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program; if not, write to the Free Software +-- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +-- This project file allows us to control the location where the +-- compilation artifacts produced when building the Ada examples +-- are stored. + +project Gnat_Ada is + + for Source_Dirs use ("@srcdir@"); + -- No need to set the Object_Dir, it is set to "." by default + -- (which means the same directory as this project file). + +end Gnat_Ada; diff --git a/gdb/testsuite/gdb.arch/e500-prologue.c b/gdb/testsuite/gdb.arch/e500-prologue.c new file mode 100644 index 00000000000..f9e83dabf8a --- /dev/null +++ b/gdb/testsuite/gdb.arch/e500-prologue.c @@ -0,0 +1,54 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2004 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + USA. */ + +void arg_passing_test2 (void); + +int +main (void) +{ + arg_passing_test2 (); + return 0; +} + + +/* Asm for procedure arg_passing_test2. + + The challenge here is getting past the 'mr 0,3' and 'stb' + instructions. */ + +asm (" .section \".text\"\n" + " .align 2\n" + " .globl arg_passing_test2\n" + " .type arg_passing_test2, @function\n" + "arg_passing_test2:\n" + " stwu 1,-64(1)\n" + " stw 31,60(1)\n" + " mr 31,1\n" + " mr 0,3\n" + " evstdd 4,16(31)\n" + " stw 5,24(31)\n" + " stw 7,32(31)\n" + " stw 8,36(31)\n" + " stw 9,40(31)\n" + " stb 0,8(31)\n" + " lwz 11,0(1)\n" + " lwz 31,-4(11)\n" + " mr 1,11\n" + " blr\n" + " .size arg_passing_test2, .-arg_passing_test2\n"); diff --git a/gdb/testsuite/gdb.arch/e500-prologue.exp b/gdb/testsuite/gdb.arch/e500-prologue.exp new file mode 100644 index 00000000000..06dec9fb28d --- /dev/null +++ b/gdb/testsuite/gdb.arch/e500-prologue.exp @@ -0,0 +1,82 @@ +# Copyright 2004 Free Software Foundation, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# This file is part of the gdb testsuite. + +if $tracelevel { + strace $tracelevel +} + +# Test PowerPC E500 prologue analyzer. + +set prms_id 0 +set bug_id 0 + +if ![istarget "powerpc-*"] then { + verbose "Skipping powerpc E500 prologue tests." + return +} + +set testfile "e500-prologue" +set srcfile ${testfile}.c +set binfile ${objdir}/${subdir}/${testfile} +if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {}] != "" } { + unsupported "Testcase compile failed." + return -1 +} + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + +# Insert a breakpoint in FUNCTION and verifies that the breakpoint was +# inserted at the expected location. EXPECTED_LOCATION should be an +# offset relative to the function start address. +proc insert_breakpoint {function expected_location} { + global gdb_prompt + global expect_out + global hex + + set address "" + + # Insert a breakpoint using the given function name, and extract + # the breakpoint address for the output. + gdb_test_multiple "break $function" "set breakpoint in $function" { + -re "Breakpoint 1 at ($hex).*$gdb_prompt $" { + set address $expect_out(1,string) + } + default { + fail "set breakpoint in $function" + } + } + + # If we managed to get the breakpoing address, then check that + # we inserted it at the expected location by examining the + # instruction at that address (we're not interested in the insn + # itself, but rather at the address printed at the begining of + # the instruction). + if { $address != "" } then { + gdb_test "x /i $address" \ + ".*<$function\\+$expected_location>.*" \ + "check $function breakpoint address" + } else { + fail "unable to compute breakpoint address" + } + +} + +insert_breakpoint "arg_passing_test2" 40 diff --git a/gdb/testsuite/gdb.arch/i386-cpuid.h b/gdb/testsuite/gdb.arch/i386-cpuid.h new file mode 100644 index 00000000000..067b22fa712 --- /dev/null +++ b/gdb/testsuite/gdb.arch/i386-cpuid.h @@ -0,0 +1,77 @@ +/* Helper file for i386 platform. Runtime check for MMX/SSE/SSE2 support. + + Copyright 2004 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* Used by 20020523-2.c and i386-sse-6.c, and possibly others. */ +/* Plagarized from 20020523-2.c. */ +/* Plagarized from gcc. */ + +#define bit_CMOV (1 << 15) +#define bit_MMX (1 << 23) +#define bit_SSE (1 << 25) +#define bit_SSE2 (1 << 26) + +#ifndef NOINLINE +#define NOINLINE __attribute__ ((noinline)) +#endif + +unsigned int i386_cpuid (void) NOINLINE; + +unsigned int NOINLINE +i386_cpuid (void) +{ + int fl1, fl2; + +#ifndef __x86_64__ + /* See if we can use cpuid. On AMD64 we always can. */ + __asm__ ("pushfl; pushfl; popl %0; movl %0,%1; xorl %2,%0;" + "pushl %0; popfl; pushfl; popl %0; popfl" + : "=&r" (fl1), "=&r" (fl2) + : "i" (0x00200000)); + if (((fl1 ^ fl2) & 0x00200000) == 0) + return (0); +#endif + + /* Host supports cpuid. See if cpuid gives capabilities, try + CPUID(0). Preserve %ebx and %ecx; cpuid insn clobbers these, we + don't need their CPUID values here, and %ebx may be the PIC + register. */ +#ifdef __x86_64__ + __asm__ ("pushq %%rcx; pushq %%rbx; cpuid; popq %%rbx; popq %%rcx" + : "=a" (fl1) : "0" (0) : "rdx", "cc"); +#else + __asm__ ("pushl %%ecx; pushl %%ebx; cpuid; popl %%ebx; popl %%ecx" + : "=a" (fl1) : "0" (0) : "edx", "cc"); +#endif + if (fl1 == 0) + return (0); + + /* Invoke CPUID(1), return %edx; caller can examine bits to + determine what's supported. */ +#ifdef __x86_64__ + __asm__ ("pushq %%rcx; pushq %%rbx; cpuid; popq %%rbx; popq %%rcx" + : "=d" (fl2), "=a" (fl1) : "1" (1) : "cc"); +#else + __asm__ ("pushl %%ecx; pushl %%ebx; cpuid; popl %%ebx; popl %%ecx" + : "=d" (fl2), "=a" (fl1) : "1" (1) : "cc"); +#endif + + return fl2; +} diff --git a/gdb/testsuite/gdb.arch/i386-sse.c b/gdb/testsuite/gdb.arch/i386-sse.c new file mode 100644 index 00000000000..496721c5e82 --- /dev/null +++ b/gdb/testsuite/gdb.arch/i386-sse.c @@ -0,0 +1,90 @@ +/* Test program for SSE registers. + + Copyright 2004 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include "i386-cpuid.h" + +typedef struct { + float f[4]; +} v4sf_t; + + +v4sf_t data[8] = + { + { { 0.0, 0.25, 0.50, 0.75 } }, + { { 1.0, 1.25, 1.50, 1.75 } }, + { { 2.0, 2.25, 2.50, 2.75 } }, + { { 3.0, 3.25, 3.50, 3.75 } }, + { { 4.0, 4.25, 4.50, 4.75 } }, + { { 5.0, 5.25, 5.50, 5.75 } }, + { { 6.0, 6.25, 6.50, 6.75 } }, + { { 7.0, 7.25, 7.50, 7.75 } }, + }; + + +int +have_sse (void) +{ + int edx = i386_cpuid (); + + if (edx & bit_SSE) + return 1; + else + return 0; +} + +int +main (int argc, char **argv) +{ + if (have_sse ()) + { + asm ("movaps 0(%0), %%xmm0\n\t" + "movaps 16(%0), %%xmm1\n\t" + "movaps 32(%0), %%xmm2\n\t" + "movaps 48(%0), %%xmm3\n\t" + "movaps 64(%0), %%xmm4\n\t" + "movaps 80(%0), %%xmm5\n\t" + "movaps 96(%0), %%xmm6\n\t" + "movaps 112(%0), %%xmm7\n\t" + : /* no output operands */ + : "r" (data) + : "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7"); + + puts ("Hi!"); /* first breakpoint here */ + + asm ( + "movaps %%xmm0, 0(%0)\n\t" + "movaps %%xmm1, 16(%0)\n\t" + "movaps %%xmm2, 32(%0)\n\t" + "movaps %%xmm3, 48(%0)\n\t" + "movaps %%xmm4, 64(%0)\n\t" + "movaps %%xmm5, 80(%0)\n\t" + "movaps %%xmm6, 96(%0)\n\t" + "movaps %%xmm7, 112(%0)\n\t" + : /* no output operands */ + : "r" (data) + : "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7"); + + puts ("Bye!"); /* second breakpoint here */ + } + + return 0; +} diff --git a/gdb/testsuite/gdb.arch/i386-sse.exp b/gdb/testsuite/gdb.arch/i386-sse.exp new file mode 100644 index 00000000000..702ee7127a5 --- /dev/null +++ b/gdb/testsuite/gdb.arch/i386-sse.exp @@ -0,0 +1,92 @@ +# Copyright 2004 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +# Please email any bugs, comments, and/or additions to this file to: +# bug-gdb@gnu.org + +# This file is part of the gdb testsuite. + +if $tracelevel { + strace $tracelevel +} + +set prms_id 0 +set bug_id 0 + +if ![istarget "i?86-*-*"] then { + verbose "Skipping i386 SSE tests." + return +} + +set testfile "i386-sse" +set srcfile ${testfile}.c +set binfile ${objdir}/${subdir}/${testfile} +if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } { + unsupported "compiler does not support SSE" + return +} + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + +if ![runto_main] then { + gdb_suppress_tests +} + +send_gdb "print have_sse ()\r" +gdb_expect { + -re ".. = 1\r\n$gdb_prompt " { + pass "check whether processor supports SSE" + } + -re ".. = 0\r\n$gdb_prompt " { + verbose "processor does not support SSE; skipping SSE tests" + return + } + -re ".*$gdb_prompt $" { + fail "check whether processor supports SSE" + } + timeout { + fail "check whether processor supports SSE (timeout)" + } +} + +gdb_test "break [gdb_get_line_number "first breakpoint here"]" \ + "Breakpoint .* at .*i386-sse.c.*" \ + "set breakpoint in main" +gdb_continue_to_breakpoint "continue to first breakpoint in main" + +foreach r {0 1 2 3 4 5 6 7} { + gdb_test "print \$xmm$r.v4_float" \ + ".. = \\{$r, $r.25, $r.5, $r.75\\}.*" \ + "check contents of %xmm$r" +} + +foreach r {0 1 2 3 4 5 6 7} { + gdb_test "set var \$xmm$r.v4_float\[0\] = $r + 10" "" "set %xmm$r" +} + +gdb_test "break [gdb_get_line_number "second breakpoint here"]" \ + "Breakpoint .* at .*i386-sse.c.*" \ + "set breakpoint in main" +gdb_continue_to_breakpoint "continue to second breakpoint in main" + +foreach r {0 1 2 3 4 5 6 7} { + gdb_test "print data\[$r\]" \ + ".. = \\{f = \\{[expr $r + 10], $r.25, $r.5, $r.75\\}\\}.*" \ + "check contents of data\[$r\]" +} diff --git a/gdb/testsuite/gdb.arch/powerpc-aix-prologue.c b/gdb/testsuite/gdb.arch/powerpc-aix-prologue.c new file mode 100644 index 00000000000..ee31b496d3e --- /dev/null +++ b/gdb/testsuite/gdb.arch/powerpc-aix-prologue.c @@ -0,0 +1,55 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2004 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + USA. */ + +void li_stw (void); + +int +main (void) +{ + li_stw (); + return 0; +} + +/* Asm for procedure li_stw(). + + The purpose of this function is to verify that GDB does not + include the li insn as part of the function prologue (only part + of the prologue if part of a pair of insns saving vector registers). + Similarly, GDB should not include the stw insn following the li insn, + because the source register is not used for parameter passing. */ + + +asm (" .csect .text[PR]\n" + " .align 2\n" + " .lglobl .li_stw\n" + " .csect li_stw[DS]\n" + "li_stw:\n" + " .long .li_stw, TOC[tc0], 0\n" + " .csect .text[PR]\n" + ".li_stw:\n" + " stw 31,-4(1)\n" + " stwu 1,-48(1)\n" + " mr 31,1\n" + " stw 11,24(31)\n" + " li 0,8765\n" + " stw 0,28(31)\n" + " lwz 1,0(1)\n" + " lwz 31,-4(1)\n" + " blr\n"); + diff --git a/gdb/testsuite/gdb.arch/powerpc-aix-prologue.exp b/gdb/testsuite/gdb.arch/powerpc-aix-prologue.exp new file mode 100644 index 00000000000..76e3c27cf2e --- /dev/null +++ b/gdb/testsuite/gdb.arch/powerpc-aix-prologue.exp @@ -0,0 +1,82 @@ +# Copyright 2004 Free Software Foundation, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# This file is part of the gdb testsuite. + +if $tracelevel { + strace $tracelevel +} + +# Test rs6000 prologue analyzer. + +set prms_id 0 +set bug_id 0 + +if ![istarget "powerpc-*-aix*"] then { + verbose "Skipping powerpc-aix prologue tests." + return +} + +set testfile "powerpc-aix-prologue" +set srcfile ${testfile}.c +set binfile ${objdir}/${subdir}/${testfile} +if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {}] != "" } { + unsupported "Testcase compile failed." + return -1 +} + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + +# Insert a breakpoint in FUNCTION and verifies that the breakpoint was +# inserted at the expected location. EXPECTED_LOCATION should be an +# offset relative to the function start address. +proc insert_breakpoint {function expected_location} { + global gdb_prompt + global expect_out + global hex + + set address "" + + # Insert a breakpoint using the given function name, and extract + # the breakpoint address for the output. + gdb_test_multiple "break $function" "set breakpoint in $function" { + -re "Breakpoint 1 at ($hex).*$gdb_prompt $" { + set address $expect_out(1,string) + } + default { + fail "set breakpoint in $function" + } + } + + # If we managed to get the breakpoing address, then check that + # we inserted it at the expected location by examining the + # instruction at that address (we're not interested in the insn + # itself, but rather at the address printed at the begining of + # the instruction). + if { $address != "" } then { + gdb_test "x /i $address" \ + ".*<$function\\+$expected_location>.*" \ + "check $function breakpoint address" + } else { + fail "unable to compute breakpoint address" + } + +} + +insert_breakpoint "li_stw" 12 diff --git a/gdb/testsuite/gdb.asm/pa.inc b/gdb/testsuite/gdb.asm/pa.inc new file mode 100644 index 00000000000..d53336e3167 --- /dev/null +++ b/gdb/testsuite/gdb.asm/pa.inc @@ -0,0 +1,44 @@ + comment "subroutine prologue" + .macro gdbasm_enter + stw %rp, -20(%sp) + copy %r3, %r1 + copy %sp, %r3 + stwm %r1, 64(%sp) + .endm + + comment "subroutine epilogue" + .macro gdbasm_leave + ldw -20(%r3), %rp + bv %r0(%rp) + ldwm -64(%sp), %r3 + .endm + + .macro gdbasm_call subr + bl \subr , %rp + nop + .endm + + .macro gdbasm_several_nops + nop + nop + nop + nop + .endm + + comment "exit (0)" + .macro gdbasm_exit0 + comment "Don't know how to exit, but this will certainly halt..." + ldw 0(%r0), %r1 + .endm + + comment "crt0 startup" + .macro gdbasm_startup + .align 4 + .endm + + comment "Declare a data variable" + .macro gdbasm_datavar name value + .data +\name: + .long \value + .endm diff --git a/gdb/testsuite/gdb.base/call-sc.c b/gdb/testsuite/gdb.base/call-sc.c new file mode 100644 index 00000000000..70ae87f7991 --- /dev/null +++ b/gdb/testsuite/gdb.base/call-sc.c @@ -0,0 +1,83 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2004 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +/* Useful abreviations. */ +typedef void t; +typedef char tc; +typedef short ts; +typedef int ti; +typedef long tl; +typedef long long tll; +typedef float tf; +typedef double td; +typedef long double tld; +typedef enum { e = '1' } te; + +/* Force the type of each field. */ +#ifndef T +typedef t T; +#endif + +T foo = '1', L; + +T fun() +{ + return foo; +} + +#ifdef PROTOTYPES +void Fun(T foo) +#else +void Fun(foo) + T foo; +#endif +{ + L = foo; +} + +zed () +{ + L = 'Z'; +} + +int main() +{ +#ifdef usestubs + set_debug_traps(); + breakpoint(); +#endif + int i; + + Fun(foo); + + /* An infinite loop that first clears all the variables and then + calls the function. This "hack" is to make re-testing easier - + "advance fun" is guaranteed to have always been preceeded by a + global variable clearing zed call. */ + + zed (); + while (1) + { + L = fun (); + zed (); + } + + return 0; +} diff --git a/gdb/testsuite/gdb.base/call-sc.exp b/gdb/testsuite/gdb.base/call-sc.exp new file mode 100644 index 00000000000..01a9f152097 --- /dev/null +++ b/gdb/testsuite/gdb.base/call-sc.exp @@ -0,0 +1,500 @@ +# This testcase is part of GDB, the GNU debugger. + +# Copyright 2004 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +# Test "return", "finish", and "call" of functions that a scalar (int, +# float, enum) and/or take a single scalar parameter. + +if $tracelevel then { + strace $tracelevel +} + +set prms_id 0 +set bug_id 0 + +# Some targets can't call functions, so don't even bother with this +# test. + +if [target_info exists gdb,cannot_call_functions] { + setup_xfail "*-*-*" + fail "This target can not call functions" + continue +} + +set testfile "call-sc" +set srcfile ${testfile}.c +set binfile ${objdir}/${subdir}/${testfile} + +# Create and source the file that provides information about the +# compiler used to compile the test case. + +if [get_compiler_info ${binfile}] { + return -1; +} + +# Use the file name, compiler and tuples to set up any needed KFAILs. + +proc setup_kfails { file tuples bug } { + global testfile + if [string match $file $testfile] { + foreach f $tuples { setup_kfail $f $bug } + } +} + +proc setup_compiler_kfails { file compiler format tuples bug } { + global testfile + if {[string match $file $testfile] && [test_compiler_info $compiler] && [test_debug_format $format]} { + foreach f $tuples { setup_kfail $f $bug } + } +} + +# Compile a variant of scalars.c using TYPE to specify the type of the +# parameter and return-type. Run the compiled program up to "main". +# Also updates the global "testfile" to reflect the most recent build. + +proc start_scalars_test { type } { + global testfile + global srcfile + global binfile + global objdir + global subdir + global srcdir + global gdb_prompt + global expect_out + + # Create the additional flags + set flags "debug additional_flags=-DT=${type}" + set testfile "call-sc-${type}" + + set binfile ${objdir}/${subdir}/${testfile} + if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable "${flags}"] != "" } { + # built the second test case since we can't use prototypes + warning "Prototypes not supported, rebuilding with -DNO_PROTOTYPES" + if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable "${flags} additional_flags=-DNO_PROTOTYPES"] != "" } { + gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail." + } + } + + # Start with a fresh gdb. + gdb_exit + gdb_start + gdb_reinitialize_dir $srcdir/$subdir + gdb_load ${binfile} + + # Make certain that the output is consistent + gdb_test "set print sevenbit-strings" "" \ + "set print sevenbit-strings; ${testfile}" + gdb_test "set print address off" "" \ + "set print address off; ${testfile}" + gdb_test "set width 0" "" \ + "set width 0; ${testfile}" + + # Advance to main + if { ![runto_main] } then { + gdb_suppress_tests; + } + + # Get the debug format + get_debug_format + + # check that type matches what was passed in + set test "ptype; ${testfile}" + set foo_t "xxx" + gdb_test_multiple "ptype ${type}" "${test}" { + -re "type = (\[^\r\n\]*)\r\n$gdb_prompt $" { + set foo_t "$expect_out(1,string)" + pass "$test (${foo_t})" + } + } + gdb_test "ptype foo" "type = ${foo_t}" "ptype foo; ${testfile} $expect_out(1,string)" +} + + +# Given N (0..25), return the corresponding alphabetic letter in lower +# or upper case. This is ment to be i18n proof. + +proc i2a { n } { + return [string range "abcdefghijklmnopqrstuvwxyz" $n $n] +} + +proc I2A { n } { + return [string toupper [i2a $n]] +} + + +# Use the file name, compiler and tuples to set up any needed KFAILs. + +proc setup_kfails { file tuples bug } { + global testfile + if [string match $file $testfile] { + foreach f $tuples { setup_kfail $f $bug } + } +} + +proc setup_compiler_kfails { file compiler format tuples bug } { + global testfile + if {[string match $file $testfile] && [test_compiler_info $compiler] && [test_debug_format $format]} { + foreach f $tuples { setup_kfail $f $bug } + } +} + +# Test GDB's ability to make inferior function calls to functions +# returning (or passing) in a single scalar. + +# start_scalars_test() will have previously built a program with a +# specified scalar type. To ensure robustness of the output, "p/c" is +# used. + +# This tests the code paths "which return-value convention?" and +# "extract return-value from registers" called by "infcall.c". + +proc test_scalar_calls { } { + global testfile + global gdb_prompt + + # Check that GDB can always extract a scalar-return value from an + # inferior function call. Since GDB always knows the location of + # an inferior function call's return value these should never fail + + # Implemented by calling the parameterless function "fun" and then + # examining the return value printed by GDB. + + set tests "call ${testfile}" + + # Call fun, checking the printed return-value. + gdb_test "p/c fun()" "= 49 '1'" "p/c fun(); ${tests}" + + # Check that GDB can always pass a structure to an inferior function. + # This test can never fail. + + # Implemented by calling the one parameter function "Fun" which + # stores its parameter in the global variable "L". GDB then + # examining that global to confirm that the value is as expected. + + gdb_test "call Fun(foo)" "" "call Fun(foo); ${tests}" + gdb_test "p/c L" " = 49 '1'" "p/c L; ${tests}" +} + +# Test GDB's ability to both return a function (with "return" or +# "finish") and correctly extract/store any corresponding +# return-value. + +# Check that GDB can consistently extract/store structure return +# values. There are two cases - returned in registers and returned in +# memory. For the latter case, the return value can't be found and a +# failure is "expected". However GDB must still both return the +# function and display the final source and line information. + +# N identifies the number of elements in the struct that will be used +# for the test case. FAILS is a list of target tuples that will fail +# this test. + +# This tests the code paths "which return-value convention?", "extract +# return-value from registers", and "store return-value in registers". +# Unlike "test struct calls", this test is expected to "fail" when the +# return-value is in memory (GDB can't find the location). The test +# is in three parts: test "return"; test "finish"; check that the two +# are consistent. GDB can sometimes work for one command and not the +# other. + +proc test_scalar_returns { } { + global gdb_prompt + global testfile + + set tests "return ${testfile}" + + + # Check that "return" works. + + # GDB must always force the return of a function that has + # a struct result. Dependant on the ABI, it may, or may not be + # possible to store the return value in a register. + + # The relevant code looks like "L{n} = fun{n}()". The test forces + # "fun{n}" to "return" with an explicit value. Since that code + # snippet will store the the returned value in "L{n}" the return + # is tested by examining "L{n}". This assumes that the + # compiler implemented this as fun{n}(&L{n}) and hence that when + # the value isn't stored "L{n}" remains unchanged. Also check for + # consistency between this and the "finish" case. + + # Get into a call of fun + gdb_test "advance fun" \ + "fun .*\[\r\n\]+\[0-9\].*return foo.*" \ + "advance to fun for return; ${tests}" + + # Check that the program invalidated the relevant global. + gdb_test "p/c L" " = 90 'Z'" "zed L for return; ${tests}" + + # Force the "return". This checks that the return is always + # performed, and that GDB correctly reported this to the user. + # GDB 6.0 and earlier, when the return-value's location wasn't + # known, both failed to print a final "source and line" and misplaced + # the frame ("No frame"). + + # The test is writen so that it only reports one FAIL/PASS for the + # entire operation. The value returned is checked further down. + # "return_value_unknown", if non-empty, records why GDB realised + # that it didn't know where the return value was. + + set test "return foo; ${tests}" + set return_value_unknown 0 + set return_value_unimplemented 0 + gdb_test_multiple "return foo" "${test}" { + -re "The location" { + # Ulgh, a struct return, remember this (still need prompt). + set return_value_unknown 1 + exp_continue + } + -re "A structure or union" { + # Ulgh, a struct return, remember this (still need prompt). + set return_value_unknown 1 + # Double ulgh. Architecture doesn't use return_value and + # hence hasn't implemented small structure return. + set return_value_unimplemented 1 + exp_continue + } + -re "Make fun return now.*y or n. $" { + gdb_test_multiple "y" "${test}" { + -re "L *= fun.*${gdb_prompt} $" { + # Need to step off the function call + gdb_test "next" "zed.*" "${test}" + } + -re "zed \\(\\);.*$gdb_prompt $" { + pass "${test}" + } + } + } + } + + # If the previous test did not work, the program counter might + # still be inside foo() rather than main(). Make sure the program + # counter is is main(). + # + # This happens on ppc64 GNU/Linux with gcc 3.4.1 and a buggy GDB + + set test "return foo; synchronize pc to main()" + for {set loop_count 0} {$loop_count < 2} {incr loop_count} { + gdb_test_multiple "backtrace 1" $test { + -re "#0.*main \\(\\).*${gdb_prompt} $" { + pass $test + set loop_count 2 + } + -re "#0.*fun \\(\\).*${gdb_prompt} $" { + if {$loop_count < 1} { + gdb_test "finish" ".*" "" + } else { + fail $test + set loop_count 2 + } + } + } + } + + # Check that the return-value is as expected. At this stage we're + # just checking that GDB has returned a value consistent with + # "return_value_unknown" set above. + + set test "value foo returned; ${tests}" + gdb_test_multiple "p/c L" "${test}" { + -re " = 49 '1'.*${gdb_prompt} $" { + if $return_value_unknown { + # This contradicts the above claim that GDB didn't + # know the location of the return-value. + fail "${test}" + } else { + pass "${test}" + } + } + -re " = 90 .*${gdb_prompt} $" { + if $return_value_unknown { + # The struct return case. Since any modification + # would be by reference, and that can't happen, the + # value should be unmodified and hence Z is expected. + # Is this a reasonable assumption? + pass "${test}" + } else { + # This contradicts the above claim that GDB knew + # the location of the return-value. + fail "${test}" + } + } + -re ".*${gdb_prompt} $" { + if $return_value_unimplemented { + # What a suprize. The architecture hasn't implemented + # return_value, and hence has to fail. + kfail "$test" gdb/1444 + } else { + fail "$test" + } + } + } + + # Check that a "finish" works. + + # This is almost but not quite the same as "call struct funcs". + # Architectures can have subtle differences in the two code paths. + + # The relevant code snippet is "L{n} = fun{n}()". The program is + # advanced into a call to "fun{n}" and then that function is + # finished. The returned value that GDB prints, reformatted using + # "p/c", is checked. + + # Get into "fun()". + gdb_test "advance fun" \ + "fun .*\[\r\n\]+\[0-9\].*return foo.*" \ + "advance to fun for finish; ${tests}" + + # Check that the program invalidated the relevant global. + gdb_test "p/c L" " = 90 'Z'" "zed L for finish; ${tests}" + + # Finish the function, set 'finish_value_unknown" to non-empty if the + # return-value was not found. + set test "finish foo; ${tests}" + set finish_value_unknown 0 + gdb_test_multiple "finish" "${test}" { + -re "Value returned is .*${gdb_prompt} $" { + pass "${test}" + } + -re "Cannot determine contents.*${gdb_prompt} $" { + # Expected bad value. For the moment this is ok. + set finish_value_unknown 1 + pass "${test}" + } + } + + # Re-print the last (return-value) using the more robust + # "p/c". If no return value was found, the 'Z' from the previous + # check that the variable was cleared, is printed. + set test "value foo finished; ${tests}" + gdb_test_multiple "p/c" "${test}" { + -re " = 49 '1'\[\r\n\]+${gdb_prompt} $" { + if $finish_value_unknown { + # This contradicts the above claim that GDB didn't + # know the location of the return-value. + fail "${test}" + } else { + pass "${test}" + } + } + -re " = 90 'Z'\[\r\n\]+${gdb_prompt} $" { + # The value didn't get found. This is "expected". + if $finish_value_unknown { + pass "${test}" + } else { + # This contradicts the above claim that GDB did + # know the location of the return-value. + fail "${test}" + } + } + } + + # Finally, check that "return" and finish" have consistent + # behavior. + + # Since both "return" and "finish" use equivalent "which + # return-value convention" logic, both commands should have + # identical can/can-not find return-value messages. + + # Note that since "call" and "finish" use common code paths, a + # failure here is a strong indicator of problems with "store + # return-value" code paths. Suggest looking at "return_value" + # when investigating a fix. + + set test "return and finish use same convention; ${tests}" + if {$finish_value_unknown == $return_value_unknown} { + pass "${test}" + } else { + kfail gdb/1444 "${test}" + } +} + +# ABIs pass anything >8 or >16 bytes in memory but below that things +# randomly use register and/and structure conventions. Check all +# possible sized char scalars in that range. But only a restricted +# range of the other types. + +# NetBSD/PPC returns "unnatural" (3, 5, 6, 7) sized scalars in memory. + +# d10v is weird. 5/6 byte scalars go in memory. 2 or more char +# scalars go in memory. Everything else is in a register! + +# Test every single char struct from 1..17 in size. This is what the +# original "scalars" test was doing. + +start_scalars_test tc +test_scalar_calls +test_scalar_returns + + +# Let the fun begin. + +# Assuming that any integer struct larger than 8 bytes goes in memory, +# come up with many and varied combinations of a return struct. For +# "struct calls" test just beyond that 8 byte boundary, for "struct +# returns" test up to that boundary. + +# For floats, assumed that up to two struct elements can be stored in +# floating point registers, regardless of their size. + +# The approx size of each structure it is computed assumed that tc=1, +# ts=2, ti=4, tl=4, tll=8, tf=4, td=8, tld=16, and that all fields are +# naturally aligned. Padding being added where needed. Note that +# these numbers are just approx, the d10v has ti=2, a 64-bit has has +# tl=8. + +# Approx size: 2, 4, ... +start_scalars_test ts +test_scalar_calls +test_scalar_returns + +# Approx size: 4, 8, ... +start_scalars_test ti +test_scalar_calls +test_scalar_returns + +# Approx size: 4, 8, ... +start_scalars_test tl +test_scalar_calls +test_scalar_returns + +# Approx size: 8, 16, ... +start_scalars_test tll +test_scalar_calls +test_scalar_returns + +# Approx size: 4, 8, ... +start_scalars_test tf +test_scalar_calls +test_scalar_returns + +# Approx size: 8, 16, ... +start_scalars_test td +test_scalar_calls +test_scalar_returns + +# Approx size: 16, 32, ... +start_scalars_test tld +test_scalar_calls +test_scalar_returns + +# Approx size: 4, 8, ... +start_scalars_test te +test_scalar_calls +test_scalar_returns + +return 0 diff --git a/gdb/testsuite/gdb.base/lineinc.c b/gdb/testsuite/gdb.base/lineinc.c new file mode 100644 index 00000000000..91784e7d2b3 --- /dev/null +++ b/gdb/testsuite/gdb.base/lineinc.c @@ -0,0 +1,30 @@ +/* The following is written to tickle a specific bug in the macro + table code (now hopefully fixed), which doesn't insert new included + files in the #including file's list in the proper place. They + should be sorted by the number of the line which #included them, in + increasing order, but the sense of the comparison was reversed, so + the list ends up being built backwards. This isn't a problem by + itself, but the code to pick new, non-conflicting line numbers for + headers alleged to be #included at the same line as some other + header assumes that the list's line numbers are in ascending order. + + So, given the following input, lineinc1.h gets added to lineinc.c's + #inclusion list first, at line 10. When the debug info reader + tries to add lineinc2.h at line 10 as well, the code will notice the + duplication --- since there's only one extant element in the list, + it'll find it --- and insert it after lineinc1.h, with line 11. + Since the code is putting the list in order of descending + #inclusion line number, the list is now out of order. When we try + to #include lineinc3.h at line 11, we won't notice the duplication. */ + +#line 10 +#include "lineinc1.h" +#line 10 +#include "lineinc2.h" +#line 11 +#include "lineinc3.h" + +int +main (int argc, char **argv) +{ +} diff --git a/gdb/testsuite/gdb.base/lineinc.exp b/gdb/testsuite/gdb.base/lineinc.exp new file mode 100644 index 00000000000..4707ce516e1 --- /dev/null +++ b/gdb/testsuite/gdb.base/lineinc.exp @@ -0,0 +1,126 @@ +# Test macro handling of #included files. +# Copyright 2003 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +# Please email any bugs, comments, and/or additions to this file to: +# bug-gdb@prep.ai.mit.edu + +# The test program lineinc.c contains a mix of #line directives and +# #include directives that will cause the compiler to attribute more +# than one #inclusion to the same source line. You can get similar +# effects using things like GCC's '-imacros' flag. +# +# Compiling lineinc.c with Dwarf 2 macro information will produce +# something like this: +# +# $ gcc -g3 lineinc.c -o lineinc +# $ readelf -wml lineinc +# ... +# The File Name Table: +# Entry Dir Time Size Name +# 1 0 0 0 lineinc.c +# 2 0 0 0 lineinc1.h +# 3 0 0 0 lineinc2.h +# 4 0 0 0 lineinc3.h +# ... +# Contents of the .debug_macinfo section: +# +# DW_MACINFO_start_file - lineno: 0 filenum: 1 +# DW_MACINFO_define - lineno : 1 macro : __VERSION__ "3.2 20020903 (Red Hat Linux 8.0 3.2-7)" +# DW_MACINFO_define - lineno : 2 macro : __USER_LABEL_PREFIX__ +# ... +# DW_MACINFO_define - lineno : 1 macro : __i386__ 1 +# DW_MACINFO_define - lineno : 1 macro : __tune_i386__ 1 +# DW_MACINFO_start_file - lineno: 10 filenum: 2 +# DW_MACINFO_define - lineno : 1 macro : FOO 1 +# DW_MACINFO_end_file +# DW_MACINFO_start_file - lineno: 10 filenum: 3 +# DW_MACINFO_undef - lineno : 1 macro : FOO +# DW_MACINFO_define - lineno : 2 macro : FOO 2 +# DW_MACINFO_end_file +# DW_MACINFO_start_file - lineno: 11 filenum: 4 +# DW_MACINFO_undef - lineno : 1 macro : FOO +# DW_MACINFO_define - lineno : 2 macro : FOO 3 +# DW_MACINFO_end_file +# DW_MACINFO_end_file +# $ +# +# Note how the inclusions of lineinc1.h and lineinc2.h are both +# attributed to line 10 of lineinc.c, and the #inclusion of lineinc3.h +# is attributed to line 11. This is all correct, given the #line +# directives in lineinc.c. +# +# Dwarf 2 macro information doesn't contain enough information to +# allow GDB to figure out what's really going on here --- it makes no +# mention of the #line directives --- so we just try to cope as best +# we can. If the macro table were to attribute more than one +# #inclusion to the same source line, then GDB wouldn't be able to +# tell which #included file's #definitions and #undefinitions come +# first, so it can't tell which #definitions are in scope following +# all the #inclusions. To cope with this, GDB puts all the files +# #included by a given source file in a list sorted by the line at +# which they were #included; this gives GDB the chance to detect +# multiple #inclusions at the same line, complain, and assign +# distinct, albiet incorrect, line numbers to each #inclusion. +# +# However, at one point GDB was sorting the list in reverse order, +# while the code to assign new, distinct line numbers assumed it was +# sorted in ascending order; GDB would get an internal error trying to +# read the above debugging info. + +if $tracelevel then { + strace $tracelevel +} + +set prms_id 0 +set bug_id 0 + +set testfile "lineinc" +set binfile ${objdir}/${subdir}/${testfile} + + +if {[gdb_compile "${srcdir}/${subdir}/${testfile}.c" ${binfile} executable {debug}] != ""} { + gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail." +} + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + +# Any command that causes GDB to read the debugging info for the +# lineinc.c compilation unit will do here. +set test_name "tolerate macro info with multiple #inclusions per line" +gdb_test_multiple "break main" $test_name { + -re "Breakpoint 1 at 0x.*: file .*lineinc.c.*\\.\r\n${gdb_prompt}" { + pass $test_name + } + -re ".*internal-error:.*.y or n. " { + fail $test_name + send_gdb "y\n" + gdb_expect { + -re ".*.y or n. " { + send_gdb "n\n" + exp_continue + } + -re "$gdb_prompt" { + } + timeout { + fail "$test_name (timeout)" + } + } + } +} diff --git a/gdb/testsuite/gdb.base/lineinc1.h b/gdb/testsuite/gdb.base/lineinc1.h new file mode 100644 index 00000000000..8523d58b330 --- /dev/null +++ b/gdb/testsuite/gdb.base/lineinc1.h @@ -0,0 +1 @@ +#define FOO 1 diff --git a/gdb/testsuite/gdb.base/lineinc2.h b/gdb/testsuite/gdb.base/lineinc2.h new file mode 100644 index 00000000000..ee800ba72e8 --- /dev/null +++ b/gdb/testsuite/gdb.base/lineinc2.h @@ -0,0 +1,2 @@ +#undef FOO +#define FOO 2 diff --git a/gdb/testsuite/gdb.base/lineinc3.h b/gdb/testsuite/gdb.base/lineinc3.h new file mode 100644 index 00000000000..be3bb54506a --- /dev/null +++ b/gdb/testsuite/gdb.base/lineinc3.h @@ -0,0 +1,2 @@ +#undef FOO +#define FOO 3 diff --git a/gdb/testsuite/gdb.base/sep-proc.c b/gdb/testsuite/gdb.base/sep-proc.c new file mode 100644 index 00000000000..0fbb17a82c2 --- /dev/null +++ b/gdb/testsuite/gdb.base/sep-proc.c @@ -0,0 +1,26 @@ +/* This file is part of GDB, the GNU debugger. + + Copyright 2004 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + Please email any bugs, comments, and/or additions to this file to: + bug-gdb@prep.ai.mit.edu */ + +void +say_hello (void) +{ + printf ("Hello world.\n"); +} diff --git a/gdb/testsuite/gdb.base/sep.c b/gdb/testsuite/gdb.base/sep.c new file mode 100644 index 00000000000..4402bd84251 --- /dev/null +++ b/gdb/testsuite/gdb.base/sep.c @@ -0,0 +1,35 @@ +/* This file is part of GDB, the GNU debugger. + + Copyright 2004 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + Please email any bugs, comments, and/or additions to this file to: + bug-gdb@prep.ai.mit.edu */ + +#include + +/* Include a .c file. This is usually considered bad practice in C, + but this emulate a practice which is common in other languages. + One such language is Ada and its concept of "separates", for instance. */ +#include "sep-proc.c" + +int +main (void) +{ + say_hello (); + return 0; +} + diff --git a/gdb/testsuite/gdb.base/sep.exp b/gdb/testsuite/gdb.base/sep.exp new file mode 100644 index 00000000000..7a7c22ae1b6 --- /dev/null +++ b/gdb/testsuite/gdb.base/sep.exp @@ -0,0 +1,68 @@ +# Copyright 2004 Free Software Foundation, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# Please email any bugs, comments, and/or additions to this file to: +# bug-gdb@prep.ai.mit.edu + +if $tracelevel then { + strace $tracelevel +} + +set testfile "sep" +set srcfile ${testfile}.c +set binfile ${objdir}/${subdir}/${testfile} + +if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug additional_flags=-w}] != "" } { + gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail." +} + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + +# Try to display the source code inside a file which is included by +# another source file. The purpose of this test is to verify that +# this operation works, even before we have loaded full symbols for +# that file (by doing a "break say_hello" for instance). +# +# We just check that the command succeeds, so no need to match the +# complete exact output. Simply verifying that we get procedure +# say_hello is good enough, and avoid unnecessary failures is someone +# decides later to reformat sep-proc.c. + +gdb_test "list sep-proc.c:23" \ + "void.*say_hello.*" \ + "list using location inside included file" + +# Try the same, but this time with a breakpoint. We need to exit +# GDB to make sure that we havn't loaded the full symbols yet when +# we test the breakpoint insertion. +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + +set test "breakpoint inside included file" +gdb_test_multiple "break sep-proc.c:25" "$test" { + -re "Breakpoint.*at.* file .*sep-proc.c, line .*" { + pass "$test" + } + -re "No source file named sep-proc.c.*" { + fail "$test" + } +} + diff --git a/gdb/testsuite/gdb.base/sigaltstack.c b/gdb/testsuite/gdb.base/sigaltstack.c new file mode 100644 index 00000000000..b7abc9b5241 --- /dev/null +++ b/gdb/testsuite/gdb.base/sigaltstack.c @@ -0,0 +1,97 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2004 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + Please email any bugs, comments, and/or additions to this file to: + bug-gdb@prep.ai.mit.edu */ + +#include +#include +#include +#include +#include + +enum level { MAIN, OUTER, INNER, LEAF, NR_LEVELS }; + +/* Levels completed flag. */ +volatile enum level level = NR_LEVELS; + +void catcher (int signal); + +void +thrower (enum level next_level, int sig, int itimer, int on_stack) +{ + level = next_level; + /* Set up the signal handler. */ + { + struct sigaction act; + memset (&act, 0, sizeof (act)); + act.sa_handler = catcher; + act.sa_flags |= on_stack; + sigaction (sig, &act, NULL); + } + /* Set up a one-off timer. A timer, rather than SIGSEGV, is used as + after a timer handler finishes the interrupted code can safely + resume. */ + { + struct itimerval itime; + memset (&itime, 0, sizeof (itime)); + itime.it_value.tv_usec = 250 * 1000; + setitimer (itimer, &itime, NULL); + } + /* Wait. */ + while (level != LEAF); +} + +void +catcher (int signal) +{ + /* Find the next level. */ + switch (level) + { + case MAIN: + thrower (OUTER, SIGALRM, ITIMER_REAL, SA_ONSTACK); + break; + case OUTER: + thrower (INNER, SIGVTALRM, ITIMER_VIRTUAL, SA_ONSTACK); + break; + case INNER: + level = LEAF; + return; + } +} + + +main () +{ + /* Set up the altstack. */ + { + static char stack[SIGSTKSZ * NR_LEVELS]; + struct sigaltstack alt; + memset (&alt, 0, sizeof (alt)); + alt.ss_sp = stack; + alt.ss_size = SIGSTKSZ; + alt.ss_flags = 0; + if (sigaltstack (&alt, NULL) < 0) + { + perror ("sigaltstack"); + exit (0); + } + } + level = MAIN; + catcher (0); +} diff --git a/gdb/testsuite/gdb.base/sigaltstack.exp b/gdb/testsuite/gdb.base/sigaltstack.exp new file mode 100644 index 00000000000..d1e37d8aa98 --- /dev/null +++ b/gdb/testsuite/gdb.base/sigaltstack.exp @@ -0,0 +1,105 @@ +# Copyright 2004 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + +# The program sigaltstack.c creates a backtrace containing nested +# signal handlers on an alternative stack. This in turn leads to a +# non-contiguous (and possibly non-monotonic) backtrace - stack +# address jump at the normal-alt stack boundary. + +# This test confirms that GDB can both backtrace through and finish +# such a stack. + +if [target_info exists gdb,nosignals] { + verbose "Skipping signals.exp because of nosignals." + continue +} + +if $tracelevel then { + strace $tracelevel +} + +set prms_id 0 +set bug_id 0 + +set testfile sigaltstack +set srcfile ${testfile}.c +set binfile ${objdir}/${subdir}/${testfile} +if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } { + untested "Couldn't compile ${module}.c" + return -1 +} + +# get things started +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + +# Pass all the alarms straight through (but verbosely) +gdb_test "handle SIGALRM print pass nostop" +gdb_test "handle SIGVTALRM print pass nostop" +gdb_test "handle SIGPROF print pass nostop" + +# Advance to main +if { ![runto_main] } then { + gdb_suppress_tests; +} + +# Stop in handle, when at the inner most level +gdb_test "break catcher if level == INNER" +gdb_test "continue" ".* catcher .*" "continue to catch" +# step off the assignment +gdb_test "next" + +# Full backtrace? +send_gdb "bt\n" +gdb_expect_list "backtrace" ".*$gdb_prompt $" { + "\[\r\n\]+.0 \[^\r\n\]* catcher " + "\[\r\n\]+.1 .signal handler called." + "\[\r\n\]+.2 \[^\r\n\]* thrower .next_level=INNER" + "\[\r\n\]+.3 \[^\r\n\]* catcher " + "\[\r\n\]+.4 .signal handler called." + "\[\r\n\]+.5 \[^\r\n\]* thrower .next_level=OUTER" + "\[\r\n\]+.6 \[^\r\n\]* catcher " + "\[\r\n\]+.7 \[^\r\n\]* main .*" +} + +proc finish_test { pattern msg } { + global gdb_prompt + + gdb_test_multiple "finish" $msg { + -re "Cannot insert breakpoint 0.*${gdb_prompt} $" { + # Some platforms use a special read-only page for signal + # trampolines. We can't set a breakpoint there, and we + # don't gracefully fall back to single-stepping. + setup_kfail "i?86-*-linux*" gdb/1736 + fail "$msg (could not set breakpoint)" + } + -re "$pattern.*${gdb_prompt} $" { + pass $msg + } + } +} + +# Finish? +finish_test "signal handler called." "finish from catch LEAF" +finish_test "thrower .next_level=INNER, .*" "finish to throw INNER" +finish_test "catcher .*" "finish to catch INNER" +finish_test "signal handler called.*" "finish from catch INNER" +finish_test "thrower .next_level=OUTER, .*" "finish to OUTER" +finish_test "catcher .*" "finish to catch MAIN" +finish_test "main .*" "finish to MAIN" diff --git a/gdb/testsuite/gdb.base/sigbpt.c b/gdb/testsuite/gdb.base/sigbpt.c new file mode 100644 index 00000000000..b189f6da7da --- /dev/null +++ b/gdb/testsuite/gdb.base/sigbpt.c @@ -0,0 +1,53 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2004 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ + +#include +#include +#include + +extern void +keeper (int sig) +{ +} + +volatile long v1 = 0; +volatile long v2 = 0; +volatile long v3 = 0; + +extern long +bowler (void) +{ + /* Try to read address zero. Do it in a slightly convoluted way so + that more than one instruction is used. */ + return *(char *) (v1 + v2 + v3); +} + +int +main () +{ + static volatile int i; + + struct sigaction act; + memset (&act, 0, sizeof act); + act.sa_handler = keeper; + sigaction (SIGSEGV, &act, NULL); + + bowler (); + return 0; +} diff --git a/gdb/testsuite/gdb.base/sigbpt.exp b/gdb/testsuite/gdb.base/sigbpt.exp new file mode 100644 index 00000000000..61625b52373 --- /dev/null +++ b/gdb/testsuite/gdb.base/sigbpt.exp @@ -0,0 +1,266 @@ +# This testcase is part of GDB, the GNU debugger. + +# Copyright 2004 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +# Check that GDB can and only executes single instructions when +# stepping through a sequence of breakpoints interleaved by a signal +# handler. + +# This test is known to tickle the following problems: kernel letting +# the inferior execute both the system call, and the instruction +# following, when single-stepping a system call; kernel failing to +# propogate the single-step state when single-stepping the sigreturn +# system call, instead resuming the inferior at full speed; GDB +# doesn't know how to software single-step across a sigreturn +# instruction. Since the kernel problems can be "fixed" using +# software single-step this is KFAILed rather than XFAILed. + +if $tracelevel { + strace $tracelevel +} + +set prms_id 0 +set bug_id 0 + +set testfile "sigbpt" +set srcfile ${testfile}.c +set binfile ${objdir}/${subdir}/${testfile} +if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } { + gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail." +} + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + +# +# Run to `main' where we begin our tests. +# + +if ![runto_main] then { + gdb_suppress_tests +} + +# If we can examine what's at memory address 0, it is possible that we +# could also execute it. This could probably make us run away, +# executing random code, which could have all sorts of ill effects, +# especially on targets without an MMU. Don't run the tests in that +# case. + +send_gdb "x 0\n" +gdb_expect { + -re "0x0:.*Cannot access memory at address 0x0.*$gdb_prompt $" { } + -re "0x0:.*Error accessing memory address 0x0.*$gdb_prompt $" { } + -re ".*$gdb_prompt $" { + untested "Memory at address 0 is possibly executable" + return + } +} + +gdb_test "break keeper" + +# Run to bowler, and then single step until there's a SIGSEGV. Record +# the address of each single-step instruction (up to and including the +# instruction that causes the SIGSEGV) in bowler_addrs, and the address +# of the actual SIGSEGV in segv_addr. + +set bowler_addrs bowler +gdb_test {display/i $pc} +gdb_test "advance *bowler" "bowler.*" "advance to the bowler" +set test "stepping to SIGSEGV" +gdb_test_multiple "stepi" "$test" { + -re "Program received signal SIGSEGV.*pc *(0x\[0-9a-f\]*).*$gdb_prompt $" { + set segv_addr $expect_out(1,string) + pass "$test" + } + -re " .*pc *(0x\[0-9a-f\]*).*bowler.*$gdb_prompt $" { + set bowler_addrs [concat $expect_out(1,string) $bowler_addrs] + send_gdb "stepi\n" + exp_continue + } +} + +# Now record the address of the instruction following the faulting +# instruction in bowler_addrs. + +set test "get insn after fault" +gdb_test_multiple {x/2i $pc} "$test" { + -re "(0x\[0-9a-f\]*).*bowler.*(0x\[0-9a-f\]*).*bowler.*$gdb_prompt $" { + set bowler_addrs [concat $expect_out(2,string) $bowler_addrs] + pass "$test" + } +} + +# Procedures for returning the address of the instruction before, at +# and after, the faulting instruction. + +proc before_segv { } { + global bowler_addrs + return [lindex $bowler_addrs 2] +} + +proc at_segv { } { + global bowler_addrs + return [lindex $bowler_addrs 1] +} + +proc after_segv { } { + global bowler_addrs + return [lindex $bowler_addrs 0] +} + +# Check that the address table and SIGSEGV correspond. + +set test "Verify that SIGSEGV occurs at the last STEPI insn" +if {[string compare $segv_addr [at_segv]] == 0} { + pass "$test" +} else { + fail "$test ($segv_addr [at_segv])" +} + +# Check that the inferior is correctly single stepped all the way back +# to a faulting instruction. + +proc stepi_out { name args } { + global gdb_prompt + + # Set SIGSEGV to pass+nostop and then run the inferior all the way + # through to the signal handler. With the handler is reached, + # disable SIGSEGV, ensuring that further signals stop the + # inferior. Stops a SIGSEGV infinite loop when a broke system + # keeps re-executing the faulting instruction. + rerun_to_main + gdb_test "handle SIGSEGV nostop print pass" "" "${name}; pass SIGSEGV" + gdb_test "continue" "keeper.*" "${name}; continue to keeper" + gdb_test "handle SIGSEGV stop print nopass" "" "${name}; nopass SIGSEGV" + + # Insert all the breakpoints. To avoid the need to step over + # these instructions, this is delayed until after the keeper has + # been reached. + for {set i 0} {$i < [llength $args]} {incr i} { + gdb_test "break [lindex $args $i]" "Breakpoint.*" \ + "${name}; set breakpoint $i of [llength $args]" + } + + # Single step our way out of the keeper, through the signal + # trampoline, and back to the instruction that faulted. + set test "${name}; stepi out of handler" + gdb_test_multiple "stepi" "$test" { + -re "keeper.*$gdb_prompt $" { + send_gdb "stepi\n" + exp_continue + } + -re "signal handler.*$gdb_prompt $" { + send_gdb "stepi\n" + exp_continue + } + -re "Program received signal SIGSEGV.*$gdb_prompt $" { + kfail gdb/1702 "$test (executed fault insn)" + } + -re "Breakpoint.*pc *[at_segv] .*bowler.*$gdb_prompt $" { + pass "$test (at breakpoint)" + } + -re "Breakpoint.*pc *[after_segv] .*bowler.*$gdb_prompt $" { + kfail gdb/1702 "$test (executed breakpoint)" + } + -re "pc *[at_segv] .*bowler.*$gdb_prompt $" { + pass "$test" + } + -re "pc *[after_segv] .*bowler.*$gdb_prompt $" { + kfail gdb/1702 "$test (skipped fault insn)" + } + -re "pc *0x\[a-z0-9\]* .*bowler.*$gdb_prompt $" { + kfail gdb/1702 "$test (corrupt pc)" + } + } + + # Clear any breakpoints + for {set i 0} {$i < [llength $args]} {incr i} { + gdb_test "clear [lindex $args $i]" "Deleted .*" \ + "${name}; clear breakpoint $i of [llength $args]" + } +} + +# Let a signal handler exit, returning to a breakpoint instruction +# inserted at the original fault instruction. Check that the +# breakpoint is hit, and that single stepping off that breakpoint +# executes the underlying fault instruction causing a SIGSEGV. + +proc cont_out { name args } { + global gdb_prompt + + # Set SIGSEGV to pass+nostop and then run the inferior all the way + # through to the signal handler. With the handler is reached, + # disable SIGSEGV, ensuring that further signals stop the + # inferior. Stops a SIGSEGV infinite loop when a broke system + # keeps re-executing the faulting instruction. + rerun_to_main + gdb_test "handle SIGSEGV nostop print pass" "" "${name}; pass SIGSEGV" + gdb_test "continue" "keeper.*" "${name}; continue to keeper" + gdb_test "handle SIGSEGV stop print nopass" "" "${name}; nopass SIGSEGV" + + # Insert all the breakpoints. To avoid the need to step over + # these instructions, this is delayed until after the keeper has + # been reached. Always set a breakpoint at the signal trampoline + # instruction. + set args [concat $args "*[at_segv]"] + for {set i 0} {$i < [llength $args]} {incr i} { + gdb_test "break [lindex $args $i]" "Breakpoint.*" \ + "${name}; set breakpoint $i of [llength $args]" + } + + # Let the handler return, it should "appear to hit" the breakpoint + # inserted at the faulting instruction. Note that the breakpoint + # instruction wasn't executed, rather the inferior was SIGTRAPed + # with the PC at the breakpoint. + gdb_test "continue" "Breakpoint.*pc *[at_segv] .*" \ + "${name}; continue to breakpoint at fault" + + # Now single step the faulted instrction at that breakpoint. + gdb_test "stepi" \ + "Program received signal SIGSEGV.*pc *[at_segv] .*" \ + "${name}; stepi fault" + + # Clear any breakpoints + for {set i 0} {$i < [llength $args]} {incr i} { + gdb_test "clear [lindex $args $i]" "Deleted .*" \ + "${name}; clear breakpoint $i of [llength $args]" + } + +} + + + +# Try to confuse DECR_PC_AFTER_BREAK architectures by scattering +# breakpoints around the faulting address. In all cases the inferior +# should single-step out of the signal trampoline halting (but not +# executing) the fault instruction. + +stepi_out "stepi" +stepi_out "stepi bp before segv" "*[before_segv]" +stepi_out "stepi bp at segv" "*[at_segv]" +stepi_out "stepi bp before and at segv" "*[at_segv]" "*[before_segv]" + + +# Try to confuse DECR_PC_AFTER_BREAK architectures by scattering +# breakpoints around the faulting address. In all cases the inferior +# should exit the signal trampoline halting at the breakpoint that +# replaced the fault instruction. +cont_out "cont" +cont_out "cont bp after segv" "*[before_segv]" +cont_out "cont bp before and after segv" "*[before_segv]" "*[after_segv]" diff --git a/gdb/testsuite/gdb.base/siginfo.c b/gdb/testsuite/gdb.base/siginfo.c new file mode 100644 index 00000000000..6303f07194f --- /dev/null +++ b/gdb/testsuite/gdb.base/siginfo.c @@ -0,0 +1,69 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2004 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#include +#include +#include +#include + +static volatile int done; + +#ifdef SA_SIGINFO +static void /* HANDLER */ +handler (int sig, siginfo_t *info, void *context) +{ + done = 1; +} /* handler */ +#else +static void +handler (int sig) +{ + done = 1; +} /* handler */ +#endif + +main () +{ + /* Set up the signal handler. */ + { + struct sigaction action; + memset (&action, 0, sizeof (action)); +#ifdef SA_SIGINFO + action.sa_sigaction = handler; + action.sa_flags |= SA_SIGINFO; +#else + action.sa_handler = handler; +#endif + sigaction (SIGVTALRM, &action, NULL); + } + + /* Set up a one-off timer. A timer, rather than SIGSEGV, is used as + after a timer handler finishes the interrupted code can safely + resume. */ + { + struct itimerval itime; + memset (&itime, 0, sizeof (itime)); + itime.it_value.tv_usec = 250 * 1000; + setitimer (ITIMER_VIRTUAL, &itime, NULL); + } + /* Wait. */ + while (!done); + return 0; +} /* main */ diff --git a/gdb/testsuite/gdb.base/siginfo.exp b/gdb/testsuite/gdb.base/siginfo.exp new file mode 100644 index 00000000000..a081ab8e887 --- /dev/null +++ b/gdb/testsuite/gdb.base/siginfo.exp @@ -0,0 +1,98 @@ +# Copyright 2004 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + +# The program siginfo.c creates a backtrace containing a signal +# handler registered using sigaction's sa_sigaction / SA_SIGINFO. +# Some OS's (e.g., GNU/Linux) use different signal trampolines for +# sa_sigaction and sa_handler. + +# This test first confirms that GDB can backtrace through the +# alternative sa_sigaction signal handler, and second that GDB can +# nexti/stepi out of such a handler. + +if [target_info exists gdb,nosignals] { + verbose "Skipping signals.exp because of nosignals." + continue +} + +if $tracelevel then { + strace $tracelevel +} + +set prms_id 0 +set bug_id 0 + +set testfile siginfo +set srcfile ${testfile}.c +set binfile ${objdir}/${subdir}/${testfile} +if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } { + untested "Couldn't compile ${module}.c" + return -1 +} + +# get things started +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + +gdb_test "display/i \$pc" + +# Advance to main +if { ![runto_main] } then { + gdb_suppress_tests; +} + +# Pass all the alarms straight through (but verbosely) +# gdb_test "handle SIGALRM print pass nostop" +# gdb_test "handle SIGVTALRM print pass nostop" +# gdb_test "handle SIGPROF print pass nostop" + +# Run to the signal handler, validate the backtrace. +gdb_test "break handler" +gdb_test "continue" ".* handler .*" "continue to stepi handler" +send_gdb "bt\n" +gdb_expect_list "backtrace for nexti" ".*$gdb_prompt $" { + "\[\r\n\]+.0 \[^\r\n\]* handler " + "\[\r\n\]+.1 .signal handler called." + "\[\r\n\]+.2 \[^\r\n\]* main .*" +} + +# Check that GDB can step the inferior back to main +set test "step out of handler" +gdb_test_multiple "step" "${test}" { + -re "done = 1;.*${gdb_prompt} $" { + send_gdb "$i\n" + exp_continue + } + -re "\} .. handler .*${gdb_prompt} $" { + send_gdb "step\n" + exp_continue + } + -re "Program exited normally.*${gdb_prompt} $" { + kfail gdb/1613 "$test (program exited)" + } + -re "(while ..done|return 0).*${gdb_prompt} $" { + # After stepping out of a function /r signal-handler, GDB will + # advance the inferior until it is at the first instruction of + # a code-line. While typically things return to the middle of + # the "while..." (and hence GDB advances the inferior to the + # "return..." line) it is also possible for the return to land + # on the first instruction of "while...". Accept both cases. + pass "$test" + } +} diff --git a/gdb/testsuite/gdb.base/signull.c b/gdb/testsuite/gdb.base/signull.c new file mode 100644 index 00000000000..4139d14640e --- /dev/null +++ b/gdb/testsuite/gdb.base/signull.c @@ -0,0 +1,88 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 1996, 1999, 2003, 2004 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ + +#include +#include +#include +#include + +enum tests { + code_entry_point, code_descriptor, data_read, data_write +}; + +static volatile enum tests test; + +/* Some basic types and zero buffers. */ + +typedef long data_t; +typedef long code_t (void); +data_t *volatile data; +code_t *volatile code; +/* "desc" is intentionally initialized to a data object. This is + needed to test function descriptors on arches like ia64. */ +data_t zero[10]; +code_t *volatile desc = (code_t *) (void *) zero; + +sigjmp_buf env; + +extern void +keeper (int sig) +{ + siglongjmp (env, 0); +} + +extern long +bowler (void) +{ + switch (test) + { + case data_read: + /* Try to read address zero. */ + return (*data); + case data_write: + /* Try to write (the assignment) to address zero. */ + return (*data) = 1; + case code_entry_point: + /* For typical architectures, call a function at address + zero. */ + return (*code) (); + case code_descriptor: + /* For atypical architectures that use function descriptors, + call a function descriptor, the code field of which is zero + (which has the effect of jumping to address zero). */ + return (*desc) (); + } +} + +int +main () +{ + static volatile int i; + + struct sigaction act; + memset (&act, 0, sizeof act); + act.sa_handler = keeper; + sigaction (SIGSEGV, &act, NULL); + + for (i = 0; i < 10; i++) + { + sigsetjmp (env, 1); + bowler (); + } +} diff --git a/gdb/testsuite/gdb.base/signull.exp b/gdb/testsuite/gdb.base/signull.exp new file mode 100644 index 00000000000..59b1a5647e6 --- /dev/null +++ b/gdb/testsuite/gdb.base/signull.exp @@ -0,0 +1,122 @@ +# This testcase is part of GDB, the GNU debugger. + +# Copyright 2004 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +# Check that GDB can trigger and backtrace SIGSEGV signal stacks +# caused by both accessing (data) and executing (code) at address +# zero. + +# On function descriptor architectures, a zero descriptor, instead of +# a NULL pointer, is used. That way the NULL code test always +# contains a zero code reference. + +# For recovery, sigjmp/longjmp are used. + +# This also tests backtrace/gdb1476. + +if $tracelevel { + strace $tracelevel +} + +set prms_id 0 +set bug_id 0 + +set testfile "signull" +set srcfile ${testfile}.c +set binfile ${objdir}/${subdir}/${testfile} +if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } { + gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail." +} + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + +# +# Run to `main' where we begin our tests. +# + +if ![runto_main] then { + gdb_suppress_tests +} + +# If we can examine what's at memory address 0, it is possible that we +# could also execute it. This could probably make us run away, +# executing random code, which could have all sorts of ill effects, +# especially on targets without an MMU. Don't run the tests in that +# case. + +send_gdb "x 0\n" +gdb_expect { + -re "0x0:.*Cannot access memory at address 0x0.*$gdb_prompt $" { } + -re "0x0:.*Error accessing memory address 0x0.*$gdb_prompt $" { } + -re ".*$gdb_prompt $" { + untested "Memory at address 0 is possibly executable" + return + } +} + +# If an attempt to call a NULL pointer leaves the inferior in main, +# then function pointers are descriptors, probe this and remember the +# result. + +gdb_test "set test = code_entry_point" "" "set for function pointer probe" +set test "probe function pointer" +set function_pointer code_entry_point +gdb_test_multiple "continue" "$test" { + -re "Program received signal SIGSEGV.*bowler .*$gdb_prompt $" { + set function_pointer code_descriptor + pass "$test (function descriptor)" + } + -re "Program received signal SIGSEGV.*0.*$gdb_prompt $" { + pass "$test (function entry-point)" + } +} + +# Re-start from scratch, breakpoint the bowler so that control is +# regained after each test, and run up to that. +rerun_to_main +gdb_test "break bowler" +gdb_test "break keeper" +# By default Stop:Yes Print:Yes Pass:Yes +gdb_test "handle SIGSEGV" "SIGSEGV.*Yes.*Yes.*Yes.*Segmentation fault" + +# For the given signal type, check that: the SIGSEGV occures; a +# backtrace from the SEGV works; the sigsegv is delivered; a backtrace +# through the SEGV works. + +proc test_segv { name tag bt_from_segv bt_from_keeper } { + gdb_test continue "Breakpoint.* bowler.*" "${name}; start with the bowler" + # NB: Don't use $tag in the testname - changes across systems. + gdb_test "set test = $tag" "" "${name}; select the pointer type" + gdb_test continue "Program received signal SIGSEGV.*" \ + "${name}; take the SIGSEGV" + gdb_test backtrace $bt_from_segv "${name}; backtrace from SIGSEGV" + gdb_test continue "Breakpoint.* keeper.*" "${name}; continue to the keeper" + gdb_test backtrace $bt_from_keeper "${name}; backtrace from keeper through SIGSEGV" +} + +test_segv "data read" data_read \ + {#0 .* bowler .*#1 .* main .*} \ + {#0 .* keeper .*#1 .* handler .*#2 .* bowler .*#3 .* main .*} +test_segv "data write" data_write \ + {#0 .* bowler .*#1 .* main .*} \ + {#0 .* keeper .*#1 .* handler .*#2 .* bowler .*#3 .* main .*} +test_segv code $function_pointer \ + {#0 .* 0x0+ .*#1 .* bowler .*#2 .* main .*} \ + {#0 .* keeper .*#1 .* handler .*#2 .* 0x0+ .*#3 .* bowler .*#4 .* main .*} diff --git a/gdb/testsuite/gdb.base/sigstep.c b/gdb/testsuite/gdb.base/sigstep.c new file mode 100644 index 00000000000..0f0d8b7a4f0 --- /dev/null +++ b/gdb/testsuite/gdb.base/sigstep.c @@ -0,0 +1,68 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2004 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#include +#include +#include +#include + +static volatile int done; + +static void +handler (int sig) +{ + done = 1; +} /* handler */ + +struct itimerval itime; +struct sigaction action; + +/* The enum is so that GDB can easily see these macro values. */ +enum { + itimer_real = ITIMER_REAL, + itimer_virtual = ITIMER_VIRTUAL +} itimer = ITIMER_VIRTUAL; + +main () +{ + + /* Set up the signal handler. */ + memset (&action, 0, sizeof (action)); + action.sa_handler = handler; + sigaction (SIGVTALRM, &action, NULL); + sigaction (SIGALRM, &action, NULL); + + /* The values needed for the itimer. This needs to be at least long + enough for the setitimer() call to return. */ + memset (&itime, 0, sizeof (itime)); + itime.it_value.tv_usec = 250 * 1000; + + /* Loop for ever, constantly taking an interrupt. */ + while (1) + { + /* Set up a one-off timer. A timer, rather than SIGSEGV, is + used as after a timer handler finishes the interrupted code + can safely resume. */ + setitimer (itimer, &itime, NULL); + /* Wait. */ + while (!done); + done = 0; + } +} diff --git a/gdb/testsuite/gdb.base/sigstep.exp b/gdb/testsuite/gdb.base/sigstep.exp new file mode 100644 index 00000000000..55de44520f8 --- /dev/null +++ b/gdb/testsuite/gdb.base/sigstep.exp @@ -0,0 +1,423 @@ +# Copyright 2004 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + +# The program sigstep.c creates a very simple backtrace containing one +# signal handler and signal trampoline. A flag is set and then the +# handler returns. This is repeated at infinitum. + +# This test runs the program up to the signal handler, and then +# attempts to step/next out of the handler and back into main. + +if [target_info exists gdb,nosignals] { + verbose "Skipping sigstep.exp because of nosignals." + continue +} + +if $tracelevel then { + strace $tracelevel +} + +set prms_id 0 +set bug_id 0 + +set testfile sigstep +set srcfile ${testfile}.c +set binfile ${objdir}/${subdir}/${testfile} +if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } { + untested "Couldn't compile ${module}.c" + return -1 +} + +# get things started +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + +gdb_test "display/i \$pc" + +# Advance to main +if { ![runto_main] } then { + gdb_suppress_tests; +} + +# Pass all the alarms straight through (but verbosely) +# gdb_test "handle SIGALRM print pass nostop" +# gdb_test "handle SIGVTALRM print pass nostop" +# gdb_test "handle SIGPROF print pass nostop" + +# Run to the signal handler, validate the backtrace. +gdb_test "break handler" +gdb_test "continue" ".* handler .*" "continue to stepi handler" +send_gdb "bt\n" +gdb_expect_list "backtrace for nexti" ".*$gdb_prompt $" { + "\[\r\n\]+.0 \[^\r\n\]* handler " + "\[\r\n\]+.1 .signal handler called." + "\[\r\n\]+.2 \[^\r\n\]* main .*" +} + +proc advance { i } { + global gdb_prompt + set prefix "$i from handler" + + # Get us back into the handler + gdb_test "continue" ".* handler .*" "$prefix; continue to handler" + + set test "$prefix; leave handler" + gdb_test_multiple "$i" "${test}" { + -re "done = 1;.*${gdb_prompt} $" { + send_gdb "$i\n" + exp_continue -continue_timer + } + -re "\} .. handler .*${gdb_prompt} $" { + send_gdb "$i\n" + exp_continue -continue_timer + } + -re "Program exited normally.*${gdb_prompt} $" { + setup_kfail powerpc-*-*bsd* gdb/1639 + fail "$test (program exited)" + } + -re "(while ..done|done = 0).*${gdb_prompt} $" { + # After stepping out of a function /r signal-handler, GDB will + # advance the inferior until it is at the first instruction of + # a code-line. While typically things return to the middle of + # the "while..." (and hence GDB advances the inferior to the + # "return..." line) it is also possible for the return to land + # on the first instruction of "while...". Accept both cases. + pass "$test" + } + } +} + +proc advancei { i } { + global gdb_prompt + set prefix "$i from handleri" + set program_exited 0 + + # Get us back into the handler + gdb_test "continue" ".* handler .*" "$prefix; continue to handler" + + set test "$prefix; leave handler" + gdb_test_multiple "$i" "${test}" { + -re "Cannot insert breakpoint 0.*${gdb_prompt} $" { + # Some platforms use a special read-only page for signal + # trampolines. We can't set a breakpoint there, and we + # don't gracefully fall back to single-stepping. + setup_kfail "i?86-*-linux*" gdb/1736 + fail "$test (could not set breakpoint)" + return + } + -re "done = 1;.*${gdb_prompt} $" { + send_gdb "$i\n" + exp_continue -continue_timer + } + -re "\} .. handler .*${gdb_prompt} $" { + send_gdb "$i\n" + exp_continue -continue_timer + } + -re "signal handler called.*${gdb_prompt} $" { + pass "$test" + } + -re "main .*${gdb_prompt} $" { + fail "$test (in main)" + } + -re "Program exited normally.*${gdb_prompt} $" { + fail "$test (program exited)" + set program_exited 1 + } + -re "Make handler return now.*y or n. $" { + send_gdb "y\n" + exp_continue -continue_timer + } + } + + set test "$prefix; leave signal trampoline" + gdb_test_multiple "$i" "${test}" { + -re "while .*${gdb_prompt} $" { + pass "$test (in main)" + } + -re "signal handler called.*${gdb_prompt} $" { + send_gdb "$i\n" + exp_continue -continue_timer + } + -re "return .*${gdb_prompt} $" { + fail "$test (stepped)" + } + -re "Make .*frame return now.*y or n. $" { + send_gdb "y\n" + exp_continue -continue_timer + } + -re "Program exited normally.*${gdb_prompt} $" { + kfail gdb/1639 "$test (program exited)" + set program_exited 1 + } + -re "The program is not being run.*${gdb_prompt} $" { + if { $program_exited } { + # Previously kfailed with an exit + pass "$test (the program is not being run)" + } else { + fail "$test (the program is not being run)" + } + } + } +} + +# Check that we can step/next our way out of a signal handler. + +advance step +advancei stepi + +advance next +advancei nexti + +advancei finish +advancei return +gdb_test "set done = 1" "" "Set done as return will have skipped it" + + +# Check that we can step/next our way into / over a signal handler. + +# There are at least the following cases: breakpoint @pc VS breakpoint +# in handler VS step / next / continue. + +# Use the real-time itimer, as otherwize the process never gets enough +# time to expire the timer. + +delete_breakpoints +set infinite_loop [gdb_get_line_number {while (!done)}] +gdb_test "set itimer = itimer_real" +gdb_test "break [gdb_get_line_number {done = 0}]" + +# Try stepping when there's a signal pending, and a breakpoint at the +# handler. Should step into the signal handler. + +proc skip_to_handler { i } { + global gdb_prompt + global infinite_loop + set prefix "$i to handler" + + # Run around to the done + set test "$prefix; resync" + gdb_test_multiple "continue" "$test" { + -re "done = 0.*$gdb_prompt " { + pass "$test" + } + # other patterns can go here + } + + # Advance to the infinite loop + gdb_test "advance $infinite_loop" "" "$prefix; advance to infinite loop" + + # Make the signal pending + sleep 1 + + # Insert / remove the handler breakpoint. + gdb_test "break handler" "" "$prefix; break handler" + gdb_test "$i" " handler .*" "$prefix; performing $i" + gdb_test "clear handler" "" "$prefix; clear handler" +} + +skip_to_handler step +skip_to_handler next +skip_to_handler continue + +# Try stepping when there's a signal pending, and a breakpoint at the +# handler's entry-point. Should step into the signal handler stopping +# at the entry-point. + +# Some systems (e.x., GNU/Linux as of 2004-08-30), when delivering a +# signal, resume the process at the first instruction of the signal +# handler and not the first instruction of the signal trampoline. The +# stack is constructed such that the signal handler still appears to +# have been called by the trampoline code. This test checks that it +# is possible to stop the inferior, even at that first instruction. + +proc skip_to_handler_entry { i } { + global gdb_prompt + global infinite_loop + set prefix "$i to handler entry" + + # Run around to the done + set test "$prefix; resync" + gdb_test_multiple "continue" "$test" { + -re "done = 0.*$gdb_prompt " { + pass "$test" + } + # other patterns can go here + } + + # Advance to the infinite loop + gdb_test "advance $infinite_loop" "" "$prefix; advance to infinite loop" + + # Make the signal pending + sleep 1 + + # Insert / remove the handler breakpoint. + gdb_test "break *handler" "" "$prefix; break handler" + gdb_test "$i" " handler .*" "$prefix; performing $i" + gdb_test "clear *handler" "" "$prefix; clear handler" +} + +skip_to_handler_entry step +skip_to_handler_entry next +skip_to_handler_entry continue + +# Try stepping when there's a signal pending but no breakpoints. +# Should skip the handler advancing to the next line. + +proc skip_over_handler { i } { + global gdb_prompt + global infinite_loop + set prefix "$i over handler" + + # Run around to the done + set test "$prefix; resync" + gdb_test_multiple "continue" "$test" { + -re "done = 0.*$gdb_prompt " { + pass "$test" + } + # other patterns can go here + } + + # Advance to the infinite loop + gdb_test "advance $infinite_loop" "" "$prefix; advance to infinite loop" + + # Make the signal pending + sleep 1 + + gdb_test "$i" "done = 0.*" "$prefix; performing $i" +} + +skip_over_handler step +skip_over_handler next +skip_over_handler continue + +# Try stepping when there's a signal pending, a pre-existing +# breakpoint at the current instruction, and a breakpoint in the +# handler. Should advance to the signal handler. + +proc breakpoint_to_handler { i } { + global gdb_prompt + global infinite_loop + set prefix "$i on breakpoint, to handler" + + # Run around to the done + set test "$prefix; resync" + gdb_test_multiple "continue" "$test" { + -re "done = 0.*$gdb_prompt " { + pass "$test" + } + # other patterns can go here + } + + gdb_test "break $infinite_loop" "" "$prefix; break infinite loop" + gdb_test "break handler" "" "$prefix; break handler" + + # Continue to the infinite loop + gdb_test "continue" "while ..done.*" "$prefix; continue to infinite loop" + + # Make the signal pending + sleep 1 + + setup_kfail "i*86-*-*" gdb/1738 + gdb_test "$i" " handler .*" "$prefix; performing $i" + gdb_test "clear $infinite_loop" "" "$prefix; clear infinite loop" + gdb_test "clear handler" "" "$prefix; clear handler" +} + +breakpoint_to_handler step +breakpoint_to_handler next +breakpoint_to_handler continue + +# Try stepping when there's a signal pending, and a breakpoint at the +# handler's entry instruction and a breakpoint at the current +# instruction. Should step into the signal handler and breakpoint at +# that entry instruction. + +# Some systems (e.x., GNU/Linux as of 2004-08-30), when delivering a +# signal, resume the process at the first instruction of the signal +# handler and not the first instruction of the signal trampoline. The +# stack is constructed such that the signal handler still appears to +# have been called by the trampoline code. This test checks that it +# is possible to stop the inferior, even at that first instruction. + +proc breakpoint_to_handler_entry { i } { + global gdb_prompt + global infinite_loop + set prefix "$i on breakpoint, to handler entry" + + # Run around to the done + set test "$prefix; resync" + gdb_test_multiple "continue" "$test" { + -re "done = 0.*$gdb_prompt " { + pass "$test" + } + # other patterns can go here + } + + gdb_test "break $infinite_loop" "" "$prefix; break infinite loop" + gdb_test "break *handler" "" "$prefix; break handler" + + # Continue to the infinite loop + gdb_test "continue" "while ..done.*" "$prefix; continue to infinite loop" + + # Make the signal pending + sleep 1 + + setup_kfail "i*86-*-*" gdb/1738 + gdb_test "$i" " handler .*" "$prefix; performing $i" + gdb_test "clear $infinite_loop" "" "$prefix; clear infinite loop" + gdb_test "clear *handler" "" "$prefix; clear handler" +} + +breakpoint_to_handler_entry step +breakpoint_to_handler_entry next +breakpoint_to_handler_entry continue + +# Try stepping when there's a signal pending, and a pre-existing +# breakpoint at the current instruction, and no breakpoint in the +# handler. Should advance to the next line. + +proc breakpoint_over_handler { i } { + global gdb_prompt + global infinite_loop + set prefix "$i on breakpoint, skip handler" + + # Run around to the done + set test "$prefix; resync" + gdb_test_multiple "continue" "$test" { + -re "done = 0.*$gdb_prompt " { + pass "$test" + } + # other patterns can go here + } + + gdb_test "break $infinite_loop" "" "$prefix; break infinite loop" + + # Continue to the infinite loop + gdb_test "continue" "while ..done.*" "$prefix; continue to infinite loop" + + # Make the signal pending + sleep 1 + + gdb_test "$i" "done = 0.*" "$prefix; performing $i" + gdb_test "clear $infinite_loop" "" "$prefix; clear infinite loop" +} + +breakpoint_over_handler step +breakpoint_over_handler next +breakpoint_over_handler continue diff --git a/gdb/testsuite/gdb.base/unload.c b/gdb/testsuite/gdb.base/unload.c new file mode 100644 index 00000000000..5c5e3d3c1d8 --- /dev/null +++ b/gdb/testsuite/gdb.base/unload.c @@ -0,0 +1,58 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2004 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include +#include +#include + +int k = 0; + +#define SHLIB_NAME SHLIB_DIR "/unloadshr.sl" + +int main() +{ + void *handle; + int (*unloadshr) (int); + int y; + const char *msg; + + handle = dlopen (SHLIB_NAME, RTLD_LAZY); + msg = dlerror (); + + if (!handle) + { + fprintf (stderr, msg); + exit (1); + } + + unloadshr = (int (*)(int))dlsym (handle, "shrfunc1"); + + if (!unloadshr) + { + fprintf (stderr, dlerror ()); + exit (1); + } + + y = (*unloadshr)(3); + + printf ("y is %d\n", y); + + dlclose (handle); + + return 0; +} diff --git a/gdb/testsuite/gdb.base/unload.exp b/gdb/testsuite/gdb.base/unload.exp new file mode 100644 index 00000000000..242dcf5d08d --- /dev/null +++ b/gdb/testsuite/gdb.base/unload.exp @@ -0,0 +1,144 @@ +# Copyright 2003, 2004 +# Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +# This file was created by Jeff Johnston. (jjohnstn@redhat.com) +# The shared library compilation portion was copied from shlib-call.exp which was +# written by Elena Zannoni (ezannoni@redhat.com). + +if $tracelevel then { + strace $tracelevel +} + +# +# test running programs +# +set prms_id 0 +set bug_id 0 + +# are we on a target board? +if ![isnative] then { + return 0 +} + +set testfile "unload" +set libfile "unloadshr" +set libsrcfile ${libfile}.c +set srcfile ${testfile}.c +set binfile ${objdir}/${subdir}/${testfile} +set shlibdir ${objdir}/${subdir} + +if [get_compiler_info ${binfile}] { + return -1 +} + +set dl_lib_flag "" +switch -glob [istarget] { + "hppa*-hp-hpux*" { } + "*-*-linux*" { set dl_lib_flag "libs=-ldl" } + "*-*-solaris*" { set dl_lib_flag "libs=-ldl" } + default { } +} + +if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable [list debug "additional_flags=-DSHLIB_DIR\=\"${shlibdir}\"" $dl_lib_flag]] != "" } { + gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail." +} + +# Build the shared libraries this test case needs. +# + +if {$gcc_compiled == 0} { + if [istarget "hppa*-hp-hpux*"] then { + set additional_flags "additional_flags=+z" + } elseif { [istarget "mips-sgi-irix*"] } { + # Disable SGI compiler's implicit -Dsgi + set additional_flags "additional_flags=-Usgi" + } else { + # don't know what the compiler is... + set additional_flags "" + } +} else { + if { ([istarget "powerpc*-*-aix*"] + || [istarget "rs6000*-*-aix*"]) } { + set additional_flags "" + } else { + set additional_flags "additional_flags=-fpic" + } +} + +if {[gdb_compile "${srcdir}/${subdir}/${libsrcfile}" "${objdir}/${subdir}/${libfile}.o" object [list debug $additional_flags]] != ""} { + gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail." +} + +if [istarget "hppa*-*-hpux*"] { + remote_exec build "ld -b ${objdir}/${subdir}/${libfile}.o -o ${objdir}/${subdir}/${libfile}.sl" +} else { + set additional_flags "additional_flags=-shared" + if {[gdb_compile "${objdir}/${subdir}/${libfile}.o" "${objdir}/${subdir}/${libfile}.sl" executable [list debug $additional_flags]] != ""} { + gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail." + } +} + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + +if [target_info exists gdb_stub] { + gdb_step_for_stub; +} + +# +# Test setting a breakpoint in a dynamically loaded library which is +# manually loaded and unloaded +# + +gdb_test_multiple "break shrfunc1" "set pending breakpoint" { + -re ".*Make breakpoint pending.*y or \\\[n\\\]. $" { + gdb_test "y" "Breakpoint.*shrfunc1.*pending." "set pending breakpoint" + } +} + +gdb_test "info break" \ + "Num Type\[ \]+Disp Enb Address\[ \]+What.* +\[0-9\]+\[\t \]+breakpoint keep y.*PENDING.*shrfunc1.*" \ +"single pending breakpoint info" + +set unloadshr_line [gdb_get_line_number "unloadshr break" ${srcdir}/${subdir}/${libsrcfile}] + +gdb_test "run" \ +"Starting program.*unload.* +Breakpoint.*at.* +Pending breakpoint \"shrfunc1\" resolved.* +Breakpoint.*, shrfunc1 \\\(x=3\\\).*unloadshr.c:$unloadshr_line.*" \ +"running program" + +gdb_test "continue" \ +"Continuing.*y is 7.*warning: Temporarily disabling breakpoints for.*unloadshr.sl.*Program exited normally." \ +"continuing to end of program" + +# +# Try to rerun program and verify that shared breakpoint is reset properly +# + +gdb_test "run" \ +".*Breakpoint.*shrfunc1.*at.*unloadshr.c:$unloadshr_line.*" \ +"rerun to shared library breakpoint" + +gdb_test "continue" \ +"Continuing.*y is 7.*warning: Temporarily disabling breakpoints for.*unloadshr.sl.*Program exited normally." \ +"continuing to end of program second time" + diff --git a/gdb/testsuite/gdb.base/unloadshr.c b/gdb/testsuite/gdb.base/unloadshr.c new file mode 100644 index 00000000000..3896e67ffc1 --- /dev/null +++ b/gdb/testsuite/gdb.base/unloadshr.c @@ -0,0 +1,24 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2004 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include + +int shrfunc1 (int x) +{ + return x + 4; /* unloadshr break */ +} diff --git a/gdb/testsuite/gdb.fortran/Makefile.in b/gdb/testsuite/gdb.fortran/Makefile.in new file mode 100644 index 00000000000..a1c3b074a07 --- /dev/null +++ b/gdb/testsuite/gdb.fortran/Makefile.in @@ -0,0 +1,34 @@ +# Makefile for regression testing the GNU debugger. +# Copyright 1992, 1993, 1994, 1995, 1996, 1999, 2001, 2003, 2004 +# Free Software Foundation, Inc. + +# This file is part of GDB. + +# GDB is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# GDB is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +VPATH = @srcdir@ +srcdir = @srcdir@ + +EXECUTABLES = + +all info install-info dvi install uninstall installcheck check: + @echo "Nothing to be done for $@..." + +clean mostlyclean: + -rm -f *~ *.o *.ci + -rm -f core ${EXECUTABLES} + +distclean maintainer-clean realclean: clean + -rm -f Makefile config.status config.log diff --git a/gdb/testsuite/gdb.gdb/selftest.exp b/gdb/testsuite/gdb.gdb/selftest.exp new file mode 100644 index 00000000000..e7d46bdc331 --- /dev/null +++ b/gdb/testsuite/gdb.gdb/selftest.exp @@ -0,0 +1,523 @@ +# Copyright 1988, 1990, 1991, 1992, 1994, 1997, 1999, 2000, 2002, +# 2003, 2004 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +# This file was written by Rob Savoye. (rob@cygnus.com) + +if $tracelevel then { + strace $tracelevel +} + +set prms_id 0 +set bug_id 0 + +# are we on a target board +if [is_remote target] { + return +} + +# Not all of the lines of code near the start of main are executed for +# every machine. Also, optimization may reorder some of the lines. +# So all we do is try to step or next over everything until we get +# to a line that we know is always executed. + +proc do_steps_and_nexts {} { + global gdb_prompt + global srcdir + + gdb_reinitialize_dir $srcdir/.. + + for {set count 0} {$count < 32} {incr count} { + send_gdb "list\n" + # NOTE: carlton/2002-12-11: The "initial brace" and + # "current_directory initialization" possibilities happen to + # me with GCC 3.1 on i686-pc-linux-gnu when I compile with + # optimization. + gdb_expect { + -re ".*context = data.*$gdb_prompt $" { + set description "step over context initialization" + set command "step" + } + -re ".*argc = context->argc.*$gdb_prompt $" { + set description "step over argc initialization" + set command "step" + } + -re ".*argv = context->argv.*$gdb_prompt $" { + set description "step over argv initialization" + set command "step" + } + -re ".*quiet = 0.*$gdb_prompt $" { + set description "step over quiet initialization" + set command "step" + } + -re ".*batch = 0.*$gdb_prompt $" { + set description "step over batch initialization" + set command "step" + } + -re ".*symarg = NULL.*$gdb_prompt $" { + set description "step over symarg initialization" + set command "step" + } + -re ".*execarg = NULL.*$gdb_prompt $" { + set description "step over execarg initialization" + set command "step" + } + -re ".*corearg = NULL.*$gdb_prompt $" { + set description "step over corearg initialization" + set command "step" + } + -re ".*cdarg = NULL.*$gdb_prompt $" { + set description "step over cdarg initialization" + set command "step" + } + -re ".*ttyarg = NULL.*$gdb_prompt $" { + set description "step over ttyarg initialization" + set command "step" + } + -re ".*time_at_startup = get_run_time.*$gdb_prompt $" { + set description "next over get_run_time and everything it calls" + set command "next" + } + -re ".*START_PROGRESS.*$gdb_prompt $" { + # Note: ezannoni/2004/02/17: This check should be + # removed, since as of today that source line is not + # in gdb anymore. + set description "next over START_PROGRESS and everything it calls" + set command "next" + } + -re ".*mac_init.*$gdb_prompt $" { + set description "next over mac_init and everything it calls" + set command "next" + } + -re ".*init_malloc.*$gdb_prompt $" { + # gdb 6.2.X is the last gdb which called init_malloc + set description "next over init_malloc and everything it calls" + set command "next" + } + -re ".*lim_at_start.*$gdb_prompt $" { + set description "next over lim_at_start initialization" + set command "next" + } + -re ".*count . 0x3.*$gdb_prompt $" { + set description "next over conditional stack alignment code 1" + set command "next" + } + -re ".*if .i != 0.*$gdb_prompt $" { + set description "next over conditional stack alignment code 2" + set command "next" + } + -re ".*alloca .i - 4.*$gdb_prompt $" { + set description "next over conditional stack alignment alloca" + set command "next" + } + -re ".*cmdsize = 1.*$gdb_prompt $" { + set description "step over cmdsize initialization" + set command "next" + } + -re ".*cmdarg = .* xmalloc.*$gdb_prompt $" { + set description "next over cmdarg initialization via xmalloc" + set command "next" + } + -re ".*ncmd = 0.*$gdb_prompt $" { + set description "next over ncmd initialization" + set command "next" + } + -re ".*dirsize = 1.*$gdb_prompt $" { + set description "next over dirsize initialization" + set command "next" + } + -re ".*dirarg = .* xmalloc.*$gdb_prompt $" { + return + } + -re ".*setlocale .LC_MESSAGES,.*$gdb_prompt $" { + set description "next over setlocale LC_MESSAGES" + set command "next" + } + -re ".*setlocale .LC_CTYPE,.*$gdb_prompt $" { + set description "next over setlocale LC_CTYPE" + set command "next" + } + -re ".*bindtextdomain .PACKAGE, LOCALEDIR.;.*$gdb_prompt $" { + set description "next over bindtextdomain" + set command "next" + } + -re ".*textdomain .PACKAGE.;.*$gdb_prompt $" { + set description "next over textdomain PACKAGE" + set command "next" + } + -re "\[0-9\]*\t\{\r\n$gdb_prompt $" { + set description "step over initial brace" + set command "step" + } + -re ".*current_directory = gdb_dirbuf.*$gdb_prompt $" { + set description "step over current_directory initialization" + set command "step" + } + -re ".*gdb_sysroot = .*$gdb_prompt $" { + # NOTE: carlton/2003-01-15: More optimization reordering, + # observed on GCC 3.1. + set description "step over gdb_sysroot initialization" + set command "step" + } + -re ".*ndir = 0.*$gdb_prompt $" { + set description "step over ndir initialization" + set command "step" + } + -re ".*instream = stdin.*$gdb_prompt $" { + set description "step over instream initialization" + set command "step" + } + -re ".*getcwd .gdb_dirbuf, sizeof .gdb_dirbuf..;.*$gdb_prompt $" { + set description "next over getcwd" + set command "next" + } + -re "\[ \t\]+\{\r\n$gdb_prompt $" { + setup_xfail "mips-*-irix5*" + fail "$description ended up at odd location" + } + -re ".*main.c.*No such file or directory.*$gdb_prompt $" { + setup_xfail "rs6000-*-aix3*" + fail "must be able to list source lines" + return + } + -re ".*$gdb_prompt $" { + fail "unknown source line after $description" + return + } + default { + fail "unknown source line near main" + return + } + } + send_gdb "$command\n" + gdb_expect { + -re ".*No such file or directory.\r\n$gdb_prompt $" { + fail "$description (no source available)" + } + -re ".*A file or directory .* does not exist..\r\n$gdb_prompt $" { + fail "$description (no source available)" + } + -re ".*$gdb_prompt $" { + pass "$description" + } + timeout { + fail "$description (timeout)" + } + } + } +} + +proc test_with_self { executable } { + global gdb_prompt + global tool + global det_file + global decimal + global timeout + + # load yourself into the debugger + # This can take a relatively long time, particularly for testing where + # the executable is being accessed over a network, or where gdb does not + # support partial symbols for a particular target and has to load the + # entire symbol table. Set the timeout to 10 minutes, which should be + # adequate for most environments (it *has* timed out with 5 min on a + # SPARCstation SLC under moderate load, so this isn't unreasonable). + # After gdb is started, set the timeout to 30 seconds for the duration + # of this test, and then back to the original value. + + set oldtimeout $timeout + set timeout 600 + verbose "Timeout is now $timeout seconds" 2 + + global gdb_file_cmd_debug_info + set gdb_file_cmd_debug_info "unset" + + set result [gdb_load $executable] + set timeout $oldtimeout + verbose "Timeout is now $timeout seconds" 2 + + if { $result != 0 } then { + return -1 + } + + if { $gdb_file_cmd_debug_info != "debug" } then { + untested "No debug information, skipping testcase." + return -1 + } + + # disassemble yourself + gdb_test "x/10i main" \ + "x/10i.*main.*main.$decimal.*main.$decimal.*" \ + "Disassemble main" + + # Set a breakpoint at main + gdb_test "break captured_main" \ + "Breakpoint.*at.* file.*, line.*" \ + "breakpoint in captured_main" + + # We'll need this when we send a ^C to GDB. Need to do it before we + # run the program and gdb starts saving and restoring tty states. + # On Ultrix, we don't need it and it is really slow (because shell_escape + # doesn't use vfork). + if ![istarget "*-*-ultrix*"] then { + gdb_test "shell stty intr '^C'" "" \ + "set interrupt character in test_with_self" + } + + # FIXME: If we put this after the run to main, the first list + # command doesn't print the same line as the current line where + # gdb is stopped. + gdb_test "set listsize 1" "" "set listsize to 1" + + # run yourself + # It may take a very long time for the inferior gdb to start (lynx), + # so we bump it back up for the duration of this command. + set timeout 600 + + set description "run until breakpoint at captured_main" + send_gdb "run -nw\n" + gdb_expect { + -re "Starting program.*Breakpoint \[0-9\]+,.*captured_main .data.* at .*main.c:.*$gdb_prompt $" { + pass "$description" + } + -re "Starting program.*Breakpoint \[0-9\]+,.*captured_main .data.*$gdb_prompt $" { + xfail "$description (line numbers scrambled?)" + } + -re "vfork: No more processes.*$gdb_prompt $" { + fail "$description (out of virtual memory)" + set timeout $oldtimeout + verbose "Timeout is now $timeout seconds" 2 + return -1 + } + -re ".*$gdb_prompt $" { + fail "$description" + set timeout $oldtimeout + verbose "Timeout is now $timeout seconds" 2 + return -1 + } + timeout { + fail "$description (timeout)" + } + } + + set timeout $oldtimeout + verbose "Timeout is now $timeout seconds" 2 + + # do we have a version number ? + send_gdb "print version\n" + gdb_expect { + -re ".\[0-9\]+ = .\[0-9.\]+.*$gdb_prompt $" { + pass "printed version as string" + } + -re ".\[0-9\]+ = +0x.*\[0-9.\]+.*$gdb_prompt $" { + pass "printed version as pointer" + } + -re ".\[0-9\]+ = +.+ +0x.*\[0-9.\]+.*$gdb_prompt $" { + pass "printed version with cast" + } + -re ".*$gdb_prompt $" { fail "printed version" } + timeout { fail "(timeout) printed version" } + } + + do_steps_and_nexts + + gdb_test "print \"foo\"" ".\[0-9\]+ = \"foo\"" "print a string" + + # do_steps_and_nexts left us ready to execute an xmalloc call, + # so give that a try. + # If we don't actually enter the xmalloc call when we give a + # step command that seems like a genuine bug. It seems to happen + # on most RISC processors. + # NOTE drow/2003-06-22: However, if we step back to the preceding two + # lines, just keep stepping until we enter. + set stepped_back 0 + setup_xfail "alpha-*-*" "mips-*-*" + set description "step into xmalloc call" + send_gdb "step\n" + gdb_expect { + -re "ncmd = 0;.*$gdb_prompt $" { + set stepped_back 1 + send_gdb "step\n" + exp_continue + } + -re ".*cmdarg = .* xmalloc.*$gdb_prompt $" { + set stepped_back 1 + send_gdb "step\n" + exp_continue + } + -re "dirsize = 1;.*$gdb_prompt $" { + set stepped_back 1 + send_gdb "step\n" + exp_continue + } + -re ".*dirarg = .* xmalloc.*$gdb_prompt $" { + if { $stepped_back == 1 } { + send_gdb "step\n" + exp_continue + } else { + fail "$description" + } + } + -re "xmalloc.*size=.*at.*utils.c.*$gdb_prompt $" { + pass "$description" + } + -re ".*No such file or directory.\r\n$gdb_prompt $" { + pass "$description (no source available)" + } + -re "A file or directory .* does not exist..\r\n$gdb_prompt $" { + pass "$description (no source available)" + } + -re ".*$gdb_prompt $" { + fail "$description" + } + timeout { + fail "$description (timeout)" + } + } + + # start the "xgdb" process + send_gdb "continue\n" + gdb_expect { + -re "GNU gdb \[0-9\.\]*.* +Copyright \[0-9\]* Free Software Foundation, Inc.* +GDB is free software, covered by the GNU General Public License, and you are.* +welcome to change it and/or distribute copies of it under certain conditions.* +Type \"show copying\" to see the conditions.* +There is absolutely no warranty for GDB. Type \"show warranty\" for details.* +This GDB was configured as .*$gdb_prompt $"\ + { pass "xgdb is at prompt" } + -re "GDB is free software and you are welcome to distribute copies of it.* + under certain conditions; type \"show copying\" to see the conditions..* +There is absolutely no warranty for GDB; type \"show warranty\" for details..* +GDB.*Copyright \[0-9\]+ Free Software Foundation, Inc..*$gdb_prompt $"\ + { pass "xgdb is at prompt (obsolescent gdb)" } + -re ".*$gdb_prompt $" { fail "xgdb is at prompt" } + timeout { fail "(timeout) xgdb is at prompt" } + } + + # set xgdb prompt so we can tell which is which + send_gdb "set prompt (xgdb) \n" + gdb_expect { + -re "\[(\]xgdb\[)\].*\[(\]xgdb\[)\] $" { pass "Set xgdb prompt" } + -re ".*$gdb_prompt $" { fail "Set xgdb prompt" } + default { fail "(timeout) Set xgdb prompt" } + } + + # kill the xgdb process + set description "send ^C to child process" + send_gdb "\003" + gdb_expect { + -re "Program received signal SIGINT.*$gdb_prompt $" { + pass "$description" + } + -re ".*$gdb_prompt $" { + fail "$description" + } + timeout { + fail "$description (timeout)" + } + } + + set description "send SIGINT signal to child process" + send_gdb "signal SIGINT\n" + gdb_expect { + -re "Continuing with signal SIGINT.*$gdb_prompt $" { + pass "$description" + } + -re ".*$gdb_prompt $" { + fail "$description" + } + timeout { + fail "$description (timeout)" + } + } + + # get a stack trace + # + # This fails on some linux systems for unknown reasons. On the + # systems where it fails, sometimes it works fine when run manually. + # The testsuite failures may not be limited to just aout systems. + setup_xfail "i*86-pc-linuxaout-gnu" + set description "backtrace through signal handler" + send_gdb "backtrace\n" + gdb_expect { + -re "#0.*(read|poll).*in main \\(.*\\) at .*gdb\\.c.*$gdb_prompt $" { + pass "$description" + } + -re ".*$gdb_prompt $" { + # On the alpha, we hit the infamous problem about gdb + # being unable to get the frame pointer (mentioned in + # gdb/README). As it is intermittent, there is no way to + # XFAIL it which will give us an XPASS if the problem goes + # away. + setup_xfail "alpha*-*-osf*" + fail "$description" + } + timeout { + fail "$description (timeout)" + } + } + + + # Set the timeout back to the value it had when we were called. + set timeout $oldtimeout + verbose "Timeout is now $timeout seconds" 2 + + # Restart gdb in case next test expects it to be started already. + return 0 +} + +# Find a pathname to a file that we would execute if the shell was asked +# to run $arg using the current PATH. + +proc find_gdb { arg } { + + # If the arg directly specifies an existing executable file, then + # simply use it. + + if [file executable $arg] then { + return $arg + } + + set result [which $arg] + if [string match "/" [ string range $result 0 0 ]] then { + return $result + } + + # If everything fails, just return the unqualified pathname as default + # and hope for best. + + return $arg +} + +# Run the test with self. +# Copy the file executable file in case this OS doesn't like to edit its own +# text space. + +set GDB_FULLPATH [find_gdb $GDB] + +# Remove any old copy lying around. +remote_file host delete x$tool + +gdb_start +set file [remote_download host $GDB_FULLPATH x$tool] +set result [test_with_self $file]; +gdb_exit; +catch "remote_file host delete $file"; + +if {$result <0} then { + warning "Couldn't test self" + return -1 +} diff --git a/gdb/testsuite/gdb.java/jmain.exp b/gdb/testsuite/gdb.java/jmain.exp new file mode 100644 index 00000000000..49e7ca3b511 --- /dev/null +++ b/gdb/testsuite/gdb.java/jmain.exp @@ -0,0 +1,67 @@ +# Copyright 2000, 2004 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +# This file was based on jmisc.exp which in turn was written by +# Anthony Green. (green@redhat.com) + +if $tracelevel then { + strace $tracelevel +} + +load_lib "java.exp" + +set testfile "jmain" +set srcfile ${srcdir}/$subdir/${testfile}.java +set binfile ${objdir}/${subdir}/${testfile} +if { [compile_java_from_source ${srcfile} ${binfile} "-g"] != "" } { + untested "Couldn't compile ${srcfile}" + return -1 +} + +set prms_id 0 +set bug_id 0 + +# Start with a fresh gdb. + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir + +gdb_test "set print sevenbit-strings" ".*" + +# Check that plain old "main" works. The load should both set the +# language to java and (since --main=jmain), some how set the scope to +# jmain's main. + +# Where the breakpoint should always land + +set bpmain "Breakpoint .* file .*jmain.java, line 5\." + +gdb_load "${binfile}" +setup_kfail *-*-* java/1567 +gdb_test "break main" "${bpmain}" + +# Check that an unqualified "main" works. + + +gdb_load "${binfile}" +setup_kfail *-*-* java/1565 +gdb_test "break jmain.main" "${bpmain}" + +# Check that a fully qualified "main" works. +gdb_load "${binfile}" +setup_xfail *-*-* gcc/16439 +gdb_test "break \'${testfile}.main(java.lang.String\[\])\'" "${bpmain}" diff --git a/gdb/testsuite/gdb.java/jmain.java b/gdb/testsuite/gdb.java/jmain.java new file mode 100644 index 00000000000..ee5c8bb00ce --- /dev/null +++ b/gdb/testsuite/gdb.java/jmain.java @@ -0,0 +1,7 @@ +public class jmain +{ + public static void main (String[] args) + { + return; + } +} diff --git a/gdb/testsuite/gdb.stabs/exclfwd.exp b/gdb/testsuite/gdb.stabs/exclfwd.exp new file mode 100644 index 00000000000..05ab97c0fb0 --- /dev/null +++ b/gdb/testsuite/gdb.stabs/exclfwd.exp @@ -0,0 +1,72 @@ +# Copyright 2004 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +# Please email any bugs, comments, and/or additions to this file to: +# bug-gdb@gnu.org + +if $tracelevel { + strace $tracelevel +} + +# +# test running programs +# +set prms_id 0 +set bug_id 0 + +set testfile exclfwd +set binfile ${objdir}/${subdir}/${testfile} + +foreach file {exclfwd1 exclfwd2} { + if {[gdb_compile "${srcdir}/${subdir}/${file}.c" "${file}.o" object {debug}] != ""} { + gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail." + } +} + +if {[gdb_compile "exclfwd1.o exclfwd2.o" ${binfile} executable {debug}] != "" } { + gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail." +} + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + +if ![runto_main] then { + perror "couldn't run to breakpoint" + continue +} + +get_debug_format + +set eol "\[ \t\]*\[\n\r\]+" + +gdb_test "ptype v1" "type = struct a {$eol + int x;$eol + int y;$eol +}$eol" + +if { [test_debug_format "stabs"] } then { + setup_kfail "gdb/1602" *-*-* +} +gdb_test "ptype v2" "type = struct a {$eol + const char .c;$eol +}$eol" + +if { [test_debug_format "stabs"] } then { + setup_kfail "gdb/1603" *-*-* +} +gdb_test "ptype v3" "type = const char ." diff --git a/gdb/testsuite/gdb.stabs/exclfwd.h b/gdb/testsuite/gdb.stabs/exclfwd.h new file mode 100644 index 00000000000..3f064b12857 --- /dev/null +++ b/gdb/testsuite/gdb.stabs/exclfwd.h @@ -0,0 +1,22 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2004 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + Please email any bugs, comments, and/or additions to this file to: + bug-gdb@gnu.org */ + +typedef struct a a_t; diff --git a/gdb/testsuite/gdb.stabs/exclfwd1.c b/gdb/testsuite/gdb.stabs/exclfwd1.c new file mode 100644 index 00000000000..a7574e5098b --- /dev/null +++ b/gdb/testsuite/gdb.stabs/exclfwd1.c @@ -0,0 +1,34 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2004 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + Please email any bugs, comments, and/or additions to this file to: + bug-gdb@gnu.org */ + +#include "exclfwd.h" + +struct a +{ + int x, y; +}; + +a_t v1; + +int +main () +{ +} diff --git a/gdb/testsuite/gdb.stabs/exclfwd2.c b/gdb/testsuite/gdb.stabs/exclfwd2.c new file mode 100644 index 00000000000..f7de01544be --- /dev/null +++ b/gdb/testsuite/gdb.stabs/exclfwd2.c @@ -0,0 +1,30 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2004 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + Please email any bugs, comments, and/or additions to this file to: + bug-gdb@gnu.org */ + +#include "exclfwd.h" + +struct a +{ + const char *c; +}; + +a_t v2; +const char *v3; diff --git a/gdb/testsuite/gdb.threads/bp_in_thread.exp b/gdb/testsuite/gdb.threads/bp_in_thread.exp new file mode 100644 index 00000000000..e9dfadb9b1a --- /dev/null +++ b/gdb/testsuite/gdb.threads/bp_in_thread.exp @@ -0,0 +1,49 @@ +# Copyright (C) 2004 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +# gdb 6.1.1 on AIX had a bug where the aix-threads code called +# getthrds() incorrectly so that gdb lost track of breakpoints. +# GDB reported a SIGTRAP signal in a random thread when hitting +# a breakpoint. + +if $tracelevel then { + strace $tracelevel +} + +set testfile "pthread_cond_wait" +set srcfile ${testfile}.c +set binfile ${objdir}/${subdir}/${testfile} + +if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable [list debug "incdir=${objdir}"]] != "" } { + return -1 +} + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + +gdb_test "break noreturn" \ + "Breakpoint 1 at .*: file .*${srcfile}, line .*" \ + "breakpoint on noreturn" + +# Run the program and make sure GDB reports that we stopped after +# hitting breakpoint 1 in noreturn(). + +gdb_test "run" \ + ".*Breakpoint 1, noreturn ().*" \ + "run to noreturn" + diff --git a/gdb/testsuite/gdb.threads/manythreads.c b/gdb/testsuite/gdb.threads/manythreads.c new file mode 100644 index 00000000000..e39412cde8f --- /dev/null +++ b/gdb/testsuite/gdb.threads/manythreads.c @@ -0,0 +1,68 @@ +/* Manythreads test program. + Copyright 2004 + Free Software Foundation, Inc. + + Written by Jeff Johnston + Contributed by Red Hat + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include + +void * +thread_function (void *arg) +{ + int x = (int)arg; + + printf ("Thread <%d> executing\n", x); + + return NULL; +} + +int +main (int argc, char **argv) +{ + pthread_attr_t attr; + pthread_t threads[256]; + int i, j; + + pthread_attr_init (&attr); + pthread_attr_setstacksize (&attr, PTHREAD_STACK_MIN); + + /* Create a ton of quick-executing threads, then wait for them to + complete. */ + for (i = 0; i < 1000; ++i) + { + for (j = 0; j < 256; ++j) + { + pthread_create (&threads[j], &attr, thread_function, + (void *)(i * 1000 + j)); + } + + for (j = 0; j < 256; ++j) + { + pthread_join (threads[j], NULL); + } + } + + pthread_attr_destroy (&attr); + + return 0; +} diff --git a/gdb/testsuite/gdb.threads/manythreads.exp b/gdb/testsuite/gdb.threads/manythreads.exp new file mode 100644 index 00000000000..a2baf846aa9 --- /dev/null +++ b/gdb/testsuite/gdb.threads/manythreads.exp @@ -0,0 +1,127 @@ +# manythreads.exp -- Expect script to test stopping many threads +# Copyright (C) 2004 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +# Please email any bugs, comments, and/or additions to this file to: +# bug-gdb@prep.ai.mit.edu + +# This file was written by Jeff Johnston. (jjohnstn@redhat.com) + +if $tracelevel then { + strace $tracelevel +} + +set prms_id 0 +set bug_id 0 + +set testfile "manythreads" +set srcfile ${testfile}.c +set binfile ${objdir}/${subdir}/${testfile} + +if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable [list debug "incdir=${objdir}"]] != "" } { + return -1 +} + +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} +gdb_test "set print sevenbit-strings" "" +runto_main + +# We'll need this when we send_gdb a ^C to GDB. Need to do it before we +# run the program and gdb starts saving and restoring tty states. +# On Ultrix, we don't need it and it is really slow (because shell_escape +# doesn't use vfork). +if ![istarget "*-*-ultrix*"] then { + gdb_test "shell stty intr '^C'" "" +} + +set message "first continue" +gdb_test_multiple "continue" "first continue" { + -re "error:.*$gdb_prompt $" { + fail "$message" + } + -re "Continuing" { + pass "$message" + } +} + +# Send a Ctrl-C and verify that we can do info threads and continue +after 1000 +send_gdb "\003" +set message "stop threads 1" +gdb_test_multiple "" "stop threads 1" { + -re "\\\[New \[^\]\]*\\\]\r\n" { + exp_continue + } + -re "\\\[\[^\]\]* exited\\\]\r\n" { + exp_continue + } + -re "Thread \[^\n\]* executing\r\n" { + exp_continue + } + -re "Program received signal SIGINT.*$gdb_prompt $" { + pass "$message" + } + timeout { + fail "$message (timeout)" + } +} + +gdb_test "info threads" ".*1 Thread.*.LWP.*" + +set message "second continue" +gdb_test_multiple "continue" "second continue" { + -re "error:.*$gdb_prompt $" { + fail "$message" + } + -re "Continuing" { + pass "$message" + } +} + +# Send another Ctrl-C and verify that we can do info threads and quit +after 1000 +send_gdb "\003" +set message "stop threads 2" +gdb_test_multiple "" "stop threads 2" { + -re "\\\[New \[^\]\]*\\\]\r\n" { + exp_continue + } + -re "\\\[\[^\]\]* exited\\\]\r\n" { + exp_continue + } + -re "Thread \[^\n\]* executing\r\n" { + exp_continue + } + -re "Program received signal SIGINT.*$gdb_prompt $" { + pass "stop threads 2" + } +} + +gdb_test_multiple "quit" "GDB exits after stopping multithreaded program" { + -re "The program is running. Exit anyway\\? \\(y or n\\) $" { + send_gdb "y\n" + exp_continue + } + eof { + pass "GDB exits after stopping multithreaded program" + } + timeout { + fail "GDB exits after stopping multithreaded program (timeout)" + } +} + diff --git a/gdb/testsuite/gdb.threads/pthread_cond_wait.c b/gdb/testsuite/gdb.threads/pthread_cond_wait.c new file mode 100644 index 00000000000..ae87f8cb765 --- /dev/null +++ b/gdb/testsuite/gdb.threads/pthread_cond_wait.c @@ -0,0 +1,76 @@ +/* A small multi-threaded test case. + + Copyright 2004 + Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include + +void +cond_wait (pthread_cond_t *cond, pthread_mutex_t *mut) +{ + pthread_mutex_lock(mut); + pthread_cond_wait (cond, mut); + pthread_mutex_unlock (mut); +} + +void +noreturn (void) +{ + pthread_mutex_t mut; + pthread_cond_t cond; + + pthread_mutex_init (&mut, NULL); + pthread_cond_init (&cond, NULL); + + /* Wait for a condition that will never be signaled, so we effectively + block the thread here. */ + cond_wait (&cond, &mut); +} + +void * +forever_pthread (void *unused) +{ + noreturn (); +} + +void +break_me (void) +{ + /* Just an anchor to help putting a breakpoint. */ +} + +int +main (void) +{ + pthread_t forever; + const struct timespec ts = { 0, 10000000 }; /* 0.01 sec */ + + pthread_create (&forever, NULL, forever_pthread, NULL); + for (;;) + { + nanosleep (&ts, NULL); + break_me(); + } + + return 0; +} + diff --git a/gdb/testsuite/gdb.threads/pthread_cond_wait.exp b/gdb/testsuite/gdb.threads/pthread_cond_wait.exp new file mode 100644 index 00000000000..72ae03a0cd9 --- /dev/null +++ b/gdb/testsuite/gdb.threads/pthread_cond_wait.exp @@ -0,0 +1,73 @@ +# Copyright (C) 2004 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +# Please email any bugs, comments, and/or additions to this file to: +# bug-gdb@gnu.org + +# This file verifies that GDB is able to compute a backtrace for a thread +# being blocked on a call to pthread_cond_wait(). + +if $tracelevel then { + strace $tracelevel +} + +set testfile "pthread_cond_wait" +set srcfile ${testfile}.c +set binfile ${objdir}/${subdir}/${testfile} + +if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable [list debug "incdir=${objdir}"]] != "" } { + return -1 +} + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + +gdb_test "break break_me" \ + "Breakpoint 1 at .*: file .*${srcfile}, line .*" \ + "breakpoint on break_me" + +gdb_test "run" \ + ".*Breakpoint 1, break_me ().*" \ + "run to break_me" + +# +# Backtrace all threads, find the one running noreturn, and +# verify that we are able to get a sensible backtrace, including +# the frame for the pthread_cond_wait() call. +# +# The string below will only match if the functions named +# occur in a single thread's backtrace, in the given order. +# + +global hex +global decimal + +# +# This is a "backtrace break" ("btb"): +# +set btb "\[^\r\n\]+\[\r\n\]+\#${decimal}\[ \t\]+${hex} in " + +# One of the threads is blocked on a call to pthread_cond_wait, and +# we want to verify that we are able to get a sensible backtrace for +# that thread. Because we don't know its thread ID, we can't switch +# to it before doing the backtrace. So we get a backtrace for all +# threads, and verify that one them returns the expected backtrace. +gdb_test "thread apply all backtrace" \ + "pthread_cond_wait${btb}cond_wait${btb}noreturn${btb}forever_pthread.*" \ + "backtrace in blocked thread" + diff --git a/gdb/testsuite/gdb.threads/staticthreads.c b/gdb/testsuite/gdb.threads/staticthreads.c new file mode 100644 index 00000000000..57defefcae4 --- /dev/null +++ b/gdb/testsuite/gdb.threads/staticthreads.c @@ -0,0 +1,73 @@ +/* This test program is part of GDB, The GNU debugger. + + Copyright 2004 Free Software Foundation, Inc. + + Originally written by Jeff Johnston , + contributed by Red Hat + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include +#include +#include + +sem_t semaphore; + +void * +thread_function (void *arg) +{ + printf ("Thread executing\n"); + while (sem_wait (&semaphore) != 0) + { + if (errno != EINTR) + { + perror ("thread_function"); + return; + } + } + return NULL; +} + +int +main (int argc, char **argv) +{ + pthread_attr_t attr; + + pthread_attr_init (&attr); + pthread_attr_setstacksize (&attr, PTHREAD_STACK_MIN); + + if (sem_init (&semaphore, 0, 0) == -1) + { + perror ("semaphore"); + return -1; + } + + + /* Create a thread, wait for it to complete. */ + { + pthread_t thread; + pthread_create (&thread, &attr, thread_function, NULL); + sem_post (&semaphore); + pthread_join (thread, NULL); + } + + pthread_attr_destroy (&attr); + return 0; +} diff --git a/gdb/testsuite/gdb.threads/staticthreads.exp b/gdb/testsuite/gdb.threads/staticthreads.exp new file mode 100644 index 00000000000..bf04fa3bcee --- /dev/null +++ b/gdb/testsuite/gdb.threads/staticthreads.exp @@ -0,0 +1,95 @@ +# static.exp -- test script, for GDB, the GNU debugger. + +# Copyright 2004 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +# Based on manythreads written by Jeff Johnston, contributed by Red +# Hat. + +if $tracelevel then { + strace $tracelevel +} + +set prms_id 0 +set bug_id 0 + +set testfile "staticthreads" +set srcfile ${testfile}.c +set binfile ${objdir}/${subdir}/${testfile} +set static_flag "-static" + +if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" \ + executable \ + [list debug "incdir=${objdir}" "additional_flags=${static_flag}" \ + ]] != "" } { + return -1 +} + +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} +gdb_test "set print sevenbit-strings" "" + + +# See if the static multi-threaded program runs. + +runto_main +gdb_test "break sem_post" +set test "Continue to main's call of sem_post" +gdb_test_multiple "continue" "$test" { + -re " sem_post .*$gdb_prompt " { + pass "$test" + } + -re "Program received signal .*$gdb_prompt " { + kfail gdb/1328 "$test" + } +} + + +# See if handle SIG32 helps (a little) with a static multi-threaded +# program. + +rerun_to_main +gdb_test "handle SIG32 nostop noprint pass" +set test "Handle SIG32 helps" +gdb_test "continue" " sem_post .*" "handle SIG32 helps" + + +# See if info threads produces anything approaching a thread list. + +set test "info threads" +gdb_test_multiple "info threads" "$test" { + -re " Thread .*$gdb_prompt " { + pass "$test" + } + -re "$gdb_prompt " { + kfail gdb/1328 "$test" + } +} + + +# Check that the program can be quit. + +set test "GDB exits with static thread program" +gdb_test_multiple "quit" "$test" { + -re "The program is running. Exit anyway\\? \\(y or n\\) $" { + send_gdb "y\n" + exp_continue + } + eof { + pass "$test" + } +} diff --git a/gdb/testsuite/gdb.threads/thread_check.c b/gdb/testsuite/gdb.threads/thread_check.c new file mode 100644 index 00000000000..58cb79e01fa --- /dev/null +++ b/gdb/testsuite/gdb.threads/thread_check.c @@ -0,0 +1,75 @@ +/* +* Copyright (C) 2004 Free Software Foundation, Inc. + +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +* This file was written by Steve Munroe. (sjmunroe@us.ibm.com) +* Test break points and single step on thread functions. +*/ + +#include +#include +#include +#include +#include +#include + +#define N 2 + +static void * +tf (void *arg) +{ + int n = (int) (long int) arg; + char number[160]; + int unslept = 10; + + sprintf(number, "tf(%ld): begin", (long)arg); + puts (number); + + while (unslept > 0) + unslept = sleep(unslept); + + sprintf(number, "tf(%ld): end", (long)arg); + puts (number); + return NULL; +} + +int main (int argc, char *argv[]) +{ + int n; + int unslept = 2; + pthread_t th[N]; + + for (n = 0; n < N; ++n) + if (pthread_create (&th[n], NULL, tf, (void *) (long int) n) != 0) + { + while (unslept > 0) + unslept = sleep(2); + puts ("create failed"); + exit (1); + } + + puts("after create"); + + for (n = 0; n < N; ++n) + if (pthread_join (th[n], NULL) != 0) + { + puts ("join failed"); + exit (1); + } + + puts("after join"); + return 0; +} diff --git a/gdb/testsuite/gdb.threads/thread_check.exp b/gdb/testsuite/gdb.threads/thread_check.exp new file mode 100644 index 00000000000..95b89d03968 --- /dev/null +++ b/gdb/testsuite/gdb.threads/thread_check.exp @@ -0,0 +1,96 @@ +# Copyright (C) 2004 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +# Please email any bugs, comments, and/or additions to this file to: +# bug-gdb@prep.ai.mit.edu + +# This file was written by Manoj Iyer. (manjo@austin.ibm.com) +# Test break points and single step on thread functions. +# +# Test Purpose: +# - Test that breakpoints, continue in a threaded application works. +# On powerpc64-unknown-linux-gnu system, running kernel version +# 2.6.5-7.71-pseries64 this test is known to fail due to kernel bug +# in ptrace system call. +# +# Test Strategy: +# - tbug.c creates 2 threads +# - start gdb +# - create 2 breakpoints #1 main() #2 tf() (the thread function) +# - run gdb till #1 main() breakpoint is reached +# - continue to breakpoint #2 tf() +# - delete all breakpoints +# - exit gdb. + +if $tracelevel then { + strace $tracelevel +} + +set prms_id 0 +set bug_id 0 + +set testfile "thread_check" +set srcfile ${testfile}.c +set binfile ${objdir}/${subdir}/${testfile} + +if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable [list debug "incdir=${objdir}"]] != "" } { + return -1 +} + + +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + +if ![runto_main] then { + fail "Can't run to main" + return 1; +} + + +# +# set breakpoint at thread fucntion tf +# +gdb_test "break tf" \ + "Breakpoint.*at.* file .*$srcfile, line.*" \ + "breakpoint at tf" + + +# +# +# continue to tf() breakpoint #2 +# +gdb_test "continue" \ + ".*Breakpoint 2.*tf.* at .*tbug.* .*\r\n.*$gdb_prompt $" \ + "continue to tf" + +# +# backtrace from thread function. +# +gdb_test "backtrace" \ + "#0 .*tf .*at .*tbug.*" \ + "backtrace from thread function" + + +# +# delete all breakpoints +# +delete_breakpoints + +# +# exit gdb +# +gdb_exit diff --git a/gdb/testsuite/gdb.threads/watchthreads.exp b/gdb/testsuite/gdb.threads/watchthreads.exp new file mode 100644 index 00000000000..d6e89d93824 --- /dev/null +++ b/gdb/testsuite/gdb.threads/watchthreads.exp @@ -0,0 +1,125 @@ +# This testcase is part of GDB, the GNU debugger. + +# Copyright 2004 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +# Check that GDB can support multiple watchpoints across threads. + +if $tracelevel { + strace $tracelevel +} + +set prms_id 0 +set bug_id 0 + +# This test verifies that a watchpoint is detected in the proper thread +# so the test is only meaningful on a system with hardware watchpoints. +if [target_info exists gdb,no_hardware_watchpoints] { + return 0; +} + +set testfile "schedlock" +set srcfile ${testfile}.c +set binfile ${objdir}/${subdir}/${testfile} +if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable [list debug "incdir=${objdir}"]] != "" } { + return -1 +} + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + +gdb_test "set can-use-hw-watchpoints 1" "" "" + +# +# Run to `main' where we begin our tests. +# + +if ![runto_main] then { + gdb_suppress_tests +} + +set args_0 0 +set args_1 0 + +# Watch values that will be modified by distinct threads. +gdb_test "watch args\[0\]" "Hardware watchpoint 2: args\\\[0\\\]" +gdb_test "watch args\[1\]" "Hardware watchpoint 3: args\\\[1\\\]" + +# Loop and continue to allow both watchpoints to be triggered. +for {set i 0} {$i < 30} {incr i} { + set test_flag 0 + gdb_test_multiple "continue" "threaded watch loop" { + -re "Hardware watchpoint 2: args\\\[0\\\].*Old value = 0.*New value = 1.*main \\\(\\\) at .*schedlock.c:21.*$gdb_prompt $" + { set args_0 1; set test_flag 1 } + -re "Hardware watchpoint 3: args\\\[1\\\].*Old value = 0.*New value = 1.*main \\\(\\\) at .*schedlock.c:21.*$gdb_prompt $" + { set args_1 1; set test_flag 1 } + -re "Hardware watchpoint 2: args\\\[0\\\].*Old value = $args_0.*New value = [expr $args_0+1].*in thread_function \\\(arg=0x0\\\) at .*schedlock.c:42.*$gdb_prompt $" + { set args_0 [expr $args_0+1]; set test_flag 1 } + -re "Hardware watchpoint 3: args\\\[1\\\].*Old value = $args_1.*New value = [expr $args_1+1].*in thread_function \\\(arg=0x1\\\) at .*schedlock.c:42.*$gdb_prompt $" + { set args_1 [expr $args_1+1]; set test_flag 1 } + } + # If we fail above, don't bother continuing loop + if { $test_flag == 0 } { + set i 30; + } +} + +# Print success message if loop succeeded. +if { $test_flag == 1 } { + pass "threaded watch loop" +} + +# Verify that we hit first watchpoint in main thread. +set message "first watchpoint on args\[0\] hit" +if { $args_0 > 0 } { + pass $message +} else { + fail $message +} + +# Verify that we hit second watchpoint in main thread. +set message "first watchpoint on args\[1\] hit" +if { $args_1 > 0 } { + pass $message +} else { + fail $message +} + +# Verify that we hit first watchpoint in child thread. +set message "watchpoint on args\[0\] hit in thread" +if { $args_0 > 1 } { + pass $message +} else { + fail $message +} + +# Verify that we hit second watchpoint in child thread. +set message "watchpoint on args\[1\] hit in thread" +if { $args_1 > 1 } { + pass $message +} else { + fail $message +} + +# Verify that all watchpoint hits are accounted for. +set message "combination of threaded watchpoints = 30" +if { [expr $args_0+$args_1] == 30 } { + pass $message +} else { + fail $message +} diff --git a/gdb/testsuite/lib/cp-support.exp b/gdb/testsuite/lib/cp-support.exp new file mode 100644 index 00000000000..7ce1e4806a7 --- /dev/null +++ b/gdb/testsuite/lib/cp-support.exp @@ -0,0 +1,469 @@ +# This test code is part of GDB, the GNU debugger. + +# Copyright 2003, 2004 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +# Auxiliary function to check for known problems. +# +# EXPECTED_STRING is the string expected by the test. +# +# ACTUAL_STRING is the actual string output by gdb. +# +# ERRATA_TABLE is a list of lines of the form: +# +# { expected-string broken-string {eval-block} } +# +# If there is a line for the given EXPECTED_STRING, and if the +# ACTUAL_STRING output by gdb is the same as the BROKEN_STRING in the +# table, then I eval the eval-block. + +proc cp_check_errata { expected_string actual_string errata_table } { + foreach erratum $errata_table { + if { "$expected_string" == [lindex $erratum 0] + && "$actual_string" == [lindex $erratum 1] } then { + eval [lindex $erratum 2] + } + } +} + +# Test ptype of a class. +# +# Different C++ compilers produce different output. To accommodate all +# the variations listed below, I read the output of "ptype" and process +# each line, matching it to the class description given in the +# parameters. +# +# IN_COMMAND and IN_TESTNAME are the command and testname for +# gdb_test_multiple. If IN_TESTNAME is the empty string, then it +# defaults to IN_COMMAND. +# +# IN_KEY is "class" or "struct". For now, I ignore it, and allow either +# "class" or "struct" in the output, as long as the access specifiers all +# work out okay. +# +# IN_TAG is the class tag or structure tag. +# +# IN_CLASS_TABLE is a list of class information. Each entry contains a +# keyword and some values. The keywords and their values are: +# +# { base "base-declaration" } +# +# the class has a base with the given declaration. +# +# { vbase "name" } +# +# the class has a virtual base pointer with the given name. this +# is for gcc 2.95.3, which emits ptype entries for the virtual base +# pointers. the vbase list includes both indirect and direct +# virtual base classes (indeed, a virtual base is usually +# indirect), so this information cannot be derived from the base +# declarations. +# +# { field "access" "declaration" } +# +# the class has a data field with the given access type and the +# given declaration. +# +# { method "access" "declaration" } +# +# the class has a member function with the given access type +# and the given declaration. +# +# If you test the same class declaration more than once, you can specify +# IN_CLASS_TABLE as "ibid". "ibid" means: look for a previous class +# table that had the same IN_KEY and IN_TAG, and re-use that table. +# +# IN_TAIL is the expected text after the close brace, specifically the "*" +# in "struct { ... } *". This is an optional parameter. The default +# value is "", for no tail. +# +# IN_ERRATA_TABLE is a list of errata entries. See cp_check_errata for the +# format of the errata table. Note: the errata entries are not subject to +# demangler syntax adjustment, so you have to make a bigger table +# with lines for each output variation. +# +# gdb can vary the output of ptype in several ways: +# +# . CLASS/STRUCT +# +# The output can start with either "class" or "struct", depending on +# what the symbol table reader in gdb decides. This is usually +# unrelated to the original source code. +# +# dwarf-2 debug info distinguishes class/struct, but gdb ignores it +# stabs+ debug info does not distinguish class/struct +# hp debug info distinguishes class/struct, and gdb honors it +# +# I tried to accommodate this with regular expressions such as +# "((class|struct) A \{ public:|struct A \{)", but that turns into a +# hairy mess because of optional private virtual base pointers and +# optional public synthetic operators. This is the big reason I gave +# up on regular expressions and started parsing the output. +# +# . REDUNDANT ACCESS SPECIFIER +# +# In "class { private: ... }" or "struct { public: ... }", gdb might +# or might not emit a redundant initial access specifier, depending +# on the gcc version. +# +# . VIRTUAL BASE POINTERS +# +# If a class has virtual bases, either direct or indirect, the class +# will have virtual base pointers. With gcc 2.95.3, gdb prints lines +# for these virtual base pointers. This does not happen with gcc +# 3.3.4, gcc 3.4.1, or hp acc A.03.45. +# +# I accept these lines. These lines are optional; but if I see one of +# these lines, then I expect to see all of them. +# +# Note: drow considers printing these lines to be a bug in gdb. +# +# . SYNTHETIC METHODS +# +# A C++ compiler may synthesize some methods: an assignment +# operator, a copy constructor, a constructor, and a destructor. The +# compiler might include debug information for these methods. +# +# dwarf-2 gdb does not show these methods +# stabs+ gdb shows these methods +# hp gdb does not show these methods +# +# I accept these methods. These lines are optional, and any or +# all of them might appear, mixed in anywhere in the regular methods. +# +# With gcc v2, the synthetic copy-ctor and ctor have an additional +# "int" parameter at the beginning, the "in-charge" flag. +# +# . DEMANGLER SYNTAX VARIATIONS +# +# Different demanglers produce "int foo(void)" versus "int foo()", +# "const A&" versus "const A &", and so on. +# +# TESTED WITH +# +# gcc 2.95.3 -gdwarf-2 +# gcc 2.95.3 -gstabs+ +# gcc 3.3.4 -gdwarf-2 +# gcc 3.3.4 -gstabs+ +# gcc 3.4.1 -gdwarf-2 +# gcc 3.4.1 -gstabs+ +# gcc HEAD 20040731 -gdwarf-2 +# gcc HEAD 20040731 -gstabs+ +# +# TODO +# +# Tagless structs. +# +# "A*" versus "A *" and "A&" versus "A &" in user methods. +# +# Test with hp ACC. +# +# -- chastain 2004-08-07 + +proc cp_test_ptype_class { in_command in_testname in_key in_tag in_class_table { in_tail "" } { in_errata_table { } } } { + global gdb_prompt + set wsopt "\[\r\n\t \]*" + + # The test name defaults to the command. + + if { "$in_testname" == "" } then { set in_testname "$in_command" } + + # Save class tables in a history array for reuse. + + global cp_class_table_history + if { $in_class_table == "ibid" } then { + if { ! [info exists cp_class_table_history("$in_key,$in_tag") ] } then { + fail "$in_testname // bad ibid" + return + } + set in_class_table $cp_class_table_history("$in_key,$in_tag") + } else { + set cp_class_table_history("$in_key,$in_tag") $in_class_table + } + + # Split the class table into separate tables. + + set list_bases { } + set list_vbases { } + set list_fields { } + set list_methods { } + + foreach class_line $in_class_table { + switch [lindex $class_line 0] { + "base" { lappend list_bases [lindex $class_line 1] } + "vbase" { lappend list_vbases [lindex $class_line 1] } + "field" { lappend list_fields [lrange $class_line 1 2] } + "method" { lappend list_methods [lrange $class_line 1 2] } + default { fail "$in_testname // bad line in class table: $class_line"; return; } + } + } + + # Construct a list of synthetic operators. + # These are: { count ccess-type regular-expression }. + + set list_synth { } + lappend list_synth [list 0 "public" "$in_tag & operator=\\($in_tag const ?&\\);"] + lappend list_synth [list 0 "public" "$in_tag\\((int,|) ?$in_tag const ?&\\);"] + lappend list_synth [list 0 "public" "$in_tag\\((int|void|)\\);"] + + # Actually do the ptype. + + set parse_okay 0 + gdb_test_multiple "$in_command" "$in_testname // parse failed" { + -re "type = (struct|class)${wsopt}(\[A-Za-z0-9_\]*)${wsopt}((:\[^\{\]*)?)${wsopt}\{(.*)\}${wsopt}(\[^\r\n\]*)\[\r\n\]+$gdb_prompt $" { + set parse_okay 1 + set actual_key $expect_out(1,string) + set actual_tag $expect_out(2,string) + set actual_base_string $expect_out(3,string) + set actual_body $expect_out(5,string) + set actual_tail $expect_out(6,string) + } + } + if { ! $parse_okay } then { return } + + # Check the actual key. It would be nice to require that it match + # the input key, but gdb does not support that. For now, accept any + # $actual_key as long as the access property of each field/method + # matches. + + switch "$actual_key" { + "class" { set access "private" } + "struct" { set access "public" } + default { + cp_check_errata "class" "$actual_key" $in_errata_table + cp_check_errata "struct" "$actual_key" $in_errata_table + fail "$in_testname // wrong key: $actual_key" + return + } + } + + # Check the actual tag. + + if { "$actual_tag" != "$in_tag" } then { + cp_check_errata "$in_tag" "$actual_tag" $in_errata_table + fail "$in_testname // wrong tag: $actual_tag" + return + } + + # Check the actual bases. + # First parse them into a list. + + set list_actual_bases { } + if { "$actual_base_string" != "" } then { + regsub "^:${wsopt}" $actual_base_string "" actual_base_string + set list_actual_bases [split $actual_base_string ","] + } + + # Check the base count. + + if { [llength $list_actual_bases] < [llength $list_bases] } then { + fail "$in_testname // too few bases" + return + } + if { [llength $list_actual_bases] > [llength $list_bases] } then { + fail "$in_testname // too many bases" + return + } + + # Check each base. + + foreach actual_base $list_actual_bases { + set actual_base [string trim $actual_base] + set base [lindex $list_bases 0] + if { "$actual_base" != "$base" } then { + cp_check_errata "$base" "$actual_base" $in_errata_table + fail "$in_testname // wrong base: $actual_base" + return + } + set list_bases [lreplace $list_bases 0 0] + } + + # Parse each line in the body. + + set last_was_access 0 + set vbase_match 0 + + foreach actual_line [split $actual_body "\r\n"] { + + # Chomp the line. + + set actual_line [string trim $actual_line] + if { "$actual_line" == "" } then { continue } + + # Access specifiers. + + if { [regexp "^(public|protected|private)${wsopt}:\$" "$actual_line" s0 s1] } then { + set access "$s1" + if { $last_was_access } then { + fail "$in_testname // redundant access specifier" + return + } + set last_was_access 1 + continue + } else { + set last_was_access 0 + } + + # Optional virtual base pointer. + + if { [ llength $list_vbases ] > 0 } then { + set vbase [lindex $list_vbases 0] + if { [ regexp "$vbase \\*(_vb.|_vb\\\$|__vb_)\[0-9\]*$vbase;" $actual_line ] } then { + if { "$access" != "private" } then { + cp_check_errata "private" "$access" $in_errata_table + fail "$in_testname // wrong access specifier for virtual base: $access" + return + } + set list_vbases [lreplace $list_vbases 0 0] + set vbase_match 1 + continue + } + } + + # Data field. + + if { [llength $list_fields] > 0 } then { + set field_access [lindex [lindex $list_fields 0] 0] + set field_decl [lindex [lindex $list_fields 0] 1] + if { "$actual_line" == "$field_decl" } then { + if { "$access" != "$field_access" } then { + cp_check_errata "$field_access" "$access" $in_errata_table + fail "$in_testname // wrong access specifier for field: $access" + return + } + set list_fields [lreplace $list_fields 0 0] + continue + } + + # Data fields must appear before synths and methods. + cp_check_errata "$field_decl" "$actual_line" $in_errata_table + fail "$in_testname // unrecognized line type 1: $actual_line" + return + } + + # Method function. + + if { [llength $list_methods] > 0 } then { + set method_access [lindex [lindex $list_methods 0] 0] + set method_decl [lindex [lindex $list_methods 0] 1] + if { "$actual_line" == "$method_decl" } then { + if { "$access" != "$method_access" } then { + cp_check_errata "$method_access" "$access" $in_errata_table + fail "$in_testname // wrong access specifier for method: $access" + return + } + set list_methods [lreplace $list_methods 0 0] + continue + } + + # gcc 2.95.3 shows "foo()" as "foo(void)". + regsub -all "\\(\\)" $method_decl "(void)" method_decl + if { "$actual_line" == "$method_decl" } then { + if { "$access" != "$method_access" } then { + cp_check_errata "$method_access" "$access" $in_errata_table + fail "$in_testname // wrong access specifier for method: $access" + return + } + set list_methods [lreplace $list_methods 0 0] + continue + } + } + + # Synthetic operators. These are optional and can be mixed in + # with the methods in any order, but duplicates are wrong. + # + # This test must come after the user methods, so that a user + # method which matches a synth-method pattern is treated + # properly as a user method. + + set synth_match 0 + for { set isynth 0 } { $isynth < [llength $list_synth] } { incr isynth } { + set synth [lindex $list_synth $isynth] + set synth_count [lindex $synth 0] + set synth_access [lindex $synth 1] + set synth_re [lindex $synth 2] + + if { [ regexp "$synth_re" "$actual_line" ] } then { + + if { "$access" != "$synth_access" } then { + cp_check_errata "$synth_access" "$access" $in_errata_table + fail "$in_testname // wrong access specifier for synthetic operator: $access" + return + } + + if { $synth_count > 0 } then { + cp_check_errata "$actual_line" "$actual_line" $in_errata_table + fail "$in_testname // duplicate synthetic operator: $actual_line" + } + + # Update the count in list_synth. + + incr synth_count + set synth [list $synth_count $synth_access "$synth_re"] + set list_synth [lreplace $list_synth $isynth $isynth $synth] + + # Match found. + + set synth_match 1 + break + } + } + if { $synth_match } then { continue } + + # Unrecognized line. + + if { [llength $list_methods] > 0 } then { + set method_decl [lindex [lindex $list_methods 0] 1] + cp_check_errata "$method_decl" "$actual_line" $in_errata_table + } + + fail "$in_testname // unrecognized line type 2: $actual_line" + return + } + + # Check for missing elements. + + if { $vbase_match } then { + if { [llength $list_vbases] > 0 } then { + fail "$in_testname // missing virtual base pointers" + return + } + } + + if { [llength $list_fields] > 0 } then { + fail "$in_testname // missing fields" + return + } + + if { [llength $list_methods] > 0 } then { + fail "$in_testname // missing methods" + return + } + + # Check the tail. + + set actual_tail [string trim $actual_tail] + if { "$actual_tail" != "$in_tail" } then { + cp_check_errata "$in_tail" "$actual_tail" $in_errata_table + fail "$in_testname // wrong tail: $actual_tail" + return + } + + # It all worked! + + pass "$in_testname" + return +} diff --git a/gdb/vax-nat.c b/gdb/vax-nat.c new file mode 100644 index 00000000000..9dc0c51fa05 --- /dev/null +++ b/gdb/vax-nat.c @@ -0,0 +1,106 @@ +/* Native-dependent code for VAX UNIXen (including older BSD's). + + Copyright 2004 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include "defs.h" +#include "inferior.h" + +#include "gdb_assert.h" +#include +#include +#include + +#ifdef HAVE_SYS_PTRACE_H +#include +#endif + +#ifndef PT_READ_U +#define PT_READ_U 3 +#endif + +#ifdef SYS_REG_H +/* UNIX 32V and derivatives (including 3BSD). */ +#include +#else +/* 4.2BSD and derivatives. */ +#include +#endif + +#include "vax-tdep.h" + +/* Address of the user structure. This is the the value for 32V; 3BSD + uses a different value, but hey, who's still using those systems? */ +CORE_ADDR vax_kernel_u_addr = 0x80020000; + +/* Location of the user's stored registers; usage is `u.u_ar0[XX]'. + For 4.2BSD and ULTRIX these are negative! See . */ +static int vax_register_index[] = +{ + R0, R1, R2, R3, R4, R5, + R6, R7, R8, R9, R10, R11, + AP, FP, SP, PC, PS +}; + +CORE_ADDR +vax_register_u_addr (CORE_ADDR u_ar0, int regnum) +{ + gdb_assert (regnum >= 0 && regnum < ARRAY_SIZE (vax_register_index)); + + /* Type is `int *u_ar0'. See . */ + return u_ar0 + vax_register_index[regnum - VAX_R0_REGNUM] * 4; +} + + +CORE_ADDR +vax_register_u_offset (int regnum) +{ + size_t u_ar0_offset = offsetof (struct user, u_ar0); + CORE_ADDR u_ar0; + int pid; + + errno = 0; + pid = PIDGET (inferior_ptid); + u_ar0 = ptrace (PT_READ_U, pid, u_ar0_offset, 0); + if (errno) + perror_with_name ("Unable to determine location of registers"); + + return vax_register_u_addr (u_ar0, regnum) - vax_kernel_u_addr; +} + + +#include + +#ifndef _PATH_UNIX +#define _PATH_UNIX "/vmunix" +#endif + +/* Provide a prototype to silence -Wmissing-prototypes. */ +void _initialize_vax_nat (void); + +void +_initialize_vax_nat (void) +{ + struct nlist names[2]; + + names[0].n_name = "_u"; + names[1].n_name = NULL; + if (nlist (_PATH_UNIX, names) == 0) + vax_kernel_u_addr = names[0].n_value; +} diff --git a/gdb/vaxbsd-nat.c b/gdb/vaxbsd-nat.c new file mode 100644 index 00000000000..b00e93db3b5 --- /dev/null +++ b/gdb/vaxbsd-nat.c @@ -0,0 +1,138 @@ +/* Native-dependent code for modern VAX BSD's. + + Copyright 2004 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include "defs.h" +#include "inferior.h" +#include "regcache.h" + +#include +#include +#include + +#include "vax-tdep.h" + +/* Supply the general-purpose registers stored in GREGS to REGCACHE. */ + +static void +vaxbsd_supply_gregset (struct regcache *regcache, const void *gregs) +{ + const char *regs = gregs; + int regnum; + + for (regnum = 0; regnum < VAX_NUM_REGS; regnum++) + regcache_raw_supply (regcache, regnum, regs + regnum * 4); +} + +/* Collect the general-purpose registers from REGCACHE and store them + in GREGS. */ + +static void +vaxbsd_collect_gregset (const struct regcache *regcache, + void *gregs, int regnum) +{ + char *regs = gregs; + int i; + + for (i = 0; i <= VAX_NUM_REGS; i++) + { + if (regnum == -1 || regnum == i) + regcache_raw_collect (regcache, i, regs + i * 4); + } +} + + +/* Fetch register REGNUM from the inferior. If REGNUM is -1, do this + for all registers. */ + +void +fetch_inferior_registers (int regnum) +{ + struct reg regs; + + if (ptrace (PT_GETREGS, PIDGET (inferior_ptid), + (PTRACE_TYPE_ARG3) ®s, 0) == -1) + perror_with_name ("Couldn't get registers"); + + vaxbsd_supply_gregset (current_regcache, ®s); +} + +/* Store register REGNUM back into the inferior. If REGNUM is -1, do + this for all registers. */ + +void +store_inferior_registers (int regnum) +{ + struct reg regs; + + if (ptrace (PT_GETREGS, PIDGET (inferior_ptid), + (PTRACE_TYPE_ARG3) ®s, 0) == -1) + perror_with_name ("Couldn't get registers"); + + vaxbsd_collect_gregset (current_regcache, ®s, regnum); + + if (ptrace (PT_SETREGS, PIDGET (inferior_ptid), + (PTRACE_TYPE_ARG3) ®s, 0) == -1) + perror_with_name ("Couldn't write registers"); +} + + +/* Support for debugging kernel virtual memory images. */ + +#include +#include + +#include "bsd-kvm.h" + +static int +vaxbsd_supply_pcb (struct regcache *regcache, struct pcb *pcb) +{ + int regnum; + + /* The following is true for OpenBSD 3.5: + + The pcb contains the register state at the context switch inside + cpu_switch(). */ + + /* The stack pointer shouldn't be zero. */ + if (pcb->KSP == 0) + return 0; + + for (regnum = VAX_R0_REGNUM; regnum < VAX_AP_REGNUM; regnum++) + regcache_raw_supply (regcache, regnum, &pcb->R[regnum - VAX_R0_REGNUM]); + regcache_raw_supply (regcache, VAX_AP_REGNUM, &pcb->AP); + regcache_raw_supply (regcache, VAX_FP_REGNUM, &pcb->FP); + regcache_raw_supply (regcache, VAX_SP_REGNUM, &pcb->KSP); + regcache_raw_supply (regcache, VAX_PC_REGNUM, &pcb->PC); + regcache_raw_supply (regcache, VAX_PS_REGNUM, &pcb->PSL); + + return 1; +} + + +/* Provide a prototype to silence -Wmissing-prototypes. */ +void _initialize_vaxbsd_nat (void); + +void +_initialize_vaxbsd_nat (void) +{ + /* Support debugging kernel virtual memory images. */ + bsd_kvm_add_target (vaxbsd_supply_pcb); +} diff --git a/gdb/vaxnbsd-tdep.c b/gdb/vaxnbsd-tdep.c new file mode 100644 index 00000000000..c324da8cd43 --- /dev/null +++ b/gdb/vaxnbsd-tdep.c @@ -0,0 +1,75 @@ +/* Target-dependent code for NetBSD/vax. + + Copyright 2004 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include "defs.h" +#include "arch-utils.h" +#include "osabi.h" + +#include "vax-tdep.h" +#include "solib-svr4.h" + +#include "gdb_string.h" + +/* Support for shared libraries. */ + +/* Return non-zero if we are in a shared library trampoline code stub. */ + +int +vaxnbsd_aout_in_solib_call_trampoline (CORE_ADDR pc, char *name) +{ + return (name && !strcmp (name, "_DYNAMIC")); +} + + +/* NetBSD a.out. */ + +static void +vaxnbsd_aout_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) +{ + /* Assume SunOS-style shared libraries. */ + set_gdbarch_in_solib_call_trampoline + (gdbarch, vaxnbsd_aout_in_solib_call_trampoline); +} + +/* NetBSD ELF. */ + +static void +vaxnbsd_elf_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) +{ + /* NetBSD ELF uses SVR4-style shared libraries. */ + set_gdbarch_in_solib_call_trampoline + (gdbarch, generic_in_solib_call_trampoline); + set_solib_svr4_fetch_link_map_offsets + (gdbarch, svr4_ilp32_fetch_link_map_offsets); +} + + +/* Provide a prototype to silence -Wmissing-prototypes. */ +void _initialize_vaxnbsd_tdep (void); + +void +_initialize_vaxnbsd_tdep (void) +{ + gdbarch_register_osabi (bfd_arch_vax, 0, GDB_OSABI_NETBSD_AOUT, + vaxnbsd_aout_init_abi); + gdbarch_register_osabi (bfd_arch_vax, 0, GDB_OSABI_NETBSD_ELF, + vaxnbsd_elf_init_abi); +} diff --git a/include/elf/crx.h b/include/elf/crx.h new file mode 100644 index 00000000000..33ba0051478 --- /dev/null +++ b/include/elf/crx.h @@ -0,0 +1,53 @@ +/* CRX ELF support for BFD. + Copyright 2004 Free Software Foundation, Inc. + Contributed by Tomer Levi, NSC, Israel. + Originally written for GAS 2.12 by Tomer Levi, NSC, Israel. + Updates, BFDizing, GNUifying and ELF support by Tomer Levi. + + This file is part of BFD, the Binary File Descriptor library. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifndef _ELF_CRX_H +#define _ELF_CRX_H + +#include "elf/reloc-macros.h" + +/* Creating indices for reloc_map_index array. */ +START_RELOC_NUMBERS(elf_crx_reloc_type) + RELOC_NUMBER (R_CRX_NONE, 0) + RELOC_NUMBER (R_CRX_REL4, 1) + RELOC_NUMBER (R_CRX_REL8, 2) + RELOC_NUMBER (R_CRX_REL8_CMP, 3) + RELOC_NUMBER (R_CRX_REL16, 4) + RELOC_NUMBER (R_CRX_REL24, 5) + RELOC_NUMBER (R_CRX_REL32, 6) + RELOC_NUMBER (R_CRX_REGREL12, 7) + RELOC_NUMBER (R_CRX_REGREL22, 8) + RELOC_NUMBER (R_CRX_REGREL28, 9) + RELOC_NUMBER (R_CRX_REGREL32, 10) + RELOC_NUMBER (R_CRX_ABS16, 11) + RELOC_NUMBER (R_CRX_ABS32, 12) + RELOC_NUMBER (R_CRX_NUM8, 13) + RELOC_NUMBER (R_CRX_NUM16, 14) + RELOC_NUMBER (R_CRX_NUM32, 15) + RELOC_NUMBER (R_CRX_IMM16, 16) + RELOC_NUMBER (R_CRX_IMM32, 17) + RELOC_NUMBER (R_CRX_SWITCH8, 18) + RELOC_NUMBER (R_CRX_SWITCH16, 19) + RELOC_NUMBER (R_CRX_SWITCH32, 20) +END_RELOC_NUMBERS(R_CRX_MAX) + +#endif /* _ELF_CRX_H */ diff --git a/include/gdb/sim-ppc.h b/include/gdb/sim-ppc.h new file mode 100644 index 00000000000..e31a6711292 --- /dev/null +++ b/include/gdb/sim-ppc.h @@ -0,0 +1,771 @@ +/* sim-ppc.h --- interface between PowerPC simulator and GDB. + + Copyright 2004 Free Software Foundation, Inc. + + Contributed by Red Hat. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ + +#if !defined (SIM_PPC_H) +#define SIM_PPC_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* The register access functions, sim_fetch_register and + sim_store_register, use the following numbering for PowerPC + registers. */ + +enum sim_ppc_regnum + { + /* General-purpose registers, r0 -- r31. */ + sim_ppc_r0_regnum, + sim_ppc_r1_regnum, + sim_ppc_r2_regnum, + sim_ppc_r3_regnum, + sim_ppc_r4_regnum, + sim_ppc_r5_regnum, + sim_ppc_r6_regnum, + sim_ppc_r7_regnum, + sim_ppc_r8_regnum, + sim_ppc_r9_regnum, + sim_ppc_r10_regnum, + sim_ppc_r11_regnum, + sim_ppc_r12_regnum, + sim_ppc_r13_regnum, + sim_ppc_r14_regnum, + sim_ppc_r15_regnum, + sim_ppc_r16_regnum, + sim_ppc_r17_regnum, + sim_ppc_r18_regnum, + sim_ppc_r19_regnum, + sim_ppc_r20_regnum, + sim_ppc_r21_regnum, + sim_ppc_r22_regnum, + sim_ppc_r23_regnum, + sim_ppc_r24_regnum, + sim_ppc_r25_regnum, + sim_ppc_r26_regnum, + sim_ppc_r27_regnum, + sim_ppc_r28_regnum, + sim_ppc_r29_regnum, + sim_ppc_r30_regnum, + sim_ppc_r31_regnum, + + /* Floating-point registers, f0 -- f31. */ + sim_ppc_f0_regnum, + sim_ppc_f1_regnum, + sim_ppc_f2_regnum, + sim_ppc_f3_regnum, + sim_ppc_f4_regnum, + sim_ppc_f5_regnum, + sim_ppc_f6_regnum, + sim_ppc_f7_regnum, + sim_ppc_f8_regnum, + sim_ppc_f9_regnum, + sim_ppc_f10_regnum, + sim_ppc_f11_regnum, + sim_ppc_f12_regnum, + sim_ppc_f13_regnum, + sim_ppc_f14_regnum, + sim_ppc_f15_regnum, + sim_ppc_f16_regnum, + sim_ppc_f17_regnum, + sim_ppc_f18_regnum, + sim_ppc_f19_regnum, + sim_ppc_f20_regnum, + sim_ppc_f21_regnum, + sim_ppc_f22_regnum, + sim_ppc_f23_regnum, + sim_ppc_f24_regnum, + sim_ppc_f25_regnum, + sim_ppc_f26_regnum, + sim_ppc_f27_regnum, + sim_ppc_f28_regnum, + sim_ppc_f29_regnum, + sim_ppc_f30_regnum, + sim_ppc_f31_regnum, + + /* Altivec vector registers, vr0 -- vr31. */ + sim_ppc_vr0_regnum, + sim_ppc_vr1_regnum, + sim_ppc_vr2_regnum, + sim_ppc_vr3_regnum, + sim_ppc_vr4_regnum, + sim_ppc_vr5_regnum, + sim_ppc_vr6_regnum, + sim_ppc_vr7_regnum, + sim_ppc_vr8_regnum, + sim_ppc_vr9_regnum, + sim_ppc_vr10_regnum, + sim_ppc_vr11_regnum, + sim_ppc_vr12_regnum, + sim_ppc_vr13_regnum, + sim_ppc_vr14_regnum, + sim_ppc_vr15_regnum, + sim_ppc_vr16_regnum, + sim_ppc_vr17_regnum, + sim_ppc_vr18_regnum, + sim_ppc_vr19_regnum, + sim_ppc_vr20_regnum, + sim_ppc_vr21_regnum, + sim_ppc_vr22_regnum, + sim_ppc_vr23_regnum, + sim_ppc_vr24_regnum, + sim_ppc_vr25_regnum, + sim_ppc_vr26_regnum, + sim_ppc_vr27_regnum, + sim_ppc_vr28_regnum, + sim_ppc_vr29_regnum, + sim_ppc_vr30_regnum, + sim_ppc_vr31_regnum, + + /* SPE APU GPR upper halves. These are the upper 32 bits of the + gprs; there is one upper-half register for each gpr, so it is + appropriate to use sim_ppc_num_gprs for iterating through + these. */ + sim_ppc_rh0_regnum, + sim_ppc_rh1_regnum, + sim_ppc_rh2_regnum, + sim_ppc_rh3_regnum, + sim_ppc_rh4_regnum, + sim_ppc_rh5_regnum, + sim_ppc_rh6_regnum, + sim_ppc_rh7_regnum, + sim_ppc_rh8_regnum, + sim_ppc_rh9_regnum, + sim_ppc_rh10_regnum, + sim_ppc_rh11_regnum, + sim_ppc_rh12_regnum, + sim_ppc_rh13_regnum, + sim_ppc_rh14_regnum, + sim_ppc_rh15_regnum, + sim_ppc_rh16_regnum, + sim_ppc_rh17_regnum, + sim_ppc_rh18_regnum, + sim_ppc_rh19_regnum, + sim_ppc_rh20_regnum, + sim_ppc_rh21_regnum, + sim_ppc_rh22_regnum, + sim_ppc_rh23_regnum, + sim_ppc_rh24_regnum, + sim_ppc_rh25_regnum, + sim_ppc_rh26_regnum, + sim_ppc_rh27_regnum, + sim_ppc_rh28_regnum, + sim_ppc_rh29_regnum, + sim_ppc_rh30_regnum, + sim_ppc_rh31_regnum, + + /* SPE APU GPR full registers. Each of these registers is the + 64-bit concatenation of a 32-bit GPR (providing the lower bits) + and a 32-bit upper-half register (providing the higher bits). + As for the upper-half registers, it is appropriate to use + sim_ppc_num_gprs with these. */ + sim_ppc_ev0_regnum, + sim_ppc_ev1_regnum, + sim_ppc_ev2_regnum, + sim_ppc_ev3_regnum, + sim_ppc_ev4_regnum, + sim_ppc_ev5_regnum, + sim_ppc_ev6_regnum, + sim_ppc_ev7_regnum, + sim_ppc_ev8_regnum, + sim_ppc_ev9_regnum, + sim_ppc_ev10_regnum, + sim_ppc_ev11_regnum, + sim_ppc_ev12_regnum, + sim_ppc_ev13_regnum, + sim_ppc_ev14_regnum, + sim_ppc_ev15_regnum, + sim_ppc_ev16_regnum, + sim_ppc_ev17_regnum, + sim_ppc_ev18_regnum, + sim_ppc_ev19_regnum, + sim_ppc_ev20_regnum, + sim_ppc_ev21_regnum, + sim_ppc_ev22_regnum, + sim_ppc_ev23_regnum, + sim_ppc_ev24_regnum, + sim_ppc_ev25_regnum, + sim_ppc_ev26_regnum, + sim_ppc_ev27_regnum, + sim_ppc_ev28_regnum, + sim_ppc_ev29_regnum, + sim_ppc_ev30_regnum, + sim_ppc_ev31_regnum, + + /* Segment registers, sr0 -- sr15. */ + sim_ppc_sr0_regnum, + sim_ppc_sr1_regnum, + sim_ppc_sr2_regnum, + sim_ppc_sr3_regnum, + sim_ppc_sr4_regnum, + sim_ppc_sr5_regnum, + sim_ppc_sr6_regnum, + sim_ppc_sr7_regnum, + sim_ppc_sr8_regnum, + sim_ppc_sr9_regnum, + sim_ppc_sr10_regnum, + sim_ppc_sr11_regnum, + sim_ppc_sr12_regnum, + sim_ppc_sr13_regnum, + sim_ppc_sr14_regnum, + sim_ppc_sr15_regnum, + + /* Miscellaneous --- but non-SPR --- registers. */ + sim_ppc_pc_regnum, + sim_ppc_ps_regnum, + sim_ppc_cr_regnum, + sim_ppc_fpscr_regnum, + sim_ppc_acc_regnum, + sim_ppc_vscr_regnum, + + /* Special-purpose registers. */ + sim_ppc_spr0_regnum, sim_ppc_spr1_regnum, + sim_ppc_spr2_regnum, sim_ppc_spr3_regnum, + sim_ppc_spr4_regnum, sim_ppc_spr5_regnum, + sim_ppc_spr6_regnum, sim_ppc_spr7_regnum, + sim_ppc_spr8_regnum, sim_ppc_spr9_regnum, + sim_ppc_spr10_regnum, sim_ppc_spr11_regnum, + sim_ppc_spr12_regnum, sim_ppc_spr13_regnum, + sim_ppc_spr14_regnum, sim_ppc_spr15_regnum, + sim_ppc_spr16_regnum, sim_ppc_spr17_regnum, + sim_ppc_spr18_regnum, sim_ppc_spr19_regnum, + sim_ppc_spr20_regnum, sim_ppc_spr21_regnum, + sim_ppc_spr22_regnum, sim_ppc_spr23_regnum, + sim_ppc_spr24_regnum, sim_ppc_spr25_regnum, + sim_ppc_spr26_regnum, sim_ppc_spr27_regnum, + sim_ppc_spr28_regnum, sim_ppc_spr29_regnum, + sim_ppc_spr30_regnum, sim_ppc_spr31_regnum, + sim_ppc_spr32_regnum, sim_ppc_spr33_regnum, + sim_ppc_spr34_regnum, sim_ppc_spr35_regnum, + sim_ppc_spr36_regnum, sim_ppc_spr37_regnum, + sim_ppc_spr38_regnum, sim_ppc_spr39_regnum, + sim_ppc_spr40_regnum, sim_ppc_spr41_regnum, + sim_ppc_spr42_regnum, sim_ppc_spr43_regnum, + sim_ppc_spr44_regnum, sim_ppc_spr45_regnum, + sim_ppc_spr46_regnum, sim_ppc_spr47_regnum, + sim_ppc_spr48_regnum, sim_ppc_spr49_regnum, + sim_ppc_spr50_regnum, sim_ppc_spr51_regnum, + sim_ppc_spr52_regnum, sim_ppc_spr53_regnum, + sim_ppc_spr54_regnum, sim_ppc_spr55_regnum, + sim_ppc_spr56_regnum, sim_ppc_spr57_regnum, + sim_ppc_spr58_regnum, sim_ppc_spr59_regnum, + sim_ppc_spr60_regnum, sim_ppc_spr61_regnum, + sim_ppc_spr62_regnum, sim_ppc_spr63_regnum, + sim_ppc_spr64_regnum, sim_ppc_spr65_regnum, + sim_ppc_spr66_regnum, sim_ppc_spr67_regnum, + sim_ppc_spr68_regnum, sim_ppc_spr69_regnum, + sim_ppc_spr70_regnum, sim_ppc_spr71_regnum, + sim_ppc_spr72_regnum, sim_ppc_spr73_regnum, + sim_ppc_spr74_regnum, sim_ppc_spr75_regnum, + sim_ppc_spr76_regnum, sim_ppc_spr77_regnum, + sim_ppc_spr78_regnum, sim_ppc_spr79_regnum, + sim_ppc_spr80_regnum, sim_ppc_spr81_regnum, + sim_ppc_spr82_regnum, sim_ppc_spr83_regnum, + sim_ppc_spr84_regnum, sim_ppc_spr85_regnum, + sim_ppc_spr86_regnum, sim_ppc_spr87_regnum, + sim_ppc_spr88_regnum, sim_ppc_spr89_regnum, + sim_ppc_spr90_regnum, sim_ppc_spr91_regnum, + sim_ppc_spr92_regnum, sim_ppc_spr93_regnum, + sim_ppc_spr94_regnum, sim_ppc_spr95_regnum, + sim_ppc_spr96_regnum, sim_ppc_spr97_regnum, + sim_ppc_spr98_regnum, sim_ppc_spr99_regnum, + sim_ppc_spr100_regnum, sim_ppc_spr101_regnum, + sim_ppc_spr102_regnum, sim_ppc_spr103_regnum, + sim_ppc_spr104_regnum, sim_ppc_spr105_regnum, + sim_ppc_spr106_regnum, sim_ppc_spr107_regnum, + sim_ppc_spr108_regnum, sim_ppc_spr109_regnum, + sim_ppc_spr110_regnum, sim_ppc_spr111_regnum, + sim_ppc_spr112_regnum, sim_ppc_spr113_regnum, + sim_ppc_spr114_regnum, sim_ppc_spr115_regnum, + sim_ppc_spr116_regnum, sim_ppc_spr117_regnum, + sim_ppc_spr118_regnum, sim_ppc_spr119_regnum, + sim_ppc_spr120_regnum, sim_ppc_spr121_regnum, + sim_ppc_spr122_regnum, sim_ppc_spr123_regnum, + sim_ppc_spr124_regnum, sim_ppc_spr125_regnum, + sim_ppc_spr126_regnum, sim_ppc_spr127_regnum, + sim_ppc_spr128_regnum, sim_ppc_spr129_regnum, + sim_ppc_spr130_regnum, sim_ppc_spr131_regnum, + sim_ppc_spr132_regnum, sim_ppc_spr133_regnum, + sim_ppc_spr134_regnum, sim_ppc_spr135_regnum, + sim_ppc_spr136_regnum, sim_ppc_spr137_regnum, + sim_ppc_spr138_regnum, sim_ppc_spr139_regnum, + sim_ppc_spr140_regnum, sim_ppc_spr141_regnum, + sim_ppc_spr142_regnum, sim_ppc_spr143_regnum, + sim_ppc_spr144_regnum, sim_ppc_spr145_regnum, + sim_ppc_spr146_regnum, sim_ppc_spr147_regnum, + sim_ppc_spr148_regnum, sim_ppc_spr149_regnum, + sim_ppc_spr150_regnum, sim_ppc_spr151_regnum, + sim_ppc_spr152_regnum, sim_ppc_spr153_regnum, + sim_ppc_spr154_regnum, sim_ppc_spr155_regnum, + sim_ppc_spr156_regnum, sim_ppc_spr157_regnum, + sim_ppc_spr158_regnum, sim_ppc_spr159_regnum, + sim_ppc_spr160_regnum, sim_ppc_spr161_regnum, + sim_ppc_spr162_regnum, sim_ppc_spr163_regnum, + sim_ppc_spr164_regnum, sim_ppc_spr165_regnum, + sim_ppc_spr166_regnum, sim_ppc_spr167_regnum, + sim_ppc_spr168_regnum, sim_ppc_spr169_regnum, + sim_ppc_spr170_regnum, sim_ppc_spr171_regnum, + sim_ppc_spr172_regnum, sim_ppc_spr173_regnum, + sim_ppc_spr174_regnum, sim_ppc_spr175_regnum, + sim_ppc_spr176_regnum, sim_ppc_spr177_regnum, + sim_ppc_spr178_regnum, sim_ppc_spr179_regnum, + sim_ppc_spr180_regnum, sim_ppc_spr181_regnum, + sim_ppc_spr182_regnum, sim_ppc_spr183_regnum, + sim_ppc_spr184_regnum, sim_ppc_spr185_regnum, + sim_ppc_spr186_regnum, sim_ppc_spr187_regnum, + sim_ppc_spr188_regnum, sim_ppc_spr189_regnum, + sim_ppc_spr190_regnum, sim_ppc_spr191_regnum, + sim_ppc_spr192_regnum, sim_ppc_spr193_regnum, + sim_ppc_spr194_regnum, sim_ppc_spr195_regnum, + sim_ppc_spr196_regnum, sim_ppc_spr197_regnum, + sim_ppc_spr198_regnum, sim_ppc_spr199_regnum, + sim_ppc_spr200_regnum, sim_ppc_spr201_regnum, + sim_ppc_spr202_regnum, sim_ppc_spr203_regnum, + sim_ppc_spr204_regnum, sim_ppc_spr205_regnum, + sim_ppc_spr206_regnum, sim_ppc_spr207_regnum, + sim_ppc_spr208_regnum, sim_ppc_spr209_regnum, + sim_ppc_spr210_regnum, sim_ppc_spr211_regnum, + sim_ppc_spr212_regnum, sim_ppc_spr213_regnum, + sim_ppc_spr214_regnum, sim_ppc_spr215_regnum, + sim_ppc_spr216_regnum, sim_ppc_spr217_regnum, + sim_ppc_spr218_regnum, sim_ppc_spr219_regnum, + sim_ppc_spr220_regnum, sim_ppc_spr221_regnum, + sim_ppc_spr222_regnum, sim_ppc_spr223_regnum, + sim_ppc_spr224_regnum, sim_ppc_spr225_regnum, + sim_ppc_spr226_regnum, sim_ppc_spr227_regnum, + sim_ppc_spr228_regnum, sim_ppc_spr229_regnum, + sim_ppc_spr230_regnum, sim_ppc_spr231_regnum, + sim_ppc_spr232_regnum, sim_ppc_spr233_regnum, + sim_ppc_spr234_regnum, sim_ppc_spr235_regnum, + sim_ppc_spr236_regnum, sim_ppc_spr237_regnum, + sim_ppc_spr238_regnum, sim_ppc_spr239_regnum, + sim_ppc_spr240_regnum, sim_ppc_spr241_regnum, + sim_ppc_spr242_regnum, sim_ppc_spr243_regnum, + sim_ppc_spr244_regnum, sim_ppc_spr245_regnum, + sim_ppc_spr246_regnum, sim_ppc_spr247_regnum, + sim_ppc_spr248_regnum, sim_ppc_spr249_regnum, + sim_ppc_spr250_regnum, sim_ppc_spr251_regnum, + sim_ppc_spr252_regnum, sim_ppc_spr253_regnum, + sim_ppc_spr254_regnum, sim_ppc_spr255_regnum, + sim_ppc_spr256_regnum, sim_ppc_spr257_regnum, + sim_ppc_spr258_regnum, sim_ppc_spr259_regnum, + sim_ppc_spr260_regnum, sim_ppc_spr261_regnum, + sim_ppc_spr262_regnum, sim_ppc_spr263_regnum, + sim_ppc_spr264_regnum, sim_ppc_spr265_regnum, + sim_ppc_spr266_regnum, sim_ppc_spr267_regnum, + sim_ppc_spr268_regnum, sim_ppc_spr269_regnum, + sim_ppc_spr270_regnum, sim_ppc_spr271_regnum, + sim_ppc_spr272_regnum, sim_ppc_spr273_regnum, + sim_ppc_spr274_regnum, sim_ppc_spr275_regnum, + sim_ppc_spr276_regnum, sim_ppc_spr277_regnum, + sim_ppc_spr278_regnum, sim_ppc_spr279_regnum, + sim_ppc_spr280_regnum, sim_ppc_spr281_regnum, + sim_ppc_spr282_regnum, sim_ppc_spr283_regnum, + sim_ppc_spr284_regnum, sim_ppc_spr285_regnum, + sim_ppc_spr286_regnum, sim_ppc_spr287_regnum, + sim_ppc_spr288_regnum, sim_ppc_spr289_regnum, + sim_ppc_spr290_regnum, sim_ppc_spr291_regnum, + sim_ppc_spr292_regnum, sim_ppc_spr293_regnum, + sim_ppc_spr294_regnum, sim_ppc_spr295_regnum, + sim_ppc_spr296_regnum, sim_ppc_spr297_regnum, + sim_ppc_spr298_regnum, sim_ppc_spr299_regnum, + sim_ppc_spr300_regnum, sim_ppc_spr301_regnum, + sim_ppc_spr302_regnum, sim_ppc_spr303_regnum, + sim_ppc_spr304_regnum, sim_ppc_spr305_regnum, + sim_ppc_spr306_regnum, sim_ppc_spr307_regnum, + sim_ppc_spr308_regnum, sim_ppc_spr309_regnum, + sim_ppc_spr310_regnum, sim_ppc_spr311_regnum, + sim_ppc_spr312_regnum, sim_ppc_spr313_regnum, + sim_ppc_spr314_regnum, sim_ppc_spr315_regnum, + sim_ppc_spr316_regnum, sim_ppc_spr317_regnum, + sim_ppc_spr318_regnum, sim_ppc_spr319_regnum, + sim_ppc_spr320_regnum, sim_ppc_spr321_regnum, + sim_ppc_spr322_regnum, sim_ppc_spr323_regnum, + sim_ppc_spr324_regnum, sim_ppc_spr325_regnum, + sim_ppc_spr326_regnum, sim_ppc_spr327_regnum, + sim_ppc_spr328_regnum, sim_ppc_spr329_regnum, + sim_ppc_spr330_regnum, sim_ppc_spr331_regnum, + sim_ppc_spr332_regnum, sim_ppc_spr333_regnum, + sim_ppc_spr334_regnum, sim_ppc_spr335_regnum, + sim_ppc_spr336_regnum, sim_ppc_spr337_regnum, + sim_ppc_spr338_regnum, sim_ppc_spr339_regnum, + sim_ppc_spr340_regnum, sim_ppc_spr341_regnum, + sim_ppc_spr342_regnum, sim_ppc_spr343_regnum, + sim_ppc_spr344_regnum, sim_ppc_spr345_regnum, + sim_ppc_spr346_regnum, sim_ppc_spr347_regnum, + sim_ppc_spr348_regnum, sim_ppc_spr349_regnum, + sim_ppc_spr350_regnum, sim_ppc_spr351_regnum, + sim_ppc_spr352_regnum, sim_ppc_spr353_regnum, + sim_ppc_spr354_regnum, sim_ppc_spr355_regnum, + sim_ppc_spr356_regnum, sim_ppc_spr357_regnum, + sim_ppc_spr358_regnum, sim_ppc_spr359_regnum, + sim_ppc_spr360_regnum, sim_ppc_spr361_regnum, + sim_ppc_spr362_regnum, sim_ppc_spr363_regnum, + sim_ppc_spr364_regnum, sim_ppc_spr365_regnum, + sim_ppc_spr366_regnum, sim_ppc_spr367_regnum, + sim_ppc_spr368_regnum, sim_ppc_spr369_regnum, + sim_ppc_spr370_regnum, sim_ppc_spr371_regnum, + sim_ppc_spr372_regnum, sim_ppc_spr373_regnum, + sim_ppc_spr374_regnum, sim_ppc_spr375_regnum, + sim_ppc_spr376_regnum, sim_ppc_spr377_regnum, + sim_ppc_spr378_regnum, sim_ppc_spr379_regnum, + sim_ppc_spr380_regnum, sim_ppc_spr381_regnum, + sim_ppc_spr382_regnum, sim_ppc_spr383_regnum, + sim_ppc_spr384_regnum, sim_ppc_spr385_regnum, + sim_ppc_spr386_regnum, sim_ppc_spr387_regnum, + sim_ppc_spr388_regnum, sim_ppc_spr389_regnum, + sim_ppc_spr390_regnum, sim_ppc_spr391_regnum, + sim_ppc_spr392_regnum, sim_ppc_spr393_regnum, + sim_ppc_spr394_regnum, sim_ppc_spr395_regnum, + sim_ppc_spr396_regnum, sim_ppc_spr397_regnum, + sim_ppc_spr398_regnum, sim_ppc_spr399_regnum, + sim_ppc_spr400_regnum, sim_ppc_spr401_regnum, + sim_ppc_spr402_regnum, sim_ppc_spr403_regnum, + sim_ppc_spr404_regnum, sim_ppc_spr405_regnum, + sim_ppc_spr406_regnum, sim_ppc_spr407_regnum, + sim_ppc_spr408_regnum, sim_ppc_spr409_regnum, + sim_ppc_spr410_regnum, sim_ppc_spr411_regnum, + sim_ppc_spr412_regnum, sim_ppc_spr413_regnum, + sim_ppc_spr414_regnum, sim_ppc_spr415_regnum, + sim_ppc_spr416_regnum, sim_ppc_spr417_regnum, + sim_ppc_spr418_regnum, sim_ppc_spr419_regnum, + sim_ppc_spr420_regnum, sim_ppc_spr421_regnum, + sim_ppc_spr422_regnum, sim_ppc_spr423_regnum, + sim_ppc_spr424_regnum, sim_ppc_spr425_regnum, + sim_ppc_spr426_regnum, sim_ppc_spr427_regnum, + sim_ppc_spr428_regnum, sim_ppc_spr429_regnum, + sim_ppc_spr430_regnum, sim_ppc_spr431_regnum, + sim_ppc_spr432_regnum, sim_ppc_spr433_regnum, + sim_ppc_spr434_regnum, sim_ppc_spr435_regnum, + sim_ppc_spr436_regnum, sim_ppc_spr437_regnum, + sim_ppc_spr438_regnum, sim_ppc_spr439_regnum, + sim_ppc_spr440_regnum, sim_ppc_spr441_regnum, + sim_ppc_spr442_regnum, sim_ppc_spr443_regnum, + sim_ppc_spr444_regnum, sim_ppc_spr445_regnum, + sim_ppc_spr446_regnum, sim_ppc_spr447_regnum, + sim_ppc_spr448_regnum, sim_ppc_spr449_regnum, + sim_ppc_spr450_regnum, sim_ppc_spr451_regnum, + sim_ppc_spr452_regnum, sim_ppc_spr453_regnum, + sim_ppc_spr454_regnum, sim_ppc_spr455_regnum, + sim_ppc_spr456_regnum, sim_ppc_spr457_regnum, + sim_ppc_spr458_regnum, sim_ppc_spr459_regnum, + sim_ppc_spr460_regnum, sim_ppc_spr461_regnum, + sim_ppc_spr462_regnum, sim_ppc_spr463_regnum, + sim_ppc_spr464_regnum, sim_ppc_spr465_regnum, + sim_ppc_spr466_regnum, sim_ppc_spr467_regnum, + sim_ppc_spr468_regnum, sim_ppc_spr469_regnum, + sim_ppc_spr470_regnum, sim_ppc_spr471_regnum, + sim_ppc_spr472_regnum, sim_ppc_spr473_regnum, + sim_ppc_spr474_regnum, sim_ppc_spr475_regnum, + sim_ppc_spr476_regnum, sim_ppc_spr477_regnum, + sim_ppc_spr478_regnum, sim_ppc_spr479_regnum, + sim_ppc_spr480_regnum, sim_ppc_spr481_regnum, + sim_ppc_spr482_regnum, sim_ppc_spr483_regnum, + sim_ppc_spr484_regnum, sim_ppc_spr485_regnum, + sim_ppc_spr486_regnum, sim_ppc_spr487_regnum, + sim_ppc_spr488_regnum, sim_ppc_spr489_regnum, + sim_ppc_spr490_regnum, sim_ppc_spr491_regnum, + sim_ppc_spr492_regnum, sim_ppc_spr493_regnum, + sim_ppc_spr494_regnum, sim_ppc_spr495_regnum, + sim_ppc_spr496_regnum, sim_ppc_spr497_regnum, + sim_ppc_spr498_regnum, sim_ppc_spr499_regnum, + sim_ppc_spr500_regnum, sim_ppc_spr501_regnum, + sim_ppc_spr502_regnum, sim_ppc_spr503_regnum, + sim_ppc_spr504_regnum, sim_ppc_spr505_regnum, + sim_ppc_spr506_regnum, sim_ppc_spr507_regnum, + sim_ppc_spr508_regnum, sim_ppc_spr509_regnum, + sim_ppc_spr510_regnum, sim_ppc_spr511_regnum, + sim_ppc_spr512_regnum, sim_ppc_spr513_regnum, + sim_ppc_spr514_regnum, sim_ppc_spr515_regnum, + sim_ppc_spr516_regnum, sim_ppc_spr517_regnum, + sim_ppc_spr518_regnum, sim_ppc_spr519_regnum, + sim_ppc_spr520_regnum, sim_ppc_spr521_regnum, + sim_ppc_spr522_regnum, sim_ppc_spr523_regnum, + sim_ppc_spr524_regnum, sim_ppc_spr525_regnum, + sim_ppc_spr526_regnum, sim_ppc_spr527_regnum, + sim_ppc_spr528_regnum, sim_ppc_spr529_regnum, + sim_ppc_spr530_regnum, sim_ppc_spr531_regnum, + sim_ppc_spr532_regnum, sim_ppc_spr533_regnum, + sim_ppc_spr534_regnum, sim_ppc_spr535_regnum, + sim_ppc_spr536_regnum, sim_ppc_spr537_regnum, + sim_ppc_spr538_regnum, sim_ppc_spr539_regnum, + sim_ppc_spr540_regnum, sim_ppc_spr541_regnum, + sim_ppc_spr542_regnum, sim_ppc_spr543_regnum, + sim_ppc_spr544_regnum, sim_ppc_spr545_regnum, + sim_ppc_spr546_regnum, sim_ppc_spr547_regnum, + sim_ppc_spr548_regnum, sim_ppc_spr549_regnum, + sim_ppc_spr550_regnum, sim_ppc_spr551_regnum, + sim_ppc_spr552_regnum, sim_ppc_spr553_regnum, + sim_ppc_spr554_regnum, sim_ppc_spr555_regnum, + sim_ppc_spr556_regnum, sim_ppc_spr557_regnum, + sim_ppc_spr558_regnum, sim_ppc_spr559_regnum, + sim_ppc_spr560_regnum, sim_ppc_spr561_regnum, + sim_ppc_spr562_regnum, sim_ppc_spr563_regnum, + sim_ppc_spr564_regnum, sim_ppc_spr565_regnum, + sim_ppc_spr566_regnum, sim_ppc_spr567_regnum, + sim_ppc_spr568_regnum, sim_ppc_spr569_regnum, + sim_ppc_spr570_regnum, sim_ppc_spr571_regnum, + sim_ppc_spr572_regnum, sim_ppc_spr573_regnum, + sim_ppc_spr574_regnum, sim_ppc_spr575_regnum, + sim_ppc_spr576_regnum, sim_ppc_spr577_regnum, + sim_ppc_spr578_regnum, sim_ppc_spr579_regnum, + sim_ppc_spr580_regnum, sim_ppc_spr581_regnum, + sim_ppc_spr582_regnum, sim_ppc_spr583_regnum, + sim_ppc_spr584_regnum, sim_ppc_spr585_regnum, + sim_ppc_spr586_regnum, sim_ppc_spr587_regnum, + sim_ppc_spr588_regnum, sim_ppc_spr589_regnum, + sim_ppc_spr590_regnum, sim_ppc_spr591_regnum, + sim_ppc_spr592_regnum, sim_ppc_spr593_regnum, + sim_ppc_spr594_regnum, sim_ppc_spr595_regnum, + sim_ppc_spr596_regnum, sim_ppc_spr597_regnum, + sim_ppc_spr598_regnum, sim_ppc_spr599_regnum, + sim_ppc_spr600_regnum, sim_ppc_spr601_regnum, + sim_ppc_spr602_regnum, sim_ppc_spr603_regnum, + sim_ppc_spr604_regnum, sim_ppc_spr605_regnum, + sim_ppc_spr606_regnum, sim_ppc_spr607_regnum, + sim_ppc_spr608_regnum, sim_ppc_spr609_regnum, + sim_ppc_spr610_regnum, sim_ppc_spr611_regnum, + sim_ppc_spr612_regnum, sim_ppc_spr613_regnum, + sim_ppc_spr614_regnum, sim_ppc_spr615_regnum, + sim_ppc_spr616_regnum, sim_ppc_spr617_regnum, + sim_ppc_spr618_regnum, sim_ppc_spr619_regnum, + sim_ppc_spr620_regnum, sim_ppc_spr621_regnum, + sim_ppc_spr622_regnum, sim_ppc_spr623_regnum, + sim_ppc_spr624_regnum, sim_ppc_spr625_regnum, + sim_ppc_spr626_regnum, sim_ppc_spr627_regnum, + sim_ppc_spr628_regnum, sim_ppc_spr629_regnum, + sim_ppc_spr630_regnum, sim_ppc_spr631_regnum, + sim_ppc_spr632_regnum, sim_ppc_spr633_regnum, + sim_ppc_spr634_regnum, sim_ppc_spr635_regnum, + sim_ppc_spr636_regnum, sim_ppc_spr637_regnum, + sim_ppc_spr638_regnum, sim_ppc_spr639_regnum, + sim_ppc_spr640_regnum, sim_ppc_spr641_regnum, + sim_ppc_spr642_regnum, sim_ppc_spr643_regnum, + sim_ppc_spr644_regnum, sim_ppc_spr645_regnum, + sim_ppc_spr646_regnum, sim_ppc_spr647_regnum, + sim_ppc_spr648_regnum, sim_ppc_spr649_regnum, + sim_ppc_spr650_regnum, sim_ppc_spr651_regnum, + sim_ppc_spr652_regnum, sim_ppc_spr653_regnum, + sim_ppc_spr654_regnum, sim_ppc_spr655_regnum, + sim_ppc_spr656_regnum, sim_ppc_spr657_regnum, + sim_ppc_spr658_regnum, sim_ppc_spr659_regnum, + sim_ppc_spr660_regnum, sim_ppc_spr661_regnum, + sim_ppc_spr662_regnum, sim_ppc_spr663_regnum, + sim_ppc_spr664_regnum, sim_ppc_spr665_regnum, + sim_ppc_spr666_regnum, sim_ppc_spr667_regnum, + sim_ppc_spr668_regnum, sim_ppc_spr669_regnum, + sim_ppc_spr670_regnum, sim_ppc_spr671_regnum, + sim_ppc_spr672_regnum, sim_ppc_spr673_regnum, + sim_ppc_spr674_regnum, sim_ppc_spr675_regnum, + sim_ppc_spr676_regnum, sim_ppc_spr677_regnum, + sim_ppc_spr678_regnum, sim_ppc_spr679_regnum, + sim_ppc_spr680_regnum, sim_ppc_spr681_regnum, + sim_ppc_spr682_regnum, sim_ppc_spr683_regnum, + sim_ppc_spr684_regnum, sim_ppc_spr685_regnum, + sim_ppc_spr686_regnum, sim_ppc_spr687_regnum, + sim_ppc_spr688_regnum, sim_ppc_spr689_regnum, + sim_ppc_spr690_regnum, sim_ppc_spr691_regnum, + sim_ppc_spr692_regnum, sim_ppc_spr693_regnum, + sim_ppc_spr694_regnum, sim_ppc_spr695_regnum, + sim_ppc_spr696_regnum, sim_ppc_spr697_regnum, + sim_ppc_spr698_regnum, sim_ppc_spr699_regnum, + sim_ppc_spr700_regnum, sim_ppc_spr701_regnum, + sim_ppc_spr702_regnum, sim_ppc_spr703_regnum, + sim_ppc_spr704_regnum, sim_ppc_spr705_regnum, + sim_ppc_spr706_regnum, sim_ppc_spr707_regnum, + sim_ppc_spr708_regnum, sim_ppc_spr709_regnum, + sim_ppc_spr710_regnum, sim_ppc_spr711_regnum, + sim_ppc_spr712_regnum, sim_ppc_spr713_regnum, + sim_ppc_spr714_regnum, sim_ppc_spr715_regnum, + sim_ppc_spr716_regnum, sim_ppc_spr717_regnum, + sim_ppc_spr718_regnum, sim_ppc_spr719_regnum, + sim_ppc_spr720_regnum, sim_ppc_spr721_regnum, + sim_ppc_spr722_regnum, sim_ppc_spr723_regnum, + sim_ppc_spr724_regnum, sim_ppc_spr725_regnum, + sim_ppc_spr726_regnum, sim_ppc_spr727_regnum, + sim_ppc_spr728_regnum, sim_ppc_spr729_regnum, + sim_ppc_spr730_regnum, sim_ppc_spr731_regnum, + sim_ppc_spr732_regnum, sim_ppc_spr733_regnum, + sim_ppc_spr734_regnum, sim_ppc_spr735_regnum, + sim_ppc_spr736_regnum, sim_ppc_spr737_regnum, + sim_ppc_spr738_regnum, sim_ppc_spr739_regnum, + sim_ppc_spr740_regnum, sim_ppc_spr741_regnum, + sim_ppc_spr742_regnum, sim_ppc_spr743_regnum, + sim_ppc_spr744_regnum, sim_ppc_spr745_regnum, + sim_ppc_spr746_regnum, sim_ppc_spr747_regnum, + sim_ppc_spr748_regnum, sim_ppc_spr749_regnum, + sim_ppc_spr750_regnum, sim_ppc_spr751_regnum, + sim_ppc_spr752_regnum, sim_ppc_spr753_regnum, + sim_ppc_spr754_regnum, sim_ppc_spr755_regnum, + sim_ppc_spr756_regnum, sim_ppc_spr757_regnum, + sim_ppc_spr758_regnum, sim_ppc_spr759_regnum, + sim_ppc_spr760_regnum, sim_ppc_spr761_regnum, + sim_ppc_spr762_regnum, sim_ppc_spr763_regnum, + sim_ppc_spr764_regnum, sim_ppc_spr765_regnum, + sim_ppc_spr766_regnum, sim_ppc_spr767_regnum, + sim_ppc_spr768_regnum, sim_ppc_spr769_regnum, + sim_ppc_spr770_regnum, sim_ppc_spr771_regnum, + sim_ppc_spr772_regnum, sim_ppc_spr773_regnum, + sim_ppc_spr774_regnum, sim_ppc_spr775_regnum, + sim_ppc_spr776_regnum, sim_ppc_spr777_regnum, + sim_ppc_spr778_regnum, sim_ppc_spr779_regnum, + sim_ppc_spr780_regnum, sim_ppc_spr781_regnum, + sim_ppc_spr782_regnum, sim_ppc_spr783_regnum, + sim_ppc_spr784_regnum, sim_ppc_spr785_regnum, + sim_ppc_spr786_regnum, sim_ppc_spr787_regnum, + sim_ppc_spr788_regnum, sim_ppc_spr789_regnum, + sim_ppc_spr790_regnum, sim_ppc_spr791_regnum, + sim_ppc_spr792_regnum, sim_ppc_spr793_regnum, + sim_ppc_spr794_regnum, sim_ppc_spr795_regnum, + sim_ppc_spr796_regnum, sim_ppc_spr797_regnum, + sim_ppc_spr798_regnum, sim_ppc_spr799_regnum, + sim_ppc_spr800_regnum, sim_ppc_spr801_regnum, + sim_ppc_spr802_regnum, sim_ppc_spr803_regnum, + sim_ppc_spr804_regnum, sim_ppc_spr805_regnum, + sim_ppc_spr806_regnum, sim_ppc_spr807_regnum, + sim_ppc_spr808_regnum, sim_ppc_spr809_regnum, + sim_ppc_spr810_regnum, sim_ppc_spr811_regnum, + sim_ppc_spr812_regnum, sim_ppc_spr813_regnum, + sim_ppc_spr814_regnum, sim_ppc_spr815_regnum, + sim_ppc_spr816_regnum, sim_ppc_spr817_regnum, + sim_ppc_spr818_regnum, sim_ppc_spr819_regnum, + sim_ppc_spr820_regnum, sim_ppc_spr821_regnum, + sim_ppc_spr822_regnum, sim_ppc_spr823_regnum, + sim_ppc_spr824_regnum, sim_ppc_spr825_regnum, + sim_ppc_spr826_regnum, sim_ppc_spr827_regnum, + sim_ppc_spr828_regnum, sim_ppc_spr829_regnum, + sim_ppc_spr830_regnum, sim_ppc_spr831_regnum, + sim_ppc_spr832_regnum, sim_ppc_spr833_regnum, + sim_ppc_spr834_regnum, sim_ppc_spr835_regnum, + sim_ppc_spr836_regnum, sim_ppc_spr837_regnum, + sim_ppc_spr838_regnum, sim_ppc_spr839_regnum, + sim_ppc_spr840_regnum, sim_ppc_spr841_regnum, + sim_ppc_spr842_regnum, sim_ppc_spr843_regnum, + sim_ppc_spr844_regnum, sim_ppc_spr845_regnum, + sim_ppc_spr846_regnum, sim_ppc_spr847_regnum, + sim_ppc_spr848_regnum, sim_ppc_spr849_regnum, + sim_ppc_spr850_regnum, sim_ppc_spr851_regnum, + sim_ppc_spr852_regnum, sim_ppc_spr853_regnum, + sim_ppc_spr854_regnum, sim_ppc_spr855_regnum, + sim_ppc_spr856_regnum, sim_ppc_spr857_regnum, + sim_ppc_spr858_regnum, sim_ppc_spr859_regnum, + sim_ppc_spr860_regnum, sim_ppc_spr861_regnum, + sim_ppc_spr862_regnum, sim_ppc_spr863_regnum, + sim_ppc_spr864_regnum, sim_ppc_spr865_regnum, + sim_ppc_spr866_regnum, sim_ppc_spr867_regnum, + sim_ppc_spr868_regnum, sim_ppc_spr869_regnum, + sim_ppc_spr870_regnum, sim_ppc_spr871_regnum, + sim_ppc_spr872_regnum, sim_ppc_spr873_regnum, + sim_ppc_spr874_regnum, sim_ppc_spr875_regnum, + sim_ppc_spr876_regnum, sim_ppc_spr877_regnum, + sim_ppc_spr878_regnum, sim_ppc_spr879_regnum, + sim_ppc_spr880_regnum, sim_ppc_spr881_regnum, + sim_ppc_spr882_regnum, sim_ppc_spr883_regnum, + sim_ppc_spr884_regnum, sim_ppc_spr885_regnum, + sim_ppc_spr886_regnum, sim_ppc_spr887_regnum, + sim_ppc_spr888_regnum, sim_ppc_spr889_regnum, + sim_ppc_spr890_regnum, sim_ppc_spr891_regnum, + sim_ppc_spr892_regnum, sim_ppc_spr893_regnum, + sim_ppc_spr894_regnum, sim_ppc_spr895_regnum, + sim_ppc_spr896_regnum, sim_ppc_spr897_regnum, + sim_ppc_spr898_regnum, sim_ppc_spr899_regnum, + sim_ppc_spr900_regnum, sim_ppc_spr901_regnum, + sim_ppc_spr902_regnum, sim_ppc_spr903_regnum, + sim_ppc_spr904_regnum, sim_ppc_spr905_regnum, + sim_ppc_spr906_regnum, sim_ppc_spr907_regnum, + sim_ppc_spr908_regnum, sim_ppc_spr909_regnum, + sim_ppc_spr910_regnum, sim_ppc_spr911_regnum, + sim_ppc_spr912_regnum, sim_ppc_spr913_regnum, + sim_ppc_spr914_regnum, sim_ppc_spr915_regnum, + sim_ppc_spr916_regnum, sim_ppc_spr917_regnum, + sim_ppc_spr918_regnum, sim_ppc_spr919_regnum, + sim_ppc_spr920_regnum, sim_ppc_spr921_regnum, + sim_ppc_spr922_regnum, sim_ppc_spr923_regnum, + sim_ppc_spr924_regnum, sim_ppc_spr925_regnum, + sim_ppc_spr926_regnum, sim_ppc_spr927_regnum, + sim_ppc_spr928_regnum, sim_ppc_spr929_regnum, + sim_ppc_spr930_regnum, sim_ppc_spr931_regnum, + sim_ppc_spr932_regnum, sim_ppc_spr933_regnum, + sim_ppc_spr934_regnum, sim_ppc_spr935_regnum, + sim_ppc_spr936_regnum, sim_ppc_spr937_regnum, + sim_ppc_spr938_regnum, sim_ppc_spr939_regnum, + sim_ppc_spr940_regnum, sim_ppc_spr941_regnum, + sim_ppc_spr942_regnum, sim_ppc_spr943_regnum, + sim_ppc_spr944_regnum, sim_ppc_spr945_regnum, + sim_ppc_spr946_regnum, sim_ppc_spr947_regnum, + sim_ppc_spr948_regnum, sim_ppc_spr949_regnum, + sim_ppc_spr950_regnum, sim_ppc_spr951_regnum, + sim_ppc_spr952_regnum, sim_ppc_spr953_regnum, + sim_ppc_spr954_regnum, sim_ppc_spr955_regnum, + sim_ppc_spr956_regnum, sim_ppc_spr957_regnum, + sim_ppc_spr958_regnum, sim_ppc_spr959_regnum, + sim_ppc_spr960_regnum, sim_ppc_spr961_regnum, + sim_ppc_spr962_regnum, sim_ppc_spr963_regnum, + sim_ppc_spr964_regnum, sim_ppc_spr965_regnum, + sim_ppc_spr966_regnum, sim_ppc_spr967_regnum, + sim_ppc_spr968_regnum, sim_ppc_spr969_regnum, + sim_ppc_spr970_regnum, sim_ppc_spr971_regnum, + sim_ppc_spr972_regnum, sim_ppc_spr973_regnum, + sim_ppc_spr974_regnum, sim_ppc_spr975_regnum, + sim_ppc_spr976_regnum, sim_ppc_spr977_regnum, + sim_ppc_spr978_regnum, sim_ppc_spr979_regnum, + sim_ppc_spr980_regnum, sim_ppc_spr981_regnum, + sim_ppc_spr982_regnum, sim_ppc_spr983_regnum, + sim_ppc_spr984_regnum, sim_ppc_spr985_regnum, + sim_ppc_spr986_regnum, sim_ppc_spr987_regnum, + sim_ppc_spr988_regnum, sim_ppc_spr989_regnum, + sim_ppc_spr990_regnum, sim_ppc_spr991_regnum, + sim_ppc_spr992_regnum, sim_ppc_spr993_regnum, + sim_ppc_spr994_regnum, sim_ppc_spr995_regnum, + sim_ppc_spr996_regnum, sim_ppc_spr997_regnum, + sim_ppc_spr998_regnum, sim_ppc_spr999_regnum, + sim_ppc_spr1000_regnum, sim_ppc_spr1001_regnum, + sim_ppc_spr1002_regnum, sim_ppc_spr1003_regnum, + sim_ppc_spr1004_regnum, sim_ppc_spr1005_regnum, + sim_ppc_spr1006_regnum, sim_ppc_spr1007_regnum, + sim_ppc_spr1008_regnum, sim_ppc_spr1009_regnum, + sim_ppc_spr1010_regnum, sim_ppc_spr1011_regnum, + sim_ppc_spr1012_regnum, sim_ppc_spr1013_regnum, + sim_ppc_spr1014_regnum, sim_ppc_spr1015_regnum, + sim_ppc_spr1016_regnum, sim_ppc_spr1017_regnum, + sim_ppc_spr1018_regnum, sim_ppc_spr1019_regnum, + sim_ppc_spr1020_regnum, sim_ppc_spr1021_regnum, + sim_ppc_spr1022_regnum, sim_ppc_spr1023_regnum + }; + + +/* Sizes of various register sets. */ +enum + { + sim_ppc_num_gprs = 32, + sim_ppc_num_fprs = 32, + sim_ppc_num_vrs = 32, + sim_ppc_num_srs = 16, + sim_ppc_num_sprs = 1024, + }; + + +#ifdef __cplusplus +} +#endif + +#endif /* SIM_PPC_H */ diff --git a/include/opcode/crx.h b/include/opcode/crx.h new file mode 100644 index 00000000000..1e0d5733ab3 --- /dev/null +++ b/include/opcode/crx.h @@ -0,0 +1,395 @@ +/* crx.h -- Header file for CRX opcode and register tables. + Copyright 2004 Free Software Foundation, Inc. + Contributed by Tomer Levi, NSC, Israel. + Originally written for GAS 2.12 by Tomer Levi, NSC, Israel. + Updates, BFDizing, GNUifying and ELF support by Tomer Levi. + + This file is part of GAS, GDB and the GNU binutils. + + GAS, GDB, and GNU binutils is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at your + option) any later version. + + GAS, GDB, and GNU binutils are distributed in the hope that they will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifndef _CRX_H_ +#define _CRX_H_ + +/* CRX core/debug Registers : + The enums are used as indices to CRX registers table (crx_regtab). + Therefore, order MUST be preserved. */ + +typedef enum + { + /* 32-bit general purpose registers. */ + r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, + r10, r11, r12, r13, r14, r15, ra, sp, + /* 32-bit user registers. */ + u0, u1, u2, u3, u4, u5, u6, u7, u8, u9, + u10, u11, u12, u13, u14, u15, ura, usp, + /* hi and lo registers. */ + hi, lo, + /* hi and lo user registers. */ + uhi, ulo, + /* Processor Status Register. */ + psr, + /* Configuration Register. */ + cfg, + /* Coprocessor Configuration Register. */ + cpcfg, + /* Cashe Configuration Register. */ + ccfg, + /* Interrupt Base Register. */ + intbase, + /* Interrupt Stack Pointer Register. */ + isp, + /* Coprocessor Enable Register. */ + cen, + /* Program Counter Register. */ + pc, + /* Not a register. */ + nullregister, + MAX_REG + } +reg; + +/* CRX Coprocessor registers and special registers : + The enums are used as indices to CRX coprocessor registers table + (crx_copregtab). Therefore, order MUST be preserved. */ + +typedef enum + { + /* Coprocessor registers. */ + c0 = MAX_REG, c1, c2, c3, c4, c5, c6, c7, c8, + c9, c10, c11, c12, c13, c14, c15, + /* Coprocessor special registers. */ + cs0, cs1 ,cs2, cs3, cs4, cs5, cs6, cs7, cs8, + cs9, cs10, cs11, cs12, cs13, cs14, cs15, + /* Not a Coprocessor register. */ + nullcopregister, + MAX_COPREG + } +copreg; + +/* CRX Register types. */ + +typedef enum + { + CRX_PC_REGTYPE, /* pc type */ + CRX_R_REGTYPE, /* r */ + CRX_U_REGTYPE, /* u */ + CRX_C_REGTYPE, /* c */ + CRX_CS_REGTYPE, /* cs */ + CRX_MTPR_REGTYPE, /* mtpr */ + CRX_CFG_REGTYPE /* *hi|lo, *cfg, psr */ + } +reg_type; + +/* CRX argument types : + The argument types correspond to instructions operands + + Argument types : + r - register + c - constant + d - displacement + ic - immediate + icr - index register + rbase - register base + s - star ('*') + copr - coprocessor register + copsr - coprocessor special register. */ + +typedef enum + { + arg_r, arg_c, arg_cr, arg_dc, arg_dcr, arg_sc, + arg_ic, arg_icr, arg_rbase, arg_copr, arg_copsr, + /* Not an argument. */ + nullargs + } +argtype; + +/* CRX operand types : + The operand types correspond to instructions operands + + Operand Types : + cst4 - 4-bit encoded constant + iN - N-bit immediate field + d, dispsN - N-bit immediate signed displacement + dispuN - N-bit immediate unsigned displacement + absN - N-bit absolute address + rbase - 4-bit genaral-purpose register specifier + regr - 4-bit genaral-purpose register specifier + regr8 - 8-bit register address space + copregr - coprocessor register + copsregr - coprocessor special register + scl2 - 2-bit scaling factor for memory index + ridx - register index. */ + +typedef enum + { + dummy, cst4, disps9, + i3, i4, i5, i8, i12, i16, i32, + d5, d9, d17, d25, d33, + abs16, abs32, + rbase, rbase_cst4, + rbase_dispu8, rbase_dispu12, rbase_dispu16, rbase_dispu28, rbase_dispu32, + rbase_ridx_scl2_dispu6, rbase_ridx_scl2_dispu22, + regr, regr8, copregr,copregr8,copsregr, + /* Not an operand. */ + nulloperand, + /* Maximum supported operand. */ + MAX_OPRD + } +operand_type; + +/* CRX instruction types. */ + +#define ARITH_INS 1 +#define LD_STOR_INS 2 +#define BRANCH_INS 3 +#define ARITH_BYTE_INS 4 +#define CMPBR_INS 5 +#define SHIFT_INS 6 +#define BRANCH_NEQ_INS 7 +#define LD_STOR_INS_INC 8 +#define STOR_IMM_INS 9 +#define CSTBIT_INS 10 +#define SYS_INS 11 +#define JMP_INS 12 +#define MUL_INS 13 +#define DIV_INS 14 +#define COP_BRANCH_INS 15 +#define COP_REG_INS 16 +#define DCR_BRANCH_INS 17 +#define MMC_INS 18 +#define MMU_INS 19 + +/* Maximum value supported for instruction types. */ +#define CRX_INS_MAX (1 << 5) +/* Mask to record an instruction type. */ +#define CRX_INS_MASK (CRX_INS_MAX - 1) +/* Return instruction type, given instruction's attributes. */ +#define CRX_INS_TYPE(attr) ((attr) & CRX_INS_MASK) + +/* Indicates whether this instruction has a register list as parameter. */ +#define REG_LIST CRX_INS_MAX +/* The operands in binary and assembly are placed in reverse order. + load - (REVERSE_MATCH)/store - (! REVERSE_MATCH). */ +#define REVERSE_MATCH (REG_LIST << 1) + +/* Kind of displacement map used DISPU[BWD]4. */ +#define DISPUB4 (REVERSE_MATCH << 1) +#define DISPUW4 (DISPUB4 << 1) +#define DISPUD4 (DISPUW4 << 1) +#define CST4MAP (DISPUB4 | DISPUW4 | DISPUD4) + +/* Printing formats, where the instruction prefix isn't consecutive. */ +#define FMT_1 (DISPUD4 << 1) /* 0xF0F00000 */ +#define FMT_2 (FMT_1 << 1) /* 0xFFF0FF00 */ +#define FMT_3 (FMT_2 << 1) /* 0xFFF00F00 */ +#define FMT_4 (FMT_3 << 1) /* 0xFFF0F000 */ +#define FMT_5 (FMT_4 << 1) /* 0xFFF0FFF0 */ +#define FMT_CRX (FMT_1 | FMT_2 | FMT_3 | FMT_4 | FMT_5) + +#define RELAXABLE (FMT_5 << 1) + +/* Maximum operands per instruction. */ +#define MAX_OPERANDS 5 +/* Maximum words per instruction. */ +#define MAX_WORDS 3 +/* Maximum register name length. */ +#define MAX_REGNAME_LEN 10 +/* Maximum instruction length. */ +#define MAX_INST_LEN 256 + +/* Single operand description. */ + +typedef struct + { + /* Operand type. */ + operand_type op_type; + /* Operand location within the opcode. */ + unsigned int shift; + } +operand_desc; + +/* Instruction data structure used in instruction table. */ + +typedef struct + { + /* Name. */ + const char *mnemonic; + /* Size (in words). */ + unsigned int size; + /* Constant prefix (matched by the disassembler). */ + unsigned long match; + /* Match size (in bits). */ + int match_bits; + /* Attributes. */ + unsigned int flags; + /* Operands (always last, so unreferenced operands are initialized). */ + operand_desc operands[MAX_OPERANDS]; + } +inst; + +/* Data structure for a single instruction's arguments (Operands). */ + +typedef struct + { + /* Register or base register. */ + reg r; + /* Index register. */ + reg i_r; + /* Coprocessor register. */ + copreg cr; + /* Constant/immediate/absolute value. */ + unsigned long int constant; + /* Scaled index mode. */ + unsigned int scale; + /* Argument type. */ + argtype type; + /* Size of the argument (in bits) required to represent. */ + int size; + /* Indicates whether a constant is positive or negative. */ + int signflag; + } +argument; + +/* Internal structure to hold the various entities + corresponding to the current assembling instruction. */ + +typedef struct + { + /* Number of arguments. */ + int nargs; + /* The argument data structure for storing args (operands). */ + argument arg[MAX_OPERANDS]; +/* The following fields are required only by CRX-assembler. */ +#ifdef TC_CRX + /* Expression used for setting the fixups (if any). */ + expressionS exp; + bfd_reloc_code_real_type rtype; +#endif /* TC_CRX */ + /* Instruction size (in bytes). */ + int size; + } +ins; + +/* Structure to hold information about predefined operands. */ + +typedef struct + { + /* Size (in bits). */ + unsigned int bit_size; + /* Argument type. */ + argtype arg_type; + } +operand_entry; + +/* Structure to hold trap handler information. */ + +typedef struct + { + /* Trap name. */ + char *name; + /* Index in dispatch table. */ + unsigned int entry; + } +trap_entry; + +/* Structure to hold information about predefined registers. */ + +typedef struct + { + /* Name (string representation). */ + char *name; + /* Value (enum representation). */ + union + { + /* Register. */ + reg reg_val; + /* Coprocessor register. */ + copreg copreg_val; + } value; + /* Register image. */ + int image; + /* Register type. */ + reg_type type; + } +reg_entry; + +/* Structure to hold a cst4 operand mapping. */ + +typedef struct + { + /* The binary value which is written to the object file. */ + int binary; + /* The value which is mapped. */ + int value; + } +cst4_entry; + +/* CRX opcode table. */ +extern const inst crx_instruction[]; +extern const int crx_num_opcodes; +#define NUMOPCODES crx_num_opcodes + +/* CRX operands table. */ +extern const operand_entry crx_optab[]; + +/* CRX registers table. */ +extern const reg_entry crx_regtab[]; +extern const int crx_num_regs; +#define NUMREGS crx_num_regs + +/* CRX coprocessor registers table. */ +extern const reg_entry crx_copregtab[]; +extern const int crx_num_copregs; +#define NUMCOPREGS crx_num_copregs + +/* CRX trap/interrupt table. */ +extern const trap_entry crx_traps[]; +extern const int crx_num_traps; +#define NUMTRAPS crx_num_traps + +/* cst4 operand mapping. */ +extern const cst4_entry cst4_map[]; +extern const int cst4_maps; + +/* Current instruction we're assembling. */ +extern const inst *instruction; + +/* A macro for representing the instruction "constant" opcode, that is, + the FIXED part of the instruction. The "constant" opcode is represented + as a 32-bit unsigned long, where OPC is expanded (by a left SHIFT) + over that range. */ +#define BIN(OPC,SHIFT) (OPC << SHIFT) + +/* Is the current instruction type is TYPE ? */ +#define IS_INSN_TYPE(TYPE) \ + (CRX_INS_TYPE(instruction->flags) == TYPE) + +/* Is the current instruction mnemonic is MNEMONIC ? */ +#define IS_INSN_MNEMONIC(MNEMONIC) \ + (strcmp(instruction->mnemonic,MNEMONIC) == 0) + +/* Does the current instruction has register list ? */ +#define INST_HAS_REG_LIST \ + (instruction->flags & REG_LIST) + +/* Long long type handling. */ +/* Replace all appearances of 'long long int' with LONGLONG. */ +typedef long long int LONGLONG; +typedef unsigned long long ULONGLONG; +/* A mask for the upper 31 bits of a 64 bits type. */ +#define UPPER31_MASK 0xFFFFFFFE00000000LL + +#endif /* _CRX_H_ */ diff --git a/opcodes/crx-dis.c b/opcodes/crx-dis.c new file mode 100644 index 00000000000..5796a2ef08a --- /dev/null +++ b/opcodes/crx-dis.c @@ -0,0 +1,700 @@ +/* Disassembler code for CRX. + Copyright 2004 Free Software Foundation, Inc. + Contributed by Tomer Levi, NSC, Israel. + Written by Tomer Levi. + + This file is part of the GNU binutils and GDB, the GNU debugger. + + This program is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free + Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include "dis-asm.h" +#include "sysdep.h" +#include "opcode/crx.h" + +/* String to print when opcode was not matched. */ +#define ILLEGAL "illegal" + /* Escape to 16-bit immediate. */ +#define ESCAPE_16_BIT 0xE + +/* Extract 'n_bits' from 'a' starting from offset 'offs'. */ +#define EXTRACT(a, offs, n_bits) \ + (n_bits == 32 ? (((a) >> (offs)) & ~0L) \ + : (((a) >> (offs)) & ((1 << (n_bits)) -1))) + +/* Set Bit Mask - a mask to set all bits starting from offset 'offs'. */ +#define SBM(offs) ((((1 << (32 - offs)) -1) << (offs))) + +typedef unsigned long dwordU; +typedef unsigned short wordU; + +typedef struct +{ + dwordU val; + int nbits; +} parameter; + +/* Structure to hold valid 'cinv' instruction options. */ + +typedef struct + { + /* Cinv printed string. */ + char *str; + /* Value corresponding to the string. */ + unsigned int value; + } +cinv_entry; + +/* CRX 'cinv' options. */ +const cinv_entry crx_cinvs[] = +{ + {"[i]", 2}, {"[i,u]", 3}, {"[d]", 4}, + {"[d,u]", 5}, {"[d,i]", 6}, {"[d,i,u]", 7} +}; + +/* Number of valid 'cinv' instruction options. */ +int NUMCINVS = ((sizeof crx_cinvs)/(sizeof crx_cinvs[0])); +/* Current opcode table entry we're disassembling. */ +const inst *instruction; +/* Current instruction we're disassembling. */ +ins currInsn; +/* The current instruction is read into 3 consecutive words. */ +wordU words[3]; +/* Contains all words in appropriate order. */ +ULONGLONG allWords; +/* Holds the current processed argument number. */ +int processing_argument_number; +/* Nonzero means a CST4 instruction. */ +int cst4flag; +/* Nonzero means the instruction's original size is + incremented (escape sequence is used). */ +int size_changed; + +static int get_number_of_operands (void); +static argtype getargtype (operand_type); +static int getbits (operand_type); +static char *getregname (reg); +static char *getcopregname (copreg, reg_type); +static char * getprocregname (int); +static char *gettrapstring (unsigned); +static char *getcinvstring (unsigned); +static void getregliststring (int, char *, int); +static wordU get_word_at_PC (bfd_vma, struct disassemble_info *); +static void get_words_at_PC (bfd_vma, struct disassemble_info *); +static unsigned long build_mask (void); +static int powerof2 (int); +static int match_opcode (void); +static void make_instruction (void); +static void print_arguments (ins *, struct disassemble_info *); +static void print_arg (argument *, struct disassemble_info *); + +/* Retrieve the number of operands for the current assembled instruction. */ + +static int +get_number_of_operands (void) +{ + int i; + + for (i = 0; instruction->operands[i].op_type && i < MAX_OPERANDS; i++) + ; + + return i; +} + +/* Return the bit size for a given operand. */ + +static int +getbits (operand_type op) +{ + if (op < MAX_OPRD) + return crx_optab[op].bit_size; + else + return 0; +} + +/* Return the argument type of a given operand. */ + +static argtype +getargtype (operand_type op) +{ + if (op < MAX_OPRD) + return crx_optab[op].arg_type; + else + return nullargs; +} + +/* Given the trap index in dispatch table, return its name. + This routine is used when disassembling the 'excp' instruction. */ + +static char * +gettrapstring (unsigned int index) +{ + const trap_entry *trap; + + for (trap = crx_traps; trap < crx_traps + NUMTRAPS; trap++) + if (trap->entry == index) + return trap->name; + + return ILLEGAL; +} + +/* Given a 'cinv' instruction constant operand, return its corresponding string. + This routine is used when disassembling the 'cinv' instruction. */ + +static char * +getcinvstring (unsigned int num) +{ + const cinv_entry *cinv; + + for (cinv = crx_cinvs; cinv < (crx_cinvs + NUMCINVS); cinv++) + if (cinv->value == num) + return cinv->str; + + return ILLEGAL; +} + +/* Given a register enum value, retrieve its name. */ + +char * +getregname (reg r) +{ + const reg_entry *reg = &crx_regtab[r]; + + if (reg->type != CRX_R_REGTYPE) + return ILLEGAL; + else + return reg->name; +} + +/* Given a coprocessor register enum value, retrieve its name. */ + +char * +getcopregname (copreg r, reg_type type) +{ + const reg_entry *reg; + + if (type == CRX_C_REGTYPE) + reg = &crx_copregtab[r]; + else if (type == CRX_CS_REGTYPE) + reg = &crx_copregtab[r+(cs0-c0)]; + else + return ILLEGAL; + + return reg->name; +} + + +/* Getting a processor register name. */ + +static char * +getprocregname (int index) +{ + const reg_entry *r; + + for (r = crx_regtab; r < crx_regtab + NUMREGS; r++) + if (r->image == index) + return r->name; + + return "ILLEGAL REGISTER"; +} + +/* Get the power of two for a given integer. */ + +static int +powerof2 (int x) +{ + int product, i; + + for (i = 0, product = 1; i < x; i++) + product *= 2; + + return product; +} + +/* Transform a register bit mask to a register list. */ + +void +getregliststring (int trap, char *string, int core_cop) +{ + char temp_string[5]; + int i; + + string[0] = '{'; + string[1] = '\0'; + + for (i = 0; i < 16; i++) + { + if (trap & 0x1) + { + if (core_cop) + sprintf (temp_string, "r%d", i); + else + sprintf (temp_string, "c%d", i); + strcat (string, temp_string); + if (trap & 0xfffe) + strcat (string, ","); + } + trap = trap >> 1; + } + + strcat (string, "}"); +} + +/* START and END are relating 'allWords' struct, which is 48 bits size. + + START|--------|END + +---------+---------+---------+---------+ + | | V | A | L | + +---------+---------+---------+---------+ + 0 16 32 48 + words [0] [1] [2] */ + +static parameter +makelongparameter (ULONGLONG val, int start, int end) +{ + parameter p; + + p.val = (dwordU) EXTRACT(val, 48 - end, end - start); + p.nbits = end - start; + return p; +} + +/* Build a mask of the instruction's 'constant' opcode, + based on the instruction's printing flags. */ + +static unsigned long +build_mask (void) +{ + unsigned int print_flags; + unsigned long mask; + + print_flags = instruction->flags & FMT_CRX; + switch (print_flags) + { + case FMT_1: + mask = 0xF0F00000; + break; + case FMT_2: + mask = 0xFFF0FF00; + break; + case FMT_3: + mask = 0xFFF00F00; + break; + case FMT_4: + mask = 0xFFF0F000; + break; + case FMT_5: + mask = 0xFFF0FFF0; + break; + default: + mask = SBM(instruction->match_bits); + break; + } + + return mask; +} + +/* Search for a matching opcode. Return 1 for success, 0 for failure. */ + +static int +match_opcode (void) +{ + unsigned long mask; + + /* The instruction 'constant' opcode doewsn't exceed 32 bits. */ + unsigned long doubleWord = words[1] + (words[0] << 16); + + /* Start searching from end of instruction table. */ + instruction = &crx_instruction[NUMOPCODES - 2]; + + /* Loop over instruction table until a full match is found. */ + while (instruction >= crx_instruction) + { + mask = build_mask (); + if ((doubleWord & mask) == BIN(instruction->match, instruction->match_bits)) + return 1; + else + instruction--; + } + return 0; +} + +/* Set the proper parameter value for different type of arguments. */ + +static void +make_argument (argument * a, int start_bits) +{ + int inst_bit_size, total_size; + parameter p; + + if ((instruction->size == 3) && a->size >= 16) + inst_bit_size = 48; + else + inst_bit_size = 32; + + switch (a->type) + { + case arg_copr: + case arg_copsr: + p = makelongparameter (allWords, inst_bit_size - (start_bits + a->size), + inst_bit_size - start_bits); + a->cr = p.val; + break; + + case arg_r: + p = makelongparameter (allWords, inst_bit_size - (start_bits + a->size), + inst_bit_size - start_bits); + a->r = p.val; + break; + + case arg_ic: + p = makelongparameter (allWords, inst_bit_size - (start_bits + a->size), + inst_bit_size - start_bits); + + if ((p.nbits == 4) && cst4flag) + { + if (IS_INSN_TYPE (CMPBR_INS) && (p.val == ESCAPE_16_BIT)) + { + /* A special case, where the value is actually stored + in the last 4 bits. */ + p = makelongparameter (allWords, 44, 48); + /* The size of the instruction should be incremented. */ + size_changed = 1; + } + + if (p.val == 6) + p.val = -1; + else if (p.val == 13) + p.val = 48; + else if (p.val == 5) + p.val = -4; + else if (p.val == 10) + p.val = 32; + else if (p.val == 11) + p.val = 20; + else if (p.val == 9) + p.val = 16; + } + + a->constant = p.val; + break; + + case arg_icr: + a->scale = 0; + total_size = a->size + 10; /* sizeof(rbase + ridx + scl2) = 10. */ + p = makelongparameter (allWords, inst_bit_size - total_size, + inst_bit_size - (total_size - 4)); + a->r = p.val; + p = makelongparameter (allWords, inst_bit_size - (total_size - 4), + inst_bit_size - (total_size - 8)); + a->i_r = p.val; + p = makelongparameter (allWords, inst_bit_size - (total_size - 8), + inst_bit_size - (total_size - 10)); + a->scale = p.val; + p = makelongparameter (allWords, inst_bit_size - (total_size - 10), + inst_bit_size); + a->constant = p.val; + break; + + case arg_rbase: + p = makelongparameter (allWords, inst_bit_size - (start_bits + 4), + inst_bit_size - start_bits); + a->r = p.val; + break; + + case arg_cr: + if (a->size <= 8) + { + p = makelongparameter (allWords, inst_bit_size - (start_bits + 4), + inst_bit_size - start_bits); + a->r = p.val; + /* Case for opc4 r dispu rbase. */ + p = makelongparameter (allWords, inst_bit_size - (start_bits + 8), + inst_bit_size - (start_bits + 4)); + } + else + { + /* The 'rbase' start_bits is always relative to a 32-bit data type. */ + p = makelongparameter (allWords, 32 - (start_bits + 4), + 32 - start_bits); + a->r = p.val; + p = makelongparameter (allWords, 32 - start_bits, + inst_bit_size); + } + if ((p.nbits == 4) && cst4flag) + { + if (instruction->flags & DISPUW4) + p.val *= 2; + else if (instruction->flags & DISPUD4) + p.val *= 4; + } + a->constant = p.val; + break; + + case arg_c: + p = makelongparameter (allWords, inst_bit_size - (start_bits + a->size), + inst_bit_size - start_bits); + a->constant = p.val; + break; + default: + break; + } +} + +/* Print a single argument. */ + +static void +print_arg (argument *a, struct disassemble_info *info) +{ + LONGLONG longdisp, mask; + char sign_flag; + int op_index = 0; + char string[200]; + PTR stream = info->stream; + fprintf_ftype func = info->fprintf_func; + + switch (a->type) + { + case arg_copr: + func (stream, "%s", getcopregname (a->cr, CRX_C_REGTYPE)); + break; + + case arg_copsr: + func (stream, "%s", getcopregname (a->cr, CRX_CS_REGTYPE)); + break; + + case arg_r: + if (IS_INSN_MNEMONIC ("mtpr") || IS_INSN_MNEMONIC ("mfpr")) + func (stream, "%s", getprocregname (a->r)); + else + func (stream, "%s", getregname (a->r)); + break; + + case arg_ic: + if (IS_INSN_MNEMONIC ("excp")) + func (stream, "%s", gettrapstring (a->constant)); + + else if (IS_INSN_MNEMONIC ("cinv")) + func (stream, "%s", getcinvstring (a->constant)); + + else if (INST_HAS_REG_LIST) + { + if (!IS_INSN_TYPE (COP_REG_INS)) + { + getregliststring (a->constant, string, 1); + func (stream, "%s", string); + } + else + { + /* Check for proper argument number. */ + if (processing_argument_number == 2) + { + getregliststring (a->constant, string, 0); + func (stream, "%s", string); + } + else + func (stream, "$0x%x", a->constant); + } + } + else + func (stream, "$0x%x", a->constant); + break; + + case arg_icr: + func (stream, "0x%x(%s,%s,%d)", a->constant, getregname (a->r), + getregname (a->i_r), powerof2 (a->scale)); + break; + + case arg_rbase: + func (stream, "(%s)", getregname (a->r)); + break; + + case arg_cr: + func (stream, "0x%x(%s)", a->constant, getregname (a->r)); + + if (IS_INSN_TYPE (LD_STOR_INS_INC)) + func (stream, "+"); + break; + + case arg_c: + /* Removed the *2 part as because implicit zeros are no more required. + Have to fix this as this needs a bit of extension in terms of branchins. + Have to add support for cmp and branch instructions. */ + if (IS_INSN_TYPE (BRANCH_INS) || IS_INSN_MNEMONIC ("bal") + || IS_INSN_TYPE (CMPBR_INS) || IS_INSN_TYPE (DCR_BRANCH_INS) + || IS_INSN_TYPE (COP_BRANCH_INS)) + { + func (stream, "%c", '*'); + longdisp = a->constant; + longdisp <<= 1; + sign_flag = '+'; + + switch (a->size) + { + case 8: + case 16: + case 24: + case 32: + mask = ((LONGLONG)1 << a->size) - 1; + if (longdisp & ((LONGLONG)1 << a->size)) + { + sign_flag = '-'; + longdisp = ~(longdisp) + 1; + } + a->constant = (unsigned long int) (longdisp & mask); + break; + default: + func (stream, + "Wrong offset used in branch/bal instruction"); + break; + } + + func (stream, "%c", sign_flag); + } + /* For branch Neq instruction it is 2*offset + 2. */ + if (IS_INSN_TYPE (BRANCH_NEQ_INS)) + a->constant = 2 * a->constant + 2; + if (IS_INSN_TYPE (LD_STOR_INS_INC) + || IS_INSN_TYPE (LD_STOR_INS) + || IS_INSN_TYPE (STOR_IMM_INS) + || IS_INSN_TYPE (CSTBIT_INS)) + { + op_index = instruction->flags & REVERSE_MATCH ? 0 : 1; + if (instruction->operands[op_index].op_type == abs16) + a->constant |= 0xFFFF0000; + } + func (stream, "0x%x", a->constant); + break; + default: + break; + } +} + +/* Print all the arguments of CURRINSN instruction. */ + +static void +print_arguments (ins *currInsn, struct disassemble_info *info) +{ + int i; + + for (i = 0; i < currInsn->nargs; i++) + { + processing_argument_number = i; + + print_arg (&currInsn->arg[i], info); + + if (i != currInsn->nargs - 1) + info->fprintf_func (info->stream, ", "); + } +} + +/* Build the instruction's arguments. */ + +static void +make_instruction (void) +{ + int i; + unsigned int temp_value, shift; + argument a; + + for (i = 0; i < currInsn.nargs; i++) + { + a.type = getargtype (instruction->operands[i].op_type); + if (instruction->operands[i].op_type == cst4 + || instruction->operands[i].op_type == rbase_cst4) + cst4flag = 1; + a.size = getbits (instruction->operands[i].op_type); + shift = instruction->operands[i].shift; + + make_argument (&a, shift); + currInsn.arg[i] = a; + } + + /* Calculate instruction size (in bytes). */ + currInsn.size = instruction->size + (size_changed ? 1 : 0); + currInsn.size *= 2; + + /* Swapping first and second arguments. */ + if (IS_INSN_TYPE (COP_BRANCH_INS)) + { + temp_value = currInsn.arg[0].constant; + currInsn.arg[0].constant = currInsn.arg[1].constant; + currInsn.arg[1].constant = temp_value; + } +} + +/* Retrieve a single word from a given memory address. */ + +static wordU +get_word_at_PC (bfd_vma memaddr, struct disassemble_info *info) +{ + bfd_byte buffer[4]; + int status; + wordU insn = 0; + + status = info->read_memory_func (memaddr, buffer, 2, info); + + if (status == 0) + insn = (wordU) bfd_getl16 (buffer); + + return insn; +} + +/* Retrieve multiple words (3) from a given memory address. */ + +static void +get_words_at_PC (bfd_vma memaddr, struct disassemble_info *info) +{ + int i; + bfd_vma mem; + + for (i = 0, mem = memaddr; i < 3; i++, mem += 2) + words[i] = get_word_at_PC (mem, info); + + allWords = + ((ULONGLONG) words[0] << 32) + ((unsigned long) words[1] << 16) + words[2]; +} + +/* Prints the instruction by calling print_arguments after proper matching. */ + +int +print_insn_crx (memaddr, info) + bfd_vma memaddr; + struct disassemble_info *info; +{ + int is_decoded; /* Nonzero means instruction has a match. */ + + /* Initialize global variables. */ + cst4flag = 0; + size_changed = 0; + + /* Retrieve the encoding from current memory location. */ + get_words_at_PC (memaddr, info); + /* Find a matching opcode in table. */ + is_decoded = match_opcode (); + /* If found, print the instruction's mnemonic and arguments. */ + if (is_decoded > 0 && (words[0] << 16 || words[1]) != 0) + { + info->fprintf_func (info->stream, "%s", instruction->mnemonic); + if ((currInsn.nargs = get_number_of_operands ()) != 0) + info->fprintf_func (info->stream, "\t"); + make_instruction (); + print_arguments (&currInsn, info); + return currInsn.size; + } + + /* No match found. */ + info->fprintf_func (info->stream,"%s ",ILLEGAL); + return 2; +} diff --git a/opcodes/crx-opc.c b/opcodes/crx-opc.c new file mode 100644 index 00000000000..b01addfa525 --- /dev/null +++ b/opcodes/crx-opc.c @@ -0,0 +1,675 @@ +/* crx-opc.c -- Table of opcodes for the CRX processor. + Copyright 2004 Free Software Foundation, Inc. + Contributed by Tomer Levi NSC, Israel. + Originally written for GAS 2.12 by Tomer Levi. + + This file is part of GAS, GDB and the GNU binutils. + + GAS, GDB, and GNU binutils is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at your + option) any later version. + + GAS, GDB, and GNU binutils are distributed in the hope that they will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include +#include "libiberty.h" +#include "symcat.h" +#include "opcode/crx.h" + +const inst crx_instruction[] = +{ +/* Create an arithmetic instruction - INST[bw]. */ +#define ARITH_BYTE_INST(NAME, OPC) \ + /* opc8 cst4 r */ \ + {NAME, 1, OPC, 24, ARITH_BYTE_INS, {{cst4,20}, {regr,16}}}, \ + /* opc8 i16 r */ \ + {NAME, 2, (OPC<<4)+0xE, 20, ARITH_BYTE_INS, {{i16,0}, {regr,16}}}, \ + /* opc8 r r */ \ + {NAME, 1, OPC+0x40, 24, ARITH_BYTE_INS, {{regr,20}, {regr,16}}} + + ARITH_BYTE_INST ("addub", 0x0), + ARITH_BYTE_INST ("addb", 0x1), + ARITH_BYTE_INST ("addcb", 0x2), + ARITH_BYTE_INST ("andb", 0x3), + ARITH_BYTE_INST ("cmpb", 0x4), + ARITH_BYTE_INST ("movb", 0x5), + ARITH_BYTE_INST ("orb", 0x6), + ARITH_BYTE_INST ("subb", 0x7), + ARITH_BYTE_INST ("subcb", 0x8), + ARITH_BYTE_INST ("xorb", 0x9), + ARITH_BYTE_INST ("mulb", 0xA), + + ARITH_BYTE_INST ("adduw", 0x10), + ARITH_BYTE_INST ("addw", 0x11), + ARITH_BYTE_INST ("addcw", 0x12), + ARITH_BYTE_INST ("andw", 0x13), + ARITH_BYTE_INST ("cmpw", 0x14), + ARITH_BYTE_INST ("movw", 0x15), + ARITH_BYTE_INST ("orw", 0x16), + ARITH_BYTE_INST ("subw", 0x17), + ARITH_BYTE_INST ("subcw", 0x18), + ARITH_BYTE_INST ("xorw", 0x19), + ARITH_BYTE_INST ("mulw", 0x1A), + +/* Create an arithmetic instruction - INST[d]. */ +#define ARITH_INST(NAME, OPC) \ + /* opc8 cst4 r */ \ + {NAME, 1, OPC, 24, ARITH_INS, {{cst4,20}, {regr,16}}}, \ + /* opc8 i16 r */ \ + {NAME, 2, (OPC<<4)+0xE, 20, ARITH_INS, {{i16,0}, {regr,16}}}, \ + /* opc8 i32 r */ \ + {NAME, 3, (OPC<<4)+0xF, 20, ARITH_INS, {{i32,0}, {regr,16}}}, \ + /* opc8 r r */ \ + {NAME, 1, OPC+0x40, 24, ARITH_INS, {{regr,20}, {regr,16}}} + + ARITH_INST ("addud", 0x20), + ARITH_INST ("addd", 0x21), + ARITH_INST ("addcd", 0x22), + ARITH_INST ("andd", 0x23), + ARITH_INST ("cmpd", 0x24), + ARITH_INST ("movd", 0x25), + ARITH_INST ("ord", 0x26), + ARITH_INST ("subd", 0x27), + ARITH_INST ("subcd", 0x28), + ARITH_INST ("xord", 0x29), + ARITH_INST ("muld", 0x2A), + +/* Create a shift instruction. */ +#define SHIFT_INST(NAME, OPRD, OPC1, SHIFT1, OPC2) \ + /* OPRD=i3 -->> opc9 i3 r */ \ + /* OPRD=i4 -->> opc8 i4 r */ \ + /* OPRD=i5 -->> opc7 i5 r */ \ + {NAME, 1, OPC1, SHIFT1, SHIFT_INS, {{OPRD,20}, {regr,16}}}, \ + /* opc8 r r */ \ + {NAME, 1, OPC2, 24, SHIFT_INS, {{regr,20}, {regr,16}}} + + SHIFT_INST ("sllb", i3, 0x1F8, 23, 0x4D), + SHIFT_INST ("srlb", i3, 0x1F9, 23, 0x4E), + SHIFT_INST ("srab", i3, 0x1FA, 23, 0x4F), + + SHIFT_INST ("sllw", i4, 0xB6, 24, 0x5D), + SHIFT_INST ("srlw", i4, 0xB7, 24, 0x5E), + SHIFT_INST ("sraw", i4, 0xB8, 24, 0x5F), + + SHIFT_INST ("slld", i5, 0x78, 25, 0x6D), + SHIFT_INST ("srld", i5, 0x79, 25, 0x6E), + SHIFT_INST ("srad", i5, 0x7A, 25, 0x6F), + +/* Create a conditional branch instruction. */ +#define BRANCH_INST(NAME, OPC) \ + /* opc4 c4 dispe9 */ \ + {NAME, 1, OPC, 24, BRANCH_INS | RELAXABLE, {{d9,16}}}, \ + /* opc4 c4 disps17 */ \ + {NAME, 2, (OPC<<8)+0x7E, 16, BRANCH_INS | RELAXABLE, {{d17,0}}}, \ + /* opc4 c4 disps33 */ \ + {NAME, 3, (OPC<<8)+0x7F, 16, BRANCH_INS | RELAXABLE, {{d33,0}}} + + BRANCH_INST ("beq", 0x70), + BRANCH_INST ("bne", 0x71), + BRANCH_INST ("bcs", 0x72), + BRANCH_INST ("bcc", 0x73), + BRANCH_INST ("bhi", 0x74), + BRANCH_INST ("bls", 0x75), + BRANCH_INST ("bgt", 0x76), + BRANCH_INST ("ble", 0x77), + BRANCH_INST ("bfs", 0x78), + BRANCH_INST ("bfc", 0x79), + BRANCH_INST ("blo", 0x7A), + BRANCH_INST ("bhs", 0x7B), + BRANCH_INST ("blt", 0x7C), + BRANCH_INST ("bge", 0x7D), + BRANCH_INST ("br", 0x7E), + +/* Create a 'Branch if Equal to 0' instruction. */ +#define BRANCH_NEQ_INST(NAME, OPC) \ + /* opc8 dispu5 r */ \ + {NAME, 1, OPC, 24, BRANCH_NEQ_INS, {{regr,16}, {d5,20}}} + + BRANCH_NEQ_INST ("beq0b", 0xB0), + BRANCH_NEQ_INST ("bne0b", 0xB1), + BRANCH_NEQ_INST ("beq0w", 0xB2), + BRANCH_NEQ_INST ("bne0w", 0xB3), + BRANCH_NEQ_INST ("beq0d", 0xB4), + BRANCH_NEQ_INST ("bne0d", 0xB5), + +/* Create instruction with no operands. */ +#define NO_OP_INST(NAME, OPC) \ + /* opc16 */ \ + {NAME, 1, OPC, 16, 0, {{0, 0}}} + + NO_OP_INST ("nop", 0x3002), + NO_OP_INST ("retx", 0x3003), + NO_OP_INST ("di", 0x3004), + NO_OP_INST ("ei", 0x3005), + NO_OP_INST ("wait", 0x3006), + NO_OP_INST ("eiwait", 0x3007), + +/* Create a 'Compare & Branch' instruction. */ +#define CMPBR_INST(NAME, OPC1, OPC2, C4) \ + /* opc12 r r c4 disps9 */ \ + {NAME, 2, ((0x300+OPC1)<<12)+C4, 8, CMPBR_INS | FMT_3 | RELAXABLE, {{regr,16}, {regr,12}, {d9,0}}}, \ + /* opc12 r r c4 disps25 */ \ + {NAME, 3, ((0x310+OPC1)<<12)+C4, 8, CMPBR_INS | FMT_3 | RELAXABLE, {{regr,16}, {regr,12}, {d25,0}}}, \ + /* opc12 i4cst4 r c4 disps9 */ \ + {NAME, 2, ((0x300+OPC2)<<12)+C4, 8, CMPBR_INS | FMT_3 | RELAXABLE, {{cst4,16}, {regr,12}, {d9,0}}}, \ + /* opc12 i4cst4 r c4 disps25 */ \ + {NAME, 3, ((0x310+OPC2)<<12)+C4, 8, CMPBR_INS | FMT_3 | RELAXABLE, {{cst4,16}, {regr,12}, {d25,0}}} + + CMPBR_INST ("cmpbeqb", 0x8, 0xC, 0x0), + CMPBR_INST ("cmpbneb", 0x8, 0xC, 0x1), + CMPBR_INST ("cmpbhib", 0x8, 0xC, 0x4), + CMPBR_INST ("cmpblsb", 0x8, 0xC, 0x5), + CMPBR_INST ("cmpbgtb", 0x8, 0xC, 0x6), + CMPBR_INST ("cmpbleb", 0x8, 0xC, 0x7), + CMPBR_INST ("cmpblob", 0x8, 0xC, 0xA), + CMPBR_INST ("cmpbhsb", 0x8, 0xC, 0xB), + CMPBR_INST ("cmpbltb", 0x8, 0xC, 0xC), + CMPBR_INST ("cmpbgeb", 0x8, 0xC, 0xD), + + CMPBR_INST ("cmpbeqw", 0x9, 0xD, 0x0), + CMPBR_INST ("cmpbnew", 0x9, 0xD, 0x1), + CMPBR_INST ("cmpbhiw", 0x9, 0xD, 0x4), + CMPBR_INST ("cmpblsw", 0x9, 0xD, 0x5), + CMPBR_INST ("cmpbgtw", 0x9, 0xD, 0x6), + CMPBR_INST ("cmpblew", 0x9, 0xD, 0x7), + CMPBR_INST ("cmpblow", 0x9, 0xD, 0xA), + CMPBR_INST ("cmpbhsw", 0x9, 0xD, 0xB), + CMPBR_INST ("cmpbltw", 0x9, 0xD, 0xC), + CMPBR_INST ("cmpbgew", 0x9, 0xD, 0xD), + + CMPBR_INST ("cmpbeqd", 0xA, 0xE, 0x0), + CMPBR_INST ("cmpbned", 0xA, 0xE, 0x1), + CMPBR_INST ("cmpbhid", 0xA, 0xE, 0x4), + CMPBR_INST ("cmpblsd", 0xA, 0xE, 0x5), + CMPBR_INST ("cmpbgtd", 0xA, 0xE, 0x6), + CMPBR_INST ("cmpbled", 0xA, 0xE, 0x7), + CMPBR_INST ("cmpblod", 0xA, 0xE, 0xA), + CMPBR_INST ("cmpbhsd", 0xA, 0xE, 0xB), + CMPBR_INST ("cmpbltd", 0xA, 0xE, 0xC), + CMPBR_INST ("cmpbged", 0xA, 0xE, 0xD), + +/* Create an instruction using a single register operand. */ +#define REG1_INST(NAME, OPC) \ + /* opc8 c4 r */ \ + {NAME, 1, OPC, 20, 0, {{regr,16}}} + + /* JCond instructions */ + REG1_INST ("jeq", 0xBA0), + REG1_INST ("jne", 0xBA1), + REG1_INST ("jcs", 0xBA2), + REG1_INST ("jcc", 0xBA3), + REG1_INST ("jhi", 0xBA4), + REG1_INST ("jls", 0xBA5), + REG1_INST ("jgt", 0xBA6), + REG1_INST ("jle", 0xBA7), + REG1_INST ("jfs", 0xBA8), + REG1_INST ("jfc", 0xBA9), + REG1_INST ("jlo", 0xBAA), + REG1_INST ("jhs", 0xBAB), + REG1_INST ("jlt", 0xBAC), + REG1_INST ("jge", 0xBAD), + REG1_INST ("jump", 0xBAE), + + /* SCond instructions */ + REG1_INST ("seq", 0xBB0), + REG1_INST ("sne", 0xBB1), + REG1_INST ("scs", 0xBB2), + REG1_INST ("scc", 0xBB3), + REG1_INST ("shi", 0xBB4), + REG1_INST ("sls", 0xBB5), + REG1_INST ("sgt", 0xBB6), + REG1_INST ("sle", 0xBB7), + REG1_INST ("sfs", 0xBB8), + REG1_INST ("sfc", 0xBB9), + REG1_INST ("slo", 0xBBA), + REG1_INST ("shs", 0xBBB), + REG1_INST ("slt", 0xBBC), + REG1_INST ("sge", 0xBBD), + +/* Create an instruction using two register operands. */ +#define REG2_INST(NAME, OPC) \ + /* opc24 r r OR opc20 c4 r r */ \ + {NAME, 2, 0x300800+OPC, 8, 0, {{regr,4}, {regr,0}}} + + /* MULTIPLY INSTRUCTIONS */ + REG2_INST ("macsb", 0x40), + REG2_INST ("macub", 0x41), + REG2_INST ("macqb", 0x42), + + REG2_INST ("macsw", 0x50), + REG2_INST ("macuw", 0x51), + REG2_INST ("macqw", 0x52), + + REG2_INST ("macsd", 0x60), + REG2_INST ("macud", 0x61), + REG2_INST ("macqd", 0x62), + + REG2_INST ("mullsd", 0x65), + REG2_INST ("mullud", 0x66), + + REG2_INST ("mulsbw", 0x3B), + REG2_INST ("mulubw", 0x3C), + REG2_INST ("mulswd", 0x3D), + REG2_INST ("muluwd", 0x3E), + + /* SIGNEXTEND STUFF */ + REG2_INST ("sextbw", 0x30), + REG2_INST ("sextbd", 0x31), + REG2_INST ("sextwd", 0x32), + REG2_INST ("zextbw", 0x34), + REG2_INST ("zextbd", 0x35), + REG2_INST ("zextwd", 0x36), + + REG2_INST ("bswap", 0x3F), + + REG2_INST ("maxsb", 0x80), + REG2_INST ("minsb", 0x81), + REG2_INST ("maxub", 0x82), + REG2_INST ("minub", 0x83), + REG2_INST ("absb", 0x84), + REG2_INST ("negb", 0x85), + REG2_INST ("cntl0b", 0x86), + REG2_INST ("cntl1b", 0x87), + REG2_INST ("popcntb",0x88), + REG2_INST ("rotlb", 0x89), + REG2_INST ("rotrb", 0x8A), + REG2_INST ("mulqb", 0x8B), + REG2_INST ("addqb", 0x8C), + REG2_INST ("subqb", 0x8D), + REG2_INST ("cntlsb", 0x8E), + + REG2_INST ("maxsw", 0x90), + REG2_INST ("minsw", 0x91), + REG2_INST ("maxuw", 0x92), + REG2_INST ("minuw", 0x93), + REG2_INST ("absw", 0x94), + REG2_INST ("negw", 0x95), + REG2_INST ("cntl0w", 0x96), + REG2_INST ("cntl1w", 0x97), + REG2_INST ("popcntw",0x98), + REG2_INST ("rotlw", 0x99), + REG2_INST ("rotrw", 0x9A), + REG2_INST ("mulqw", 0x9B), + REG2_INST ("addqw", 0x9C), + REG2_INST ("subqw", 0x9D), + REG2_INST ("cntlsw", 0x9E), + + REG2_INST ("maxsd", 0xA0), + REG2_INST ("minsd", 0xA1), + REG2_INST ("maxud", 0xA2), + REG2_INST ("minud", 0xA3), + REG2_INST ("absd", 0xA4), + REG2_INST ("negd", 0xA5), + REG2_INST ("cntl0d", 0xA6), + REG2_INST ("cntl1d", 0xA7), + REG2_INST ("popcntd",0xA8), + REG2_INST ("rotld", 0xA9), + REG2_INST ("rotrd", 0xAA), + REG2_INST ("mulqd", 0xAB), + REG2_INST ("addqd", 0xAC), + REG2_INST ("subqd", 0xAD), + REG2_INST ("cntlsd", 0xAE), + +/* Conditional move instructions */ + REG2_INST ("cmoveqd", 0x70), + REG2_INST ("cmovned", 0x71), + REG2_INST ("cmovcsd", 0x72), + REG2_INST ("cmovccd", 0x73), + REG2_INST ("cmovhid", 0x74), + REG2_INST ("cmovlsd", 0x75), + REG2_INST ("cmovgtd", 0x76), + REG2_INST ("cmovled", 0x77), + REG2_INST ("cmovfsd", 0x78), + REG2_INST ("cmovfcd", 0x79), + REG2_INST ("cmovlod", 0x7A), + REG2_INST ("cmovhsd", 0x7B), + REG2_INST ("cmovltd", 0x7C), + REG2_INST ("cmovged", 0x7D), + +/* Load instructions (from memory to register). */ +#define LD_REG_INST(NAME, OPC1, OPC2, DISP) \ + /* opc12 r abs16 */ \ + {NAME, 2, 0x320+OPC1, 20, LD_STOR_INS | REVERSE_MATCH, {{abs16,0}, {regr,16}}}, \ + /* opc12 r abs32 */ \ + {NAME, 3, 0x330+OPC1, 20, LD_STOR_INS | REVERSE_MATCH, {{abs32,0}, {regr,16}}}, \ + /* opc4 r c4 rbase */ \ + {NAME, 1, ((0x8+OPC2)<<8), 20, LD_STOR_INS | DISP | FMT_1 | REVERSE_MATCH, {{rbase,20}, {regr,24}}},\ + /* opc4 r rbase dispu[bwd]4 */ \ + {NAME, 1, 0x8+OPC2, 28, LD_STOR_INS | DISP | REVERSE_MATCH, {{rbase_cst4,16}, {regr,24}}}, \ + /* opc4 r rbase disps16 */ \ + {NAME, 2, ((0x8+OPC2)<<8)+0xE, 20, LD_STOR_INS | DISP | FMT_1 | REVERSE_MATCH, {{rbase_dispu16,16}, {regr,24}}}, \ + /* opc4 r rbase disps32 */ \ + {NAME, 3, ((0x8+OPC2)<<8)+0xF, 20, LD_STOR_INS | FMT_1 | REVERSE_MATCH, {{rbase_dispu32,16}, {regr,24}}}, \ + /* opc12 r rbase */ \ + {NAME, 2, 0x328+OPC1, 20, LD_STOR_INS_INC | REVERSE_MATCH, {{rbase,12}, {regr,16}}}, \ + /* opc12 r rbase disps12 */ \ + {NAME, 2, 0x328+OPC1, 20, LD_STOR_INS_INC | REVERSE_MATCH, {{rbase_dispu12,12}, {regr,16}}}, \ + /* opc12 r rbase ridx scl2 disps6 */ \ + {NAME, 2, 0x32C+OPC1, 20, LD_STOR_INS | REVERSE_MATCH, {{rbase_ridx_scl2_dispu6,0}, {regr,16}}}, \ + /* opc12 r rbase ridx scl2 disps22 */ \ + {NAME, 3, 0x33C+OPC1, 20, LD_STOR_INS | REVERSE_MATCH, {{rbase_ridx_scl2_dispu22,0}, {regr,16}}} + + LD_REG_INST ("loadb", 0x0, 0x0, DISPUB4), + LD_REG_INST ("loadw", 0x1, 0x1, DISPUW4), + LD_REG_INST ("loadd", 0x2, 0x2, DISPUD4), + +/* Store instructions (from Register to Memory). */ +#define ST_REG_INST(NAME, OPC1, OPC2, DISP) \ + /* opc12 r abs16 */ \ + {NAME, 2, 0x320+OPC1, 20, LD_STOR_INS, {{regr,16}, {abs16,0}}}, \ + /* opc12 r abs32 */ \ + {NAME, 3, 0x330+OPC1, 20, LD_STOR_INS, {{regr,16}, {abs32,0}}}, \ + /* opc4 r c4 rbase */ \ + {NAME, 1, ((0x8+OPC2)<<8), 20, LD_STOR_INS | DISP | FMT_1, {{regr,24}, {rbase,20}}},\ + /* opc4 r rbase dispu[bwd]4 */ \ + {NAME, 1, 0x8+OPC2, 28, LD_STOR_INS | DISP, {{regr,24}, {rbase_cst4,16}}}, \ + /* opc4 r rbase disps16 */ \ + {NAME, 2, ((0x8+OPC2)<<8)+0xE, 20, LD_STOR_INS | DISP | FMT_1, {{regr,24}, {rbase_dispu16,16}}}, \ + /* opc4 r rbase disps32 */ \ + {NAME, 3, ((0x8+OPC2)<<8)+0xF, 20, LD_STOR_INS | FMT_1, {{regr,24}, {rbase_dispu32,16}}}, \ + /* opc12 r rbase */ \ + {NAME, 2, 0x328+OPC1, 20, LD_STOR_INS_INC, {{regr,16}, {rbase,12}}}, \ + /* opc12 r rbase disps12 */ \ + {NAME, 2, 0x328+OPC1, 20, LD_STOR_INS_INC, {{regr,16}, {rbase_dispu12,12}}}, \ + /* opc12 r rbase ridx scl2 disps6 */ \ + {NAME, 2, 0x32C+OPC1, 20, LD_STOR_INS, {{regr,16}, {rbase_ridx_scl2_dispu6,0}}}, \ + /* opc12 r rbase ridx scl2 disps22 */ \ + {NAME, 3, 0x33C+OPC1, 20, LD_STOR_INS, {{regr,16}, {rbase_ridx_scl2_dispu22,0}}} + +/* Store instructions (Immediate to Memory). */ +#define ST_I_INST(NAME, OPC) \ + /* opc12 i4 abs16 */ \ + {NAME, 2, 0x360+OPC, 20, STOR_IMM_INS, {{i4,16}, {abs16,0}}}, \ + /* opc12 i4 abs32 */ \ + {NAME, 3, 0x370+OPC, 20, STOR_IMM_INS, {{i4,16}, {abs32,0}}}, \ + /* opc12 i4 c4 rbase */ \ + {NAME, 1, 0x368+OPC, 20, LD_STOR_INS_INC, {{i4,16}, {rbase,12}}}, \ + /* opc12 i4 rbase disps12 */ \ + {NAME, 2, 0x368+OPC, 20, LD_STOR_INS_INC, {{i4,16}, {rbase_dispu12,12}}}, \ + /* opc4 i4 c4 rbase */ \ + {NAME, 1, 0x364+OPC, 20, STOR_IMM_INS, {{i4,16}, {rbase,12}}}, \ + /* opc12 i4 rbase disps12 */ \ + {NAME, 2, 0x364+OPC, 20, STOR_IMM_INS, {{i4,16}, {rbase_dispu12,12}}}, \ + /* opc12 i4 rbase disps28 */ \ + {NAME, 3, 0x374+OPC, 20, STOR_IMM_INS, {{i4,16}, {rbase_dispu28,12}}}, \ + /* opc12 i4 rbase ridx scl2 disps6 */ \ + {NAME, 2, 0x36C+OPC, 20, STOR_IMM_INS, {{i4,16}, {rbase_ridx_scl2_dispu6,0}}},\ + /* opc12 i4 rbase ridx scl2 disps22 */ \ + {NAME, 3, 0x37C+OPC, 20, STOR_IMM_INS, {{i4,16}, {rbase_ridx_scl2_dispu22,0}}} + + ST_REG_INST ("storb", 0x20, 0x4, DISPUB4), + ST_I_INST ("storb", 0x0), + + ST_REG_INST ("storw", 0x21, 0x5, DISPUW4), + ST_I_INST ("storw", 0x1), + + ST_REG_INST ("stord", 0x22, 0x6, DISPUD4), + ST_I_INST ("stord", 0x2), + +/* Create a bit instruction. */ +#define CSTBIT_INST(NAME, OP, OPC1, DIFF, SHIFT, OPC2) \ + /* OP=i3 -->> opc13 i3 */ \ + /* OP=i4 -->> opc12 i4 */ \ + /* OP=i5 -->> opc11 i5 */ \ + \ + /* opcNN iN abs16 */ \ + {NAME, 2, OPC1+0*DIFF, SHIFT, CSTBIT_INS, {{OP,16}, {abs16,0}}}, \ + /* opcNN iN abs32 */ \ + {NAME, 3, OPC1+1*DIFF, SHIFT, CSTBIT_INS, {{OP,16}, {abs32,0}}}, \ + /* opcNN iN rbase */ \ + {NAME, 1, OPC2, SHIFT+4, CSTBIT_INS, {{OP,20}, {rbase,16}}}, \ + /* opcNN iN rbase disps12 */ \ + {NAME, 2, OPC1+2*DIFF, SHIFT, CSTBIT_INS, {{OP,16}, {rbase_dispu12,12}}}, \ + /* opcNN iN rbase disps28 */ \ + {NAME, 3, OPC1+3*DIFF, SHIFT, CSTBIT_INS, {{OP,16}, {rbase_dispu28,12}}}, \ + /* opcNN iN rbase ridx scl2 disps6 */ \ + {NAME, 2, OPC1+4*DIFF, SHIFT, CSTBIT_INS, {{OP,16}, {rbase_ridx_scl2_dispu6,0}}}, \ + /* opcNN iN rbase ridx scl2 disps22 */ \ + {NAME, 3, OPC1+5*DIFF, SHIFT, CSTBIT_INS, {{OP,16}, {rbase_ridx_scl2_dispu22,0}}} + + CSTBIT_INST ("cbitb", i3, 0x700, 0x20, 19, 0x1FC), + CSTBIT_INST ("cbitw", i4, 0x382, 0x10, 20, 0xBD), + CSTBIT_INST ("cbitd", i5, 0x1C3, 0x8, 21, 0x7B), + {"cbitd", 2, 0x300838, 8, CSTBIT_INS, {{regr,4}, {regr,0}}}, + {"cbitd", 2, 0x18047B, 9, CSTBIT_INS, {{i5,4}, {regr,0}}}, + + CSTBIT_INST ("sbitb", i3, 0x701, 0x20, 19, 0x1FD), + CSTBIT_INST ("sbitw", i4, 0x383, 0x10, 20, 0xBE), + CSTBIT_INST ("sbitd", i5, 0x1C4, 0x8, 21, 0x7C), + {"sbitd", 2, 0x300839, 8, CSTBIT_INS, {{regr,4}, {regr,0}}}, + {"sbitd", 2, 0x18047C, 9, CSTBIT_INS, {{i5,4}, {regr,0}}}, + + CSTBIT_INST ("tbitb", i3, 0x702, 0x20, 19, 0x1FE), + CSTBIT_INST ("tbitw", i4, 0x384, 0x10, 20, 0xBF), + CSTBIT_INST ("tbitd", i5, 0x1C5, 0x8, 21, 0x7D), + {"tbitd", 2, 0x30083A, 8, CSTBIT_INS, {{regr,4}, {regr,0}}}, + {"tbitd", 2, 0x18047D, 9, CSTBIT_INS, {{i5,4}, {regr,0}}}, + +/* Instructions including a register list (opcode is represented as a mask). */ +#define REGLIST_INST(NAME, OPC) \ + /* opc12 r mask16 */ \ + {NAME, 2, OPC, 20, REG_LIST, {{regr,16}, {i16,0}}} + + REG1_INST ("getrfid", 0xFF9), + REG1_INST ("setrfid", 0xFFA), + + REGLIST_INST ("push", 0x346), + REG1_INST ("push", 0xFFB), + REGLIST_INST ("pushx", 0x347), + + REGLIST_INST ("pop", 0x324), + REG1_INST ("pop", 0xFFC), + REGLIST_INST ("popx", 0x327), + + REGLIST_INST ("popret", 0x326), + REG1_INST ("popret", 0xFFD), + + REGLIST_INST ("loadm", 0x324), + REGLIST_INST ("loadma", 0x325), + REGLIST_INST ("popa", 0x325), + + REGLIST_INST ("storm", 0x344), + REGLIST_INST ("storma", 0x345), + +/* Create a branch instruction. */ +#define BR_INST(NAME, OPC1, OPC2, INS_TYPE) \ + /* opc12 r disps17 */ \ + {NAME, 2, OPC1, 20, INS_TYPE | RELAXABLE, {{regr,16}, {d17,0}}}, \ + /* opc12 r disps33 */ \ + {NAME, 3, OPC2, 20, INS_TYPE | RELAXABLE, {{regr,16}, {d33,0}}} + + BR_INST ("bal", 0x307, 0x317, 0), + + /* Decrement and Branch instructions */ + BR_INST ("dbnzb", 0x304, 0x314, DCR_BRANCH_INS), + BR_INST ("dbnzw", 0x305, 0x315, DCR_BRANCH_INS), + BR_INST ("dbnzd", 0x306, 0x316, DCR_BRANCH_INS), + + /* Jump and link instructions */ + REG1_INST ("jal", 0xFF8), + REG2_INST ("jal", 0x37), + REG2_INST ("jalid", 0x33), + + /* opc12 c4 opc12 r mask16 */ + {"loadmcr", 3, 0x3110300, 4, COP_REG_INS | REG_LIST | FMT_5, {{i4,16}, {regr,0}, {i16,0}}}, + {"stormcr", 3, 0x3110301, 4, COP_REG_INS | REG_LIST | FMT_5, {{i4,16}, {regr,0}, {i16,0}}}, + + /* esc16 r procreg */ + {"mtpr", 2, 0x3009, 16, 0, {{regr8,8}, {regr8,0}}}, + /* esc16 procreg r */ + {"mfpr", 2, 0x300A, 16, 0, {{regr8,8}, {regr8,0}}}, + /* opc12 c4 opc8 r copreg */ + {"mtcr", 2, 0x301030, 8, COP_REG_INS | FMT_2, {{i4,16}, {regr,4}, {copregr,0}}}, + /* opc12 c4 opc8 copreg r */ + {"mfcr", 2, 0x301031, 8, COP_REG_INS | FMT_2, {{i4,16}, {copregr,4}, {regr,0}}}, + /* opc12 c4 opc8 r copsreg */ + {"mtcsr", 2, 0x301032, 8, COP_REG_INS | FMT_2, {{i4,16}, {regr,4}, {copsregr,0}}}, + /* opc12 c4 opc8 copsreg r */ + {"mfcsr", 2, 0x301033, 8, COP_REG_INS | FMT_2, {{i4,16}, {copsregr,4}, {regr,0}}}, + + /* CO-processor extensions */ + /* opc12 c4 opc4 i4 disps9 */ + {"bcop", 2, 0x30107, 12, COP_BRANCH_INS | FMT_4, {{i4,16}, {i4,8}, {d9,0}}}, + /* opc12 c4 opc4 i4 disps25 */ + {"bcop", 3, 0x31107, 12, COP_BRANCH_INS | FMT_4, {{i4,16}, {i4,8}, {d25,0}}}, + + /* opc12 i4 */ + {"excp", 1, 0xFFF, 20, 0, {{i4,16}}}, + /* opc28 i4 */ + {"cinv", 2, 0x3010000, 4, 0, {{i4,0}}}, + + /* opc9 i5 i5 i5 r r */ + {"ram", 2, 0x7C, 23, 0, {{i5,18}, {i5,13}, {i5,8}, {regr,4}, {regr,0}}}, + {"rim", 2, 0x7D, 23, 0, {{i5,18}, {i5,13}, {i5,8}, {regr,4}, {regr,0}}}, + + /* opc9 i3 r */ + {"rotb", 1, 0x1FB, 23, 0, {{i3,20}, {regr,16}}}, + /* opc8 i4 r */ + {"rotw", 1, 0xB9, 24, 0, {{i4,20}, {regr,16}}}, + /* opc23 i5 r */ + {"rotd", 2, 0x180478, 9, 0, {{i5,4}, {regr,0}}}, + + {NULL, 0, 0, 0, 0, {{0, 0}}} +}; + +const int crx_num_opcodes = ARRAY_SIZE (crx_instruction); + +/* Macro to build a reg_entry, which have an opcode image : + For example : + REG(u4, 0x84, CRX_U_REGTYPE) + is interpreted as : + {"u4", u4, 0x84, CRX_U_REGTYPE} */ +#define REG(NAME, N, TYPE) {STRINGX(NAME), {NAME}, N, TYPE} + +const reg_entry crx_regtab[] = +{ +/* Build a general purpose register r. */ +#define REG_R(N) REG(CONCAT2(r,N), N, CRX_R_REGTYPE) + + REG_R(0), REG_R(1), REG_R(2), REG_R(3), + REG_R(4), REG_R(5), REG_R(6), REG_R(7), + REG_R(8), REG_R(9), REG_R(10), REG_R(11), + REG_R(12), REG_R(13), REG_R(14), REG_R(15), + REG(ra, 0xe, CRX_R_REGTYPE), + REG(sp, 0xf, CRX_R_REGTYPE), + +/* Build a user register u. */ +#define REG_U(N) REG(CONCAT2(u,N), 0x80 + N, CRX_U_REGTYPE) + + REG_U(0), REG_U(1), REG_U(2), REG_U(3), + REG_U(4), REG_U(5), REG_U(6), REG_U(7), + REG_U(8), REG_U(9), REG_U(10), REG_U(11), + REG_U(12), REG_U(13), REG_U(14), REG_U(15), + REG(ura, 0x8e, CRX_U_REGTYPE), + REG(usp, 0x8f, CRX_U_REGTYPE), + +/* Build a configuration register. */ +#define REG_CFG(NAME, N) REG(NAME, N, CRX_CFG_REGTYPE) + + REG_CFG(hi, 0x10), + REG_CFG(lo, 0x11), + REG_CFG(uhi, 0x90), + REG_CFG(ulo, 0x91), + REG_CFG(psr, 0x12), + REG_CFG(cfg, 0x15), + REG_CFG(cpcfg, 0x16), + REG_CFG(ccfg, 0x1b), + +/* Build a mptr register. */ +#define REG_MPTR(NAME, N) REG(NAME, N, CRX_MTPR_REGTYPE) + + REG_MPTR(intbase, 0x13), + REG_MPTR(isp, 0x14), + REG_MPTR(cen, 0x17), + +/* Build a pc register. */ +#define REG_PC(NAME, N) REG(NAME, N, CRX_PC_REGTYPE) + + REG_PC(pc, 0x0) +}; + +const int crx_num_regs = ARRAY_SIZE (crx_regtab); + +const reg_entry crx_copregtab[] = +{ +/* Build a Coprocessor register c. */ +#define REG_C(N) REG(CONCAT2(c,N), N, CRX_C_REGTYPE) + + REG_C(0), REG_C(1), REG_C(2), REG_C(3), + REG_C(4), REG_C(5), REG_C(6), REG_C(7), + REG_C(8), REG_C(9), REG_C(10), REG_C(11), + REG_C(12), REG_C(13), REG_C(14), REG_C(15), + +/* Build a Coprocessor Special register cs. */ +#define REG_CS(N) REG(CONCAT2(cs,N), N, CRX_CS_REGTYPE) + + REG_CS(0), REG_CS(1), REG_CS(2), REG_CS(3), + REG_CS(4), REG_CS(5), REG_CS(6), REG_CS(7), + REG_CS(8), REG_CS(9), REG_CS(10), REG_CS(11), + REG_CS(12), REG_CS(13), REG_CS(14), REG_CS(15) +}; + +const int crx_num_copregs = ARRAY_SIZE (crx_copregtab); + +/* CRX operands table. */ +const operand_entry crx_optab[] = +{ + /* Index 0 is dummy, so we can count the instruction's operands. */ + {0, nullargs}, /* dummy */ + {4, arg_ic}, /* cst4 */ + {8, arg_c}, /* disps9 */ + {3, arg_ic}, /* i3 */ + {4, arg_ic}, /* i4 */ + {5, arg_ic}, /* i5 */ + {8, arg_ic}, /* i8 */ + {12, arg_ic}, /* i12 */ + {16, arg_ic}, /* i16 */ + {32, arg_ic}, /* i32 */ + {4, arg_c}, /* d5 */ + {8, arg_c}, /* d9 */ + {16, arg_c}, /* d17 */ + {24, arg_c}, /* d25 */ + {32, arg_c}, /* d33 */ + {16, arg_c}, /* abs16 */ + {32, arg_c}, /* abs32 */ + {4, arg_rbase}, /* rbase */ + {4, arg_cr}, /* rbase_cst4 */ + {8, arg_cr}, /* rbase_dispu8 */ + {12, arg_cr}, /* rbase_dispu12 */ + {16, arg_cr}, /* rbase_dispu16 */ + {28, arg_cr}, /* rbase_dispu28 */ + {32, arg_cr}, /* rbase_dispu32 */ + {6, arg_icr}, /* rbase_ridx_scl2_dispu6 */ + {22, arg_icr}, /* rbase_ridx_scl2_dispu22 */ + {4, arg_r}, /* regr */ + {8, arg_r}, /* regr8 */ + {4, arg_copr}, /* copregr */ + {8, arg_copr}, /* copregr8 */ + {4, arg_copsr} /* copsregr */ +}; + +/* CRX traps/interrupts. */ +const trap_entry crx_traps[] = +{ + {"nmi", 1}, {"svc", 5}, {"dvz", 6}, {"flg", 7}, + {"bpt", 8}, {"und", 10}, {"prv", 11}, {"iberr", 12} +}; + +const int crx_num_traps = ARRAY_SIZE (crx_traps); + +/* cst4 operand mapping. */ +const cst4_entry cst4_map[] = +{ + {0,0}, {1,1}, {2,2}, {3,3}, {4,4}, {5,-4}, {6,-1}, + {7,7}, {8,8}, {9,16}, {10,32}, {11,20}, {12,12}, {13,48} +}; + +const int cst4_maps = ARRAY_SIZE (cst4_map); diff --git a/sim/mn10300/am33-2.igen b/sim/mn10300/am33-2.igen new file mode 100644 index 00000000000..bcf68b46e2b --- /dev/null +++ b/sim/mn10300/am33-2.igen @@ -0,0 +1,2285 @@ +// data cache pre-fetch: + +// 1111 1001 1010 0110 Rm.. 0000; dcpf (Rm) +8.0xf9+8.0xa6+4.RN2,4.0000:D1a:::dcpf +"dcpf" +*am33_2 +{ + int srcreg; + + PC = cia; + + srcreg = translate_rreg (SD_, RN2); + load_word (State.regs[srcreg]); +} + +// 1111 1001 1010 0111 0000 0000; dcpf (sp) +8.0xf9+8.0xa7+8.0x00:D1b:::dcpf +"dcpf" +*am33_2 +{ + PC = cia; + + load_word (SP); +} + +// 1111 1011 1010 0110 Ri.. Rm.. 0000 0000; dcpf (Ri,Rm) +8.0xfb+8.0xa6+4.RN2,4.RN0+8.0x00:D2a:::dcpf +"dcpf" +*am33_2 +{ + int srci, srcm; + + PC = cia; + + srci = translate_rreg (SD_, RN2); + srcm = translate_rreg (SD_, RN0); + + load_word (State.regs[srci] + State.regs[srcm]); +} + +// 1111 1011 1010 0111 Rm.. 0000 IMM8; dcpf (d8,Rm) +8.0xfb+8.0xa7+4.RN2,4.0000+8.IMM8:D2b:::dcpf +"dcpf" +*am33_2 +{ + int srcreg; + + PC = cia; + + srcreg = translate_rreg (SD_, RN2); + + load_word (State.regs[srcreg] + EXTEND8 (IMM8)); +} + +// 1111 1101 1010 0111 Rm.. 0000 IMM24; dcpf (d24,Rm) +8.0xfd+8.0xa7+4.RN2,4.0000+8.IMM24A+8.IMM24B+8.IMM24C:D4a:::dcpf +"dcpf" +*am33_2 +{ + int srcreg; + + PC = cia; + + srcreg = translate_rreg (SD_, RN2); + + load_word (State.regs[srcreg] + EXTEND24 (FETCH24 (IMM24A, + IMM24B, IMM24C))); +} + +// 1111 1110 0100 0110 Rm.. 0000 IMM32; dcpf (d32,Rm) +8.0xfe+8.0x46+4.RN2,4.0000+8.IMM32A+8.IMM32B+8.IMM32C+8.IMM32D:D5a:::dcpf +"dcpf" +*am33_2 +{ + int srcreg; + + PC = cia; + + srcreg = translate_rreg (SD_, RN2); + + load_word (State.regs[srcreg] + + FETCH32 (IMM32A, IMM32B, IMM32C, IMM32D)); +} + +// bit operations with imm8,(abs16) addressing mode: + +// 1111 1110 1000 0010 ABS16 IMM8; btst imm8,(abs16) +8.0xfe+8.0x82+8.IMM16A+8.IMM16B+8.IMM8:D3:::btst +"btst" +*am33_2 +{ + PC = cia; + genericBtst (IMM8, FETCH16 (IMM16A, IMM16B)); +} + +// 1111 1110 1000 0000 ABS16 IMM8; bset imm8,(abs16) +8.0xfe+8.0x80+8.IMM16A+8.IMM16B+8.IMM8:D3:::bset +"bset" +*am33_2 +{ + unsigned32 temp; + int z; + + PC = cia; + temp = load_byte (FETCH16 (IMM16A, IMM16B)); + z = (temp & IMM8) == 0; + temp |= IMM8; + store_byte (FETCH16 (IMM16A, IMM16B), temp); + PSW &= ~(PSW_Z | PSW_N | PSW_C | PSW_V); + PSW |= (z ? PSW_Z : 0); +} + +// 1111 1110 1000 0001 ABS16 IMM8; bclr imm8,(abs16) +8.0xfe+8.0x81+8.IMM16A+8.IMM16B+8.IMM8:D3:::bclr +"bclr" +*am33_2 +{ + unsigned32 temp; + int z; + + PC = cia; + temp = load_byte (FETCH16 (IMM16A, IMM16B)); + z = (temp & IMM8) == 0; + temp = temp & ~(IMM8); + store_byte (FETCH16 (IMM16A, IMM16B), temp); + PSW &= ~(PSW_Z | PSW_N | PSW_C | PSW_V); + PSW |= (z ? PSW_Z : 0); +} + +// single precision fmov: + +// 1111 1001 0010 000X Rm.. Sn..; fmov (Rm),FSn +8.0xf9+4.2,3.0,1.X+4.Rm,4.Sn:D1a:::fmov +"fmov" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else + { + int reg = translate_rreg (SD_, Rm); + XS2FS (X,Sn) = load_word (State.regs[reg]); + } +} + +// 1111 1001 0010 001X Rm.. Sn..; fmov (Rm+),FSn +8.0xf9+4.2,3.1,1.X+4.Rm,4.Sn:D1b:::fmov +"fmov" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else + { + int reg = translate_rreg (SD_, Rm); + XS2FS (X,Sn) = load_word (State.regs[reg]); + State.regs[reg] += 4; + } +} + +// 1111 1001 0010 010X ---- Sn..; fmov (SP),FSn +8.0xf9+4.2,3.2,1.X+4.0,4.Sn:D1c:::fmov +"fmov" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else + { + int reg = REG_SP; + XS2FS (X,Sn) = load_word (State.regs[reg]); + } +} + +// 1111 1001 0010 011X Rm.. Sn..; fmov Rm,FSn +8.0xf9+4.2,3.3,1.X+4.Rm,4.Sn:D1d:::fmov +"fmov" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else + { + int reg = translate_rreg (SD_, Rm); + XS2FS (X,Sn) = State.regs[reg]; + } +} + +// 1111 1001 0011 00Y0 Sm.. Rn..; fmov FSm,(Rn) +8.0xf9+4.3,2.0,1.Y,1.0+4.Sm,4.Rn:D1e:::fmov +"fmov" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else + { + int reg = translate_rreg (SD_, Rn); + store_word (State.regs[reg], XS2FS (Y,Sm)); + } +} + +// 1111 1001 0011 00Y1 Sm.. Rn..; fmov FSm,(Rn+) +8.0xf9+4.3,2.0,1.Y,1.1+4.Sm,4.Rn:D1f:::fmov +"fmov" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else + { + int reg = translate_rreg (SD_, Rn); + store_word (State.regs[reg], XS2FS (Y,Sm)); + State.regs[reg] += 4; + } +} + +// 1111 1001 0011 01Y0 Sm.. ----; fmov FSm,(SP) +8.0xf9+4.3,2.1,1.Y,1.0+4.Sm,4.0:D1g:::fmov +"fmov" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else + { + int reg = REG_SP; + store_word (State.regs[reg], XS2FS (Y,Sm)); + } +} + +// 1111 1001 0011 01Y1 Sm.. Rn..; fmov FSm,Rn +8.0xf9+4.3,2.1,1.Y,1.1+4.Sm,4.Rn:D1h:::fmov +"fmov" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else + { + int reg = translate_rreg (SD_, Rn); + State.regs[reg] = XS2FS (Y,Sm); + } +} + +// 1111 1001 0100 00YX Sm.. Sn..; fmov FSm,FSn +8.0xf9+4.4,2.0,1.Y,1.X+4.Sm,4.Sn:D1i:::fmov +"fmov" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else + XS2FS (X,Sn) = XS2FS (Y,Sm); +} + +// 1111 1011 0010 000X Rm.. Sn.. d8; fmov (d8,Rm),FSn +8.0xfb+4.2,3.0,1.X+4.Rm,4.Sn+8.IMM8:D2a:::fmov +"fmov" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else + { + int reg = translate_rreg (SD_, Rm); + XS2FS (X, Sn) = load_word (State.regs[reg] + EXTEND8 (IMM8)); + } +} + +// 1111 1011 0010 001X Rm.. Sn.. d8; fmov (Rm+,imm8),FSn +8.0xfb+4.2,3.1,1.X+4.Rm,4.Sn+8.IMM8:D2b:::fmov +"fmov" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else + { + int reg = translate_rreg (SD_, Rm); + XS2FS (X, Sn) = load_word (State.regs[reg] + EXTEND8 (IMM8)); + State.regs[reg] += 4; + } +} + +// 1111 1011 0010 010X ---- Sn.. d8; fmov (d8,SP),FSn +8.0xfb+4.2,3.2,1.X+4.0,4.Sn+8.IMM8:D2c:::fmov +"fmov" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else + { + int reg = REG_SP; + XS2FS (X, Sn) = load_word (State.regs[reg] + IMM8); + } +} + +// 1111 1011 0010 0111 Ri.. Rm.. Sn.. --Z-; fmov (Ri,Rm),FSn +8.0xfb+8.0x27+4.Ri,4.Rm+4.Sn,2.0,1.Z,1.0:D2d:::fmov +"fmov" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else + { + int ri = translate_rreg (SD_, Ri); + int rm = translate_rreg (SD_, Rm); + XS2FS (Z, Sn) = load_word (State.regs[ri] + State.regs[rm]); + } +} + +// 1111 1011 0011 00Y0 Sm.. Rn.. d8; fmov FSm,(d8,Rn) +8.0xfb+4.3,2.0,1.Y,1.0+4.Sm,4.Rn+8.IMM8:D2e:::fmov +"fmov" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else + { + int reg = translate_rreg (SD_, Rn); + store_word (State.regs[reg] + EXTEND8 (IMM8), XS2FS (Y, Sm)); + } +} + +// 1111 1011 0011 00Y1 Sm.. Rn.. d8; fmov FSm,(Rn+,d8) +8.0xfb+4.3,2.0,1.Y,1.1+4.Sm,4.Rn+8.IMM8:D2f:::fmov +"fmov" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else + { + int reg = translate_rreg (SD_, Rn); + store_word (State.regs[reg] + EXTEND8 (IMM8), XS2FS (Y, Sm)); + State.regs[reg] += 4; + } +} + +// 1111 1011 0011 01Y0 Sm.. ---- d8; fmov FSm,(d8,SP) +8.0xfb+4.3,2.1,1.Y,1.0+4.Sm,4.0+8.IMM8:D2g:::fmov +"fmov" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else + { + int reg = REG_SP; + store_word (State.regs[reg] + IMM8, XS2FS (Y, Sm)); + } +} + +// 1111 1011 0011 0111 Ri.. Rm.. Sm.. --Z-; fmov FSm,(Ri,Rm) +8.0xfb+8.0x37+4.Ri,4.Rm+4.Sm,2.0,1.Z,1.0:D2h:::fmov +"fmov" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else + { + int ri = translate_rreg (SD_, Ri); + int rm = translate_rreg (SD_, Rm); + store_word (State.regs[ri] + State.regs[rm], XS2FS (Z, Sm)); + } +} + +// 1111 1101 0010 000X Rm.. Sn.. d24; fmov (d24,Rm),FSn +8.0xfd+4.2,3.0,1.X+4.Rm,4.Sn+8.IMM24A+8.IMM24B+8.IMM24C:D4a:::fmov +"fmov" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else + { + int reg = translate_rreg (SD_, Rm); + XS2FS (X, Sn) = load_word (State.regs[reg] + + EXTEND24 (FETCH24 (IMM24A, + IMM24B, IMM24C))); + } +} + +// 1111 1101 0010 001X Rm.. Sn.. d24; fmov (Rm+,imm24),FSn +8.0xfd+4.2,3.1,1.X+4.Rm,4.Sn+8.IMM24A+8.IMM24B+8.IMM24C:D4b:::fmov +"fmov" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else + { + int reg = translate_rreg (SD_, Rm); + XS2FS (X, Sn) = load_word (State.regs[reg] + + EXTEND24 (FETCH24 (IMM24A, + IMM24B, IMM24C))); + State.regs[reg] += 4; + } +} + +// 1111 1101 0010 010X ---- Sn.. d24; fmov (d24,SP),FSn +8.0xfd+4.2,3.2,1.X+4.0,4.Sn+8.IMM24A+8.IMM24B+8.IMM24C:D4c:::fmov +"fmov" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else + { + int reg = REG_SP; + XS2FS (X, Sn) = load_word (State.regs[reg] + FETCH24 (IMM24A, + IMM24B, IMM24C)); + } +} + +// 1111 1101 0011 00Y0 Sm.. Rn.. d24; fmov FSm,(d24,Rn) +8.0xfd+4.3,2.0,1.Y,1.0+4.Sm,4.Rn+8.IMM24A+8.IMM24B+8.IMM24C:D4e:::fmov +"fmov" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else + { + int reg = translate_rreg (SD_, Rn); + store_word (State.regs[reg] + + EXTEND24 (FETCH24 (IMM24A, + IMM24B, IMM24C)), XS2FS (Y, Sm)); + } +} + +// 1111 1101 0011 00Y1 Sm.. Rn.. d24; fmov FSm,(Rn+,d24) +8.0xfd+4.3,2.0,1.Y,1.1+4.Sm,4.Rn+8.IMM24A+8.IMM24B+8.IMM24C:D4f:::fmov +"fmov" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else + { + int reg = translate_rreg (SD_, Rn); + store_word (State.regs[reg] + + EXTEND24 (FETCH24 (IMM24A, + IMM24B, IMM24C)), XS2FS (Y, Sm)); + State.regs[reg] += 4; + } +} + +// 1111 1101 0011 01Y0 Sm.. ---- d24; fmov FSm,(d24,SP) +8.0xfd+4.3,2.1,1.Y,1.0+4.Sm,4.0+8.IMM24A+8.IMM24B+8.IMM24C:D4g:::fmov +"fmov" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else + { + int reg = REG_SP; + store_word (State.regs[reg] + + FETCH24 (IMM24A, + IMM24B, IMM24C), XS2FS (Y, Sm)); + } +} + +// 1111 1110 0010 000X Rm.. Sn.. d32; fmov (d32,Rm),FSn +8.0xfe+4.2,3.0,1.X+4.Rm,4.Sn+8.IMM32A+8.IMM32B+8.IMM32C+8.IMM32D:D5a:::fmov +"fmov" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else + { + int reg = translate_rreg (SD_, Rm); + XS2FS (X, Sn) = load_word (State.regs[reg] + + EXTEND32 (FETCH32 (IMM32A, IMM32B, + IMM32C, IMM32D))); + } +} + +// 1111 1110 0010 001X Rm.. Sn.. d32; fmov (Rm+,imm32),FSn +8.0xfe+4.2,3.1,1.X+4.Rm,4.Sn+8.IMM32A+8.IMM32B+8.IMM32C+8.IMM32D:D5b:::fmov +"fmov" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else + { + int reg = translate_rreg (SD_, Rm); + XS2FS (X, Sn) = load_word (State.regs[reg] + + EXTEND32 (FETCH32 (IMM32A, IMM32B, + IMM32C, IMM32D))); + State.regs[reg] += 4; + } +} + +// 1111 1110 0010 010X ---- Sn.. d32; fmov (d32,SP),FSn +8.0xfe+4.2,3.2,1.X+4.0,4.Sn+8.IMM32A+8.IMM32B+8.IMM32C+8.IMM32D:D5c:::fmov +"fmov" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else + { + int reg = REG_SP; + XS2FS (X, Sn) = load_word (State.regs[reg] + + FETCH32 (IMM32A, IMM32B, + IMM32C, IMM32D)); + } +} + +// 1111 1110 0010 011X ---- Sn.. d32; fmov imm32,FSn +8.0xfe+4.2,3.3,1.X+4.0,4.Sn+8.IMM32A+8.IMM32B+8.IMM32C+8.IMM32D:D5d:::fmov +"fmov" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else + XS2FS (X, Sn) = FETCH32 (IMM32A, IMM32B, IMM32C, IMM32D); +} + +// 1111 1110 0011 00Y0 Sm.. Rn.. d32; fmov FSm,(d32,Rn) +8.0xfe+4.3,2.0,1.Y,1.0+4.Sm,4.Rn+8.IMM32A+8.IMM32B+8.IMM32C+8.IMM32D:D5e:::fmov +"fmov" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else + { + int reg = translate_rreg (SD_, Rn); + store_word (State.regs[reg] + + EXTEND32 (FETCH32 (IMM32A, IMM32B, + IMM32C, IMM32D)), XS2FS (Y, Sm)); + } +} + +// 1111 1110 0011 00Y1 Sm.. Rn.. d32; fmov FSm,(Rn+,d32) +8.0xfe+4.3,2.0,1.Y,1.1+4.Sm,4.Rn+8.IMM32A+8.IMM32B+8.IMM32C+8.IMM32D:D5f:::fmov +"fmov" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else + { + int reg = translate_rreg (SD_, Rn); + store_word (State.regs[reg] + + EXTEND32 (FETCH32 (IMM32A, IMM32B, + IMM32C, IMM32D)), XS2FS (Y, Sm)); + State.regs[reg] += 4; + } +} + +// 1111 1110 0011 01Y0 Sm.. ---- d32; fmov FSm,(d32,SP) +8.0xfe+4.3,2.1,1.Y,1.0+4.Sm,4.0+8.IMM32A+8.IMM32B+8.IMM32C+8.IMM32D:D5g:::fmov +"fmov" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else + { + int reg = REG_SP; + store_word (State.regs[reg] + + FETCH32 (IMM32A, IMM32B, + IMM32C, IMM32D), XS2FS (Y, Sm)); + } +} + +// double precision fmov: + +// 1111 1001 1010 000X Rm.. fn.-; fmov (Rm),FDn +8.0xf9+4.0xa,3.0,1.X+4.Rm,3.fn,1.0:D1j:::fmov +"fmov" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else + { + int reg = translate_rreg (SD_, Rm); + Xf2FD (X,fn) = load_dword (State.regs[reg]); + } +} + +// 1111 1001 1010 001X Rm.. fn.-; fmov (Rm+),FDn +8.0xf9+4.0xa,3.1,1.X+4.Rm,3.fn,1.0:D1k:::fmov +"fmov" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else + { + int reg = translate_rreg (SD_, Rm); + Xf2FD (X,fn) = load_dword (State.regs[reg]); + State.regs[reg] += 8; + } +} + +// 1111 1001 1010 010X ---- fn.-; fmov (SP),FDn +8.0xf9+4.0xa,3.2,1.X+4.0,3.fn,1.0:D1l:::fmov +"fmov" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else + { + int reg = REG_SP; + Xf2FD (X,fn) = load_dword (State.regs[reg]); + } +} + +// 1111 1001 1011 00Y0 fm.- Rn..; fmov FDm,(Rn) +8.0xf9+4.0xb,2.0,1.Y,1.0+3.fm,1.0,4.Rn:D1m:::fmov +"fmov" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else + { + int reg = translate_rreg (SD_, Rn); + store_dword (State.regs[reg], Xf2FD (Y,fm)); + } +} + +// 1111 1001 1011 00Y1 fm.- Rn..; fmov FDm,(Rn+) +8.0xf9+4.0xb,2.0,1.Y,1.1+3.fm,1.0,4.Rn:D1n:::fmov +"fmov" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else + { + int reg = translate_rreg (SD_, Rn); + store_dword (State.regs[reg], Xf2FD (Y,fm)); + State.regs[reg] += 8; + } +} + +// 1111 1001 1011 01Y0 fm.- ----; fmov FDm,(SP) +8.0xf9+4.0xb,2.1,1.Y,1.0+3.fm,1.0,4.0:D1o:::fmov +"fmov" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else + { + int reg = REG_SP; + store_dword (State.regs[reg], Xf2FD (Y,fm)); + } +} + +// 1111 1001 1100 00YX fm.- fn.-; fmov FDm,FDn +8.0xf9+4.0xc,2.0,1.Y,1.X+3.fm,1.0,3.fn,1.0:D1p:::fmov +"fmov" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else + fpu_unimp_exception (SD, CPU, cia); +} + +// 1111 1011 0100 0111 Ri.. Rm.. fn.- --Z-; fmov (Ri,Rm),FDn +8.0xfb+8.0x47+4.Ri,4.Rm+3.fn,1.0,2.0,1.Z,1.0:D2i:::fmov +"fmov" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else + { + int ri = translate_rreg (SD_, Ri); + int rm = translate_rreg (SD_, Rm); + Xf2FD (Z,fn) = load_dword (State.regs[ri] + State.regs[rm]); + } +} + +// 1111 1011 0101 0111 Ri.. Rn.. fm.- --Z-; fmov FDm,(Ri,Rn) +8.0xfb+8.0x57+4.Ri,4.Rn+3.fm,1.0,2.0,1.Z,1.0:D2j:::fmov +"fmov" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else + { + int ri = translate_rreg (SD_, Ri); + int rn = translate_rreg (SD_, Rn); + store_dword (State.regs[ri] + State.regs[rn], Xf2FD (Z,fm)); + } +} + +// 1111 1011 1010 000X Rm.. fn.- d8; fmov (d8,Rm),FDn +8.0xfb+4.0xa,3.0,1.X+4.Rm,4.fn+8.IMM8:D2k:::fmov +"fmov" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else + { + int reg = translate_rreg (SD_, Rm); + Xf2FD (X, fn) = load_dword (State.regs[reg] + EXTEND8 (IMM8)); + } +} + +// 1111 1011 1010 001X Rm.. fn.- d8; fmov (Rm+,imm8),FDn +8.0xfb+4.0xa,3.1,1.X+4.Rm,4.fn+8.IMM8:D2l:::fmov +"fmov" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else + { + int reg = translate_rreg (SD_, Rm); + Xf2FD (X, fn) = load_dword (State.regs[reg] + EXTEND8 (IMM8)); + State.regs[reg] += 8; + } +} + +// 1111 1011 1010 010X ---- fn.- d8; fmov (d8,SP),FDn +8.0xfb+4.0xa,3.2,1.X+4.0,4.fn+8.IMM8:D2m:::fmov +"fmov" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else + { + int reg = REG_SP; + Xf2FD (X, fn) = load_dword (State.regs[reg] + IMM8); + } +} + +// 1111 1011 1011 00Y0 fm.- Rn.. d8; fmov FDm,(d8,Rn) +8.0xfb+4.0xb,2.0,1.Y,1.0+4.fm,4.Rn+8.IMM8:D2n:::fmov +"fmov" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else + { + int reg = translate_rreg (SD_, Rn); + store_dword (State.regs[reg] + EXTEND8 (IMM8), Xf2FD (Y, fm)); + } +} + +// 1111 1011 1011 00Y1 fm.- Rn.. d8; fmov FDm,(Rn+,d8) +8.0xfb+4.0xb,2.0,1.Y,1.1+4.fm,4.Rn+8.IMM8:D2o:::fmov +"fmov" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else + { + int reg = translate_rreg (SD_, Rn); + store_dword (State.regs[reg] + EXTEND8 (IMM8), Xf2FD (Y, fm)); + State.regs[reg] += 8; + } +} + +// 1111 1011 1011 01Y0 fm.- ---- d8; fmov FDm,(d8,SP) +8.0xfb+4.0xb,2.1,1.Y,1.0+4.fm,4.0+8.IMM8:D2p:::fmov +"fmov" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else + { + int reg = REG_SP; + store_dword (State.regs[reg] + IMM8, Xf2FD (Y, fm)); + } +} + +// 1111 1101 1010 000X Rm.. fn.- d24; fmov (d24,Rm),FDn +8.0xfd+4.0xa,3.0,1.X+4.Rm,4.fn+8.IMM24A+8.IMM24B+8.IMM24C:D4k:::fmov +"fmov" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else + { + int reg = translate_rreg (SD_, Rm); + Xf2FD (X, fn) = load_dword (State.regs[reg] + + EXTEND24 (FETCH24 (IMM24A, + IMM24B, IMM24C))); + } +} + +// 1111 1101 1010 001X Rm.. fn.- d24; fmov (Rm+,imm24),FDn +8.0xfd+4.0xa,3.1,1.X+4.Rm,4.fn+8.IMM24A+8.IMM24B+8.IMM24C:D4l:::fmov +"fmov" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else + { + int reg = translate_rreg (SD_, Rm); + Xf2FD (X, fn) = load_dword (State.regs[reg] + + EXTEND24 (FETCH24 (IMM24A, + IMM24B, IMM24C))); + State.regs[reg] += 8; + } +} + +// 1111 1101 1010 010X ---- fn.- d24; fmov (d24,SP),FDn +8.0xfd+4.0xa,3.2,1.X+4.0,4.fn+8.IMM24A+8.IMM24B+8.IMM24C:D4m:::fmov +"fmov" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else + { + int reg = REG_SP; + Xf2FD (X, fn) = load_dword (State.regs[reg] + + FETCH24 (IMM24A, + IMM24B, IMM24C)); + } +} + +// 1111 1101 1011 00Y0 fm.- Rn.. d24; fmov FDm,(d24,Rn) +8.0xfd+4.0xb,2.0,1.Y,1.0+4.fm,4.Rn+8.IMM24A+8.IMM24B+8.IMM24C:D4n:::fmov +"fmov" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else + { + int reg = translate_rreg (SD_, Rn); + store_dword (State.regs[reg] + + EXTEND24 (FETCH24 (IMM24A, + IMM24B, IMM24C)), Xf2FD (Y, fm)); + } +} + +// 1111 1101 1011 00Y1 fm.- Rn.. d24; fmov FDm,(Rn+,d24) +8.0xfd+4.0xb,2.0,1.Y,1.1+4.fm,4.Rn+8.IMM24A+8.IMM24B+8.IMM24C:D4o:::fmov +"fmov" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else + { + int reg = translate_rreg (SD_, Rn); + store_dword (State.regs[reg] + + EXTEND24 (FETCH24 (IMM24A, + IMM24B, IMM24C)), Xf2FD (Y, fm)); + State.regs[reg] += 8; + } +} + +// 1111 1101 1011 01Y0 fm.- ---- d24; fmov FDm,(d24,SP) +8.0xfd+4.0xb,2.1,1.Y,1.0+4.fm,4.0+8.IMM24A+8.IMM24B+8.IMM24C:D4p:::fmov +"fmov" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else + { + int reg = REG_SP; + store_dword (State.regs[reg] + FETCH24 (IMM24A, + IMM24B, IMM24C), Xf2FD (Y, fm)); + } +} + +// 1111 1110 1010 000X Rm.. fn.- d32; fmov (d32,Rm),FDn +8.0xfe+4.0xa,3.0,1.X+4.Rm,4.fn+8.IMM32A+8.IMM32B+8.IMM32C+8.IMM32D:D5k:::fmov +"fmov" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else + { + int reg = translate_rreg (SD_, Rm); + Xf2FD (X, fn) = load_dword (State.regs[reg] + + EXTEND32 (FETCH32 (IMM32A, IMM32B, + IMM32C, IMM32D))); + } +} + +// 1111 1110 1010 001X Rm.. fn.- d32; fmov (Rm+,imm32),FDn +8.0xfe+4.0xa,3.1,1.X+4.Rm,4.fn+8.IMM32A+8.IMM32B+8.IMM32C+8.IMM32D:D5l:::fmov +"fmov" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else + { + int reg = translate_rreg (SD_, Rm); + Xf2FD (X, fn) = load_dword (State.regs[reg] + + EXTEND32 (FETCH32 (IMM32A, IMM32B, + IMM32C, IMM32D))); + State.regs[reg] += 8; + } +} + +// 1111 1110 1010 010X ---- fn.- d32; fmov (d32,SP),FDn +8.0xfe+4.0xa,3.2,1.X+4.0,4.fn+8.IMM32A+8.IMM32B+8.IMM32C+8.IMM32D:D5m:::fmov +"fmov" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else + { + int reg = REG_SP; + Xf2FD (X, fn) = load_dword (State.regs[reg] + + FETCH32 (IMM32A, IMM32B, + IMM32C, IMM32D)); + } +} + +// 1111 1110 1011 00Y0 fm.- Rn.. d32; fmov FDm,(d32,Rn) +8.0xfe+4.0xb,2.0,1.Y,1.0+4.fm,4.Rn+8.IMM32A+8.IMM32B+8.IMM32C+8.IMM32D:D5n:::fmov +"fmov" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else + { + int reg = translate_rreg (SD_, Rn); + store_dword (State.regs[reg] + + EXTEND32 (FETCH32 (IMM32A, IMM32B, + IMM32C, IMM32D)), Xf2FD (Y, fm)); + } +} + +// 1111 1110 1011 00Y1 fm.- Rn.. d32; fmov FDm,(Rn+,d32) +8.0xfe+4.0xb,2.0,1.Y,1.1+4.fm,4.Rn+8.IMM32A+8.IMM32B+8.IMM32C+8.IMM32D:D5o:::fmov +"fmov" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else + { + int reg = translate_rreg (SD_, Rn); + store_dword (State.regs[reg] + + EXTEND32 (FETCH32 (IMM32A, IMM32B, + IMM32C, IMM32D)), Xf2FD (Y, fm)); + State.regs[reg] += 8; + } +} + +// 1111 1110 1011 01Y0 fm.- ---- d32; fmov FDm,(d32,SP) +8.0xfe+4.0xb,2.1,1.Y,1.0+4.fm,4.0+8.IMM32A+8.IMM32B+8.IMM32C+8.IMM32D:D5p:::fmov +"fmov" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else + { + int reg = REG_SP; + store_dword (State.regs[reg] + + FETCH32 (IMM32A, IMM32B, + IMM32C, IMM32D), Xf2FD (Y, fm)); + } +} + +// FPCR fmov: + +// 1111 1001 1011 0101 Rm.. ----; fmov Rm,FPCR +8.0xf9+8.0xb5+4.Rm,4.0:D1q:::fmov +"fmov" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else + { + int reg = translate_rreg (SD_, Rm); + unsigned32 val = State.regs[reg]; + FPCR = (val & (EC_MASK | EE_MASK | FCC_MASK)) + | ((FPCR & ~val) & EF_MASK); + } +} + +// 1111 1001 1011 0111 ---- Rn..; fmov FPCR,Rn +8.0xf9+8.0xb7+4.0,4.Rn:D1r:::fmov +"fmov" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else + { + int reg = translate_rreg (SD_, Rn); + State.regs[reg] = FPCR & FPCR_MASK; + } +} + +// 1111 1101 1011 0101 imm32; fmov imm32,FPCR +8.0xfd+8.0xb5+8.IMM32A+8.IMM32B+8.IMM32C+8.IMM32D:D5:::fmov +"fmov" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else + { + unsigned32 val = FETCH32 (IMM32A, IMM32B, IMM32C, IMM32D); + FPCR = (val & (EC_MASK | EE_MASK | FCC_MASK)) + | ((FPCR & ~val) & EF_MASK); + } +} + +// fabs: + +// 1111 1001 0100 010X ---- Sn..; fabs FSn +8.0xf9+4.4,3.2,1.X+4.0,4.Sn:D1a:::fabs +"fabs" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else + { + sim_fpu in, out; + + FS2FPU (XS2FS (X,Sn), in); + sim_fpu_abs (&out, &in); + FPU2FS (out, XS2FS (X,Sn)); + } +} + +// 1111 1001 1100 010X ---- Sn..; fabs FDn +8.0xf9+4.0xc,3.2,1.X+4.0,3.fn,1.0:D1b:::fabs +"fabs" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else + fpu_unimp_exception (SD, CPU, cia); +} + +// 1111 1011 0100 0100 Sm.. ---- Sn.. X-Z-; fabs FSm,FSn +8.0xfb+8.0x44+4.Sm,4.0+4.Sn,1.X,1.0,1.Z,1.0:D2a:::fabs +"fabs" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else + { + sim_fpu in, out; + + FS2FPU (XS2FS (X,Sm), in); + sim_fpu_abs (&out, &in); + FPU2FS (out, XS2FS (Z,Sn)); + } +} + +// 1111 1011 1100 0100 fm.- ---- fn.- X-Z-; fabs FDm,FDn +8.0xfb+8.0xc4+3.fm,1.0,4.0+3.fn,1.0,1.X,1.0,1.Z,1.0:D2b:::fabs +"fabs" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else + fpu_unimp_exception (SD, CPU, cia); +} + +// 1111 1001 0100 011X ---- Sn..; fneg FSn +8.0xf9+4.4,3.3,1.X+4.0,4.Sn:D1a:::fneg +"fneg" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else + { + sim_fpu in, out; + + FS2FPU (XS2FS (X,Sn), in); + sim_fpu_neg (&out, &in); + FPU2FS (out, XS2FS (X,Sn)); + } +} + +// 1111 1001 1100 011X ---- Sn..; fneg FDn +8.0xf9+4.0xc,3.3,1.X+4.0,3.fn,1.0:D1b:::fneg +"fneg" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else + fpu_unimp_exception (SD, CPU, cia); +} + +// 1111 1011 0100 0110 Sm.. ---- Sn.. X-Z-; fneg FSm,FSn +8.0xfb+8.0x46+4.Sm,4.0+4.Sn,1.X,1.0,1.Z,1.0:D2a:::fneg +"fneg" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else + { + sim_fpu in, out; + + FS2FPU (XS2FS (X,Sm), in); + sim_fpu_neg (&out, &in); + FPU2FS (out, XS2FS (Z,Sn)); + } +} + +// 1111 1011 1100 0110 fm.- ---- fn.- X-Z-; fneg FDm,FDn +8.0xfb+8.0xc6+3.fm,1.0,4.0+3.fn,1.0,1.X,1.0,1.Z,1.0:D2b:::fneg +"fneg" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else + fpu_unimp_exception (SD, CPU, cia); +} + +// 1111 1001 0101 000X ---- Sn..; frsqrt FSn +8.0xf9+4.5,3.0,1.X+4.0,4.Sn:D1a:::frsqrt +"frsqrt" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else + fpu_rsqrt (SD, CPU, cia, &XS2FS (X,Sn), &XS2FS (X,Sn), FP_SINGLE); +} + +// 1111 1001 1101 000X ---- fn.-; frsqrt FDn +8.0xf9+4.0xd,3.0,1.X+4.0,3.fn,1.0:D1b:::frsqrt +"frsqrt" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else + fpu_unimp_exception (SD, CPU, cia); +} + +// 1111 1011 0101 0000 Sm.. ---- Sn.. X-Z-; frsqrt FSm,FSn +8.0xfb+8.0x50+4.Sm,4.0+4.Sn,1.X,1.0,1.Z,1.0:D2a:::frsqrt +"frsqrt" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else + fpu_rsqrt (SD, CPU, cia, &XS2FS (X,Sm), &XS2FS (Z,Sn), FP_SINGLE); +} + +// 1111 1011 1101 0000 fm.- ---- fn.- X-Z-; frsqrt FDm,FDn +8.0xfb+8.0xd0+3.fm,1.0,4.0+3.fn,1.0,1.X,1.0,1.Z,1.0:D2b:::frsqrt +"frsqrt" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else + fpu_unimp_exception (SD, CPU, cia); +} + +// 1111 1001 0101 001X ---- Sn..; fsqrt FSn +8.0xf9+4.5,3.1,1.X+4.0,4.Sn:D1a:::fsqrt +"fsqrt" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else + fpu_unimp_exception (SD, CPU, cia); +} + +// 1111 1001 1101 001X ---- fn.-; fsqrt FDn +8.0xf9+4.0xd,3.1,1.X+4.0,3.fn,1.0:D1b:::fsqrt +"fsqrt" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else + fpu_unimp_exception (SD, CPU, cia); +} + +// 1111 1011 0101 0100 Sm.. ---- Sn.. X-Z-; fsqrt FSm,FSn +8.0xfb+8.0x54+4.Sm,4.0+4.Sn,1.X,1.0,1.Z,1.0:D2a:::fsqrt +"fsqrt" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else + fpu_unimp_exception (SD, CPU, cia); +} + +// 1111 1011 1101 0100 fm.- ---- fn.- X-Z-; fsqrt FDm,FDn +8.0xfb+8.0xd4+3.fm,1.0,4.0+3.fn,1.0,1.X,1.0,1.Z,1.0:D2b:::fsqrt +"fsqrt" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else + fpu_unimp_exception (SD, CPU, cia); +} + +// 1111 1001 0101 01YX Sm.. Sn..; fcmp FSm, FSn +8.0xf9+4.5,2.1,1.Y,1.X+4.Sm,4.Sn:D1a:::fcmp +"fcmp" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else + fpu_cmp (SD, CPU, cia, &XS2FS (X,Sn), &XS2FS (Y,Sm), FP_SINGLE); +} + +// 1111 1001 1101 01YX fm.- fn.-; fcmp FDm, FDn +8.0xf9+4.0xd,2.1,1.Y,1.X+3.fm,1.0,3.fn,1.0:D1b:::fcmp +"fcmp" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else + fpu_unimp_exception (SD, CPU, cia); +} + +// 1111 1110 0011 01Y1 Sm.. ---- IMM32; fcmp imm32, FSm +8.0xfe+4.3,2.1,1.Y,1.1+4.Sm,4.0+8.IMM32A+8.IMM32B+8.IMM32C+8.IMM32D:D5:::fcmp +"fcmp" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else + { + uint32 imm = FETCH32 (IMM32A, IMM32B, IMM32C, IMM32D); + + fpu_cmp (SD, CPU, cia, &XS2FS (Y,Sm), &imm, FP_SINGLE); + } +} + +// 1111 1001 0110 00YX Sm.. Sn..; fadd FSm, FSn +8.0xf9+4.6,2.0,1.Y,1.X+4.Sm,4.Sn:D1a:::fadd +"fadd" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else + fpu_add (SD, CPU, cia, + &XS2FS (Y,Sm), &XS2FS (X,Sn), &XS2FS (X,Sn), FP_SINGLE); +} + +// 1111 1001 1110 00YX fm.- fn.-; fadd FDm, FDn +8.0xf9+4.0xe,2.0,1.Y,1.X+3.fm,1.0,3.fn,1.0:D1b:::fadd +"fadd" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else + fpu_unimp_exception (SD, CPU, cia); +} + +// 1111 1011 0110 0000 Sm1. Sm2. Sn.. XYZ-; fadd FSm1, FSm2, FSn +8.0xfb+8.0x60+4.Sm1,4.Sm2+4.Sn,1.X,1.Y,1.Z,1.0:D2a:::fadd +"fadd" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else + fpu_add (SD, CPU, cia, + &XS2FS (X,Sm1), &XS2FS (Y,Sm2), &XS2FS (Z,Sn), FP_SINGLE); +} + +// 1111 1011 1110 0000 fm1- fm2- fn.- XYZ-; fadd FDm1, FDm2, FDn +8.0xfb+8.0xe0+3.fm1,1.0,3.fm2,1.0+3.fn,1.0,1.X,1.Y,1.Z,1.0:D2b:::fadd +"fadd" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else + fpu_unimp_exception (SD, CPU, cia); +} + + +// 1111 1110 0110 00YX Sm.. Sn.. IMM32; fadd imm32, FSm, FSn +8.0xfe+4.6,2.0,1.Y,1.X+4.Sm,4.Sn+8.IMM32A+8.IMM32B+8.IMM32C+8.IMM32D:D5:::fadd +"fadd" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else + { + uint32 imm = FETCH32 (IMM32A, IMM32B, IMM32C, IMM32D); + + fpu_add (SD, CPU, cia, + &XS2FS (Y,Sm), &imm, &XS2FS (X,Sn), FP_SINGLE); + } +} + +// 1111 1001 0110 01YX Sm.. Sn..; fsub FSm, FSn +8.0xf9+4.6,2.1,1.Y,1.X+4.Sm,4.Sn:D1a:::fsub +"fsub" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else + fpu_sub (SD, CPU, cia, + &XS2FS (X,Sn), &XS2FS (Y,Sm), &XS2FS (X,Sn), FP_SINGLE); +} + +// 1111 1001 1110 01YX fm.- fn.-; fsub FDm, FDn +8.0xf9+4.0xe,2.1,1.Y,1.X+3.fm,1.0,3.fn,1.0:D1b:::fsub +"fsub" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else + fpu_unimp_exception (SD, CPU, cia); +} + +// 1111 1011 0110 0100 Sm1. Sm2. Sn.. XYZ-; fsub FSm1, FSm2, FSn +8.0xfb+8.0x64+4.Sm1,4.Sm2+4.Sn,1.X,1.Y,1.Z,1.0:D2a:::fsub +"fsub" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else + fpu_sub (SD, CPU, cia, + &XS2FS (Y,Sm2), &XS2FS (X,Sm1), &XS2FS (Z,Sn), FP_SINGLE); +} + +// 1111 1011 1110 0100 fm1- fm2- fn.- XYZ-; fsub FDm1, FDm2, FDn +8.0xfb+8.0xe4+3.fm1,1.0,3.fm2,1.0+3.fn,1.0,1.X,1.Y,1.Z,1.0:D2b:::fsub +"fsub" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else + fpu_unimp_exception (SD, CPU, cia); +} + + +// 1111 1110 0110 01YX Sm.. Sn.. IMM32; fsub imm32, FSm, FSn +8.0xfe+4.6,2.1,1.Y,1.X+4.Sm,4.Sn+8.IMM32A+8.IMM32B+8.IMM32C+8.IMM32D:D5:::fsub +"fsub" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else + { + uint32 imm = FETCH32 (IMM32A, IMM32B, IMM32C, IMM32D); + + fpu_sub (SD, CPU, cia, + &XS2FS (Y,Sm), &imm, &XS2FS (X,Sn), FP_SINGLE); + } +} + +// 1111 1001 0111 00YX Sm.. Sn..; fmul FSm, FSn +8.0xf9+4.7,2.0,1.Y,1.X+4.Sm,4.Sn:D1a:::fmul +"fmul" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else + fpu_mul (SD, CPU, cia, + &XS2FS (Y,Sm), &XS2FS (X,Sn), &XS2FS (X,Sn), FP_SINGLE); +} + +// 1111 1001 1111 00YX fm.- fn.-; fmul FDm, FDn +8.0xf9+4.0xf,2.0,1.Y,1.X+3.fm,1.0,3.fn,1.0:D1b:::fmul +"fmul" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else + fpu_unimp_exception (SD, CPU, cia); +} + +// 1111 1011 0111 0000 Sm1. Sm2. Sn.. XYZ-; fmul FSm1, FSm2, FSn +8.0xfb+8.0x70+4.Sm1,4.Sm2+4.Sn,1.X,1.Y,1.Z,1.0:D2a:::fmul +"fmul" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else + fpu_mul (SD, CPU, cia, + &XS2FS (X,Sm1), &XS2FS (Y,Sm2), &XS2FS (Z,Sn), FP_SINGLE); +} + +// 1111 1011 1111 0000 fm1- fm2- fn.- XYZ-; fmul FDm1, FDm2, FDn +8.0xfb+8.0xf0+3.fm1,1.0,3.fm2,1.0+3.fn,1.0,1.X,1.Y,1.Z,1.0:D2b:::fmul +"fmul" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else + fpu_unimp_exception (SD, CPU, cia); +} + + +// 1111 1110 0111 00YX Sm.. Sn.. IMM32; fmul imm32, FSm, FSn +8.0xfe+4.7,2.0,1.Y,1.X+4.Sm,4.Sn+8.IMM32A+8.IMM32B+8.IMM32C+8.IMM32D:D5:::fmul +"fmul" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else + { + uint32 imm = FETCH32 (IMM32A, IMM32B, IMM32C, IMM32D); + + fpu_mul (SD, CPU, cia, + &imm, &XS2FS (Y,Sm), &XS2FS (X,Sn), FP_SINGLE); + } +} + +// 1111 1001 0111 01YX Sm.. Sn..; fdiv FSm, FSn +8.0xf9+4.7,2.1,1.Y,1.X+4.Sm,4.Sn:D1a:::fdiv +"fdiv" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else + fpu_div (SD, CPU, cia, + &XS2FS (X,Sn), &XS2FS (Y,Sm), &XS2FS (X,Sn), FP_SINGLE); +} + +// 1111 1001 1111 01YX fm.- fn.-; fdiv FDm, FDn +8.0xf9+4.0xf,2.1,1.Y,1.X+3.fm,1.0,3.fn,1.0:D1b:::fdiv +"fdiv" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else + fpu_unimp_exception (SD, CPU, cia); +} + +// 1111 1011 0111 0100 Sm1. Sm2. Sn.. XYZ-; fdiv FSm1, FSm2, FSn +8.0xfb+8.0x74+4.Sm1,4.Sm2+4.Sn,1.X,1.Y,1.Z,1.0:D2a:::fdiv +"fdiv" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else + fpu_div (SD, CPU, cia, + &XS2FS (Y,Sm2), &XS2FS (X,Sm1), &XS2FS (Z,Sn), FP_SINGLE); +} + +// 1111 1011 1111 0100 fm1- fm2- fn.- XYZ-; fdiv FDm1, FDm2, FDn +8.0xfb+8.0xf4+3.fm1,1.0,3.fm2,1.0+3.fn,1.0,1.X,1.Y,1.Z,1.0:D2b:::fdiv +"fdiv" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else + fpu_unimp_exception (SD, CPU, cia); +} + + +// 1111 1110 0111 01YX Sm.. Sn.. IMM32; fdiv imm32, FSm, FSn +8.0xfe+4.7,2.1,1.Y,1.X+4.Sm,4.Sn+8.IMM32A+8.IMM32B+8.IMM32C+8.IMM32D:D5:::fdiv +"fdiv" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else + { + uint32 imm = FETCH32 (IMM32A, IMM32B, IMM32C, IMM32D); + + fpu_div (SD, CPU, cia, + &XS2FS (Y,Sm), &imm, &XS2FS (X,Sn), FP_SINGLE); + } +} + +// 1111 1011 1000 00Sn Sm1. Sm2. Sm3. XYZA; fmadd FSm1, FSm2, FSm3, FSn +8.0xfb+4.8,2.0,2.Sn+4.Sm1,4.Sm2+4.Sm3,1.X,1.Y,1.Z,1.A:D2:::fmadd +"fmadd" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else + fpu_fmadd (SD, CPU, cia, + &XS2FS (X,Sm1), &XS2FS (Y,Sm2), &XS2FS (Z,Sm3), + &AS2FS (A,Sn), FP_SINGLE); +} + +// 1111 1011 1000 01Sn Sm1. Sm2. Sm3. XYZA; fmsub FSm1, FSm2, FSm3, FSn +8.0xfb+4.8,2.1,2.Sn+4.Sm1,4.Sm2+4.Sm3,1.X,1.Y,1.Z,1.A:D2:::fmsub +"fmsub" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else + fpu_fmsub (SD, CPU, cia, + &XS2FS (X,Sm1), &XS2FS (Y,Sm2), &XS2FS (Z,Sm3), + &AS2FS (A,Sn), FP_SINGLE); +} + +// 1111 1011 1001 00Sn Sm1. Sm2. Sm3. XYZA; fnmadd FSm1, FSm2, FSm3, FSn +8.0xfb+4.9,2.0,2.Sn+4.Sm1,4.Sm2+4.Sm3,1.X,1.Y,1.Z,1.A:D2:::fnmadd +"fnmadd" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else + fpu_fnmadd (SD, CPU, cia, + &XS2FS (X,Sm1), &XS2FS (Y,Sm2), &XS2FS (Z,Sm3), + &AS2FS (A,Sn), FP_SINGLE); +} + +// 1111 1011 1001 01Sn Sm1. Sm2. Sm3. XYZA; fnmsub FSm1, FSm2, FSm3, FSn +8.0xfb+4.9,2.1,2.Sn+4.Sm1,4.Sm2+4.Sm3,1.X,1.Y,1.Z,1.A:D2:::fnmsub +"fnmsub" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else + fpu_fnmsub (SD, CPU, cia, + &XS2FS (X,Sm1), &XS2FS (Y,Sm2), &XS2FS (Z,Sm3), + &AS2FS (A,Sn), FP_SINGLE); +} + +// conversion: + +// 1111 1011 0100 0000 Sm.. ---- Sn.. X-Z-; ftoi FSm,FSn +8.0xfb+8.0x40+4.Sm,4.0+4.Sn,1.X,1.0,1.Z,1.0:D2:::ftoi +"ftoi" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else + fpu_unimp_exception (SD, CPU, cia); +} + +// 1111 1011 0100 0010 Sm.. ---- Sn.. X-Z-; itof FSm,FSn +8.0xfb+8.0x42+4.Sm,4.0+4.Sn,1.X,1.0,1.Z,1.0:D2:::itof +"itof" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else + fpu_unimp_exception (SD, CPU, cia); +} + +// 1111 1011 0101 0010 Sm.. ---- fn.- X-Z-; ftod FSm,FDn +8.0xfb+8.0x52+4.Sm,4.0+3.fn,1.0,1.X,1.0,1.Z,1.0:D2:::ftod +"ftod" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else + fpu_unimp_exception (SD, CPU, cia); +} + +// 1111 1011 0101 0110 fm.- ---- Sn.. X-Z-; dtof FDm,FSn +8.0xfb+8.0x56+3.fm,1.0,4.0+4.Sn,1.X,1.0,1.Z,1.0:D2:::dtof +"dtof" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else + fpu_unimp_exception (SD, CPU, cia); +} + +// branching: + +// 1111 1000 1101 0000 d8; fbeq (d8,PC) (d8 is sign-extended) +8.0xf8+8.0xd0+8.D8:D1:::fbeq +"fbeq" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else if ((FPCR & FCC_E)) + { + State.regs[REG_PC] += EXTEND8 (D8); + nia = PC; + } +} + +// 1111 1000 1101 0001 d8; fbne (d8,PC) (d8 is sign-extended) +8.0xf8+8.0xd1+8.D8:D1:::fbne +"fbne" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else if ((FPCR & (FCC_U | FCC_L | FCC_G))) + { + State.regs[REG_PC] += EXTEND8 (D8); + nia = PC; + } +} + +// 1111 1000 1101 0010 d8; fbgt (d8,PC) (d8 is sign-extended) +8.0xf8+8.0xd2+8.D8:D1:::fbgt +"fbgt" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else if ((FPCR & FCC_G)) + { + State.regs[REG_PC] += EXTEND8 (D8); + nia = PC; + } +} + +// 1111 1000 1101 0011 d8; fbge (d8,PC) (d8 is sign-extended) +8.0xf8+8.0xd3+8.D8:D1:::fbge +"fbge" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else if ((FPCR & (FCC_G | FCC_E))) + { + State.regs[REG_PC] += EXTEND8 (D8); + nia = PC; + } +} + +// 1111 1000 1101 0100 d8; fblt (d8,PC) (d8 is sign-extended) +8.0xf8+8.0xd4+8.D8:D1:::fblt +"fblt" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else if ((FPCR & FCC_L)) + { + State.regs[REG_PC] += EXTEND8 (D8); + nia = PC; + } +} + +// 1111 1000 1101 0101 d8; fble (d8,PC) (d8 is sign-extended) +8.0xf8+8.0xd5+8.D8:D1:::fble +"fble" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else if ((FPCR & (FCC_L | FCC_E))) + { + State.regs[REG_PC] += EXTEND8 (D8); + nia = PC; + } +} + +// 1111 1000 1101 0110 d8; fbuo (d8,PC) (d8 is sign-extended) +8.0xf8+8.0xd6+8.D8:D1:::fbuo +"fbuo" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else if ((FPCR & FCC_U)) + { + State.regs[REG_PC] += EXTEND8 (D8); + nia = PC; + } +} + +// 1111 1000 1101 0111 d8; fblg (d8,PC) (d8 is sign-extended) +8.0xf8+8.0xd7+8.D8:D1:::fblg +"fblg" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else if ((FPCR & (FCC_L | FCC_G))) + { + State.regs[REG_PC] += EXTEND8 (D8); + nia = PC; + } +} +// 1111 1000 1101 1000 d8; fbleg (d8,PC) (d8 is sign-extended) +8.0xf8+8.0xd8+8.D8:D1:::fbleg +"fbleg" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else if ((FPCR & (FCC_L | FCC_E | FCC_G))) + { + State.regs[REG_PC] += EXTEND8 (D8); + nia = PC; + } +} + +// 1111 1000 1101 1001 d8; fbug (d8,PC) (d8 is sign-extended) +8.0xf8+8.0xd9+8.D8:D1:::fbug +"fbug" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else if ((FPCR & (FCC_U | FCC_G))) + { + State.regs[REG_PC] += EXTEND8 (D8); + nia = PC; + } +} + +// 1111 1000 1101 1010 d8; fbuge (d8,PC) (d8 is sign-extended) +8.0xf8+8.0xda+8.D8:D1:::fbuge +"fbuge" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else if ((FPCR & (FCC_U | FCC_G | FCC_E))) + { + State.regs[REG_PC] += EXTEND8 (D8); + nia = PC; + } +} + +// 1111 1000 1101 1011 d8; fbul (d8,PC) (d8 is sign-extended) +8.0xf8+8.0xdb+8.D8:D1:::fbul +"fbul" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else if ((FPCR & (FCC_U | FCC_L))) + { + State.regs[REG_PC] += EXTEND8 (D8); + nia = PC; + } +} + +// 1111 1000 1101 1100 d8; fbule (d8,PC) (d8 is sign-extended) +8.0xf8+8.0xdc+8.D8:D1:::fbule +"fbule" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else if ((FPCR & (FCC_U | FCC_L | FCC_E))) + { + State.regs[REG_PC] += EXTEND8 (D8); + nia = PC; + } +} + +// 1111 1000 1101 1101 d8; fbue (d8,PC) (d8 is sign-extended) +8.0xf8+8.0xdd+8.D8:D1:::fbue +"fbue" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else if ((FPCR & (FCC_U | FCC_E))) + { + State.regs[REG_PC] += EXTEND8 (D8); + nia = PC; + } +} + +// 1111 0000 1101 0000; fleq +8.0xf0+8.0xd0:D0:::fleq +"fleq" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else if ((FPCR & FCC_E)) + { + State.regs[REG_PC] = State.regs[REG_LAR] - 4; + nia = PC; + } +} + +// 1111 0000 1101 0001; flne +8.0xf0+8.0xd1:D0:::flne +"flne" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else if ((FPCR & (FCC_U | FCC_L | FCC_G))) + { + State.regs[REG_PC] = State.regs[REG_LAR] - 4; + nia = PC; + } +} + +// 1111 0000 1101 0010; flgt +8.0xf0+8.0xd2:D0:::flgt +"flgt" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else if ((FPCR & FCC_G)) + { + State.regs[REG_PC] = State.regs[REG_LAR] - 4; + nia = PC; + } +} + +// 1111 0000 1101 0011; flge +8.0xf0+8.0xd3:D0:::flge +"flge" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else if ((FPCR & (FCC_G | FCC_E))) + { + State.regs[REG_PC] = State.regs[REG_LAR] - 4; + nia = PC; + } +} + +// 1111 0000 1101 0100; fllt +8.0xf0+8.0xd4:D0:::fllt +"fllt" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else if ((FPCR & FCC_L)) + { + State.regs[REG_PC] = State.regs[REG_LAR] - 4; + nia = PC; + } +} + +// 1111 0000 1101 0101; flle +8.0xf0+8.0xd5:D0:::flle +"flle" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else if ((FPCR & (FCC_L | FCC_E))) + { + State.regs[REG_PC] = State.regs[REG_LAR] - 4; + nia = PC; + } +} + +// 1111 0000 1101 0110; fluo +8.0xf0+8.0xd6:D0:::fluo +"fluo" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else if ((FPCR & FCC_U)) + { + State.regs[REG_PC] = State.regs[REG_LAR] - 4; + nia = PC; + } +} + +// 1111 0000 1101 0111; fllg +8.0xf0+8.0xd7:D0:::fllg +"fllg" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else if ((FPCR & (FCC_L | FCC_G))) + { + State.regs[REG_PC] = State.regs[REG_LAR] - 4; + nia = PC; + } +} +// 1111 0000 1101 1000; flleg +8.0xf0+8.0xd8:D0:::flleg +"flleg" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else if ((FPCR & (FCC_L | FCC_E | FCC_G))) + { + State.regs[REG_PC] = State.regs[REG_LAR] - 4; + nia = PC; + } +} + +// 1111 0000 1101 1001; flug +8.0xf0+8.0xd9:D0:::flug +"flug" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else if ((FPCR & (FCC_U | FCC_G))) + { + State.regs[REG_PC] = State.regs[REG_LAR] - 4; + nia = PC; + } +} + +// 1111 0000 1101 1010; fluge +8.0xf0+8.0xda:D0:::fluge +"fluge" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else if ((FPCR & (FCC_U | FCC_G | FCC_E))) + { + State.regs[REG_PC] = State.regs[REG_LAR] - 4; + nia = PC; + } +} + +// 1111 0000 1101 1011; flul +8.0xf0+8.0xdb:D0:::flul +"flul" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else if ((FPCR & (FCC_U | FCC_L))) + { + State.regs[REG_PC] = State.regs[REG_LAR] - 4; + nia = PC; + } +} + +// 1111 0000 1101 1100; flule +8.0xf0+8.0xdc:D0:::flule +"flule" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else if ((FPCR & (FCC_U | FCC_L | FCC_E))) + { + State.regs[REG_PC] = State.regs[REG_LAR] - 4; + nia = PC; + } +} + +// 1111 0000 1101 1101; flue +8.0xf0+8.0xdd:D0:::flue +"flue" +*am33_2 +{ + PC = cia; + + if (FPU_DISABLED) + fpu_disabled_exception (SD, CPU, cia); + else if ((FPCR & (FCC_U | FCC_E))) + { + State.regs[REG_PC] = State.regs[REG_LAR] - 4; + nia = PC; + } +} diff --git a/sim/ppc/gdb-sim.c b/sim/ppc/gdb-sim.c new file mode 100644 index 00000000000..648d8ef1285 --- /dev/null +++ b/sim/ppc/gdb-sim.c @@ -0,0 +1,1295 @@ +/* This file is part of GDB. + + Copyright 2004 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + */ + + +#include "psim.h" +#include "options.h" +#include "registers.h" + +#include "ansidecl.h" +#include "sim_callbacks.h" +#include "gdb/callback.h" +#include "gdb/remote-sim.h" +#include "gdb/sim-ppc.h" + +/* Return the name of the register whose number is REGNUM, or zero if + REGNUM is an invalid register number. */ + +static const char * +regnum2spr (int spr) +{ + if (spr_is_valid (spr)) + return spr_name (spr); + else + return NULL; +} + +static const char * +regnum2name (int regnum) +{ + switch (regnum) + { + case sim_ppc_r0_regnum: return "r0"; + case sim_ppc_r1_regnum: return "r1"; + case sim_ppc_r2_regnum: return "r2"; + case sim_ppc_r3_regnum: return "r3"; + case sim_ppc_r4_regnum: return "r4"; + case sim_ppc_r5_regnum: return "r5"; + case sim_ppc_r6_regnum: return "r6"; + case sim_ppc_r7_regnum: return "r7"; + case sim_ppc_r8_regnum: return "r8"; + case sim_ppc_r9_regnum: return "r9"; + case sim_ppc_r10_regnum: return "r10"; + case sim_ppc_r11_regnum: return "r11"; + case sim_ppc_r12_regnum: return "r12"; + case sim_ppc_r13_regnum: return "r13"; + case sim_ppc_r14_regnum: return "r14"; + case sim_ppc_r15_regnum: return "r15"; + case sim_ppc_r16_regnum: return "r16"; + case sim_ppc_r17_regnum: return "r17"; + case sim_ppc_r18_regnum: return "r18"; + case sim_ppc_r19_regnum: return "r19"; + case sim_ppc_r20_regnum: return "r20"; + case sim_ppc_r21_regnum: return "r21"; + case sim_ppc_r22_regnum: return "r22"; + case sim_ppc_r23_regnum: return "r23"; + case sim_ppc_r24_regnum: return "r24"; + case sim_ppc_r25_regnum: return "r25"; + case sim_ppc_r26_regnum: return "r26"; + case sim_ppc_r27_regnum: return "r27"; + case sim_ppc_r28_regnum: return "r28"; + case sim_ppc_r29_regnum: return "r29"; + case sim_ppc_r30_regnum: return "r30"; + case sim_ppc_r31_regnum: return "r31"; + + case sim_ppc_f0_regnum: return "f0"; + case sim_ppc_f1_regnum: return "f1"; + case sim_ppc_f2_regnum: return "f2"; + case sim_ppc_f3_regnum: return "f3"; + case sim_ppc_f4_regnum: return "f4"; + case sim_ppc_f5_regnum: return "f5"; + case sim_ppc_f6_regnum: return "f6"; + case sim_ppc_f7_regnum: return "f7"; + case sim_ppc_f8_regnum: return "f8"; + case sim_ppc_f9_regnum: return "f9"; + case sim_ppc_f10_regnum: return "f10"; + case sim_ppc_f11_regnum: return "f11"; + case sim_ppc_f12_regnum: return "f12"; + case sim_ppc_f13_regnum: return "f13"; + case sim_ppc_f14_regnum: return "f14"; + case sim_ppc_f15_regnum: return "f15"; + case sim_ppc_f16_regnum: return "f16"; + case sim_ppc_f17_regnum: return "f17"; + case sim_ppc_f18_regnum: return "f18"; + case sim_ppc_f19_regnum: return "f19"; + case sim_ppc_f20_regnum: return "f20"; + case sim_ppc_f21_regnum: return "f21"; + case sim_ppc_f22_regnum: return "f22"; + case sim_ppc_f23_regnum: return "f23"; + case sim_ppc_f24_regnum: return "f24"; + case sim_ppc_f25_regnum: return "f25"; + case sim_ppc_f26_regnum: return "f26"; + case sim_ppc_f27_regnum: return "f27"; + case sim_ppc_f28_regnum: return "f28"; + case sim_ppc_f29_regnum: return "f29"; + case sim_ppc_f30_regnum: return "f30"; + case sim_ppc_f31_regnum: return "f31"; + + case sim_ppc_vr0_regnum: return "vr0"; + case sim_ppc_vr1_regnum: return "vr1"; + case sim_ppc_vr2_regnum: return "vr2"; + case sim_ppc_vr3_regnum: return "vr3"; + case sim_ppc_vr4_regnum: return "vr4"; + case sim_ppc_vr5_regnum: return "vr5"; + case sim_ppc_vr6_regnum: return "vr6"; + case sim_ppc_vr7_regnum: return "vr7"; + case sim_ppc_vr8_regnum: return "vr8"; + case sim_ppc_vr9_regnum: return "vr9"; + case sim_ppc_vr10_regnum: return "vr10"; + case sim_ppc_vr11_regnum: return "vr11"; + case sim_ppc_vr12_regnum: return "vr12"; + case sim_ppc_vr13_regnum: return "vr13"; + case sim_ppc_vr14_regnum: return "vr14"; + case sim_ppc_vr15_regnum: return "vr15"; + case sim_ppc_vr16_regnum: return "vr16"; + case sim_ppc_vr17_regnum: return "vr17"; + case sim_ppc_vr18_regnum: return "vr18"; + case sim_ppc_vr19_regnum: return "vr19"; + case sim_ppc_vr20_regnum: return "vr20"; + case sim_ppc_vr21_regnum: return "vr21"; + case sim_ppc_vr22_regnum: return "vr22"; + case sim_ppc_vr23_regnum: return "vr23"; + case sim_ppc_vr24_regnum: return "vr24"; + case sim_ppc_vr25_regnum: return "vr25"; + case sim_ppc_vr26_regnum: return "vr26"; + case sim_ppc_vr27_regnum: return "vr27"; + case sim_ppc_vr28_regnum: return "vr28"; + case sim_ppc_vr29_regnum: return "vr29"; + case sim_ppc_vr30_regnum: return "vr30"; + case sim_ppc_vr31_regnum: return "vr31"; + case sim_ppc_rh0_regnum: return "rh0"; + case sim_ppc_rh1_regnum: return "rh1"; + case sim_ppc_rh2_regnum: return "rh2"; + case sim_ppc_rh3_regnum: return "rh3"; + case sim_ppc_rh4_regnum: return "rh4"; + case sim_ppc_rh5_regnum: return "rh5"; + case sim_ppc_rh6_regnum: return "rh6"; + case sim_ppc_rh7_regnum: return "rh7"; + case sim_ppc_rh8_regnum: return "rh8"; + case sim_ppc_rh9_regnum: return "rh9"; + case sim_ppc_rh10_regnum: return "rh10"; + case sim_ppc_rh11_regnum: return "rh11"; + case sim_ppc_rh12_regnum: return "rh12"; + case sim_ppc_rh13_regnum: return "rh13"; + case sim_ppc_rh14_regnum: return "rh14"; + case sim_ppc_rh15_regnum: return "rh15"; + case sim_ppc_rh16_regnum: return "rh16"; + case sim_ppc_rh17_regnum: return "rh17"; + case sim_ppc_rh18_regnum: return "rh18"; + case sim_ppc_rh19_regnum: return "rh19"; + case sim_ppc_rh20_regnum: return "rh20"; + case sim_ppc_rh21_regnum: return "rh21"; + case sim_ppc_rh22_regnum: return "rh22"; + case sim_ppc_rh23_regnum: return "rh23"; + case sim_ppc_rh24_regnum: return "rh24"; + case sim_ppc_rh25_regnum: return "rh25"; + case sim_ppc_rh26_regnum: return "rh26"; + case sim_ppc_rh27_regnum: return "rh27"; + case sim_ppc_rh28_regnum: return "rh28"; + case sim_ppc_rh29_regnum: return "rh29"; + case sim_ppc_rh30_regnum: return "rh30"; + case sim_ppc_rh31_regnum: return "rh31"; + + case sim_ppc_ev0_regnum: return "ev0"; + case sim_ppc_ev1_regnum: return "ev1"; + case sim_ppc_ev2_regnum: return "ev2"; + case sim_ppc_ev3_regnum: return "ev3"; + case sim_ppc_ev4_regnum: return "ev4"; + case sim_ppc_ev5_regnum: return "ev5"; + case sim_ppc_ev6_regnum: return "ev6"; + case sim_ppc_ev7_regnum: return "ev7"; + case sim_ppc_ev8_regnum: return "ev8"; + case sim_ppc_ev9_regnum: return "ev9"; + case sim_ppc_ev10_regnum: return "ev10"; + case sim_ppc_ev11_regnum: return "ev11"; + case sim_ppc_ev12_regnum: return "ev12"; + case sim_ppc_ev13_regnum: return "ev13"; + case sim_ppc_ev14_regnum: return "ev14"; + case sim_ppc_ev15_regnum: return "ev15"; + case sim_ppc_ev16_regnum: return "ev16"; + case sim_ppc_ev17_regnum: return "ev17"; + case sim_ppc_ev18_regnum: return "ev18"; + case sim_ppc_ev19_regnum: return "ev19"; + case sim_ppc_ev20_regnum: return "ev20"; + case sim_ppc_ev21_regnum: return "ev21"; + case sim_ppc_ev22_regnum: return "ev22"; + case sim_ppc_ev23_regnum: return "ev23"; + case sim_ppc_ev24_regnum: return "ev24"; + case sim_ppc_ev25_regnum: return "ev25"; + case sim_ppc_ev26_regnum: return "ev26"; + case sim_ppc_ev27_regnum: return "ev27"; + case sim_ppc_ev28_regnum: return "ev28"; + case sim_ppc_ev29_regnum: return "ev29"; + case sim_ppc_ev30_regnum: return "ev30"; + case sim_ppc_ev31_regnum: return "ev31"; + + case sim_ppc_sr0_regnum: return "sr0"; + case sim_ppc_sr1_regnum: return "sr1"; + case sim_ppc_sr2_regnum: return "sr2"; + case sim_ppc_sr3_regnum: return "sr3"; + case sim_ppc_sr4_regnum: return "sr4"; + case sim_ppc_sr5_regnum: return "sr5"; + case sim_ppc_sr6_regnum: return "sr6"; + case sim_ppc_sr7_regnum: return "sr7"; + case sim_ppc_sr8_regnum: return "sr8"; + case sim_ppc_sr9_regnum: return "sr9"; + case sim_ppc_sr10_regnum: return "sr10"; + case sim_ppc_sr11_regnum: return "sr11"; + case sim_ppc_sr12_regnum: return "sr12"; + case sim_ppc_sr13_regnum: return "sr13"; + case sim_ppc_sr14_regnum: return "sr14"; + case sim_ppc_sr15_regnum: return "sr15"; + + case sim_ppc_pc_regnum: return "pc"; + case sim_ppc_ps_regnum: return "ps"; + case sim_ppc_cr_regnum: return "cr"; + case sim_ppc_fpscr_regnum: return "fpscr"; + case sim_ppc_acc_regnum: return "acc"; + case sim_ppc_vscr_regnum: return "vscr"; + + case sim_ppc_spr0_regnum: return regnum2spr (0); + case sim_ppc_spr1_regnum: return regnum2spr (1); + case sim_ppc_spr2_regnum: return regnum2spr (2); + case sim_ppc_spr3_regnum: return regnum2spr (3); + case sim_ppc_spr4_regnum: return regnum2spr (4); + case sim_ppc_spr5_regnum: return regnum2spr (5); + case sim_ppc_spr6_regnum: return regnum2spr (6); + case sim_ppc_spr7_regnum: return regnum2spr (7); + case sim_ppc_spr8_regnum: return regnum2spr (8); + case sim_ppc_spr9_regnum: return regnum2spr (9); + case sim_ppc_spr10_regnum: return regnum2spr (10); + case sim_ppc_spr11_regnum: return regnum2spr (11); + case sim_ppc_spr12_regnum: return regnum2spr (12); + case sim_ppc_spr13_regnum: return regnum2spr (13); + case sim_ppc_spr14_regnum: return regnum2spr (14); + case sim_ppc_spr15_regnum: return regnum2spr (15); + case sim_ppc_spr16_regnum: return regnum2spr (16); + case sim_ppc_spr17_regnum: return regnum2spr (17); + case sim_ppc_spr18_regnum: return regnum2spr (18); + case sim_ppc_spr19_regnum: return regnum2spr (19); + case sim_ppc_spr20_regnum: return regnum2spr (20); + case sim_ppc_spr21_regnum: return regnum2spr (21); + case sim_ppc_spr22_regnum: return regnum2spr (22); + case sim_ppc_spr23_regnum: return regnum2spr (23); + case sim_ppc_spr24_regnum: return regnum2spr (24); + case sim_ppc_spr25_regnum: return regnum2spr (25); + case sim_ppc_spr26_regnum: return regnum2spr (26); + case sim_ppc_spr27_regnum: return regnum2spr (27); + case sim_ppc_spr28_regnum: return regnum2spr (28); + case sim_ppc_spr29_regnum: return regnum2spr (29); + case sim_ppc_spr30_regnum: return regnum2spr (30); + case sim_ppc_spr31_regnum: return regnum2spr (31); + case sim_ppc_spr32_regnum: return regnum2spr (32); + case sim_ppc_spr33_regnum: return regnum2spr (33); + case sim_ppc_spr34_regnum: return regnum2spr (34); + case sim_ppc_spr35_regnum: return regnum2spr (35); + case sim_ppc_spr36_regnum: return regnum2spr (36); + case sim_ppc_spr37_regnum: return regnum2spr (37); + case sim_ppc_spr38_regnum: return regnum2spr (38); + case sim_ppc_spr39_regnum: return regnum2spr (39); + case sim_ppc_spr40_regnum: return regnum2spr (40); + case sim_ppc_spr41_regnum: return regnum2spr (41); + case sim_ppc_spr42_regnum: return regnum2spr (42); + case sim_ppc_spr43_regnum: return regnum2spr (43); + case sim_ppc_spr44_regnum: return regnum2spr (44); + case sim_ppc_spr45_regnum: return regnum2spr (45); + case sim_ppc_spr46_regnum: return regnum2spr (46); + case sim_ppc_spr47_regnum: return regnum2spr (47); + case sim_ppc_spr48_regnum: return regnum2spr (48); + case sim_ppc_spr49_regnum: return regnum2spr (49); + case sim_ppc_spr50_regnum: return regnum2spr (50); + case sim_ppc_spr51_regnum: return regnum2spr (51); + case sim_ppc_spr52_regnum: return regnum2spr (52); + case sim_ppc_spr53_regnum: return regnum2spr (53); + case sim_ppc_spr54_regnum: return regnum2spr (54); + case sim_ppc_spr55_regnum: return regnum2spr (55); + case sim_ppc_spr56_regnum: return regnum2spr (56); + case sim_ppc_spr57_regnum: return regnum2spr (57); + case sim_ppc_spr58_regnum: return regnum2spr (58); + case sim_ppc_spr59_regnum: return regnum2spr (59); + case sim_ppc_spr60_regnum: return regnum2spr (60); + case sim_ppc_spr61_regnum: return regnum2spr (61); + case sim_ppc_spr62_regnum: return regnum2spr (62); + case sim_ppc_spr63_regnum: return regnum2spr (63); + case sim_ppc_spr64_regnum: return regnum2spr (64); + case sim_ppc_spr65_regnum: return regnum2spr (65); + case sim_ppc_spr66_regnum: return regnum2spr (66); + case sim_ppc_spr67_regnum: return regnum2spr (67); + case sim_ppc_spr68_regnum: return regnum2spr (68); + case sim_ppc_spr69_regnum: return regnum2spr (69); + case sim_ppc_spr70_regnum: return regnum2spr (70); + case sim_ppc_spr71_regnum: return regnum2spr (71); + case sim_ppc_spr72_regnum: return regnum2spr (72); + case sim_ppc_spr73_regnum: return regnum2spr (73); + case sim_ppc_spr74_regnum: return regnum2spr (74); + case sim_ppc_spr75_regnum: return regnum2spr (75); + case sim_ppc_spr76_regnum: return regnum2spr (76); + case sim_ppc_spr77_regnum: return regnum2spr (77); + case sim_ppc_spr78_regnum: return regnum2spr (78); + case sim_ppc_spr79_regnum: return regnum2spr (79); + case sim_ppc_spr80_regnum: return regnum2spr (80); + case sim_ppc_spr81_regnum: return regnum2spr (81); + case sim_ppc_spr82_regnum: return regnum2spr (82); + case sim_ppc_spr83_regnum: return regnum2spr (83); + case sim_ppc_spr84_regnum: return regnum2spr (84); + case sim_ppc_spr85_regnum: return regnum2spr (85); + case sim_ppc_spr86_regnum: return regnum2spr (86); + case sim_ppc_spr87_regnum: return regnum2spr (87); + case sim_ppc_spr88_regnum: return regnum2spr (88); + case sim_ppc_spr89_regnum: return regnum2spr (89); + case sim_ppc_spr90_regnum: return regnum2spr (90); + case sim_ppc_spr91_regnum: return regnum2spr (91); + case sim_ppc_spr92_regnum: return regnum2spr (92); + case sim_ppc_spr93_regnum: return regnum2spr (93); + case sim_ppc_spr94_regnum: return regnum2spr (94); + case sim_ppc_spr95_regnum: return regnum2spr (95); + case sim_ppc_spr96_regnum: return regnum2spr (96); + case sim_ppc_spr97_regnum: return regnum2spr (97); + case sim_ppc_spr98_regnum: return regnum2spr (98); + case sim_ppc_spr99_regnum: return regnum2spr (99); + case sim_ppc_spr100_regnum: return regnum2spr (100); + case sim_ppc_spr101_regnum: return regnum2spr (101); + case sim_ppc_spr102_regnum: return regnum2spr (102); + case sim_ppc_spr103_regnum: return regnum2spr (103); + case sim_ppc_spr104_regnum: return regnum2spr (104); + case sim_ppc_spr105_regnum: return regnum2spr (105); + case sim_ppc_spr106_regnum: return regnum2spr (106); + case sim_ppc_spr107_regnum: return regnum2spr (107); + case sim_ppc_spr108_regnum: return regnum2spr (108); + case sim_ppc_spr109_regnum: return regnum2spr (109); + case sim_ppc_spr110_regnum: return regnum2spr (110); + case sim_ppc_spr111_regnum: return regnum2spr (111); + case sim_ppc_spr112_regnum: return regnum2spr (112); + case sim_ppc_spr113_regnum: return regnum2spr (113); + case sim_ppc_spr114_regnum: return regnum2spr (114); + case sim_ppc_spr115_regnum: return regnum2spr (115); + case sim_ppc_spr116_regnum: return regnum2spr (116); + case sim_ppc_spr117_regnum: return regnum2spr (117); + case sim_ppc_spr118_regnum: return regnum2spr (118); + case sim_ppc_spr119_regnum: return regnum2spr (119); + case sim_ppc_spr120_regnum: return regnum2spr (120); + case sim_ppc_spr121_regnum: return regnum2spr (121); + case sim_ppc_spr122_regnum: return regnum2spr (122); + case sim_ppc_spr123_regnum: return regnum2spr (123); + case sim_ppc_spr124_regnum: return regnum2spr (124); + case sim_ppc_spr125_regnum: return regnum2spr (125); + case sim_ppc_spr126_regnum: return regnum2spr (126); + case sim_ppc_spr127_regnum: return regnum2spr (127); + case sim_ppc_spr128_regnum: return regnum2spr (128); + case sim_ppc_spr129_regnum: return regnum2spr (129); + case sim_ppc_spr130_regnum: return regnum2spr (130); + case sim_ppc_spr131_regnum: return regnum2spr (131); + case sim_ppc_spr132_regnum: return regnum2spr (132); + case sim_ppc_spr133_regnum: return regnum2spr (133); + case sim_ppc_spr134_regnum: return regnum2spr (134); + case sim_ppc_spr135_regnum: return regnum2spr (135); + case sim_ppc_spr136_regnum: return regnum2spr (136); + case sim_ppc_spr137_regnum: return regnum2spr (137); + case sim_ppc_spr138_regnum: return regnum2spr (138); + case sim_ppc_spr139_regnum: return regnum2spr (139); + case sim_ppc_spr140_regnum: return regnum2spr (140); + case sim_ppc_spr141_regnum: return regnum2spr (141); + case sim_ppc_spr142_regnum: return regnum2spr (142); + case sim_ppc_spr143_regnum: return regnum2spr (143); + case sim_ppc_spr144_regnum: return regnum2spr (144); + case sim_ppc_spr145_regnum: return regnum2spr (145); + case sim_ppc_spr146_regnum: return regnum2spr (146); + case sim_ppc_spr147_regnum: return regnum2spr (147); + case sim_ppc_spr148_regnum: return regnum2spr (148); + case sim_ppc_spr149_regnum: return regnum2spr (149); + case sim_ppc_spr150_regnum: return regnum2spr (150); + case sim_ppc_spr151_regnum: return regnum2spr (151); + case sim_ppc_spr152_regnum: return regnum2spr (152); + case sim_ppc_spr153_regnum: return regnum2spr (153); + case sim_ppc_spr154_regnum: return regnum2spr (154); + case sim_ppc_spr155_regnum: return regnum2spr (155); + case sim_ppc_spr156_regnum: return regnum2spr (156); + case sim_ppc_spr157_regnum: return regnum2spr (157); + case sim_ppc_spr158_regnum: return regnum2spr (158); + case sim_ppc_spr159_regnum: return regnum2spr (159); + case sim_ppc_spr160_regnum: return regnum2spr (160); + case sim_ppc_spr161_regnum: return regnum2spr (161); + case sim_ppc_spr162_regnum: return regnum2spr (162); + case sim_ppc_spr163_regnum: return regnum2spr (163); + case sim_ppc_spr164_regnum: return regnum2spr (164); + case sim_ppc_spr165_regnum: return regnum2spr (165); + case sim_ppc_spr166_regnum: return regnum2spr (166); + case sim_ppc_spr167_regnum: return regnum2spr (167); + case sim_ppc_spr168_regnum: return regnum2spr (168); + case sim_ppc_spr169_regnum: return regnum2spr (169); + case sim_ppc_spr170_regnum: return regnum2spr (170); + case sim_ppc_spr171_regnum: return regnum2spr (171); + case sim_ppc_spr172_regnum: return regnum2spr (172); + case sim_ppc_spr173_regnum: return regnum2spr (173); + case sim_ppc_spr174_regnum: return regnum2spr (174); + case sim_ppc_spr175_regnum: return regnum2spr (175); + case sim_ppc_spr176_regnum: return regnum2spr (176); + case sim_ppc_spr177_regnum: return regnum2spr (177); + case sim_ppc_spr178_regnum: return regnum2spr (178); + case sim_ppc_spr179_regnum: return regnum2spr (179); + case sim_ppc_spr180_regnum: return regnum2spr (180); + case sim_ppc_spr181_regnum: return regnum2spr (181); + case sim_ppc_spr182_regnum: return regnum2spr (182); + case sim_ppc_spr183_regnum: return regnum2spr (183); + case sim_ppc_spr184_regnum: return regnum2spr (184); + case sim_ppc_spr185_regnum: return regnum2spr (185); + case sim_ppc_spr186_regnum: return regnum2spr (186); + case sim_ppc_spr187_regnum: return regnum2spr (187); + case sim_ppc_spr188_regnum: return regnum2spr (188); + case sim_ppc_spr189_regnum: return regnum2spr (189); + case sim_ppc_spr190_regnum: return regnum2spr (190); + case sim_ppc_spr191_regnum: return regnum2spr (191); + case sim_ppc_spr192_regnum: return regnum2spr (192); + case sim_ppc_spr193_regnum: return regnum2spr (193); + case sim_ppc_spr194_regnum: return regnum2spr (194); + case sim_ppc_spr195_regnum: return regnum2spr (195); + case sim_ppc_spr196_regnum: return regnum2spr (196); + case sim_ppc_spr197_regnum: return regnum2spr (197); + case sim_ppc_spr198_regnum: return regnum2spr (198); + case sim_ppc_spr199_regnum: return regnum2spr (199); + case sim_ppc_spr200_regnum: return regnum2spr (200); + case sim_ppc_spr201_regnum: return regnum2spr (201); + case sim_ppc_spr202_regnum: return regnum2spr (202); + case sim_ppc_spr203_regnum: return regnum2spr (203); + case sim_ppc_spr204_regnum: return regnum2spr (204); + case sim_ppc_spr205_regnum: return regnum2spr (205); + case sim_ppc_spr206_regnum: return regnum2spr (206); + case sim_ppc_spr207_regnum: return regnum2spr (207); + case sim_ppc_spr208_regnum: return regnum2spr (208); + case sim_ppc_spr209_regnum: return regnum2spr (209); + case sim_ppc_spr210_regnum: return regnum2spr (210); + case sim_ppc_spr211_regnum: return regnum2spr (211); + case sim_ppc_spr212_regnum: return regnum2spr (212); + case sim_ppc_spr213_regnum: return regnum2spr (213); + case sim_ppc_spr214_regnum: return regnum2spr (214); + case sim_ppc_spr215_regnum: return regnum2spr (215); + case sim_ppc_spr216_regnum: return regnum2spr (216); + case sim_ppc_spr217_regnum: return regnum2spr (217); + case sim_ppc_spr218_regnum: return regnum2spr (218); + case sim_ppc_spr219_regnum: return regnum2spr (219); + case sim_ppc_spr220_regnum: return regnum2spr (220); + case sim_ppc_spr221_regnum: return regnum2spr (221); + case sim_ppc_spr222_regnum: return regnum2spr (222); + case sim_ppc_spr223_regnum: return regnum2spr (223); + case sim_ppc_spr224_regnum: return regnum2spr (224); + case sim_ppc_spr225_regnum: return regnum2spr (225); + case sim_ppc_spr226_regnum: return regnum2spr (226); + case sim_ppc_spr227_regnum: return regnum2spr (227); + case sim_ppc_spr228_regnum: return regnum2spr (228); + case sim_ppc_spr229_regnum: return regnum2spr (229); + case sim_ppc_spr230_regnum: return regnum2spr (230); + case sim_ppc_spr231_regnum: return regnum2spr (231); + case sim_ppc_spr232_regnum: return regnum2spr (232); + case sim_ppc_spr233_regnum: return regnum2spr (233); + case sim_ppc_spr234_regnum: return regnum2spr (234); + case sim_ppc_spr235_regnum: return regnum2spr (235); + case sim_ppc_spr236_regnum: return regnum2spr (236); + case sim_ppc_spr237_regnum: return regnum2spr (237); + case sim_ppc_spr238_regnum: return regnum2spr (238); + case sim_ppc_spr239_regnum: return regnum2spr (239); + case sim_ppc_spr240_regnum: return regnum2spr (240); + case sim_ppc_spr241_regnum: return regnum2spr (241); + case sim_ppc_spr242_regnum: return regnum2spr (242); + case sim_ppc_spr243_regnum: return regnum2spr (243); + case sim_ppc_spr244_regnum: return regnum2spr (244); + case sim_ppc_spr245_regnum: return regnum2spr (245); + case sim_ppc_spr246_regnum: return regnum2spr (246); + case sim_ppc_spr247_regnum: return regnum2spr (247); + case sim_ppc_spr248_regnum: return regnum2spr (248); + case sim_ppc_spr249_regnum: return regnum2spr (249); + case sim_ppc_spr250_regnum: return regnum2spr (250); + case sim_ppc_spr251_regnum: return regnum2spr (251); + case sim_ppc_spr252_regnum: return regnum2spr (252); + case sim_ppc_spr253_regnum: return regnum2spr (253); + case sim_ppc_spr254_regnum: return regnum2spr (254); + case sim_ppc_spr255_regnum: return regnum2spr (255); + case sim_ppc_spr256_regnum: return regnum2spr (256); + case sim_ppc_spr257_regnum: return regnum2spr (257); + case sim_ppc_spr258_regnum: return regnum2spr (258); + case sim_ppc_spr259_regnum: return regnum2spr (259); + case sim_ppc_spr260_regnum: return regnum2spr (260); + case sim_ppc_spr261_regnum: return regnum2spr (261); + case sim_ppc_spr262_regnum: return regnum2spr (262); + case sim_ppc_spr263_regnum: return regnum2spr (263); + case sim_ppc_spr264_regnum: return regnum2spr (264); + case sim_ppc_spr265_regnum: return regnum2spr (265); + case sim_ppc_spr266_regnum: return regnum2spr (266); + case sim_ppc_spr267_regnum: return regnum2spr (267); + case sim_ppc_spr268_regnum: return regnum2spr (268); + case sim_ppc_spr269_regnum: return regnum2spr (269); + case sim_ppc_spr270_regnum: return regnum2spr (270); + case sim_ppc_spr271_regnum: return regnum2spr (271); + case sim_ppc_spr272_regnum: return regnum2spr (272); + case sim_ppc_spr273_regnum: return regnum2spr (273); + case sim_ppc_spr274_regnum: return regnum2spr (274); + case sim_ppc_spr275_regnum: return regnum2spr (275); + case sim_ppc_spr276_regnum: return regnum2spr (276); + case sim_ppc_spr277_regnum: return regnum2spr (277); + case sim_ppc_spr278_regnum: return regnum2spr (278); + case sim_ppc_spr279_regnum: return regnum2spr (279); + case sim_ppc_spr280_regnum: return regnum2spr (280); + case sim_ppc_spr281_regnum: return regnum2spr (281); + case sim_ppc_spr282_regnum: return regnum2spr (282); + case sim_ppc_spr283_regnum: return regnum2spr (283); + case sim_ppc_spr284_regnum: return regnum2spr (284); + case sim_ppc_spr285_regnum: return regnum2spr (285); + case sim_ppc_spr286_regnum: return regnum2spr (286); + case sim_ppc_spr287_regnum: return regnum2spr (287); + case sim_ppc_spr288_regnum: return regnum2spr (288); + case sim_ppc_spr289_regnum: return regnum2spr (289); + case sim_ppc_spr290_regnum: return regnum2spr (290); + case sim_ppc_spr291_regnum: return regnum2spr (291); + case sim_ppc_spr292_regnum: return regnum2spr (292); + case sim_ppc_spr293_regnum: return regnum2spr (293); + case sim_ppc_spr294_regnum: return regnum2spr (294); + case sim_ppc_spr295_regnum: return regnum2spr (295); + case sim_ppc_spr296_regnum: return regnum2spr (296); + case sim_ppc_spr297_regnum: return regnum2spr (297); + case sim_ppc_spr298_regnum: return regnum2spr (298); + case sim_ppc_spr299_regnum: return regnum2spr (299); + case sim_ppc_spr300_regnum: return regnum2spr (300); + case sim_ppc_spr301_regnum: return regnum2spr (301); + case sim_ppc_spr302_regnum: return regnum2spr (302); + case sim_ppc_spr303_regnum: return regnum2spr (303); + case sim_ppc_spr304_regnum: return regnum2spr (304); + case sim_ppc_spr305_regnum: return regnum2spr (305); + case sim_ppc_spr306_regnum: return regnum2spr (306); + case sim_ppc_spr307_regnum: return regnum2spr (307); + case sim_ppc_spr308_regnum: return regnum2spr (308); + case sim_ppc_spr309_regnum: return regnum2spr (309); + case sim_ppc_spr310_regnum: return regnum2spr (310); + case sim_ppc_spr311_regnum: return regnum2spr (311); + case sim_ppc_spr312_regnum: return regnum2spr (312); + case sim_ppc_spr313_regnum: return regnum2spr (313); + case sim_ppc_spr314_regnum: return regnum2spr (314); + case sim_ppc_spr315_regnum: return regnum2spr (315); + case sim_ppc_spr316_regnum: return regnum2spr (316); + case sim_ppc_spr317_regnum: return regnum2spr (317); + case sim_ppc_spr318_regnum: return regnum2spr (318); + case sim_ppc_spr319_regnum: return regnum2spr (319); + case sim_ppc_spr320_regnum: return regnum2spr (320); + case sim_ppc_spr321_regnum: return regnum2spr (321); + case sim_ppc_spr322_regnum: return regnum2spr (322); + case sim_ppc_spr323_regnum: return regnum2spr (323); + case sim_ppc_spr324_regnum: return regnum2spr (324); + case sim_ppc_spr325_regnum: return regnum2spr (325); + case sim_ppc_spr326_regnum: return regnum2spr (326); + case sim_ppc_spr327_regnum: return regnum2spr (327); + case sim_ppc_spr328_regnum: return regnum2spr (328); + case sim_ppc_spr329_regnum: return regnum2spr (329); + case sim_ppc_spr330_regnum: return regnum2spr (330); + case sim_ppc_spr331_regnum: return regnum2spr (331); + case sim_ppc_spr332_regnum: return regnum2spr (332); + case sim_ppc_spr333_regnum: return regnum2spr (333); + case sim_ppc_spr334_regnum: return regnum2spr (334); + case sim_ppc_spr335_regnum: return regnum2spr (335); + case sim_ppc_spr336_regnum: return regnum2spr (336); + case sim_ppc_spr337_regnum: return regnum2spr (337); + case sim_ppc_spr338_regnum: return regnum2spr (338); + case sim_ppc_spr339_regnum: return regnum2spr (339); + case sim_ppc_spr340_regnum: return regnum2spr (340); + case sim_ppc_spr341_regnum: return regnum2spr (341); + case sim_ppc_spr342_regnum: return regnum2spr (342); + case sim_ppc_spr343_regnum: return regnum2spr (343); + case sim_ppc_spr344_regnum: return regnum2spr (344); + case sim_ppc_spr345_regnum: return regnum2spr (345); + case sim_ppc_spr346_regnum: return regnum2spr (346); + case sim_ppc_spr347_regnum: return regnum2spr (347); + case sim_ppc_spr348_regnum: return regnum2spr (348); + case sim_ppc_spr349_regnum: return regnum2spr (349); + case sim_ppc_spr350_regnum: return regnum2spr (350); + case sim_ppc_spr351_regnum: return regnum2spr (351); + case sim_ppc_spr352_regnum: return regnum2spr (352); + case sim_ppc_spr353_regnum: return regnum2spr (353); + case sim_ppc_spr354_regnum: return regnum2spr (354); + case sim_ppc_spr355_regnum: return regnum2spr (355); + case sim_ppc_spr356_regnum: return regnum2spr (356); + case sim_ppc_spr357_regnum: return regnum2spr (357); + case sim_ppc_spr358_regnum: return regnum2spr (358); + case sim_ppc_spr359_regnum: return regnum2spr (359); + case sim_ppc_spr360_regnum: return regnum2spr (360); + case sim_ppc_spr361_regnum: return regnum2spr (361); + case sim_ppc_spr362_regnum: return regnum2spr (362); + case sim_ppc_spr363_regnum: return regnum2spr (363); + case sim_ppc_spr364_regnum: return regnum2spr (364); + case sim_ppc_spr365_regnum: return regnum2spr (365); + case sim_ppc_spr366_regnum: return regnum2spr (366); + case sim_ppc_spr367_regnum: return regnum2spr (367); + case sim_ppc_spr368_regnum: return regnum2spr (368); + case sim_ppc_spr369_regnum: return regnum2spr (369); + case sim_ppc_spr370_regnum: return regnum2spr (370); + case sim_ppc_spr371_regnum: return regnum2spr (371); + case sim_ppc_spr372_regnum: return regnum2spr (372); + case sim_ppc_spr373_regnum: return regnum2spr (373); + case sim_ppc_spr374_regnum: return regnum2spr (374); + case sim_ppc_spr375_regnum: return regnum2spr (375); + case sim_ppc_spr376_regnum: return regnum2spr (376); + case sim_ppc_spr377_regnum: return regnum2spr (377); + case sim_ppc_spr378_regnum: return regnum2spr (378); + case sim_ppc_spr379_regnum: return regnum2spr (379); + case sim_ppc_spr380_regnum: return regnum2spr (380); + case sim_ppc_spr381_regnum: return regnum2spr (381); + case sim_ppc_spr382_regnum: return regnum2spr (382); + case sim_ppc_spr383_regnum: return regnum2spr (383); + case sim_ppc_spr384_regnum: return regnum2spr (384); + case sim_ppc_spr385_regnum: return regnum2spr (385); + case sim_ppc_spr386_regnum: return regnum2spr (386); + case sim_ppc_spr387_regnum: return regnum2spr (387); + case sim_ppc_spr388_regnum: return regnum2spr (388); + case sim_ppc_spr389_regnum: return regnum2spr (389); + case sim_ppc_spr390_regnum: return regnum2spr (390); + case sim_ppc_spr391_regnum: return regnum2spr (391); + case sim_ppc_spr392_regnum: return regnum2spr (392); + case sim_ppc_spr393_regnum: return regnum2spr (393); + case sim_ppc_spr394_regnum: return regnum2spr (394); + case sim_ppc_spr395_regnum: return regnum2spr (395); + case sim_ppc_spr396_regnum: return regnum2spr (396); + case sim_ppc_spr397_regnum: return regnum2spr (397); + case sim_ppc_spr398_regnum: return regnum2spr (398); + case sim_ppc_spr399_regnum: return regnum2spr (399); + case sim_ppc_spr400_regnum: return regnum2spr (400); + case sim_ppc_spr401_regnum: return regnum2spr (401); + case sim_ppc_spr402_regnum: return regnum2spr (402); + case sim_ppc_spr403_regnum: return regnum2spr (403); + case sim_ppc_spr404_regnum: return regnum2spr (404); + case sim_ppc_spr405_regnum: return regnum2spr (405); + case sim_ppc_spr406_regnum: return regnum2spr (406); + case sim_ppc_spr407_regnum: return regnum2spr (407); + case sim_ppc_spr408_regnum: return regnum2spr (408); + case sim_ppc_spr409_regnum: return regnum2spr (409); + case sim_ppc_spr410_regnum: return regnum2spr (410); + case sim_ppc_spr411_regnum: return regnum2spr (411); + case sim_ppc_spr412_regnum: return regnum2spr (412); + case sim_ppc_spr413_regnum: return regnum2spr (413); + case sim_ppc_spr414_regnum: return regnum2spr (414); + case sim_ppc_spr415_regnum: return regnum2spr (415); + case sim_ppc_spr416_regnum: return regnum2spr (416); + case sim_ppc_spr417_regnum: return regnum2spr (417); + case sim_ppc_spr418_regnum: return regnum2spr (418); + case sim_ppc_spr419_regnum: return regnum2spr (419); + case sim_ppc_spr420_regnum: return regnum2spr (420); + case sim_ppc_spr421_regnum: return regnum2spr (421); + case sim_ppc_spr422_regnum: return regnum2spr (422); + case sim_ppc_spr423_regnum: return regnum2spr (423); + case sim_ppc_spr424_regnum: return regnum2spr (424); + case sim_ppc_spr425_regnum: return regnum2spr (425); + case sim_ppc_spr426_regnum: return regnum2spr (426); + case sim_ppc_spr427_regnum: return regnum2spr (427); + case sim_ppc_spr428_regnum: return regnum2spr (428); + case sim_ppc_spr429_regnum: return regnum2spr (429); + case sim_ppc_spr430_regnum: return regnum2spr (430); + case sim_ppc_spr431_regnum: return regnum2spr (431); + case sim_ppc_spr432_regnum: return regnum2spr (432); + case sim_ppc_spr433_regnum: return regnum2spr (433); + case sim_ppc_spr434_regnum: return regnum2spr (434); + case sim_ppc_spr435_regnum: return regnum2spr (435); + case sim_ppc_spr436_regnum: return regnum2spr (436); + case sim_ppc_spr437_regnum: return regnum2spr (437); + case sim_ppc_spr438_regnum: return regnum2spr (438); + case sim_ppc_spr439_regnum: return regnum2spr (439); + case sim_ppc_spr440_regnum: return regnum2spr (440); + case sim_ppc_spr441_regnum: return regnum2spr (441); + case sim_ppc_spr442_regnum: return regnum2spr (442); + case sim_ppc_spr443_regnum: return regnum2spr (443); + case sim_ppc_spr444_regnum: return regnum2spr (444); + case sim_ppc_spr445_regnum: return regnum2spr (445); + case sim_ppc_spr446_regnum: return regnum2spr (446); + case sim_ppc_spr447_regnum: return regnum2spr (447); + case sim_ppc_spr448_regnum: return regnum2spr (448); + case sim_ppc_spr449_regnum: return regnum2spr (449); + case sim_ppc_spr450_regnum: return regnum2spr (450); + case sim_ppc_spr451_regnum: return regnum2spr (451); + case sim_ppc_spr452_regnum: return regnum2spr (452); + case sim_ppc_spr453_regnum: return regnum2spr (453); + case sim_ppc_spr454_regnum: return regnum2spr (454); + case sim_ppc_spr455_regnum: return regnum2spr (455); + case sim_ppc_spr456_regnum: return regnum2spr (456); + case sim_ppc_spr457_regnum: return regnum2spr (457); + case sim_ppc_spr458_regnum: return regnum2spr (458); + case sim_ppc_spr459_regnum: return regnum2spr (459); + case sim_ppc_spr460_regnum: return regnum2spr (460); + case sim_ppc_spr461_regnum: return regnum2spr (461); + case sim_ppc_spr462_regnum: return regnum2spr (462); + case sim_ppc_spr463_regnum: return regnum2spr (463); + case sim_ppc_spr464_regnum: return regnum2spr (464); + case sim_ppc_spr465_regnum: return regnum2spr (465); + case sim_ppc_spr466_regnum: return regnum2spr (466); + case sim_ppc_spr467_regnum: return regnum2spr (467); + case sim_ppc_spr468_regnum: return regnum2spr (468); + case sim_ppc_spr469_regnum: return regnum2spr (469); + case sim_ppc_spr470_regnum: return regnum2spr (470); + case sim_ppc_spr471_regnum: return regnum2spr (471); + case sim_ppc_spr472_regnum: return regnum2spr (472); + case sim_ppc_spr473_regnum: return regnum2spr (473); + case sim_ppc_spr474_regnum: return regnum2spr (474); + case sim_ppc_spr475_regnum: return regnum2spr (475); + case sim_ppc_spr476_regnum: return regnum2spr (476); + case sim_ppc_spr477_regnum: return regnum2spr (477); + case sim_ppc_spr478_regnum: return regnum2spr (478); + case sim_ppc_spr479_regnum: return regnum2spr (479); + case sim_ppc_spr480_regnum: return regnum2spr (480); + case sim_ppc_spr481_regnum: return regnum2spr (481); + case sim_ppc_spr482_regnum: return regnum2spr (482); + case sim_ppc_spr483_regnum: return regnum2spr (483); + case sim_ppc_spr484_regnum: return regnum2spr (484); + case sim_ppc_spr485_regnum: return regnum2spr (485); + case sim_ppc_spr486_regnum: return regnum2spr (486); + case sim_ppc_spr487_regnum: return regnum2spr (487); + case sim_ppc_spr488_regnum: return regnum2spr (488); + case sim_ppc_spr489_regnum: return regnum2spr (489); + case sim_ppc_spr490_regnum: return regnum2spr (490); + case sim_ppc_spr491_regnum: return regnum2spr (491); + case sim_ppc_spr492_regnum: return regnum2spr (492); + case sim_ppc_spr493_regnum: return regnum2spr (493); + case sim_ppc_spr494_regnum: return regnum2spr (494); + case sim_ppc_spr495_regnum: return regnum2spr (495); + case sim_ppc_spr496_regnum: return regnum2spr (496); + case sim_ppc_spr497_regnum: return regnum2spr (497); + case sim_ppc_spr498_regnum: return regnum2spr (498); + case sim_ppc_spr499_regnum: return regnum2spr (499); + case sim_ppc_spr500_regnum: return regnum2spr (500); + case sim_ppc_spr501_regnum: return regnum2spr (501); + case sim_ppc_spr502_regnum: return regnum2spr (502); + case sim_ppc_spr503_regnum: return regnum2spr (503); + case sim_ppc_spr504_regnum: return regnum2spr (504); + case sim_ppc_spr505_regnum: return regnum2spr (505); + case sim_ppc_spr506_regnum: return regnum2spr (506); + case sim_ppc_spr507_regnum: return regnum2spr (507); + case sim_ppc_spr508_regnum: return regnum2spr (508); + case sim_ppc_spr509_regnum: return regnum2spr (509); + case sim_ppc_spr510_regnum: return regnum2spr (510); + case sim_ppc_spr511_regnum: return regnum2spr (511); + case sim_ppc_spr512_regnum: return regnum2spr (512); + case sim_ppc_spr513_regnum: return regnum2spr (513); + case sim_ppc_spr514_regnum: return regnum2spr (514); + case sim_ppc_spr515_regnum: return regnum2spr (515); + case sim_ppc_spr516_regnum: return regnum2spr (516); + case sim_ppc_spr517_regnum: return regnum2spr (517); + case sim_ppc_spr518_regnum: return regnum2spr (518); + case sim_ppc_spr519_regnum: return regnum2spr (519); + case sim_ppc_spr520_regnum: return regnum2spr (520); + case sim_ppc_spr521_regnum: return regnum2spr (521); + case sim_ppc_spr522_regnum: return regnum2spr (522); + case sim_ppc_spr523_regnum: return regnum2spr (523); + case sim_ppc_spr524_regnum: return regnum2spr (524); + case sim_ppc_spr525_regnum: return regnum2spr (525); + case sim_ppc_spr526_regnum: return regnum2spr (526); + case sim_ppc_spr527_regnum: return regnum2spr (527); + case sim_ppc_spr528_regnum: return regnum2spr (528); + case sim_ppc_spr529_regnum: return regnum2spr (529); + case sim_ppc_spr530_regnum: return regnum2spr (530); + case sim_ppc_spr531_regnum: return regnum2spr (531); + case sim_ppc_spr532_regnum: return regnum2spr (532); + case sim_ppc_spr533_regnum: return regnum2spr (533); + case sim_ppc_spr534_regnum: return regnum2spr (534); + case sim_ppc_spr535_regnum: return regnum2spr (535); + case sim_ppc_spr536_regnum: return regnum2spr (536); + case sim_ppc_spr537_regnum: return regnum2spr (537); + case sim_ppc_spr538_regnum: return regnum2spr (538); + case sim_ppc_spr539_regnum: return regnum2spr (539); + case sim_ppc_spr540_regnum: return regnum2spr (540); + case sim_ppc_spr541_regnum: return regnum2spr (541); + case sim_ppc_spr542_regnum: return regnum2spr (542); + case sim_ppc_spr543_regnum: return regnum2spr (543); + case sim_ppc_spr544_regnum: return regnum2spr (544); + case sim_ppc_spr545_regnum: return regnum2spr (545); + case sim_ppc_spr546_regnum: return regnum2spr (546); + case sim_ppc_spr547_regnum: return regnum2spr (547); + case sim_ppc_spr548_regnum: return regnum2spr (548); + case sim_ppc_spr549_regnum: return regnum2spr (549); + case sim_ppc_spr550_regnum: return regnum2spr (550); + case sim_ppc_spr551_regnum: return regnum2spr (551); + case sim_ppc_spr552_regnum: return regnum2spr (552); + case sim_ppc_spr553_regnum: return regnum2spr (553); + case sim_ppc_spr554_regnum: return regnum2spr (554); + case sim_ppc_spr555_regnum: return regnum2spr (555); + case sim_ppc_spr556_regnum: return regnum2spr (556); + case sim_ppc_spr557_regnum: return regnum2spr (557); + case sim_ppc_spr558_regnum: return regnum2spr (558); + case sim_ppc_spr559_regnum: return regnum2spr (559); + case sim_ppc_spr560_regnum: return regnum2spr (560); + case sim_ppc_spr561_regnum: return regnum2spr (561); + case sim_ppc_spr562_regnum: return regnum2spr (562); + case sim_ppc_spr563_regnum: return regnum2spr (563); + case sim_ppc_spr564_regnum: return regnum2spr (564); + case sim_ppc_spr565_regnum: return regnum2spr (565); + case sim_ppc_spr566_regnum: return regnum2spr (566); + case sim_ppc_spr567_regnum: return regnum2spr (567); + case sim_ppc_spr568_regnum: return regnum2spr (568); + case sim_ppc_spr569_regnum: return regnum2spr (569); + case sim_ppc_spr570_regnum: return regnum2spr (570); + case sim_ppc_spr571_regnum: return regnum2spr (571); + case sim_ppc_spr572_regnum: return regnum2spr (572); + case sim_ppc_spr573_regnum: return regnum2spr (573); + case sim_ppc_spr574_regnum: return regnum2spr (574); + case sim_ppc_spr575_regnum: return regnum2spr (575); + case sim_ppc_spr576_regnum: return regnum2spr (576); + case sim_ppc_spr577_regnum: return regnum2spr (577); + case sim_ppc_spr578_regnum: return regnum2spr (578); + case sim_ppc_spr579_regnum: return regnum2spr (579); + case sim_ppc_spr580_regnum: return regnum2spr (580); + case sim_ppc_spr581_regnum: return regnum2spr (581); + case sim_ppc_spr582_regnum: return regnum2spr (582); + case sim_ppc_spr583_regnum: return regnum2spr (583); + case sim_ppc_spr584_regnum: return regnum2spr (584); + case sim_ppc_spr585_regnum: return regnum2spr (585); + case sim_ppc_spr586_regnum: return regnum2spr (586); + case sim_ppc_spr587_regnum: return regnum2spr (587); + case sim_ppc_spr588_regnum: return regnum2spr (588); + case sim_ppc_spr589_regnum: return regnum2spr (589); + case sim_ppc_spr590_regnum: return regnum2spr (590); + case sim_ppc_spr591_regnum: return regnum2spr (591); + case sim_ppc_spr592_regnum: return regnum2spr (592); + case sim_ppc_spr593_regnum: return regnum2spr (593); + case sim_ppc_spr594_regnum: return regnum2spr (594); + case sim_ppc_spr595_regnum: return regnum2spr (595); + case sim_ppc_spr596_regnum: return regnum2spr (596); + case sim_ppc_spr597_regnum: return regnum2spr (597); + case sim_ppc_spr598_regnum: return regnum2spr (598); + case sim_ppc_spr599_regnum: return regnum2spr (599); + case sim_ppc_spr600_regnum: return regnum2spr (600); + case sim_ppc_spr601_regnum: return regnum2spr (601); + case sim_ppc_spr602_regnum: return regnum2spr (602); + case sim_ppc_spr603_regnum: return regnum2spr (603); + case sim_ppc_spr604_regnum: return regnum2spr (604); + case sim_ppc_spr605_regnum: return regnum2spr (605); + case sim_ppc_spr606_regnum: return regnum2spr (606); + case sim_ppc_spr607_regnum: return regnum2spr (607); + case sim_ppc_spr608_regnum: return regnum2spr (608); + case sim_ppc_spr609_regnum: return regnum2spr (609); + case sim_ppc_spr610_regnum: return regnum2spr (610); + case sim_ppc_spr611_regnum: return regnum2spr (611); + case sim_ppc_spr612_regnum: return regnum2spr (612); + case sim_ppc_spr613_regnum: return regnum2spr (613); + case sim_ppc_spr614_regnum: return regnum2spr (614); + case sim_ppc_spr615_regnum: return regnum2spr (615); + case sim_ppc_spr616_regnum: return regnum2spr (616); + case sim_ppc_spr617_regnum: return regnum2spr (617); + case sim_ppc_spr618_regnum: return regnum2spr (618); + case sim_ppc_spr619_regnum: return regnum2spr (619); + case sim_ppc_spr620_regnum: return regnum2spr (620); + case sim_ppc_spr621_regnum: return regnum2spr (621); + case sim_ppc_spr622_regnum: return regnum2spr (622); + case sim_ppc_spr623_regnum: return regnum2spr (623); + case sim_ppc_spr624_regnum: return regnum2spr (624); + case sim_ppc_spr625_regnum: return regnum2spr (625); + case sim_ppc_spr626_regnum: return regnum2spr (626); + case sim_ppc_spr627_regnum: return regnum2spr (627); + case sim_ppc_spr628_regnum: return regnum2spr (628); + case sim_ppc_spr629_regnum: return regnum2spr (629); + case sim_ppc_spr630_regnum: return regnum2spr (630); + case sim_ppc_spr631_regnum: return regnum2spr (631); + case sim_ppc_spr632_regnum: return regnum2spr (632); + case sim_ppc_spr633_regnum: return regnum2spr (633); + case sim_ppc_spr634_regnum: return regnum2spr (634); + case sim_ppc_spr635_regnum: return regnum2spr (635); + case sim_ppc_spr636_regnum: return regnum2spr (636); + case sim_ppc_spr637_regnum: return regnum2spr (637); + case sim_ppc_spr638_regnum: return regnum2spr (638); + case sim_ppc_spr639_regnum: return regnum2spr (639); + case sim_ppc_spr640_regnum: return regnum2spr (640); + case sim_ppc_spr641_regnum: return regnum2spr (641); + case sim_ppc_spr642_regnum: return regnum2spr (642); + case sim_ppc_spr643_regnum: return regnum2spr (643); + case sim_ppc_spr644_regnum: return regnum2spr (644); + case sim_ppc_spr645_regnum: return regnum2spr (645); + case sim_ppc_spr646_regnum: return regnum2spr (646); + case sim_ppc_spr647_regnum: return regnum2spr (647); + case sim_ppc_spr648_regnum: return regnum2spr (648); + case sim_ppc_spr649_regnum: return regnum2spr (649); + case sim_ppc_spr650_regnum: return regnum2spr (650); + case sim_ppc_spr651_regnum: return regnum2spr (651); + case sim_ppc_spr652_regnum: return regnum2spr (652); + case sim_ppc_spr653_regnum: return regnum2spr (653); + case sim_ppc_spr654_regnum: return regnum2spr (654); + case sim_ppc_spr655_regnum: return regnum2spr (655); + case sim_ppc_spr656_regnum: return regnum2spr (656); + case sim_ppc_spr657_regnum: return regnum2spr (657); + case sim_ppc_spr658_regnum: return regnum2spr (658); + case sim_ppc_spr659_regnum: return regnum2spr (659); + case sim_ppc_spr660_regnum: return regnum2spr (660); + case sim_ppc_spr661_regnum: return regnum2spr (661); + case sim_ppc_spr662_regnum: return regnum2spr (662); + case sim_ppc_spr663_regnum: return regnum2spr (663); + case sim_ppc_spr664_regnum: return regnum2spr (664); + case sim_ppc_spr665_regnum: return regnum2spr (665); + case sim_ppc_spr666_regnum: return regnum2spr (666); + case sim_ppc_spr667_regnum: return regnum2spr (667); + case sim_ppc_spr668_regnum: return regnum2spr (668); + case sim_ppc_spr669_regnum: return regnum2spr (669); + case sim_ppc_spr670_regnum: return regnum2spr (670); + case sim_ppc_spr671_regnum: return regnum2spr (671); + case sim_ppc_spr672_regnum: return regnum2spr (672); + case sim_ppc_spr673_regnum: return regnum2spr (673); + case sim_ppc_spr674_regnum: return regnum2spr (674); + case sim_ppc_spr675_regnum: return regnum2spr (675); + case sim_ppc_spr676_regnum: return regnum2spr (676); + case sim_ppc_spr677_regnum: return regnum2spr (677); + case sim_ppc_spr678_regnum: return regnum2spr (678); + case sim_ppc_spr679_regnum: return regnum2spr (679); + case sim_ppc_spr680_regnum: return regnum2spr (680); + case sim_ppc_spr681_regnum: return regnum2spr (681); + case sim_ppc_spr682_regnum: return regnum2spr (682); + case sim_ppc_spr683_regnum: return regnum2spr (683); + case sim_ppc_spr684_regnum: return regnum2spr (684); + case sim_ppc_spr685_regnum: return regnum2spr (685); + case sim_ppc_spr686_regnum: return regnum2spr (686); + case sim_ppc_spr687_regnum: return regnum2spr (687); + case sim_ppc_spr688_regnum: return regnum2spr (688); + case sim_ppc_spr689_regnum: return regnum2spr (689); + case sim_ppc_spr690_regnum: return regnum2spr (690); + case sim_ppc_spr691_regnum: return regnum2spr (691); + case sim_ppc_spr692_regnum: return regnum2spr (692); + case sim_ppc_spr693_regnum: return regnum2spr (693); + case sim_ppc_spr694_regnum: return regnum2spr (694); + case sim_ppc_spr695_regnum: return regnum2spr (695); + case sim_ppc_spr696_regnum: return regnum2spr (696); + case sim_ppc_spr697_regnum: return regnum2spr (697); + case sim_ppc_spr698_regnum: return regnum2spr (698); + case sim_ppc_spr699_regnum: return regnum2spr (699); + case sim_ppc_spr700_regnum: return regnum2spr (700); + case sim_ppc_spr701_regnum: return regnum2spr (701); + case sim_ppc_spr702_regnum: return regnum2spr (702); + case sim_ppc_spr703_regnum: return regnum2spr (703); + case sim_ppc_spr704_regnum: return regnum2spr (704); + case sim_ppc_spr705_regnum: return regnum2spr (705); + case sim_ppc_spr706_regnum: return regnum2spr (706); + case sim_ppc_spr707_regnum: return regnum2spr (707); + case sim_ppc_spr708_regnum: return regnum2spr (708); + case sim_ppc_spr709_regnum: return regnum2spr (709); + case sim_ppc_spr710_regnum: return regnum2spr (710); + case sim_ppc_spr711_regnum: return regnum2spr (711); + case sim_ppc_spr712_regnum: return regnum2spr (712); + case sim_ppc_spr713_regnum: return regnum2spr (713); + case sim_ppc_spr714_regnum: return regnum2spr (714); + case sim_ppc_spr715_regnum: return regnum2spr (715); + case sim_ppc_spr716_regnum: return regnum2spr (716); + case sim_ppc_spr717_regnum: return regnum2spr (717); + case sim_ppc_spr718_regnum: return regnum2spr (718); + case sim_ppc_spr719_regnum: return regnum2spr (719); + case sim_ppc_spr720_regnum: return regnum2spr (720); + case sim_ppc_spr721_regnum: return regnum2spr (721); + case sim_ppc_spr722_regnum: return regnum2spr (722); + case sim_ppc_spr723_regnum: return regnum2spr (723); + case sim_ppc_spr724_regnum: return regnum2spr (724); + case sim_ppc_spr725_regnum: return regnum2spr (725); + case sim_ppc_spr726_regnum: return regnum2spr (726); + case sim_ppc_spr727_regnum: return regnum2spr (727); + case sim_ppc_spr728_regnum: return regnum2spr (728); + case sim_ppc_spr729_regnum: return regnum2spr (729); + case sim_ppc_spr730_regnum: return regnum2spr (730); + case sim_ppc_spr731_regnum: return regnum2spr (731); + case sim_ppc_spr732_regnum: return regnum2spr (732); + case sim_ppc_spr733_regnum: return regnum2spr (733); + case sim_ppc_spr734_regnum: return regnum2spr (734); + case sim_ppc_spr735_regnum: return regnum2spr (735); + case sim_ppc_spr736_regnum: return regnum2spr (736); + case sim_ppc_spr737_regnum: return regnum2spr (737); + case sim_ppc_spr738_regnum: return regnum2spr (738); + case sim_ppc_spr739_regnum: return regnum2spr (739); + case sim_ppc_spr740_regnum: return regnum2spr (740); + case sim_ppc_spr741_regnum: return regnum2spr (741); + case sim_ppc_spr742_regnum: return regnum2spr (742); + case sim_ppc_spr743_regnum: return regnum2spr (743); + case sim_ppc_spr744_regnum: return regnum2spr (744); + case sim_ppc_spr745_regnum: return regnum2spr (745); + case sim_ppc_spr746_regnum: return regnum2spr (746); + case sim_ppc_spr747_regnum: return regnum2spr (747); + case sim_ppc_spr748_regnum: return regnum2spr (748); + case sim_ppc_spr749_regnum: return regnum2spr (749); + case sim_ppc_spr750_regnum: return regnum2spr (750); + case sim_ppc_spr751_regnum: return regnum2spr (751); + case sim_ppc_spr752_regnum: return regnum2spr (752); + case sim_ppc_spr753_regnum: return regnum2spr (753); + case sim_ppc_spr754_regnum: return regnum2spr (754); + case sim_ppc_spr755_regnum: return regnum2spr (755); + case sim_ppc_spr756_regnum: return regnum2spr (756); + case sim_ppc_spr757_regnum: return regnum2spr (757); + case sim_ppc_spr758_regnum: return regnum2spr (758); + case sim_ppc_spr759_regnum: return regnum2spr (759); + case sim_ppc_spr760_regnum: return regnum2spr (760); + case sim_ppc_spr761_regnum: return regnum2spr (761); + case sim_ppc_spr762_regnum: return regnum2spr (762); + case sim_ppc_spr763_regnum: return regnum2spr (763); + case sim_ppc_spr764_regnum: return regnum2spr (764); + case sim_ppc_spr765_regnum: return regnum2spr (765); + case sim_ppc_spr766_regnum: return regnum2spr (766); + case sim_ppc_spr767_regnum: return regnum2spr (767); + case sim_ppc_spr768_regnum: return regnum2spr (768); + case sim_ppc_spr769_regnum: return regnum2spr (769); + case sim_ppc_spr770_regnum: return regnum2spr (770); + case sim_ppc_spr771_regnum: return regnum2spr (771); + case sim_ppc_spr772_regnum: return regnum2spr (772); + case sim_ppc_spr773_regnum: return regnum2spr (773); + case sim_ppc_spr774_regnum: return regnum2spr (774); + case sim_ppc_spr775_regnum: return regnum2spr (775); + case sim_ppc_spr776_regnum: return regnum2spr (776); + case sim_ppc_spr777_regnum: return regnum2spr (777); + case sim_ppc_spr778_regnum: return regnum2spr (778); + case sim_ppc_spr779_regnum: return regnum2spr (779); + case sim_ppc_spr780_regnum: return regnum2spr (780); + case sim_ppc_spr781_regnum: return regnum2spr (781); + case sim_ppc_spr782_regnum: return regnum2spr (782); + case sim_ppc_spr783_regnum: return regnum2spr (783); + case sim_ppc_spr784_regnum: return regnum2spr (784); + case sim_ppc_spr785_regnum: return regnum2spr (785); + case sim_ppc_spr786_regnum: return regnum2spr (786); + case sim_ppc_spr787_regnum: return regnum2spr (787); + case sim_ppc_spr788_regnum: return regnum2spr (788); + case sim_ppc_spr789_regnum: return regnum2spr (789); + case sim_ppc_spr790_regnum: return regnum2spr (790); + case sim_ppc_spr791_regnum: return regnum2spr (791); + case sim_ppc_spr792_regnum: return regnum2spr (792); + case sim_ppc_spr793_regnum: return regnum2spr (793); + case sim_ppc_spr794_regnum: return regnum2spr (794); + case sim_ppc_spr795_regnum: return regnum2spr (795); + case sim_ppc_spr796_regnum: return regnum2spr (796); + case sim_ppc_spr797_regnum: return regnum2spr (797); + case sim_ppc_spr798_regnum: return regnum2spr (798); + case sim_ppc_spr799_regnum: return regnum2spr (799); + case sim_ppc_spr800_regnum: return regnum2spr (800); + case sim_ppc_spr801_regnum: return regnum2spr (801); + case sim_ppc_spr802_regnum: return regnum2spr (802); + case sim_ppc_spr803_regnum: return regnum2spr (803); + case sim_ppc_spr804_regnum: return regnum2spr (804); + case sim_ppc_spr805_regnum: return regnum2spr (805); + case sim_ppc_spr806_regnum: return regnum2spr (806); + case sim_ppc_spr807_regnum: return regnum2spr (807); + case sim_ppc_spr808_regnum: return regnum2spr (808); + case sim_ppc_spr809_regnum: return regnum2spr (809); + case sim_ppc_spr810_regnum: return regnum2spr (810); + case sim_ppc_spr811_regnum: return regnum2spr (811); + case sim_ppc_spr812_regnum: return regnum2spr (812); + case sim_ppc_spr813_regnum: return regnum2spr (813); + case sim_ppc_spr814_regnum: return regnum2spr (814); + case sim_ppc_spr815_regnum: return regnum2spr (815); + case sim_ppc_spr816_regnum: return regnum2spr (816); + case sim_ppc_spr817_regnum: return regnum2spr (817); + case sim_ppc_spr818_regnum: return regnum2spr (818); + case sim_ppc_spr819_regnum: return regnum2spr (819); + case sim_ppc_spr820_regnum: return regnum2spr (820); + case sim_ppc_spr821_regnum: return regnum2spr (821); + case sim_ppc_spr822_regnum: return regnum2spr (822); + case sim_ppc_spr823_regnum: return regnum2spr (823); + case sim_ppc_spr824_regnum: return regnum2spr (824); + case sim_ppc_spr825_regnum: return regnum2spr (825); + case sim_ppc_spr826_regnum: return regnum2spr (826); + case sim_ppc_spr827_regnum: return regnum2spr (827); + case sim_ppc_spr828_regnum: return regnum2spr (828); + case sim_ppc_spr829_regnum: return regnum2spr (829); + case sim_ppc_spr830_regnum: return regnum2spr (830); + case sim_ppc_spr831_regnum: return regnum2spr (831); + case sim_ppc_spr832_regnum: return regnum2spr (832); + case sim_ppc_spr833_regnum: return regnum2spr (833); + case sim_ppc_spr834_regnum: return regnum2spr (834); + case sim_ppc_spr835_regnum: return regnum2spr (835); + case sim_ppc_spr836_regnum: return regnum2spr (836); + case sim_ppc_spr837_regnum: return regnum2spr (837); + case sim_ppc_spr838_regnum: return regnum2spr (838); + case sim_ppc_spr839_regnum: return regnum2spr (839); + case sim_ppc_spr840_regnum: return regnum2spr (840); + case sim_ppc_spr841_regnum: return regnum2spr (841); + case sim_ppc_spr842_regnum: return regnum2spr (842); + case sim_ppc_spr843_regnum: return regnum2spr (843); + case sim_ppc_spr844_regnum: return regnum2spr (844); + case sim_ppc_spr845_regnum: return regnum2spr (845); + case sim_ppc_spr846_regnum: return regnum2spr (846); + case sim_ppc_spr847_regnum: return regnum2spr (847); + case sim_ppc_spr848_regnum: return regnum2spr (848); + case sim_ppc_spr849_regnum: return regnum2spr (849); + case sim_ppc_spr850_regnum: return regnum2spr (850); + case sim_ppc_spr851_regnum: return regnum2spr (851); + case sim_ppc_spr852_regnum: return regnum2spr (852); + case sim_ppc_spr853_regnum: return regnum2spr (853); + case sim_ppc_spr854_regnum: return regnum2spr (854); + case sim_ppc_spr855_regnum: return regnum2spr (855); + case sim_ppc_spr856_regnum: return regnum2spr (856); + case sim_ppc_spr857_regnum: return regnum2spr (857); + case sim_ppc_spr858_regnum: return regnum2spr (858); + case sim_ppc_spr859_regnum: return regnum2spr (859); + case sim_ppc_spr860_regnum: return regnum2spr (860); + case sim_ppc_spr861_regnum: return regnum2spr (861); + case sim_ppc_spr862_regnum: return regnum2spr (862); + case sim_ppc_spr863_regnum: return regnum2spr (863); + case sim_ppc_spr864_regnum: return regnum2spr (864); + case sim_ppc_spr865_regnum: return regnum2spr (865); + case sim_ppc_spr866_regnum: return regnum2spr (866); + case sim_ppc_spr867_regnum: return regnum2spr (867); + case sim_ppc_spr868_regnum: return regnum2spr (868); + case sim_ppc_spr869_regnum: return regnum2spr (869); + case sim_ppc_spr870_regnum: return regnum2spr (870); + case sim_ppc_spr871_regnum: return regnum2spr (871); + case sim_ppc_spr872_regnum: return regnum2spr (872); + case sim_ppc_spr873_regnum: return regnum2spr (873); + case sim_ppc_spr874_regnum: return regnum2spr (874); + case sim_ppc_spr875_regnum: return regnum2spr (875); + case sim_ppc_spr876_regnum: return regnum2spr (876); + case sim_ppc_spr877_regnum: return regnum2spr (877); + case sim_ppc_spr878_regnum: return regnum2spr (878); + case sim_ppc_spr879_regnum: return regnum2spr (879); + case sim_ppc_spr880_regnum: return regnum2spr (880); + case sim_ppc_spr881_regnum: return regnum2spr (881); + case sim_ppc_spr882_regnum: return regnum2spr (882); + case sim_ppc_spr883_regnum: return regnum2spr (883); + case sim_ppc_spr884_regnum: return regnum2spr (884); + case sim_ppc_spr885_regnum: return regnum2spr (885); + case sim_ppc_spr886_regnum: return regnum2spr (886); + case sim_ppc_spr887_regnum: return regnum2spr (887); + case sim_ppc_spr888_regnum: return regnum2spr (888); + case sim_ppc_spr889_regnum: return regnum2spr (889); + case sim_ppc_spr890_regnum: return regnum2spr (890); + case sim_ppc_spr891_regnum: return regnum2spr (891); + case sim_ppc_spr892_regnum: return regnum2spr (892); + case sim_ppc_spr893_regnum: return regnum2spr (893); + case sim_ppc_spr894_regnum: return regnum2spr (894); + case sim_ppc_spr895_regnum: return regnum2spr (895); + case sim_ppc_spr896_regnum: return regnum2spr (896); + case sim_ppc_spr897_regnum: return regnum2spr (897); + case sim_ppc_spr898_regnum: return regnum2spr (898); + case sim_ppc_spr899_regnum: return regnum2spr (899); + case sim_ppc_spr900_regnum: return regnum2spr (900); + case sim_ppc_spr901_regnum: return regnum2spr (901); + case sim_ppc_spr902_regnum: return regnum2spr (902); + case sim_ppc_spr903_regnum: return regnum2spr (903); + case sim_ppc_spr904_regnum: return regnum2spr (904); + case sim_ppc_spr905_regnum: return regnum2spr (905); + case sim_ppc_spr906_regnum: return regnum2spr (906); + case sim_ppc_spr907_regnum: return regnum2spr (907); + case sim_ppc_spr908_regnum: return regnum2spr (908); + case sim_ppc_spr909_regnum: return regnum2spr (909); + case sim_ppc_spr910_regnum: return regnum2spr (910); + case sim_ppc_spr911_regnum: return regnum2spr (911); + case sim_ppc_spr912_regnum: return regnum2spr (912); + case sim_ppc_spr913_regnum: return regnum2spr (913); + case sim_ppc_spr914_regnum: return regnum2spr (914); + case sim_ppc_spr915_regnum: return regnum2spr (915); + case sim_ppc_spr916_regnum: return regnum2spr (916); + case sim_ppc_spr917_regnum: return regnum2spr (917); + case sim_ppc_spr918_regnum: return regnum2spr (918); + case sim_ppc_spr919_regnum: return regnum2spr (919); + case sim_ppc_spr920_regnum: return regnum2spr (920); + case sim_ppc_spr921_regnum: return regnum2spr (921); + case sim_ppc_spr922_regnum: return regnum2spr (922); + case sim_ppc_spr923_regnum: return regnum2spr (923); + case sim_ppc_spr924_regnum: return regnum2spr (924); + case sim_ppc_spr925_regnum: return regnum2spr (925); + case sim_ppc_spr926_regnum: return regnum2spr (926); + case sim_ppc_spr927_regnum: return regnum2spr (927); + case sim_ppc_spr928_regnum: return regnum2spr (928); + case sim_ppc_spr929_regnum: return regnum2spr (929); + case sim_ppc_spr930_regnum: return regnum2spr (930); + case sim_ppc_spr931_regnum: return regnum2spr (931); + case sim_ppc_spr932_regnum: return regnum2spr (932); + case sim_ppc_spr933_regnum: return regnum2spr (933); + case sim_ppc_spr934_regnum: return regnum2spr (934); + case sim_ppc_spr935_regnum: return regnum2spr (935); + case sim_ppc_spr936_regnum: return regnum2spr (936); + case sim_ppc_spr937_regnum: return regnum2spr (937); + case sim_ppc_spr938_regnum: return regnum2spr (938); + case sim_ppc_spr939_regnum: return regnum2spr (939); + case sim_ppc_spr940_regnum: return regnum2spr (940); + case sim_ppc_spr941_regnum: return regnum2spr (941); + case sim_ppc_spr942_regnum: return regnum2spr (942); + case sim_ppc_spr943_regnum: return regnum2spr (943); + case sim_ppc_spr944_regnum: return regnum2spr (944); + case sim_ppc_spr945_regnum: return regnum2spr (945); + case sim_ppc_spr946_regnum: return regnum2spr (946); + case sim_ppc_spr947_regnum: return regnum2spr (947); + case sim_ppc_spr948_regnum: return regnum2spr (948); + case sim_ppc_spr949_regnum: return regnum2spr (949); + case sim_ppc_spr950_regnum: return regnum2spr (950); + case sim_ppc_spr951_regnum: return regnum2spr (951); + case sim_ppc_spr952_regnum: return regnum2spr (952); + case sim_ppc_spr953_regnum: return regnum2spr (953); + case sim_ppc_spr954_regnum: return regnum2spr (954); + case sim_ppc_spr955_regnum: return regnum2spr (955); + case sim_ppc_spr956_regnum: return regnum2spr (956); + case sim_ppc_spr957_regnum: return regnum2spr (957); + case sim_ppc_spr958_regnum: return regnum2spr (958); + case sim_ppc_spr959_regnum: return regnum2spr (959); + case sim_ppc_spr960_regnum: return regnum2spr (960); + case sim_ppc_spr961_regnum: return regnum2spr (961); + case sim_ppc_spr962_regnum: return regnum2spr (962); + case sim_ppc_spr963_regnum: return regnum2spr (963); + case sim_ppc_spr964_regnum: return regnum2spr (964); + case sim_ppc_spr965_regnum: return regnum2spr (965); + case sim_ppc_spr966_regnum: return regnum2spr (966); + case sim_ppc_spr967_regnum: return regnum2spr (967); + case sim_ppc_spr968_regnum: return regnum2spr (968); + case sim_ppc_spr969_regnum: return regnum2spr (969); + case sim_ppc_spr970_regnum: return regnum2spr (970); + case sim_ppc_spr971_regnum: return regnum2spr (971); + case sim_ppc_spr972_regnum: return regnum2spr (972); + case sim_ppc_spr973_regnum: return regnum2spr (973); + case sim_ppc_spr974_regnum: return regnum2spr (974); + case sim_ppc_spr975_regnum: return regnum2spr (975); + case sim_ppc_spr976_regnum: return regnum2spr (976); + case sim_ppc_spr977_regnum: return regnum2spr (977); + case sim_ppc_spr978_regnum: return regnum2spr (978); + case sim_ppc_spr979_regnum: return regnum2spr (979); + case sim_ppc_spr980_regnum: return regnum2spr (980); + case sim_ppc_spr981_regnum: return regnum2spr (981); + case sim_ppc_spr982_regnum: return regnum2spr (982); + case sim_ppc_spr983_regnum: return regnum2spr (983); + case sim_ppc_spr984_regnum: return regnum2spr (984); + case sim_ppc_spr985_regnum: return regnum2spr (985); + case sim_ppc_spr986_regnum: return regnum2spr (986); + case sim_ppc_spr987_regnum: return regnum2spr (987); + case sim_ppc_spr988_regnum: return regnum2spr (988); + case sim_ppc_spr989_regnum: return regnum2spr (989); + case sim_ppc_spr990_regnum: return regnum2spr (990); + case sim_ppc_spr991_regnum: return regnum2spr (991); + case sim_ppc_spr992_regnum: return regnum2spr (992); + case sim_ppc_spr993_regnum: return regnum2spr (993); + case sim_ppc_spr994_regnum: return regnum2spr (994); + case sim_ppc_spr995_regnum: return regnum2spr (995); + case sim_ppc_spr996_regnum: return regnum2spr (996); + case sim_ppc_spr997_regnum: return regnum2spr (997); + case sim_ppc_spr998_regnum: return regnum2spr (998); + case sim_ppc_spr999_regnum: return regnum2spr (999); + case sim_ppc_spr1000_regnum: return regnum2spr (1000); + case sim_ppc_spr1001_regnum: return regnum2spr (1001); + case sim_ppc_spr1002_regnum: return regnum2spr (1002); + case sim_ppc_spr1003_regnum: return regnum2spr (1003); + case sim_ppc_spr1004_regnum: return regnum2spr (1004); + case sim_ppc_spr1005_regnum: return regnum2spr (1005); + case sim_ppc_spr1006_regnum: return regnum2spr (1006); + case sim_ppc_spr1007_regnum: return regnum2spr (1007); + case sim_ppc_spr1008_regnum: return regnum2spr (1008); + case sim_ppc_spr1009_regnum: return regnum2spr (1009); + case sim_ppc_spr1010_regnum: return regnum2spr (1010); + case sim_ppc_spr1011_regnum: return regnum2spr (1011); + case sim_ppc_spr1012_regnum: return regnum2spr (1012); + case sim_ppc_spr1013_regnum: return regnum2spr (1013); + case sim_ppc_spr1014_regnum: return regnum2spr (1014); + case sim_ppc_spr1015_regnum: return regnum2spr (1015); + case sim_ppc_spr1016_regnum: return regnum2spr (1016); + case sim_ppc_spr1017_regnum: return regnum2spr (1017); + case sim_ppc_spr1018_regnum: return regnum2spr (1018); + case sim_ppc_spr1019_regnum: return regnum2spr (1019); + case sim_ppc_spr1020_regnum: return regnum2spr (1020); + case sim_ppc_spr1021_regnum: return regnum2spr (1021); + case sim_ppc_spr1022_regnum: return regnum2spr (1022); + case sim_ppc_spr1023_regnum: return regnum2spr (1023); + default: + /* Not a valid register number at all. */ + return NULL; + } +} + + +int +sim_fetch_register (SIM_DESC sd, int regno, unsigned char *buf, int length) +{ + const char *regname = regnum2name (regno); + + if (simulator == NULL || regname == NULL) + return -1; + + TRACE(trace_gdb, ("sim_fetch_register(regno=%d(%s), buf=0x%lx)\n", + regno, regname, (long)buf)); + return psim_read_register(simulator, MAX_NR_PROCESSORS, + buf, regname, raw_transfer); +} + + +int +sim_store_register (SIM_DESC sd, int regno, unsigned char *buf, int length) +{ + const char *regname = regnum2name (regno); + + if (simulator == NULL || regname == NULL) + return -1; + + TRACE(trace_gdb, ("sim_store_register(regno=%d(%s), buf=0x%lx)\n", + regno, regname, (long)buf)); + return psim_write_register(simulator, MAX_NR_PROCESSORS, + buf, regname, raw_transfer); +} diff --git a/sim/testsuite/sim/mips/fpu64-ps-sb1.s b/sim/testsuite/sim/mips/fpu64-ps-sb1.s new file mode 100644 index 00000000000..a39d0799c0d --- /dev/null +++ b/sim/testsuite/sim/mips/fpu64-ps-sb1.s @@ -0,0 +1,72 @@ +# mips test sanity, expected to pass. +# mach: sb1 +# as: -mabi=eabi +# ld: -N -Ttext=0x80010000 +# output: *\\npass\\n + + .include "testutils.inc" + + .macro check_ps psval, upperval, lowerval + .set push + .set noreorder + cvt.s.pu $f0, \psval # upper + cvt.s.pl $f2, \psval # lower + li.s $f4, \upperval + li.s $f6, \lowerval + c.eq.s $fcc0, $f0, $f4 + bc1f $fcc0, _fail + c.eq.s $fcc0, $f2, $f6 + bc1f $fcc0, _fail + nop + .set pop + .endm + + setup + + .set noreorder + + .ent DIAG +DIAG: + + # make sure that Status.FR, .CU1, and .SBX are set. + mfc0 $2, $12 + or $2, $2, (1 << 26) | (1 << 29) | (1 << 16) + mtc0 $2, $12 + + + li.s $f10, 4.0 + li.s $f12, 16.0 + cvt.ps.s $f20, $f10, $f12 # $f20: u=4.0, l=16.0 + + li.s $f10, -1.0 + li.s $f12, 2.0 + cvt.ps.s $f22, $f10, $f12 # $f22: u=-1.0, l=2.0 + + + writemsg "div.ps" + + div.ps $f8, $f20, $f22 + check_ps $f8, -4.0, 8.0 + + + writemsg "recip.ps" + + recip.ps $f8, $f20 + check_ps $f8, 0.25, 0.0625 + + + writemsg "rsqrt.ps" + + rsqrt.ps $f8, $f20 + check_ps $f8, 0.5, 0.25 + + + writemsg "sqrt.ps" + + sqrt.ps $f8, $f20 + check_ps $f8, 2.0, 4.0 + + + pass + + .end DIAG diff --git a/sim/testsuite/sim/mips/fpu64-ps.s b/sim/testsuite/sim/mips/fpu64-ps.s new file mode 100644 index 00000000000..ad493b8ac31 --- /dev/null +++ b/sim/testsuite/sim/mips/fpu64-ps.s @@ -0,0 +1,367 @@ +# mips test sanity, expected to pass. +# mach: mips64 sb1 +# as: -mabi=eabi +# ld: -N -Ttext=0x80010000 +# output: *\\npass\\n + + .include "testutils.inc" + + .macro check_ps psval, upperval, lowerval + .set push + .set noreorder + cvt.s.pu $f0, \psval # upper + cvt.s.pl $f2, \psval # lower + li.s $f4, \upperval + li.s $f6, \lowerval + c.eq.s $fcc0, $f0, $f4 + bc1f $fcc0, _fail + c.eq.s $fcc0, $f2, $f6 + bc1f $fcc0, _fail + nop + .set pop + .endm + + setup + + .set noreorder + + .ent DIAG +DIAG: + + # make sure that Status.FR and .CU1 are set. + mfc0 $2, $12 + or $2, $2, (1 << 26) | (1 << 29) + mtc0 $2, $12 + + + writemsg "ldc1" + + .data +1: .dword 0xc1a8000042200000 # -21.0, 40.0 + .text + la $2, 1b + ldc1 $f8, 0($2) + check_ps $f8, -21.0, 40.0 + + + writemsg "cvt.ps.s" + + li.s $f10, 1.0 + li.s $f12, 3.0 + cvt.ps.s $f8, $f10, $f12 # upper, lower + check_ps $f8, 1.0, 3.0 + + + writemsg "cvt.ps.s, sdc1, copy, ldc1" + + .data +1: .dword 0 + .dword 0 + .text + la $2, 1b + li.s $f12, -4.0 + li.s $f14, 32.0 + cvt.ps.s $f10, $f12, $f14 # upper, lower + sdc1 $f10, 8($2) + lw $3, 8($2) + lw $4, 12($2) + sw $3, 0($2) + sw $4, 4($2) + ldc1 $f8, 0($2) + check_ps $f8, -4.0, 32.0 + + + # Load some constants for later use + + li.s $f10, 4.0 + li.s $f12, 16.0 + cvt.ps.s $f20, $f10, $f12 # $f20: u=4.0, l=16.0 + + li.s $f10, -1.0 + li.s $f12, 2.0 + cvt.ps.s $f22, $f10, $f12 # $f22: u=-1.0, l=2.0 + + li.s $f10, 17.0 + li.s $f12, -8.0 + cvt.ps.s $f24, $f10, $f12 # $f24: u=17.0, l=-8.0 + + + writemsg "pll.ps" + + pll.ps $f8, $f20, $f22 + check_ps $f8, 16.0, 2.0 + + + writemsg "plu.ps" + + plu.ps $f8, $f20, $f22 + check_ps $f8, 16.0, -1.0 + + + writemsg "pul.ps" + + pul.ps $f8, $f20, $f22 + check_ps $f8, 4.0, 2.0 + + + writemsg "puu.ps" + + puu.ps $f8, $f20, $f22 + check_ps $f8, 4.0, -1.0 + + + writemsg "abs.ps" + + abs.ps $f8, $f22 + check_ps $f8, 1.0, 2.0 + + + writemsg "mov.ps" + + mov.ps $f8, $f22 + check_ps $f8, -1.0, 2.0 + + + writemsg "neg.ps" + + neg.ps $f8, $f22 + check_ps $f8, 1.0, -2.0 + + + writemsg "add.ps" + + add.ps $f8, $f20, $f22 + check_ps $f8, 3.0, 18.0 + + + writemsg "mul.ps" + + mul.ps $f8, $f20, $f22 + check_ps $f8, -4.0, 32.0 + + + writemsg "sub.ps" + + sub.ps $f8, $f20, $f22 + check_ps $f8, 5.0, 14.0 + + + writemsg "madd.ps" + + madd.ps $f8, $f24, $f20, $f22 + check_ps $f8, 13.0, 24.0 + + + writemsg "msub.ps" + + msub.ps $f8, $f24, $f20, $f22 + check_ps $f8, -21.0, 40.0 + + + writemsg "nmadd.ps" + + nmadd.ps $f8, $f24, $f20, $f22 + check_ps $f8, -13.0, -24.0 + + + writemsg "nmsub.ps" + + nmsub.ps $f8, $f24, $f20, $f22 + check_ps $f8, 21.0, -40.0 + + + writemsg "movn.ps (n)" + + li $2, 0 + mov.ps $f8, $f20 + movn.ps $f8, $f22, $2 # doesn't move + check_ps $f8, 4.0, 16.0 + + + writemsg "movn.ps (y)" + + li $2, 1 + mov.ps $f8, $f20 + movn.ps $f8, $f22, $2 # does move + check_ps $f8, -1.0, 2.0 + + + writemsg "movz.ps (y)" + + li $2, 0 + mov.ps $f8, $f20 + movz.ps $f8, $f22, $2 # does move + check_ps $f8, -1.0, 2.0 + + + writemsg "movz.ps (n)" + + li $2, 1 + mov.ps $f8, $f20 + movz.ps $f8, $f22, $2 # doesn't move + check_ps $f8, 4.0, 16.0 + + + writemsg "movf.ps (y,y)" + + cfc1 $2, $31 + or $2, $2, (1 << 23) | (1 << 25) + xor $2, $2, (1 << 23) | (1 << 25) + ctc1 $2, $31 # clear fcc0, clear fcc1 + mov.ps $f8, $f20 + movf.ps $f8, $f22, $fcc0 # moves both halves + check_ps $f8, -1.0, 2.0 + + + writemsg "movf.ps (y,n)" + + cfc1 $2, $31 + or $2, $2, (1 << 23) | (1 << 25) + xor $2, $2, (0 << 23) | (1 << 25) + ctc1 $2, $31 # set fcc0, clear fcc1 + mov.ps $f8, $f20 + movf.ps $f8, $f22, $fcc0 # moves upper half only + check_ps $f8, -1.0, 16.0 + + + writemsg "movf.ps (n,y)" + + cfc1 $2, $31 + or $2, $2, (1 << 23) | (1 << 25) + xor $2, $2, (1 << 23) | (0 << 25) + ctc1 $2, $31 # clear fcc0, set fcc1 + mov.ps $f8, $f20 + movf.ps $f8, $f22, $fcc0 # moves lower half only + check_ps $f8, 4.0, 2.0 + + + writemsg "movf.ps (n,n)" + + cfc1 $2, $31 + or $2, $2, (1 << 23) | (1 << 25) + xor $2, $2, (0 << 23) | (0 << 25) + ctc1 $2, $31 # set fcc0, set fcc1 + mov.ps $f8, $f20 + movf.ps $f8, $f22, $fcc0 # doesn't move either half + check_ps $f8, 4.0, 16.0 + + + writemsg "movt.ps (n,n)" + + cfc1 $2, $31 + or $2, $2, (1 << 23) | (1 << 25) + xor $2, $2, (1 << 23) | (1 << 25) + ctc1 $2, $31 # clear fcc0, clear fcc1 + mov.ps $f8, $f20 + movt.ps $f8, $f22, $fcc0 # doesn't move either half + check_ps $f8, 4.0, 16.0 + + + writemsg "movt.ps (n,y)" + + cfc1 $2, $31 + or $2, $2, (1 << 23) | (1 << 25) + xor $2, $2, (0 << 23) | (1 << 25) + ctc1 $2, $31 # set fcc0, clear fcc1 + mov.ps $f8, $f20 + movt.ps $f8, $f22, $fcc0 # moves lower half only + check_ps $f8, 4.0, 2.0 + + + writemsg "movt.ps (y,n)" + + cfc1 $2, $31 + or $2, $2, (1 << 23) | (1 << 25) + xor $2, $2, (1 << 23) | (0 << 25) + ctc1 $2, $31 # clear fcc0, set fcc1 + mov.ps $f8, $f20 + movt.ps $f8, $f22, $fcc0 # moves upper half only + check_ps $f8, -1.0, 16.0 + + + writemsg "movt.ps (y,y)" + + cfc1 $2, $31 + or $2, $2, (1 << 23) | (1 << 25) + xor $2, $2, (0 << 23) | (0 << 25) + ctc1 $2, $31 # set fcc0, set fcc1 + mov.ps $f8, $f20 + movt.ps $f8, $f22, $fcc0 # moves both halves + check_ps $f8, -1.0, 2.0 + + + writemsg "alnv.ps (aligned)" + + .data +1: .dword 0xc1a8000042200000 # -21.0, 40.0 + .dword 0xc228000041a00000 # -42.0, 20.0 + .text + la $2, 1b + li $3, 0 + addu $4, $3, 8 + luxc1 $f10, $3($2) + luxc1 $f12, $4($2) + alnv.ps $f8, $f10, $f12, $3 + check_ps $f8, -21.0, 40.0 + + + writemsg "alnv.ps (unaligned)" + + .data +1: .dword 0xc1a8000042200000 # -21.0, 40.0 + .dword 0xc228000041a00000 # -42.0, 20.0 + .hword 0x0001 + .text + la $2, 1b + li $3, 4 + addu $4, $3, 8 + luxc1 $f10, $3($2) + luxc1 $f12, $4($2) + alnv.ps $f8, $f10, $f12, $3 + + lb $5, 16($2) + bnez $5, 2f # little endian + nop + + # big endian + check_ps $f8, 40.0, -42.0 + b 3f + nop +2: + # little endian + check_ps $f8, 20.0, -21.0 +3: + + + # We test c.cond.ps only lightly, just to make sure it modifies + # two bits and compares the halves separately. Perhaps it should + # be tested more thoroughly. + + writemsg "c.f.ps" + + cfc1 $2, $31 + or $2, $2, (1 << 23) | (0x7f << 25) + ctc1 $2, $31 # set all fcc bits + c.f.ps $fcc0, $f8, $f8 # -> f, f + bc1t $fcc0, _fail + nop + bc1t $fcc1, _fail + nop + + + writemsg "c.olt.ps" + + cfc1 $2, $31 + or $2, $2, (1 << 23) | (0x7f << 25) + xor $2, $2, (1 << 23) | (0x7f << 25) + ctc1 $2, $31 # clear all fcc bits + c.lt.ps $fcc0, $f22, $f24 # -> f, t + bc1t $fcc0, _fail + nop + bc1f $fcc1, _fail + nop + + + pass + + .end DIAG diff --git a/sim/testsuite/sim/mips/mdmx-ob-sb1.s b/sim/testsuite/sim/mips/mdmx-ob-sb1.s new file mode 100644 index 00000000000..c8409fc0b42 --- /dev/null +++ b/sim/testsuite/sim/mips/mdmx-ob-sb1.s @@ -0,0 +1,102 @@ +# MDMX .OB op tests. +# mach: sb1 +# as: -mabi=eabi +# ld: -N -Ttext=0x80010000 +# output: *\\npass\\n + + .include "testutils.inc" + .include "utils-mdmx.inc" + + setup + + .set noreorder + + .ent DIAG +DIAG: + + enable_mdmx + + # set Status.SBX to enable SB-1 extensions. + mfc0 $2, $12 + or $2, $2, (1 << 16) + mtc0 $2, $12 + + + ### + ### SB-1 Non-accumulator .ob format ops. + ### + ### Key: v = vector + ### ev = vector of single element + ### cv = vector of constant. + ### + + + writemsg "pavg.ob (v)" + ld_ob $f8, 0x1122334455667788 + ld_ob $f9, 0x66778899aabbccdd + pavg.ob $f10, $f8, $f9 + ck_ob $f10, 0x3c4d5e6f8091a2b3 + + writemsg "pavg.ob (ev)" + ld_ob $f8, 0x1122334455667788 + ld_ob $f9, 0x66778899aabbccdd + pavg.ob $f10, $f8, $f9[6] + ck_ob $f10, 0x444d555e666f7780 + + writemsg "pavg.ob (cv)" + ld_ob $f8, 0x1122334455667788 + pavg.ob $f10, $f8, 0x10 + ck_ob $f10, 0x1119222a333b444c + + + writemsg "pabsdiff.ob (v)" + ld_ob $f8, 0x1122334455667788 + ld_ob $f9, 0x66778899aabbccdd + pabsdiff.ob $f10, $f8, $f9 + ck_ob $f10, 0x5555555555555555 + + writemsg "pabsdiff.ob (ev)" + ld_ob $f8, 0x1122334455667788 + ld_ob $f9, 0x66778899aabbccdd + pabsdiff.ob $f10, $f8, $f9[7] + ck_ob $f10, 0x5544332211001122 + + writemsg "pabsdiff.ob (cv)" + ld_ob $f8, 0x0001020304050607 + pabsdiff.ob $f10, $f8, 0x04 + ck_ob $f10, 0x0403020100010203 + + + ### + ### SB-1 Accumulator .ob format ops + ### + ### Key: v = vector + ### ev = vector of single element + ### cv = vector of constant. + ### + + + writemsg "pabsdiffc.ob (v)" + ld_acc_ob 0x0001020304050607, 0x0000000000000000, 0x0000000000000000 + ld_ob $f8, 0x1122334455667788 + ld_ob $f9, 0x66778899aabbccdd + pabsdiffc.ob $f8, $f9 + ck_acc_ob 0x0001020304050607, 0x0000000000000000, 0x5555555555555555 + + writemsg "pabsdiffc.ob (ev)" + ld_acc_ob 0x0001020304050607, 0x0000000000000000, 0x0000000000000000 + ld_ob $f8, 0x1122334455667788 + ld_ob $f9, 0x66778899aabbccdd + pabsdiffc.ob $f8, $f9[7] + ck_acc_ob 0x0001020304050607, 0x0000000000000000, 0x5544332211001122 + + writemsg "pabsdiffc.ob (cv)" + ld_acc_ob 0x0001020304050607, 0x0000000000000000, 0x0000000000000000 + ld_ob $f8, 0x0001020304050607 + pabsdiffc.ob $f8, 0x04 + ck_acc_ob 0x0001020304050607, 0x0000000000000000, 0x0403020100010203 + + + pass + + .end DIAG diff --git a/sim/testsuite/sim/mips/mdmx-ob.s b/sim/testsuite/sim/mips/mdmx-ob.s new file mode 100644 index 00000000000..ad9bbda3cae --- /dev/null +++ b/sim/testsuite/sim/mips/mdmx-ob.s @@ -0,0 +1,631 @@ +# MDMX .OB op tests. +# mach: mips64 sb1 +# as: -mabi=eabi +# as(mips64): -mabi=eabi -mdmx +# ld: -N -Ttext=0x80010000 +# output: *\\npass\\n + + .include "testutils.inc" + .include "utils-fpu.inc" + .include "utils-mdmx.inc" + + setup + + .set noreorder + + .ent DIAG +DIAG: + + enable_mdmx + + + ### + ### Non-accumulator, non-CC-using .ob format ops. + ### + ### Key: v = vector + ### ev = vector of single element + ### cv = vector of constant. + ### + + + writemsg "add.ob (v)" + ld_ob $f8, 0x1122334455667788 + ld_ob $f9, 0x66778899aabbccdd + add.ob $f10, $f8, $f9 + ck_ob $f10, 0x7799bbddffffffff + + writemsg "add.ob (ev)" + ld_ob $f8, 0x1122334455667788 + ld_ob $f9, 0x66778899aabbccdd + add.ob $f10, $f8, $f9[6] + ck_ob $f10, 0x8899aabbccddeeff + + writemsg "add.ob (cv)" + ld_ob $f8, 0x1122334455667788 + add.ob $f10, $f8, 0x10 + ck_ob $f10, 0x2132435465768798 + + + writemsg "alni.ob" + ld_ob $f8, 0x1122334455667788 + ld_ob $f9, 0x66778899aabbccdd + alni.ob $f10, $f8, $f9, 3 + ck_ob $f10, 0x4455667788667788 + + + writemsg "alnv.ob" + ld_ob $f8, 0x1122334455667788 + ld_ob $f9, 0x66778899aabbccdd + li $4, 5 + alnv.ob $f10, $f8, $f9, $4 + ck_ob $f10, 0x66778866778899aa + + + writemsg "and.ob (v)" + ld_ob $f8, 0x1122334455667788 + ld_ob $f9, 0x66778899aabbccdd + and.ob $f10, $f8, $f9 + ck_ob $f10, 0x0022000000224488 + + writemsg "and.ob (ev)" + ld_ob $f8, 0x1122334455667788 + ld_ob $f9, 0x66778899aabbccdd + and.ob $f10, $f8, $f9[4] + ck_ob $f10, 0x1100110011001188 + + writemsg "and.ob (cv)" + ld_ob $f8, 0x1122334455667788 + and.ob $f10, $f8, 0x1e + ck_ob $f10, 0x1002120414061608 + + + writemsg "max.ob (v)" + ld_ob $f8, 0x1122334455667788 + ld_ob $f9, 0x66778899aabbccdd + max.ob $f10, $f8, $f9 + ck_ob $f10, 0x66778899aabbccdd + + writemsg "max.ob (ev)" + ld_ob $f8, 0x1122334455667788 + ld_ob $f9, 0x66778899aabbccdd + max.ob $f10, $f8, $f9[7] + ck_ob $f10, 0x6666666666667788 + + writemsg "max.ob (cv)" + ld_ob $f8, 0x1122334455667788 + max.ob $f10, $f8, 0x15 + ck_ob $f10, 0x1522334455667788 + + + writemsg "min.ob (v)" + ld_ob $f8, 0x1122334455667788 + ld_ob $f9, 0x66778899aabbccdd + min.ob $f10, $f8, $f9 + ck_ob $f10, 0x1122334455667788 + + writemsg "min.ob (ev)" + ld_ob $f8, 0x1122334455667788 + ld_ob $f9, 0x66778899aabbccdd + min.ob $f10, $f8, $f9[7] + ck_ob $f10, 0x1122334455666666 + + writemsg "min.ob (cv)" + ld_ob $f8, 0x1122334455667788 + min.ob $f10, $f8, 0x15 + ck_ob $f10, 0x1115151515151515 + + + writemsg "mul.ob (v)" + ld_ob $f8, 0x1122334455667788 + ld_ob $f9, 0x0001020304050607 + mul.ob $f10, $f8, $f9 + ck_ob $f10, 0x002266ccffffffff + + writemsg "mul.ob (ev)" + ld_ob $f8, 0x1122334455667788 + ld_ob $f9, 0x0001020304050607 + mul.ob $f10, $f8, $f9[4] + ck_ob $f10, 0x336699ccffffffff + + writemsg "mul.ob (cv)" + ld_ob $f8, 0x1122334455667788 + mul.ob $f10, $f8, 2 + ck_ob $f10, 0x22446688aacceeff + + + writemsg "nor.ob (v)" + ld_ob $f8, 0x1122334455667788 + ld_ob $f9, 0x66778899aabbccdd + nor.ob $f10, $f8, $f9 + ck_ob $f10, 0x8888442200000022 + + writemsg "nor.ob (ev)" + ld_ob $f8, 0x1122334455667788 + ld_ob $f9, 0x66778899aabbccdd + nor.ob $f10, $f8, $f9[6] + ck_ob $f10, 0x8888888888888800 + + writemsg "nor.ob (cv)" + ld_ob $f8, 0x1122334455667788 + nor.ob $f10, $f8, 0x08 + ck_ob $f10, 0xe6d5c4b3a2918077 + + + writemsg "or.ob (v)" + ld_ob $f8, 0x1122334455667788 + ld_ob $f9, 0x66778899aabbccdd + or.ob $f10, $f8, $f9 + ck_ob $f10, 0x7777bbddffffffdd + + writemsg "or.ob (ev)" + ld_ob $f8, 0x1122334455667788 + ld_ob $f9, 0x66778899aabbccdd + or.ob $f10, $f8, $f9[6] + ck_ob $f10, 0x77777777777777ff + + writemsg "or.ob (cv)" + ld_ob $f8, 0x1122334455667788 + or.ob $f10, $f8, 0x08 + ck_ob $f10, 0x192a3b4c5d6e7f88 + + + writemsg "shfl.mixh.ob" + ld_ob $f8, 0x1122334455667788 + ld_ob $f9, 0x66778899aabbccdd + shfl.mixh.ob $f10, $f8, $f9 + ck_ob $f10, 0x1166227733884499 + + + writemsg "shfl.mixl.ob" + ld_ob $f8, 0x1122334455667788 + ld_ob $f9, 0x66778899aabbccdd + shfl.mixl.ob $f10, $f8, $f9 + ck_ob $f10, 0x55aa66bb77cc88dd + + + writemsg "shfl.pach.ob" + ld_ob $f8, 0x1122334455667788 + ld_ob $f9, 0x66778899aabbccdd + shfl.pach.ob $f10, $f8, $f9 + ck_ob $f10, 0x113355776688aacc + + + writemsg "shfl.upsl.ob" + ld_ob $f8, 0x1122334455667788 + shfl.upsl.ob $f10, $f8, $f8 + ck_ob $f10, 0x005500660077ff88 + + + writemsg "sll.ob (v)" + ld_ob $f8, 0x1122334455667788 + ld_ob $f9, 0x0001020304050607 + sll.ob $f10, $f8, $f9 + ck_ob $f10, 0x1144cc2050c0c000 + + writemsg "sll.ob (ev)" + ld_ob $f8, 0x1122334455667788 + ld_ob $f9, 0x0001020304050607 + sll.ob $f10, $f8, $f9[3] + ck_ob $f10, 0x1020304050607080 + + writemsg "sll.ob (cv)" + ld_ob $f8, 0x1122334455667788 + sll.ob $f10, $f8, 1 + ck_ob $f10, 0x22446688aaccee10 + + + writemsg "srl.ob (v)" + ld_ob $f8, 0x1122334455667788 + ld_ob $f9, 0x0001020304050607 + srl.ob $f10, $f8, $f9 + ck_ob $f10, 0x11110c0805030101 + + writemsg "srl.ob (ev)" + ld_ob $f8, 0x1122334455667788 + ld_ob $f9, 0x0001020304050607 + srl.ob $f10, $f8, $f9[3] + ck_ob $f10, 0x0102030405060708 + + writemsg "srl.ob (cv)" + ld_ob $f8, 0x1122334455667788 + srl.ob $f10, $f8, 1 + ck_ob $f10, 0x081119222a333b44 + + + writemsg "sub.ob (v)" + ld_ob $f8, 0x1122334455667788 + ld_ob $f9, 0x0001020304050607 + sub.ob $f10, $f8, $f9 + ck_ob $f10, 0x1121314151617181 + + writemsg "sub.ob (ev)" + ld_ob $f8, 0x1122334455667788 + ld_ob $f9, 0x66778899aabbccdd + sub.ob $f10, $f8, $f9[7] + ck_ob $f10, 0x0000000000001122 + + writemsg "sub.ob (cv)" + ld_ob $f8, 0x1122334455667788 + sub.ob $f10, $f8, 0x10 + ck_ob $f10, 0x0112233445566778 + + + writemsg "xor.ob (v)" + ld_ob $f8, 0x1122334455667788 + ld_ob $f9, 0x66778899aabbccdd + xor.ob $f10, $f8, $f9 + ck_ob $f10, 0x7755bbddffddbb55 + + writemsg "xor.ob (ev)" + ld_ob $f8, 0x1122334455667788 + ld_ob $f9, 0x66778899aabbccdd + xor.ob $f10, $f8, $f9[6] + ck_ob $f10, 0x66554433221100ff + + writemsg "xor.ob (cv)" + ld_ob $f8, 0x1122334455667788 + xor.ob $f10, $f8, 0x08 + ck_ob $f10, 0x192a3b4c5d6e7f80 + + + ### + ### Accumulator .ob format ops (in order: rd/wr, math, scale/round) + ### + ### Key: v = vector + ### ev = vector of single element + ### cv = vector of constant. + ### + + + writemsg "wacl.ob / rac[hml].ob" + ld_ob $f8, 0x8001028304850687 + ld_ob $f9, 0x1011121314151617 + wacl.ob $f8, $f9 + ck_acc_ob 0xff0000ff00ff00ff, 0x8001028304850687, 0x1011121314151617 + + # Note: relies on data left in accumulator by previous test. + writemsg "wach.ob / rac[hml].ob" + ld_ob $f8, 0x2021222324252627 + wach.ob $f8 + ck_acc_ob 0x2021222324252627, 0x8001028304850687, 0x1011121314151617 + + + writemsg "adda.ob (v)" + ld_acc_ob 0x0001020304050607, 0x0000000000000000, 0x0000000000000000 + ld_ob $f8, 0x1122334455667788 + ld_ob $f9, 0x66778899aabbccdd + adda.ob $f8, $f9 + ck_acc_ob 0x0001020304050607, 0x0000000000010101, 0x7799bbddff214365 + + writemsg "adda.ob (ev)" + ld_acc_ob 0x0001020304050607, 0x0000000000000000, 0x0000000000000000 + ld_ob $f8, 0x1122334455667788 + ld_ob $f9, 0x66778899aabbccdd + adda.ob $f8, $f9[2] + ck_acc_ob 0x0001020304050607, 0x0000000001010101, 0xccddeeff10213243 + + writemsg "adda.ob (cv)" + ld_acc_ob 0x0001020304050607, 0x0000000000000000, 0x0000000000000000 + ld_ob $f8, 0x1122334455667788 + adda.ob $f8, 0x1f + ck_acc_ob 0x0001020304050607, 0x0000000000000000, 0x30415263748596a7 + + + writemsg "addl.ob (v)" + ld_acc_ob 0x0001020304050607, 0x0000000000000000, 0x0000000000000000 + ld_ob $f8, 0x1122334455667788 + ld_ob $f9, 0x66778899aabbccdd + addl.ob $f8, $f9 + ck_acc_ob 0x0000000000000000, 0x0000000000010101, 0x7799bbddff214365 + + writemsg "addl.ob (ev)" + ld_acc_ob 0x0001020304050607, 0x0000000000000000, 0x0000000000000000 + ld_ob $f8, 0x1122334455667788 + ld_ob $f9, 0x66778899aabbccdd + addl.ob $f8, $f9[2] + ck_acc_ob 0x0000000000000000, 0x0000000001010101, 0xccddeeff10213243 + + writemsg "addl.ob (cv)" + ld_acc_ob 0x0001020304050607, 0x0000000000000000, 0x0000000000000000 + ld_ob $f8, 0x1122334455667788 + addl.ob $f8, 0x1f + ck_acc_ob 0x0000000000000000, 0x0000000000000000, 0x30415263748596a7 + + + writemsg "mula.ob (v)" + ld_acc_ob 0x0001020304050607, 0x0000000000000000, 0x0000000000000000 + ld_ob $f8, 0x1122334455667788 + ld_ob $f9, 0x66778899aabbccdd + mula.ob $f8, $f9 + ck_acc_ob 0x0001020304050607, 0x060f1b28384a5e75, 0xc6ce18a47282d468 + + writemsg "mula.ob (ev)" + ld_acc_ob 0x0001020304050607, 0x0000000000000000, 0x0000000000000000 + ld_ob $f8, 0x1122334455667788 + ld_ob $f9, 0x66778899aabbccdd + mula.ob $f8, $f9[2] + ck_acc_ob 0x0001020304050607, 0x0c1825313e4a5663, 0x6bd641ac1782ed58 + + writemsg "mula.ob (cv)" + ld_acc_ob 0x0001020304050607, 0x0000000000000000, 0x0000000000000000 + ld_ob $f8, 0x1122334455667788 + mula.ob $f8, 0x1f + ck_acc_ob 0x0001020304050607, 0x020406080a0c0e10, 0x0f1e2d3c4b5a6978 + + + writemsg "mull.ob (v)" + ld_acc_ob 0x0001020304050607, 0x0000000000000000, 0x0000000000000000 + ld_ob $f8, 0x1122334455667788 + ld_ob $f9, 0x66778899aabbccdd + mull.ob $f8, $f9 + ck_acc_ob 0x0000000000000000, 0x060f1b28384a5e75, 0xc6ce18a47282d468 + + writemsg "mull.ob (ev)" + ld_acc_ob 0x0001020304050607, 0x0000000000000000, 0x0000000000000000 + ld_ob $f8, 0x1122334455667788 + ld_ob $f9, 0x66778899aabbccdd + mull.ob $f8, $f9[2] + ck_acc_ob 0x0000000000000000, 0x0c1825313e4a5663, 0x6bd641ac1782ed58 + + writemsg "mull.ob (cv)" + ld_acc_ob 0x0001020304050607, 0x0000000000000000, 0x0000000000000000 + ld_ob $f8, 0x1122334455667788 + mull.ob $f8, 0x1f + ck_acc_ob 0x0000000000000000, 0x020406080a0c0e10, 0x0f1e2d3c4b5a6978 + + + writemsg "muls.ob (v)" + ld_acc_ob 0x0001020304050607, 0x0000000000000000, 0x0000000000000000 + ld_ob $f8, 0x1122334455667788 + ld_ob $f9, 0x66778899aabbccdd + muls.ob $f8, $f9 + ck_acc_ob 0xff00010203040506, 0xf9f0e4d7c7b5a18a, 0x3a32e85c8e7e2c98 + + writemsg "muls.ob (ev)" + ld_acc_ob 0x0001020304050607, 0x0000000000000000, 0x0000000000000000 + ld_ob $f8, 0x1122334455667788 + ld_ob $f9, 0x66778899aabbccdd + muls.ob $f8, $f9[2] + ck_acc_ob 0xff00010203040506, 0xf3e7dacec1b5a99c, 0x952abf54e97e13a8 + + writemsg "muls.ob (cv)" + ld_acc_ob 0x0001020304050607, 0x0000000000000000, 0x0000000000000000 + ld_ob $f8, 0x1122334455667788 + muls.ob $f8, 0x1f + ck_acc_ob 0xff00010203040506, 0xfdfbf9f7f5f3f1ef, 0xf1e2d3c4b5a69788 + + + writemsg "mulsl.ob (v)" + ld_acc_ob 0x0001020304050607, 0x0000000000000000, 0x0000000000000000 + ld_ob $f8, 0x1122334455667788 + ld_ob $f9, 0x66778899aabbccdd + mulsl.ob $f8, $f9 + ck_acc_ob 0xffffffffffffffff, 0xf9f0e4d7c7b5a18a, 0x3a32e85c8e7e2c98 + + writemsg "mulsl.ob (ev)" + ld_acc_ob 0x0001020304050607, 0x0000000000000000, 0x0000000000000000 + ld_ob $f8, 0x1122334455667788 + ld_ob $f9, 0x66778899aabbccdd + mulsl.ob $f8, $f9[2] + ck_acc_ob 0xffffffffffffffff, 0xf3e7dacec1b5a99c, 0x952abf54e97e13a8 + + writemsg "mulsl.ob (cv)" + ld_acc_ob 0x0001020304050607, 0x0000000000000000, 0x0000000000000000 + ld_ob $f8, 0x1122334455667788 + mulsl.ob $f8, 0x1f + ck_acc_ob 0xffffffffffffffff, 0xfdfbf9f7f5f3f1ef, 0xf1e2d3c4b5a69788 + + + writemsg "suba.ob (v)" + ld_acc_ob 0x0001020304050607, 0x0000000000000000, 0x0000000000000000 + ld_ob $f8, 0x1122334455667788 + ld_ob $f9, 0x66778899aabbccdd + suba.ob $f8, $f9 + ck_acc_ob 0xff00010203040506, 0xffffffffffffffff, 0xabababababababab + + writemsg "suba.ob (ev)" + ld_acc_ob 0x0001020304050607, 0x0000000000000000, 0x0000000000000000 + ld_ob $f8, 0x1122334455667788 + ld_ob $f9, 0x66778899aabbccdd + suba.ob $f8, $f9[2] + ck_acc_ob 0xff00010203040506, 0xffffffffffffffff, 0x566778899aabbccd + + writemsg "suba.ob (cv)" + ld_acc_ob 0x0001020304050607, 0x0000000000000000, 0x0000000000000000 + ld_ob $f8, 0x1122334455667788 + suba.ob $f8, 0x1f + ck_acc_ob 0xff01020304050607, 0xff00000000000000, 0xf203142536475869 + + + writemsg "subl.ob (v)" + ld_acc_ob 0x0001020304050607, 0x0000000000000000, 0x0000000000000000 + ld_ob $f8, 0x1122334455667788 + ld_ob $f9, 0x66778899aabbccdd + subl.ob $f8, $f9 + ck_acc_ob 0xffffffffffffffff, 0xffffffffffffffff, 0xabababababababab + + writemsg "subl.ob (ev)" + ld_acc_ob 0x0001020304050607, 0x0000000000000000, 0x0000000000000000 + ld_ob $f8, 0x1122334455667788 + ld_ob $f9, 0x66778899aabbccdd + subl.ob $f8, $f9[2] + ck_acc_ob 0xffffffffffffffff, 0xffffffffffffffff, 0x566778899aabbccd + + writemsg "subl.ob (cv)" + ld_acc_ob 0x0001020304050607, 0x0000000000000000, 0x0000000000000000 + ld_ob $f8, 0x1122334455667788 + subl.ob $f8, 0x1f + ck_acc_ob 0xff00000000000000, 0xff00000000000000, 0xf203142536475869 + + + writemsg "rnau.ob (v)" + ld_acc_ob 0x0000000000000000, 0x0000000003030303, 0x40424446f8fafcfe + ld_ob $f8, 0x0001020304050607 + rnau.ob $f9, $f8 + ck_ob $f9, 0x4021110940201008 + + writemsg "rnau.ob (ev)" + ld_acc_ob 0x0000000000000000, 0x0000000003030303, 0x40424446f8fafcfe + ld_ob $f8, 0x0001020304050607 + rnau.ob $f9, $f8[4] + ck_ob $f9, 0x080809097f7f8080 + + writemsg "rnau.ob (cv)" + ld_acc_ob 0x0000000000000000, 0x0000000003030303, 0x40424446f8fafcfe + rnau.ob $f9, 2 + ck_ob $f9, 0x10111112feffffff + + + writemsg "rneu.ob (v)" + ld_acc_ob 0x0000000000000000, 0x0000000003030303, 0x40424446f8fafcfe + ld_ob $f8, 0x0001020304050607 + rneu.ob $f9, $f8 + ck_ob $f9, 0x4021110940201008 + + writemsg "rneu.ob (ev)" + ld_acc_ob 0x0000000000000000, 0x0000000003030303, 0x40424446f8fafcfe + ld_ob $f8, 0x0001020304050607 + rneu.ob $f9, $f8[4] + ck_ob $f9, 0x080808097f7f8080 + + writemsg "rneu.ob (cv)" + ld_acc_ob 0x0000000000000000, 0x0000000003030303, 0x40424446f8fafcfe + rneu.ob $f9, 2 + ck_ob $f9, 0x10101112fefeffff + + + writemsg "rzu.ob (v)" + ld_acc_ob 0x0000000000000000, 0x0000000003030303, 0x40424446f8fafcfe + ld_ob $f8, 0x0001020304050607 + rzu.ob $f9, $f8 + ck_ob $f9, 0x402111083f1f0f07 + + writemsg "rzu.ob (ev)" + ld_acc_ob 0x0000000000000000, 0x0000000003030303, 0x40424446f8fafcfe + ld_ob $f8, 0x0001020304050607 + rzu.ob $f9, $f8[4] + ck_ob $f9, 0x080808087f7f7f7f + + writemsg "rzu.ob (cv)" + ld_acc_ob 0x0000000000000000, 0x0000000003030303, 0x40424446f8fafcfe + rzu.ob $f9, 2 + ck_ob $f9, 0x10101111fefeffff + + + ### + ### CC-using .ob format ops. + ### + ### Key: v = vector + ### ev = vector of single element + ### cv = vector of constant. + ### + + + writemsg "c.eq.ob (v)" + ld_ob $f8, 0x0001010202030304 + ld_ob $f9, 0x0101020203030404 + clr_fp_cc 0xff + c.eq.ob $f8, $f9 + ck_fp_cc 0x55 + + writemsg "c.eq.ob (ev)" + ld_ob $f8, 0x0001010202030304 + ld_ob $f9, 0x0101020203030404 + clr_fp_cc 0xff + c.eq.ob $f8, $f9[5] + ck_fp_cc 0x18 + + writemsg "c.eq.ob (cv)" + ld_ob $f8, 0x0001010202030304 + clr_fp_cc 0xff + c.eq.ob $f8, 0x03 + ck_fp_cc 0x06 + + + writemsg "c.le.ob (v)" + ld_ob $f8, 0x0001010202030304 + ld_ob $f9, 0x0101020203030404 + clr_fp_cc 0xff + c.le.ob $f8, $f9 + ck_fp_cc 0xff + + writemsg "c.le.ob (ev)" + ld_ob $f8, 0x0001010202030304 + ld_ob $f9, 0x0101020203030404 + clr_fp_cc 0xff + c.le.ob $f8, $f9[5] + ck_fp_cc 0xf8 + + writemsg "c.le.ob (cv)" + ld_ob $f8, 0x0001010202030304 + clr_fp_cc 0xff + c.le.ob $f8, 0x03 + ck_fp_cc 0xfe + + + writemsg "c.lt.ob (v)" + ld_ob $f8, 0x0001010202030304 + ld_ob $f9, 0x0101020203030404 + clr_fp_cc 0xff + c.lt.ob $f8, $f9 + ck_fp_cc 0xaa + + writemsg "c.lt.ob (ev)" + ld_ob $f8, 0x0001010202030304 + ld_ob $f9, 0x0101020203030404 + clr_fp_cc 0xff + c.lt.ob $f8, $f9[5] + ck_fp_cc 0xe0 + + writemsg "c.lt.ob (cv)" + ld_ob $f8, 0x0001010202030304 + clr_fp_cc 0xff + c.lt.ob $f8, 0x03 + ck_fp_cc 0xf8 + + + writemsg "pickf.ob (v)" + ld_ob $f8, 0x0001020304050607 + ld_ob $f9, 0x08090a0b0c0d0e0f + clrset_fp_cc 0xff, 0xaa + pickf.ob $f10, $f8, $f9 + ck_ob $f10, 0x08010a030c050e07 + + writemsg "pickf.ob (ev)" + ld_ob $f8, 0x0001020304050607 + ld_ob $f9, 0x08090a0b0c0d0e0f + clrset_fp_cc 0xff, 0xaa + pickf.ob $f10, $f8, $f9[4] + ck_ob $f10, 0x0b010b030b050b07 + + writemsg "pickf.ob (cv)" + ld_ob $f8, 0x0001020304050607 + clrset_fp_cc 0xff, 0xaa + pickf.ob $f10, $f8, 0x10 + ck_ob $f10, 0x1001100310051007 + + + writemsg "pickt.ob (v)" + ld_ob $f8, 0x0001020304050607 + ld_ob $f9, 0x08090a0b0c0d0e0f + clrset_fp_cc 0xff, 0xaa + pickt.ob $f10, $f8, $f9 + ck_ob $f10, 0x0009020b040d060f + + writemsg "pickt.ob (ev)" + ld_ob $f8, 0x0001020304050607 + ld_ob $f9, 0x08090a0b0c0d0e0f + clrset_fp_cc 0xff, 0xaa + pickt.ob $f10, $f8, $f9[5] + ck_ob $f10, 0x000a020a040a060a + + writemsg "pickt.ob (cv)" + ld_ob $f8, 0x0001020304050607 + clrset_fp_cc 0xff, 0xaa + pickt.ob $f10, $f8, 0x10 + ck_ob $f10, 0x0010021004100610 + + + pass + + .end DIAG diff --git a/sim/testsuite/sim/mips/utils-fpu.inc b/sim/testsuite/sim/mips/utils-fpu.inc new file mode 100644 index 00000000000..82feb61ce9d --- /dev/null +++ b/sim/testsuite/sim/mips/utils-fpu.inc @@ -0,0 +1,105 @@ +# MIPS simulator testsuite FPU utility functions. +# Copyright (C) 2004 Free Software Foundation, Inc. +# Contributed by Chris Demetriou of Broadcom Corporation. +# +# This file is part of the GNU simulators. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + + .macro enable_fpu fr + mfc0 $20, $12 + or $20, $20, (1 << 29) | (\fr << 26) + mtc0 $20, $20 + .endm + + ### + ### Data movement macros + ### + + .macro ld_fp_df r, v + .data +1: .double \v + .previous + ldc1 \r, 1b + .endm + + .macro ld_fp_di r, v + .data +1: .dword \v + .previous + ldc1 \r, 1b + .endm + + .macro ld_fp_sf r, v + .data +1: .float \v + .previous + lwc1 \r, 1b + .endm + + .macro ld_fp_si r, v + .data +1: .word \v + .previous + lwc1 \r, 1b + .endm + + + ### + ### FP condition code manipulation macros + ### + + .macro clrset_fp_cc clr, set + cfc1 $20, $31 + or $20, $20, (((\clr & 0xfe) << 24) | ((\clr & 0x01) << 23)) + xor $20, $20, (((\clr & 0xfe) << 24) | ((\clr & 0x01) << 23)) + or $20, $20, (((\set & 0xfe) << 24) | ((\set & 0x01) << 23)) + ctc1 $20, $31 + .endm + + .macro clr_fp_cc clr + clrset_fp_cc \clr, 0 + .endm + + .macro set_fp_cc set + clrset_fp_cc 0, \set + .endm + + .macro get_fp_cc r + .set push + .set noat + cfc1 $1, $31 + srl $1, $1, 23 + andi \r, $1, 0x1fc + andi $1, $1, 0x1 + srl \r, \r, 1 + or \r, \r, $1 + .set pop + .endm + + .macro ck_fp_cc v + get_fp_cc $20 + xori $20, $20, \v + bnez $20, _fail + nop + .endm + + .macro ckm_fp_cc v, mask + get_fp_cc $20 + xori $20, $20, \v + andi $20, $20, \mask + bnez $20, _fail + nop + .endm diff --git a/sim/testsuite/sim/mips/utils-mdmx.inc b/sim/testsuite/sim/mips/utils-mdmx.inc new file mode 100644 index 00000000000..cda6550dc8c --- /dev/null +++ b/sim/testsuite/sim/mips/utils-mdmx.inc @@ -0,0 +1,72 @@ +# MIPS simulator testsuite MDMX utility functions. +# Copyright (C) 2004 Free Software Foundation, Inc. +# Contributed by Chris Demetriou of Broadcom Corporation. +# +# This file is part of the GNU simulators. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + + .include "utils-fpu.inc" + + ### + ### Shared macros + ### + + # Enable MDMX: enable the FPU w/ FR=1, then set Status.MX + .macro enable_mdmx + enable_fpu 1 + mfc0 $20, $12 + or $20, $20, (1 << 24) + mtc0 $20, $12 + .endm + + + ### + ### .OB-format macros + ### + + .macro ld_ob r, v + .data +1: .dword \v + .previous + ldc1 \r, 1b + .endm + + .macro ck_ob r, v + .data +1: .dword \v + .previous + dmfc1 $20, \r + ld $21, 1b + bne $20, $21, _fail + nop + .endm + + .macro ld_acc_ob h, m, l + ld_ob $f20, \m + ld_ob $f21, \l + wacl.ob $f20, $f21 + ld_ob $f20, \h + wach.ob $f20 + .endm + + .macro ck_acc_ob h, m, l + rach.ob $f20 + ck_ob $f20, \h + racm.ob $f20 + ck_ob $f20, \m + racl.ob $f20 + ck_ob $f20, \l + .endm diff --git a/sim/testsuite/sim/sh/bandor.s b/sim/testsuite/sim/sh/bandor.s new file mode 100644 index 00000000000..9ada4850696 --- /dev/null +++ b/sim/testsuite/sim/sh/bandor.s @@ -0,0 +1,120 @@ +# sh testcase for band, bor +# mach: all +# as(sh): -defsym sim_cpu=0 +# as(shdsp): -defsym sim_cpu=1 -dsp + + .include "testutils.inc" + + .align 2 +_x: .long 0xa5a5a5a5 + + start + +bandor_b_imm_disp12_reg: + set_grs_a5a5 + # Make sure T is true to start. + sett + + mov.l x, r1 + + band.b #0, @(3, r1) + bf8k mfail + bor.b #1, @(3, r1) + bf8k mfail + band.b #2, @(3, r1) + bf8k mfail + bor.b #3, @(3, r1) + bf8k mfail + + bor.b #4, @(3, r1) + bf8k mfail + band.b #5, @(3, r1) + bf8k mfail + bor.b #6, @(3, r1) + bf8k mfail + band.b #7, @(3, r1) + bf8k mfail + + band.b #0, @(2, r1) + bf8k mfail + bor.b #1, @(2, r1) + bf8k mfail + band.b #2, @(2, r1) + bf8k mfail + bor.b #3, @(2, r1) + bf8k mfail + + bra .L2 + nop + + .align 2 +x: .long _x + +.L2: + bor.b #4, @(2, r1) + bf8k mfail + band.b #5, @(2, r1) + bf8k mfail + bor.b #6, @(2, r1) + bf8k mfail + band.b #7, @(2, r1) + bf8k mfail + + band.b #0, @(1, r1) + bf8k mfail + bor.b #1, @(1, r1) + bf8k mfail + band.b #2, @(1, r1) + bf8k mfail + bor.b #3, @(1, r1) + bf8k mfail + + bor.b #4, @(1, r1) + bf8k mfail + band.b #5, @(1, r1) + bf8k mfail + bor.b #6, @(1, r1) + bf8k mfail + band.b #7, @(1, r1) + bf8k mfail + + band.b #0, @(0, r1) + bf8k mfail + bor.b #1, @(0, r1) + bf8k mfail + band.b #2, @(0, r1) + bf8k mfail + bor.b #3, @(0, r1) + bf8k mfail + + bor.b #4, @(0, r1) + bf8k mfail + band.b #5, @(0, r1) + bf8k mfail + bor.b #6, @(0, r1) + bf8k mfail + band.b #7, @(0, r1) + bf8k mfail + + assertreg _x, r1 + + test_gr_a5a5 r0 + test_gr_a5a5 r2 + test_gr_a5a5 r3 + test_gr_a5a5 r4 + test_gr_a5a5 r5 + test_gr_a5a5 r6 + test_gr_a5a5 r7 + test_gr_a5a5 r8 + test_gr_a5a5 r9 + test_gr_a5a5 r10 + test_gr_a5a5 r11 + test_gr_a5a5 r12 + test_gr_a5a5 r13 + test_gr_a5a5 r14 + + pass + + exit 0 + + diff --git a/sim/testsuite/sim/sh/bandornot.s b/sim/testsuite/sim/sh/bandornot.s new file mode 100644 index 00000000000..1787d0d92fb --- /dev/null +++ b/sim/testsuite/sim/sh/bandornot.s @@ -0,0 +1,120 @@ +# sh testcase for bandnot, bornot +# mach: all +# as(sh): -defsym sim_cpu=0 +# as(shdsp): -defsym sim_cpu=1 -dsp + + .include "testutils.inc" + + .align 2 +_x: .long 0xa5a5a5a5 + + start + +bandor_b_imm_disp12_reg: + set_grs_a5a5 + # Make sure T is true to start. + sett + + mov.l x, r1 + + bandnot.b #0, @(3, r1) + bt8k mfail + bornot.b #1, @(3, r1) + bf8k mfail + bandnot.b #2, @(3, r1) + bt8k mfail + bornot.b #3, @(3, r1) + bf8k mfail + + bornot.b #4, @(3, r1) + bf8k mfail + bandnot.b #5, @(3, r1) + bt8k mfail + bornot.b #6, @(3, r1) + bf8k mfail + bandnot.b #7, @(3, r1) + bt8k mfail + + bandnot.b #0, @(2, r1) + bt8k mfail + bornot.b #1, @(2, r1) + bf8k mfail + bandnot.b #2, @(2, r1) + bt8k mfail + bornot.b #3, @(2, r1) + bf8k mfail + + bra .L2 + nop + + .align 2 +x: .long _x + +.L2: + bornot.b #4, @(2, r1) + bf8k mfail + bandnot.b #5, @(2, r1) + bt8k mfail + bornot.b #6, @(2, r1) + bf8k mfail + bandnot.b #7, @(2, r1) + bt8k mfail + + bandnot.b #0, @(1, r1) + bt8k mfail + bornot.b #1, @(1, r1) + bf8k mfail + bandnot.b #2, @(1, r1) + bt8k mfail + bornot.b #3, @(1, r1) + bf8k mfail + + bornot.b #4, @(1, r1) + bf8k mfail + bandnot.b #5, @(1, r1) + bt8k mfail + bornot.b #6, @(1, r1) + bf8k mfail + bandnot.b #7, @(1, r1) + bt8k mfail + + bandnot.b #0, @(0, r1) + bt8k mfail + bornot.b #1, @(0, r1) + bf8k mfail + bandnot.b #2, @(0, r1) + bt8k mfail + bornot.b #3, @(0, r1) + bf8k mfail + + bornot.b #4, @(0, r1) + bf8k mfail + bandnot.b #5, @(0, r1) + bt8k mfail + bornot.b #6, @(0, r1) + bf8k mfail + bandnot.b #7, @(0, r1) + bt8k mfail + + assertreg _x, r1 + + test_gr_a5a5 r0 + test_gr_a5a5 r2 + test_gr_a5a5 r3 + test_gr_a5a5 r4 + test_gr_a5a5 r5 + test_gr_a5a5 r6 + test_gr_a5a5 r7 + test_gr_a5a5 r8 + test_gr_a5a5 r9 + test_gr_a5a5 r10 + test_gr_a5a5 r11 + test_gr_a5a5 r12 + test_gr_a5a5 r13 + test_gr_a5a5 r14 + + pass + + exit 0 + + diff --git a/sim/testsuite/sim/sh/bclr.s b/sim/testsuite/sim/sh/bclr.s new file mode 100644 index 00000000000..cbe1c7e618d --- /dev/null +++ b/sim/testsuite/sim/sh/bclr.s @@ -0,0 +1,139 @@ +# sh testcase for bclr +# mach: all +# as(sh): -defsym sim_cpu=0 +# as(shdsp): -defsym sim_cpu=1 -dsp + + .include "testutils.inc" + + .align 2 +_x: .long 0xffffffff +_y: .long 0x55555555 + + start + +bclr_b_imm_disp12_reg: + set_grs_a5a5 + mov.l x, r1 + + bclr.b #0, @(3, r1) + assertmem _x, 0xfffffffe + bclr.b #1, @(3, r1) + assertmem _x, 0xfffffffc + bclr.b #2, @(3, r1) + assertmem _x, 0xfffffff8 + bclr.b #3, @(3, r1) + assertmem _x, 0xfffffff0 + + bclr.b #4, @(3, r1) + assertmem _x, 0xffffffe0 + bclr.b #5, @(3, r1) + assertmem _x, 0xffffffc0 + bclr.b #6, @(3, r1) + assertmem _x, 0xffffff80 + bclr.b #7, @(3, r1) + assertmem _x, 0xffffff00 + + bclr.b #0, @(2, r1) + assertmem _x, 0xfffffe00 + bclr.b #1, @(2, r1) + assertmem _x, 0xfffffc00 + bclr.b #2, @(2, r1) + assertmem _x, 0xfffff800 + bclr.b #3, @(2, r1) + assertmem _x, 0xfffff000 + + bra .L2 + nop + + .align 2 +x: .long _x +y: .long _y + +.L2: + bclr.b #4, @(2, r1) + assertmem _x, 0xffffe000 + bclr.b #5, @(2, r1) + assertmem _x, 0xffffc000 + bclr.b #6, @(2, r1) + assertmem _x, 0xffff8000 + bclr.b #7, @(2, r1) + assertmem _x, 0xffff0000 + + bclr.b #0, @(1, r1) + assertmem _x, 0xfffe0000 + bclr.b #1, @(1, r1) + assertmem _x, 0xfffc0000 + bclr.b #2, @(1, r1) + assertmem _x, 0xfff80000 + bclr.b #3, @(1, r1) + assertmem _x, 0xfff00000 + + bclr.b #4, @(1, r1) + assertmem _x, 0xffe00000 + bclr.b #5, @(1, r1) + assertmem _x, 0xffc00000 + bclr.b #6, @(1, r1) + assertmem _x, 0xff800000 + bclr.b #7, @(1, r1) + assertmem _x, 0xff000000 + + bclr.b #0, @(0, r1) + assertmem _x, 0xfe000000 + bclr.b #1, @(0, r1) + assertmem _x, 0xfc000000 + bclr.b #2, @(0, r1) + assertmem _x, 0xf8000000 + bclr.b #3, @(0, r1) + assertmem _x, 0xf0000000 + + bclr.b #4, @(0, r1) + assertmem _x, 0xe0000000 + bclr.b #5, @(0, r1) + assertmem _x, 0xc0000000 + bclr.b #6, @(0, r1) + assertmem _x, 0x80000000 + bclr.b #7, @(0, r1) + assertmem _x, 0x00000000 + + assertreg _x, r1 + +bclr_imm_reg: + set_greg 0xff, r1 + bclr #0, r1 + assertreg 0xfe, r1 + bclr #1, r1 + assertreg 0xfc, r1 + bclr #2, r1 + assertreg 0xf8, r1 + bclr #3, r1 + assertreg 0xf0, r1 + + bclr #4, r1 + assertreg 0xe0, r1 + bclr #5, r1 + assertreg 0xc0, r1 + bclr #6, r1 + assertreg 0x80, r1 + bclr #7, r1 + assertreg 0x00, r1 + + test_gr_a5a5 r0 + test_gr_a5a5 r2 + test_gr_a5a5 r3 + test_gr_a5a5 r4 + test_gr_a5a5 r5 + test_gr_a5a5 r6 + test_gr_a5a5 r7 + test_gr_a5a5 r8 + test_gr_a5a5 r9 + test_gr_a5a5 r10 + test_gr_a5a5 r11 + test_gr_a5a5 r12 + test_gr_a5a5 r13 + test_gr_a5a5 r14 + + pass + + exit 0 + + diff --git a/sim/testsuite/sim/sh/bld.s b/sim/testsuite/sim/sh/bld.s new file mode 100644 index 00000000000..172718df676 --- /dev/null +++ b/sim/testsuite/sim/sh/bld.s @@ -0,0 +1,121 @@ +# sh testcase for bld +# mach: all +# as(sh): -defsym sim_cpu=0 +# as(shdsp): -defsym sim_cpu=1 -dsp + + .include "testutils.inc" + + .align 2 +_x: .long 0xa5a5a5a5 +_y: .long 0x55555555 + + start + +bld_b_imm_disp12_reg: + set_grs_a5a5 + mov.l x, r1 + + bld.b #0, @(0, r1) + bf8k mfail + bld.b #1, @(0, r1) + bt8k mfail + bld.b #2, @(0, r1) + bf8k mfail + bld.b #3, @(0, r1) + bt8k mfail + + bld.b #4, @(0, r1) + bt8k mfail + bld.b #5, @(0, r1) + bf8k mfail + bld.b #6, @(0, r1) + bt8k mfail + bld.b #7, @(0, r1) + bf8k mfail + + bld.b #0, @(1, r1) + bf8k mfail + bld.b #1, @(1, r1) + bt8k mfail + bld.b #2, @(1, r1) + bf8k mfail + bld.b #3, @(1, r1) + bt8k mfail + + bld.b #4, @(1, r1) + bt8k mfail + bld.b #5, @(1, r1) + bf8k mfail + bld.b #6, @(1, r1) + bt8k mfail + bld.b #7, @(1, r1) + bf8k mfail + + bld.b #0, @(2, r1) + bf8k mfail + bld.b #1, @(2, r1) + bt8k mfail + bld.b #2, @(2, r1) + bf8k mfail + bld.b #3, @(2, r1) + bt8k mfail + + bld.b #4, @(2, r1) + bt8k mfail + bld.b #5, @(2, r1) + bf8k mfail + bld.b #6, @(2, r1) + bt8k mfail + bld.b #7, @(2, r1) + bf8k mfail + + bld.b #0, @(3, r1) + bf8k mfail + bld.b #1, @(3, r1) + bt8k mfail + bld.b #2, @(3, r1) + bf8k mfail + bld.b #3, @(3, r1) + bt8k mfail + + bld.b #4, @(3, r1) + bt8k mfail + bld.b #5, @(3, r1) + bf8k mfail + bld.b #6, @(3, r1) + bt8k mfail + bld.b #7, @(3, r1) + bf8k mfail + + assertreg _x, r1 + +bld_imm_reg: + set_greg 0xa5a5a5a5, r1 + bld #0, r1 + bf8k mfail + bld #1, r1 + bt8k mfail + bld #2, r1 + bf8k mfail + bld #3, r1 + bt8k mfail + + bld #4, r1 + bt8k mfail + bld #5, r1 + bf8k mfail + bld #6, r1 + bt8k mfail + bld #7, r1 + bf8k mfail + + test_grs_a5a5 + + pass + + exit 0 + + .align 2 +x: .long _x +y: .long _y + diff --git a/sim/testsuite/sim/sh/bldnot.s b/sim/testsuite/sim/sh/bldnot.s new file mode 100644 index 00000000000..eda87def9c2 --- /dev/null +++ b/sim/testsuite/sim/sh/bldnot.s @@ -0,0 +1,102 @@ +# sh testcase for bldnot +# mach: all +# as(sh): -defsym sim_cpu=0 +# as(shdsp): -defsym sim_cpu=1 -dsp + + .include "testutils.inc" + + .align 2 +_x: .long 0xa5a5a5a5 +_y: .long 0x55555555 + + start + +bldnot_b_imm_disp12_reg: + set_grs_a5a5 + mov.l x, r1 + + bldnot.b #0, @(0, r1) + bt8k mfail + bldnot.b #1, @(0, r1) + bf8k mfail + bldnot.b #2, @(0, r1) + bt8k mfail + bldnot.b #3, @(0, r1) + bf8k mfail + + bldnot.b #4, @(0, r1) + bf8k mfail + bldnot.b #5, @(0, r1) + bt8k mfail + bldnot.b #6, @(0, r1) + bf8k mfail + bldnot.b #7, @(0, r1) + bt8k mfail + + bldnot.b #0, @(1, r1) + bt8k mfail + bldnot.b #1, @(1, r1) + bf8k mfail + bldnot.b #2, @(1, r1) + bt8k mfail + bldnot.b #3, @(1, r1) + bf8k mfail + + bldnot.b #4, @(1, r1) + bf8k mfail + bldnot.b #5, @(1, r1) + bt8k mfail + bldnot.b #6, @(1, r1) + bf8k mfail + bldnot.b #7, @(1, r1) + bt8k mfail + + bldnot.b #0, @(2, r1) + bt8k mfail + bldnot.b #1, @(2, r1) + bf8k mfail + bldnot.b #2, @(2, r1) + bt8k mfail + bldnot.b #3, @(2, r1) + bf8k mfail + + bldnot.b #4, @(2, r1) + bf8k mfail + bldnot.b #5, @(2, r1) + bt8k mfail + bldnot.b #6, @(2, r1) + bf8k mfail + bldnot.b #7, @(2, r1) + bt8k mfail + + bldnot.b #0, @(3, r1) + bt8k mfail + bldnot.b #1, @(3, r1) + bf8k mfail + bldnot.b #2, @(3, r1) + bt8k mfail + bldnot.b #3, @(3, r1) + bf8k mfail + + bldnot.b #4, @(3, r1) + bf8k mfail + bldnot.b #5, @(3, r1) + bt8k mfail + bldnot.b #6, @(3, r1) + bf8k mfail + bldnot.b #7, @(3, r1) + bt8k mfail + + assertreg _x, r1 + set_greg 0xa5a5a5a5, r1 + + test_grs_a5a5 + + pass + + exit 0 + + .align 2 +x: .long _x +y: .long _y + diff --git a/sim/testsuite/sim/sh/bset.s b/sim/testsuite/sim/sh/bset.s new file mode 100644 index 00000000000..13ae246e39c --- /dev/null +++ b/sim/testsuite/sim/sh/bset.s @@ -0,0 +1,139 @@ +# sh testcase for bset +# mach: all +# as(sh): -defsym sim_cpu=0 +# as(shdsp): -defsym sim_cpu=1 -dsp + + .include "testutils.inc" + + .align 2 +_x: .long 0 +_y: .long 0x55555555 + + start + +bset_b_imm_disp12_reg: + set_grs_a5a5 + mov.l x, r1 + + bset.b #0, @(3, r1) + assertmem _x, 0x1 + bset.b #1, @(3, r1) + assertmem _x, 0x3 + bset.b #2, @(3, r1) + assertmem _x, 0x7 + bset.b #3, @(3, r1) + assertmem _x, 0xf + + bset.b #4, @(3, r1) + assertmem _x, 0x1f + bset.b #5, @(3, r1) + assertmem _x, 0x3f + bset.b #6, @(3, r1) + assertmem _x, 0x7f + bset.b #7, @(3, r1) + assertmem _x, 0xff + + bset.b #0, @(2, r1) + assertmem _x, 0x1ff + bset.b #1, @(2, r1) + assertmem _x, 0x3ff + bset.b #2, @(2, r1) + assertmem _x, 0x7ff + bset.b #3, @(2, r1) + assertmem _x, 0xfff + + bra .L2 + nop + + .align 2 +x: .long _x +y: .long _y + +.L2: + bset.b #4, @(2, r1) + assertmem _x, 0x1fff + bset.b #5, @(2, r1) + assertmem _x, 0x3fff + bset.b #6, @(2, r1) + assertmem _x, 0x7fff + bset.b #7, @(2, r1) + assertmem _x, 0xffff + + bset.b #0, @(1, r1) + assertmem _x, 0x1ffff + bset.b #1, @(1, r1) + assertmem _x, 0x3ffff + bset.b #2, @(1, r1) + assertmem _x, 0x7ffff + bset.b #3, @(1, r1) + assertmem _x, 0xfffff + + bset.b #4, @(1, r1) + assertmem _x, 0x1fffff + bset.b #5, @(1, r1) + assertmem _x, 0x3fffff + bset.b #6, @(1, r1) + assertmem _x, 0x7fffff + bset.b #7, @(1, r1) + assertmem _x, 0xffffff + + bset.b #0, @(0, r1) + assertmem _x, 0x1ffffff + bset.b #1, @(0, r1) + assertmem _x, 0x3ffffff + bset.b #2, @(0, r1) + assertmem _x, 0x7ffffff + bset.b #3, @(0, r1) + assertmem _x, 0xfffffff + + bset.b #4, @(0, r1) + assertmem _x, 0x1fffffff + bset.b #5, @(0, r1) + assertmem _x, 0x3fffffff + bset.b #6, @(0, r1) + assertmem _x, 0x7fffffff + bset.b #7, @(0, r1) + assertmem _x, 0xffffffff + + assertreg _x, r1 + +bset_imm_reg: + set_greg 0, r1 + bset #0, r1 + assertreg 0x1, r1 + bset #1, r1 + assertreg 0x3, r1 + bset #2, r1 + assertreg 0x7, r1 + bset #3, r1 + assertreg 0xf, r1 + + bset #4, r1 + assertreg 0x1f, r1 + bset #5, r1 + assertreg 0x3f, r1 + bset #6, r1 + assertreg 0x7f, r1 + bset #7, r1 + assertreg 0xff, r1 + + test_gr_a5a5 r0 + test_gr_a5a5 r2 + test_gr_a5a5 r3 + test_gr_a5a5 r4 + test_gr_a5a5 r5 + test_gr_a5a5 r6 + test_gr_a5a5 r7 + test_gr_a5a5 r8 + test_gr_a5a5 r9 + test_gr_a5a5 r10 + test_gr_a5a5 r11 + test_gr_a5a5 r12 + test_gr_a5a5 r13 + test_gr_a5a5 r14 + + pass + + exit 0 + + diff --git a/sim/testsuite/sim/sh/bst.s b/sim/testsuite/sim/sh/bst.s new file mode 100644 index 00000000000..e8b6d656ec3 --- /dev/null +++ b/sim/testsuite/sim/sh/bst.s @@ -0,0 +1,142 @@ +# sh testcase for bst +# mach: all +# as(sh): -defsym sim_cpu=0 +# as(shdsp): -defsym sim_cpu=1 -dsp + + .include "testutils.inc" + + .align 2 +_x: .long 0 +_y: .long 0x55555555 + + start + +bst_b_imm_disp12_reg: + set_grs_a5a5 + # Make sure T is true to start. + sett + + mov.l x, r1 + + bst.b #0, @(3, r1) + assertmem _x, 0x1 + bst.b #1, @(3, r1) + assertmem _x, 0x3 + bst.b #2, @(3, r1) + assertmem _x, 0x7 + bst.b #3, @(3, r1) + assertmem _x, 0xf + + bst.b #4, @(3, r1) + assertmem _x, 0x1f + bst.b #5, @(3, r1) + assertmem _x, 0x3f + bst.b #6, @(3, r1) + assertmem _x, 0x7f + bst.b #7, @(3, r1) + assertmem _x, 0xff + + bst.b #0, @(2, r1) + assertmem _x, 0x1ff + bst.b #1, @(2, r1) + assertmem _x, 0x3ff + bst.b #2, @(2, r1) + assertmem _x, 0x7ff + bst.b #3, @(2, r1) + assertmem _x, 0xfff + + bra .L2 + nop + + .align 2 +x: .long _x +y: .long _y + +.L2: + bst.b #4, @(2, r1) + assertmem _x, 0x1fff + bst.b #5, @(2, r1) + assertmem _x, 0x3fff + bst.b #6, @(2, r1) + assertmem _x, 0x7fff + bst.b #7, @(2, r1) + assertmem _x, 0xffff + + bst.b #0, @(1, r1) + assertmem _x, 0x1ffff + bst.b #1, @(1, r1) + assertmem _x, 0x3ffff + bst.b #2, @(1, r1) + assertmem _x, 0x7ffff + bst.b #3, @(1, r1) + assertmem _x, 0xfffff + + bst.b #4, @(1, r1) + assertmem _x, 0x1fffff + bst.b #5, @(1, r1) + assertmem _x, 0x3fffff + bst.b #6, @(1, r1) + assertmem _x, 0x7fffff + bst.b #7, @(1, r1) + assertmem _x, 0xffffff + + bst.b #0, @(0, r1) + assertmem _x, 0x1ffffff + bst.b #1, @(0, r1) + assertmem _x, 0x3ffffff + bst.b #2, @(0, r1) + assertmem _x, 0x7ffffff + bst.b #3, @(0, r1) + assertmem _x, 0xfffffff + + bst.b #4, @(0, r1) + assertmem _x, 0x1fffffff + bst.b #5, @(0, r1) + assertmem _x, 0x3fffffff + bst.b #6, @(0, r1) + assertmem _x, 0x7fffffff + bst.b #7, @(0, r1) + assertmem _x, 0xffffffff + + assertreg _x, r1 + +bst_imm_reg: + set_greg 0, r1 + bst #0, r1 + assertreg 0x1, r1 + bst #1, r1 + assertreg 0x3, r1 + bst #2, r1 + assertreg 0x7, r1 + bst #3, r1 + assertreg 0xf, r1 + + bst #4, r1 + assertreg 0x1f, r1 + bst #5, r1 + assertreg 0x3f, r1 + bst #6, r1 + assertreg 0x7f, r1 + bst #7, r1 + assertreg 0xff, r1 + + test_gr_a5a5 r0 + test_gr_a5a5 r2 + test_gr_a5a5 r3 + test_gr_a5a5 r4 + test_gr_a5a5 r5 + test_gr_a5a5 r6 + test_gr_a5a5 r7 + test_gr_a5a5 r8 + test_gr_a5a5 r9 + test_gr_a5a5 r10 + test_gr_a5a5 r11 + test_gr_a5a5 r12 + test_gr_a5a5 r13 + test_gr_a5a5 r14 + + pass + + exit 0 + + diff --git a/sim/testsuite/sim/sh/bxor.s b/sim/testsuite/sim/sh/bxor.s new file mode 100644 index 00000000000..abedd38eb09 --- /dev/null +++ b/sim/testsuite/sim/sh/bxor.s @@ -0,0 +1,120 @@ +# sh testcase for bxor +# mach: all +# as(sh): -defsym sim_cpu=0 +# as(shdsp): -defsym sim_cpu=1 -dsp + + .include "testutils.inc" + + .align 2 +_x: .long 0xa5a5a5a5 + + start + +bxor_b_imm_disp12_reg: + set_grs_a5a5 + # Make sure T is true to start. + sett + + mov.l x, r1 + + bxor.b #0, @(3, r1) + bt8k mfail + bxor.b #1, @(3, r1) + bt8k mfail + bxor.b #2, @(3, r1) + bf8k mfail + bxor.b #3, @(3, r1) + bf8k mfail + + bxor.b #4, @(3, r1) + bf8k mfail + bxor.b #5, @(3, r1) + bt8k mfail + bxor.b #6, @(3, r1) + bt8k mfail + bxor.b #7, @(3, r1) + bf8k mfail + + bxor.b #0, @(2, r1) + bt8k mfail + bxor.b #1, @(2, r1) + bt8k mfail + bxor.b #2, @(2, r1) + bf8k mfail + bxor.b #3, @(2, r1) + bf8k mfail + + bra .L2 + nop + + .align 2 +x: .long _x + +.L2: + bxor.b #4, @(2, r1) + bf8k mfail + bxor.b #5, @(2, r1) + bt8k mfail + bxor.b #6, @(2, r1) + bt8k mfail + bxor.b #7, @(2, r1) + bf8k mfail + + bxor.b #0, @(1, r1) + bt8k mfail + bxor.b #1, @(1, r1) + bt8k mfail + bxor.b #2, @(1, r1) + bf8k mfail + bxor.b #3, @(1, r1) + bf8k mfail + + bxor.b #4, @(1, r1) + bf8k mfail + bxor.b #5, @(1, r1) + bt8k mfail + bxor.b #6, @(1, r1) + bt8k mfail + bxor.b #7, @(1, r1) + bf8k mfail + + bxor.b #0, @(0, r1) + bt8k mfail + bxor.b #1, @(0, r1) + bt8k mfail + bxor.b #2, @(0, r1) + bf8k mfail + bxor.b #3, @(0, r1) + bf8k mfail + + bxor.b #4, @(0, r1) + bf8k mfail + bxor.b #5, @(0, r1) + bt8k mfail + bxor.b #6, @(0, r1) + bt8k mfail + bxor.b #7, @(0, r1) + bf8k mfail + + assertreg _x, r1 + + test_gr_a5a5 r0 + test_gr_a5a5 r2 + test_gr_a5a5 r3 + test_gr_a5a5 r4 + test_gr_a5a5 r5 + test_gr_a5a5 r6 + test_gr_a5a5 r7 + test_gr_a5a5 r8 + test_gr_a5a5 r9 + test_gr_a5a5 r10 + test_gr_a5a5 r11 + test_gr_a5a5 r12 + test_gr_a5a5 r13 + test_gr_a5a5 r14 + + pass + + exit 0 + + diff --git a/sim/testsuite/sim/sh/clip.s b/sim/testsuite/sim/sh/clip.s new file mode 100644 index 00000000000..12770c381db --- /dev/null +++ b/sim/testsuite/sim/sh/clip.s @@ -0,0 +1,89 @@ +# sh testcase for clips, clipu +# mach: all +# as(sh): -defsym sim_cpu=0 +# as(shdsp): -defsym sim_cpu=1 -dsp + + .include "testutils.inc" + + start + +clips_b: + set_grs_a5a5 + clips.b r1 + test_gr0_a5a5 + assertreg 0xffffff80 r1 + test_gr_a5a5 r2 + test_gr_a5a5 r3 + test_gr_a5a5 r4 + test_gr_a5a5 r5 + test_gr_a5a5 r6 + test_gr_a5a5 r7 + test_gr_a5a5 r8 + test_gr_a5a5 r9 + test_gr_a5a5 r10 + test_gr_a5a5 r11 + test_gr_a5a5 r12 + test_gr_a5a5 r13 + test_gr_a5a5 r14 + +clipu_b: + set_grs_a5a5 + clipu.b r1 + test_gr0_a5a5 + assertreg 0xff r1 + test_gr_a5a5 r2 + test_gr_a5a5 r3 + test_gr_a5a5 r4 + test_gr_a5a5 r5 + test_gr_a5a5 r6 + test_gr_a5a5 r7 + test_gr_a5a5 r8 + test_gr_a5a5 r9 + test_gr_a5a5 r10 + test_gr_a5a5 r11 + test_gr_a5a5 r12 + test_gr_a5a5 r13 + test_gr_a5a5 r14 + +clips_w: + set_grs_a5a5 + clips.w r1 + test_gr0_a5a5 + assertreg 0xffff8000 r1 + test_gr_a5a5 r2 + test_gr_a5a5 r3 + test_gr_a5a5 r4 + test_gr_a5a5 r5 + test_gr_a5a5 r6 + test_gr_a5a5 r7 + test_gr_a5a5 r8 + test_gr_a5a5 r9 + test_gr_a5a5 r10 + test_gr_a5a5 r11 + test_gr_a5a5 r12 + test_gr_a5a5 r13 + test_gr_a5a5 r14 + +clipu_w: + set_grs_a5a5 + clipu.w r1 + test_gr0_a5a5 + assertreg 0xffff r1 + test_gr_a5a5 r2 + test_gr_a5a5 r3 + test_gr_a5a5 r4 + test_gr_a5a5 r5 + test_gr_a5a5 r6 + test_gr_a5a5 r7 + test_gr_a5a5 r8 + test_gr_a5a5 r9 + test_gr_a5a5 r10 + test_gr_a5a5 r11 + test_gr_a5a5 r12 + test_gr_a5a5 r13 + test_gr_a5a5 r14 + + pass + + exit 0 + diff --git a/sim/testsuite/sim/sh/div.s b/sim/testsuite/sim/sh/div.s new file mode 100644 index 00000000000..8293c2117f1 --- /dev/null +++ b/sim/testsuite/sim/sh/div.s @@ -0,0 +1,199 @@ +# sh testcase for divs and divu +# mach: all +# as(sh): -defsym sim_cpu=0 +# as(shdsp): -defsym sim_cpu=1 -dsp + + .include "testutils.inc" + + start + +divs_1: ! divide by one + set_grs_a5a5 + mov #1, r0 + divs r0, r1 + assertreg0 1 + test_gr_a5a5 r1 + test_gr_a5a5 r2 + test_gr_a5a5 r3 + test_gr_a5a5 r4 + test_gr_a5a5 r5 + test_gr_a5a5 r6 + test_gr_a5a5 r7 + test_gr_a5a5 r8 + test_gr_a5a5 r9 + test_gr_a5a5 r10 + test_gr_a5a5 r11 + test_gr_a5a5 r12 + test_gr_a5a5 r13 + test_gr_a5a5 r14 + +divs_2: ! divide by two + set_grs_a5a5 + mov #2, r0 + divs r0, r1 + assertreg0 2 + assertreg 0xd2d2d2d3, r1 + test_gr_a5a5 r2 + test_gr_a5a5 r3 + test_gr_a5a5 r4 + test_gr_a5a5 r5 + test_gr_a5a5 r6 + test_gr_a5a5 r7 + test_gr_a5a5 r8 + test_gr_a5a5 r9 + test_gr_a5a5 r10 + test_gr_a5a5 r11 + test_gr_a5a5 r12 + test_gr_a5a5 r13 + test_gr_a5a5 r14 + +divs_3: ! divide by three + set_grs_a5a5 + mov #3, r0 + divs r0, r1 + assertreg0 3 + assertreg 0xe1e1e1e2, r1 + test_gr_a5a5 r2 + test_gr_a5a5 r3 + test_gr_a5a5 r4 + test_gr_a5a5 r5 + test_gr_a5a5 r6 + test_gr_a5a5 r7 + test_gr_a5a5 r8 + test_gr_a5a5 r9 + test_gr_a5a5 r10 + test_gr_a5a5 r11 + test_gr_a5a5 r12 + test_gr_a5a5 r13 + test_gr_a5a5 r14 + +divs_0: ! divide by zero + set_grs_a5a5 + mov #0, r0 + divs r0, r1 + assertreg0 0 + assertreg 0x7fffffff, r1 + test_gr_a5a5 r2 + test_gr_a5a5 r3 + test_gr_a5a5 r4 + test_gr_a5a5 r5 + test_gr_a5a5 r6 + test_gr_a5a5 r7 + test_gr_a5a5 r8 + test_gr_a5a5 r9 + test_gr_a5a5 r10 + test_gr_a5a5 r11 + test_gr_a5a5 r12 + test_gr_a5a5 r13 + test_gr_a5a5 r14 + +divs_o: ! divide signed overflow + set_grs_a5a5 + mov #16, r0 + movi20 #0x8000, r1 + shad r0, r1 ! r1 == 0x80000000 + mov #-1, r0 + divs r0, r1 + assertreg0 -1 + assertreg 0x7fffffff, r1 + test_gr_a5a5 r2 + test_gr_a5a5 r3 + test_gr_a5a5 r4 + test_gr_a5a5 r5 + test_gr_a5a5 r6 + test_gr_a5a5 r7 + test_gr_a5a5 r8 + test_gr_a5a5 r9 + test_gr_a5a5 r10 + test_gr_a5a5 r11 + test_gr_a5a5 r12 + test_gr_a5a5 r13 + test_gr_a5a5 r14 + + +divu_1: ! divide by one, unsigned + set_grs_a5a5 + mov #1, r0 + divu r0, r1 + assertreg0 1 + test_gr_a5a5 r1 + test_gr_a5a5 r2 + test_gr_a5a5 r3 + test_gr_a5a5 r4 + test_gr_a5a5 r5 + test_gr_a5a5 r6 + test_gr_a5a5 r7 + test_gr_a5a5 r8 + test_gr_a5a5 r9 + test_gr_a5a5 r10 + test_gr_a5a5 r11 + test_gr_a5a5 r12 + test_gr_a5a5 r13 + test_gr_a5a5 r14 + +divu_2: ! divide by two, unsigned + set_grs_a5a5 + mov #2, r0 + divu r0, r1 + assertreg0 2 + assertreg 0x52d2d2d2, r1 + test_gr_a5a5 r2 + test_gr_a5a5 r3 + test_gr_a5a5 r4 + test_gr_a5a5 r5 + test_gr_a5a5 r6 + test_gr_a5a5 r7 + test_gr_a5a5 r8 + test_gr_a5a5 r9 + test_gr_a5a5 r10 + test_gr_a5a5 r11 + test_gr_a5a5 r12 + test_gr_a5a5 r13 + test_gr_a5a5 r14 + +divu_3: ! divide by three, unsigned + set_grs_a5a5 + mov #3, r0 + divu r0, r1 + assertreg0 3 + assertreg 0x37373737, r1 + test_gr_a5a5 r2 + test_gr_a5a5 r3 + test_gr_a5a5 r4 + test_gr_a5a5 r5 + test_gr_a5a5 r6 + test_gr_a5a5 r7 + test_gr_a5a5 r8 + test_gr_a5a5 r9 + test_gr_a5a5 r10 + test_gr_a5a5 r11 + test_gr_a5a5 r12 + test_gr_a5a5 r13 + test_gr_a5a5 r14 + +divu_0: ! divide by zero, unsigned + set_grs_a5a5 + mov #0, r0 + divu r0, r1 + assertreg0 0 + assertreg 0xffffffff, r1 + test_gr_a5a5 r2 + test_gr_a5a5 r3 + test_gr_a5a5 r4 + test_gr_a5a5 r5 + test_gr_a5a5 r6 + test_gr_a5a5 r7 + test_gr_a5a5 r8 + test_gr_a5a5 r9 + test_gr_a5a5 r10 + test_gr_a5a5 r11 + test_gr_a5a5 r12 + test_gr_a5a5 r13 + test_gr_a5a5 r14 + + + pass + + exit 0 + + \ No newline at end of file diff --git a/sim/testsuite/sim/sh/fail.s b/sim/testsuite/sim/sh/fail.s new file mode 100644 index 00000000000..0ffb0b2a6ff --- /dev/null +++ b/sim/testsuite/sim/sh/fail.s @@ -0,0 +1,13 @@ +# sh testcase, fail +# mach: all +# as(sh): -defsym sim_cpu=0 +# as(shdsp): -defsym sim_cpu=1 -dsp + + .include "testutils.inc" + + start + + fail + + exit 0 + diff --git a/sim/testsuite/sim/sh/fsca.s b/sim/testsuite/sim/sh/fsca.s new file mode 100644 index 00000000000..90df6c97680 --- /dev/null +++ b/sim/testsuite/sim/sh/fsca.s @@ -0,0 +1,97 @@ +# sh testcase for fsca +# mach: sh +# as(sh): -defsym sim_cpu=0 + + .include "testutils.inc" + + start +fsca: + set_grs_a5a5 + set_fprs_a5a5 + # Start with angle zero + mov.l zero, r0 + lds r0, fpul + fsca fpul, dr2 + assert_fpreg_i 0, fr2 + assert_fpreg_i 1, fr3 + + mov.l plus_90, r0 + lds r0, fpul + fsca fpul, dr2 + assert_fpreg_i 1, fr2 + assert_fpreg_i 0, fr3 + + mov.l plus_180, r0 + lds r0, fpul + fsca fpul, dr2 + assert_fpreg_i 0, fr2 + assert_fpreg_i -1, fr3 + + mov.l plus_270, r0 + lds r0, fpul + fsca fpul, dr2 + assert_fpreg_i -1, fr2 + assert_fpreg_i 0, fr3 + + mov.l plus_360, r0 + lds r0, fpul + fsca fpul, dr2 + assert_fpreg_i 0, fr2 + assert_fpreg_i 1, fr3 + + mov.l minus_90, r0 + lds r0, fpul + fsca fpul, dr2 + assert_fpreg_i -1, fr2 + assert_fpreg_i 0, fr3 + + mov.l minus_180, r0 + lds r0, fpul + fsca fpul, dr2 + assert_fpreg_i 0, fr2 + assert_fpreg_i -1, fr3 + + mov.l minus_270, r0 + lds r0, fpul + fsca fpul, dr2 + assert_fpreg_i 1, fr2 + assert_fpreg_i 0, fr3 + + mov.l minus_360, r0 + lds r0, fpul + fsca fpul, dr2 + assert_fpreg_i 0, fr2 + assert_fpreg_i 1, fr3 + + assertreg0 0xffff0000 + set_greg 0xa5a5a5a5, r0 + test_grs_a5a5 + test_fpr_a5a5 fr0 + test_fpr_a5a5 fr1 + test_fpr_a5a5 fr4 + test_fpr_a5a5 fr5 + test_fpr_a5a5 fr6 + test_fpr_a5a5 fr7 + test_fpr_a5a5 fr8 + test_fpr_a5a5 fr9 + test_fpr_a5a5 fr10 + test_fpr_a5a5 fr11 + test_fpr_a5a5 fr12 + test_fpr_a5a5 fr13 + test_fpr_a5a5 fr14 + test_fpr_a5a5 fr15 + pass + exit 0 + + .align 2 +zero: .long 0 +one_bitty: .long 1 +plus_90: .long 0x04000 +plus_180: .long 0x08000 +plus_270: .long 0x0c000 +plus_360: .long 0x10000 +minus_90: .long 0xffffc000 +minus_180: .long 0xffff8000 +minus_270: .long 0xffff4000 +minus_360: .long 0xffff0000 +minus_1_bitty: .long 0xffffffff diff --git a/sim/testsuite/sim/sh/fsrra.s b/sim/testsuite/sim/sh/fsrra.s new file mode 100644 index 00000000000..fdd22356d66 --- /dev/null +++ b/sim/testsuite/sim/sh/fsrra.s @@ -0,0 +1,62 @@ +# sh testcase for fsrra +# mach: sh +# as(sh): -defsym sim_cpu=0 + + .include "testutils.inc" + + start +fsrra_single: + set_grs_a5a5 + set_fprs_a5a5 + # 1/sqrt(0.0) = +infinity. + fldi0 fr0 + fsrra fr0 + assert_fpreg_x 0x7f800000, fr0 + + # 1/sqrt(1.0) = 1.0. + fldi1 fr0 + fsrra fr0 + assert_fpreg_i 1, fr0 + + # 1/sqrt(4.0) = 1/2.0 + fldi1 fr0 + # Double it. + fadd fr0, fr0 + # Double it again. + fadd fr0, fr0 + fsrra fr0 + fldi1 fr2 + # Double it. + fadd fr2, fr2 + fldi1 fr1 + # Divide + fdiv fr2, fr1 + fcmp/eq fr0, fr1 + bt .L2 + fail +.L2: + # Double-check (pun intended) + fadd fr0, fr0 + assert_fpreg_i 1, fr0 + fadd fr1, fr1 + assert_fpreg_i 1, fr1 + + # And make sure the rest of the regs are un-affected. + assert_fpreg_i 2, fr2 + test_fpr_a5a5 fr3 + test_fpr_a5a5 fr4 + test_fpr_a5a5 fr5 + test_fpr_a5a5 fr6 + test_fpr_a5a5 fr7 + test_fpr_a5a5 fr8 + test_fpr_a5a5 fr9 + test_fpr_a5a5 fr10 + test_fpr_a5a5 fr11 + test_fpr_a5a5 fr12 + test_fpr_a5a5 fr13 + test_fpr_a5a5 fr14 + test_fpr_a5a5 fr15 + test_grs_a5a5 + + pass + exit 0 diff --git a/sim/testsuite/sim/sh/mov.s b/sim/testsuite/sim/sh/mov.s new file mode 100644 index 00000000000..37fef514401 --- /dev/null +++ b/sim/testsuite/sim/sh/mov.s @@ -0,0 +1,118 @@ +# sh testcase for all mov.[bwl] instructions +# mach: sh +# as(sh): -defsym sim_cpu=0 + + .include "testutils.inc" + + .align 2 +_lsrc: .long 0x55555555 +_wsrc: .long 0x55550000 +_bsrc: .long 0x55000000 + + .align 2 +_ldst: .long 0 +_wdst: .long 0 +_bdst: .long 0 + + + start + +movb_disp12_reg: # Test 8-bit @(disp12,gr) -> gr + set_grs_a5a5 + mov.l bsrc, r1 + add #-111, r1 + add #-111, r1 + add #-111, r1 + add #-111, r1 + mov.b @(444,r1), r2 + + assertreg _bsrc-444, r1 + assertreg 0x55, r2 + +movb_reg_disp12: # Test 8-bit gr -> @(disp12,gr) + set_grs_a5a5 + mov.l bdst, r1 + add #-111, r1 + add #-111, r1 + add #-111, r1 + add #-111, r1 + mov.b r2, @(444,r1) + + assertreg _bdst-444, r1 + assertmem _bdst, 0xa5000000 + +movw_disp12_reg: # Test 16-bit @(disp12,gr) -> gr + set_grs_a5a5 + mov.l wsrc, r1 + add #-111, r1 + add #-111, r1 + add #-111, r1 + add #-111, r1 + mov.w @(444,r1), r2 + + assertreg _wsrc-444, r1 + assertreg 0x5555, r2 + +movw_reg_disp12: # Test 16-bit gr -> @(disp12,gr) + set_grs_a5a5 + mov.l wdst, r1 + add #-111, r1 + add #-111, r1 + add #-111, r1 + add #-111, r1 + mov.w r2, @(444,r1) + + assertreg _wdst-444, r1 + assertmem _wdst, 0xa5a50000 + +movl_disp12_reg: # Test 32-bit @(disp12,gr) -> gr + set_grs_a5a5 + mov.l lsrc, r1 + add #-111, r1 + add #-111, r1 + add #-111, r1 + add #-111, r1 + mov.l @(444,r1), r2 + + assertreg _lsrc-444, r1 + assertreg 0x55555555, r2 + +movl_reg_disp12: # Test 32-bit gr -> @(disp12,gr) + set_grs_a5a5 + mov.l ldst, r1 + add #-111, r1 + add #-111, r1 + add #-111, r1 + add #-111, r1 + mov.l r2, @(444,r1) + + assertreg _ldst-444, r1 + assertmem _ldst, 0xa5a5a5a5 + + test_gr_a5a5 r0 + test_gr_a5a5 r2 + test_gr_a5a5 r3 + test_gr_a5a5 r4 + test_gr_a5a5 r5 + test_gr_a5a5 r6 + test_gr_a5a5 r7 + test_gr_a5a5 r8 + test_gr_a5a5 r9 + test_gr_a5a5 r10 + test_gr_a5a5 r11 + test_gr_a5a5 r12 + test_gr_a5a5 r13 + test_gr_a5a5 r14 + + pass + + exit 0 + +lsrc: .long _lsrc +wsrc: .long _wsrc +bsrc: .long _bsrc + +ldst: .long _ldst +wdst: .long _wdst +bdst: .long _bdst + diff --git a/sim/testsuite/sim/sh/mulr.s b/sim/testsuite/sim/sh/mulr.s new file mode 100644 index 00000000000..1e755ab2de7 --- /dev/null +++ b/sim/testsuite/sim/sh/mulr.s @@ -0,0 +1,162 @@ +# sh testcase for mulr +# mach: all +# as(sh): -defsym sim_cpu=0 +# as(shdsp): -defsym sim_cpu=1 -dsp + + .include "testutils.inc" + + start + +mulr_1: ! multiply by one + set_grs_a5a5 + mov #1, r0 + mulr r0, r1 + assertreg0 1 + test_gr_a5a5 r1 + test_gr_a5a5 r2 + test_gr_a5a5 r3 + test_gr_a5a5 r4 + test_gr_a5a5 r5 + test_gr_a5a5 r6 + test_gr_a5a5 r7 + test_gr_a5a5 r8 + test_gr_a5a5 r9 + test_gr_a5a5 r10 + test_gr_a5a5 r11 + test_gr_a5a5 r12 + test_gr_a5a5 r13 + test_gr_a5a5 r14 + +mulr_2: ! multiply by two + set_grs_a5a5 + mov #2, r0 + mov #12, r1 + mulr r0, r1 + assertreg0 2 + assertreg 24, r1 + test_gr_a5a5 r2 + test_gr_a5a5 r3 + test_gr_a5a5 r4 + test_gr_a5a5 r5 + test_gr_a5a5 r6 + test_gr_a5a5 r7 + test_gr_a5a5 r8 + test_gr_a5a5 r9 + test_gr_a5a5 r10 + test_gr_a5a5 r11 + test_gr_a5a5 r12 + test_gr_a5a5 r13 + test_gr_a5a5 r14 + +mulr_3: ! multiply five by five + set_grs_a5a5 + mov #5, r0 + mov #5, r1 + mulr r0, r1 + assertreg0 5 + assertreg 25, r1 + test_gr_a5a5 r2 + test_gr_a5a5 r3 + test_gr_a5a5 r4 + test_gr_a5a5 r5 + test_gr_a5a5 r6 + test_gr_a5a5 r7 + test_gr_a5a5 r8 + test_gr_a5a5 r9 + test_gr_a5a5 r10 + test_gr_a5a5 r11 + test_gr_a5a5 r12 + test_gr_a5a5 r13 + test_gr_a5a5 r14 + + +mulr_4: ! multiply 127 by 127 + set_grs_a5a5 + mov #127, r0 + mov #127, r1 + mulr r0, r1 + assertreg0 127 + assertreg 0x3f01, r1 + test_gr_a5a5 r2 + test_gr_a5a5 r3 + test_gr_a5a5 r4 + test_gr_a5a5 r5 + test_gr_a5a5 r6 + test_gr_a5a5 r7 + test_gr_a5a5 r8 + test_gr_a5a5 r9 + test_gr_a5a5 r10 + test_gr_a5a5 r11 + test_gr_a5a5 r12 + test_gr_a5a5 r13 + test_gr_a5a5 r14 + +mulr_5: ! multiply -1 by -1 + set_grs_a5a5 + mov #-1, r0 + mov #-1, r1 + mulr r0, r1 + assertreg0 -1 + assertreg 1, r1 + test_gr_a5a5 r2 + test_gr_a5a5 r3 + test_gr_a5a5 r4 + test_gr_a5a5 r5 + test_gr_a5a5 r6 + test_gr_a5a5 r7 + test_gr_a5a5 r8 + test_gr_a5a5 r9 + test_gr_a5a5 r10 + test_gr_a5a5 r11 + test_gr_a5a5 r12 + test_gr_a5a5 r13 + test_gr_a5a5 r14 + +mulr_6: ! multiply 46340 by 46340 + set_grs_a5a5 + movi20 #46340, r0 + movi20 #46340, r1 + mulr r0, r1 + assertreg0 46340 + assertreg 0x7ffea810, r1 + test_gr_a5a5 r2 + test_gr_a5a5 r3 + test_gr_a5a5 r4 + test_gr_a5a5 r5 + test_gr_a5a5 r6 + test_gr_a5a5 r7 + test_gr_a5a5 r8 + test_gr_a5a5 r9 + test_gr_a5a5 r10 + test_gr_a5a5 r11 + test_gr_a5a5 r12 + test_gr_a5a5 r13 + test_gr_a5a5 r14 + +mulr_7: ! multiply 7ffff by 7ffff (overflow) + set_grs_a5a5 + movi20 #0x7ffff, r0 + movi20 #0x7ffff, r1 + mulr r0, r1 + assertreg0 0x7ffff + assertreg 0xfff00001, r1 + test_gr_a5a5 r2 + test_gr_a5a5 r3 + test_gr_a5a5 r4 + test_gr_a5a5 r5 + test_gr_a5a5 r6 + test_gr_a5a5 r7 + test_gr_a5a5 r8 + test_gr_a5a5 r9 + test_gr_a5a5 r10 + test_gr_a5a5 r11 + test_gr_a5a5 r12 + test_gr_a5a5 r13 + test_gr_a5a5 r14 + + + pass + + exit 0 + + \ No newline at end of file diff --git a/sim/testsuite/sim/sh/pass.s b/sim/testsuite/sim/sh/pass.s new file mode 100644 index 00000000000..cc3bbccd740 --- /dev/null +++ b/sim/testsuite/sim/sh/pass.s @@ -0,0 +1,14 @@ +# sh testcase, pass +# mach: all +# as(sh): -defsym sim_cpu=0 +# as(shdsp): -defsym sim_cpu=1 -dsp + + .include "testutils.inc" + + start + set_grs_a5a5 + test_grs_a5a5 + pass + + exit 0 + diff --git a/sim/testsuite/sim/sh/pushpop.s b/sim/testsuite/sim/sh/pushpop.s new file mode 100644 index 00000000000..9ee5bfd6888 --- /dev/null +++ b/sim/testsuite/sim/sh/pushpop.s @@ -0,0 +1,146 @@ +# sh testcase for push/pop (mov,movml,movmu...) insns. +# mach: all +# as(sh): -defsym sim_cpu=0 +# as(shdsp): -defsym sim_cpu=1 -dsp + + .include "testutils.inc" + + start +movml_1: + set_greg 0, r0 + set_greg 1, r1 + set_greg 2, r2 + set_greg 3, r3 + set_greg 4, r4 + set_greg 5, r5 + set_greg 6, r6 + set_greg 7, r7 + set_greg 8, r8 + set_greg 9, r9 + set_greg 10, r10 + set_greg 11, r11 + set_greg 12, r12 + set_greg 13, r13 + set_greg 14, r14 + set_sreg 15, pr + + movml.l r15,@-r15 + + assertmem stackt-4, 15 + assertmem stackt-8, 14 + assertmem stackt-12, 13 + assertmem stackt-16, 12 + assertmem stackt-20, 11 + assertmem stackt-24, 10 + assertmem stackt-28, 9 + assertmem stackt-32, 8 + assertmem stackt-36, 7 + assertmem stackt-40, 6 + assertmem stackt-44, 5 + assertmem stackt-48, 4 + assertmem stackt-52, 3 + assertmem stackt-56, 2 + assertmem stackt-60, 1 + assertmem stackt-64, 0 + + assertreg0 0 + assertreg 1, r1 + assertreg 2, r2 + assertreg 3, r3 + assertreg 4, r4 + assertreg 5, r5 + assertreg 6, r6 + assertreg 7, r7 + assertreg 8, r8 + assertreg 9, r9 + assertreg 10, r10 + assertreg 11, r11 + assertreg 12, r12 + assertreg 13, r13 + assertreg 14, r14 + mov r15, r0 + assertreg0 stackt-64 + +movml_2: + set_grs_a5a5 + movml.l @r15+, r15 + assert_sreg 15, pr + assertreg0 0 + assertreg 1, r1 + assertreg 2, r2 + assertreg 3, r3 + assertreg 4, r4 + assertreg 5, r5 + assertreg 6, r6 + assertreg 7, r7 + assertreg 8, r8 + assertreg 9, r9 + assertreg 10, r10 + assertreg 11, r11 + assertreg 12, r12 + assertreg 13, r13 + assertreg 14, r14 + mov r15, r0 + assertreg0 stackt + +movmu_1: + set_grs_a5a5 + add #1,r14 + add #2,r13 + add #3,r12 + set_sreg 0xa5a5,pr + + movmu.l r12,@-r15 + + assert_sreg 0xa5a5,pr + assertreg 0xa5a5a5a6, r14 + assertreg 0xa5a5a5a7, r13 + assertreg 0xa5a5a5a8, r12 + test_gr_a5a5 r11 + test_gr_a5a5 r10 + test_gr_a5a5 r9 + test_gr_a5a5 r8 + test_gr_a5a5 r7 + test_gr_a5a5 r6 + test_gr_a5a5 r5 + test_gr_a5a5 r4 + test_gr_a5a5 r3 + test_gr_a5a5 r2 + test_gr_a5a5 r1 + test_gr_a5a5 r0 + mov r15, r0 + assertreg stackt-16, r0 + + assertmem stackt-4, 0xa5a5 + assertmem stackt-8, 0xa5a5a5a6 + assertmem stackt-12, 0xa5a5a5a7 + assertmem stackt-16, 0xa5a5a5a8 + +movmu_2: + set_grs_a5a5 + movmu.l @r15+,r12 + + assert_sreg 0xa5a5, pr + assertreg 0xa5a5a5a6, r14 + assertreg 0xa5a5a5a7, r13 + assertreg 0xa5a5a5a8, r12 + test_gr_a5a5 r11 + test_gr_a5a5 r10 + test_gr_a5a5 r9 + test_gr_a5a5 r8 + test_gr_a5a5 r7 + test_gr_a5a5 r6 + test_gr_a5a5 r5 + test_gr_a5a5 r4 + test_gr_a5a5 r3 + test_gr_a5a5 r2 + test_gr_a5a5 r1 + test_gr_a5a5 r0 + mov r15, r0 + assertreg stackt, r0 + + pass + + exit 0 + + \ No newline at end of file diff --git a/sim/testsuite/sim/sh/resbank.s b/sim/testsuite/sim/sh/resbank.s new file mode 100644 index 00000000000..33801b86586 --- /dev/null +++ b/sim/testsuite/sim/sh/resbank.s @@ -0,0 +1,268 @@ +# sh testcase for ldbank stbank resbank +# mach: all +# as(sh): -defsym sim_cpu=0 +# as(shdsp): -defsym sim_cpu=1 -dsp + + .include "testutils.inc" + + .macro SEND reg bankno regno + set_greg ((\bankno << 7) + (\regno << 2)), \reg + .endm + + start + +stbank_1: + set_grs_a5a5 + mov #0, r0 + SEND r1, 0, 0 + stbank r0, @r1 + mov #1, r0 + SEND r1, 0, 1 + stbank r0, @r1 + mov #2, r0 + SEND r1, 0, 2 + stbank r0, @r1 + mov #3, r0 + SEND r1, 0, 3 + stbank r0, @r1 + mov #4, r0 + SEND r1, 0, 4 + stbank r0, @r1 + mov #5, r0 + SEND r1, 0, 5 + stbank r0, @r1 + mov #6, r0 + SEND r1, 0, 6 + stbank r0, @r1 + mov #7, r0 + SEND r1, 0, 7 + stbank r0, @r1 + mov #8, r0 + SEND r1, 0, 8 + stbank r0, @r1 + mov #9, r0 + SEND r1, 0, 9 + stbank r0, @r1 + mov #10, r0 + SEND r1, 0, 10 + stbank r0, @r1 + mov #11, r0 + SEND r1, 0, 11 + stbank r0, @r1 + mov #12, r0 + SEND r1, 0, 12 + stbank r0, @r1 + mov #13, r0 + SEND r1, 0, 13 + stbank r0, @r1 + mov #14, r0 + SEND r1, 0, 14 + stbank r0, @r1 + mov #15, r0 + SEND r1, 0, 15 + stbank r0, @r1 + mov #16, r0 + SEND r1, 0, 16 + stbank r0, @r1 + mov #17, r0 + SEND r1, 0, 17 + stbank r0, @r1 + mov #18, r0 + SEND r1, 0, 18 + stbank r0, @r1 + mov #19, r0 + SEND r1, 0, 19 + stbank r0, @r1 + + assertreg0 19 + assertreg 19 << 2, r1 + test_gr_a5a5 r2 + test_gr_a5a5 r3 + test_gr_a5a5 r4 + test_gr_a5a5 r5 + test_gr_a5a5 r6 + test_gr_a5a5 r7 + test_gr_a5a5 r8 + test_gr_a5a5 r9 + test_gr_a5a5 r10 + test_gr_a5a5 r11 + test_gr_a5a5 r12 + test_gr_a5a5 r13 + test_gr_a5a5 r14 + +ldbank_1: + set_grs_a5a5 + SEND r1, 0, 0 + ldbank @r1, r0 + assertreg0 0 + SEND r1, 0, 1 + ldbank @r1, r0 + assertreg0 1 + SEND r1, 0, 2 + ldbank @r1, r0 + assertreg0 2 + SEND r1, 0, 3 + ldbank @r1, r0 + assertreg0 3 + SEND r1, 0, 4 + ldbank @r1, r0 + assertreg0 4 + SEND r1, 0, 5 + ldbank @r1, r0 + assertreg0 5 + SEND r1, 0, 6 + ldbank @r1, r0 + assertreg0 6 + SEND r1, 0, 7 + ldbank @r1, r0 + assertreg0 7 + SEND r1, 0, 8 + ldbank @r1, r0 + assertreg0 8 + SEND r1, 0, 9 + ldbank @r1, r0 + assertreg0 9 + SEND r1, 0, 10 + ldbank @r1, r0 + assertreg0 10 + SEND r1, 0, 11 + ldbank @r1, r0 + assertreg0 11 + SEND r1, 0, 12 + ldbank @r1, r0 + assertreg0 12 + SEND r1, 0, 13 + ldbank @r1, r0 + assertreg0 13 + SEND r1, 0, 14 + ldbank @r1, r0 + assertreg0 14 + SEND r1, 0, 15 + ldbank @r1, r0 + assertreg0 15 + SEND r1, 0, 16 + ldbank @r1, r0 + assertreg0 16 + SEND r1, 0, 17 + ldbank @r1, r0 + assertreg0 17 + SEND r1, 0, 18 + ldbank @r1, r0 + assertreg0 18 + SEND r1, 0, 19 + ldbank @r1, r0 + assertreg0 19 + + assertreg (19 << 2), r1 + test_gr_a5a5 r2 + test_gr_a5a5 r3 + test_gr_a5a5 r4 + test_gr_a5a5 r5 + test_gr_a5a5 r6 + test_gr_a5a5 r7 + test_gr_a5a5 r8 + test_gr_a5a5 r9 + test_gr_a5a5 r10 + test_gr_a5a5 r11 + test_gr_a5a5 r12 + test_gr_a5a5 r13 + test_gr_a5a5 r14 + +resbank_1: + set_grs_a5a5 + mov #1, r0 + trapa #13 ! magic trap, sets ibnr + + resbank + + assertreg0 0 + assertreg 1, r1 + assertreg 2, r2 + assertreg 3, r3 + assertreg 4, r4 + assertreg 5, r5 + assertreg 6, r6 + assertreg 7, r7 + assertreg 8, r8 + assertreg 9, r9 + assertreg 10, r10 + assertreg 11, r11 + assertreg 12, r12 + assertreg 13, r13 + assertreg 14, r14 + assert_sreg 15, mach + assert_sreg 17, pr + assert_creg 18, gbr + assert_sreg 19, macl + +resbank_2: + set_grs_a5a5 + movi20 #555, r0 + mov.l r0, @-r15 + add #-1, r0 + mov.l r0, @-r15 + add #-1, r0 + mov.l r0, @-r15 + add #-1, r0 + mov.l r0, @-r15 + add #-1, r0 + mov.l r0, @-r15 + add #-1, r0 + mov.l r0, @-r15 + add #-1, r0 + mov.l r0, @-r15 + add #-1, r0 + mov.l r0, @-r15 + add #-1, r0 + mov.l r0, @-r15 + add #-1, r0 + mov.l r0, @-r15 + add #-1, r0 + mov.l r0, @-r15 + add #-1, r0 + mov.l r0, @-r15 + add #-1, r0 + mov.l r0, @-r15 + add #-1, r0 + mov.l r0, @-r15 + add #-1, r0 + mov.l r0, @-r15 + add #-1, r0 + mov.l r0, @-r15 + add #-1, r0 + mov.l r0, @-r15 + add #-1, r0 + mov.l r0, @-r15 + add #-1, r0 + mov.l r0, @-r15 + + set_sr_bit (1 << 14) ! set BO + + resbank + + assert_sreg 555, macl + assert_sreg 554, mach + assert_creg 553, gbr + assert_sreg 552, pr + assertreg 551, r14 + assertreg 550, r13 + assertreg 549, r12 + assertreg 548, r11 + assertreg 547, r10 + assertreg 546, r9 + assertreg 545, r8 + assertreg 544, r7 + assertreg 543, r6 + assertreg 542, r5 + assertreg 541, r4 + assertreg 540, r3 + assertreg 539, r2 + assertreg 538, r1 + assertreg0 537 + + mov r15, r0 + assertreg0 stackt + + pass + + exit 0 -- 2.47.2