summaryrefslogtreecommitdiff
path: root/arch/alpha
diff options
context:
space:
mode:
Diffstat (limited to 'arch/alpha')
-rw-r--r--arch/alpha/SConscript91
-rw-r--r--arch/alpha/alpha_tru64_process.cc1936
-rw-r--r--arch/alpha/arguments.cc10
-rw-r--r--arch/alpha/ev5.cc249
-rw-r--r--arch/alpha/ev5.hh4
-rw-r--r--arch/alpha/faults.cc122
-rw-r--r--arch/alpha/faults.hh266
-rw-r--r--arch/alpha/freebsd/system.cc167
-rw-r--r--arch/alpha/freebsd/system.hh (renamed from arch/alpha/pseudo_inst.hh)50
-rw-r--r--arch/alpha/isa/branch.isa259
-rw-r--r--arch/alpha/isa/decoder.isa819
-rw-r--r--arch/alpha/isa/fp.isa301
-rw-r--r--arch/alpha/isa/int.isa128
-rw-r--r--arch/alpha/isa/main.isa448
-rw-r--r--arch/alpha/isa/mem.isa702
-rw-r--r--arch/alpha/isa/opcdec.isa72
-rw-r--r--arch/alpha/isa/pal.isa271
-rw-r--r--arch/alpha/isa/unimp.isa165
-rw-r--r--arch/alpha/isa/unknown.isa52
-rw-r--r--arch/alpha/isa/util.isa112
-rw-r--r--arch/alpha/isa_desc2737
-rw-r--r--arch/alpha/isa_traits.hh336
-rw-r--r--arch/alpha/linux/aligned.hh47
-rw-r--r--arch/alpha/linux/hwrpb.hh42
-rw-r--r--arch/alpha/linux/process.cc (renamed from arch/alpha/alpha_linux_process.cc)546
-rw-r--r--arch/alpha/linux/process.hh (renamed from arch/alpha/alpha_linux_process.hh)11
-rw-r--r--arch/alpha/linux/system.cc289
-rw-r--r--arch/alpha/linux/system.hh146
-rw-r--r--arch/alpha/linux/thread_info.hh41
-rw-r--r--arch/alpha/linux/threadinfo.hh (renamed from arch/alpha/vptr.hh)99
-rw-r--r--arch/alpha/process.cc61
-rw-r--r--arch/alpha/process.hh48
-rw-r--r--arch/alpha/pseudo_inst.cc256
-rw-r--r--arch/alpha/stacktrace.cc47
-rw-r--r--arch/alpha/stacktrace.hh8
-rw-r--r--arch/alpha/system.cc299
-rw-r--r--arch/alpha/system.hh109
-rw-r--r--arch/alpha/tlb.cc (renamed from arch/alpha/alpha_memory.cc)88
-rw-r--r--arch/alpha/tlb.hh (renamed from arch/alpha/alpha_memory.hh)1
-rw-r--r--arch/alpha/tru64/process.cc543
-rw-r--r--arch/alpha/tru64/process.hh (renamed from arch/alpha/alpha_tru64_process.hh)12
-rw-r--r--arch/alpha/tru64/system.cc159
-rw-r--r--arch/alpha/tru64/system.hh71
-rw-r--r--arch/alpha/vtophys.cc30
44 files changed, 6319 insertions, 5931 deletions
diff --git a/arch/alpha/SConscript b/arch/alpha/SConscript
new file mode 100644
index 000000000..ed7fd3404
--- /dev/null
+++ b/arch/alpha/SConscript
@@ -0,0 +1,91 @@
+# -*- mode:python -*-
+
+# Copyright (c) 2004-2005 The Regents of The University of Michigan
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met: redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer;
+# redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution;
+# neither the name of the copyright holders nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+import os
+import sys
+from os.path import isdir
+
+# This file defines how to build a particular configuration of M5
+# based on variable settings in the 'env' build environment.
+
+# Import build environment variable from SConstruct.
+Import('env')
+
+###################################################
+#
+# Define needed sources.
+#
+###################################################
+
+# Base sources used by all configurations.
+base_sources = Split('''
+ faults.cc
+ isa_traits.cc
+ ''')
+
+# Full-system sources
+full_system_sources = Split('''
+ tlb.cc
+ arguments.cc
+ ev5.cc
+ osfpal.cc
+ stacktrace.cc
+ vtophys.cc
+ system.cc
+ freebsd/system.cc
+ linux/system.cc
+ tru64/system.cc
+ ''')
+
+
+# Syscall emulation (non-full-system) sources
+syscall_emulation_sources = Split('''
+ linux/process.cc
+ tru64/process.cc
+ process.cc
+ ''')
+
+# Set up complete list of sources based on configuration.
+sources = base_sources
+
+if env['FULL_SYSTEM']:
+ sources += full_system_sources
+else:
+ sources += syscall_emulation_sources
+
+# Convert file names to SCons File objects. This takes care of the
+# path relative to the top of the directory tree.
+sources = [File(s) for s in sources]
+
+# Add in files generated by the ISA description.
+isa_desc_files = env.ISADesc('isa/main.isa')
+# Only non-header files need to be compiled.
+isa_desc_sources = [f for f in isa_desc_files if not f.path.endswith('.hh')]
+sources += isa_desc_sources
+
+Return('sources')
diff --git a/arch/alpha/alpha_tru64_process.cc b/arch/alpha/alpha_tru64_process.cc
deleted file mode 100644
index a9c7b5c74..000000000
--- a/arch/alpha/alpha_tru64_process.cc
+++ /dev/null
@@ -1,1936 +0,0 @@
-/*
- * Copyright (c) 2001-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#if defined(__OpenBSD__)
-#include <sys/param.h>
-#include <sys/mount.h>
-#else
-#include <sys/statfs.h>
-#endif
-
-#include <dirent.h>
-#include <errno.h>
-#include <fcntl.h> // for host open() flags
-#include <string.h> // for memset()
-#include <unistd.h>
-
-#include "arch/alpha/alpha_common_syscall_emul.hh"
-#include "arch/alpha/alpha_tru64_process.hh"
-#include "base/trace.hh"
-#include "cpu/base.hh"
-#include "cpu/exec_context.hh"
-#include "mem/translating_port.hh"
-#include "sim/fake_syscall.hh"
-#include "sim/host.hh"
-#include "sim/process.hh"
-#include "sim/root.hh"
-#include "sim/syscall_emul.hh"
-
-using namespace std;
-
-typedef struct stat global_stat;
-typedef struct statfs global_statfs;
-typedef struct dirent global_dirent;
-
-///
-/// This class encapsulates the types, structures, constants,
-/// functions, and syscall-number mappings specific to the Alpha Tru64
-/// syscall interface.
-///
-class Tru64 {
-
- public:
-
- //@{
- /// Basic Tru64 types.
- typedef uint64_t size_t;
- typedef uint64_t off_t;
- typedef uint16_t nlink_t;
- typedef int32_t dev_t;
- typedef uint32_t uid_t;
- typedef uint32_t gid_t;
- typedef uint32_t time_t;
- typedef uint32_t mode_t;
- typedef uint32_t ino_t;
- typedef struct { int val[2]; } quad;
- typedef quad fsid_t;
- //@}
-
- //@{
- /// open(2) flag values.
- static const int TGT_O_RDONLY = 00000000;
- static const int TGT_O_WRONLY = 00000001;
- static const int TGT_O_RDWR = 00000002;
- static const int TGT_O_NONBLOCK = 00000004;
- static const int TGT_O_APPEND = 00000010;
- static const int TGT_O_CREAT = 00001000;
- static const int TGT_O_TRUNC = 00002000;
- static const int TGT_O_EXCL = 00004000;
- static const int TGT_O_NOCTTY = 00010000;
- static const int TGT_O_SYNC = 00040000;
- static const int TGT_O_DRD = 00100000;
- static const int TGT_O_DIRECTIO = 00200000;
- static const int TGT_O_CACHE = 00400000;
- static const int TGT_O_DSYNC = 02000000;
- static const int TGT_O_RSYNC = 04000000;
- //@}
-
- /// This table maps the target open() flags to the corresponding
- /// host open() flags.
- static OpenFlagTransTable openFlagTable[];
-
- /// Number of entries in openFlagTable[].
- static const int NUM_OPEN_FLAGS;
-
- /// Stat buffer. Note that Tru64 v5.0+ use a new "F64" stat
- /// structure, and a new set of syscall numbers for stat calls.
- /// On some hosts (notably Linux) define st_atime, st_mtime, and
- /// st_ctime as macros, so we append an X to get around this.
- struct F64_stat {
- dev_t st_dev; //!< st_dev
- int32_t st_retired1; //!< st_retired1
- mode_t st_mode; //!< st_mode
- nlink_t st_nlink; //!< st_nlink
- uint16_t st_nlink_reserved; //!< st_nlink_reserved
- uid_t st_uid; //!< st_uid
- gid_t st_gid; //!< st_gid
- dev_t st_rdev; //!< st_rdev
- dev_t st_ldev; //!< st_ldev
- off_t st_size; //!< st_size
- time_t st_retired2; //!< st_retired2
- int32_t st_uatime; //!< st_uatime
- time_t st_retired3; //!< st_retired3
- int32_t st_umtime; //!< st_umtime
- time_t st_retired4; //!< st_retired4
- int32_t st_uctime; //!< st_uctime
- int32_t st_retired5; //!< st_retired5
- int32_t st_retired6; //!< st_retired6
- uint32_t st_flags; //!< st_flags
- uint32_t st_gen; //!< st_gen
- uint64_t st_spare[4]; //!< st_spare[4]
- ino_t st_ino; //!< st_ino
- int32_t st_ino_reserved; //!< st_ino_reserved
- time_t st_atimeX; //!< st_atime
- int32_t st_atime_reserved; //!< st_atime_reserved
- time_t st_mtimeX; //!< st_mtime
- int32_t st_mtime_reserved; //!< st_mtime_reserved
- time_t st_ctimeX; //!< st_ctime
- int32_t st_ctime_reserved; //!< st_ctime_reserved
- uint64_t st_blksize; //!< st_blksize
- uint64_t st_blocks; //!< st_blocks
- };
-
-
- /// Old Tru64 v4.x stat struct.
- /// Tru64 maintains backwards compatibility with v4.x by
- /// implementing another set of stat functions using the old
- /// structure definition and binding them to the old syscall
- /// numbers.
- struct pre_F64_stat {
- dev_t st_dev;
- ino_t st_ino;
- mode_t st_mode;
- nlink_t st_nlink;
- uid_t st_uid;
- gid_t st_gid;
- dev_t st_rdev;
- off_t st_size;
- time_t st_atimeX;
- int32_t st_uatime;
- time_t st_mtimeX;
- int32_t st_umtime;
- time_t st_ctimeX;
- int32_t st_uctime;
- uint32_t st_blksize;
- int32_t st_blocks;
- uint32_t st_flags;
- uint32_t st_gen;
- };
-
- /// For statfs().
- struct F64_statfs {
- int16_t f_type;
- int16_t f_flags;
- int32_t f_retired1;
- int32_t f_retired2;
- int32_t f_retired3;
- int32_t f_retired4;
- int32_t f_retired5;
- int32_t f_retired6;
- int32_t f_retired7;
- fsid_t f_fsid;
- int32_t f_spare[9];
- char f_retired8[90];
- char f_retired9[90];
- uint64_t dummy[10]; // was union mount_info mount_info;
- uint64_t f_flags2;
- int64_t f_spare2[14];
- int64_t f_fsize;
- int64_t f_bsize;
- int64_t f_blocks;
- int64_t f_bfree;
- int64_t f_bavail;
- int64_t f_files;
- int64_t f_ffree;
- char f_mntonname[1024];
- char f_mntfromname[1024];
- };
-
- /// For old Tru64 v4.x statfs()
- struct pre_F64_statfs {
- int16_t f_type;
- int16_t f_flags;
- int32_t f_fsize;
- int32_t f_bsize;
- int32_t f_blocks;
- int32_t f_bfree;
- int32_t f_bavail;
- int32_t f_files;
- int32_t f_ffree;
- fsid_t f_fsid;
- int32_t f_spare[9];
- char f_mntonname[90];
- char f_mntfromname[90];
- uint64_t dummy[10]; // was union mount_info mount_info;
- };
-
- /// For getdirentries().
- struct dirent
- {
- ino_t d_ino; //!< file number of entry
- uint16_t d_reclen; //!< length of this record
- uint16_t d_namlen; //!< length of string in d_name
- char d_name[256]; //!< dummy name length
- };
-
-
- /// Length of strings in struct utsname (plus 1 for null char).
- static const int _SYS_NMLN = 32;
-
- /// Interface struct for uname().
- struct utsname {
- char sysname[_SYS_NMLN]; //!< System name.
- char nodename[_SYS_NMLN]; //!< Node name.
- char release[_SYS_NMLN]; //!< OS release.
- char version[_SYS_NMLN]; //!< OS version.
- char machine[_SYS_NMLN]; //!< Machine type.
- };
-
- //@{
- /// ioctl() command codes.
- static const unsigned TIOCGETP = 0x40067408;
- static const unsigned TIOCSETP = 0x80067409;
- static const unsigned TIOCSETN = 0x8006740a;
- static const unsigned TIOCSETC = 0x80067411;
- static const unsigned TIOCGETC = 0x40067412;
- static const unsigned FIONREAD = 0x4004667f;
- static const unsigned TIOCISATTY = 0x2000745e;
- // TIOCGETS not defined in tru64, so I made up a number
- static const unsigned TIOCGETS = 0x40000000;
- static const unsigned TIOCGETA = 0x402c7413;
- //@}
-
- /// Resource enumeration for getrlimit().
- enum rlimit_resources {
- RLIMIT_CPU = 0,
- RLIMIT_FSIZE = 1,
- RLIMIT_DATA = 2,
- RLIMIT_STACK = 3,
- RLIMIT_CORE = 4,
- RLIMIT_RSS = 5,
- RLIMIT_NOFILE = 6,
- RLIMIT_AS = 7,
- RLIMIT_VMEM = 7
- };
-
- /// Limit struct for getrlimit/setrlimit.
- struct rlimit {
- uint64_t rlim_cur; //!< soft limit
- uint64_t rlim_max; //!< hard limit
- };
-
-
- /// For mmap().
- static const unsigned TGT_MAP_ANONYMOUS = 0x10;
-
-
- //@{
- /// For getsysinfo().
- static const unsigned GSI_PLATFORM_NAME = 103; //!< platform name as string
- static const unsigned GSI_CPU_INFO = 59; //!< CPU information
- static const unsigned GSI_PROC_TYPE = 60; //!< get proc_type
- static const unsigned GSI_MAX_CPU = 30; //!< max # cpu's on this machine
- static const unsigned GSI_CPUS_IN_BOX = 55; //!< number of CPUs in system
- static const unsigned GSI_PHYSMEM = 19; //!< Physical memory in KB
- static const unsigned GSI_CLK_TCK = 42; //!< clock freq in Hz
- //@}
-
- /// For getsysinfo() GSI_CPU_INFO option.
- struct cpu_info {
- uint32_t current_cpu; //!< current_cpu
- uint32_t cpus_in_box; //!< cpus_in_box
- uint32_t cpu_type; //!< cpu_type
- uint32_t ncpus; //!< ncpus
- uint64_t cpus_present; //!< cpus_present
- uint64_t cpus_running; //!< cpus_running
- uint64_t cpu_binding; //!< cpu_binding
- uint64_t cpu_ex_binding; //!< cpu_ex_binding
- uint32_t mhz; //!< mhz
- uint32_t unused[3]; //!< future expansion
- };
-
- //@{
- /// For setsysinfo().
- static const unsigned SSI_IEEE_FP_CONTROL = 14; //!< ieee_set_fp_control()
- //@}
-
- /// For gettimeofday.
- struct timeval {
- uint32_t tv_sec; //!< seconds
- uint32_t tv_usec; //!< microseconds
- };
-
- //@{
- /// For getrusage().
- static const int RUSAGE_THREAD = 1;
- static const int RUSAGE_SELF = 0;
- static const int RUSAGE_CHILDREN = -1;
- //@}
-
- /// For getrusage().
- struct rusage {
- struct timeval ru_utime; //!< user time used
- struct timeval ru_stime; //!< system time used
- uint64_t ru_maxrss; //!< ru_maxrss
- uint64_t ru_ixrss; //!< integral shared memory size
- uint64_t ru_idrss; //!< integral unshared data "
- uint64_t ru_isrss; //!< integral unshared stack "
- uint64_t ru_minflt; //!< page reclaims - total vmfaults
- uint64_t ru_majflt; //!< page faults
- uint64_t ru_nswap; //!< swaps
- uint64_t ru_inblock; //!< block input operations
- uint64_t ru_oublock; //!< block output operations
- uint64_t ru_msgsnd; //!< messages sent
- uint64_t ru_msgrcv; //!< messages received
- uint64_t ru_nsignals; //!< signals received
- uint64_t ru_nvcsw; //!< voluntary context switches
- uint64_t ru_nivcsw; //!< involuntary "
- };
-
- /// For sigreturn().
- struct sigcontext {
- int64_t sc_onstack; //!< sigstack state to restore
- int64_t sc_mask; //!< signal mask to restore
- int64_t sc_pc; //!< pc at time of signal
- int64_t sc_ps; //!< psl to retore
- int64_t sc_regs[32]; //!< processor regs 0 to 31
- int64_t sc_ownedfp; //!< fp has been used
- int64_t sc_fpregs[32]; //!< fp regs 0 to 31
- uint64_t sc_fpcr; //!< floating point control reg
- uint64_t sc_fp_control; //!< software fpcr
- int64_t sc_reserved1; //!< reserved for kernel
- uint32_t sc_kreserved1; //!< reserved for kernel
- uint32_t sc_kreserved2; //!< reserved for kernel
- size_t sc_ssize; //!< stack size
- caddr_t sc_sbase; //!< stack start
- uint64_t sc_traparg_a0; //!< a0 argument to trap on exc
- uint64_t sc_traparg_a1; //!< a1 argument to trap on exc
- uint64_t sc_traparg_a2; //!< a2 argument to trap on exc
- uint64_t sc_fp_trap_pc; //!< imprecise pc
- uint64_t sc_fp_trigger_sum; //!< Exception summary at trigg
- uint64_t sc_fp_trigger_inst; //!< Instruction at trigger pc
- };
-
-
- /// For table().
- static const int TBL_SYSINFO = 12;
-
- /// For table().
- struct tbl_sysinfo {
- uint64_t si_user; //!< User time
- uint64_t si_nice; //!< Nice time
- uint64_t si_sys; //!< System time
- uint64_t si_idle; //!< Idle time
- uint64_t si_hz; //!< hz
- uint64_t si_phz; //!< phz
- uint64_t si_boottime; //!< Boot time in seconds
- uint64_t wait; //!< Wait time
- uint32_t si_max_procs; //!< rpb->rpb_numprocs
- uint32_t pad; //!< padding
- };
-
-
- /// For stack_create.
- struct vm_stack {
- // was void *
- Addr address; //!< address hint
- size_t rsize; //!< red zone size
- size_t ysize; //!< yellow zone size
- size_t gsize; //!< green zone size
- size_t swap; //!< amount of swap to reserve
- size_t incr; //!< growth increment
- uint64_t align; //!< address alignment
- uint64_t flags; //!< MAP_FIXED etc.
- // was struct memalloc_attr *
- Addr attr; //!< allocation policy
- uint64_t reserved; //!< reserved
- };
-
- /// Return values for nxm calls.
- enum {
- KERN_NOT_RECEIVER = 7,
- KERN_NOT_IN_SET = 12
- };
-
- /// For nxm_task_init.
- static const int NXM_TASK_INIT_VP = 2; //!< initial thread is VP
-
- /// Task attribute structure.
- struct nxm_task_attr {
- int64_t nxm_callback; //!< nxm_callback
- unsigned int nxm_version; //!< nxm_version
- unsigned short nxm_uniq_offset; //!< nxm_uniq_offset
- unsigned short flags; //!< flags
- int nxm_quantum; //!< nxm_quantum
- int pad1; //!< pad1
- int64_t pad2; //!< pad2
- };
-
- /// Signal set.
- typedef uint64_t sigset_t;
-
- /// Thread state shared between user & kernel.
- struct ushared_state {
- sigset_t sigmask; //!< thread signal mask
- sigset_t sig; //!< thread pending mask
- // struct nxm_pth_state *
- Addr pth_id; //!< out-of-line state
- int flags; //!< shared flags
-#define US_SIGSTACK 0x1 // thread called sigaltstack
-#define US_ONSTACK 0x2 // thread is running on altstack
-#define US_PROFILE 0x4 // thread called profil
-#define US_SYSCALL 0x8 // thread in syscall
-#define US_TRAP 0x10 // thread has trapped
-#define US_YELLOW 0x20 // thread has mellowed yellow
-#define US_YZONE 0x40 // thread has zoned out
-#define US_FP_OWNED 0x80 // thread used floating point
-
- int cancel_state; //!< thread's cancelation state
-#define US_CANCEL 0x1 // cancel pending
-#define US_NOCANCEL 0X2 // synch cancel disabled
-#define US_SYS_NOCANCEL 0x4 // syscall cancel disabled
-#define US_ASYNC_NOCANCEL 0x8 // asynch cancel disabled
-#define US_CANCEL_BITS (US_NOCANCEL|US_SYS_NOCANCEL|US_ASYNC_NOCANCEL)
-#define US_CANCEL_MASK (US_CANCEL|US_NOCANCEL|US_SYS_NOCANCEL| \
- US_ASYNC_NOCANCEL)
-
- // These are semi-shared. They are always visible to
- // the kernel but are never context-switched by the library.
-
- int nxm_ssig; //!< scheduler's synchronous signals
- int reserved1; //!< reserved1
- int64_t nxm_active; //!< scheduler active
- int64_t reserved2; //!< reserved2
- };
-
- struct nxm_sched_state {
- struct ushared_state nxm_u; //!< state own by user thread
- unsigned int nxm_bits; //!< scheduler state / slot
- int nxm_quantum; //!< quantum count-down value
- int nxm_set_quantum; //!< quantum reset value
- int nxm_sysevent; //!< syscall state
- // struct nxm_upcall *
- Addr nxm_uc_ret; //!< stack ptr of null thread
- // void *
- Addr nxm_tid; //!< scheduler's thread id
- int64_t nxm_va; //!< page fault address
- // struct nxm_pth_state *
- Addr nxm_pthid; //!< id of null thread
- uint64_t nxm_bound_pcs_count; //!< bound PCS thread count
- int64_t pad[2]; //!< pad
- };
-
- /// nxm_shared.
- struct nxm_shared {
- int64_t nxm_callback; //!< address of upcall routine
- unsigned int nxm_version; //!< version number
- unsigned short nxm_uniq_offset; //!< correction factor for TEB
- unsigned short pad1; //!< pad1
- int64_t space[2]; //!< future growth
- struct nxm_sched_state nxm_ss[1]; //!< array of shared areas
- };
-
- /// nxm_slot_state_t.
- enum nxm_slot_state_t {
- NXM_SLOT_AVAIL,
- NXM_SLOT_BOUND,
- NXM_SLOT_UNBOUND,
- NXM_SLOT_EMPTY
- };
-
- /// nxm_config_info
- struct nxm_config_info {
- int nxm_nslots_per_rad; //!< max number of VP slots per RAD
- int nxm_nrads; //!< max number of RADs
- // nxm_slot_state_t *
- Addr nxm_slot_state; //!< per-VP slot state
- // struct nxm_shared *
- Addr nxm_rad[1]; //!< per-RAD shared areas
- };
-
- /// For nxm_thread_create.
- enum nxm_thread_type {
- NXM_TYPE_SCS = 0,
- NXM_TYPE_VP = 1,
- NXM_TYPE_MANAGER = 2
- };
-
- /// Thread attributes.
- struct nxm_thread_attr {
- int version; //!< version
- int type; //!< type
- int cancel_flags; //!< cancel_flags
- int priority; //!< priority
- int policy; //!< policy
- int signal_type; //!< signal_type
- // void *
- Addr pthid; //!< pthid
- sigset_t sigmask; //!< sigmask
- /// Initial register values.
- struct {
- uint64_t pc; //!< pc
- uint64_t sp; //!< sp
- uint64_t a0; //!< a0
- } registers;
- uint64_t pad2[2]; //!< pad2
- };
-
- /// Helper function to convert a host stat buffer to a target stat
- /// buffer. Also copies the target buffer out to the simulated
- /// memory space. Used by stat(), fstat(), and lstat().
- template <class T>
- static void
- copyOutStatBuf(TranslatingPort *memPort, Addr addr, global_stat *host)
- {
- TypedBufferArg<T> tgt(addr);
-
- tgt->st_dev = host->st_dev;
- tgt->st_ino = host->st_ino;
- tgt->st_mode = host->st_mode;
- tgt->st_nlink = host->st_nlink;
- tgt->st_uid = host->st_uid;
- tgt->st_gid = host->st_gid;
- tgt->st_rdev = host->st_rdev;
- tgt->st_size = host->st_size;
- tgt->st_atimeX = host->st_atime;
- tgt->st_mtimeX = host->st_mtime;
- tgt->st_ctimeX = host->st_ctime;
- tgt->st_blksize = host->st_blksize;
- tgt->st_blocks = host->st_blocks;
-
- tgt.copyOut(memPort);
- }
-
- /// Helper function to convert a host statfs buffer to a target statfs
- /// buffer. Also copies the target buffer out to the simulated
- /// memory space. Used by statfs() and fstatfs().
- template <class T>
- static void
- copyOutStatfsBuf(TranslatingPort *memPort, Addr addr, global_statfs *host)
- {
- TypedBufferArg<T> tgt(addr);
-
-#if defined(__OpenBSD__)
- tgt->f_type = 0;
-#else
- tgt->f_type = host->f_type;
-#endif
- tgt->f_bsize = host->f_bsize;
- tgt->f_blocks = host->f_blocks;
- tgt->f_bfree = host->f_bfree;
- tgt->f_bavail = host->f_bavail;
- tgt->f_files = host->f_files;
- tgt->f_ffree = host->f_ffree;
- memcpy(&tgt->f_fsid, &host->f_fsid, sizeof(host->f_fsid));
-
- tgt.copyOut(memPort);
- }
-
- class F64 {
- public:
- static void copyOutStatBuf(TranslatingPort *memPort, Addr addr,
- global_stat *host)
- {
- Tru64::copyOutStatBuf<Tru64::F64_stat>(memPort, addr, host);
- }
-
- static void copyOutStatfsBuf(TranslatingPort *memPort, Addr addr,
- global_statfs *host)
- {
- Tru64::copyOutStatfsBuf<Tru64::F64_statfs>(memPort, addr, host);
- }
- };
-
- class PreF64 {
- public:
- static void copyOutStatBuf(TranslatingPort *memPort, Addr addr,
- global_stat *host)
- {
- Tru64::copyOutStatBuf<Tru64::pre_F64_stat>(memPort, addr, host);
- }
-
- static void copyOutStatfsBuf(TranslatingPort *memPort, Addr addr,
- global_statfs *host)
- {
- Tru64::copyOutStatfsBuf<Tru64::pre_F64_statfs>(memPort, addr, host);
- }
- };
-
- /// Helper function to convert a host stat buffer to an old pre-F64
- /// (4.x) target stat buffer. Also copies the target buffer out to
- /// the simulated memory space. Used by pre_F64_stat(),
- /// pre_F64_fstat(), and pre_F64_lstat().
- static void
- copyOutPreF64StatBuf(TranslatingPort *memPort, Addr addr, struct stat *host)
- {
- TypedBufferArg<Tru64::pre_F64_stat> tgt(addr);
-
- tgt->st_dev = host->st_dev;
- tgt->st_ino = host->st_ino;
- tgt->st_mode = host->st_mode;
- tgt->st_nlink = host->st_nlink;
- tgt->st_uid = host->st_uid;
- tgt->st_gid = host->st_gid;
- tgt->st_rdev = host->st_rdev;
- tgt->st_size = host->st_size;
- tgt->st_atimeX = host->st_atime;
- tgt->st_mtimeX = host->st_mtime;
- tgt->st_ctimeX = host->st_ctime;
- tgt->st_blksize = host->st_blksize;
- tgt->st_blocks = host->st_blocks;
-
- tgt.copyOut(memPort);
- }
-
-
- /// The target system's hostname.
- static const char *hostname;
-
- /// Target uname() handler.
- static SyscallReturn
- unameFunc(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
- {
- TypedBufferArg<Tru64::utsname> name(xc->getSyscallArg(0));
-
- strcpy(name->sysname, "OSF1");
- strcpy(name->nodename, hostname);
- strcpy(name->release, "V5.1");
- strcpy(name->version, "732");
- strcpy(name->machine, "alpha");
-
- name.copyOut(xc->port);
- return 0;
- }
-
-
- /// Target getsysyinfo() handler.
- static SyscallReturn
- getsysinfoFunc(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
- {
- unsigned op = xc->getSyscallArg(0);
- unsigned nbytes = xc->getSyscallArg(2);
-
- switch (op) {
-
- case Tru64::GSI_MAX_CPU: {
- TypedBufferArg<uint32_t> max_cpu(xc->getSyscallArg(1));
- *max_cpu = process->numCpus();
- max_cpu.copyOut(xc->port);
- return 1;
- }
-
- case Tru64::GSI_CPUS_IN_BOX: {
- TypedBufferArg<uint32_t> cpus_in_box(xc->getSyscallArg(1));
- *cpus_in_box = process->numCpus();
- cpus_in_box.copyOut(xc->port);
- return 1;
- }
-
- case Tru64::GSI_PHYSMEM: {
- TypedBufferArg<uint64_t> physmem(xc->getSyscallArg(1));
- *physmem = 1024 * 1024; // physical memory in KB
- physmem.copyOut(xc->port);
- return 1;
- }
-
- case Tru64::GSI_CPU_INFO: {
- TypedBufferArg<Tru64::cpu_info> infop(xc->getSyscallArg(1));
-
- infop->current_cpu = 0;
- infop->cpus_in_box = process->numCpus();
- infop->cpu_type = 57;
- infop->ncpus = process->numCpus();
- int cpumask = (1 << process->numCpus()) - 1;
- infop->cpus_present = infop->cpus_running = cpumask;
- infop->cpu_binding = 0;
- infop->cpu_ex_binding = 0;
- infop->mhz = 667;
-
- infop.copyOut(xc->port);
- return 1;
- }
-
- case Tru64::GSI_PROC_TYPE: {
- TypedBufferArg<uint64_t> proc_type(xc->getSyscallArg(1));
- *proc_type = 11;
- proc_type.copyOut(xc->port);
- return 1;
- }
-
- case Tru64::GSI_PLATFORM_NAME: {
- BufferArg bufArg(xc->getSyscallArg(1), nbytes);
- strncpy((char *)bufArg.bufferPtr(),
- "COMPAQ Professional Workstation XP1000",
- nbytes);
- bufArg.copyOut(xc->port);
- return 1;
- }
-
- case Tru64::GSI_CLK_TCK: {
- TypedBufferArg<uint64_t> clk_hz(xc->getSyscallArg(1));
- *clk_hz = 1024;
- clk_hz.copyOut(xc->port);
- return 1;
- }
-
- default:
- warn("getsysinfo: unknown op %d\n", op);
- break;
- }
-
- return 0;
- }
-
- /// Target setsysyinfo() handler.
- static SyscallReturn
- setsysinfoFunc(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
- {
- unsigned op = xc->getSyscallArg(0);
-
- switch (op) {
- case SSI_IEEE_FP_CONTROL:
- warn("setsysinfo: ignoring ieee_set_fp_control() arg 0x%x\n",
- xc->getSyscallArg(1));
- break;
-
- default:
- warn("setsysinfo: unknown op %d\n", op);
- break;
- }
-
- return 0;
- }
-
- /// Target fnctl() handler.
- static SyscallReturn
- fcntlFunc(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
- {
- int fd = xc->getSyscallArg(0);
-
- if (fd < 0 || process->sim_fd(fd) < 0)
- return -EBADF;
-
- int cmd = xc->getSyscallArg(1);
- switch (cmd) {
- case 0: // F_DUPFD
- // if we really wanted to support this, we'd need to do it
- // in the target fd space.
- warn("fcntl(%d, F_DUPFD) not supported, error returned\n", fd);
- return -EMFILE;
-
- case 1: // F_GETFD (get close-on-exec flag)
- case 2: // F_SETFD (set close-on-exec flag)
- return 0;
-
- case 3: // F_GETFL (get file flags)
- case 4: // F_SETFL (set file flags)
- // not sure if this is totally valid, but we'll pass it through
- // to the underlying OS
- warn("fcntl(%d, %d) passed through to host\n", fd, cmd);
- return fcntl(process->sim_fd(fd), cmd);
- // return 0;
-
- case 7: // F_GETLK (get lock)
- case 8: // F_SETLK (set lock)
- case 9: // F_SETLKW (set lock and wait)
- // don't mess with file locking... just act like it's OK
- warn("File lock call (fcntl(%d, %d)) ignored.\n", fd, cmd);
- return 0;
-
- default:
- warn("Unknown fcntl command %d\n", cmd);
- return 0;
- }
- }
-
-
- /// Target getdirentries() handler.
- static SyscallReturn
- getdirentriesFunc(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
- {
-#ifdef __CYGWIN__
- panic("getdirent not implemented on cygwin!");
-#else
- int fd = process->sim_fd(xc->getSyscallArg(0));
- Addr tgt_buf = xc->getSyscallArg(1);
- int tgt_nbytes = xc->getSyscallArg(2);
- Addr tgt_basep = xc->getSyscallArg(3);
-
- char * const host_buf = new char[tgt_nbytes];
-
- // just pass basep through uninterpreted.
- TypedBufferArg<int64_t> basep(tgt_basep);
- basep.copyIn(xc->port);
- long host_basep = (off_t)*basep;
- int host_result = getdirentries(fd, host_buf, tgt_nbytes, &host_basep);
-
- // check for error
- if (host_result < 0) {
- delete [] host_buf;
- return -errno;
- }
-
- // no error: copy results back to target space
- Addr tgt_buf_ptr = tgt_buf;
- char *host_buf_ptr = host_buf;
- char *host_buf_end = host_buf + host_result;
- while (host_buf_ptr < host_buf_end) {
- global_dirent *host_dp = (global_dirent *)host_buf_ptr;
- int namelen = strlen(host_dp->d_name);
-
- // Actual size includes padded string rounded up for alignment.
- // Subtract 256 for dummy char array in Tru64::dirent definition.
- // Add 1 to namelen for terminating null char.
- int tgt_bufsize = sizeof(Tru64::dirent) - 256 + roundUp(namelen+1, 8);
- TypedBufferArg<Tru64::dirent> tgt_dp(tgt_buf_ptr, tgt_bufsize);
- tgt_dp->d_ino = host_dp->d_ino;
- tgt_dp->d_reclen = tgt_bufsize;
- tgt_dp->d_namlen = namelen;
- strcpy(tgt_dp->d_name, host_dp->d_name);
- tgt_dp.copyOut(xc->port);
-
- tgt_buf_ptr += tgt_bufsize;
- host_buf_ptr += host_dp->d_reclen;
- }
-
- delete [] host_buf;
-
- *basep = host_basep;
- basep.copyOut(xc->port);
-
- return tgt_buf_ptr - tgt_buf;
-#endif
- }
-
- /// Target sigreturn() handler.
- static SyscallReturn
- sigreturnFunc(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
- {
- RegFile *regs = &xc->regs;
- TypedBufferArg<Tru64::sigcontext> sc(xc->getSyscallArg(0));
-
- sc.copyIn(xc->port);
-
- // Restore state from sigcontext structure.
- // Note that we'll advance PC <- NPC before the end of the cycle,
- // so we need to restore the desired PC into NPC.
- // The current regs->pc will get clobbered.
- regs->npc = sc->sc_pc;
-
- for (int i = 0; i < 31; ++i) {
- regs->intRegFile[i] = sc->sc_regs[i];
- regs->floatRegFile.q[i] = sc->sc_fpregs[i];
- }
-
- regs->miscRegs.fpcr = sc->sc_fpcr;
-
- return 0;
- }
-
- /// Target table() handler.
- static SyscallReturn
- tableFunc(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
- {
- int id = xc->getSyscallArg(0); // table ID
- int index = xc->getSyscallArg(1); // index into table
- // arg 2 is buffer pointer; type depends on table ID
- int nel = xc->getSyscallArg(3); // number of elements
- int lel = xc->getSyscallArg(4); // expected element size
-
- switch (id) {
- case Tru64::TBL_SYSINFO: {
- if (index != 0 || nel != 1 || lel != sizeof(Tru64::tbl_sysinfo))
- return -EINVAL;
- TypedBufferArg<Tru64::tbl_sysinfo> elp(xc->getSyscallArg(2));
-
- const int clk_hz = one_million;
- elp->si_user = curTick / (Clock::Frequency / clk_hz);
- elp->si_nice = 0;
- elp->si_sys = 0;
- elp->si_idle = 0;
- elp->wait = 0;
- elp->si_hz = clk_hz;
- elp->si_phz = clk_hz;
- elp->si_boottime = seconds_since_epoch; // seconds since epoch?
- elp->si_max_procs = process->numCpus();
- elp.copyOut(xc->port);
- return 0;
- }
-
- default:
- cerr << "table(): id " << id << " unknown." << endl;
- return -EINVAL;
- }
- }
-
- /// Array of syscall descriptors, indexed by call number.
- static SyscallDesc syscallDescs[];
-
- /// Number of syscalls in syscallDescs[].
- static const int Num_Syscall_Descs;
-
- /// Max supported syscall number.
- static const int Max_Syscall_Desc;
-
- //
- // Mach syscalls -- identified by negated syscall numbers
- //
-
- /// Create a stack region for a thread.
- static SyscallReturn
- stack_createFunc(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
- {
- TypedBufferArg<Tru64::vm_stack> argp(xc->getSyscallArg(0));
-
- argp.copyIn(xc->port);
-
- // if the user chose an address, just let them have it. Otherwise
- // pick one for them.
- if (argp->address == 0) {
- argp->address = process->next_thread_stack_base;
- int stack_size = (argp->rsize + argp->ysize + argp->gsize);
- process->next_thread_stack_base -= stack_size;
- argp.copyOut(xc->port);
- }
-
- return 0;
- }
-
- /// NXM library version stamp.
- static
- const int NXM_LIB_VERSION = 301003;
-
- /// This call sets up the interface between the user and kernel
- /// schedulers by creating a shared-memory region. The shared memory
- /// region has several structs, some global, some per-RAD, some per-VP.
- static SyscallReturn
- nxm_task_initFunc(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
- {
- TypedBufferArg<Tru64::nxm_task_attr> attrp(xc->getSyscallArg(0));
- TypedBufferArg<Addr> configptr_ptr(xc->getSyscallArg(1));
-
- attrp.copyIn(xc->port);
-
- if (attrp->nxm_version != NXM_LIB_VERSION) {
- cerr << "nxm_task_init: thread library version mismatch! "
- << "got " << attrp->nxm_version
- << ", expected " << NXM_LIB_VERSION << endl;
- abort();
- }
-
- if (attrp->flags != Tru64::NXM_TASK_INIT_VP) {
- cerr << "nxm_task_init: bad flag value " << attrp->flags
- << " (expected " << Tru64::NXM_TASK_INIT_VP << ")" << endl;
- abort();
- }
-
- const Addr base_addr = 0x12000; // was 0x3f0000000LL;
- Addr cur_addr = base_addr; // next addresses to use
- // first comes the config_info struct
- Addr config_addr = cur_addr;
- cur_addr += sizeof(Tru64::nxm_config_info);
- // next comes the per-cpu state vector
- Addr slot_state_addr = cur_addr;
- int slot_state_size =
- process->numCpus() * sizeof(Tru64::nxm_slot_state_t);
- cur_addr += slot_state_size;
- // now the per-RAD state struct (we only support one RAD)
- cur_addr = 0x14000; // bump up addr for alignment
- Addr rad_state_addr = cur_addr;
- int rad_state_size =
- (sizeof(Tru64::nxm_shared)
- + (process->numCpus()-1) * sizeof(Tru64::nxm_sched_state));
- cur_addr += rad_state_size;
-
- // now initialize a config_info struct and copy it out to user space
- TypedBufferArg<Tru64::nxm_config_info> config(config_addr);
-
- config->nxm_nslots_per_rad = process->numCpus();
- config->nxm_nrads = 1; // only one RAD in our system!
- config->nxm_slot_state = slot_state_addr;
- config->nxm_rad[0] = rad_state_addr;
-
- config.copyOut(xc->port);
-
- // initialize the slot_state array and copy it out
- TypedBufferArg<Tru64::nxm_slot_state_t> slot_state(slot_state_addr,
- slot_state_size);
- for (int i = 0; i < process->numCpus(); ++i) {
- // CPU 0 is bound to the calling process; all others are available
- slot_state[i] =
- (i == 0) ? Tru64::NXM_SLOT_BOUND : Tru64::NXM_SLOT_AVAIL;
- }
-
- slot_state.copyOut(xc->port);
-
- // same for the per-RAD "shared" struct. Note that we need to
- // allocate extra bytes for the per-VP array which is embedded at
- // the end.
- TypedBufferArg<Tru64::nxm_shared> rad_state(rad_state_addr,
- rad_state_size);
-
- rad_state->nxm_callback = attrp->nxm_callback;
- rad_state->nxm_version = attrp->nxm_version;
- rad_state->nxm_uniq_offset = attrp->nxm_uniq_offset;
- for (int i = 0; i < process->numCpus(); ++i) {
- Tru64::nxm_sched_state *ssp = &rad_state->nxm_ss[i];
- ssp->nxm_u.sigmask = 0;
- ssp->nxm_u.sig = 0;
- ssp->nxm_u.flags = 0;
- ssp->nxm_u.cancel_state = 0;
- ssp->nxm_u.nxm_ssig = 0;
- ssp->nxm_bits = 0;
- ssp->nxm_quantum = attrp->nxm_quantum;
- ssp->nxm_set_quantum = attrp->nxm_quantum;
- ssp->nxm_sysevent = 0;
-
- if (i == 0) {
- uint64_t uniq = xc->regs.miscRegs.uniq;
- ssp->nxm_u.pth_id = uniq + attrp->nxm_uniq_offset;
- ssp->nxm_u.nxm_active = uniq | 1;
- }
- else {
- ssp->nxm_u.pth_id = 0;
- ssp->nxm_u.nxm_active = 0;
- }
- }
-
- rad_state.copyOut(xc->port);
-
- //
- // copy pointer to shared config area out to user
- //
- *configptr_ptr = config_addr;
- configptr_ptr.copyOut(xc->port);
-
- // Register this as a valid address range with the process
- process->nxm_start = base_addr;
- process->nxm_end = cur_addr;
-
- return 0;
- }
-
- /// Initialize execution context.
- static void
- init_exec_context(ExecContext *ec,
- Tru64::nxm_thread_attr *attrp, uint64_t uniq_val)
- {
- memset(&ec->regs, 0, sizeof(ec->regs));
-
- ec->regs.intRegFile[ArgumentReg0] = attrp->registers.a0;
- ec->regs.intRegFile[27/*t12*/] = attrp->registers.pc;
- ec->regs.intRegFile[StackPointerReg] = attrp->registers.sp;
- ec->regs.miscRegs.uniq = uniq_val;
-
- ec->regs.pc = attrp->registers.pc;
- ec->regs.npc = attrp->registers.pc + sizeof(MachInst);
-
- ec->activate();
- }
-
- /// Create thread.
- static SyscallReturn
- nxm_thread_createFunc(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
- {
- TypedBufferArg<Tru64::nxm_thread_attr> attrp(xc->getSyscallArg(0));
- TypedBufferArg<uint64_t> kidp(xc->getSyscallArg(1));
- int thread_index = xc->getSyscallArg(2);
-
- // get attribute args
- attrp.copyIn(xc->port);
-
- if (attrp->version != NXM_LIB_VERSION) {
- cerr << "nxm_thread_create: thread library version mismatch! "
- << "got " << attrp->version
- << ", expected " << NXM_LIB_VERSION << endl;
- abort();
- }
-
- if (thread_index < 0 | thread_index > process->numCpus()) {
- cerr << "nxm_thread_create: bad thread index " << thread_index
- << endl;
- abort();
- }
-
- // On a real machine, the per-RAD shared structure is in
- // shared memory, so both the user and kernel can get at it.
- // We don't have that luxury, so we just copy it in and then
- // back out again.
- int rad_state_size =
- (sizeof(Tru64::nxm_shared) +
- (process->numCpus()-1) * sizeof(Tru64::nxm_sched_state));
-
- TypedBufferArg<Tru64::nxm_shared> rad_state(0x14000,
- rad_state_size);
- rad_state.copyIn(xc->port);
-
- uint64_t uniq_val = attrp->pthid - rad_state->nxm_uniq_offset;
-
- if (attrp->type == Tru64::NXM_TYPE_MANAGER) {
- // DEC pthreads seems to always create one of these (in
- // addition to N application threads), but we don't use it,
- // so don't bother creating it.
-
- // This is supposed to be a port number. Make something up.
- *kidp = 99;
- kidp.copyOut(xc->port);
-
- return 0;
- } else if (attrp->type == Tru64::NXM_TYPE_VP) {
- // A real "virtual processor" kernel thread. Need to fork
- // this thread on another CPU.
- Tru64::nxm_sched_state *ssp = &rad_state->nxm_ss[thread_index];
-
- if (ssp->nxm_u.nxm_active != 0)
- return (int) Tru64::KERN_NOT_RECEIVER;
-
- ssp->nxm_u.pth_id = attrp->pthid;
- ssp->nxm_u.nxm_active = uniq_val | 1;
-
- rad_state.copyOut(xc->port);
-
- Addr slot_state_addr = 0x12000 + sizeof(Tru64::nxm_config_info);
- int slot_state_size =
- process->numCpus() * sizeof(Tru64::nxm_slot_state_t);
-
- TypedBufferArg<Tru64::nxm_slot_state_t>
- slot_state(slot_state_addr,
- slot_state_size);
-
- slot_state.copyIn(xc->port);
-
- if (slot_state[thread_index] != Tru64::NXM_SLOT_AVAIL) {
- cerr << "nxm_thread_createFunc: requested VP slot "
- << thread_index << " not available!" << endl;
- fatal("");
- }
-
- slot_state[thread_index] = Tru64::NXM_SLOT_BOUND;
-
- slot_state.copyOut(xc->port);
-
- // Find a free simulator execution context.
- for (int i = 0; i < process->numCpus(); ++i) {
- ExecContext *xc = process->execContexts[i];
-
- if (xc->status() == ExecContext::Unallocated) {
- // inactive context... grab it
- init_exec_context(xc, attrp, uniq_val);
-
- // This is supposed to be a port number, but we'll try
- // and get away with just sticking the thread index
- // here.
- *kidp = thread_index;
- kidp.copyOut(xc->port);
-
- return 0;
- }
- }
-
- // fell out of loop... no available inactive context
- cerr << "nxm_thread_create: no idle contexts available." << endl;
- abort();
- } else {
- cerr << "nxm_thread_create: can't handle thread type "
- << attrp->type << endl;
- abort();
- }
-
- return 0;
- }
-
- /// Thread idle call (like yield()).
- static SyscallReturn
- nxm_idleFunc(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
- {
- return 0;
- }
-
- /// Block thread.
- static SyscallReturn
- nxm_thread_blockFunc(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
- {
- uint64_t tid = xc->getSyscallArg(0);
- uint64_t secs = xc->getSyscallArg(1);
- uint64_t flags = xc->getSyscallArg(2);
- uint64_t action = xc->getSyscallArg(3);
- uint64_t usecs = xc->getSyscallArg(4);
-
- cout << xc->cpu->name() << ": nxm_thread_block " << tid << " " << secs
- << " " << flags << " " << action << " " << usecs << endl;
-
- return 0;
- }
-
- /// block.
- static SyscallReturn
- nxm_blockFunc(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
- {
- Addr uaddr = xc->getSyscallArg(0);
- uint64_t val = xc->getSyscallArg(1);
- uint64_t secs = xc->getSyscallArg(2);
- uint64_t usecs = xc->getSyscallArg(3);
- uint64_t flags = xc->getSyscallArg(4);
-
- BaseCPU *cpu = xc->cpu;
-
- cout << cpu->name() << ": nxm_block "
- << hex << uaddr << dec << " " << val
- << " " << secs << " " << usecs
- << " " << flags << endl;
-
- return 0;
- }
-
- /// Unblock thread.
- static SyscallReturn
- nxm_unblockFunc(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
- {
- Addr uaddr = xc->getSyscallArg(0);
-
- cout << xc->cpu->name() << ": nxm_unblock "
- << hex << uaddr << dec << endl;
-
- return 0;
- }
-
- /// Switch thread priority.
- static SyscallReturn
- swtch_priFunc(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
- {
- // Attempts to switch to another runnable thread (if there is
- // one). Returns false if there are no other threads to run
- // (i.e., the thread can reasonably spin-wait) or true if there
- // are other threads.
- //
- // Since we assume at most one "kernel" thread per CPU, it's
- // always safe to return false here.
- return 0; //false;
- }
-
-
- /// Activate exec context waiting on a channel. Just activate one
- /// by default.
- static int
- activate_waiting_context(Addr uaddr, Process *process,
- bool activate_all = false)
- {
- int num_activated = 0;
-
- list<Process::WaitRec>::iterator i = process->waitList.begin();
- list<Process::WaitRec>::iterator end = process->waitList.end();
-
- while (i != end && (num_activated == 0 || activate_all)) {
- if (i->waitChan == uaddr) {
- // found waiting process: make it active
- ExecContext *newCtx = i->waitingContext;
- assert(newCtx->status() == ExecContext::Suspended);
- newCtx->activate();
-
- // get rid of this record
- i = process->waitList.erase(i);
-
- ++num_activated;
- } else {
- ++i;
- }
- }
-
- return num_activated;
- }
-
- /// M5 hacked-up lock acquire.
- static void
- m5_lock_mutex(Addr uaddr, Process *process, ExecContext *xc)
- {
- TypedBufferArg<uint64_t> lockp(uaddr);
-
- lockp.copyIn(xc->port);
-
- if (*lockp == 0) {
- // lock is free: grab it
- *lockp = 1;
- lockp.copyOut(xc->port);
- } else {
- // lock is busy: disable until free
- process->waitList.push_back(Process::WaitRec(uaddr, xc));
- xc->suspend();
- }
- }
-
- /// M5 unlock call.
- static void
- m5_unlock_mutex(Addr uaddr, Process *process, ExecContext *xc)
- {
- TypedBufferArg<uint64_t> lockp(uaddr);
-
- lockp.copyIn(xc->port);
- assert(*lockp != 0);
-
- // Check for a process waiting on the lock.
- int num_waiting = activate_waiting_context(uaddr, process);
-
- // clear lock field if no waiting context is taking over the lock
- if (num_waiting == 0) {
- *lockp = 0;
- lockp.copyOut(xc->port);
- }
- }
-
- /// Lock acquire syscall handler.
- static SyscallReturn
- m5_mutex_lockFunc(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
- {
- Addr uaddr = xc->getSyscallArg(0);
-
- m5_lock_mutex(uaddr, process, xc);
-
- // Return 0 since we will always return to the user with the lock
- // acquired. We will just keep the context inactive until that is
- // true.
- return 0;
- }
-
- /// Try lock (non-blocking).
- static SyscallReturn
- m5_mutex_trylockFunc(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
- {
- Addr uaddr = xc->getSyscallArg(0);
- TypedBufferArg<uint64_t> lockp(uaddr);
-
- lockp.copyIn(xc->port);
-
- if (*lockp == 0) {
- // lock is free: grab it
- *lockp = 1;
- lockp.copyOut(xc->port);
- return 0;
- } else {
- return 1;
- }
- }
-
- /// Unlock syscall handler.
- static SyscallReturn
- m5_mutex_unlockFunc(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
- {
- Addr uaddr = xc->getSyscallArg(0);
-
- m5_unlock_mutex(uaddr, process, xc);
-
- return 0;
- }
-
- /// Signal ocndition.
- static SyscallReturn
- m5_cond_signalFunc(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
- {
- Addr cond_addr = xc->getSyscallArg(0);
-
- // Wake up one process waiting on the condition variable.
- activate_waiting_context(cond_addr, process);
-
- return 0;
- }
-
- /// Wake up all processes waiting on the condition variable.
- static SyscallReturn
- m5_cond_broadcastFunc(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
- {
- Addr cond_addr = xc->getSyscallArg(0);
-
- activate_waiting_context(cond_addr, process, true);
-
- return 0;
- }
-
- /// Wait on a condition.
- static SyscallReturn
- m5_cond_waitFunc(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
- {
- Addr cond_addr = xc->getSyscallArg(0);
- Addr lock_addr = xc->getSyscallArg(1);
- TypedBufferArg<uint64_t> condp(cond_addr);
- TypedBufferArg<uint64_t> lockp(lock_addr);
-
- // user is supposed to acquire lock before entering
- lockp.copyIn(xc->port);
- assert(*lockp != 0);
-
- m5_unlock_mutex(lock_addr, process, xc);
-
- process->waitList.push_back(Process::WaitRec(cond_addr, xc));
- xc->suspend();
-
- return 0;
- }
-
- /// Thread exit.
- static SyscallReturn
- m5_thread_exitFunc(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
- {
- assert(xc->status() == ExecContext::Active);
- xc->deallocate();
-
- return 0;
- }
-
- /// Array of syscall descriptors for Mach syscalls, indexed by
- /// (negated) call number.
- static SyscallDesc machSyscallDescs[];
-
- /// Number of syscalls in machSyscallDescs[].
- static const int Num_Mach_Syscall_Descs;
-
- /// Max supported Mach syscall number.
- static const int Max_Mach_Syscall_Desc;
-
- /// Since negated values are used to identify Mach syscalls, the
- /// minimum (signed) valid syscall number is the negated max Mach
- /// syscall number.
- static const int Min_Syscall_Desc;
-
- /// Do the specified syscall. Just looks the call number up in
- /// the table and invokes the appropriate handler.
- static void
- doSyscall(int callnum, Process *process, ExecContext *xc)
- {
- if (callnum < Min_Syscall_Desc || callnum > Max_Syscall_Desc) {
- fatal("Syscall %d out of range\n", callnum);
- }
-
- SyscallDesc *desc =
- (callnum < 0) ?
- &machSyscallDescs[-callnum] : &syscallDescs[callnum];
-
- desc->doSyscall(callnum, process, xc);
- }
-
- /// Indirect syscall invocation (call #0).
- static SyscallReturn
- indirectSyscallFunc(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
- {
- int new_callnum = xc->getSyscallArg(0);
-
- for (int i = 0; i < 5; ++i)
- xc->setSyscallArg(i, xc->getSyscallArg(i+1));
-
- doSyscall(new_callnum, process, xc);
-
- return 0;
- }
-
-}; // class Tru64
-
-
-// open(2) flags translation table
-OpenFlagTransTable Tru64::openFlagTable[] = {
-#ifdef _MSC_VER
- { Tru64::TGT_O_RDONLY, _O_RDONLY },
- { Tru64::TGT_O_WRONLY, _O_WRONLY },
- { Tru64::TGT_O_RDWR, _O_RDWR },
- { Tru64::TGT_O_APPEND, _O_APPEND },
- { Tru64::TGT_O_CREAT, _O_CREAT },
- { Tru64::TGT_O_TRUNC, _O_TRUNC },
- { Tru64::TGT_O_EXCL, _O_EXCL },
-#ifdef _O_NONBLOCK
- { Tru64::TGT_O_NONBLOCK, _O_NONBLOCK },
-#endif
-#ifdef _O_NOCTTY
- { Tru64::TGT_O_NOCTTY, _O_NOCTTY },
-#endif
-#ifdef _O_SYNC
- { Tru64::TGT_O_SYNC, _O_SYNC },
-#endif
-#else /* !_MSC_VER */
- { Tru64::TGT_O_RDONLY, O_RDONLY },
- { Tru64::TGT_O_WRONLY, O_WRONLY },
- { Tru64::TGT_O_RDWR, O_RDWR },
- { Tru64::TGT_O_APPEND, O_APPEND },
- { Tru64::TGT_O_CREAT, O_CREAT },
- { Tru64::TGT_O_TRUNC, O_TRUNC },
- { Tru64::TGT_O_EXCL, O_EXCL },
- { Tru64::TGT_O_NONBLOCK, O_NONBLOCK },
- { Tru64::TGT_O_NOCTTY, O_NOCTTY },
-#ifdef O_SYNC
- { Tru64::TGT_O_SYNC, O_SYNC },
-#endif
-#endif /* _MSC_VER */
-};
-
-const int Tru64::NUM_OPEN_FLAGS = (sizeof(Tru64::openFlagTable)/sizeof(Tru64::openFlagTable[0]));
-
-const char *Tru64::hostname = "m5.eecs.umich.edu";
-
-SyscallDesc Tru64::syscallDescs[] = {
- /* 0 */ SyscallDesc("syscall (#0)", indirectSyscallFunc,
- SyscallDesc::SuppressReturnValue),
- /* 1 */ SyscallDesc("exit", exitFunc),
- /* 2 */ SyscallDesc("fork", unimplementedFunc),
- /* 3 */ SyscallDesc("read", readFunc),
- /* 4 */ SyscallDesc("write", writeFunc),
- /* 5 */ SyscallDesc("old_open", unimplementedFunc),
- /* 6 */ SyscallDesc("close", closeFunc),
- /* 7 */ SyscallDesc("wait4", unimplementedFunc),
- /* 8 */ SyscallDesc("old_creat", unimplementedFunc),
- /* 9 */ SyscallDesc("link", unimplementedFunc),
- /* 10 */ SyscallDesc("unlink", unlinkFunc),
- /* 11 */ SyscallDesc("execv", unimplementedFunc),
- /* 12 */ SyscallDesc("chdir", unimplementedFunc),
- /* 13 */ SyscallDesc("fchdir", unimplementedFunc),
- /* 14 */ SyscallDesc("mknod", unimplementedFunc),
- /* 15 */ SyscallDesc("chmod", unimplementedFunc),
- /* 16 */ SyscallDesc("chown", unimplementedFunc),
- /* 17 */ SyscallDesc("obreak", obreakFunc),
- /* 18 */ SyscallDesc("pre_F64_getfsstat", unimplementedFunc),
- /* 19 */ SyscallDesc("lseek", lseekFunc),
- /* 20 */ SyscallDesc("getpid", getpidFunc),
- /* 21 */ SyscallDesc("mount", unimplementedFunc),
- /* 22 */ SyscallDesc("unmount", unimplementedFunc),
- /* 23 */ SyscallDesc("setuid", setuidFunc),
- /* 24 */ SyscallDesc("getuid", getuidFunc),
- /* 25 */ SyscallDesc("exec_with_loader", unimplementedFunc),
- /* 26 */ SyscallDesc("ptrace", unimplementedFunc),
- /* 27 */ SyscallDesc("recvmsg", unimplementedFunc),
- /* 28 */ SyscallDesc("sendmsg", unimplementedFunc),
- /* 29 */ SyscallDesc("recvfrom", unimplementedFunc),
- /* 30 */ SyscallDesc("accept", unimplementedFunc),
- /* 31 */ SyscallDesc("getpeername", unimplementedFunc),
- /* 32 */ SyscallDesc("getsockname", unimplementedFunc),
- /* 33 */ SyscallDesc("access", unimplementedFunc),
- /* 34 */ SyscallDesc("chflags", unimplementedFunc),
- /* 35 */ SyscallDesc("fchflags", unimplementedFunc),
- /* 36 */ SyscallDesc("sync", unimplementedFunc),
- /* 37 */ SyscallDesc("kill", unimplementedFunc),
- /* 38 */ SyscallDesc("old_stat", unimplementedFunc),
- /* 39 */ SyscallDesc("setpgid", unimplementedFunc),
- /* 40 */ SyscallDesc("old_lstat", unimplementedFunc),
- /* 41 */ SyscallDesc("dup", unimplementedFunc),
- /* 42 */ SyscallDesc("pipe", unimplementedFunc),
- /* 43 */ SyscallDesc("set_program_attributes", unimplementedFunc),
- /* 44 */ SyscallDesc("profil", unimplementedFunc),
- /* 45 */ SyscallDesc("open", openFunc<Tru64>),
- /* 46 */ SyscallDesc("obsolete osigaction", unimplementedFunc),
- /* 47 */ SyscallDesc("getgid", getgidFunc),
- /* 48 */ SyscallDesc("sigprocmask", ignoreFunc),
- /* 49 */ SyscallDesc("getlogin", unimplementedFunc),
- /* 50 */ SyscallDesc("setlogin", unimplementedFunc),
- /* 51 */ SyscallDesc("acct", unimplementedFunc),
- /* 52 */ SyscallDesc("sigpending", unimplementedFunc),
- /* 53 */ SyscallDesc("classcntl", unimplementedFunc),
- /* 54 */ SyscallDesc("ioctl", ioctlFunc<Tru64>),
- /* 55 */ SyscallDesc("reboot", unimplementedFunc),
- /* 56 */ SyscallDesc("revoke", unimplementedFunc),
- /* 57 */ SyscallDesc("symlink", unimplementedFunc),
- /* 58 */ SyscallDesc("readlink", unimplementedFunc),
- /* 59 */ SyscallDesc("execve", unimplementedFunc),
- /* 60 */ SyscallDesc("umask", unimplementedFunc),
- /* 61 */ SyscallDesc("chroot", unimplementedFunc),
- /* 62 */ SyscallDesc("old_fstat", unimplementedFunc),
- /* 63 */ SyscallDesc("getpgrp", unimplementedFunc),
- /* 64 */ SyscallDesc("getpagesize", getpagesizeFunc),
- /* 65 */ SyscallDesc("mremap", unimplementedFunc),
- /* 66 */ SyscallDesc("vfork", unimplementedFunc),
- /* 67 */ SyscallDesc("pre_F64_stat", statFunc<Tru64::PreF64>),
- /* 68 */ SyscallDesc("pre_F64_lstat", lstatFunc<Tru64::PreF64>),
- /* 69 */ SyscallDesc("sbrk", unimplementedFunc),
- /* 70 */ SyscallDesc("sstk", unimplementedFunc),
- /* 71 */ SyscallDesc("mmap", mmapFunc<Tru64>),
- /* 72 */ SyscallDesc("ovadvise", unimplementedFunc),
- /* 73 */ SyscallDesc("munmap", munmapFunc),
- /* 74 */ SyscallDesc("mprotect", ignoreFunc),
- /* 75 */ SyscallDesc("madvise", unimplementedFunc),
- /* 76 */ SyscallDesc("old_vhangup", unimplementedFunc),
- /* 77 */ SyscallDesc("kmodcall", unimplementedFunc),
- /* 78 */ SyscallDesc("mincore", unimplementedFunc),
- /* 79 */ SyscallDesc("getgroups", unimplementedFunc),
- /* 80 */ SyscallDesc("setgroups", unimplementedFunc),
- /* 81 */ SyscallDesc("old_getpgrp", unimplementedFunc),
- /* 82 */ SyscallDesc("setpgrp", unimplementedFunc),
- /* 83 */ SyscallDesc("setitimer", unimplementedFunc),
- /* 84 */ SyscallDesc("old_wait", unimplementedFunc),
- /* 85 */ SyscallDesc("table", tableFunc),
- /* 86 */ SyscallDesc("getitimer", unimplementedFunc),
- /* 87 */ SyscallDesc("gethostname", gethostnameFunc),
- /* 88 */ SyscallDesc("sethostname", unimplementedFunc),
- /* 89 */ SyscallDesc("getdtablesize", unimplementedFunc),
- /* 90 */ SyscallDesc("dup2", unimplementedFunc),
- /* 91 */ SyscallDesc("pre_F64_fstat", fstatFunc<Tru64::PreF64>),
- /* 92 */ SyscallDesc("fcntl", fcntlFunc),
- /* 93 */ SyscallDesc("select", unimplementedFunc),
- /* 94 */ SyscallDesc("poll", unimplementedFunc),
- /* 95 */ SyscallDesc("fsync", unimplementedFunc),
- /* 96 */ SyscallDesc("setpriority", unimplementedFunc),
- /* 97 */ SyscallDesc("socket", unimplementedFunc),
- /* 98 */ SyscallDesc("connect", unimplementedFunc),
- /* 99 */ SyscallDesc("old_accept", unimplementedFunc),
- /* 100 */ SyscallDesc("getpriority", unimplementedFunc),
- /* 101 */ SyscallDesc("old_send", unimplementedFunc),
- /* 102 */ SyscallDesc("old_recv", unimplementedFunc),
- /* 103 */ SyscallDesc("sigreturn", sigreturnFunc,
- SyscallDesc::SuppressReturnValue),
- /* 104 */ SyscallDesc("bind", unimplementedFunc),
- /* 105 */ SyscallDesc("setsockopt", unimplementedFunc),
- /* 106 */ SyscallDesc("listen", unimplementedFunc),
- /* 107 */ SyscallDesc("plock", unimplementedFunc),
- /* 108 */ SyscallDesc("old_sigvec", unimplementedFunc),
- /* 109 */ SyscallDesc("old_sigblock", unimplementedFunc),
- /* 110 */ SyscallDesc("old_sigsetmask", unimplementedFunc),
- /* 111 */ SyscallDesc("sigsuspend", unimplementedFunc),
- /* 112 */ SyscallDesc("sigstack", ignoreFunc),
- /* 113 */ SyscallDesc("old_recvmsg", unimplementedFunc),
- /* 114 */ SyscallDesc("old_sendmsg", unimplementedFunc),
- /* 115 */ SyscallDesc("obsolete vtrace", unimplementedFunc),
- /* 116 */ SyscallDesc("gettimeofday", gettimeofdayFunc<Tru64>),
- /* 117 */ SyscallDesc("getrusage", getrusageFunc<Tru64>),
- /* 118 */ SyscallDesc("getsockopt", unimplementedFunc),
- /* 119 */ SyscallDesc("numa_syscalls", unimplementedFunc),
- /* 120 */ SyscallDesc("readv", unimplementedFunc),
- /* 121 */ SyscallDesc("writev", unimplementedFunc),
- /* 122 */ SyscallDesc("settimeofday", unimplementedFunc),
- /* 123 */ SyscallDesc("fchown", unimplementedFunc),
- /* 124 */ SyscallDesc("fchmod", unimplementedFunc),
- /* 125 */ SyscallDesc("old_recvfrom", unimplementedFunc),
- /* 126 */ SyscallDesc("setreuid", unimplementedFunc),
- /* 127 */ SyscallDesc("setregid", unimplementedFunc),
- /* 128 */ SyscallDesc("rename", renameFunc),
- /* 129 */ SyscallDesc("truncate", truncateFunc),
- /* 130 */ SyscallDesc("ftruncate", ftruncateFunc),
- /* 131 */ SyscallDesc("flock", unimplementedFunc),
- /* 132 */ SyscallDesc("setgid", unimplementedFunc),
- /* 133 */ SyscallDesc("sendto", unimplementedFunc),
- /* 134 */ SyscallDesc("shutdown", unimplementedFunc),
- /* 135 */ SyscallDesc("socketpair", unimplementedFunc),
- /* 136 */ SyscallDesc("mkdir", unimplementedFunc),
- /* 137 */ SyscallDesc("rmdir", unimplementedFunc),
- /* 138 */ SyscallDesc("utimes", unimplementedFunc),
- /* 139 */ SyscallDesc("obsolete 4.2 sigreturn", unimplementedFunc),
- /* 140 */ SyscallDesc("adjtime", unimplementedFunc),
- /* 141 */ SyscallDesc("old_getpeername", unimplementedFunc),
- /* 142 */ SyscallDesc("gethostid", unimplementedFunc),
- /* 143 */ SyscallDesc("sethostid", unimplementedFunc),
- /* 144 */ SyscallDesc("getrlimit", getrlimitFunc<Tru64>),
- /* 145 */ SyscallDesc("setrlimit", ignoreFunc),
- /* 146 */ SyscallDesc("old_killpg", unimplementedFunc),
- /* 147 */ SyscallDesc("setsid", unimplementedFunc),
- /* 148 */ SyscallDesc("quotactl", unimplementedFunc),
- /* 149 */ SyscallDesc("oldquota", unimplementedFunc),
- /* 150 */ SyscallDesc("old_getsockname", unimplementedFunc),
- /* 151 */ SyscallDesc("pread", unimplementedFunc),
- /* 152 */ SyscallDesc("pwrite", unimplementedFunc),
- /* 153 */ SyscallDesc("pid_block", unimplementedFunc),
- /* 154 */ SyscallDesc("pid_unblock", unimplementedFunc),
- /* 155 */ SyscallDesc("signal_urti", unimplementedFunc),
- /* 156 */ SyscallDesc("sigaction", ignoreFunc),
- /* 157 */ SyscallDesc("sigwaitprim", unimplementedFunc),
- /* 158 */ SyscallDesc("nfssvc", unimplementedFunc),
- /* 159 */ SyscallDesc("getdirentries", getdirentriesFunc),
- /* 160 */ SyscallDesc("pre_F64_statfs", statfsFunc<Tru64::PreF64>),
- /* 161 */ SyscallDesc("pre_F64_fstatfs", fstatfsFunc<Tru64::PreF64>),
- /* 162 */ SyscallDesc("unknown #162", unimplementedFunc),
- /* 163 */ SyscallDesc("async_daemon", unimplementedFunc),
- /* 164 */ SyscallDesc("getfh", unimplementedFunc),
- /* 165 */ SyscallDesc("getdomainname", unimplementedFunc),
- /* 166 */ SyscallDesc("setdomainname", unimplementedFunc),
- /* 167 */ SyscallDesc("unknown #167", unimplementedFunc),
- /* 168 */ SyscallDesc("unknown #168", unimplementedFunc),
- /* 169 */ SyscallDesc("exportfs", unimplementedFunc),
- /* 170 */ SyscallDesc("unknown #170", unimplementedFunc),
- /* 171 */ SyscallDesc("unknown #171", unimplementedFunc),
- /* 172 */ SyscallDesc("unknown #172", unimplementedFunc),
- /* 173 */ SyscallDesc("unknown #173", unimplementedFunc),
- /* 174 */ SyscallDesc("unknown #174", unimplementedFunc),
- /* 175 */ SyscallDesc("unknown #175", unimplementedFunc),
- /* 176 */ SyscallDesc("unknown #176", unimplementedFunc),
- /* 177 */ SyscallDesc("unknown #177", unimplementedFunc),
- /* 178 */ SyscallDesc("unknown #178", unimplementedFunc),
- /* 179 */ SyscallDesc("unknown #179", unimplementedFunc),
- /* 180 */ SyscallDesc("unknown #180", unimplementedFunc),
- /* 181 */ SyscallDesc("alt_plock", unimplementedFunc),
- /* 182 */ SyscallDesc("unknown #182", unimplementedFunc),
- /* 183 */ SyscallDesc("unknown #183", unimplementedFunc),
- /* 184 */ SyscallDesc("getmnt", unimplementedFunc),
- /* 185 */ SyscallDesc("unknown #185", unimplementedFunc),
- /* 186 */ SyscallDesc("unknown #186", unimplementedFunc),
- /* 187 */ SyscallDesc("alt_sigpending", unimplementedFunc),
- /* 188 */ SyscallDesc("alt_setsid", unimplementedFunc),
- /* 189 */ SyscallDesc("unknown #189", unimplementedFunc),
- /* 190 */ SyscallDesc("unknown #190", unimplementedFunc),
- /* 191 */ SyscallDesc("unknown #191", unimplementedFunc),
- /* 192 */ SyscallDesc("unknown #192", unimplementedFunc),
- /* 193 */ SyscallDesc("unknown #193", unimplementedFunc),
- /* 194 */ SyscallDesc("unknown #194", unimplementedFunc),
- /* 195 */ SyscallDesc("unknown #195", unimplementedFunc),
- /* 196 */ SyscallDesc("unknown #196", unimplementedFunc),
- /* 197 */ SyscallDesc("unknown #197", unimplementedFunc),
- /* 198 */ SyscallDesc("unknown #198", unimplementedFunc),
- /* 199 */ SyscallDesc("swapon", unimplementedFunc),
- /* 200 */ SyscallDesc("msgctl", unimplementedFunc),
- /* 201 */ SyscallDesc("msgget", unimplementedFunc),
- /* 202 */ SyscallDesc("msgrcv", unimplementedFunc),
- /* 203 */ SyscallDesc("msgsnd", unimplementedFunc),
- /* 204 */ SyscallDesc("semctl", unimplementedFunc),
- /* 205 */ SyscallDesc("semget", unimplementedFunc),
- /* 206 */ SyscallDesc("semop", unimplementedFunc),
- /* 207 */ SyscallDesc("uname", unameFunc),
- /* 208 */ SyscallDesc("lchown", unimplementedFunc),
- /* 209 */ SyscallDesc("shmat", unimplementedFunc),
- /* 210 */ SyscallDesc("shmctl", unimplementedFunc),
- /* 211 */ SyscallDesc("shmdt", unimplementedFunc),
- /* 212 */ SyscallDesc("shmget", unimplementedFunc),
- /* 213 */ SyscallDesc("mvalid", unimplementedFunc),
- /* 214 */ SyscallDesc("getaddressconf", unimplementedFunc),
- /* 215 */ SyscallDesc("msleep", unimplementedFunc),
- /* 216 */ SyscallDesc("mwakeup", unimplementedFunc),
- /* 217 */ SyscallDesc("msync", unimplementedFunc),
- /* 218 */ SyscallDesc("signal", unimplementedFunc),
- /* 219 */ SyscallDesc("utc_gettime", unimplementedFunc),
- /* 220 */ SyscallDesc("utc_adjtime", unimplementedFunc),
- /* 221 */ SyscallDesc("unknown #221", unimplementedFunc),
- /* 222 */ SyscallDesc("security", unimplementedFunc),
- /* 223 */ SyscallDesc("kloadcall", unimplementedFunc),
- /* 224 */ SyscallDesc("stat", statFunc<Tru64::F64>),
- /* 225 */ SyscallDesc("lstat", lstatFunc<Tru64::F64>),
- /* 226 */ SyscallDesc("fstat", fstatFunc<Tru64::F64>),
- /* 227 */ SyscallDesc("statfs", statfsFunc<Tru64::F64>),
- /* 228 */ SyscallDesc("fstatfs", fstatfsFunc<Tru64::F64>),
- /* 229 */ SyscallDesc("getfsstat", unimplementedFunc),
- /* 230 */ SyscallDesc("gettimeofday64", unimplementedFunc),
- /* 231 */ SyscallDesc("settimeofday64", unimplementedFunc),
- /* 232 */ SyscallDesc("unknown #232", unimplementedFunc),
- /* 233 */ SyscallDesc("getpgid", unimplementedFunc),
- /* 234 */ SyscallDesc("getsid", unimplementedFunc),
- /* 235 */ SyscallDesc("sigaltstack", ignoreFunc),
- /* 236 */ SyscallDesc("waitid", unimplementedFunc),
- /* 237 */ SyscallDesc("priocntlset", unimplementedFunc),
- /* 238 */ SyscallDesc("sigsendset", unimplementedFunc),
- /* 239 */ SyscallDesc("set_speculative", unimplementedFunc),
- /* 240 */ SyscallDesc("msfs_syscall", unimplementedFunc),
- /* 241 */ SyscallDesc("sysinfo", unimplementedFunc),
- /* 242 */ SyscallDesc("uadmin", unimplementedFunc),
- /* 243 */ SyscallDesc("fuser", unimplementedFunc),
- /* 244 */ SyscallDesc("proplist_syscall", unimplementedFunc),
- /* 245 */ SyscallDesc("ntp_adjtime", unimplementedFunc),
- /* 246 */ SyscallDesc("ntp_gettime", unimplementedFunc),
- /* 247 */ SyscallDesc("pathconf", unimplementedFunc),
- /* 248 */ SyscallDesc("fpathconf", unimplementedFunc),
- /* 249 */ SyscallDesc("sync2", unimplementedFunc),
- /* 250 */ SyscallDesc("uswitch", unimplementedFunc),
- /* 251 */ SyscallDesc("usleep_thread", unimplementedFunc),
- /* 252 */ SyscallDesc("audcntl", unimplementedFunc),
- /* 253 */ SyscallDesc("audgen", unimplementedFunc),
- /* 254 */ SyscallDesc("sysfs", unimplementedFunc),
- /* 255 */ SyscallDesc("subsys_info", unimplementedFunc),
- /* 256 */ SyscallDesc("getsysinfo", getsysinfoFunc),
- /* 257 */ SyscallDesc("setsysinfo", setsysinfoFunc),
- /* 258 */ SyscallDesc("afs_syscall", unimplementedFunc),
- /* 259 */ SyscallDesc("swapctl", unimplementedFunc),
- /* 260 */ SyscallDesc("memcntl", unimplementedFunc),
- /* 261 */ SyscallDesc("fdatasync", unimplementedFunc),
- /* 262 */ SyscallDesc("oflock", unimplementedFunc),
- /* 263 */ SyscallDesc("F64_readv", unimplementedFunc),
- /* 264 */ SyscallDesc("F64_writev", unimplementedFunc),
- /* 265 */ SyscallDesc("cdslxlate", unimplementedFunc),
- /* 266 */ SyscallDesc("sendfile", unimplementedFunc),
-};
-
-const int Tru64::Num_Syscall_Descs =
- sizeof(Tru64::syscallDescs) / sizeof(SyscallDesc);
-
-const int Tru64::Max_Syscall_Desc = Tru64::Num_Syscall_Descs - 1;
-
-SyscallDesc Tru64::machSyscallDescs[] = {
- /* 0 */ SyscallDesc("kern_invalid", unimplementedFunc),
- /* 1 */ SyscallDesc("m5_mutex_lock", m5_mutex_lockFunc),
- /* 2 */ SyscallDesc("m5_mutex_trylock", m5_mutex_trylockFunc),
- /* 3 */ SyscallDesc("m5_mutex_unlock", m5_mutex_unlockFunc),
- /* 4 */ SyscallDesc("m5_cond_signal", m5_cond_signalFunc),
- /* 5 */ SyscallDesc("m5_cond_broadcast", m5_cond_broadcastFunc),
- /* 6 */ SyscallDesc("m5_cond_wait", m5_cond_waitFunc),
- /* 7 */ SyscallDesc("m5_thread_exit", m5_thread_exitFunc),
- /* 8 */ SyscallDesc("kern_invalid", unimplementedFunc),
- /* 9 */ SyscallDesc("kern_invalid", unimplementedFunc),
- /* 10 */ SyscallDesc("task_self", unimplementedFunc),
- /* 11 */ SyscallDesc("thread_reply", unimplementedFunc),
- /* 12 */ SyscallDesc("task_notify", unimplementedFunc),
- /* 13 */ SyscallDesc("thread_self", unimplementedFunc),
- /* 14 */ SyscallDesc("kern_invalid", unimplementedFunc),
- /* 15 */ SyscallDesc("kern_invalid", unimplementedFunc),
- /* 16 */ SyscallDesc("kern_invalid", unimplementedFunc),
- /* 17 */ SyscallDesc("kern_invalid", unimplementedFunc),
- /* 18 */ SyscallDesc("kern_invalid", unimplementedFunc),
- /* 19 */ SyscallDesc("kern_invalid", unimplementedFunc),
- /* 20 */ SyscallDesc("msg_send_trap", unimplementedFunc),
- /* 21 */ SyscallDesc("msg_receive_trap", unimplementedFunc),
- /* 22 */ SyscallDesc("msg_rpc_trap", unimplementedFunc),
- /* 23 */ SyscallDesc("kern_invalid", unimplementedFunc),
- /* 24 */ SyscallDesc("nxm_block", nxm_blockFunc),
- /* 25 */ SyscallDesc("nxm_unblock", nxm_unblockFunc),
- /* 26 */ SyscallDesc("kern_invalid", unimplementedFunc),
- /* 27 */ SyscallDesc("kern_invalid", unimplementedFunc),
- /* 28 */ SyscallDesc("kern_invalid", unimplementedFunc),
- /* 29 */ SyscallDesc("nxm_thread_destroy", unimplementedFunc),
- /* 30 */ SyscallDesc("lw_wire", unimplementedFunc),
- /* 31 */ SyscallDesc("lw_unwire", unimplementedFunc),
- /* 32 */ SyscallDesc("nxm_thread_create", nxm_thread_createFunc),
- /* 33 */ SyscallDesc("nxm_task_init", nxm_task_initFunc),
- /* 34 */ SyscallDesc("kern_invalid", unimplementedFunc),
- /* 35 */ SyscallDesc("nxm_idle", nxm_idleFunc),
- /* 36 */ SyscallDesc("nxm_wakeup_idle", unimplementedFunc),
- /* 37 */ SyscallDesc("nxm_set_pthid", unimplementedFunc),
- /* 38 */ SyscallDesc("nxm_thread_kill", unimplementedFunc),
- /* 39 */ SyscallDesc("nxm_thread_block", nxm_thread_blockFunc),
- /* 40 */ SyscallDesc("nxm_thread_wakeup", unimplementedFunc),
- /* 41 */ SyscallDesc("init_process", unimplementedFunc),
- /* 42 */ SyscallDesc("nxm_get_binding", unimplementedFunc),
- /* 43 */ SyscallDesc("map_fd", unimplementedFunc),
- /* 44 */ SyscallDesc("nxm_resched", unimplementedFunc),
- /* 45 */ SyscallDesc("nxm_set_cancel", unimplementedFunc),
- /* 46 */ SyscallDesc("nxm_set_binding", unimplementedFunc),
- /* 47 */ SyscallDesc("stack_create", stack_createFunc),
- /* 48 */ SyscallDesc("nxm_get_state", unimplementedFunc),
- /* 49 */ SyscallDesc("nxm_thread_suspend", unimplementedFunc),
- /* 50 */ SyscallDesc("nxm_thread_resume", unimplementedFunc),
- /* 51 */ SyscallDesc("nxm_signal_check", unimplementedFunc),
- /* 52 */ SyscallDesc("htg_unix_syscall", unimplementedFunc),
- /* 53 */ SyscallDesc("kern_invalid", unimplementedFunc),
- /* 54 */ SyscallDesc("kern_invalid", unimplementedFunc),
- /* 55 */ SyscallDesc("host_self", unimplementedFunc),
- /* 56 */ SyscallDesc("host_priv_self", unimplementedFunc),
- /* 57 */ SyscallDesc("kern_invalid", unimplementedFunc),
- /* 58 */ SyscallDesc("kern_invalid", unimplementedFunc),
- /* 59 */ SyscallDesc("swtch_pri", swtch_priFunc),
- /* 60 */ SyscallDesc("swtch", unimplementedFunc),
- /* 61 */ SyscallDesc("thread_switch", unimplementedFunc),
- /* 62 */ SyscallDesc("semop_fast", unimplementedFunc),
- /* 63 */ SyscallDesc("nxm_pshared_init", unimplementedFunc),
- /* 64 */ SyscallDesc("nxm_pshared_block", unimplementedFunc),
- /* 65 */ SyscallDesc("nxm_pshared_unblock", unimplementedFunc),
- /* 66 */ SyscallDesc("nxm_pshared_destroy", unimplementedFunc),
- /* 67 */ SyscallDesc("nxm_swtch_pri", swtch_priFunc),
- /* 68 */ SyscallDesc("lw_syscall", unimplementedFunc),
- /* 69 */ SyscallDesc("kern_invalid", unimplementedFunc),
- /* 70 */ SyscallDesc("mach_sctimes_0", unimplementedFunc),
- /* 71 */ SyscallDesc("mach_sctimes_1", unimplementedFunc),
- /* 72 */ SyscallDesc("mach_sctimes_2", unimplementedFunc),
- /* 73 */ SyscallDesc("mach_sctimes_3", unimplementedFunc),
- /* 74 */ SyscallDesc("mach_sctimes_4", unimplementedFunc),
- /* 75 */ SyscallDesc("mach_sctimes_5", unimplementedFunc),
- /* 76 */ SyscallDesc("mach_sctimes_6", unimplementedFunc),
- /* 77 */ SyscallDesc("mach_sctimes_7", unimplementedFunc),
- /* 78 */ SyscallDesc("mach_sctimes_8", unimplementedFunc),
- /* 79 */ SyscallDesc("mach_sctimes_9", unimplementedFunc),
- /* 80 */ SyscallDesc("mach_sctimes_10", unimplementedFunc),
- /* 81 */ SyscallDesc("mach_sctimes_11", unimplementedFunc),
- /* 82 */ SyscallDesc("mach_sctimes_port_alloc_dealloc", unimplementedFunc)
-};
-
-const int Tru64::Num_Mach_Syscall_Descs =
- sizeof(Tru64::machSyscallDescs) / sizeof(SyscallDesc);
-const int Tru64::Max_Mach_Syscall_Desc = Tru64::Num_Mach_Syscall_Descs - 1;
-const int Tru64::Min_Syscall_Desc = -Tru64::Max_Mach_Syscall_Desc;
-
-
-void
-AlphaTru64Process::syscall(ExecContext *xc)
-{
- num_syscalls++;
-
- int64_t callnum = xc->regs.intRegFile[ReturnValueReg];
-
- Tru64::doSyscall(callnum, this, xc);
-}
-
-
-AlphaTru64Process::AlphaTru64Process(const std::string &name,
- ObjectFile *objFile,
- System *system,
- int stdin_fd,
- int stdout_fd,
- int stderr_fd,
- std::vector<std::string> &argv,
- std::vector<std::string> &envp)
- : LiveProcess(name, objFile, system, stdin_fd, stdout_fd, stderr_fd,
- argv, envp)
-{
-}
diff --git a/arch/alpha/arguments.cc b/arch/alpha/arguments.cc
index a340a2053..019390aeb 100644
--- a/arch/alpha/arguments.cc
+++ b/arch/alpha/arguments.cc
@@ -31,6 +31,8 @@
#include "cpu/exec_context.hh"
#include "mem/functional/physical.hh"
+using namespace AlphaISA;
+
AlphaArguments::Data::~Data()
{
while (!data.empty()) {
@@ -52,13 +54,13 @@ AlphaArguments::getArg(bool fp)
{
if (number < 6) {
if (fp)
- return xc->regs.floatRegFile.q[16 + number];
+ return xc->readFloatRegInt(16 + number);
else
- return xc->regs.intRegFile[16 + number];
+ return xc->readIntReg(16 + number);
} else {
- Addr sp = xc->regs.intRegFile[30];
+ Addr sp = xc->readIntReg(30);
Addr paddr = vtophys(xc, sp + (number-6) * sizeof(uint64_t));
- return xc->physmem->phys_read_qword(paddr);
+ return xc->getPhysMemPtr()->phys_read_qword(paddr);
}
}
diff --git a/arch/alpha/ev5.cc b/arch/alpha/ev5.cc
index 125affd03..019e83dd4 100644
--- a/arch/alpha/ev5.cc
+++ b/arch/alpha/ev5.cc
@@ -26,7 +26,7 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include "arch/alpha/alpha_memory.hh"
+#include "arch/alpha/tlb.hh"
#include "arch/alpha/isa_traits.hh"
#include "arch/alpha/osfpal.hh"
#include "base/kgdb.h"
@@ -34,6 +34,7 @@
#include "base/stats/events.hh"
#include "config/full_system.hh"
#include "cpu/base.hh"
+#include "cpu/cpu_exec_context.hh"
#include "cpu/exec_context.hh"
#include "cpu/fast/cpu.hh"
#include "kern/kernel_stats.hh"
@@ -46,83 +47,34 @@ using namespace EV5;
////////////////////////////////////////////////////////////////////////
//
-//
-//
-void
-AlphaISA::swap_palshadow(RegFile *regs, bool use_shadow)
-{
- if (regs->pal_shadow == use_shadow)
- panic("swap_palshadow: wrong PAL shadow state");
-
- regs->pal_shadow = use_shadow;
-
- for (int i = 0; i < NumIntRegs; i++) {
- if (reg_redir[i]) {
- IntReg temp = regs->intRegFile[i];
- regs->intRegFile[i] = regs->palregs[i];
- regs->palregs[i] = temp;
- }
- }
-}
-
-////////////////////////////////////////////////////////////////////////
-//
// Machine dependent functions
//
void
-AlphaISA::initCPU(RegFile *regs)
+AlphaISA::initCPU(ExecContext *xc, int cpuId)
{
- initIPRs(regs);
- // CPU comes up with PAL regs enabled
- swap_palshadow(regs, true);
+ initIPRs(xc, cpuId);
- regs->pc = regs->ipr[IPR_PAL_BASE] + fault_addr[Reset_Fault];
- regs->npc = regs->pc + sizeof(MachInst);
-}
+ xc->setIntReg(16, cpuId);
+ xc->setIntReg(0, cpuId);
-////////////////////////////////////////////////////////////////////////
-//
-// alpha exceptions - value equals trap address, update with MD_FAULT_TYPE
-//
-Addr
-AlphaISA::fault_addr[Num_Faults] = {
- 0x0000, /* No_Fault */
- 0x0001, /* Reset_Fault */
- 0x0401, /* Machine_Check_Fault */
- 0x0501, /* Arithmetic_Fault */
- 0x0101, /* Interrupt_Fault */
- 0x0201, /* Ndtb_Miss_Fault */
- 0x0281, /* Pdtb_Miss_Fault */
- 0x0301, /* Alignment_Fault */
- 0x0381, /* DTB_Fault_Fault */
- 0x0381, /* DTB_Acv_Fault */
- 0x0181, /* ITB_Miss_Fault */
- 0x0181, /* ITB_Fault_Fault */
- 0x0081, /* ITB_Acv_Fault */
- 0x0481, /* Unimplemented_Opcode_Fault */
- 0x0581, /* Fen_Fault */
- 0x2001, /* Pal_Fault */
- 0x0501, /* Integer_Overflow_Fault: maps to Arithmetic_Fault */
-};
-
-const int AlphaISA::reg_redir[AlphaISA::NumIntRegs] = {
- /* 0 */ 0, 0, 0, 0, 0, 0, 0, 0,
- /* 8 */ 1, 1, 1, 1, 1, 1, 1, 0,
- /* 16 */ 0, 0, 0, 0, 0, 0, 0, 0,
- /* 24 */ 0, 1, 0, 0, 0, 0, 0, 0 };
+ xc->setPC(xc->readMiscReg(IPR_PAL_BASE) + (new ResetFault)->vect());
+ xc->setNextPC(xc->readPC() + sizeof(MachInst));
+}
////////////////////////////////////////////////////////////////////////
//
//
//
void
-AlphaISA::initIPRs(RegFile *regs)
+AlphaISA::initIPRs(ExecContext *xc, int cpuId)
{
- uint64_t *ipr = regs->ipr;
+ for (int i = 0; i < NumInternalProcRegs; ++i) {
+ xc->setMiscReg(i, 0);
+ }
- bzero((char *)ipr, NumInternalProcRegs * sizeof(InternalProcReg));
- ipr[IPR_PAL_BASE] = PalBase;
- ipr[IPR_MCSR] = 0x6;
+ xc->setMiscReg(IPR_PAL_BASE, PalBase);
+ xc->setMiscReg(IPR_MCSR, 0x6);
+ xc->setMiscReg(IPR_PALtemp16, cpuId);
}
@@ -134,17 +86,16 @@ AlphaISA::processInterrupts(CPU *cpu)
//Handle the interrupts
int ipl = 0;
int summary = 0;
- IntReg *ipr = cpu->getIprPtr();
cpu->checkInterrupts = false;
- if (ipr[IPR_ASTRR])
+ if (cpu->readMiscReg(IPR_ASTRR))
panic("asynchronous traps not implemented\n");
- if (ipr[IPR_SIRR]) {
+ if (cpu->readMiscReg(IPR_SIRR)) {
for (int i = INTLEVEL_SOFTWARE_MIN;
i < INTLEVEL_SOFTWARE_MAX; i++) {
- if (ipr[IPR_SIRR] & (ULL(1) << i)) {
+ if (cpu->readMiscReg(IPR_SIRR) & (ULL(1) << i)) {
// See table 4-19 of the 21164 hardware reference
ipl = (i - INTLEVEL_SOFTWARE_MIN) + 1;
summary |= (ULL(1) << i);
@@ -165,12 +116,12 @@ AlphaISA::processInterrupts(CPU *cpu)
}
}
- if (ipl && ipl > ipr[IPR_IPLR]) {
- ipr[IPR_ISR] = summary;
- ipr[IPR_INTID] = ipl;
- cpu->trap(Interrupt_Fault);
+ if (ipl && ipl > cpu->readMiscReg(IPR_IPLR)) {
+ cpu->setMiscReg(IPR_ISR, summary);
+ cpu->setMiscReg(IPR_INTID, ipl);
+ cpu->trap(new InterruptFault);
DPRINTF(Flow, "Interrupt! IPLR=%d ipl=%d summary=%x\n",
- ipr[IPR_IPLR], ipl, summary);
+ cpu->readMiscReg(IPR_IPLR), ipl, summary);
}
}
@@ -182,96 +133,43 @@ AlphaISA::zeroRegisters(CPU *cpu)
// Insure ISA semantics
// (no longer very clean due to the change in setIntReg() in the
// cpu model. Consider changing later.)
- cpu->xc->setIntReg(ZeroReg, 0);
- cpu->xc->setFloatRegDouble(ZeroReg, 0.0);
+ cpu->cpuXC->setIntReg(ZeroReg, 0);
+ cpu->cpuXC->setFloatRegDouble(ZeroReg, 0.0);
}
-void
-ExecContext::ev5_trap(Fault fault)
+Fault
+CPUExecContext::hwrei()
{
- DPRINTF(Fault, "Fault %s at PC: %#x\n", FaultName(fault), regs.pc);
- cpu->recordEvent(csprintf("Fault %s", FaultName(fault)));
-
- assert(!misspeculating());
- kernelStats->fault(fault);
-
- if (fault == Arithmetic_Fault)
- panic("Arithmetic traps are unimplemented!");
+ if (!inPalMode())
+ return new UnimplementedOpcodeFault;
- AlphaISA::InternalProcReg *ipr = regs.ipr;
+ setNextPC(readMiscReg(AlphaISA::IPR_EXC_ADDR));
- // exception restart address
- if (fault != Interrupt_Fault || !inPalMode())
- ipr[AlphaISA::IPR_EXC_ADDR] = regs.pc;
+ if (!misspeculating()) {
+ cpu->kernelStats->hwrei();
- if (fault == Pal_Fault || fault == Arithmetic_Fault /* ||
- fault == Interrupt_Fault && !inPalMode() */) {
- // traps... skip faulting instruction
- ipr[AlphaISA::IPR_EXC_ADDR] += 4;
+ cpu->checkInterrupts = true;
}
- if (!inPalMode())
- AlphaISA::swap_palshadow(&regs, true);
-
- regs.pc = ipr[AlphaISA::IPR_PAL_BASE] + AlphaISA::fault_addr[fault];
- regs.npc = regs.pc + sizeof(MachInst);
+ // FIXME: XXX check for interrupts? XXX
+ return NoFault;
}
-
-void
-AlphaISA::intr_post(RegFile *regs, Fault fault, Addr pc)
+int
+AlphaISA::MiscRegFile::getInstAsid()
{
- InternalProcReg *ipr = regs->ipr;
- bool use_pc = (fault == No_Fault);
-
- if (fault == Arithmetic_Fault)
- panic("arithmetic faults NYI...");
-
- // compute exception restart address
- if (use_pc || fault == Pal_Fault || fault == Arithmetic_Fault) {
- // traps... skip faulting instruction
- ipr[IPR_EXC_ADDR] = regs->pc + 4;
- } else {
- // fault, post fault at excepting instruction
- ipr[IPR_EXC_ADDR] = regs->pc;
- }
-
- // jump to expection address (PAL PC bit set here as well...)
- if (!use_pc)
- regs->npc = ipr[IPR_PAL_BASE] + fault_addr[fault];
- else
- regs->npc = ipr[IPR_PAL_BASE] + pc;
-
- // that's it! (orders of magnitude less painful than x86)
+ return EV5::ITB_ASN_ASN(ipr[IPR_ITB_ASN]);
}
-Fault
-ExecContext::hwrei()
+int
+AlphaISA::MiscRegFile::getDataAsid()
{
- uint64_t *ipr = regs.ipr;
-
- if (!inPalMode())
- return Unimplemented_Opcode_Fault;
-
- setNextPC(ipr[AlphaISA::IPR_EXC_ADDR]);
-
- if (!misspeculating()) {
- kernelStats->hwrei();
-
- if ((ipr[AlphaISA::IPR_EXC_ADDR] & 1) == 0)
- AlphaISA::swap_palshadow(&regs, false);
-
- cpu->checkInterrupts = true;
- }
-
- // FIXME: XXX check for interrupts? XXX
- return No_Fault;
+ return EV5::DTB_ASN_ASN(ipr[IPR_DTB_ASN]);
}
-uint64_t
-ExecContext::readIpr(int idx, Fault &fault)
+AlphaISA::MiscReg
+AlphaISA::MiscRegFile::readIpr(int idx, Fault &fault, ExecContext *xc)
{
- uint64_t *ipr = regs.ipr;
uint64_t retval = 0; // return value, default 0
switch (idx) {
@@ -324,7 +222,7 @@ ExecContext::readIpr(int idx, Fault &fault)
case AlphaISA::IPR_CC:
retval |= ipr[idx] & ULL(0xffffffff00000000);
- retval |= cpu->curCycle() & ULL(0x00000000ffffffff);
+ retval |= xc->getCpuPtr()->curCycle() & ULL(0x00000000ffffffff);
break;
case AlphaISA::IPR_VA:
@@ -341,7 +239,7 @@ ExecContext::readIpr(int idx, Fault &fault)
case AlphaISA::IPR_DTB_PTE:
{
- AlphaISA::PTE &pte = dtb->index(!misspeculating());
+ AlphaISA::PTE &pte = xc->getDTBPtr()->index(!xc->misspeculating());
retval |= ((u_int64_t)pte.ppn & ULL(0x7ffffff)) << 32;
retval |= ((u_int64_t)pte.xre & ULL(0xf)) << 8;
@@ -363,12 +261,12 @@ ExecContext::readIpr(int idx, Fault &fault)
case AlphaISA::IPR_DTB_IAP:
case AlphaISA::IPR_ITB_IA:
case AlphaISA::IPR_ITB_IAP:
- fault = Unimplemented_Opcode_Fault;
+ fault = new UnimplementedOpcodeFault;
break;
default:
// invalid IPR
- fault = Unimplemented_Opcode_Fault;
+ fault = new UnimplementedOpcodeFault;
break;
}
@@ -381,13 +279,12 @@ int break_ipl = -1;
#endif
Fault
-ExecContext::setIpr(int idx, uint64_t val)
+AlphaISA::MiscRegFile::setIpr(int idx, uint64_t val, ExecContext *xc)
{
- uint64_t *ipr = regs.ipr;
uint64_t old;
- if (misspeculating())
- return No_Fault;
+ if (xc->misspeculating())
+ return NoFault;
switch (idx) {
case AlphaISA::IPR_PALtemp0:
@@ -439,7 +336,7 @@ ExecContext::setIpr(int idx, uint64_t val)
// write entire quad w/ no side-effect
old = ipr[idx];
ipr[idx] = val;
- kernelStats->context(old, val);
+ xc->getCpuPtr()->kernelStats->context(old, val, xc);
break;
case AlphaISA::IPR_DTB_PTE:
@@ -466,14 +363,14 @@ ExecContext::setIpr(int idx, uint64_t val)
// only write least significant five bits - interrupt level
ipr[idx] = val & 0x1f;
- kernelStats->swpipl(ipr[idx]);
+ xc->getCpuPtr()->kernelStats->swpipl(ipr[idx]);
break;
case AlphaISA::IPR_DTB_CM:
if (val & 0x18)
- kernelStats->mode(Kernel::user);
+ xc->getCpuPtr()->kernelStats->mode(Kernel::user, xc);
else
- kernelStats->mode(Kernel::kernel);
+ xc->getCpuPtr()->kernelStats->mode(Kernel::kernel, xc);
case AlphaISA::IPR_ICM:
// only write two mode bits - processor mode
@@ -533,7 +430,7 @@ ExecContext::setIpr(int idx, uint64_t val)
case AlphaISA::IPR_ITB_PTE_TEMP:
case AlphaISA::IPR_DTB_PTE_TEMP:
// read-only registers
- return Unimplemented_Opcode_Fault;
+ return new UnimplementedOpcodeFault;
case AlphaISA::IPR_HWINT_CLR:
case AlphaISA::IPR_SL_XMIT:
@@ -547,21 +444,22 @@ ExecContext::setIpr(int idx, uint64_t val)
// really a control write
ipr[idx] = 0;
- dtb->flushAll();
+ xc->getDTBPtr()->flushAll();
break;
case AlphaISA::IPR_DTB_IAP:
// really a control write
ipr[idx] = 0;
- dtb->flushProcesses();
+ xc->getDTBPtr()->flushProcesses();
break;
case AlphaISA::IPR_DTB_IS:
// really a control write
ipr[idx] = val;
- dtb->flushAddr(val, DTB_ASN_ASN(ipr[AlphaISA::IPR_DTB_ASN]));
+ xc->getDTBPtr()->flushAddr(val,
+ DTB_ASN_ASN(ipr[AlphaISA::IPR_DTB_ASN]));
break;
case AlphaISA::IPR_DTB_TAG: {
@@ -584,7 +482,7 @@ ExecContext::setIpr(int idx, uint64_t val)
pte.asn = DTB_ASN_ASN(ipr[AlphaISA::IPR_DTB_ASN]);
// insert new TAG/PTE value into data TLB
- dtb->insert(val, pte);
+ xc->getDTBPtr()->insert(val, pte);
}
break;
@@ -608,7 +506,7 @@ ExecContext::setIpr(int idx, uint64_t val)
pte.asn = ITB_ASN_ASN(ipr[AlphaISA::IPR_ITB_ASN]);
// insert new TAG/PTE value into data TLB
- itb->insert(ipr[AlphaISA::IPR_ITB_TAG], pte);
+ xc->getITBPtr()->insert(ipr[AlphaISA::IPR_ITB_TAG], pte);
}
break;
@@ -616,30 +514,39 @@ ExecContext::setIpr(int idx, uint64_t val)
// really a control write
ipr[idx] = 0;
- itb->flushAll();
+ xc->getITBPtr()->flushAll();
break;
case AlphaISA::IPR_ITB_IAP:
// really a control write
ipr[idx] = 0;
- itb->flushProcesses();
+ xc->getITBPtr()->flushProcesses();
break;
case AlphaISA::IPR_ITB_IS:
// really a control write
ipr[idx] = val;
- itb->flushAddr(val, ITB_ASN_ASN(ipr[AlphaISA::IPR_ITB_ASN]));
+ xc->getITBPtr()->flushAddr(val,
+ ITB_ASN_ASN(ipr[AlphaISA::IPR_ITB_ASN]));
break;
default:
// invalid IPR
- return Unimplemented_Opcode_Fault;
+ return new UnimplementedOpcodeFault;
}
// no error...
- return No_Fault;
+ return NoFault;
+}
+
+void
+AlphaISA::MiscRegFile::copyIprs(ExecContext *xc)
+{
+ for (int i = IPR_Base_DepTag; i < NumInternalProcRegs; ++i) {
+ ipr[i] = xc->readMiscReg(i);
+ }
}
/**
@@ -647,9 +554,9 @@ ExecContext::setIpr(int idx, uint64_t val)
* If return value is false, actual PAL call will be suppressed.
*/
bool
-ExecContext::simPalCheck(int palFunc)
+CPUExecContext::simPalCheck(int palFunc)
{
- kernelStats->callpal(palFunc);
+ cpu->kernelStats->callpal(palFunc, proxy);
switch (palFunc) {
case PAL::halt:
diff --git a/arch/alpha/ev5.hh b/arch/alpha/ev5.hh
index 5173b364f..7c8465cfb 100644
--- a/arch/alpha/ev5.hh
+++ b/arch/alpha/ev5.hh
@@ -30,9 +30,13 @@
#define __ARCH_ALPHA_EV5_HH__
#include "config/alpha_tlaser.hh"
+#include "arch/alpha/isa_traits.hh"
namespace EV5 {
+//It seems like a safe assumption EV5 only applies to alpha
+using namespace AlphaISA;
+
#if ALPHA_TLASER
const uint64_t AsnMask = ULL(0x7f);
#else
diff --git a/arch/alpha/faults.cc b/arch/alpha/faults.cc
index 3aecf029d..e0918da21 100644
--- a/arch/alpha/faults.cc
+++ b/arch/alpha/faults.cc
@@ -27,35 +27,105 @@
*/
#include "arch/alpha/faults.hh"
+#include "cpu/exec_context.hh"
+#include "cpu/base.hh"
+#include "base/trace.hh"
-namespace {
- const char *
- fault_name[Num_Faults] = {
- "none",
- "reset",
- "mchk",
- "arith",
- "interrupt",
- "dtb_miss_single",
- "dtb_miss_double",
- "unalign",
- "dfault",
- "dfault",
- "itbmiss",
- "itbmiss",
- "iaccvio",
- "opdec",
- "fen",
- "pal",
- };
-}
+namespace AlphaISA
+{
+
+FaultName MachineCheckFault::_name = "mchk";
+FaultVect MachineCheckFault::_vect = 0x0401;
+FaultStat MachineCheckFault::_count;
+
+FaultName AlignmentFault::_name = "unalign";
+FaultVect AlignmentFault::_vect = 0x0301;
+FaultStat AlignmentFault::_count;
+
+FaultName ResetFault::_name = "reset";
+FaultVect ResetFault::_vect = 0x0001;
+FaultStat ResetFault::_count;
+
+FaultName ArithmeticFault::_name = "arith";
+FaultVect ArithmeticFault::_vect = 0x0501;
+FaultStat ArithmeticFault::_count;
+
+FaultName InterruptFault::_name = "interrupt";
+FaultVect InterruptFault::_vect = 0x0101;
+FaultStat InterruptFault::_count;
+
+FaultName NDtbMissFault::_name = "dtb_miss_single";
+FaultVect NDtbMissFault::_vect = 0x0201;
+FaultStat NDtbMissFault::_count;
+
+FaultName PDtbMissFault::_name = "dtb_miss_double";
+FaultVect PDtbMissFault::_vect = 0x0281;
+FaultStat PDtbMissFault::_count;
+
+FaultName DtbPageFault::_name = "dfault";
+FaultVect DtbPageFault::_vect = 0x0381;
+FaultStat DtbPageFault::_count;
+
+FaultName DtbAcvFault::_name = "dfault";
+FaultVect DtbAcvFault::_vect = 0x0381;
+FaultStat DtbAcvFault::_count;
+
+FaultName ItbMissFault::_name = "itbmiss";
+FaultVect ItbMissFault::_vect = 0x0181;
+FaultStat ItbMissFault::_count;
+
+FaultName ItbPageFault::_name = "itbmiss";
+FaultVect ItbPageFault::_vect = 0x0181;
+FaultStat ItbPageFault::_count;
-const char *
-FaultName(int index)
+FaultName ItbAcvFault::_name = "iaccvio";
+FaultVect ItbAcvFault::_vect = 0x0081;
+FaultStat ItbAcvFault::_count;
+
+FaultName UnimplementedOpcodeFault::_name = "opdec";
+FaultVect UnimplementedOpcodeFault::_vect = 0x0481;
+FaultStat UnimplementedOpcodeFault::_count;
+
+FaultName FloatEnableFault::_name = "fen";
+FaultVect FloatEnableFault::_vect = 0x0581;
+FaultStat FloatEnableFault::_count;
+
+FaultName PalFault::_name = "pal";
+FaultVect PalFault::_vect = 0x2001;
+FaultStat PalFault::_count;
+
+FaultName IntegerOverflowFault::_name = "intover";
+FaultVect IntegerOverflowFault::_vect = 0x0501;
+FaultStat IntegerOverflowFault::_count;
+
+#if FULL_SYSTEM
+
+void AlphaFault::invoke(ExecContext * xc)
{
- if (index < 0 || index >= Num_Faults)
- return 0;
+ FaultBase::invoke(xc);
+ countStat()++;
+
+ // exception restart address
+ if (setRestartAddress() || !xc->inPalMode())
+ xc->setMiscReg(AlphaISA::IPR_EXC_ADDR, xc->readPC());
- return fault_name[index];
+ if (skipFaultingInstruction()) {
+ // traps... skip faulting instruction.
+ xc->setMiscReg(AlphaISA::IPR_EXC_ADDR,
+ xc->readMiscReg(AlphaISA::IPR_EXC_ADDR) + 4);
+ }
+
+ xc->setPC(xc->readMiscReg(AlphaISA::IPR_PAL_BASE) + vect());
+ xc->setNextPC(xc->readPC() + sizeof(MachInst));
+}
+
+void ArithmeticFault::invoke(ExecContext * xc)
+{
+ FaultBase::invoke(xc);
+ panic("Arithmetic traps are unimplemented!");
}
+#endif
+
+} // namespace AlphaISA
+
diff --git a/arch/alpha/faults.hh b/arch/alpha/faults.hh
index bbac7cbf2..1a196cc94 100644
--- a/arch/alpha/faults.hh
+++ b/arch/alpha/faults.hh
@@ -26,32 +26,244 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef __FAULTS_HH__
-#define __FAULTS_HH__
-
-enum Fault {
- No_Fault,
- Reset_Fault, // processor reset
- Machine_Check_Fault, // machine check (also internal S/W fault)
- Arithmetic_Fault, // FP exception
- Interrupt_Fault, // external interrupt
- Ndtb_Miss_Fault, // DTB miss
- Pdtb_Miss_Fault, // nested DTB miss
- Alignment_Fault, // unaligned access
- DTB_Fault_Fault, // DTB page fault
- DTB_Acv_Fault, // DTB access violation
- ITB_Miss_Fault, // ITB miss
- ITB_Fault_Fault, // ITB page fault
- ITB_Acv_Fault, // ITB access violation
- Unimplemented_Opcode_Fault, // invalid/unimplemented instruction
- Fen_Fault, // FP not-enabled fault
- Pal_Fault, // call_pal S/W interrupt
- Integer_Overflow_Fault,
- Fake_Mem_Fault,
- Num_Faults // number of faults
-};
-
-const char *
-FaultName(int index);
+#ifndef __ALPHA_FAULTS_HH__
+#define __ALPHA_FAULTS_HH__
+
+#include "sim/faults.hh"
+
+// The design of the "name" and "vect" functions is in sim/faults.hh
+
+namespace AlphaISA
+{
+
+typedef const Addr FaultVect;
+
+class AlphaFault : public FaultBase
+{
+ protected:
+ virtual bool skipFaultingInstruction() {return false;}
+ virtual bool setRestartAddress() {return true;}
+ public:
+#if FULL_SYSTEM
+ void invoke(ExecContext * xc);
+#endif
+ virtual FaultVect vect() = 0;
+ virtual FaultStat & countStat() = 0;
+};
+
+class MachineCheckFault : public AlphaFault
+{
+ private:
+ static FaultName _name;
+ static FaultVect _vect;
+ static FaultStat _count;
+ public:
+ FaultName name() {return _name;}
+ FaultVect vect() {return _vect;}
+ FaultStat & countStat() {return _count;}
+ bool isMachineCheckFault() {return true;}
+};
+
+class AlignmentFault : public AlphaFault
+{
+ private:
+ static FaultName _name;
+ static FaultVect _vect;
+ static FaultStat _count;
+ public:
+ FaultName name() {return _name;}
+ FaultVect vect() {return _vect;}
+ FaultStat & countStat() {return _count;}
+ bool isAlignmentFault() {return true;}
+};
+
+static inline Fault genMachineCheckFault()
+{
+ return new MachineCheckFault;
+}
+
+static inline Fault genAlignmentFault()
+{
+ return new AlignmentFault;
+}
+
+class ResetFault : public AlphaFault
+{
+ private:
+ static FaultName _name;
+ static FaultVect _vect;
+ static FaultStat _count;
+ public:
+ FaultName name() {return _name;}
+ FaultVect vect() {return _vect;}
+ FaultStat & countStat() {return _count;}
+};
+
+class ArithmeticFault : public AlphaFault
+{
+ protected:
+ bool skipFaultingInstruction() {return true;}
+ private:
+ static FaultName _name;
+ static FaultVect _vect;
+ static FaultStat _count;
+ public:
+ FaultName name() {return _name;}
+ FaultVect vect() {return _vect;}
+ FaultStat & countStat() {return _count;}
+#if FULL_SYSTEM
+ void invoke(ExecContext * xc);
+#endif
+};
+
+class InterruptFault : public AlphaFault
+{
+ protected:
+ bool setRestartAddress() {return false;}
+ private:
+ static FaultName _name;
+ static FaultVect _vect;
+ static FaultStat _count;
+ public:
+ FaultName name() {return _name;}
+ FaultVect vect() {return _vect;}
+ FaultStat & countStat() {return _count;}
+};
+
+class NDtbMissFault : public AlphaFault
+{
+ private:
+ static FaultName _name;
+ static FaultVect _vect;
+ static FaultStat _count;
+ public:
+ FaultName name() {return _name;}
+ FaultVect vect() {return _vect;}
+ FaultStat & countStat() {return _count;}
+};
+
+class PDtbMissFault : public AlphaFault
+{
+ private:
+ static FaultName _name;
+ static FaultVect _vect;
+ static FaultStat _count;
+ public:
+ FaultName name() {return _name;}
+ FaultVect vect() {return _vect;}
+ FaultStat & countStat() {return _count;}
+};
+
+class DtbPageFault : public AlphaFault
+{
+ private:
+ static FaultName _name;
+ static FaultVect _vect;
+ static FaultStat _count;
+ public:
+ FaultName name() {return _name;}
+ FaultVect vect() {return _vect;}
+ FaultStat & countStat() {return _count;}
+};
+
+class DtbAcvFault : public AlphaFault
+{
+ private:
+ static FaultName _name;
+ static FaultVect _vect;
+ static FaultStat _count;
+ public:
+ FaultName name() {return _name;}
+ FaultVect vect() {return _vect;}
+ FaultStat & countStat() {return _count;}
+};
+
+class ItbMissFault : public AlphaFault
+{
+ private:
+ static FaultName _name;
+ static FaultVect _vect;
+ static FaultStat _count;
+ public:
+ FaultName name() {return _name;}
+ FaultVect vect() {return _vect;}
+ FaultStat & countStat() {return _count;}
+};
+
+class ItbPageFault : public AlphaFault
+{
+ private:
+ static FaultName _name;
+ static FaultVect _vect;
+ static FaultStat _count;
+ public:
+ FaultName name() {return _name;}
+ FaultVect vect() {return _vect;}
+ FaultStat & countStat() {return _count;}
+};
+
+class ItbAcvFault : public AlphaFault
+{
+ private:
+ static FaultName _name;
+ static FaultVect _vect;
+ static FaultStat _count;
+ public:
+ FaultName name() {return _name;}
+ FaultVect vect() {return _vect;}
+ FaultStat & countStat() {return _count;}
+};
+
+class UnimplementedOpcodeFault : public AlphaFault
+{
+ private:
+ static FaultName _name;
+ static FaultVect _vect;
+ static FaultStat _count;
+ public:
+ FaultName name() {return _name;}
+ FaultVect vect() {return _vect;}
+ FaultStat & countStat() {return _count;}
+};
+
+class FloatEnableFault : public AlphaFault
+{
+ private:
+ static FaultName _name;
+ static FaultVect _vect;
+ static FaultStat _count;
+ public:
+ FaultName name() {return _name;}
+ FaultVect vect() {return _vect;}
+ FaultStat & countStat() {return _count;}
+};
+
+class PalFault : public AlphaFault
+{
+ protected:
+ bool skipFaultingInstruction() {return true;}
+ private:
+ static FaultName _name;
+ static FaultVect _vect;
+ static FaultStat _count;
+ public:
+ FaultName name() {return _name;}
+ FaultVect vect() {return _vect;}
+ FaultStat & countStat() {return _count;}
+};
+
+class IntegerOverflowFault : public AlphaFault
+{
+ private:
+ static FaultName _name;
+ static FaultVect _vect;
+ static FaultStat _count;
+ public:
+ FaultName name() {return _name;}
+ FaultVect vect() {return _vect;}
+ FaultStat & countStat() {return _count;}
+};
+
+} // AlphaISA namespace
#endif // __FAULTS_HH__
diff --git a/arch/alpha/freebsd/system.cc b/arch/alpha/freebsd/system.cc
new file mode 100644
index 000000000..e32053afd
--- /dev/null
+++ b/arch/alpha/freebsd/system.cc
@@ -0,0 +1,167 @@
+/*
+ * Copyright (c) 2004-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @file
+ * Modifications for the FreeBSD kernel.
+ * Based on kern/linux/linux_system.cc.
+ *
+ */
+
+#include "arch/alpha/system.hh"
+#include "arch/alpha/freebsd/system.hh"
+#include "base/loader/symtab.hh"
+#include "cpu/exec_context.hh"
+#include "mem/functional/memory_control.hh"
+#include "mem/functional/physical.hh"
+#include "arch/isa_traits.hh"
+#include "sim/builder.hh"
+#include "sim/byteswap.hh"
+#include "arch/vtophys.hh"
+
+#define TIMER_FREQUENCY 1193180
+
+using namespace std;
+using namespace AlphaISA;
+
+FreebsdAlphaSystem::FreebsdAlphaSystem(Params *p)
+ : AlphaSystem(p)
+{
+ /**
+ * Any time DELAY is called just skip the function.
+ * Shouldn't we actually emulate the delay?
+ */
+ skipDelayEvent = addKernelFuncEvent<SkipFuncEvent>("DELAY");
+ skipCalibrateClocks =
+ addKernelFuncEvent<SkipCalibrateClocksEvent>("calibrate_clocks");
+}
+
+
+FreebsdAlphaSystem::~FreebsdAlphaSystem()
+{
+ delete skipDelayEvent;
+ delete skipCalibrateClocks;
+}
+
+
+void
+FreebsdAlphaSystem::doCalibrateClocks(ExecContext *xc)
+{
+ Addr ppc_vaddr = 0;
+ Addr timer_vaddr = 0;
+ Addr ppc_paddr = 0;
+ Addr timer_paddr = 0;
+
+ ppc_vaddr = (Addr)xc->readIntReg(ArgumentReg1);
+ timer_vaddr = (Addr)xc->readIntReg(ArgumentReg2);
+
+ ppc_paddr = vtophys(physmem, ppc_vaddr);
+ timer_paddr = vtophys(physmem, timer_vaddr);
+
+ uint8_t *ppc = physmem->dma_addr(ppc_paddr, sizeof(uint32_t));
+ uint8_t *timer = physmem->dma_addr(timer_paddr, sizeof(uint32_t));
+
+ *(uint32_t *)ppc = htog((uint32_t)Clock::Frequency);
+ *(uint32_t *)timer = htog((uint32_t)TIMER_FREQUENCY);
+}
+
+
+void
+FreebsdAlphaSystem::SkipCalibrateClocksEvent::process(ExecContext *xc)
+{
+ SkipFuncEvent::process(xc);
+ ((FreebsdAlphaSystem *)xc->getSystemPtr())->doCalibrateClocks(xc);
+}
+
+
+BEGIN_DECLARE_SIM_OBJECT_PARAMS(FreebsdAlphaSystem)
+
+ Param<Tick> boot_cpu_frequency;
+ SimObjectParam<MemoryController *> memctrl;
+ SimObjectParam<PhysicalMemory *> physmem;
+
+ Param<string> kernel;
+ Param<string> console;
+ Param<string> pal;
+
+ Param<string> boot_osflags;
+ Param<string> readfile;
+ Param<unsigned int> init_param;
+
+ Param<uint64_t> system_type;
+ Param<uint64_t> system_rev;
+
+ Param<bool> bin;
+ VectorParam<string> binned_fns;
+ Param<bool> bin_int;
+
+END_DECLARE_SIM_OBJECT_PARAMS(FreebsdAlphaSystem)
+
+BEGIN_INIT_SIM_OBJECT_PARAMS(FreebsdAlphaSystem)
+
+ INIT_PARAM(boot_cpu_frequency, "Frequency of the boot CPU"),
+ INIT_PARAM(memctrl, "memory controller"),
+ INIT_PARAM(physmem, "phsyical memory"),
+ INIT_PARAM(kernel, "file that contains the kernel code"),
+ INIT_PARAM(console, "file that contains the console code"),
+ INIT_PARAM(pal, "file that contains palcode"),
+ INIT_PARAM_DFLT(boot_osflags, "flags to pass to the kernel during boot",
+ "a"),
+ INIT_PARAM_DFLT(readfile, "file to read startup script from", ""),
+ INIT_PARAM_DFLT(init_param, "numerical value to pass into simulator", 0),
+ INIT_PARAM_DFLT(system_type, "Type of system we are emulating", 34),
+ INIT_PARAM_DFLT(system_rev, "Revision of system we are emulating", 1<<10),
+ INIT_PARAM_DFLT(bin, "is this system to be binned", false),
+ INIT_PARAM(binned_fns, "functions to be broken down and binned"),
+ INIT_PARAM_DFLT(bin_int, "is interrupt code binned seperately?", true)
+
+END_INIT_SIM_OBJECT_PARAMS(FreebsdAlphaSystem)
+
+CREATE_SIM_OBJECT(FreebsdAlphaSystem)
+{
+ AlphaSystem::Params *p = new AlphaSystem::Params;
+ p->name = getInstanceName();
+ p->boot_cpu_frequency = boot_cpu_frequency;
+ p->memctrl = memctrl;
+ p->physmem = physmem;
+ p->kernel_path = kernel;
+ p->console_path = console;
+ p->palcode = pal;
+ p->boot_osflags = boot_osflags;
+ p->init_param = init_param;
+ p->readfile = readfile;
+ p->system_type = system_type;
+ p->system_rev = system_rev;
+ p->bin = bin;
+ p->binned_fns = binned_fns;
+ p->bin_int = bin_int;
+ return new FreebsdAlphaSystem(p);
+}
+
+REGISTER_SIM_OBJECT("FreebsdAlphaSystem", FreebsdAlphaSystem)
+
diff --git a/arch/alpha/pseudo_inst.hh b/arch/alpha/freebsd/system.hh
index 0e7462a56..5d996955e 100644
--- a/arch/alpha/pseudo_inst.hh
+++ b/arch/alpha/freebsd/system.hh
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2005 The Regents of The University of Michigan
+ * Copyright (c) 2004-2005 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -26,29 +26,31 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-class ExecContext;
+#ifndef __KERN_FREEBSD_FREEBSD_SYSTEM_HH__
+#define __KERN_FREEBSD_FREEBSD_SYSTEM_HH__
-namespace AlphaPseudo
+#include "kern/system_events.hh"
+
+class FreebsdAlphaSystem : public AlphaSystem
{
- /**
- * @todo these externs are only here for a hack in fullCPU::takeOver...
- */
- extern bool doStatisticsInsts;
- extern bool doCheckpointInsts;
- extern bool doQuiesce;
+ private:
+ class SkipCalibrateClocksEvent : public SkipFuncEvent
+ {
+ public:
+ SkipCalibrateClocksEvent(PCEventQueue *q, const std::string &desc,
+ Addr addr)
+ : SkipFuncEvent(q, desc, addr) {}
+ virtual void process(ExecContext *xc);
+ };
+
+ SkipFuncEvent *skipDelayEvent;
+ SkipCalibrateClocksEvent *skipCalibrateClocks;
+
+ public:
+ FreebsdAlphaSystem(Params *p);
+ ~FreebsdAlphaSystem();
+ void doCalibrateClocks(ExecContext *xc);
+
+};
- void arm(ExecContext *xc);
- void quiesce(ExecContext *xc);
- void ivlb(ExecContext *xc);
- void ivle(ExecContext *xc);
- void m5exit(ExecContext *xc);
- void m5exit_old(ExecContext *xc);
- void resetstats(ExecContext *xc);
- void dumpstats(ExecContext *xc);
- void dumpresetstats(ExecContext *xc);
- void m5checkpoint(ExecContext *xc);
- void readfile(ExecContext *xc);
- void debugbreak(ExecContext *xc);
- void switchcpu(ExecContext *xc);
- void addsymbol(ExecContext *xc);
-}
+#endif // __KERN_FREEBSD_FREEBSD_SYSTEM_HH__
diff --git a/arch/alpha/isa/branch.isa b/arch/alpha/isa/branch.isa
new file mode 100644
index 000000000..b528df938
--- /dev/null
+++ b/arch/alpha/isa/branch.isa
@@ -0,0 +1,259 @@
+// -*- mode:c++ -*-
+
+// Copyright (c) 2003-2005 The Regents of The University of Michigan
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met: redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer;
+// redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution;
+// neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+output header {{
+
+ /**
+ * Base class for instructions whose disassembly is not purely a
+ * function of the machine instruction (i.e., it depends on the
+ * PC). This class overrides the disassemble() method to check
+ * the PC and symbol table values before re-using a cached
+ * disassembly string. This is necessary for branches and jumps,
+ * where the disassembly string includes the target address (which
+ * may depend on the PC and/or symbol table).
+ */
+ class PCDependentDisassembly : public AlphaStaticInst
+ {
+ protected:
+ /// Cached program counter from last disassembly
+ mutable Addr cachedPC;
+ /// Cached symbol table pointer from last disassembly
+ mutable const SymbolTable *cachedSymtab;
+
+ /// Constructor
+ PCDependentDisassembly(const char *mnem, ExtMachInst _machInst,
+ OpClass __opClass)
+ : AlphaStaticInst(mnem, _machInst, __opClass),
+ cachedPC(0), cachedSymtab(0)
+ {
+ }
+
+ const std::string &
+ disassemble(Addr pc, const SymbolTable *symtab) const;
+ };
+
+ /**
+ * Base class for branches (PC-relative control transfers),
+ * conditional or unconditional.
+ */
+ class Branch : public PCDependentDisassembly
+ {
+ protected:
+ /// Displacement to target address (signed).
+ int32_t disp;
+
+ /// Constructor.
+ Branch(const char *mnem, ExtMachInst _machInst, OpClass __opClass)
+ : PCDependentDisassembly(mnem, _machInst, __opClass),
+ disp(BRDISP << 2)
+ {
+ }
+
+ Addr branchTarget(Addr branchPC) const;
+
+ std::string
+ generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+ };
+
+ /**
+ * Base class for jumps (register-indirect control transfers). In
+ * the Alpha ISA, these are always unconditional.
+ */
+ class Jump : public PCDependentDisassembly
+ {
+ protected:
+
+ /// Displacement to target address (signed).
+ int32_t disp;
+
+ public:
+ /// Constructor
+ Jump(const char *mnem, ExtMachInst _machInst, OpClass __opClass)
+ : PCDependentDisassembly(mnem, _machInst, __opClass),
+ disp(BRDISP)
+ {
+ }
+
+ Addr branchTarget(ExecContext *xc) const;
+
+ std::string
+ generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+ };
+}};
+
+output decoder {{
+ Addr
+ Branch::branchTarget(Addr branchPC) const
+ {
+ return branchPC + 4 + disp;
+ }
+
+ Addr
+ Jump::branchTarget(ExecContext *xc) const
+ {
+ Addr NPC = xc->readPC() + 4;
+ uint64_t Rb = xc->readIntReg(_srcRegIdx[0]);
+ return (Rb & ~3) | (NPC & 1);
+ }
+
+ const std::string &
+ PCDependentDisassembly::disassemble(Addr pc,
+ const SymbolTable *symtab) const
+ {
+ if (!cachedDisassembly ||
+ pc != cachedPC || symtab != cachedSymtab)
+ {
+ if (cachedDisassembly)
+ delete cachedDisassembly;
+
+ cachedDisassembly =
+ new std::string(generateDisassembly(pc, symtab));
+ cachedPC = pc;
+ cachedSymtab = symtab;
+ }
+
+ return *cachedDisassembly;
+ }
+
+ std::string
+ Branch::generateDisassembly(Addr pc, const SymbolTable *symtab) const
+ {
+ std::stringstream ss;
+
+ ccprintf(ss, "%-10s ", mnemonic);
+
+ // There's only one register arg (RA), but it could be
+ // either a source (the condition for conditional
+ // branches) or a destination (the link reg for
+ // unconditional branches)
+ if (_numSrcRegs > 0) {
+ printReg(ss, _srcRegIdx[0]);
+ ss << ",";
+ }
+ else if (_numDestRegs > 0) {
+ printReg(ss, _destRegIdx[0]);
+ ss << ",";
+ }
+
+#ifdef SS_COMPATIBLE_DISASSEMBLY
+ if (_numSrcRegs == 0 && _numDestRegs == 0) {
+ printReg(ss, 31);
+ ss << ",";
+ }
+#endif
+
+ Addr target = pc + 4 + disp;
+
+ std::string str;
+ if (symtab && symtab->findSymbol(target, str))
+ ss << str;
+ else
+ ccprintf(ss, "0x%x", target);
+
+ return ss.str();
+ }
+
+ std::string
+ Jump::generateDisassembly(Addr pc, const SymbolTable *symtab) const
+ {
+ std::stringstream ss;
+
+ ccprintf(ss, "%-10s ", mnemonic);
+
+#ifdef SS_COMPATIBLE_DISASSEMBLY
+ if (_numDestRegs == 0) {
+ printReg(ss, 31);
+ ss << ",";
+ }
+#endif
+
+ if (_numDestRegs > 0) {
+ printReg(ss, _destRegIdx[0]);
+ ss << ",";
+ }
+
+ ccprintf(ss, "(r%d)", RB);
+
+ return ss.str();
+ }
+}};
+
+def template JumpOrBranchDecode {{
+ return (RA == 31)
+ ? (StaticInst *)new %(class_name)s(machInst)
+ : (StaticInst *)new %(class_name)sAndLink(machInst);
+}};
+
+def format CondBranch(code) {{
+ code = 'bool cond;\n' + code + '\nif (cond) NPC = NPC + disp;\n';
+ iop = InstObjParams(name, Name, 'Branch', CodeBlock(code),
+ ('IsDirectControl', 'IsCondControl'))
+ header_output = BasicDeclare.subst(iop)
+ decoder_output = BasicConstructor.subst(iop)
+ decode_block = BasicDecode.subst(iop)
+ exec_output = BasicExecute.subst(iop)
+}};
+
+let {{
+def UncondCtrlBase(name, Name, base_class, npc_expr, flags):
+ # Declare basic control transfer w/o link (i.e. link reg is R31)
+ nolink_code = 'NPC = %s;\n' % npc_expr
+ nolink_iop = InstObjParams(name, Name, base_class,
+ CodeBlock(nolink_code), flags)
+ header_output = BasicDeclare.subst(nolink_iop)
+ decoder_output = BasicConstructor.subst(nolink_iop)
+ exec_output = BasicExecute.subst(nolink_iop)
+
+ # Generate declaration of '*AndLink' version, append to decls
+ link_code = 'Ra = NPC & ~3;\n' + nolink_code
+ link_iop = InstObjParams(name, Name + 'AndLink', base_class,
+ CodeBlock(link_code), flags)
+ header_output += BasicDeclare.subst(link_iop)
+ decoder_output += BasicConstructor.subst(link_iop)
+ exec_output += BasicExecute.subst(link_iop)
+
+ # need to use link_iop for the decode template since it is expecting
+ # the shorter version of class_name (w/o "AndLink")
+
+ return (header_output, decoder_output,
+ JumpOrBranchDecode.subst(nolink_iop), exec_output)
+}};
+
+def format UncondBranch(*flags) {{
+ flags += ('IsUncondControl', 'IsDirectControl')
+ (header_output, decoder_output, decode_block, exec_output) = \
+ UncondCtrlBase(name, Name, 'Branch', 'NPC + disp', flags)
+}};
+
+def format Jump(*flags) {{
+ flags += ('IsUncondControl', 'IsIndirectControl')
+ (header_output, decoder_output, decode_block, exec_output) = \
+ UncondCtrlBase(name, Name, 'Jump', '(Rb & ~3) | (NPC & 1)', flags)
+}};
+
+
diff --git a/arch/alpha/isa/decoder.isa b/arch/alpha/isa/decoder.isa
new file mode 100644
index 000000000..e09673269
--- /dev/null
+++ b/arch/alpha/isa/decoder.isa
@@ -0,0 +1,819 @@
+// -*- mode:c++ -*-
+
+// Copyright (c) 2003-2006 The Regents of The University of Michigan
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met: redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer;
+// redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution;
+// neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+decode OPCODE default Unknown::unknown() {
+
+ format LoadAddress {
+ 0x08: lda({{ Ra = Rb + disp; }});
+ 0x09: ldah({{ Ra = Rb + (disp << 16); }});
+ }
+
+ format LoadOrNop {
+ 0x0a: ldbu({{ Ra.uq = Mem.ub; }});
+ 0x0c: ldwu({{ Ra.uq = Mem.uw; }});
+ 0x0b: ldq_u({{ Ra = Mem.uq; }}, ea_code = {{ EA = (Rb + disp) & ~7; }});
+ 0x23: ldt({{ Fa = Mem.df; }});
+ 0x2a: ldl_l({{ Ra.sl = Mem.sl; }}, mem_flags = LOCKED);
+ 0x2b: ldq_l({{ Ra.uq = Mem.uq; }}, mem_flags = LOCKED);
+ 0x20: MiscPrefetch::copy_load({{ EA = Ra; }},
+ {{ fault = xc->copySrcTranslate(EA); }},
+ inst_flags = [IsMemRef, IsLoad, IsCopy]);
+ }
+
+ format LoadOrPrefetch {
+ 0x28: ldl({{ Ra.sl = Mem.sl; }});
+ 0x29: ldq({{ Ra.uq = Mem.uq; }}, pf_flags = EVICT_NEXT);
+ // IsFloating flag on lds gets the prefetch to disassemble
+ // using f31 instead of r31... funcitonally it's unnecessary
+ 0x22: lds({{ Fa.uq = s_to_t(Mem.ul); }},
+ pf_flags = PF_EXCLUSIVE, inst_flags = IsFloating);
+ }
+
+ format Store {
+ 0x0e: stb({{ Mem.ub = Ra<7:0>; }});
+ 0x0d: stw({{ Mem.uw = Ra<15:0>; }});
+ 0x2c: stl({{ Mem.ul = Ra<31:0>; }});
+ 0x2d: stq({{ Mem.uq = Ra.uq; }});
+ 0x0f: stq_u({{ Mem.uq = Ra.uq; }}, {{ EA = (Rb + disp) & ~7; }});
+ 0x26: sts({{ Mem.ul = t_to_s(Fa.uq); }});
+ 0x27: stt({{ Mem.df = Fa; }});
+ 0x24: MiscPrefetch::copy_store({{ EA = Rb; }},
+ {{ fault = xc->copy(EA); }},
+ inst_flags = [IsMemRef, IsStore, IsCopy]);
+ }
+
+ format StoreCond {
+ 0x2e: stl_c({{ Mem.ul = Ra<31:0>; }},
+ {{
+ uint64_t tmp = write_result;
+ // see stq_c
+ Ra = (tmp == 0 || tmp == 1) ? tmp : Ra;
+ }}, mem_flags = LOCKED);
+ 0x2f: stq_c({{ Mem.uq = Ra; }},
+ {{
+ uint64_t tmp = write_result;
+ // If the write operation returns 0 or 1, then
+ // this was a conventional store conditional,
+ // and the value indicates the success/failure
+ // of the operation. If another value is
+ // returned, then this was a Turbolaser
+ // mailbox access, and we don't update the
+ // result register at all.
+ Ra = (tmp == 0 || tmp == 1) ? tmp : Ra;
+ }}, mem_flags = LOCKED);
+ }
+
+ format IntegerOperate {
+
+ 0x10: decode INTFUNC { // integer arithmetic operations
+
+ 0x00: addl({{ Rc.sl = Ra.sl + Rb_or_imm.sl; }});
+ 0x40: addlv({{
+ uint32_t tmp = Ra.sl + Rb_or_imm.sl;
+ // signed overflow occurs when operands have same sign
+ // and sign of result does not match.
+ if (Ra.sl<31:> == Rb_or_imm.sl<31:> && tmp<31:> != Ra.sl<31:>)
+ fault = new IntegerOverflowFault;
+ Rc.sl = tmp;
+ }});
+ 0x02: s4addl({{ Rc.sl = (Ra.sl << 2) + Rb_or_imm.sl; }});
+ 0x12: s8addl({{ Rc.sl = (Ra.sl << 3) + Rb_or_imm.sl; }});
+
+ 0x20: addq({{ Rc = Ra + Rb_or_imm; }});
+ 0x60: addqv({{
+ uint64_t tmp = Ra + Rb_or_imm;
+ // signed overflow occurs when operands have same sign
+ // and sign of result does not match.
+ if (Ra<63:> == Rb_or_imm<63:> && tmp<63:> != Ra<63:>)
+ fault = new IntegerOverflowFault;
+ Rc = tmp;
+ }});
+ 0x22: s4addq({{ Rc = (Ra << 2) + Rb_or_imm; }});
+ 0x32: s8addq({{ Rc = (Ra << 3) + Rb_or_imm; }});
+
+ 0x09: subl({{ Rc.sl = Ra.sl - Rb_or_imm.sl; }});
+ 0x49: sublv({{
+ uint32_t tmp = Ra.sl - Rb_or_imm.sl;
+ // signed overflow detection is same as for add,
+ // except we need to look at the *complemented*
+ // sign bit of the subtrahend (Rb), i.e., if the initial
+ // signs are the *same* then no overflow can occur
+ if (Ra.sl<31:> != Rb_or_imm.sl<31:> && tmp<31:> != Ra.sl<31:>)
+ fault = new IntegerOverflowFault;
+ Rc.sl = tmp;
+ }});
+ 0x0b: s4subl({{ Rc.sl = (Ra.sl << 2) - Rb_or_imm.sl; }});
+ 0x1b: s8subl({{ Rc.sl = (Ra.sl << 3) - Rb_or_imm.sl; }});
+
+ 0x29: subq({{ Rc = Ra - Rb_or_imm; }});
+ 0x69: subqv({{
+ uint64_t tmp = Ra - Rb_or_imm;
+ // signed overflow detection is same as for add,
+ // except we need to look at the *complemented*
+ // sign bit of the subtrahend (Rb), i.e., if the initial
+ // signs are the *same* then no overflow can occur
+ if (Ra<63:> != Rb_or_imm<63:> && tmp<63:> != Ra<63:>)
+ fault = new IntegerOverflowFault;
+ Rc = tmp;
+ }});
+ 0x2b: s4subq({{ Rc = (Ra << 2) - Rb_or_imm; }});
+ 0x3b: s8subq({{ Rc = (Ra << 3) - Rb_or_imm; }});
+
+ 0x2d: cmpeq({{ Rc = (Ra == Rb_or_imm); }});
+ 0x6d: cmple({{ Rc = (Ra.sq <= Rb_or_imm.sq); }});
+ 0x4d: cmplt({{ Rc = (Ra.sq < Rb_or_imm.sq); }});
+ 0x3d: cmpule({{ Rc = (Ra.uq <= Rb_or_imm.uq); }});
+ 0x1d: cmpult({{ Rc = (Ra.uq < Rb_or_imm.uq); }});
+
+ 0x0f: cmpbge({{
+ int hi = 7;
+ int lo = 0;
+ uint64_t tmp = 0;
+ for (int i = 0; i < 8; ++i) {
+ tmp |= (Ra.uq<hi:lo> >= Rb_or_imm.uq<hi:lo>) << i;
+ hi += 8;
+ lo += 8;
+ }
+ Rc = tmp;
+ }});
+ }
+
+ 0x11: decode INTFUNC { // integer logical operations
+
+ 0x00: and({{ Rc = Ra & Rb_or_imm; }});
+ 0x08: bic({{ Rc = Ra & ~Rb_or_imm; }});
+ 0x20: bis({{ Rc = Ra | Rb_or_imm; }});
+ 0x28: ornot({{ Rc = Ra | ~Rb_or_imm; }});
+ 0x40: xor({{ Rc = Ra ^ Rb_or_imm; }});
+ 0x48: eqv({{ Rc = Ra ^ ~Rb_or_imm; }});
+
+ // conditional moves
+ 0x14: cmovlbs({{ Rc = ((Ra & 1) == 1) ? Rb_or_imm : Rc; }});
+ 0x16: cmovlbc({{ Rc = ((Ra & 1) == 0) ? Rb_or_imm : Rc; }});
+ 0x24: cmoveq({{ Rc = (Ra == 0) ? Rb_or_imm : Rc; }});
+ 0x26: cmovne({{ Rc = (Ra != 0) ? Rb_or_imm : Rc; }});
+ 0x44: cmovlt({{ Rc = (Ra.sq < 0) ? Rb_or_imm : Rc; }});
+ 0x46: cmovge({{ Rc = (Ra.sq >= 0) ? Rb_or_imm : Rc; }});
+ 0x64: cmovle({{ Rc = (Ra.sq <= 0) ? Rb_or_imm : Rc; }});
+ 0x66: cmovgt({{ Rc = (Ra.sq > 0) ? Rb_or_imm : Rc; }});
+
+ // For AMASK, RA must be R31.
+ 0x61: decode RA {
+ 31: amask({{ Rc = Rb_or_imm & ~ULL(0x17); }});
+ }
+
+ // For IMPLVER, RA must be R31 and the B operand
+ // must be the immediate value 1.
+ 0x6c: decode RA {
+ 31: decode IMM {
+ 1: decode INTIMM {
+ // return EV5 for FULL_SYSTEM and EV6 otherwise
+ 1: implver({{
+#if FULL_SYSTEM
+ Rc = 1;
+#else
+ Rc = 2;
+#endif
+ }});
+ }
+ }
+ }
+
+#if FULL_SYSTEM
+ // The mysterious 11.25...
+ 0x25: WarnUnimpl::eleven25();
+#endif
+ }
+
+ 0x12: decode INTFUNC {
+ 0x39: sll({{ Rc = Ra << Rb_or_imm<5:0>; }});
+ 0x34: srl({{ Rc = Ra.uq >> Rb_or_imm<5:0>; }});
+ 0x3c: sra({{ Rc = Ra.sq >> Rb_or_imm<5:0>; }});
+
+ 0x02: mskbl({{ Rc = Ra & ~(mask( 8) << (Rb_or_imm<2:0> * 8)); }});
+ 0x12: mskwl({{ Rc = Ra & ~(mask(16) << (Rb_or_imm<2:0> * 8)); }});
+ 0x22: mskll({{ Rc = Ra & ~(mask(32) << (Rb_or_imm<2:0> * 8)); }});
+ 0x32: mskql({{ Rc = Ra & ~(mask(64) << (Rb_or_imm<2:0> * 8)); }});
+
+ 0x52: mskwh({{
+ int bv = Rb_or_imm<2:0>;
+ Rc = bv ? (Ra & ~(mask(16) >> (64 - 8 * bv))) : Ra;
+ }});
+ 0x62: msklh({{
+ int bv = Rb_or_imm<2:0>;
+ Rc = bv ? (Ra & ~(mask(32) >> (64 - 8 * bv))) : Ra;
+ }});
+ 0x72: mskqh({{
+ int bv = Rb_or_imm<2:0>;
+ Rc = bv ? (Ra & ~(mask(64) >> (64 - 8 * bv))) : Ra;
+ }});
+
+ 0x06: extbl({{ Rc = (Ra.uq >> (Rb_or_imm<2:0> * 8))< 7:0>; }});
+ 0x16: extwl({{ Rc = (Ra.uq >> (Rb_or_imm<2:0> * 8))<15:0>; }});
+ 0x26: extll({{ Rc = (Ra.uq >> (Rb_or_imm<2:0> * 8))<31:0>; }});
+ 0x36: extql({{ Rc = (Ra.uq >> (Rb_or_imm<2:0> * 8)); }});
+
+ 0x5a: extwh({{
+ Rc = (Ra << (64 - (Rb_or_imm<2:0> * 8))<5:0>)<15:0>; }});
+ 0x6a: extlh({{
+ Rc = (Ra << (64 - (Rb_or_imm<2:0> * 8))<5:0>)<31:0>; }});
+ 0x7a: extqh({{
+ Rc = (Ra << (64 - (Rb_or_imm<2:0> * 8))<5:0>); }});
+
+ 0x0b: insbl({{ Rc = Ra< 7:0> << (Rb_or_imm<2:0> * 8); }});
+ 0x1b: inswl({{ Rc = Ra<15:0> << (Rb_or_imm<2:0> * 8); }});
+ 0x2b: insll({{ Rc = Ra<31:0> << (Rb_or_imm<2:0> * 8); }});
+ 0x3b: insql({{ Rc = Ra << (Rb_or_imm<2:0> * 8); }});
+
+ 0x57: inswh({{
+ int bv = Rb_or_imm<2:0>;
+ Rc = bv ? (Ra.uq<15:0> >> (64 - 8 * bv)) : 0;
+ }});
+ 0x67: inslh({{
+ int bv = Rb_or_imm<2:0>;
+ Rc = bv ? (Ra.uq<31:0> >> (64 - 8 * bv)) : 0;
+ }});
+ 0x77: insqh({{
+ int bv = Rb_or_imm<2:0>;
+ Rc = bv ? (Ra.uq >> (64 - 8 * bv)) : 0;
+ }});
+
+ 0x30: zap({{
+ uint64_t zapmask = 0;
+ for (int i = 0; i < 8; ++i) {
+ if (Rb_or_imm<i:>)
+ zapmask |= (mask(8) << (i * 8));
+ }
+ Rc = Ra & ~zapmask;
+ }});
+ 0x31: zapnot({{
+ uint64_t zapmask = 0;
+ for (int i = 0; i < 8; ++i) {
+ if (!Rb_or_imm<i:>)
+ zapmask |= (mask(8) << (i * 8));
+ }
+ Rc = Ra & ~zapmask;
+ }});
+ }
+
+ 0x13: decode INTFUNC { // integer multiplies
+ 0x00: mull({{ Rc.sl = Ra.sl * Rb_or_imm.sl; }}, IntMultOp);
+ 0x20: mulq({{ Rc = Ra * Rb_or_imm; }}, IntMultOp);
+ 0x30: umulh({{
+ uint64_t hi, lo;
+ mul128(Ra, Rb_or_imm, hi, lo);
+ Rc = hi;
+ }}, IntMultOp);
+ 0x40: mullv({{
+ // 32-bit multiply with trap on overflow
+ int64_t Rax = Ra.sl; // sign extended version of Ra.sl
+ int64_t Rbx = Rb_or_imm.sl;
+ int64_t tmp = Rax * Rbx;
+ // To avoid overflow, all the upper 32 bits must match
+ // the sign bit of the lower 32. We code this as
+ // checking the upper 33 bits for all 0s or all 1s.
+ uint64_t sign_bits = tmp<63:31>;
+ if (sign_bits != 0 && sign_bits != mask(33))
+ fault = new IntegerOverflowFault;
+ Rc.sl = tmp<31:0>;
+ }}, IntMultOp);
+ 0x60: mulqv({{
+ // 64-bit multiply with trap on overflow
+ uint64_t hi, lo;
+ mul128(Ra, Rb_or_imm, hi, lo);
+ // all the upper 64 bits must match the sign bit of
+ // the lower 64
+ if (!((hi == 0 && lo<63:> == 0) ||
+ (hi == mask(64) && lo<63:> == 1)))
+ fault = new IntegerOverflowFault;
+ Rc = lo;
+ }}, IntMultOp);
+ }
+
+ 0x1c: decode INTFUNC {
+ 0x00: decode RA { 31: sextb({{ Rc.sb = Rb_or_imm< 7:0>; }}); }
+ 0x01: decode RA { 31: sextw({{ Rc.sw = Rb_or_imm<15:0>; }}); }
+ 0x32: ctlz({{
+ uint64_t count = 0;
+ uint64_t temp = Rb;
+ if (temp<63:32>) temp >>= 32; else count += 32;
+ if (temp<31:16>) temp >>= 16; else count += 16;
+ if (temp<15:8>) temp >>= 8; else count += 8;
+ if (temp<7:4>) temp >>= 4; else count += 4;
+ if (temp<3:2>) temp >>= 2; else count += 2;
+ if (temp<1:1>) temp >>= 1; else count += 1;
+ if ((temp<0:0>) != 0x1) count += 1;
+ Rc = count;
+ }}, IntAluOp);
+
+ 0x33: cttz({{
+ uint64_t count = 0;
+ uint64_t temp = Rb;
+ if (!(temp<31:0>)) { temp >>= 32; count += 32; }
+ if (!(temp<15:0>)) { temp >>= 16; count += 16; }
+ if (!(temp<7:0>)) { temp >>= 8; count += 8; }
+ if (!(temp<3:0>)) { temp >>= 4; count += 4; }
+ if (!(temp<1:0>)) { temp >>= 2; count += 2; }
+ if (!(temp<0:0> & ULL(0x1))) count += 1;
+ Rc = count;
+ }}, IntAluOp);
+
+ format FailUnimpl {
+ 0x30: ctpop();
+ 0x31: perr();
+ 0x34: unpkbw();
+ 0x35: unpkbl();
+ 0x36: pkwb();
+ 0x37: pklb();
+ 0x38: minsb8();
+ 0x39: minsw4();
+ 0x3a: minub8();
+ 0x3b: minuw4();
+ 0x3c: maxub8();
+ 0x3d: maxuw4();
+ 0x3e: maxsb8();
+ 0x3f: maxsw4();
+ }
+
+ format BasicOperateWithNopCheck {
+ 0x70: decode RB {
+ 31: ftoit({{ Rc = Fa.uq; }}, FloatCvtOp);
+ }
+ 0x78: decode RB {
+ 31: ftois({{ Rc.sl = t_to_s(Fa.uq); }},
+ FloatCvtOp);
+ }
+ }
+ }
+ }
+
+ // Conditional branches.
+ format CondBranch {
+ 0x39: beq({{ cond = (Ra == 0); }});
+ 0x3d: bne({{ cond = (Ra != 0); }});
+ 0x3e: bge({{ cond = (Ra.sq >= 0); }});
+ 0x3f: bgt({{ cond = (Ra.sq > 0); }});
+ 0x3b: ble({{ cond = (Ra.sq <= 0); }});
+ 0x3a: blt({{ cond = (Ra.sq < 0); }});
+ 0x38: blbc({{ cond = ((Ra & 1) == 0); }});
+ 0x3c: blbs({{ cond = ((Ra & 1) == 1); }});
+
+ 0x31: fbeq({{ cond = (Fa == 0); }});
+ 0x35: fbne({{ cond = (Fa != 0); }});
+ 0x36: fbge({{ cond = (Fa >= 0); }});
+ 0x37: fbgt({{ cond = (Fa > 0); }});
+ 0x33: fble({{ cond = (Fa <= 0); }});
+ 0x32: fblt({{ cond = (Fa < 0); }});
+ }
+
+ // unconditional branches
+ format UncondBranch {
+ 0x30: br();
+ 0x34: bsr(IsCall);
+ }
+
+ // indirect branches
+ 0x1a: decode JMPFUNC {
+ format Jump {
+ 0: jmp();
+ 1: jsr(IsCall);
+ 2: ret(IsReturn);
+ 3: jsr_coroutine(IsCall, IsReturn);
+ }
+ }
+
+ // Square root and integer-to-FP moves
+ 0x14: decode FP_SHORTFUNC {
+ // Integer to FP register moves must have RB == 31
+ 0x4: decode RB {
+ 31: decode FP_FULLFUNC {
+ format BasicOperateWithNopCheck {
+ 0x004: itofs({{ Fc.uq = s_to_t(Ra.ul); }}, FloatCvtOp);
+ 0x024: itoft({{ Fc.uq = Ra.uq; }}, FloatCvtOp);
+ 0x014: FailUnimpl::itoff(); // VAX-format conversion
+ }
+ }
+ }
+
+ // Square root instructions must have FA == 31
+ 0xb: decode FA {
+ 31: decode FP_TYPEFUNC {
+ format FloatingPointOperate {
+#if SS_COMPATIBLE_FP
+ 0x0b: sqrts({{
+ if (Fb < 0.0)
+ fault = new ArithmeticFault;
+ Fc = sqrt(Fb);
+ }}, FloatSqrtOp);
+#else
+ 0x0b: sqrts({{
+ if (Fb.sf < 0.0)
+ fault = new ArithmeticFault;
+ Fc.sf = sqrt(Fb.sf);
+ }}, FloatSqrtOp);
+#endif
+ 0x2b: sqrtt({{
+ if (Fb < 0.0)
+ fault = new ArithmeticFault;
+ Fc = sqrt(Fb);
+ }}, FloatSqrtOp);
+ }
+ }
+ }
+
+ // VAX-format sqrtf and sqrtg are not implemented
+ 0xa: FailUnimpl::sqrtfg();
+ }
+
+ // IEEE floating point
+ 0x16: decode FP_SHORTFUNC_TOP2 {
+ // The top two bits of the short function code break this
+ // space into four groups: binary ops, compares, reserved, and
+ // conversions. See Table 4-12 of AHB. There are different
+ // special cases in these different groups, so we decode on
+ // these top two bits first just to select a decode strategy.
+ // Most of these instructions may have various trapping and
+ // rounding mode flags set; these are decoded in the
+ // FloatingPointDecode template used by the
+ // FloatingPointOperate format.
+
+ // add/sub/mul/div: just decode on the short function code
+ // and source type. All valid trapping and rounding modes apply.
+ 0: decode FP_TRAPMODE {
+ // check for valid trapping modes here
+ 0,1,5,7: decode FP_TYPEFUNC {
+ format FloatingPointOperate {
+#if SS_COMPATIBLE_FP
+ 0x00: adds({{ Fc = Fa + Fb; }});
+ 0x01: subs({{ Fc = Fa - Fb; }});
+ 0x02: muls({{ Fc = Fa * Fb; }}, FloatMultOp);
+ 0x03: divs({{ Fc = Fa / Fb; }}, FloatDivOp);
+#else
+ 0x00: adds({{ Fc.sf = Fa.sf + Fb.sf; }});
+ 0x01: subs({{ Fc.sf = Fa.sf - Fb.sf; }});
+ 0x02: muls({{ Fc.sf = Fa.sf * Fb.sf; }}, FloatMultOp);
+ 0x03: divs({{ Fc.sf = Fa.sf / Fb.sf; }}, FloatDivOp);
+#endif
+
+ 0x20: addt({{ Fc = Fa + Fb; }});
+ 0x21: subt({{ Fc = Fa - Fb; }});
+ 0x22: mult({{ Fc = Fa * Fb; }}, FloatMultOp);
+ 0x23: divt({{ Fc = Fa / Fb; }}, FloatDivOp);
+ }
+ }
+ }
+
+ // Floating-point compare instructions must have the default
+ // rounding mode, and may use the default trapping mode or
+ // /SU. Both trapping modes are treated the same by M5; the
+ // only difference on the real hardware (as far a I can tell)
+ // is that without /SU you'd get an imprecise trap if you
+ // tried to compare a NaN with something else (instead of an
+ // "unordered" result).
+ 1: decode FP_FULLFUNC {
+ format BasicOperateWithNopCheck {
+ 0x0a5, 0x5a5: cmpteq({{ Fc = (Fa == Fb) ? 2.0 : 0.0; }},
+ FloatCmpOp);
+ 0x0a7, 0x5a7: cmptle({{ Fc = (Fa <= Fb) ? 2.0 : 0.0; }},
+ FloatCmpOp);
+ 0x0a6, 0x5a6: cmptlt({{ Fc = (Fa < Fb) ? 2.0 : 0.0; }},
+ FloatCmpOp);
+ 0x0a4, 0x5a4: cmptun({{ // unordered
+ Fc = (!(Fa < Fb) && !(Fa == Fb) && !(Fa > Fb)) ? 2.0 : 0.0;
+ }}, FloatCmpOp);
+ }
+ }
+
+ // The FP-to-integer and integer-to-FP conversion insts
+ // require that FA be 31.
+ 3: decode FA {
+ 31: decode FP_TYPEFUNC {
+ format FloatingPointOperate {
+ 0x2f: decode FP_ROUNDMODE {
+ format FPFixedRounding {
+ // "chopped" i.e. round toward zero
+ 0: cvttq({{ Fc.sq = (int64_t)trunc(Fb); }},
+ Chopped);
+ // round to minus infinity
+ 1: cvttq({{ Fc.sq = (int64_t)floor(Fb); }},
+ MinusInfinity);
+ }
+ default: cvttq({{ Fc.sq = (int64_t)nearbyint(Fb); }});
+ }
+
+ // The cvtts opcode is overloaded to be cvtst if the trap
+ // mode is 2 or 6 (which are not valid otherwise)
+ 0x2c: decode FP_FULLFUNC {
+ format BasicOperateWithNopCheck {
+ // trap on denorm version "cvtst/s" is
+ // simulated same as cvtst
+ 0x2ac, 0x6ac: cvtst({{ Fc = Fb.sf; }});
+ }
+ default: cvtts({{ Fc.sf = Fb; }});
+ }
+
+ // The trapping mode for integer-to-FP conversions
+ // must be /SUI or nothing; /U and /SU are not
+ // allowed. The full set of rounding modes are
+ // supported though.
+ 0x3c: decode FP_TRAPMODE {
+ 0,7: cvtqs({{ Fc.sf = Fb.sq; }});
+ }
+ 0x3e: decode FP_TRAPMODE {
+ 0,7: cvtqt({{ Fc = Fb.sq; }});
+ }
+ }
+ }
+ }
+ }
+
+ // misc FP operate
+ 0x17: decode FP_FULLFUNC {
+ format BasicOperateWithNopCheck {
+ 0x010: cvtlq({{
+ Fc.sl = (Fb.uq<63:62> << 30) | Fb.uq<58:29>;
+ }});
+ 0x030: cvtql({{
+ Fc.uq = (Fb.uq<31:30> << 62) | (Fb.uq<29:0> << 29);
+ }});
+
+ // We treat the precise & imprecise trapping versions of
+ // cvtql identically.
+ 0x130, 0x530: cvtqlv({{
+ // To avoid overflow, all the upper 32 bits must match
+ // the sign bit of the lower 32. We code this as
+ // checking the upper 33 bits for all 0s or all 1s.
+ uint64_t sign_bits = Fb.uq<63:31>;
+ if (sign_bits != 0 && sign_bits != mask(33))
+ fault = new IntegerOverflowFault;
+ Fc.uq = (Fb.uq<31:30> << 62) | (Fb.uq<29:0> << 29);
+ }});
+
+ 0x020: cpys({{ // copy sign
+ Fc.uq = (Fa.uq<63:> << 63) | Fb.uq<62:0>;
+ }});
+ 0x021: cpysn({{ // copy sign negated
+ Fc.uq = (~Fa.uq<63:> << 63) | Fb.uq<62:0>;
+ }});
+ 0x022: cpyse({{ // copy sign and exponent
+ Fc.uq = (Fa.uq<63:52> << 52) | Fb.uq<51:0>;
+ }});
+
+ 0x02a: fcmoveq({{ Fc = (Fa == 0) ? Fb : Fc; }});
+ 0x02b: fcmovne({{ Fc = (Fa != 0) ? Fb : Fc; }});
+ 0x02c: fcmovlt({{ Fc = (Fa < 0) ? Fb : Fc; }});
+ 0x02d: fcmovge({{ Fc = (Fa >= 0) ? Fb : Fc; }});
+ 0x02e: fcmovle({{ Fc = (Fa <= 0) ? Fb : Fc; }});
+ 0x02f: fcmovgt({{ Fc = (Fa > 0) ? Fb : Fc; }});
+
+ 0x024: mt_fpcr({{ FPCR = Fa.uq; }});
+ 0x025: mf_fpcr({{ Fa.uq = FPCR; }});
+ }
+ }
+
+ // miscellaneous mem-format ops
+ 0x18: decode MEMFUNC {
+ format WarnUnimpl {
+ 0x8000: fetch();
+ 0xa000: fetch_m();
+ 0xe800: ecb();
+ }
+
+ format MiscPrefetch {
+ 0xf800: wh64({{ EA = Rb & ~ULL(63); }},
+ {{ xc->writeHint(EA, 64, memAccessFlags); }},
+ mem_flags = NO_FAULT,
+ inst_flags = [IsMemRef, IsDataPrefetch,
+ IsStore, MemWriteOp]);
+ }
+
+ format BasicOperate {
+ 0xc000: rpcc({{
+#if FULL_SYSTEM
+ /* Rb is a fake dependency so here is a fun way to get
+ * the parser to understand that.
+ */
+ Ra = xc->readMiscRegWithEffect(AlphaISA::IPR_CC, fault) + (Rb & 0);
+
+#else
+ Ra = curTick;
+#endif
+ }});
+
+ // All of the barrier instructions below do nothing in
+ // their execute() methods (hence the empty code blocks).
+ // All of their functionality is hard-coded in the
+ // pipeline based on the flags IsSerializing,
+ // IsMemBarrier, and IsWriteBarrier. In the current
+ // detailed CPU model, the execute() function only gets
+ // called at fetch, so there's no way to generate pipeline
+ // behavior at any other stage. Once we go to an
+ // exec-in-exec CPU model we should be able to get rid of
+ // these flags and implement this behavior via the
+ // execute() methods.
+
+ // trapb is just a barrier on integer traps, where excb is
+ // a barrier on integer and FP traps. "EXCB is thus a
+ // superset of TRAPB." (Alpha ARM, Sec 4.11.4) We treat
+ // them the same though.
+ 0x0000: trapb({{ }}, IsSerializing, No_OpClass);
+ 0x0400: excb({{ }}, IsSerializing, No_OpClass);
+ 0x4000: mb({{ }}, IsMemBarrier, MemReadOp);
+ 0x4400: wmb({{ }}, IsWriteBarrier, MemWriteOp);
+ }
+
+#if FULL_SYSTEM
+ format BasicOperate {
+ 0xe000: rc({{
+ Ra = xc->readIntrFlag();
+ xc->setIntrFlag(0);
+ }}, IsNonSpeculative);
+ 0xf000: rs({{
+ Ra = xc->readIntrFlag();
+ xc->setIntrFlag(1);
+ }}, IsNonSpeculative);
+ }
+#else
+ format FailUnimpl {
+ 0xe000: rc();
+ 0xf000: rs();
+ }
+#endif
+ }
+
+#if FULL_SYSTEM
+ 0x00: CallPal::call_pal({{
+ if (!palValid ||
+ (palPriv
+ && xc->readMiscRegWithEffect(AlphaISA::IPR_ICM, fault) != AlphaISA::mode_kernel)) {
+ // invalid pal function code, or attempt to do privileged
+ // PAL call in non-kernel mode
+ fault = new UnimplementedOpcodeFault;
+ }
+ else {
+ // check to see if simulator wants to do something special
+ // on this PAL call (including maybe suppress it)
+ bool dopal = xc->simPalCheck(palFunc);
+
+ if (dopal) {
+ xc->setMiscRegWithEffect(AlphaISA::IPR_EXC_ADDR, NPC);
+ NPC = xc->readMiscRegWithEffect(AlphaISA::IPR_PAL_BASE, fault) + palOffset;
+ }
+ }
+ }}, IsNonSpeculative);
+#else
+ 0x00: decode PALFUNC {
+ format EmulatedCallPal {
+ 0x00: halt ({{
+ SimExit(curTick, "halt instruction encountered");
+ }}, IsNonSpeculative);
+ 0x83: callsys({{
+ xc->syscall();
+ }}, IsNonSpeculative);
+ // Read uniq reg into ABI return value register (r0)
+ 0x9e: rduniq({{ R0 = Runiq; }});
+ // Write uniq reg with value from ABI arg register (r16)
+ 0x9f: wruniq({{ Runiq = R16; }});
+ }
+ }
+#endif
+
+#if FULL_SYSTEM
+ 0x1b: decode PALMODE {
+ 0: OpcdecFault::hw_st_quad();
+ 1: decode HW_LDST_QUAD {
+ format HwLoad {
+ 0: hw_ld({{ EA = (Rb + disp) & ~3; }}, {{ Ra = Mem.ul; }}, L);
+ 1: hw_ld({{ EA = (Rb + disp) & ~7; }}, {{ Ra = Mem.uq; }}, Q);
+ }
+ }
+ }
+
+ 0x1f: decode PALMODE {
+ 0: OpcdecFault::hw_st_cond();
+ format HwStore {
+ 1: decode HW_LDST_COND {
+ 0: decode HW_LDST_QUAD {
+ 0: hw_st({{ EA = (Rb + disp) & ~3; }},
+ {{ Mem.ul = Ra<31:0>; }}, L);
+ 1: hw_st({{ EA = (Rb + disp) & ~7; }},
+ {{ Mem.uq = Ra.uq; }}, Q);
+ }
+
+ 1: FailUnimpl::hw_st_cond();
+ }
+ }
+ }
+
+ 0x19: decode PALMODE {
+ 0: OpcdecFault::hw_mfpr();
+ format HwMoveIPR {
+ 1: hw_mfpr({{
+ Ra = xc->readMiscRegWithEffect(ipr_index, fault);
+ }});
+ }
+ }
+
+ 0x1d: decode PALMODE {
+ 0: OpcdecFault::hw_mtpr();
+ format HwMoveIPR {
+ 1: hw_mtpr({{
+ xc->setMiscRegWithEffect(ipr_index, Ra);
+ if (traceData) { traceData->setData(Ra); }
+ }});
+ }
+ }
+
+ format BasicOperate {
+ 0x1e: decode PALMODE {
+ 0: OpcdecFault::hw_rei();
+ 1:hw_rei({{ xc->hwrei(); }}, IsSerializing);
+ }
+
+ // M5 special opcodes use the reserved 0x01 opcode space
+ 0x01: decode M5FUNC {
+ 0x00: arm({{
+ AlphaPseudo::arm(xc->xcBase());
+ }}, IsNonSpeculative);
+ 0x01: quiesce({{
+ AlphaPseudo::quiesce(xc->xcBase());
+ }}, IsNonSpeculative);
+ 0x02: quiesceNs({{
+ AlphaPseudo::quiesceNs(xc->xcBase(), R16);
+ }}, IsNonSpeculative);
+ 0x03: quiesceCycles({{
+ AlphaPseudo::quiesceCycles(xc->xcBase(), R16);
+ }}, IsNonSpeculative);
+ 0x04: quiesceTime({{
+ R0 = AlphaPseudo::quiesceTime(xc->xcBase());
+ }}, IsNonSpeculative);
+ 0x10: ivlb({{
+ AlphaPseudo::ivlb(xc->xcBase());
+ }}, No_OpClass, IsNonSpeculative);
+ 0x11: ivle({{
+ AlphaPseudo::ivle(xc->xcBase());
+ }}, No_OpClass, IsNonSpeculative);
+ 0x20: m5exit_old({{
+ AlphaPseudo::m5exit_old(xc->xcBase());
+ }}, No_OpClass, IsNonSpeculative);
+ 0x21: m5exit({{
+ AlphaPseudo::m5exit(xc->xcBase(), R16);
+ }}, No_OpClass, IsNonSpeculative);
+ 0x30: initparam({{ Ra = xc->xcBase()->getCpuPtr()->system->init_param; }});
+ 0x40: resetstats({{
+ AlphaPseudo::resetstats(xc->xcBase(), R16, R17);
+ }}, IsNonSpeculative);
+ 0x41: dumpstats({{
+ AlphaPseudo::dumpstats(xc->xcBase(), R16, R17);
+ }}, IsNonSpeculative);
+ 0x42: dumpresetstats({{
+ AlphaPseudo::dumpresetstats(xc->xcBase(), R16, R17);
+ }}, IsNonSpeculative);
+ 0x43: m5checkpoint({{
+ AlphaPseudo::m5checkpoint(xc->xcBase(), R16, R17);
+ }}, IsNonSpeculative);
+ 0x50: m5readfile({{
+ R0 = AlphaPseudo::readfile(xc->xcBase(), R16, R17, R18);
+ }}, IsNonSpeculative);
+ 0x51: m5break({{
+ AlphaPseudo::debugbreak(xc->xcBase());
+ }}, IsNonSpeculative);
+ 0x52: m5switchcpu({{
+ AlphaPseudo::switchcpu(xc->xcBase());
+ }}, IsNonSpeculative);
+ 0x53: m5addsymbol({{
+ AlphaPseudo::addsymbol(xc->xcBase(), R16, R17);
+ }}, IsNonSpeculative);
+ 0x54: m5panic({{
+ panic("M5 panic instruction called.");
+ }}, IsNonSpeculative);
+
+ }
+ }
+#endif
+}
diff --git a/arch/alpha/isa/fp.isa b/arch/alpha/isa/fp.isa
new file mode 100644
index 000000000..f34c13c42
--- /dev/null
+++ b/arch/alpha/isa/fp.isa
@@ -0,0 +1,301 @@
+// -*- mode:c++ -*-
+
+// Copyright (c) 2003-2005 The Regents of The University of Michigan
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met: redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer;
+// redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution;
+// neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+output exec {{
+ /// Check "FP enabled" machine status bit. Called when executing any FP
+ /// instruction in full-system mode.
+ /// @retval Full-system mode: NoFault if FP is enabled, FenFault
+ /// if not. Non-full-system mode: always returns NoFault.
+#if FULL_SYSTEM
+ inline Fault checkFpEnableFault(%(CPU_exec_context)s *xc)
+ {
+ Fault fault = NoFault; // dummy... this ipr access should not fault
+ if (!EV5::ICSR_FPE(xc->readMiscRegWithEffect(AlphaISA::IPR_ICSR, fault))) {
+ fault = new FloatEnableFault;
+ }
+ return fault;
+ }
+#else
+ inline Fault checkFpEnableFault(%(CPU_exec_context)s *xc)
+ {
+ return NoFault;
+ }
+#endif
+}};
+
+output header {{
+ /**
+ * Base class for general floating-point instructions. Includes
+ * support for various Alpha rounding and trapping modes. Only FP
+ * instructions that require this support are derived from this
+ * class; the rest derive directly from AlphaStaticInst.
+ */
+ class AlphaFP : public AlphaStaticInst
+ {
+ public:
+ /// Alpha FP rounding modes.
+ enum RoundingMode {
+ Chopped = 0, ///< round toward zero
+ Minus_Infinity = 1, ///< round toward minus infinity
+ Normal = 2, ///< round to nearest (default)
+ Dynamic = 3, ///< use FPCR setting (in instruction)
+ Plus_Infinity = 3 ///< round to plus inifinity (in FPCR)
+ };
+
+ /// Alpha FP trapping modes.
+ /// For instructions that produce integer results, the
+ /// "Underflow Enable" modes really mean "Overflow Enable", and
+ /// the assembly modifier is V rather than U.
+ enum TrappingMode {
+ /// default: nothing enabled
+ Imprecise = 0, ///< no modifier
+ /// underflow/overflow traps enabled, inexact disabled
+ Underflow_Imprecise = 1, ///< /U or /V
+ Underflow_Precise = 5, ///< /SU or /SV
+ /// underflow/overflow and inexact traps enabled
+ Underflow_Inexact_Precise = 7 ///< /SUI or /SVI
+ };
+
+ protected:
+ /// Map Alpha rounding mode to C99 constants from <fenv.h>.
+ static const int alphaToC99RoundingMode[];
+
+ /// Map enum RoundingMode values to disassembly suffixes.
+ static const char *roundingModeSuffix[];
+ /// Map enum TrappingMode values to FP disassembly suffixes.
+ static const char *fpTrappingModeSuffix[];
+ /// Map enum TrappingMode values to integer disassembly suffixes.
+ static const char *intTrappingModeSuffix[];
+
+ /// This instruction's rounding mode.
+ RoundingMode roundingMode;
+ /// This instruction's trapping mode.
+ TrappingMode trappingMode;
+
+ /// Have we warned about this instruction's unsupported
+ /// rounding mode (if applicable)?
+ mutable bool warnedOnRounding;
+
+ /// Have we warned about this instruction's unsupported
+ /// trapping mode (if applicable)?
+ mutable bool warnedOnTrapping;
+
+ /// Constructor
+ AlphaFP(const char *mnem, ExtMachInst _machInst, OpClass __opClass)
+ : AlphaStaticInst(mnem, _machInst, __opClass),
+ roundingMode((enum RoundingMode)FP_ROUNDMODE),
+ trappingMode((enum TrappingMode)FP_TRAPMODE),
+ warnedOnRounding(false),
+ warnedOnTrapping(false)
+ {
+ }
+
+ int getC99RoundingMode(uint64_t fpcr_val) const;
+
+ // This differs from the AlphaStaticInst version only in
+ // printing suffixes for non-default rounding & trapping modes.
+ std::string
+ generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+ };
+
+}};
+
+
+output decoder {{
+ int
+ AlphaFP::getC99RoundingMode(uint64_t fpcr_val) const
+ {
+ if (roundingMode == Dynamic) {
+ return alphaToC99RoundingMode[bits(fpcr_val, 59, 58)];
+ }
+ else {
+ return alphaToC99RoundingMode[roundingMode];
+ }
+ }
+
+ std::string
+ AlphaFP::generateDisassembly(Addr pc, const SymbolTable *symtab) const
+ {
+ std::string mnem_str(mnemonic);
+
+#ifndef SS_COMPATIBLE_DISASSEMBLY
+ std::string suffix("");
+ suffix += ((_destRegIdx[0] >= FP_Base_DepTag)
+ ? fpTrappingModeSuffix[trappingMode]
+ : intTrappingModeSuffix[trappingMode]);
+ suffix += roundingModeSuffix[roundingMode];
+
+ if (suffix != "") {
+ mnem_str = csprintf("%s/%s", mnemonic, suffix);
+ }
+#endif
+
+ std::stringstream ss;
+ ccprintf(ss, "%-10s ", mnem_str.c_str());
+
+ // just print the first two source regs... if there's
+ // a third one, it's a read-modify-write dest (Rc),
+ // e.g. for CMOVxx
+ if (_numSrcRegs > 0) {
+ printReg(ss, _srcRegIdx[0]);
+ }
+ if (_numSrcRegs > 1) {
+ ss << ",";
+ printReg(ss, _srcRegIdx[1]);
+ }
+
+ // just print the first dest... if there's a second one,
+ // it's generally implicit
+ if (_numDestRegs > 0) {
+ if (_numSrcRegs > 0)
+ ss << ",";
+ printReg(ss, _destRegIdx[0]);
+ }
+
+ return ss.str();
+ }
+
+ const int AlphaFP::alphaToC99RoundingMode[] = {
+ FE_TOWARDZERO, // Chopped
+ FE_DOWNWARD, // Minus_Infinity
+ FE_TONEAREST, // Normal
+ FE_UPWARD // Dynamic in inst, Plus_Infinity in FPCR
+ };
+
+ const char *AlphaFP::roundingModeSuffix[] = { "c", "m", "", "d" };
+ // mark invalid trapping modes, but don't fail on them, because
+ // you could decode anything on a misspeculated path
+ const char *AlphaFP::fpTrappingModeSuffix[] =
+ { "", "u", "INVTM2", "INVTM3", "INVTM4", "su", "INVTM6", "sui" };
+ const char *AlphaFP::intTrappingModeSuffix[] =
+ { "", "v", "INVTM2", "INVTM3", "INVTM4", "sv", "INVTM6", "svi" };
+}};
+
+// FP instruction class execute method template. Handles non-standard
+// rounding modes.
+def template FloatingPointExecute {{
+ Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData) const
+ {
+ if (trappingMode != Imprecise && !warnedOnTrapping) {
+ warn("%s: non-standard trapping mode not supported",
+ generateDisassembly(0, NULL));
+ warnedOnTrapping = true;
+ }
+
+ Fault fault = NoFault;
+
+ %(fp_enable_check)s;
+ %(op_decl)s;
+ %(op_rd)s;
+#if USE_FENV
+ if (roundingMode == Normal) {
+ %(code)s;
+ } else {
+ fesetround(getC99RoundingMode(
+ xc->readMiscReg(AlphaISA::Fpcr_DepTag)));
+ %(code)s;
+ fesetround(FE_TONEAREST);
+ }
+#else
+ if (roundingMode != Normal && !warnedOnRounding) {
+ warn("%s: non-standard rounding mode not supported",
+ generateDisassembly(0, NULL));
+ warnedOnRounding = true;
+ }
+ %(code)s;
+#endif
+
+ if (fault == NoFault) {
+ %(op_wb)s;
+ }
+
+ return fault;
+ }
+}};
+
+// FP instruction class execute method template where no dynamic
+// rounding mode control is needed. Like BasicExecute, but includes
+// check & warning for non-standard trapping mode.
+def template FPFixedRoundingExecute {{
+ Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData) const
+ {
+ if (trappingMode != Imprecise && !warnedOnTrapping) {
+ warn("%s: non-standard trapping mode not supported",
+ generateDisassembly(0, NULL));
+ warnedOnTrapping = true;
+ }
+
+ Fault fault = NoFault;
+
+ %(fp_enable_check)s;
+ %(op_decl)s;
+ %(op_rd)s;
+ %(code)s;
+
+ if (fault == NoFault) {
+ %(op_wb)s;
+ }
+
+ return fault;
+ }
+}};
+
+def template FloatingPointDecode {{
+ {
+ AlphaStaticInst *i = new %(class_name)s(machInst);
+ if (FC == 31) {
+ i = makeNop(i);
+ }
+ return i;
+ }
+}};
+
+// General format for floating-point operate instructions:
+// - Checks trapping and rounding mode flags. Trapping modes
+// currently unimplemented (will fail).
+// - Generates NOP if FC == 31.
+def format FloatingPointOperate(code, *opt_args) {{
+ iop = InstObjParams(name, Name, 'AlphaFP', CodeBlock(code), opt_args)
+ decode_block = FloatingPointDecode.subst(iop)
+ header_output = BasicDeclare.subst(iop)
+ decoder_output = BasicConstructor.subst(iop)
+ exec_output = FloatingPointExecute.subst(iop)
+}};
+
+// Special format for cvttq where rounding mode is pre-decoded
+def format FPFixedRounding(code, class_suffix, *opt_args) {{
+ Name += class_suffix
+ iop = InstObjParams(name, Name, 'AlphaFP', CodeBlock(code), opt_args)
+ decode_block = FloatingPointDecode.subst(iop)
+ header_output = BasicDeclare.subst(iop)
+ decoder_output = BasicConstructor.subst(iop)
+ exec_output = FPFixedRoundingExecute.subst(iop)
+}};
+
diff --git a/arch/alpha/isa/int.isa b/arch/alpha/isa/int.isa
new file mode 100644
index 000000000..17ecc1a51
--- /dev/null
+++ b/arch/alpha/isa/int.isa
@@ -0,0 +1,128 @@
+// -*- mode:c++ -*-
+
+// Copyright (c) 2003-2005 The Regents of The University of Michigan
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met: redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer;
+// redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution;
+// neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+output header {{
+ /**
+ * Base class for integer immediate instructions.
+ */
+ class IntegerImm : public AlphaStaticInst
+ {
+ protected:
+ /// Immediate operand value (unsigned 8-bit int).
+ uint8_t imm;
+
+ /// Constructor
+ IntegerImm(const char *mnem, ExtMachInst _machInst, OpClass __opClass)
+ : AlphaStaticInst(mnem, _machInst, __opClass), imm(INTIMM)
+ {
+ }
+
+ std::string
+ generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+ };
+}};
+
+output decoder {{
+ std::string
+ IntegerImm::generateDisassembly(Addr pc, const SymbolTable *symtab) const
+ {
+ std::stringstream ss;
+
+ ccprintf(ss, "%-10s ", mnemonic);
+
+ // just print the first source reg... if there's
+ // a second one, it's a read-modify-write dest (Rc),
+ // e.g. for CMOVxx
+ if (_numSrcRegs > 0) {
+ printReg(ss, _srcRegIdx[0]);
+ ss << ",";
+ }
+
+ ss << (int)imm;
+
+ if (_numDestRegs > 0) {
+ ss << ",";
+ printReg(ss, _destRegIdx[0]);
+ }
+
+ return ss.str();
+ }
+}};
+
+
+def template RegOrImmDecode {{
+ {
+ AlphaStaticInst *i =
+ (IMM) ? (AlphaStaticInst *)new %(class_name)sImm(machInst)
+ : (AlphaStaticInst *)new %(class_name)s(machInst);
+ if (RC == 31) {
+ i = makeNop(i);
+ }
+ return i;
+ }
+}};
+
+// Primary format for integer operate instructions:
+// - Generates both reg-reg and reg-imm versions if Rb_or_imm is used.
+// - Generates NOP if RC == 31.
+def format IntegerOperate(code, *opt_flags) {{
+ # If the code block contains 'Rb_or_imm', we define two instructions,
+ # one using 'Rb' and one using 'imm', and have the decoder select
+ # the right one.
+ uses_imm = (code.find('Rb_or_imm') != -1)
+ if uses_imm:
+ orig_code = code
+ # base code is reg version:
+ # rewrite by substituting 'Rb' for 'Rb_or_imm'
+ code = re.sub(r'Rb_or_imm', 'Rb', orig_code)
+ # generate immediate version by substituting 'imm'
+ # note that imm takes no extenstion, so we extend
+ # the regexp to replace any extension as well
+ imm_code = re.sub(r'Rb_or_imm(\.\w+)?', 'imm', orig_code)
+
+ # generate declaration for register version
+ cblk = CodeBlock(code)
+ iop = InstObjParams(name, Name, 'AlphaStaticInst', cblk, opt_flags)
+ header_output = BasicDeclare.subst(iop)
+ decoder_output = BasicConstructor.subst(iop)
+ exec_output = BasicExecute.subst(iop)
+
+ if uses_imm:
+ # append declaration for imm version
+ imm_cblk = CodeBlock(imm_code)
+ imm_iop = InstObjParams(name, Name + 'Imm', 'IntegerImm', imm_cblk,
+ opt_flags)
+ header_output += BasicDeclare.subst(imm_iop)
+ decoder_output += BasicConstructor.subst(imm_iop)
+ exec_output += BasicExecute.subst(imm_iop)
+ # decode checks IMM bit to pick correct version
+ decode_block = RegOrImmDecode.subst(iop)
+ else:
+ # no imm version: just check for nop
+ decode_block = OperateNopCheckDecode.subst(iop)
+}};
diff --git a/arch/alpha/isa/main.isa b/arch/alpha/isa/main.isa
new file mode 100644
index 000000000..d4c744fbc
--- /dev/null
+++ b/arch/alpha/isa/main.isa
@@ -0,0 +1,448 @@
+// -*- mode:c++ -*-
+
+// Copyright (c) 2003-2005 The Regents of The University of Michigan
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met: redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer;
+// redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution;
+// neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+output header {{
+#include <sstream>
+#include <iostream>
+#include <iomanip>
+
+#include "config/ss_compatible_fp.hh"
+#include "cpu/static_inst.hh"
+#include "arch/alpha/faults.hh"
+#include "mem/request.hh" // some constructors use MemReq flags
+}};
+
+output decoder {{
+#include "base/cprintf.hh"
+#include "base/fenv.hh"
+#include "base/loader/symtab.hh"
+#include "config/ss_compatible_fp.hh"
+#include "cpu/exec_context.hh" // for Jump::branchTarget()
+
+#include <math.h>
+
+using namespace AlphaISA;
+}};
+
+output exec {{
+#include <math.h>
+
+#if FULL_SYSTEM
+#include "sim/pseudo_inst.hh"
+#endif
+#include "base/fenv.hh"
+#include "config/ss_compatible_fp.hh"
+#include "cpu/base.hh"
+#include "cpu/exetrace.hh"
+#include "sim/sim_exit.hh"
+
+using namespace AlphaISA;
+}};
+
+////////////////////////////////////////////////////////////////////
+//
+// Namespace statement. Everything below this line will be in the
+// AlphaISAInst namespace.
+//
+
+
+namespace AlphaISA;
+
+////////////////////////////////////////////////////////////////////
+//
+// Bitfield definitions.
+//
+
+// Universal (format-independent) fields
+def bitfield PALMODE <32:32>;
+def bitfield OPCODE <31:26>;
+def bitfield RA <25:21>;
+def bitfield RB <20:16>;
+
+// Memory format
+def signed bitfield MEMDISP <15: 0>; // displacement
+def bitfield MEMFUNC <15: 0>; // function code (same field, unsigned)
+
+// Memory-format jumps
+def bitfield JMPFUNC <15:14>; // function code (disp<15:14>)
+def bitfield JMPHINT <13: 0>; // tgt Icache idx hint (disp<13:0>)
+
+// Branch format
+def signed bitfield BRDISP <20: 0>; // displacement
+
+// Integer operate format(s>;
+def bitfield INTIMM <20:13>; // integer immediate (literal)
+def bitfield IMM <12:12>; // immediate flag
+def bitfield INTFUNC <11: 5>; // function code
+def bitfield RC < 4: 0>; // dest reg
+
+// Floating-point operate format
+def bitfield FA <25:21>;
+def bitfield FB <20:16>;
+def bitfield FP_FULLFUNC <15: 5>; // complete function code
+ def bitfield FP_TRAPMODE <15:13>; // trapping mode
+ def bitfield FP_ROUNDMODE <12:11>; // rounding mode
+ def bitfield FP_TYPEFUNC <10: 5>; // type+func: handiest for decoding
+ def bitfield FP_SRCTYPE <10: 9>; // source reg type
+ def bitfield FP_SHORTFUNC < 8: 5>; // short function code
+ def bitfield FP_SHORTFUNC_TOP2 <8:7>; // top 2 bits of short func code
+def bitfield FC < 4: 0>; // dest reg
+
+// PALcode format
+def bitfield PALFUNC <25: 0>; // function code
+
+// EV5 PAL instructions:
+// HW_LD/HW_ST
+def bitfield HW_LDST_PHYS <15>; // address is physical
+def bitfield HW_LDST_ALT <14>; // use ALT_MODE IPR
+def bitfield HW_LDST_WRTCK <13>; // HW_LD only: fault if no write acc
+def bitfield HW_LDST_QUAD <12>; // size: 0=32b, 1=64b
+def bitfield HW_LDST_VPTE <11>; // HW_LD only: is PTE fetch
+def bitfield HW_LDST_LOCK <10>; // HW_LD only: is load locked
+def bitfield HW_LDST_COND <10>; // HW_ST only: is store conditional
+def signed bitfield HW_LDST_DISP <9:0>; // signed displacement
+
+// HW_REI
+def bitfield HW_REI_TYP <15:14>; // type: stalling vs. non-stallingk
+def bitfield HW_REI_MBZ <13: 0>; // must be zero
+
+// HW_MTPR/MW_MFPR
+def bitfield HW_IPR_IDX <15:0>; // IPR index
+
+// M5 instructions
+def bitfield M5FUNC <7:0>;
+
+def operand_types {{
+ 'sb' : ('signed int', 8),
+ 'ub' : ('unsigned int', 8),
+ 'sw' : ('signed int', 16),
+ 'uw' : ('unsigned int', 16),
+ 'sl' : ('signed int', 32),
+ 'ul' : ('unsigned int', 32),
+ 'sq' : ('signed int', 64),
+ 'uq' : ('unsigned int', 64),
+ 'sf' : ('float', 32),
+ 'df' : ('float', 64)
+}};
+
+def operands {{
+ # Int regs default to unsigned, but code should not count on this.
+ # For clarity, descriptions that depend on unsigned behavior should
+ # explicitly specify '.uq'.
+ 'Ra': ('IntReg', 'uq', 'PALMODE ? AlphaISA::reg_redir[RA] : RA',
+ 'IsInteger', 1),
+ 'Rb': ('IntReg', 'uq', 'PALMODE ? AlphaISA::reg_redir[RB] : RB',
+ 'IsInteger', 2),
+ 'Rc': ('IntReg', 'uq', 'PALMODE ? AlphaISA::reg_redir[RC] : RC',
+ 'IsInteger', 3),
+ 'Fa': ('FloatReg', 'df', 'FA', 'IsFloating', 1),
+ 'Fb': ('FloatReg', 'df', 'FB', 'IsFloating', 2),
+ 'Fc': ('FloatReg', 'df', 'FC', 'IsFloating', 3),
+ 'Mem': ('Mem', 'uq', None, ('IsMemRef', 'IsLoad', 'IsStore'), 4),
+ 'NPC': ('NPC', 'uq', None, ( None, None, 'IsControl' ), 4),
+ 'Runiq': ('ControlReg', 'uq', 'TheISA::Uniq_DepTag', None, 1),
+ 'FPCR': (' ControlReg', 'uq', 'TheISA::Fpcr_DepTag', None, 1),
+ # The next two are hacks for non-full-system call-pal emulation
+ 'R0': ('IntReg', 'uq', '0', None, 1),
+ 'R16': ('IntReg', 'uq', '16', None, 1),
+ 'R17': ('IntReg', 'uq', '17', None, 1),
+ 'R18': ('IntReg', 'uq', '18', None, 1)
+}};
+
+////////////////////////////////////////////////////////////////////
+//
+// Basic instruction classes/templates/formats etc.
+//
+
+output header {{
+// uncomment the following to get SimpleScalar-compatible disassembly
+// (useful for diffing output traces).
+// #define SS_COMPATIBLE_DISASSEMBLY
+
+ /**
+ * Base class for all Alpha static instructions.
+ */
+ class AlphaStaticInst : public StaticInst
+ {
+ protected:
+
+ /// Make AlphaISA register dependence tags directly visible in
+ /// this class and derived classes. Maybe these should really
+ /// live here and not in the AlphaISA namespace.
+ enum DependenceTags {
+ FP_Base_DepTag = AlphaISA::FP_Base_DepTag,
+ Fpcr_DepTag = AlphaISA::Fpcr_DepTag,
+ Uniq_DepTag = AlphaISA::Uniq_DepTag,
+ Lock_Flag_DepTag = AlphaISA::Lock_Flag_DepTag,
+ Lock_Addr_DepTag = AlphaISA::Lock_Addr_DepTag,
+ IPR_Base_DepTag = AlphaISA::IPR_Base_DepTag
+ };
+
+ /// Constructor.
+ AlphaStaticInst(const char *mnem, ExtMachInst _machInst,
+ OpClass __opClass)
+ : StaticInst(mnem, _machInst, __opClass)
+ {
+ }
+
+ /// Print a register name for disassembly given the unique
+ /// dependence tag number (FP or int).
+ void printReg(std::ostream &os, int reg) const;
+
+ std::string
+ generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+ };
+}};
+
+output decoder {{
+ void
+ AlphaStaticInst::printReg(std::ostream &os, int reg) const
+ {
+ if (reg < FP_Base_DepTag) {
+ ccprintf(os, "r%d", reg);
+ }
+ else {
+ ccprintf(os, "f%d", reg - FP_Base_DepTag);
+ }
+ }
+
+ std::string
+ AlphaStaticInst::generateDisassembly(Addr pc,
+ const SymbolTable *symtab) const
+ {
+ std::stringstream ss;
+
+ ccprintf(ss, "%-10s ", mnemonic);
+
+ // just print the first two source regs... if there's
+ // a third one, it's a read-modify-write dest (Rc),
+ // e.g. for CMOVxx
+ if (_numSrcRegs > 0) {
+ printReg(ss, _srcRegIdx[0]);
+ }
+ if (_numSrcRegs > 1) {
+ ss << ",";
+ printReg(ss, _srcRegIdx[1]);
+ }
+
+ // just print the first dest... if there's a second one,
+ // it's generally implicit
+ if (_numDestRegs > 0) {
+ if (_numSrcRegs > 0)
+ ss << ",";
+ printReg(ss, _destRegIdx[0]);
+ }
+
+ return ss.str();
+ }
+}};
+
+// Declarations for execute() methods.
+def template BasicExecDeclare {{
+ Fault execute(%(CPU_exec_context)s *, Trace::InstRecord *) const;
+}};
+
+// Basic instruction class declaration template.
+def template BasicDeclare {{
+ /**
+ * Static instruction class for "%(mnemonic)s".
+ */
+ class %(class_name)s : public %(base_class)s
+ {
+ public:
+ /// Constructor.
+ %(class_name)s(ExtMachInst machInst);
+
+ %(BasicExecDeclare)s
+ };
+}};
+
+// Basic instruction class constructor template.
+def template BasicConstructor {{
+ inline %(class_name)s::%(class_name)s(ExtMachInst machInst)
+ : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s)
+ {
+ %(constructor)s;
+ }
+}};
+
+// Basic instruction class execute method template.
+def template BasicExecute {{
+ Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData) const
+ {
+ Fault fault = NoFault;
+
+ %(fp_enable_check)s;
+ %(op_decl)s;
+ %(op_rd)s;
+ %(code)s;
+
+ if (fault == NoFault) {
+ %(op_wb)s;
+ }
+
+ return fault;
+ }
+}};
+
+// Basic decode template.
+def template BasicDecode {{
+ return new %(class_name)s(machInst);
+}};
+
+// Basic decode template, passing mnemonic in as string arg to constructor.
+def template BasicDecodeWithMnemonic {{
+ return new %(class_name)s("%(mnemonic)s", machInst);
+}};
+
+// The most basic instruction format... used only for a few misc. insts
+def format BasicOperate(code, *flags) {{
+ iop = InstObjParams(name, Name, 'AlphaStaticInst', CodeBlock(code), flags)
+ header_output = BasicDeclare.subst(iop)
+ decoder_output = BasicConstructor.subst(iop)
+ decode_block = BasicDecode.subst(iop)
+ exec_output = BasicExecute.subst(iop)
+}};
+
+
+
+////////////////////////////////////////////////////////////////////
+//
+// Nop
+//
+
+output header {{
+ /**
+ * Static instruction class for no-ops. This is a leaf class.
+ */
+ class Nop : public AlphaStaticInst
+ {
+ /// Disassembly of original instruction.
+ const std::string originalDisassembly;
+
+ public:
+ /// Constructor
+ Nop(const std::string _originalDisassembly, ExtMachInst _machInst)
+ : AlphaStaticInst("nop", _machInst, No_OpClass),
+ originalDisassembly(_originalDisassembly)
+ {
+ flags[IsNop] = true;
+ }
+
+ ~Nop() { }
+
+ std::string
+ generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+
+ %(BasicExecDeclare)s
+ };
+
+ /// Helper function for decoding nops. Substitute Nop object
+ /// for original inst passed in as arg (and delete latter).
+ static inline
+ AlphaStaticInst *
+ makeNop(AlphaStaticInst *inst)
+ {
+ AlphaStaticInst *nop = new Nop(inst->disassemble(0), inst->machInst);
+ delete inst;
+ return nop;
+ }
+}};
+
+output decoder {{
+ std::string Nop::generateDisassembly(Addr pc,
+ const SymbolTable *symtab) const
+ {
+#ifdef SS_COMPATIBLE_DISASSEMBLY
+ return originalDisassembly;
+#else
+ return csprintf("%-10s (%s)", "nop", originalDisassembly);
+#endif
+ }
+}};
+
+output exec {{
+ Fault
+ Nop::execute(%(CPU_exec_context)s *, Trace::InstRecord *) const
+ {
+ return NoFault;
+ }
+}};
+
+// integer & FP operate instructions use Rc as dest, so check for
+// Rc == 31 to detect nops
+def template OperateNopCheckDecode {{
+ {
+ AlphaStaticInst *i = new %(class_name)s(machInst);
+ if (RC == 31) {
+ i = makeNop(i);
+ }
+ return i;
+ }
+}};
+
+// Like BasicOperate format, but generates NOP if RC/FC == 31
+def format BasicOperateWithNopCheck(code, *opt_args) {{
+ iop = InstObjParams(name, Name, 'AlphaStaticInst', CodeBlock(code),
+ opt_args)
+ header_output = BasicDeclare.subst(iop)
+ decoder_output = BasicConstructor.subst(iop)
+ decode_block = OperateNopCheckDecode.subst(iop)
+ exec_output = BasicExecute.subst(iop)
+}};
+
+// Integer instruction templates, formats, etc.
+##include "m5/arch/alpha/isa/int.isa"
+
+// Floating-point instruction templates, formats, etc.
+##include "m5/arch/alpha/isa/fp.isa"
+
+// Memory instruction templates, formats, etc.
+##include "m5/arch/alpha/isa/mem.isa"
+
+// Branch/jump instruction templates, formats, etc.
+##include "m5/arch/alpha/isa/branch.isa"
+
+// PAL instruction templates, formats, etc.
+##include "m5/arch/alpha/isa/pal.isa"
+
+// Opcdec fault instruction templates, formats, etc.
+##include "m5/arch/alpha/isa/opcdec.isa"
+
+// Unimplemented instruction templates, formats, etc.
+##include "m5/arch/alpha/isa/unimp.isa"
+
+// Unknown instruction templates, formats, etc.
+##include "m5/arch/alpha/isa/unknown.isa"
+
+// Execution utility functions
+##include "m5/arch/alpha/isa/util.isa"
+
+// The actual decoder
+##include "m5/arch/alpha/isa/decoder.isa"
diff --git a/arch/alpha/isa/mem.isa b/arch/alpha/isa/mem.isa
new file mode 100644
index 000000000..3c8b4f755
--- /dev/null
+++ b/arch/alpha/isa/mem.isa
@@ -0,0 +1,702 @@
+// -*- mode:c++ -*-
+
+// Copyright (c) 2003-2005 The Regents of The University of Michigan
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met: redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer;
+// redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution;
+// neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+output header {{
+ /**
+ * Base class for general Alpha memory-format instructions.
+ */
+ class Memory : public AlphaStaticInst
+ {
+ protected:
+
+ /// Memory request flags. See mem_req_base.hh.
+ unsigned memAccessFlags;
+ /// Pointer to EAComp object.
+ const StaticInstPtr eaCompPtr;
+ /// Pointer to MemAcc object.
+ const StaticInstPtr memAccPtr;
+
+ /// Constructor
+ Memory(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
+ StaticInstPtr _eaCompPtr = nullStaticInstPtr,
+ StaticInstPtr _memAccPtr = nullStaticInstPtr)
+ : AlphaStaticInst(mnem, _machInst, __opClass),
+ memAccessFlags(0), eaCompPtr(_eaCompPtr), memAccPtr(_memAccPtr)
+ {
+ }
+
+ std::string
+ generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+
+ public:
+
+ const StaticInstPtr &eaCompInst() const { return eaCompPtr; }
+ const StaticInstPtr &memAccInst() const { return memAccPtr; }
+ };
+
+ /**
+ * Base class for memory-format instructions using a 32-bit
+ * displacement (i.e. most of them).
+ */
+ class MemoryDisp32 : public Memory
+ {
+ protected:
+ /// Displacement for EA calculation (signed).
+ int32_t disp;
+
+ /// Constructor.
+ MemoryDisp32(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
+ StaticInstPtr _eaCompPtr = nullStaticInstPtr,
+ StaticInstPtr _memAccPtr = nullStaticInstPtr)
+ : Memory(mnem, _machInst, __opClass, _eaCompPtr, _memAccPtr),
+ disp(MEMDISP)
+ {
+ }
+ };
+
+
+ /**
+ * Base class for a few miscellaneous memory-format insts
+ * that don't interpret the disp field: wh64, fetch, fetch_m, ecb.
+ * None of these instructions has a destination register either.
+ */
+ class MemoryNoDisp : public Memory
+ {
+ protected:
+ /// Constructor
+ MemoryNoDisp(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
+ StaticInstPtr _eaCompPtr = nullStaticInstPtr,
+ StaticInstPtr _memAccPtr = nullStaticInstPtr)
+ : Memory(mnem, _machInst, __opClass, _eaCompPtr, _memAccPtr)
+ {
+ }
+
+ std::string
+ generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+ };
+}};
+
+
+output decoder {{
+ std::string
+ Memory::generateDisassembly(Addr pc, const SymbolTable *symtab) const
+ {
+ return csprintf("%-10s %c%d,%d(r%d)", mnemonic,
+ flags[IsFloating] ? 'f' : 'r', RA, MEMDISP, RB);
+ }
+
+ std::string
+ MemoryNoDisp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
+ {
+ return csprintf("%-10s (r%d)", mnemonic, RB);
+ }
+}};
+
+def format LoadAddress(code) {{
+ iop = InstObjParams(name, Name, 'MemoryDisp32', CodeBlock(code))
+ header_output = BasicDeclare.subst(iop)
+ decoder_output = BasicConstructor.subst(iop)
+ decode_block = BasicDecode.subst(iop)
+ exec_output = BasicExecute.subst(iop)
+}};
+
+
+def template LoadStoreDeclare {{
+ /**
+ * Static instruction class for "%(mnemonic)s".
+ */
+ class %(class_name)s : public %(base_class)s
+ {
+ protected:
+
+ /**
+ * "Fake" effective address computation class for "%(mnemonic)s".
+ */
+ class EAComp : public %(base_class)s
+ {
+ public:
+ /// Constructor
+ EAComp(ExtMachInst machInst);
+
+ %(BasicExecDeclare)s
+ };
+
+ /**
+ * "Fake" memory access instruction class for "%(mnemonic)s".
+ */
+ class MemAcc : public %(base_class)s
+ {
+ public:
+ /// Constructor
+ MemAcc(ExtMachInst machInst);
+
+ %(BasicExecDeclare)s
+ };
+
+ public:
+
+ /// Constructor.
+ %(class_name)s(ExtMachInst machInst);
+
+ %(BasicExecDeclare)s
+
+ %(InitiateAccDeclare)s
+
+ %(CompleteAccDeclare)s
+ };
+}};
+
+
+def template InitiateAccDeclare {{
+ Fault initiateAcc(%(CPU_exec_context)s *, Trace::InstRecord *) const;
+}};
+
+
+def template CompleteAccDeclare {{
+ Fault completeAcc(uint8_t *, %(CPU_exec_context)s *, Trace::InstRecord *) const;
+}};
+
+
+def template LoadStoreConstructor {{
+ /** TODO: change op_class to AddrGenOp or something (requires
+ * creating new member of OpClass enum in op_class.hh, updating
+ * config files, etc.). */
+ inline %(class_name)s::EAComp::EAComp(ExtMachInst machInst)
+ : %(base_class)s("%(mnemonic)s (EAComp)", machInst, IntAluOp)
+ {
+ %(ea_constructor)s;
+ }
+
+ inline %(class_name)s::MemAcc::MemAcc(ExtMachInst machInst)
+ : %(base_class)s("%(mnemonic)s (MemAcc)", machInst, %(op_class)s)
+ {
+ %(memacc_constructor)s;
+ }
+
+ inline %(class_name)s::%(class_name)s(ExtMachInst machInst)
+ : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s,
+ new EAComp(machInst), new MemAcc(machInst))
+ {
+ %(constructor)s;
+ }
+}};
+
+
+def template EACompExecute {{
+ Fault
+ %(class_name)s::EAComp::execute(%(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData) const
+ {
+ Addr EA;
+ Fault fault = NoFault;
+
+ %(fp_enable_check)s;
+ %(op_decl)s;
+ %(op_rd)s;
+ %(code)s;
+
+ if (fault == NoFault) {
+ %(op_wb)s;
+ xc->setEA(EA);
+ }
+
+ return fault;
+ }
+}};
+
+def template LoadMemAccExecute {{
+ Fault
+ %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData) const
+ {
+ Addr EA;
+ Fault fault = NoFault;
+
+ %(fp_enable_check)s;
+ %(op_decl)s;
+ %(op_rd)s;
+ EA = xc->getEA();
+
+ if (fault == NoFault) {
+ fault = xc->read(EA, (uint%(mem_acc_size)d_t&)Mem, memAccessFlags);
+ %(code)s;
+ }
+
+ if (fault == NoFault) {
+ %(op_wb)s;
+ }
+
+ return fault;
+ }
+}};
+
+
+def template LoadExecute {{
+ Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData) const
+ {
+ Addr EA;
+ Fault fault = NoFault;
+
+ %(fp_enable_check)s;
+ %(op_decl)s;
+ %(op_rd)s;
+ %(ea_code)s;
+
+ if (fault == NoFault) {
+ fault = xc->read(EA, (uint%(mem_acc_size)d_t&)Mem, memAccessFlags);
+ %(memacc_code)s;
+ }
+
+ if (fault == NoFault) {
+ %(op_wb)s;
+ }
+
+ return fault;
+ }
+}};
+
+
+def template LoadInitiateAcc {{
+ Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData) const
+ {
+ Addr EA;
+ Fault fault = NoFault;
+
+ %(fp_enable_check)s;
+ %(op_src_decl)s;
+ %(op_rd)s;
+ %(ea_code)s;
+
+ if (fault == NoFault) {
+ fault = xc->read(EA, (uint%(mem_acc_size)d_t &)Mem, memAccessFlags);
+ }
+
+ return fault;
+ }
+}};
+
+
+def template LoadCompleteAcc {{
+ Fault %(class_name)s::completeAcc(uint8_t *data,
+ %(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData) const
+ {
+ Fault fault = NoFault;
+
+ %(fp_enable_check)s;
+ %(op_src_decl)s;
+ %(op_dest_decl)s;
+
+ memcpy(&Mem, data, sizeof(Mem));
+
+ if (fault == NoFault) {
+ %(memacc_code)s;
+ }
+
+ if (fault == NoFault) {
+ %(op_wb)s;
+ }
+
+ return fault;
+ }
+}};
+
+
+def template StoreMemAccExecute {{
+ Fault
+ %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData) const
+ {
+ Addr EA;
+ Fault fault = NoFault;
+ uint64_t write_result = 0;
+
+ %(fp_enable_check)s;
+ %(op_decl)s;
+ %(op_rd)s;
+ EA = xc->getEA();
+
+ if (fault == NoFault) {
+ %(code)s;
+ }
+
+ if (fault == NoFault) {
+ fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA,
+ memAccessFlags, &write_result);
+ if (traceData) { traceData->setData(Mem); }
+ }
+
+ if (fault == NoFault) {
+ %(postacc_code)s;
+ }
+
+ if (fault == NoFault) {
+ %(op_wb)s;
+ }
+
+ return fault;
+ }
+}};
+
+
+def template StoreExecute {{
+ Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData) const
+ {
+ Addr EA;
+ Fault fault = NoFault;
+ uint64_t write_result = 0;
+
+ %(fp_enable_check)s;
+ %(op_decl)s;
+ %(op_rd)s;
+ %(ea_code)s;
+
+ if (fault == NoFault) {
+ %(memacc_code)s;
+ }
+
+ if (fault == NoFault) {
+ fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA,
+ memAccessFlags, &write_result);
+ if (traceData) { traceData->setData(Mem); }
+ }
+
+ if (fault == NoFault) {
+ %(postacc_code)s;
+ }
+
+ if (fault == NoFault) {
+ %(op_wb)s;
+ }
+
+ return fault;
+ }
+}};
+
+def template StoreInitiateAcc {{
+ Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData) const
+ {
+ Addr EA;
+ Fault fault = NoFault;
+ uint64_t write_result = 0;
+
+ %(fp_enable_check)s;
+ %(op_src_decl)s;
+ %(op_dest_decl)s;
+ %(op_rd)s;
+ %(ea_code)s;
+
+ if (fault == NoFault) {
+ %(memacc_code)s;
+ }
+
+ if (fault == NoFault) {
+ fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA,
+ memAccessFlags, &write_result);
+ if (traceData) { traceData->setData(Mem); }
+ }
+
+ return fault;
+ }
+}};
+
+
+def template StoreCompleteAcc {{
+ Fault %(class_name)s::completeAcc(uint8_t *data,
+ %(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData) const
+ {
+ Fault fault = NoFault;
+ uint64_t write_result = 0;
+
+ %(fp_enable_check)s;
+ %(op_dest_decl)s;
+
+ memcpy(&write_result, data, sizeof(write_result));
+
+ if (fault == NoFault) {
+ %(postacc_code)s;
+ }
+
+ if (fault == NoFault) {
+ %(op_wb)s;
+ }
+
+ return fault;
+ }
+}};
+
+
+def template MiscMemAccExecute {{
+ Fault %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData) const
+ {
+ Addr EA;
+ Fault fault = NoFault;
+
+ %(fp_enable_check)s;
+ %(op_decl)s;
+ %(op_rd)s;
+ EA = xc->getEA();
+
+ if (fault == NoFault) {
+ %(code)s;
+ }
+
+ return NoFault;
+ }
+}};
+
+def template MiscExecute {{
+ Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData) const
+ {
+ Addr EA;
+ Fault fault = NoFault;
+
+ %(fp_enable_check)s;
+ %(op_decl)s;
+ %(op_rd)s;
+ %(ea_code)s;
+
+ if (fault == NoFault) {
+ %(memacc_code)s;
+ }
+
+ return NoFault;
+ }
+}};
+
+def template MiscInitiateAcc {{
+ Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData) const
+ {
+ panic("Misc instruction does not support split access method!");
+ return NoFault;
+ }
+}};
+
+
+def template MiscCompleteAcc {{
+ Fault %(class_name)s::completeAcc(uint8_t *data,
+ %(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData) const
+ {
+ panic("Misc instruction does not support split access method!");
+
+ return NoFault;
+ }
+}};
+
+// load instructions use Ra as dest, so check for
+// Ra == 31 to detect nops
+def template LoadNopCheckDecode {{
+ {
+ AlphaStaticInst *i = new %(class_name)s(machInst);
+ if (RA == 31) {
+ i = makeNop(i);
+ }
+ return i;
+ }
+}};
+
+
+// for some load instructions, Ra == 31 indicates a prefetch (not a nop)
+def template LoadPrefetchCheckDecode {{
+ {
+ if (RA != 31) {
+ return new %(class_name)s(machInst);
+ }
+ else {
+ return new %(class_name)sPrefetch(machInst);
+ }
+ }
+}};
+
+
+let {{
+def LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
+ postacc_code = '', base_class = 'MemoryDisp32',
+ decode_template = BasicDecode, exec_template_base = ''):
+ # Make sure flags are in lists (convert to lists if not).
+ mem_flags = makeList(mem_flags)
+ inst_flags = makeList(inst_flags)
+
+ # add hook to get effective addresses into execution trace output.
+ ea_code += '\nif (traceData) { traceData->setAddr(EA); }\n'
+
+ # generate code block objects
+ ea_cblk = CodeBlock(ea_code)
+ memacc_cblk = CodeBlock(memacc_code)
+ postacc_cblk = CodeBlock(postacc_code)
+
+ # Some CPU models execute the memory operation as an atomic unit,
+ # while others want to separate them into an effective address
+ # computation and a memory access operation. As a result, we need
+ # to generate three StaticInst objects. Note that the latter two
+ # are nested inside the larger "atomic" one.
+
+ # generate InstObjParams for EAComp object
+ ea_iop = InstObjParams(name, Name, base_class, ea_cblk, inst_flags)
+
+ # generate InstObjParams for MemAcc object
+ memacc_iop = InstObjParams(name, Name, base_class, memacc_cblk, inst_flags)
+ # in the split execution model, the MemAcc portion is responsible
+ # for the post-access code.
+ memacc_iop.postacc_code = postacc_cblk.code
+
+ # generate InstObjParams for InitiateAcc, CompleteAcc object
+ # The code used depends on the template being used
+ if (exec_template_base == 'Load'):
+ initiateacc_cblk = CodeBlock(ea_code + memacc_code)
+ completeacc_cblk = CodeBlock(memacc_code + postacc_code)
+ elif (exec_template_base == 'Store'):
+ initiateacc_cblk = CodeBlock(ea_code + memacc_code)
+ completeacc_cblk = CodeBlock(postacc_code)
+ else:
+ initiateacc_cblk = ''
+ completeacc_cblk = ''
+
+ initiateacc_iop = InstObjParams(name, Name, base_class, initiateacc_cblk,
+ inst_flags)
+
+ completeacc_iop = InstObjParams(name, Name, base_class, completeacc_cblk,
+ inst_flags)
+
+ if (exec_template_base == 'Load'):
+ initiateacc_iop.ea_code = ea_cblk.code
+ initiateacc_iop.memacc_code = memacc_cblk.code
+ completeacc_iop.memacc_code = memacc_cblk.code
+ completeacc_iop.postacc_code = postacc_cblk.code
+ elif (exec_template_base == 'Store'):
+ initiateacc_iop.ea_code = ea_cblk.code
+ initiateacc_iop.memacc_code = memacc_cblk.code
+ completeacc_iop.postacc_code = postacc_cblk.code
+
+ # generate InstObjParams for unified execution
+ cblk = CodeBlock(ea_code + memacc_code + postacc_code)
+ iop = InstObjParams(name, Name, base_class, cblk, inst_flags)
+
+ iop.ea_constructor = ea_cblk.constructor
+ iop.ea_code = ea_cblk.code
+ iop.memacc_constructor = memacc_cblk.constructor
+ iop.memacc_code = memacc_cblk.code
+ iop.postacc_code = postacc_cblk.code
+
+ if mem_flags:
+ s = '\n\tmemAccessFlags = ' + string.join(mem_flags, '|') + ';'
+ iop.constructor += s
+ memacc_iop.constructor += s
+
+ # select templates
+ memAccExecTemplate = eval(exec_template_base + 'MemAccExecute')
+ fullExecTemplate = eval(exec_template_base + 'Execute')
+ initiateAccTemplate = eval(exec_template_base + 'InitiateAcc')
+ completeAccTemplate = eval(exec_template_base + 'CompleteAcc')
+
+ # (header_output, decoder_output, decode_block, exec_output)
+ return (LoadStoreDeclare.subst(iop), LoadStoreConstructor.subst(iop),
+ decode_template.subst(iop),
+ EACompExecute.subst(ea_iop)
+ + memAccExecTemplate.subst(memacc_iop)
+ + fullExecTemplate.subst(iop)
+ + initiateAccTemplate.subst(initiateacc_iop)
+ + completeAccTemplate.subst(completeacc_iop))
+}};
+
+
+def format LoadOrNop(memacc_code, ea_code = {{ EA = Rb + disp; }},
+ mem_flags = [], inst_flags = []) {{
+ (header_output, decoder_output, decode_block, exec_output) = \
+ LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
+ decode_template = LoadNopCheckDecode,
+ exec_template_base = 'Load')
+}};
+
+
+// Note that the flags passed in apply only to the prefetch version
+def format LoadOrPrefetch(memacc_code, ea_code = {{ EA = Rb + disp; }},
+ mem_flags = [], pf_flags = [], inst_flags = []) {{
+ # declare the load instruction object and generate the decode block
+ (header_output, decoder_output, decode_block, exec_output) = \
+ LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
+ decode_template = LoadPrefetchCheckDecode,
+ exec_template_base = 'Load')
+
+ # Declare the prefetch instruction object.
+
+ # Make sure flag args are lists so we can mess with them.
+ mem_flags = makeList(mem_flags)
+ pf_flags = makeList(pf_flags)
+ inst_flags = makeList(inst_flags)
+
+ pf_mem_flags = mem_flags + pf_flags + ['NO_FAULT']
+ pf_inst_flags = inst_flags + ['IsMemRef', 'IsLoad',
+ 'IsDataPrefetch', 'MemReadOp']
+
+ (pf_header_output, pf_decoder_output, _, pf_exec_output) = \
+ LoadStoreBase(name, Name + 'Prefetch', ea_code,
+ 'xc->prefetch(EA, memAccessFlags);',
+ pf_mem_flags, pf_inst_flags, exec_template_base = 'Misc')
+
+ header_output += pf_header_output
+ decoder_output += pf_decoder_output
+ exec_output += pf_exec_output
+}};
+
+
+def format Store(memacc_code, ea_code = {{ EA = Rb + disp; }},
+ mem_flags = [], inst_flags = []) {{
+ (header_output, decoder_output, decode_block, exec_output) = \
+ LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
+ exec_template_base = 'Store')
+}};
+
+
+def format StoreCond(memacc_code, postacc_code,
+ ea_code = {{ EA = Rb + disp; }},
+ mem_flags = [], inst_flags = []) {{
+ (header_output, decoder_output, decode_block, exec_output) = \
+ LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
+ postacc_code, exec_template_base = 'Store')
+}};
+
+
+// Use 'MemoryNoDisp' as base: for wh64, fetch, ecb
+def format MiscPrefetch(ea_code, memacc_code,
+ mem_flags = [], inst_flags = []) {{
+ (header_output, decoder_output, decode_block, exec_output) = \
+ LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
+ base_class = 'MemoryNoDisp', exec_template_base = 'Misc')
+}};
+
+
diff --git a/arch/alpha/isa/opcdec.isa b/arch/alpha/isa/opcdec.isa
new file mode 100644
index 000000000..bb2f91e5c
--- /dev/null
+++ b/arch/alpha/isa/opcdec.isa
@@ -0,0 +1,72 @@
+// -*- mode:c++ -*-
+
+// Copyright (c) 2003-2005 The Regents of The University of Michigan
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met: redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer;
+// redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution;
+// neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+output header {{
+ /**
+ * Static instruction class for instructions that cause an OPCDEC fault
+ * when executed. This is currently only for PAL mode instructions
+ * executed in non-PAL mode.
+ */
+ class OpcdecFault : public AlphaStaticInst
+ {
+ public:
+ /// Constructor
+ OpcdecFault(ExtMachInst _machInst)
+ : AlphaStaticInst("opcdec fault", _machInst, No_OpClass)
+ {
+ }
+
+ %(BasicExecDeclare)s
+
+ std::string
+ generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+ };
+}};
+
+output decoder {{
+ std::string
+ OpcdecFault::generateDisassembly(Addr pc, const SymbolTable *symtab) const
+ {
+ return csprintf("%-10s (inst 0x%x, opcode 0x%x)",
+ " OPCDEC fault", machInst, OPCODE);
+ }
+}};
+
+output exec {{
+ Fault
+ OpcdecFault::execute(%(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData) const
+ {
+ return new UnimplementedOpcodeFault;
+ }
+}};
+
+def format OpcdecFault() {{
+ decode_block = 'return new OpcdecFault(machInst);\n'
+}};
+
diff --git a/arch/alpha/isa/pal.isa b/arch/alpha/isa/pal.isa
new file mode 100644
index 000000000..e07bea5a8
--- /dev/null
+++ b/arch/alpha/isa/pal.isa
@@ -0,0 +1,271 @@
+// -*- mode:c++ -*-
+
+// Copyright (c) 2003-2005 The Regents of The University of Michigan
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met: redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer;
+// redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution;
+// neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+output header {{
+ /**
+ * Base class for emulated call_pal calls (used only in
+ * non-full-system mode).
+ */
+ class EmulatedCallPal : public AlphaStaticInst
+ {
+ protected:
+
+ /// Constructor.
+ EmulatedCallPal(const char *mnem, ExtMachInst _machInst,
+ OpClass __opClass)
+ : AlphaStaticInst(mnem, _machInst, __opClass)
+ {
+ }
+
+ std::string
+ generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+ };
+}};
+
+output decoder {{
+ std::string
+ EmulatedCallPal::generateDisassembly(Addr pc,
+ const SymbolTable *symtab) const
+ {
+#ifdef SS_COMPATIBLE_DISASSEMBLY
+ return csprintf("%s %s", "call_pal", mnemonic);
+#else
+ return csprintf("%-10s %s", "call_pal", mnemonic);
+#endif
+ }
+}};
+
+def format EmulatedCallPal(code, *flags) {{
+ iop = InstObjParams(name, Name, 'EmulatedCallPal', CodeBlock(code), flags)
+ header_output = BasicDeclare.subst(iop)
+ decoder_output = BasicConstructor.subst(iop)
+ decode_block = BasicDecode.subst(iop)
+ exec_output = BasicExecute.subst(iop)
+}};
+
+output header {{
+ /**
+ * Base class for full-system-mode call_pal instructions.
+ * Probably could turn this into a leaf class and get rid of the
+ * parser template.
+ */
+ class CallPalBase : public AlphaStaticInst
+ {
+ protected:
+ int palFunc; ///< Function code part of instruction
+ int palOffset; ///< Target PC, offset from IPR_PAL_BASE
+ bool palValid; ///< is the function code valid?
+ bool palPriv; ///< is this call privileged?
+
+ /// Constructor.
+ CallPalBase(const char *mnem, ExtMachInst _machInst,
+ OpClass __opClass);
+
+ std::string
+ generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+ };
+}};
+
+output decoder {{
+ inline
+ CallPalBase::CallPalBase(const char *mnem, ExtMachInst _machInst,
+ OpClass __opClass)
+ : AlphaStaticInst(mnem, _machInst, __opClass),
+ palFunc(PALFUNC)
+ {
+ // From the 21164 HRM (paraphrased):
+ // Bit 7 of the function code (mask 0x80) indicates
+ // whether the call is privileged (bit 7 == 0) or
+ // unprivileged (bit 7 == 1). The privileged call table
+ // starts at 0x2000, the unprivielged call table starts at
+ // 0x3000. Bits 5-0 (mask 0x3f) are used to calculate the
+ // offset.
+ const int palPrivMask = 0x80;
+ const int palOffsetMask = 0x3f;
+
+ // Pal call is invalid unless all other bits are 0
+ palValid = ((machInst & ~(palPrivMask | palOffsetMask)) == 0);
+ palPriv = ((machInst & palPrivMask) == 0);
+ int shortPalFunc = (machInst & palOffsetMask);
+ // Add 1 to base to set pal-mode bit
+ palOffset = (palPriv ? 0x2001 : 0x3001) + (shortPalFunc << 6);
+ }
+
+ std::string
+ CallPalBase::generateDisassembly(Addr pc, const SymbolTable *symtab) const
+ {
+ return csprintf("%-10s %#x", "call_pal", palFunc);
+ }
+}};
+
+def format CallPal(code, *flags) {{
+ iop = InstObjParams(name, Name, 'CallPalBase', CodeBlock(code), flags)
+ header_output = BasicDeclare.subst(iop)
+ decoder_output = BasicConstructor.subst(iop)
+ decode_block = BasicDecode.subst(iop)
+ exec_output = BasicExecute.subst(iop)
+}};
+
+////////////////////////////////////////////////////////////////////
+//
+// hw_ld, hw_st
+//
+
+output header {{
+ /**
+ * Base class for hw_ld and hw_st.
+ */
+ class HwLoadStore : public Memory
+ {
+ protected:
+
+ /// Displacement for EA calculation (signed).
+ int16_t disp;
+
+ /// Constructor
+ HwLoadStore(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
+ StaticInstPtr _eaCompPtr = nullStaticInstPtr,
+ StaticInstPtr _memAccPtr = nullStaticInstPtr);
+
+ std::string
+ generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+ };
+}};
+
+
+output decoder {{
+ inline
+ HwLoadStore::HwLoadStore(const char *mnem, ExtMachInst _machInst,
+ OpClass __opClass,
+ StaticInstPtr _eaCompPtr,
+ StaticInstPtr _memAccPtr)
+ : Memory(mnem, _machInst, __opClass, _eaCompPtr, _memAccPtr),
+ disp(HW_LDST_DISP)
+ {
+ memAccessFlags = 0;
+ if (HW_LDST_PHYS) memAccessFlags |= PHYSICAL;
+ if (HW_LDST_ALT) memAccessFlags |= ALTMODE;
+ if (HW_LDST_VPTE) memAccessFlags |= VPTE;
+ if (HW_LDST_LOCK) memAccessFlags |= LOCKED;
+ }
+
+ std::string
+ HwLoadStore::generateDisassembly(Addr pc, const SymbolTable *symtab) const
+ {
+#ifdef SS_COMPATIBLE_DISASSEMBLY
+ return csprintf("%-10s r%d,%d(r%d)", mnemonic, RA, disp, RB);
+#else
+ // HW_LDST_LOCK and HW_LDST_COND are the same bit.
+ const char *lock_str =
+ (HW_LDST_LOCK) ? (flags[IsLoad] ? ",LOCK" : ",COND") : "";
+
+ return csprintf("%-10s r%d,%d(r%d)%s%s%s%s%s",
+ mnemonic, RA, disp, RB,
+ HW_LDST_PHYS ? ",PHYS" : "",
+ HW_LDST_ALT ? ",ALT" : "",
+ HW_LDST_QUAD ? ",QUAD" : "",
+ HW_LDST_VPTE ? ",VPTE" : "",
+ lock_str);
+#endif
+ }
+}};
+
+def format HwLoad(ea_code, memacc_code, class_ext, *flags) {{
+ (header_output, decoder_output, decode_block, exec_output) = \
+ LoadStoreBase(name, Name + class_ext, ea_code, memacc_code,
+ mem_flags = [], inst_flags = flags,
+ base_class = 'HwLoadStore', exec_template_base = 'Load')
+}};
+
+
+def format HwStore(ea_code, memacc_code, class_ext, *flags) {{
+ (header_output, decoder_output, decode_block, exec_output) = \
+ LoadStoreBase(name, Name + class_ext, ea_code, memacc_code,
+ mem_flags = [], inst_flags = flags,
+ base_class = 'HwLoadStore', exec_template_base = 'Store')
+}};
+
+
+def format HwStoreCond(ea_code, memacc_code, postacc_code, class_ext,
+ *flags) {{
+ (header_output, decoder_output, decode_block, exec_output) = \
+ LoadStoreBase(name, Name + class_ext, ea_code, memacc_code,
+ postacc_code, mem_flags = [], inst_flags = flags,
+ base_class = 'HwLoadStore')
+}};
+
+
+output header {{
+ /**
+ * Base class for hw_mfpr and hw_mtpr.
+ */
+ class HwMoveIPR : public AlphaStaticInst
+ {
+ protected:
+ /// Index of internal processor register.
+ int ipr_index;
+
+ /// Constructor
+ HwMoveIPR(const char *mnem, ExtMachInst _machInst, OpClass __opClass)
+ : AlphaStaticInst(mnem, _machInst, __opClass),
+ ipr_index(HW_IPR_IDX)
+ {
+ }
+
+ std::string
+ generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+ };
+}};
+
+output decoder {{
+ std::string
+ HwMoveIPR::generateDisassembly(Addr pc, const SymbolTable *symtab) const
+ {
+ if (_numSrcRegs > 0) {
+ // must be mtpr
+ return csprintf("%-10s r%d,IPR(%#x)",
+ mnemonic, RA, ipr_index);
+ }
+ else {
+ // must be mfpr
+ return csprintf("%-10s IPR(%#x),r%d",
+ mnemonic, ipr_index, RA);
+ }
+ }
+}};
+
+def format HwMoveIPR(code) {{
+ iop = InstObjParams(name, Name, 'HwMoveIPR', CodeBlock(code),
+ ['IprAccessOp'])
+ header_output = BasicDeclare.subst(iop)
+ decoder_output = BasicConstructor.subst(iop)
+ decode_block = BasicDecode.subst(iop)
+ exec_output = BasicExecute.subst(iop)
+}};
+
+
diff --git a/arch/alpha/isa/unimp.isa b/arch/alpha/isa/unimp.isa
new file mode 100644
index 000000000..392522801
--- /dev/null
+++ b/arch/alpha/isa/unimp.isa
@@ -0,0 +1,165 @@
+// -*- mode:c++ -*-
+
+// Copyright (c) 2003-2005 The Regents of The University of Michigan
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met: redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer;
+// redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution;
+// neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+output header {{
+ /**
+ * Static instruction class for unimplemented instructions that
+ * cause simulator termination. Note that these are recognized
+ * (legal) instructions that the simulator does not support; the
+ * 'Unknown' class is used for unrecognized/illegal instructions.
+ * This is a leaf class.
+ */
+ class FailUnimplemented : public AlphaStaticInst
+ {
+ public:
+ /// Constructor
+ FailUnimplemented(const char *_mnemonic, ExtMachInst _machInst)
+ : AlphaStaticInst(_mnemonic, _machInst, No_OpClass)
+ {
+ // don't call execute() (which panics) if we're on a
+ // speculative path
+ flags[IsNonSpeculative] = true;
+ }
+
+ %(BasicExecDeclare)s
+
+ std::string
+ generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+ };
+
+ /**
+ * Base class for unimplemented instructions that cause a warning
+ * to be printed (but do not terminate simulation). This
+ * implementation is a little screwy in that it will print a
+ * warning for each instance of a particular unimplemented machine
+ * instruction, not just for each unimplemented opcode. Should
+ * probably make the 'warned' flag a static member of the derived
+ * class.
+ */
+ class WarnUnimplemented : public AlphaStaticInst
+ {
+ private:
+ /// Have we warned on this instruction yet?
+ mutable bool warned;
+
+ public:
+ /// Constructor
+ WarnUnimplemented(const char *_mnemonic, ExtMachInst _machInst)
+ : AlphaStaticInst(_mnemonic, _machInst, No_OpClass), warned(false)
+ {
+ // don't call execute() (which panics) if we're on a
+ // speculative path
+ flags[IsNonSpeculative] = true;
+ }
+
+ %(BasicExecDeclare)s
+
+ std::string
+ generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+ };
+}};
+
+output decoder {{
+ std::string
+ FailUnimplemented::generateDisassembly(Addr pc,
+ const SymbolTable *symtab) const
+ {
+ return csprintf("%-10s (unimplemented)", mnemonic);
+ }
+
+ std::string
+ WarnUnimplemented::generateDisassembly(Addr pc,
+ const SymbolTable *symtab) const
+ {
+#ifdef SS_COMPATIBLE_DISASSEMBLY
+ return csprintf("%-10s", mnemonic);
+#else
+ return csprintf("%-10s (unimplemented)", mnemonic);
+#endif
+ }
+}};
+
+output exec {{
+ Fault
+ FailUnimplemented::execute(%(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData) const
+ {
+ panic("attempt to execute unimplemented instruction '%s' "
+ "(inst 0x%08x, opcode 0x%x)", mnemonic, machInst, OPCODE);
+ return new UnimplementedOpcodeFault;
+ }
+
+ Fault
+ WarnUnimplemented::execute(%(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData) const
+ {
+ if (!warned) {
+ warn("instruction '%s' unimplemented\n", mnemonic);
+ warned = true;
+ }
+
+ return NoFault;
+ }
+}};
+
+
+def format FailUnimpl() {{
+ iop = InstObjParams(name, 'FailUnimplemented')
+ decode_block = BasicDecodeWithMnemonic.subst(iop)
+}};
+
+def format WarnUnimpl() {{
+ iop = InstObjParams(name, 'WarnUnimplemented')
+ decode_block = BasicDecodeWithMnemonic.subst(iop)
+}};
+
+output header {{
+ /**
+ * Static instruction class for unknown (illegal) instructions.
+ * These cause simulator termination if they are executed in a
+ * non-speculative mode. This is a leaf class.
+ */
+ class Unknown : public AlphaStaticInst
+ {
+ public:
+ /// Constructor
+ Unknown(ExtMachInst _machInst)
+ : AlphaStaticInst("unknown", _machInst, No_OpClass)
+ {
+ // don't call execute() (which panics) if we're on a
+ // speculative path
+ flags[IsNonSpeculative] = true;
+ }
+
+ %(BasicExecDeclare)s
+
+ std::string
+ generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+ };
+}};
+
diff --git a/arch/alpha/isa/unknown.isa b/arch/alpha/isa/unknown.isa
new file mode 100644
index 000000000..47d166255
--- /dev/null
+++ b/arch/alpha/isa/unknown.isa
@@ -0,0 +1,52 @@
+// -*- mode:c++ -*-
+
+// Copyright (c) 2003-2005 The Regents of The University of Michigan
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met: redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer;
+// redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution;
+// neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+output decoder {{
+ std::string
+ Unknown::generateDisassembly(Addr pc, const SymbolTable *symtab) const
+ {
+ return csprintf("%-10s (inst 0x%x, opcode 0x%x)",
+ "unknown", machInst, OPCODE);
+ }
+}};
+
+output exec {{
+ Fault
+ Unknown::execute(%(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData) const
+ {
+ panic("attempt to execute unknown instruction "
+ "(inst 0x%08x, opcode 0x%x)", machInst, OPCODE);
+ return new UnimplementedOpcodeFault;
+ }
+}};
+
+def format Unknown() {{
+ decode_block = 'return new Unknown(machInst);\n'
+}};
+
diff --git a/arch/alpha/isa/util.isa b/arch/alpha/isa/util.isa
new file mode 100644
index 000000000..9fbbf6636
--- /dev/null
+++ b/arch/alpha/isa/util.isa
@@ -0,0 +1,112 @@
+// -*- mode:c++ -*-
+
+// Copyright (c) 2003-2005 The Regents of The University of Michigan
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met: redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer;
+// redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution;
+// neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+output exec {{
+
+ /// Return opa + opb, summing carry into third arg.
+ inline uint64_t
+ addc(uint64_t opa, uint64_t opb, int &carry)
+ {
+ uint64_t res = opa + opb;
+ if (res < opa || res < opb)
+ ++carry;
+ return res;
+ }
+
+ /// Multiply two 64-bit values (opa * opb), returning the 128-bit
+ /// product in res_hi and res_lo.
+ inline void
+ mul128(uint64_t opa, uint64_t opb, uint64_t &res_hi, uint64_t &res_lo)
+ {
+ // do a 64x64 --> 128 multiply using four 32x32 --> 64 multiplies
+ uint64_t opa_hi = opa<63:32>;
+ uint64_t opa_lo = opa<31:0>;
+ uint64_t opb_hi = opb<63:32>;
+ uint64_t opb_lo = opb<31:0>;
+
+ res_lo = opa_lo * opb_lo;
+
+ // The middle partial products logically belong in bit
+ // positions 95 to 32. Thus the lower 32 bits of each product
+ // sum into the upper 32 bits of the low result, while the
+ // upper 32 sum into the low 32 bits of the upper result.
+ uint64_t partial1 = opa_hi * opb_lo;
+ uint64_t partial2 = opa_lo * opb_hi;
+
+ uint64_t partial1_lo = partial1<31:0> << 32;
+ uint64_t partial1_hi = partial1<63:32>;
+ uint64_t partial2_lo = partial2<31:0> << 32;
+ uint64_t partial2_hi = partial2<63:32>;
+
+ // Add partial1_lo and partial2_lo to res_lo, keeping track
+ // of any carries out
+ int carry_out = 0;
+ res_lo = addc(partial1_lo, res_lo, carry_out);
+ res_lo = addc(partial2_lo, res_lo, carry_out);
+
+ // Now calculate the high 64 bits...
+ res_hi = (opa_hi * opb_hi) + partial1_hi + partial2_hi + carry_out;
+ }
+
+ /// Map 8-bit S-floating exponent to 11-bit T-floating exponent.
+ /// See Table 2-2 of Alpha AHB.
+ inline int
+ map_s(int old_exp)
+ {
+ int hibit = old_exp<7:>;
+ int lobits = old_exp<6:0>;
+
+ if (hibit == 1) {
+ return (lobits == 0x7f) ? 0x7ff : (0x400 | lobits);
+ }
+ else {
+ return (lobits == 0) ? 0 : (0x380 | lobits);
+ }
+ }
+
+ /// Convert a 32-bit S-floating value to the equivalent 64-bit
+ /// representation to be stored in an FP reg.
+ inline uint64_t
+ s_to_t(uint32_t s_val)
+ {
+ uint64_t tmp = s_val;
+ return (tmp<31:> << 63 // sign bit
+ | (uint64_t)map_s(tmp<30:23>) << 52 // exponent
+ | tmp<22:0> << 29); // fraction
+ }
+
+ /// Convert a 64-bit T-floating value to the equivalent 32-bit
+ /// S-floating representation to be stored in memory.
+ inline int32_t
+ t_to_s(uint64_t t_val)
+ {
+ return (t_val<63:62> << 30 // sign bit & hi exp bit
+ | t_val<58:29>); // rest of exp & fraction
+ }
+}};
+
diff --git a/arch/alpha/isa_desc b/arch/alpha/isa_desc
deleted file mode 100644
index e64a95957..000000000
--- a/arch/alpha/isa_desc
+++ /dev/null
@@ -1,2737 +0,0 @@
-// -*- mode:c++ -*-
-
-//Copyright (c) 2003, 2004, 2005
-//The Regents of The University of Michigan
-//All Rights Reserved
-
-//This code is part of the M5 simulator, developed by Nathan Binkert,
-//Erik Hallnor, Steve Raasch, and Steve Reinhardt, with contributions
-//from Ron Dreslinski, Dave Greene, Lisa Hsu, Kevin Lim, Ali Saidi,
-//and Andrew Schultz.
-
-//Permission is granted to use, copy, create derivative works and
-//redistribute this software and such derivative works for any purpose,
-//so long as the copyright notice above, this grant of permission, and
-//the disclaimer below appear in all copies made; and so long as the
-//name of The University of Michigan is not used in any advertising or
-//publicity pertaining to the use or distribution of this software
-//without specific, written prior authorization.
-
-//THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION FROM THE
-//UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY PURPOSE, AND WITHOUT
-//WARRANTY BY THE UNIVERSITY OF MICHIGAN OF ANY KIND, EITHER EXPRESS OR
-//IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED WARRANTIES OF
-//MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE REGENTS OF
-//THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE FOR ANY DAMAGES,
-//INCLUDING DIRECT, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
-//DAMAGES, WITH RESPECT TO ANY CLAIM ARISING OUT OF OR IN CONNECTION
-//WITH THE USE OF THE SOFTWARE, EVEN IF IT HAS BEEN OR IS HEREAFTER
-//ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
-
-////////////////////////////////////////////////////////////////////
-//
-// Alpha ISA description file.
-//
-////////////////////////////////////////////////////////////////////
-
-
-////////////////////////////////////////////////////////////////////
-//
-// Output include file directives.
-//
-
-output header {{
-#include <sstream>
-#include <iostream>
-#include <iomanip>
-
-#include "config/ss_compatible_fp.hh"
-#include "cpu/static_inst.hh"
-#include "mem/request.hh" // some constructors use MemReq flags
-}};
-
-output decoder {{
-#include "base/cprintf.hh"
-#include "base/fenv.hh"
-#include "base/loader/symtab.hh"
-#include "config/ss_compatible_fp.hh"
-#include "cpu/exec_context.hh" // for Jump::branchTarget()
-
-#include <math.h>
-}};
-
-output exec {{
-#include <math.h>
-
-#if FULL_SYSTEM
-#include "arch/alpha/pseudo_inst.hh"
-#endif
-#include "base/fenv.hh"
-#include "config/ss_compatible_fp.hh"
-#include "cpu/base.hh"
-#include "cpu/exetrace.hh"
-#include "sim/sim_exit.hh"
-}};
-
-////////////////////////////////////////////////////////////////////
-//
-// Namespace statement. Everything below this line will be in the
-// AlphaISAInst namespace.
-//
-
-
-namespace AlphaISA;
-
-////////////////////////////////////////////////////////////////////
-//
-// Bitfield definitions.
-//
-
-// Universal (format-independent) fields
-def bitfield OPCODE <31:26>;
-def bitfield RA <25:21>;
-def bitfield RB <20:16>;
-
-// Memory format
-def signed bitfield MEMDISP <15: 0>; // displacement
-def bitfield MEMFUNC <15: 0>; // function code (same field, unsigned)
-
-// Memory-format jumps
-def bitfield JMPFUNC <15:14>; // function code (disp<15:14>)
-def bitfield JMPHINT <13: 0>; // tgt Icache idx hint (disp<13:0>)
-
-// Branch format
-def signed bitfield BRDISP <20: 0>; // displacement
-
-// Integer operate format(s>;
-def bitfield INTIMM <20:13>; // integer immediate (literal)
-def bitfield IMM <12:12>; // immediate flag
-def bitfield INTFUNC <11: 5>; // function code
-def bitfield RC < 4: 0>; // dest reg
-
-// Floating-point operate format
-def bitfield FA <25:21>;
-def bitfield FB <20:16>;
-def bitfield FP_FULLFUNC <15: 5>; // complete function code
- def bitfield FP_TRAPMODE <15:13>; // trapping mode
- def bitfield FP_ROUNDMODE <12:11>; // rounding mode
- def bitfield FP_TYPEFUNC <10: 5>; // type+func: handiest for decoding
- def bitfield FP_SRCTYPE <10: 9>; // source reg type
- def bitfield FP_SHORTFUNC < 8: 5>; // short function code
- def bitfield FP_SHORTFUNC_TOP2 <8:7>; // top 2 bits of short func code
-def bitfield FC < 4: 0>; // dest reg
-
-// PALcode format
-def bitfield PALFUNC <25: 0>; // function code
-
-// EV5 PAL instructions:
-// HW_LD/HW_ST
-def bitfield HW_LDST_PHYS <15>; // address is physical
-def bitfield HW_LDST_ALT <14>; // use ALT_MODE IPR
-def bitfield HW_LDST_WRTCK <13>; // HW_LD only: fault if no write acc
-def bitfield HW_LDST_QUAD <12>; // size: 0=32b, 1=64b
-def bitfield HW_LDST_VPTE <11>; // HW_LD only: is PTE fetch
-def bitfield HW_LDST_LOCK <10>; // HW_LD only: is load locked
-def bitfield HW_LDST_COND <10>; // HW_ST only: is store conditional
-def signed bitfield HW_LDST_DISP <9:0>; // signed displacement
-
-// HW_REI
-def bitfield HW_REI_TYP <15:14>; // type: stalling vs. non-stallingk
-def bitfield HW_REI_MBZ <13: 0>; // must be zero
-
-// HW_MTPR/MW_MFPR
-def bitfield HW_IPR_IDX <15:0>; // IPR index
-
-// M5 instructions
-def bitfield M5FUNC <7:0>;
-
-def operand_types {{
- 'sb' : ('signed int', 8),
- 'ub' : ('unsigned int', 8),
- 'sw' : ('signed int', 16),
- 'uw' : ('unsigned int', 16),
- 'sl' : ('signed int', 32),
- 'ul' : ('unsigned int', 32),
- 'sq' : ('signed int', 64),
- 'uq' : ('unsigned int', 64),
- 'sf' : ('float', 32),
- 'df' : ('float', 64)
-}};
-
-def operands {{
- # Int regs default to unsigned, but code should not count on this.
- # For clarity, descriptions that depend on unsigned behavior should
- # explicitly specify '.uq'.
- 'Ra': IntRegOperandTraits('uq', 'RA', 'IsInteger', 1),
- 'Rb': IntRegOperandTraits('uq', 'RB', 'IsInteger', 2),
- 'Rc': IntRegOperandTraits('uq', 'RC', 'IsInteger', 3),
- 'Fa': FloatRegOperandTraits('df', 'FA', 'IsFloating', 1),
- 'Fb': FloatRegOperandTraits('df', 'FB', 'IsFloating', 2),
- 'Fc': FloatRegOperandTraits('df', 'FC', 'IsFloating', 3),
- 'Mem': MemOperandTraits('uq', None,
- ('IsMemRef', 'IsLoad', 'IsStore'), 4),
- 'NPC': NPCOperandTraits('uq', None, ( None, None, 'IsControl' ), 4),
- 'Runiq': ControlRegOperandTraits('uq', 'Uniq', None, 1),
- 'FPCR': ControlRegOperandTraits('uq', 'Fpcr', None, 1),
- # The next two are hacks for non-full-system call-pal emulation
- 'R0': IntRegOperandTraits('uq', '0', None, 1),
- 'R16': IntRegOperandTraits('uq', '16', None, 1)
-}};
-
-////////////////////////////////////////////////////////////////////
-//
-// Basic instruction classes/templates/formats etc.
-//
-
-output header {{
-// uncomment the following to get SimpleScalar-compatible disassembly
-// (useful for diffing output traces).
-// #define SS_COMPATIBLE_DISASSEMBLY
-
- /**
- * Base class for all Alpha static instructions.
- */
- class AlphaStaticInst : public StaticInst<AlphaISA>
- {
- protected:
-
- /// Make AlphaISA register dependence tags directly visible in
- /// this class and derived classes. Maybe these should really
- /// live here and not in the AlphaISA namespace.
- enum DependenceTags {
- FP_Base_DepTag = AlphaISA::FP_Base_DepTag,
- Fpcr_DepTag = AlphaISA::Fpcr_DepTag,
- Uniq_DepTag = AlphaISA::Uniq_DepTag,
- IPR_Base_DepTag = AlphaISA::IPR_Base_DepTag
- };
-
- /// Constructor.
- AlphaStaticInst(const char *mnem, MachInst _machInst,
- OpClass __opClass)
- : StaticInst<AlphaISA>(mnem, _machInst, __opClass)
- {
- }
-
- /// Print a register name for disassembly given the unique
- /// dependence tag number (FP or int).
- void printReg(std::ostream &os, int reg) const;
-
- std::string
- generateDisassembly(Addr pc, const SymbolTable *symtab) const;
- };
-}};
-
-output decoder {{
- void
- AlphaStaticInst::printReg(std::ostream &os, int reg) const
- {
- if (reg < FP_Base_DepTag) {
- ccprintf(os, "r%d", reg);
- }
- else {
- ccprintf(os, "f%d", reg - FP_Base_DepTag);
- }
- }
-
- std::string
- AlphaStaticInst::generateDisassembly(Addr pc,
- const SymbolTable *symtab) const
- {
- std::stringstream ss;
-
- ccprintf(ss, "%-10s ", mnemonic);
-
- // just print the first two source regs... if there's
- // a third one, it's a read-modify-write dest (Rc),
- // e.g. for CMOVxx
- if (_numSrcRegs > 0) {
- printReg(ss, _srcRegIdx[0]);
- }
- if (_numSrcRegs > 1) {
- ss << ",";
- printReg(ss, _srcRegIdx[1]);
- }
-
- // just print the first dest... if there's a second one,
- // it's generally implicit
- if (_numDestRegs > 0) {
- if (_numSrcRegs > 0)
- ss << ",";
- printReg(ss, _destRegIdx[0]);
- }
-
- return ss.str();
- }
-}};
-
-// Declarations for execute() methods.
-def template BasicExecDeclare {{
- Fault execute(%(CPU_exec_context)s *, Trace::InstRecord *) const;
-}};
-
-// Basic instruction class declaration template.
-def template BasicDeclare {{
- /**
- * Static instruction class for "%(mnemonic)s".
- */
- class %(class_name)s : public %(base_class)s
- {
- public:
- /// Constructor.
- %(class_name)s(MachInst machInst);
-
- %(BasicExecDeclare)s
- };
-}};
-
-// Basic instruction class constructor template.
-def template BasicConstructor {{
- inline %(class_name)s::%(class_name)s(MachInst machInst)
- : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s)
- {
- %(constructor)s;
- }
-}};
-
-// Basic instruction class execute method template.
-def template BasicExecute {{
- Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
- Trace::InstRecord *traceData) const
- {
- Fault fault = No_Fault;
-
- %(fp_enable_check)s;
- %(op_decl)s;
- %(op_rd)s;
- %(code)s;
-
- if (fault == No_Fault) {
- %(op_wb)s;
- }
-
- return fault;
- }
-}};
-
-// Basic decode template.
-def template BasicDecode {{
- return new %(class_name)s(machInst);
-}};
-
-// Basic decode template, passing mnemonic in as string arg to constructor.
-def template BasicDecodeWithMnemonic {{
- return new %(class_name)s("%(mnemonic)s", machInst);
-}};
-
-// The most basic instruction format... used only for a few misc. insts
-def format BasicOperate(code, *flags) {{
- iop = InstObjParams(name, Name, 'AlphaStaticInst', CodeBlock(code), flags)
- header_output = BasicDeclare.subst(iop)
- decoder_output = BasicConstructor.subst(iop)
- decode_block = BasicDecode.subst(iop)
- exec_output = BasicExecute.subst(iop)
-}};
-
-
-
-////////////////////////////////////////////////////////////////////
-//
-// Nop
-//
-
-output header {{
- /**
- * Static instruction class for no-ops. This is a leaf class.
- */
- class Nop : public AlphaStaticInst
- {
- /// Disassembly of original instruction.
- const std::string originalDisassembly;
-
- public:
- /// Constructor
- Nop(const std::string _originalDisassembly, MachInst _machInst)
- : AlphaStaticInst("nop", _machInst, No_OpClass),
- originalDisassembly(_originalDisassembly)
- {
- flags[IsNop] = true;
- }
-
- ~Nop() { }
-
- std::string
- generateDisassembly(Addr pc, const SymbolTable *symtab) const;
-
- %(BasicExecDeclare)s
- };
-}};
-
-output decoder {{
- std::string Nop::generateDisassembly(Addr pc,
- const SymbolTable *symtab) const
- {
-#ifdef SS_COMPATIBLE_DISASSEMBLY
- return originalDisassembly;
-#else
- return csprintf("%-10s (%s)", "nop", originalDisassembly);
-#endif
- }
-
- /// Helper function for decoding nops. Substitute Nop object
- /// for original inst passed in as arg (and delete latter).
- inline
- AlphaStaticInst *
- makeNop(AlphaStaticInst *inst)
- {
- AlphaStaticInst *nop = new Nop(inst->disassemble(0), inst->machInst);
- delete inst;
- return nop;
- }
-}};
-
-output exec {{
- Fault
- Nop::execute(%(CPU_exec_context)s *, Trace::InstRecord *) const
- {
- return No_Fault;
- }
-}};
-
-// integer & FP operate instructions use Rc as dest, so check for
-// Rc == 31 to detect nops
-def template OperateNopCheckDecode {{
- {
- AlphaStaticInst *i = new %(class_name)s(machInst);
- if (RC == 31) {
- i = makeNop(i);
- }
- return i;
- }
-}};
-
-// Like BasicOperate format, but generates NOP if RC/FC == 31
-def format BasicOperateWithNopCheck(code, *opt_args) {{
- iop = InstObjParams(name, Name, 'AlphaStaticInst', CodeBlock(code),
- opt_args)
- header_output = BasicDeclare.subst(iop)
- decoder_output = BasicConstructor.subst(iop)
- decode_block = OperateNopCheckDecode.subst(iop)
- exec_output = BasicExecute.subst(iop)
-}};
-
-
-////////////////////////////////////////////////////////////////////
-//
-// Integer operate instructions
-//
-
-output header {{
- /**
- * Base class for integer immediate instructions.
- */
- class IntegerImm : public AlphaStaticInst
- {
- protected:
- /// Immediate operand value (unsigned 8-bit int).
- uint8_t imm;
-
- /// Constructor
- IntegerImm(const char *mnem, MachInst _machInst, OpClass __opClass)
- : AlphaStaticInst(mnem, _machInst, __opClass), imm(INTIMM)
- {
- }
-
- std::string
- generateDisassembly(Addr pc, const SymbolTable *symtab) const;
- };
-}};
-
-output decoder {{
- std::string
- IntegerImm::generateDisassembly(Addr pc, const SymbolTable *symtab) const
- {
- std::stringstream ss;
-
- ccprintf(ss, "%-10s ", mnemonic);
-
- // just print the first source reg... if there's
- // a second one, it's a read-modify-write dest (Rc),
- // e.g. for CMOVxx
- if (_numSrcRegs > 0) {
- printReg(ss, _srcRegIdx[0]);
- ss << ",";
- }
-
- ss << (int)imm;
-
- if (_numDestRegs > 0) {
- ss << ",";
- printReg(ss, _destRegIdx[0]);
- }
-
- return ss.str();
- }
-}};
-
-
-def template RegOrImmDecode {{
- {
- AlphaStaticInst *i =
- (IMM) ? (AlphaStaticInst *)new %(class_name)sImm(machInst)
- : (AlphaStaticInst *)new %(class_name)s(machInst);
- if (RC == 31) {
- i = makeNop(i);
- }
- return i;
- }
-}};
-
-// Primary format for integer operate instructions:
-// - Generates both reg-reg and reg-imm versions if Rb_or_imm is used.
-// - Generates NOP if RC == 31.
-def format IntegerOperate(code, *opt_flags) {{
- # If the code block contains 'Rb_or_imm', we define two instructions,
- # one using 'Rb' and one using 'imm', and have the decoder select
- # the right one.
- uses_imm = (code.find('Rb_or_imm') != -1)
- if uses_imm:
- orig_code = code
- # base code is reg version:
- # rewrite by substituting 'Rb' for 'Rb_or_imm'
- code = re.sub(r'Rb_or_imm', 'Rb', orig_code)
- # generate immediate version by substituting 'imm'
- # note that imm takes no extenstion, so we extend
- # the regexp to replace any extension as well
- imm_code = re.sub(r'Rb_or_imm(\.\w+)?', 'imm', orig_code)
-
- # generate declaration for register version
- cblk = CodeBlock(code)
- iop = InstObjParams(name, Name, 'AlphaStaticInst', cblk, opt_flags)
- header_output = BasicDeclare.subst(iop)
- decoder_output = BasicConstructor.subst(iop)
- exec_output = BasicExecute.subst(iop)
-
- if uses_imm:
- # append declaration for imm version
- imm_cblk = CodeBlock(imm_code)
- imm_iop = InstObjParams(name, Name + 'Imm', 'IntegerImm', imm_cblk,
- opt_flags)
- header_output += BasicDeclare.subst(imm_iop)
- decoder_output += BasicConstructor.subst(imm_iop)
- exec_output += BasicExecute.subst(imm_iop)
- # decode checks IMM bit to pick correct version
- decode_block = RegOrImmDecode.subst(iop)
- else:
- # no imm version: just check for nop
- decode_block = OperateNopCheckDecode.subst(iop)
-}};
-
-
-////////////////////////////////////////////////////////////////////
-//
-// Floating-point instructions
-//
-// Note that many FP-type instructions which do not support all the
-// various rounding & trapping modes use the simpler format
-// BasicOperateWithNopCheck.
-//
-
-output exec {{
- /// Check "FP enabled" machine status bit. Called when executing any FP
- /// instruction in full-system mode.
- /// @retval Full-system mode: No_Fault if FP is enabled, Fen_Fault
- /// if not. Non-full-system mode: always returns No_Fault.
-#if FULL_SYSTEM
- inline Fault checkFpEnableFault(%(CPU_exec_context)s *xc)
- {
- Fault fault = No_Fault; // dummy... this ipr access should not fault
- if (!EV5::ICSR_FPE(xc->readIpr(AlphaISA::IPR_ICSR, fault))) {
- fault = Fen_Fault;
- }
- return fault;
- }
-#else
- inline Fault checkFpEnableFault(%(CPU_exec_context)s *xc)
- {
- return No_Fault;
- }
-#endif
-}};
-
-output header {{
- /**
- * Base class for general floating-point instructions. Includes
- * support for various Alpha rounding and trapping modes. Only FP
- * instructions that require this support are derived from this
- * class; the rest derive directly from AlphaStaticInst.
- */
- class AlphaFP : public AlphaStaticInst
- {
- public:
- /// Alpha FP rounding modes.
- enum RoundingMode {
- Chopped = 0, ///< round toward zero
- Minus_Infinity = 1, ///< round toward minus infinity
- Normal = 2, ///< round to nearest (default)
- Dynamic = 3, ///< use FPCR setting (in instruction)
- Plus_Infinity = 3 ///< round to plus inifinity (in FPCR)
- };
-
- /// Alpha FP trapping modes.
- /// For instructions that produce integer results, the
- /// "Underflow Enable" modes really mean "Overflow Enable", and
- /// the assembly modifier is V rather than U.
- enum TrappingMode {
- /// default: nothing enabled
- Imprecise = 0, ///< no modifier
- /// underflow/overflow traps enabled, inexact disabled
- Underflow_Imprecise = 1, ///< /U or /V
- Underflow_Precise = 5, ///< /SU or /SV
- /// underflow/overflow and inexact traps enabled
- Underflow_Inexact_Precise = 7 ///< /SUI or /SVI
- };
-
- protected:
- /// Map Alpha rounding mode to C99 constants from <fenv.h>.
- static const int alphaToC99RoundingMode[];
-
- /// Map enum RoundingMode values to disassembly suffixes.
- static const char *roundingModeSuffix[];
- /// Map enum TrappingMode values to FP disassembly suffixes.
- static const char *fpTrappingModeSuffix[];
- /// Map enum TrappingMode values to integer disassembly suffixes.
- static const char *intTrappingModeSuffix[];
-
- /// This instruction's rounding mode.
- RoundingMode roundingMode;
- /// This instruction's trapping mode.
- TrappingMode trappingMode;
-
- /// Have we warned about this instruction's unsupported
- /// rounding mode (if applicable)?
- mutable bool warnedOnRounding;
-
- /// Have we warned about this instruction's unsupported
- /// trapping mode (if applicable)?
- mutable bool warnedOnTrapping;
-
- /// Constructor
- AlphaFP(const char *mnem, MachInst _machInst, OpClass __opClass)
- : AlphaStaticInst(mnem, _machInst, __opClass),
- roundingMode((enum RoundingMode)FP_ROUNDMODE),
- trappingMode((enum TrappingMode)FP_TRAPMODE),
- warnedOnRounding(false),
- warnedOnTrapping(false)
- {
- }
-
- int getC99RoundingMode(uint64_t fpcr_val) const;
-
- // This differs from the AlphaStaticInst version only in
- // printing suffixes for non-default rounding & trapping modes.
- std::string
- generateDisassembly(Addr pc, const SymbolTable *symtab) const;
- };
-
-}};
-
-
-output decoder {{
- int
- AlphaFP::getC99RoundingMode(uint64_t fpcr_val) const
- {
- if (roundingMode == Dynamic) {
- return alphaToC99RoundingMode[bits(fpcr_val, 59, 58)];
- }
- else {
- return alphaToC99RoundingMode[roundingMode];
- }
- }
-
- std::string
- AlphaFP::generateDisassembly(Addr pc, const SymbolTable *symtab) const
- {
- std::string mnem_str(mnemonic);
-
-#ifndef SS_COMPATIBLE_DISASSEMBLY
- std::string suffix("");
- suffix += ((_destRegIdx[0] >= FP_Base_DepTag)
- ? fpTrappingModeSuffix[trappingMode]
- : intTrappingModeSuffix[trappingMode]);
- suffix += roundingModeSuffix[roundingMode];
-
- if (suffix != "") {
- mnem_str = csprintf("%s/%s", mnemonic, suffix);
- }
-#endif
-
- std::stringstream ss;
- ccprintf(ss, "%-10s ", mnem_str.c_str());
-
- // just print the first two source regs... if there's
- // a third one, it's a read-modify-write dest (Rc),
- // e.g. for CMOVxx
- if (_numSrcRegs > 0) {
- printReg(ss, _srcRegIdx[0]);
- }
- if (_numSrcRegs > 1) {
- ss << ",";
- printReg(ss, _srcRegIdx[1]);
- }
-
- // just print the first dest... if there's a second one,
- // it's generally implicit
- if (_numDestRegs > 0) {
- if (_numSrcRegs > 0)
- ss << ",";
- printReg(ss, _destRegIdx[0]);
- }
-
- return ss.str();
- }
-
- const int AlphaFP::alphaToC99RoundingMode[] = {
- FE_TOWARDZERO, // Chopped
- FE_DOWNWARD, // Minus_Infinity
- FE_TONEAREST, // Normal
- FE_UPWARD // Dynamic in inst, Plus_Infinity in FPCR
- };
-
- const char *AlphaFP::roundingModeSuffix[] = { "c", "m", "", "d" };
- // mark invalid trapping modes, but don't fail on them, because
- // you could decode anything on a misspeculated path
- const char *AlphaFP::fpTrappingModeSuffix[] =
- { "", "u", "INVTM2", "INVTM3", "INVTM4", "su", "INVTM6", "sui" };
- const char *AlphaFP::intTrappingModeSuffix[] =
- { "", "v", "INVTM2", "INVTM3", "INVTM4", "sv", "INVTM6", "svi" };
-}};
-
-// FP instruction class execute method template. Handles non-standard
-// rounding modes.
-def template FloatingPointExecute {{
- Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
- Trace::InstRecord *traceData) const
- {
- if (trappingMode != Imprecise && !warnedOnTrapping) {
- warn("%s: non-standard trapping mode not supported",
- generateDisassembly(0, NULL));
- warnedOnTrapping = true;
- }
-
- Fault fault = No_Fault;
-
- %(fp_enable_check)s;
- %(op_decl)s;
- %(op_rd)s;
-#if USE_FENV
- if (roundingMode == Normal) {
- %(code)s;
- } else {
- fesetround(getC99RoundingMode(xc->readFpcr()));
- %(code)s;
- fesetround(FE_TONEAREST);
- }
-#else
- if (roundingMode != Normal && !warnedOnRounding) {
- warn("%s: non-standard rounding mode not supported",
- generateDisassembly(0, NULL));
- warnedOnRounding = true;
- }
- %(code)s;
-#endif
-
- if (fault == No_Fault) {
- %(op_wb)s;
- }
-
- return fault;
- }
-}};
-
-// FP instruction class execute method template where no dynamic
-// rounding mode control is needed. Like BasicExecute, but includes
-// check & warning for non-standard trapping mode.
-def template FPFixedRoundingExecute {{
- Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
- Trace::InstRecord *traceData) const
- {
- if (trappingMode != Imprecise && !warnedOnTrapping) {
- warn("%s: non-standard trapping mode not supported",
- generateDisassembly(0, NULL));
- warnedOnTrapping = true;
- }
-
- Fault fault = No_Fault;
-
- %(fp_enable_check)s;
- %(op_decl)s;
- %(op_rd)s;
- %(code)s;
-
- if (fault == No_Fault) {
- %(op_wb)s;
- }
-
- return fault;
- }
-}};
-
-def template FloatingPointDecode {{
- {
- AlphaStaticInst *i = new %(class_name)s(machInst);
- if (FC == 31) {
- i = makeNop(i);
- }
- return i;
- }
-}};
-
-// General format for floating-point operate instructions:
-// - Checks trapping and rounding mode flags. Trapping modes
-// currently unimplemented (will fail).
-// - Generates NOP if FC == 31.
-def format FloatingPointOperate(code, *opt_args) {{
- iop = InstObjParams(name, Name, 'AlphaFP', CodeBlock(code), opt_args)
- decode_block = FloatingPointDecode.subst(iop)
- header_output = BasicDeclare.subst(iop)
- decoder_output = BasicConstructor.subst(iop)
- exec_output = FloatingPointExecute.subst(iop)
-}};
-
-// Special format for cvttq where rounding mode is pre-decoded
-def format FPFixedRounding(code, class_suffix, *opt_args) {{
- Name += class_suffix
- iop = InstObjParams(name, Name, 'AlphaFP', CodeBlock(code), opt_args)
- decode_block = FloatingPointDecode.subst(iop)
- header_output = BasicDeclare.subst(iop)
- decoder_output = BasicConstructor.subst(iop)
- exec_output = FPFixedRoundingExecute.subst(iop)
-}};
-
-////////////////////////////////////////////////////////////////////
-//
-// Memory-format instructions: LoadAddress, Load, Store
-//
-
-output header {{
- /**
- * Base class for general Alpha memory-format instructions.
- */
- class Memory : public AlphaStaticInst
- {
- protected:
-
- /// Memory request flags. See mem_req_base.hh.
- unsigned memAccessFlags;
- /// Pointer to EAComp object.
- const StaticInstPtr<AlphaISA> eaCompPtr;
- /// Pointer to MemAcc object.
- const StaticInstPtr<AlphaISA> memAccPtr;
-
- /// Constructor
- Memory(const char *mnem, MachInst _machInst, OpClass __opClass,
- StaticInstPtr<AlphaISA> _eaCompPtr = nullStaticInstPtr,
- StaticInstPtr<AlphaISA> _memAccPtr = nullStaticInstPtr)
- : AlphaStaticInst(mnem, _machInst, __opClass),
- memAccessFlags(0), eaCompPtr(_eaCompPtr), memAccPtr(_memAccPtr)
- {
- }
-
- std::string
- generateDisassembly(Addr pc, const SymbolTable *symtab) const;
-
- public:
-
- const StaticInstPtr<AlphaISA> &eaCompInst() const { return eaCompPtr; }
- const StaticInstPtr<AlphaISA> &memAccInst() const { return memAccPtr; }
- };
-
- /**
- * Base class for memory-format instructions using a 32-bit
- * displacement (i.e. most of them).
- */
- class MemoryDisp32 : public Memory
- {
- protected:
- /// Displacement for EA calculation (signed).
- int32_t disp;
-
- /// Constructor.
- MemoryDisp32(const char *mnem, MachInst _machInst, OpClass __opClass,
- StaticInstPtr<AlphaISA> _eaCompPtr = nullStaticInstPtr,
- StaticInstPtr<AlphaISA> _memAccPtr = nullStaticInstPtr)
- : Memory(mnem, _machInst, __opClass, _eaCompPtr, _memAccPtr),
- disp(MEMDISP)
- {
- }
- };
-
-
- /**
- * Base class for a few miscellaneous memory-format insts
- * that don't interpret the disp field: wh64, fetch, fetch_m, ecb.
- * None of these instructions has a destination register either.
- */
- class MemoryNoDisp : public Memory
- {
- protected:
- /// Constructor
- MemoryNoDisp(const char *mnem, MachInst _machInst, OpClass __opClass,
- StaticInstPtr<AlphaISA> _eaCompPtr = nullStaticInstPtr,
- StaticInstPtr<AlphaISA> _memAccPtr = nullStaticInstPtr)
- : Memory(mnem, _machInst, __opClass, _eaCompPtr, _memAccPtr)
- {
- }
-
- std::string
- generateDisassembly(Addr pc, const SymbolTable *symtab) const;
- };
-}};
-
-
-output decoder {{
- std::string
- Memory::generateDisassembly(Addr pc, const SymbolTable *symtab) const
- {
- return csprintf("%-10s %c%d,%d(r%d)", mnemonic,
- flags[IsFloating] ? 'f' : 'r', RA, MEMDISP, RB);
- }
-
- std::string
- MemoryNoDisp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
- {
- return csprintf("%-10s (r%d)", mnemonic, RB);
- }
-}};
-
-def format LoadAddress(code) {{
- iop = InstObjParams(name, Name, 'MemoryDisp32', CodeBlock(code))
- header_output = BasicDeclare.subst(iop)
- decoder_output = BasicConstructor.subst(iop)
- decode_block = BasicDecode.subst(iop)
- exec_output = BasicExecute.subst(iop)
-}};
-
-
-def template LoadStoreDeclare {{
- /**
- * Static instruction class for "%(mnemonic)s".
- */
- class %(class_name)s : public %(base_class)s
- {
- protected:
-
- /**
- * "Fake" effective address computation class for "%(mnemonic)s".
- */
- class EAComp : public %(base_class)s
- {
- public:
- /// Constructor
- EAComp(MachInst machInst);
-
- %(BasicExecDeclare)s
- };
-
- /**
- * "Fake" memory access instruction class for "%(mnemonic)s".
- */
- class MemAcc : public %(base_class)s
- {
- public:
- /// Constructor
- MemAcc(MachInst machInst);
-
- %(BasicExecDeclare)s
- };
-
- public:
-
- /// Constructor.
- %(class_name)s(MachInst machInst);
-
- %(BasicExecDeclare)s
- };
-}};
-
-def template LoadStoreConstructor {{
- /** TODO: change op_class to AddrGenOp or something (requires
- * creating new member of OpClass enum in op_class.hh, updating
- * config files, etc.). */
- inline %(class_name)s::EAComp::EAComp(MachInst machInst)
- : %(base_class)s("%(mnemonic)s (EAComp)", machInst, IntAluOp)
- {
- %(ea_constructor)s;
- }
-
- inline %(class_name)s::MemAcc::MemAcc(MachInst machInst)
- : %(base_class)s("%(mnemonic)s (MemAcc)", machInst, %(op_class)s)
- {
- %(memacc_constructor)s;
- }
-
- inline %(class_name)s::%(class_name)s(MachInst machInst)
- : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s,
- new EAComp(machInst), new MemAcc(machInst))
- {
- %(constructor)s;
- }
-}};
-
-
-def template EACompExecute {{
- Fault
- %(class_name)s::EAComp::execute(%(CPU_exec_context)s *xc,
- Trace::InstRecord *traceData) const
- {
- Addr EA;
- Fault fault = No_Fault;
-
- %(fp_enable_check)s;
- %(op_decl)s;
- %(op_rd)s;
- %(code)s;
-
- if (fault == No_Fault) {
- %(op_wb)s;
- xc->setEA(EA);
- }
-
- return fault;
- }
-}};
-
-def template MemAccExecute {{
- Fault
- %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc,
- Trace::InstRecord *traceData) const
- {
- Addr EA;
- Fault fault = No_Fault;
-
- %(fp_enable_check)s;
- %(op_decl)s;
- %(op_nonmem_rd)s;
- EA = xc->getEA();
-
- if (fault == No_Fault) {
- %(op_mem_rd)s;
- %(code)s;
- }
-
- if (fault == No_Fault) {
- %(op_mem_wb)s;
- }
-
- if (fault == No_Fault) {
- %(postacc_code)s;
- }
-
- if (fault == No_Fault) {
- %(op_nonmem_wb)s;
- }
-
- return fault;
- }
-}};
-
-
-def template LoadStoreExecute {{
- Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
- Trace::InstRecord *traceData) const
- {
- Addr EA;
- Fault fault = No_Fault;
-
- %(fp_enable_check)s;
- %(op_decl)s;
- %(op_nonmem_rd)s;
- %(ea_code)s;
-
- if (fault == No_Fault) {
- %(op_mem_rd)s;
- %(memacc_code)s;
- }
-
- if (fault == No_Fault) {
- %(op_mem_wb)s;
- }
-
- if (fault == No_Fault) {
- %(postacc_code)s;
- }
-
- if (fault == No_Fault) {
- %(op_nonmem_wb)s;
- }
-
- return fault;
- }
-}};
-
-
-def template PrefetchExecute {{
- Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
- Trace::InstRecord *traceData) const
- {
- Addr EA;
- Fault fault = No_Fault;
-
- %(fp_enable_check)s;
- %(op_decl)s;
- %(op_nonmem_rd)s;
- %(ea_code)s;
-
- if (fault == No_Fault) {
- xc->prefetch(EA, memAccessFlags);
- }
-
- return No_Fault;
- }
-}};
-
-// load instructions use Ra as dest, so check for
-// Ra == 31 to detect nops
-def template LoadNopCheckDecode {{
- {
- AlphaStaticInst *i = new %(class_name)s(machInst);
- if (RA == 31) {
- i = makeNop(i);
- }
- return i;
- }
-}};
-
-
-// for some load instructions, Ra == 31 indicates a prefetch (not a nop)
-def template LoadPrefetchCheckDecode {{
- {
- if (RA != 31) {
- return new %(class_name)s(machInst);
- }
- else {
- return new %(class_name)sPrefetch(machInst);
- }
- }
-}};
-
-
-let {{
-def LoadStoreBase(name, Name, ea_code, memacc_code, postacc_code = '',
- base_class = 'MemoryDisp32', flags = [],
- decode_template = BasicDecode,
- exec_template = LoadStoreExecute):
- # Segregate flags into instruction flags (handled by InstObjParams)
- # and memory access flags (handled here).
-
- # Would be nice to autogenerate this list, but oh well.
- valid_mem_flags = ['LOCKED', 'NO_FAULT', 'EVICT_NEXT', 'PF_EXCLUSIVE']
- mem_flags = [f for f in flags if f in valid_mem_flags]
- inst_flags = [f for f in flags if f not in valid_mem_flags]
-
- # add hook to get effective addresses into execution trace output.
- ea_code += '\nif (traceData) { traceData->setAddr(EA); }\n'
-
- # generate code block objects
- ea_cblk = CodeBlock(ea_code)
- memacc_cblk = CodeBlock(memacc_code)
- postacc_cblk = CodeBlock(postacc_code)
-
- # Some CPU models execute the memory operation as an atomic unit,
- # while others want to separate them into an effective address
- # computation and a memory access operation. As a result, we need
- # to generate three StaticInst objects. Note that the latter two
- # are nested inside the larger "atomic" one.
-
- # generate InstObjParams for EAComp object
- ea_iop = InstObjParams(name, Name, base_class, ea_cblk, inst_flags)
-
- # generate InstObjParams for MemAcc object
- memacc_iop = InstObjParams(name, Name, base_class, memacc_cblk, inst_flags)
- # in the split execution model, the MemAcc portion is responsible
- # for the post-access code.
- memacc_iop.postacc_code = postacc_cblk.code
-
- # generate InstObjParams for unified execution
- cblk = CodeBlock(ea_code + memacc_code + postacc_code)
- iop = InstObjParams(name, Name, base_class, cblk, inst_flags)
-
- iop.ea_constructor = ea_cblk.constructor
- iop.ea_code = ea_cblk.code
- iop.memacc_constructor = memacc_cblk.constructor
- iop.memacc_code = memacc_cblk.code
- iop.postacc_code = postacc_cblk.code
-
- if mem_flags:
- s = '\n\tmemAccessFlags = ' + string.join(mem_flags, '|') + ';'
- iop.constructor += s
- memacc_iop.constructor += s
-
- # (header_output, decoder_output, decode_block, exec_output)
- return (LoadStoreDeclare.subst(iop), LoadStoreConstructor.subst(iop),
- decode_template.subst(iop),
- EACompExecute.subst(ea_iop)
- + MemAccExecute.subst(memacc_iop)
- + exec_template.subst(iop))
-}};
-
-
-def format LoadOrNop(ea_code, memacc_code, *flags) {{
- (header_output, decoder_output, decode_block, exec_output) = \
- LoadStoreBase(name, Name, ea_code, memacc_code, flags = flags,
- decode_template = LoadNopCheckDecode)
-}};
-
-
-// Note that the flags passed in apply only to the prefetch version
-def format LoadOrPrefetch(ea_code, memacc_code, *pf_flags) {{
- # declare the load instruction object and generate the decode block
- (header_output, decoder_output, decode_block, exec_output) = \
- LoadStoreBase(name, Name, ea_code, memacc_code,
- decode_template = LoadPrefetchCheckDecode)
-
- # Declare the prefetch instruction object.
-
- # convert flags from tuple to list to make them mutable
- pf_flags = list(pf_flags) + ['IsMemRef', 'IsLoad', 'IsDataPrefetch', 'MemReadOp', 'NO_FAULT']
-
- (pf_header_output, pf_decoder_output, _, pf_exec_output) = \
- LoadStoreBase(name, Name + 'Prefetch', ea_code, '',
- flags = pf_flags, exec_template = PrefetchExecute)
-
- header_output += pf_header_output
- decoder_output += pf_decoder_output
- exec_output += pf_exec_output
-}};
-
-
-def format Store(ea_code, memacc_code, *flags) {{
- (header_output, decoder_output, decode_block, exec_output) = \
- LoadStoreBase(name, Name, ea_code, memacc_code, flags = flags)
-}};
-
-
-def format StoreCond(ea_code, memacc_code, postacc_code, *flags) {{
- (header_output, decoder_output, decode_block, exec_output) = \
- LoadStoreBase(name, Name, ea_code, memacc_code, postacc_code,
- flags = flags)
-}};
-
-
-// Use 'MemoryNoDisp' as base: for wh64, fetch, ecb
-def format MiscPrefetch(ea_code, memacc_code, *flags) {{
- (header_output, decoder_output, decode_block, exec_output) = \
- LoadStoreBase(name, Name, ea_code, memacc_code, flags = flags,
- base_class = 'MemoryNoDisp')
-}};
-
-
-////////////////////////////////////////////////////////////////////
-//
-// Control transfer instructions
-//
-
-output header {{
-
- /**
- * Base class for instructions whose disassembly is not purely a
- * function of the machine instruction (i.e., it depends on the
- * PC). This class overrides the disassemble() method to check
- * the PC and symbol table values before re-using a cached
- * disassembly string. This is necessary for branches and jumps,
- * where the disassembly string includes the target address (which
- * may depend on the PC and/or symbol table).
- */
- class PCDependentDisassembly : public AlphaStaticInst
- {
- protected:
- /// Cached program counter from last disassembly
- mutable Addr cachedPC;
- /// Cached symbol table pointer from last disassembly
- mutable const SymbolTable *cachedSymtab;
-
- /// Constructor
- PCDependentDisassembly(const char *mnem, MachInst _machInst,
- OpClass __opClass)
- : AlphaStaticInst(mnem, _machInst, __opClass),
- cachedPC(0), cachedSymtab(0)
- {
- }
-
- const std::string &
- disassemble(Addr pc, const SymbolTable *symtab) const;
- };
-
- /**
- * Base class for branches (PC-relative control transfers),
- * conditional or unconditional.
- */
- class Branch : public PCDependentDisassembly
- {
- protected:
- /// Displacement to target address (signed).
- int32_t disp;
-
- /// Constructor.
- Branch(const char *mnem, MachInst _machInst, OpClass __opClass)
- : PCDependentDisassembly(mnem, _machInst, __opClass),
- disp(BRDISP << 2)
- {
- }
-
- Addr branchTarget(Addr branchPC) const;
-
- std::string
- generateDisassembly(Addr pc, const SymbolTable *symtab) const;
- };
-
- /**
- * Base class for jumps (register-indirect control transfers). In
- * the Alpha ISA, these are always unconditional.
- */
- class Jump : public PCDependentDisassembly
- {
- protected:
-
- /// Displacement to target address (signed).
- int32_t disp;
-
- public:
- /// Constructor
- Jump(const char *mnem, MachInst _machInst, OpClass __opClass)
- : PCDependentDisassembly(mnem, _machInst, __opClass),
- disp(BRDISP)
- {
- }
-
- Addr branchTarget(ExecContext *xc) const;
-
- std::string
- generateDisassembly(Addr pc, const SymbolTable *symtab) const;
- };
-}};
-
-output decoder {{
- Addr
- Branch::branchTarget(Addr branchPC) const
- {
- return branchPC + 4 + disp;
- }
-
- Addr
- Jump::branchTarget(ExecContext *xc) const
- {
- Addr NPC = xc->readPC() + 4;
- uint64_t Rb = xc->readIntReg(_srcRegIdx[0]);
- return (Rb & ~3) | (NPC & 1);
- }
-
- const std::string &
- PCDependentDisassembly::disassemble(Addr pc,
- const SymbolTable *symtab) const
- {
- if (!cachedDisassembly ||
- pc != cachedPC || symtab != cachedSymtab)
- {
- if (cachedDisassembly)
- delete cachedDisassembly;
-
- cachedDisassembly =
- new std::string(generateDisassembly(pc, symtab));
- cachedPC = pc;
- cachedSymtab = symtab;
- }
-
- return *cachedDisassembly;
- }
-
- std::string
- Branch::generateDisassembly(Addr pc, const SymbolTable *symtab) const
- {
- std::stringstream ss;
-
- ccprintf(ss, "%-10s ", mnemonic);
-
- // There's only one register arg (RA), but it could be
- // either a source (the condition for conditional
- // branches) or a destination (the link reg for
- // unconditional branches)
- if (_numSrcRegs > 0) {
- printReg(ss, _srcRegIdx[0]);
- ss << ",";
- }
- else if (_numDestRegs > 0) {
- printReg(ss, _destRegIdx[0]);
- ss << ",";
- }
-
-#ifdef SS_COMPATIBLE_DISASSEMBLY
- if (_numSrcRegs == 0 && _numDestRegs == 0) {
- printReg(ss, 31);
- ss << ",";
- }
-#endif
-
- Addr target = pc + 4 + disp;
-
- std::string str;
- if (symtab && symtab->findSymbol(target, str))
- ss << str;
- else
- ccprintf(ss, "0x%x", target);
-
- return ss.str();
- }
-
- std::string
- Jump::generateDisassembly(Addr pc, const SymbolTable *symtab) const
- {
- std::stringstream ss;
-
- ccprintf(ss, "%-10s ", mnemonic);
-
-#ifdef SS_COMPATIBLE_DISASSEMBLY
- if (_numDestRegs == 0) {
- printReg(ss, 31);
- ss << ",";
- }
-#endif
-
- if (_numDestRegs > 0) {
- printReg(ss, _destRegIdx[0]);
- ss << ",";
- }
-
- ccprintf(ss, "(r%d)", RB);
-
- return ss.str();
- }
-}};
-
-def template JumpOrBranchDecode {{
- return (RA == 31)
- ? (StaticInst<AlphaISA> *)new %(class_name)s(machInst)
- : (StaticInst<AlphaISA> *)new %(class_name)sAndLink(machInst);
-}};
-
-def format CondBranch(code) {{
- code = 'bool cond;\n' + code + '\nif (cond) NPC = NPC + disp;\n';
- iop = InstObjParams(name, Name, 'Branch', CodeBlock(code),
- ('IsDirectControl', 'IsCondControl'))
- header_output = BasicDeclare.subst(iop)
- decoder_output = BasicConstructor.subst(iop)
- decode_block = BasicDecode.subst(iop)
- exec_output = BasicExecute.subst(iop)
-}};
-
-let {{
-def UncondCtrlBase(name, Name, base_class, npc_expr, flags):
- # Declare basic control transfer w/o link (i.e. link reg is R31)
- nolink_code = 'NPC = %s;\n' % npc_expr
- nolink_iop = InstObjParams(name, Name, base_class,
- CodeBlock(nolink_code), flags)
- header_output = BasicDeclare.subst(nolink_iop)
- decoder_output = BasicConstructor.subst(nolink_iop)
- exec_output = BasicExecute.subst(nolink_iop)
-
- # Generate declaration of '*AndLink' version, append to decls
- link_code = 'Ra = NPC & ~3;\n' + nolink_code
- link_iop = InstObjParams(name, Name + 'AndLink', base_class,
- CodeBlock(link_code), flags)
- header_output += BasicDeclare.subst(link_iop)
- decoder_output += BasicConstructor.subst(link_iop)
- exec_output += BasicExecute.subst(link_iop)
-
- # need to use link_iop for the decode template since it is expecting
- # the shorter version of class_name (w/o "AndLink")
-
- return (header_output, decoder_output,
- JumpOrBranchDecode.subst(nolink_iop), exec_output)
-}};
-
-def format UncondBranch(*flags) {{
- flags += ('IsUncondControl', 'IsDirectControl')
- (header_output, decoder_output, decode_block, exec_output) = \
- UncondCtrlBase(name, Name, 'Branch', 'NPC + disp', flags)
-}};
-
-def format Jump(*flags) {{
- flags += ('IsUncondControl', 'IsIndirectControl')
- (header_output, decoder_output, decode_block, exec_output) = \
- UncondCtrlBase(name, Name, 'Jump', '(Rb & ~3) | (NPC & 1)', flags)
-}};
-
-
-////////////////////////////////////////////////////////////////////
-//
-// PAL calls
-//
-
-output header {{
- /**
- * Base class for emulated call_pal calls (used only in
- * non-full-system mode).
- */
- class EmulatedCallPal : public AlphaStaticInst
- {
- protected:
-
- /// Constructor.
- EmulatedCallPal(const char *mnem, MachInst _machInst,
- OpClass __opClass)
- : AlphaStaticInst(mnem, _machInst, __opClass)
- {
- }
-
- std::string
- generateDisassembly(Addr pc, const SymbolTable *symtab) const;
- };
-}};
-
-output decoder {{
- std::string
- EmulatedCallPal::generateDisassembly(Addr pc,
- const SymbolTable *symtab) const
- {
-#ifdef SS_COMPATIBLE_DISASSEMBLY
- return csprintf("%s %s", "call_pal", mnemonic);
-#else
- return csprintf("%-10s %s", "call_pal", mnemonic);
-#endif
- }
-}};
-
-def format EmulatedCallPal(code, *flags) {{
- iop = InstObjParams(name, Name, 'EmulatedCallPal', CodeBlock(code), flags)
- header_output = BasicDeclare.subst(iop)
- decoder_output = BasicConstructor.subst(iop)
- decode_block = BasicDecode.subst(iop)
- exec_output = BasicExecute.subst(iop)
-}};
-
-output header {{
- /**
- * Base class for full-system-mode call_pal instructions.
- * Probably could turn this into a leaf class and get rid of the
- * parser template.
- */
- class CallPalBase : public AlphaStaticInst
- {
- protected:
- int palFunc; ///< Function code part of instruction
- int palOffset; ///< Target PC, offset from IPR_PAL_BASE
- bool palValid; ///< is the function code valid?
- bool palPriv; ///< is this call privileged?
-
- /// Constructor.
- CallPalBase(const char *mnem, MachInst _machInst,
- OpClass __opClass);
-
- std::string
- generateDisassembly(Addr pc, const SymbolTable *symtab) const;
- };
-}};
-
-output decoder {{
- inline
- CallPalBase::CallPalBase(const char *mnem, MachInst _machInst,
- OpClass __opClass)
- : AlphaStaticInst(mnem, _machInst, __opClass),
- palFunc(PALFUNC)
- {
- // From the 21164 HRM (paraphrased):
- // Bit 7 of the function code (mask 0x80) indicates
- // whether the call is privileged (bit 7 == 0) or
- // unprivileged (bit 7 == 1). The privileged call table
- // starts at 0x2000, the unprivielged call table starts at
- // 0x3000. Bits 5-0 (mask 0x3f) are used to calculate the
- // offset.
- const int palPrivMask = 0x80;
- const int palOffsetMask = 0x3f;
-
- // Pal call is invalid unless all other bits are 0
- palValid = ((machInst & ~(palPrivMask | palOffsetMask)) == 0);
- palPriv = ((machInst & palPrivMask) == 0);
- int shortPalFunc = (machInst & palOffsetMask);
- // Add 1 to base to set pal-mode bit
- palOffset = (palPriv ? 0x2001 : 0x3001) + (shortPalFunc << 6);
- }
-
- std::string
- CallPalBase::generateDisassembly(Addr pc, const SymbolTable *symtab) const
- {
- return csprintf("%-10s %#x", "call_pal", palFunc);
- }
-}};
-
-def format CallPal(code, *flags) {{
- iop = InstObjParams(name, Name, 'CallPalBase', CodeBlock(code), flags)
- header_output = BasicDeclare.subst(iop)
- decoder_output = BasicConstructor.subst(iop)
- decode_block = BasicDecode.subst(iop)
- exec_output = BasicExecute.subst(iop)
-}};
-
-////////////////////////////////////////////////////////////////////
-//
-// hw_ld, hw_st
-//
-
-output header {{
- /**
- * Base class for hw_ld and hw_st.
- */
- class HwLoadStore : public Memory
- {
- protected:
-
- /// Displacement for EA calculation (signed).
- int16_t disp;
-
- /// Constructor
- HwLoadStore(const char *mnem, MachInst _machInst, OpClass __opClass,
- StaticInstPtr<AlphaISA> _eaCompPtr = nullStaticInstPtr,
- StaticInstPtr<AlphaISA> _memAccPtr = nullStaticInstPtr);
-
- std::string
- generateDisassembly(Addr pc, const SymbolTable *symtab) const;
- };
-}};
-
-
-output decoder {{
- inline
- HwLoadStore::HwLoadStore(const char *mnem, MachInst _machInst,
- OpClass __opClass,
- StaticInstPtr<AlphaISA> _eaCompPtr,
- StaticInstPtr<AlphaISA> _memAccPtr)
- : Memory(mnem, _machInst, __opClass, _eaCompPtr, _memAccPtr),
- disp(HW_LDST_DISP)
- {
- memAccessFlags = 0;
- if (HW_LDST_PHYS) memAccessFlags |= PHYSICAL;
- if (HW_LDST_ALT) memAccessFlags |= ALTMODE;
- if (HW_LDST_VPTE) memAccessFlags |= VPTE;
- if (HW_LDST_LOCK) memAccessFlags |= LOCKED;
- }
-
- std::string
- HwLoadStore::generateDisassembly(Addr pc, const SymbolTable *symtab) const
- {
-#ifdef SS_COMPATIBLE_DISASSEMBLY
- return csprintf("%-10s r%d,%d(r%d)", mnemonic, RA, disp, RB);
-#else
- // HW_LDST_LOCK and HW_LDST_COND are the same bit.
- const char *lock_str =
- (HW_LDST_LOCK) ? (flags[IsLoad] ? ",LOCK" : ",COND") : "";
-
- return csprintf("%-10s r%d,%d(r%d)%s%s%s%s%s",
- mnemonic, RA, disp, RB,
- HW_LDST_PHYS ? ",PHYS" : "",
- HW_LDST_ALT ? ",ALT" : "",
- HW_LDST_QUAD ? ",QUAD" : "",
- HW_LDST_VPTE ? ",VPTE" : "",
- lock_str);
-#endif
- }
-}};
-
-def format HwLoadStore(ea_code, memacc_code, class_ext, *flags) {{
- (header_output, decoder_output, decode_block, exec_output) = \
- LoadStoreBase(name, Name + class_ext, ea_code, memacc_code,
- flags = flags, base_class = 'HwLoadStore')
-}};
-
-
-def format HwStoreCond(ea_code, memacc_code, postacc_code, class_ext, *flags) {{
- (header_output, decoder_output, decode_block, exec_output) = \
- LoadStoreBase(name, Name + class_ext, ea_code, memacc_code,
- postacc_code, flags = flags, base_class = 'HwLoadStore')
-}};
-
-
-output header {{
- /**
- * Base class for hw_mfpr and hw_mtpr.
- */
- class HwMoveIPR : public AlphaStaticInst
- {
- protected:
- /// Index of internal processor register.
- int ipr_index;
-
- /// Constructor
- HwMoveIPR(const char *mnem, MachInst _machInst, OpClass __opClass)
- : AlphaStaticInst(mnem, _machInst, __opClass),
- ipr_index(HW_IPR_IDX)
- {
- }
-
- std::string
- generateDisassembly(Addr pc, const SymbolTable *symtab) const;
- };
-}};
-
-output decoder {{
- std::string
- HwMoveIPR::generateDisassembly(Addr pc, const SymbolTable *symtab) const
- {
- if (_numSrcRegs > 0) {
- // must be mtpr
- return csprintf("%-10s r%d,IPR(%#x)",
- mnemonic, RA, ipr_index);
- }
- else {
- // must be mfpr
- return csprintf("%-10s IPR(%#x),r%d",
- mnemonic, ipr_index, RA);
- }
- }
-}};
-
-def format HwMoveIPR(code) {{
- iop = InstObjParams(name, Name, 'HwMoveIPR', CodeBlock(code),
- ['IprAccessOp'])
- header_output = BasicDeclare.subst(iop)
- decoder_output = BasicConstructor.subst(iop)
- decode_block = BasicDecode.subst(iop)
- exec_output = BasicExecute.subst(iop)
-}};
-
-
-////////////////////////////////////////////////////////////////////
-//
-// Unimplemented instructions
-//
-
-output header {{
- /**
- * Static instruction class for unimplemented instructions that
- * cause simulator termination. Note that these are recognized
- * (legal) instructions that the simulator does not support; the
- * 'Unknown' class is used for unrecognized/illegal instructions.
- * This is a leaf class.
- */
- class FailUnimplemented : public AlphaStaticInst
- {
- public:
- /// Constructor
- FailUnimplemented(const char *_mnemonic, MachInst _machInst)
- : AlphaStaticInst(_mnemonic, _machInst, No_OpClass)
- {
- // don't call execute() (which panics) if we're on a
- // speculative path
- flags[IsNonSpeculative] = true;
- }
-
- %(BasicExecDeclare)s
-
- std::string
- generateDisassembly(Addr pc, const SymbolTable *symtab) const;
- };
-
- /**
- * Base class for unimplemented instructions that cause a warning
- * to be printed (but do not terminate simulation). This
- * implementation is a little screwy in that it will print a
- * warning for each instance of a particular unimplemented machine
- * instruction, not just for each unimplemented opcode. Should
- * probably make the 'warned' flag a static member of the derived
- * class.
- */
- class WarnUnimplemented : public AlphaStaticInst
- {
- private:
- /// Have we warned on this instruction yet?
- mutable bool warned;
-
- public:
- /// Constructor
- WarnUnimplemented(const char *_mnemonic, MachInst _machInst)
- : AlphaStaticInst(_mnemonic, _machInst, No_OpClass), warned(false)
- {
- // don't call execute() (which panics) if we're on a
- // speculative path
- flags[IsNonSpeculative] = true;
- }
-
- %(BasicExecDeclare)s
-
- std::string
- generateDisassembly(Addr pc, const SymbolTable *symtab) const;
- };
-}};
-
-output decoder {{
- std::string
- FailUnimplemented::generateDisassembly(Addr pc,
- const SymbolTable *symtab) const
- {
- return csprintf("%-10s (unimplemented)", mnemonic);
- }
-
- std::string
- WarnUnimplemented::generateDisassembly(Addr pc,
- const SymbolTable *symtab) const
- {
-#ifdef SS_COMPATIBLE_DISASSEMBLY
- return csprintf("%-10s", mnemonic);
-#else
- return csprintf("%-10s (unimplemented)", mnemonic);
-#endif
- }
-}};
-
-output exec {{
- Fault
- FailUnimplemented::execute(%(CPU_exec_context)s *xc,
- Trace::InstRecord *traceData) const
- {
- panic("attempt to execute unimplemented instruction '%s' "
- "(inst 0x%08x, opcode 0x%x)", mnemonic, machInst, OPCODE);
- return Unimplemented_Opcode_Fault;
- }
-
- Fault
- WarnUnimplemented::execute(%(CPU_exec_context)s *xc,
- Trace::InstRecord *traceData) const
- {
- if (!warned) {
- warn("instruction '%s' unimplemented\n", mnemonic);
- warned = true;
- }
-
- return No_Fault;
- }
-}};
-
-
-def format FailUnimpl() {{
- iop = InstObjParams(name, 'FailUnimplemented')
- decode_block = BasicDecodeWithMnemonic.subst(iop)
-}};
-
-def format WarnUnimpl() {{
- iop = InstObjParams(name, 'WarnUnimplemented')
- decode_block = BasicDecodeWithMnemonic.subst(iop)
-}};
-
-output header {{
- /**
- * Static instruction class for unknown (illegal) instructions.
- * These cause simulator termination if they are executed in a
- * non-speculative mode. This is a leaf class.
- */
- class Unknown : public AlphaStaticInst
- {
- public:
- /// Constructor
- Unknown(MachInst _machInst)
- : AlphaStaticInst("unknown", _machInst, No_OpClass)
- {
- // don't call execute() (which panics) if we're on a
- // speculative path
- flags[IsNonSpeculative] = true;
- }
-
- %(BasicExecDeclare)s
-
- std::string
- generateDisassembly(Addr pc, const SymbolTable *symtab) const;
- };
-}};
-
-////////////////////////////////////////////////////////////////////
-//
-// Unknown instructions
-//
-
-output decoder {{
- std::string
- Unknown::generateDisassembly(Addr pc, const SymbolTable *symtab) const
- {
- return csprintf("%-10s (inst 0x%x, opcode 0x%x)",
- "unknown", machInst, OPCODE);
- }
-}};
-
-output exec {{
- Fault
- Unknown::execute(%(CPU_exec_context)s *xc,
- Trace::InstRecord *traceData) const
- {
- panic("attempt to execute unknown instruction "
- "(inst 0x%08x, opcode 0x%x)", machInst, OPCODE);
- return Unimplemented_Opcode_Fault;
- }
-}};
-
-def format Unknown() {{
- decode_block = 'return new Unknown(machInst);\n'
-}};
-
-////////////////////////////////////////////////////////////////////
-//
-// Utility functions for execute methods
-//
-
-output exec {{
-
- /// Return opa + opb, summing carry into third arg.
- inline uint64_t
- addc(uint64_t opa, uint64_t opb, int &carry)
- {
- uint64_t res = opa + opb;
- if (res < opa || res < opb)
- ++carry;
- return res;
- }
-
- /// Multiply two 64-bit values (opa * opb), returning the 128-bit
- /// product in res_hi and res_lo.
- inline void
- mul128(uint64_t opa, uint64_t opb, uint64_t &res_hi, uint64_t &res_lo)
- {
- // do a 64x64 --> 128 multiply using four 32x32 --> 64 multiplies
- uint64_t opa_hi = opa<63:32>;
- uint64_t opa_lo = opa<31:0>;
- uint64_t opb_hi = opb<63:32>;
- uint64_t opb_lo = opb<31:0>;
-
- res_lo = opa_lo * opb_lo;
-
- // The middle partial products logically belong in bit
- // positions 95 to 32. Thus the lower 32 bits of each product
- // sum into the upper 32 bits of the low result, while the
- // upper 32 sum into the low 32 bits of the upper result.
- uint64_t partial1 = opa_hi * opb_lo;
- uint64_t partial2 = opa_lo * opb_hi;
-
- uint64_t partial1_lo = partial1<31:0> << 32;
- uint64_t partial1_hi = partial1<63:32>;
- uint64_t partial2_lo = partial2<31:0> << 32;
- uint64_t partial2_hi = partial2<63:32>;
-
- // Add partial1_lo and partial2_lo to res_lo, keeping track
- // of any carries out
- int carry_out = 0;
- res_lo = addc(partial1_lo, res_lo, carry_out);
- res_lo = addc(partial2_lo, res_lo, carry_out);
-
- // Now calculate the high 64 bits...
- res_hi = (opa_hi * opb_hi) + partial1_hi + partial2_hi + carry_out;
- }
-
- /// Map 8-bit S-floating exponent to 11-bit T-floating exponent.
- /// See Table 2-2 of Alpha AHB.
- inline int
- map_s(int old_exp)
- {
- int hibit = old_exp<7:>;
- int lobits = old_exp<6:0>;
-
- if (hibit == 1) {
- return (lobits == 0x7f) ? 0x7ff : (0x400 | lobits);
- }
- else {
- return (lobits == 0) ? 0 : (0x380 | lobits);
- }
- }
-
- /// Convert a 32-bit S-floating value to the equivalent 64-bit
- /// representation to be stored in an FP reg.
- inline uint64_t
- s_to_t(uint32_t s_val)
- {
- uint64_t tmp = s_val;
- return (tmp<31:> << 63 // sign bit
- | (uint64_t)map_s(tmp<30:23>) << 52 // exponent
- | tmp<22:0> << 29); // fraction
- }
-
- /// Convert a 64-bit T-floating value to the equivalent 32-bit
- /// S-floating representation to be stored in memory.
- inline int32_t
- t_to_s(uint64_t t_val)
- {
- return (t_val<63:62> << 30 // sign bit & hi exp bit
- | t_val<58:29>); // rest of exp & fraction
- }
-}};
-
-////////////////////////////////////////////////////////////////////
-//
-// The actual decoder specification
-//
-
-decode OPCODE default Unknown::unknown() {
-
- format LoadAddress {
- 0x08: lda({{ Ra = Rb + disp; }});
- 0x09: ldah({{ Ra = Rb + (disp << 16); }});
- }
-
- format LoadOrNop {
- 0x0a: ldbu({{ EA = Rb + disp; }}, {{ Ra.uq = Mem.ub; }});
- 0x0c: ldwu({{ EA = Rb + disp; }}, {{ Ra.uq = Mem.uw; }});
- 0x0b: ldq_u({{ EA = (Rb + disp) & ~7; }}, {{ Ra = Mem.uq; }});
- 0x23: ldt({{ EA = Rb + disp; }}, {{ Fa = Mem.df; }});
- 0x2a: ldl_l({{ EA = Rb + disp; }}, {{ Ra.sl = Mem.sl; }}, LOCKED);
- 0x2b: ldq_l({{ EA = Rb + disp; }}, {{ Ra.uq = Mem.uq; }}, LOCKED);
- 0x20: copy_load({{EA = Ra;}},
- {{fault = xc->copySrcTranslate(EA);}},
- IsMemRef, IsLoad, IsCopy);
- }
-
- format LoadOrPrefetch {
- 0x28: ldl({{ EA = Rb + disp; }}, {{ Ra.sl = Mem.sl; }});
- 0x29: ldq({{ EA = Rb + disp; }}, {{ Ra.uq = Mem.uq; }}, EVICT_NEXT);
- // IsFloating flag on lds gets the prefetch to disassemble
- // using f31 instead of r31... funcitonally it's unnecessary
- 0x22: lds({{ EA = Rb + disp; }}, {{ Fa.uq = s_to_t(Mem.ul); }},
- PF_EXCLUSIVE, IsFloating);
- }
-
- format Store {
- 0x0e: stb({{ EA = Rb + disp; }}, {{ Mem.ub = Ra<7:0>; }});
- 0x0d: stw({{ EA = Rb + disp; }}, {{ Mem.uw = Ra<15:0>; }});
- 0x2c: stl({{ EA = Rb + disp; }}, {{ Mem.ul = Ra<31:0>; }});
- 0x2d: stq({{ EA = Rb + disp; }}, {{ Mem.uq = Ra.uq; }});
- 0x0f: stq_u({{ EA = (Rb + disp) & ~7; }}, {{ Mem.uq = Ra.uq; }});
- 0x26: sts({{ EA = Rb + disp; }}, {{ Mem.ul = t_to_s(Fa.uq); }});
- 0x27: stt({{ EA = Rb + disp; }}, {{ Mem.df = Fa; }});
- 0x24: copy_store({{EA = Rb;}},
- {{fault = xc->copy(EA);}},
- IsMemRef, IsStore, IsCopy);
- }
-
- format StoreCond {
- 0x2e: stl_c({{ EA = Rb + disp; }}, {{ Mem.ul = Ra<31:0>; }},
- {{
- uint64_t tmp = Mem_write_result;
- // see stq_c
- Ra = (tmp == 0 || tmp == 1) ? tmp : Ra;
- }}, LOCKED);
- 0x2f: stq_c({{ EA = Rb + disp; }}, {{ Mem.uq = Ra; }},
- {{
- uint64_t tmp = Mem_write_result;
- // If the write operation returns 0 or 1, then
- // this was a conventional store conditional,
- // and the value indicates the success/failure
- // of the operation. If another value is
- // returned, then this was a Turbolaser
- // mailbox access, and we don't update the
- // result register at all.
- Ra = (tmp == 0 || tmp == 1) ? tmp : Ra;
- }}, LOCKED);
- }
-
- format IntegerOperate {
-
- 0x10: decode INTFUNC { // integer arithmetic operations
-
- 0x00: addl({{ Rc.sl = Ra.sl + Rb_or_imm.sl; }});
- 0x40: addlv({{
- uint32_t tmp = Ra.sl + Rb_or_imm.sl;
- // signed overflow occurs when operands have same sign
- // and sign of result does not match.
- if (Ra.sl<31:> == Rb_or_imm.sl<31:> && tmp<31:> != Ra.sl<31:>)
- fault = Integer_Overflow_Fault;
- Rc.sl = tmp;
- }});
- 0x02: s4addl({{ Rc.sl = (Ra.sl << 2) + Rb_or_imm.sl; }});
- 0x12: s8addl({{ Rc.sl = (Ra.sl << 3) + Rb_or_imm.sl; }});
-
- 0x20: addq({{ Rc = Ra + Rb_or_imm; }});
- 0x60: addqv({{
- uint64_t tmp = Ra + Rb_or_imm;
- // signed overflow occurs when operands have same sign
- // and sign of result does not match.
- if (Ra<63:> == Rb_or_imm<63:> && tmp<63:> != Ra<63:>)
- fault = Integer_Overflow_Fault;
- Rc = tmp;
- }});
- 0x22: s4addq({{ Rc = (Ra << 2) + Rb_or_imm; }});
- 0x32: s8addq({{ Rc = (Ra << 3) + Rb_or_imm; }});
-
- 0x09: subl({{ Rc.sl = Ra.sl - Rb_or_imm.sl; }});
- 0x49: sublv({{
- uint32_t tmp = Ra.sl - Rb_or_imm.sl;
- // signed overflow detection is same as for add,
- // except we need to look at the *complemented*
- // sign bit of the subtrahend (Rb), i.e., if the initial
- // signs are the *same* then no overflow can occur
- if (Ra.sl<31:> != Rb_or_imm.sl<31:> && tmp<31:> != Ra.sl<31:>)
- fault = Integer_Overflow_Fault;
- Rc.sl = tmp;
- }});
- 0x0b: s4subl({{ Rc.sl = (Ra.sl << 2) - Rb_or_imm.sl; }});
- 0x1b: s8subl({{ Rc.sl = (Ra.sl << 3) - Rb_or_imm.sl; }});
-
- 0x29: subq({{ Rc = Ra - Rb_or_imm; }});
- 0x69: subqv({{
- uint64_t tmp = Ra - Rb_or_imm;
- // signed overflow detection is same as for add,
- // except we need to look at the *complemented*
- // sign bit of the subtrahend (Rb), i.e., if the initial
- // signs are the *same* then no overflow can occur
- if (Ra<63:> != Rb_or_imm<63:> && tmp<63:> != Ra<63:>)
- fault = Integer_Overflow_Fault;
- Rc = tmp;
- }});
- 0x2b: s4subq({{ Rc = (Ra << 2) - Rb_or_imm; }});
- 0x3b: s8subq({{ Rc = (Ra << 3) - Rb_or_imm; }});
-
- 0x2d: cmpeq({{ Rc = (Ra == Rb_or_imm); }});
- 0x6d: cmple({{ Rc = (Ra.sq <= Rb_or_imm.sq); }});
- 0x4d: cmplt({{ Rc = (Ra.sq < Rb_or_imm.sq); }});
- 0x3d: cmpule({{ Rc = (Ra.uq <= Rb_or_imm.uq); }});
- 0x1d: cmpult({{ Rc = (Ra.uq < Rb_or_imm.uq); }});
-
- 0x0f: cmpbge({{
- int hi = 7;
- int lo = 0;
- uint64_t tmp = 0;
- for (int i = 0; i < 8; ++i) {
- tmp |= (Ra.uq<hi:lo> >= Rb_or_imm.uq<hi:lo>) << i;
- hi += 8;
- lo += 8;
- }
- Rc = tmp;
- }});
- }
-
- 0x11: decode INTFUNC { // integer logical operations
-
- 0x00: and({{ Rc = Ra & Rb_or_imm; }});
- 0x08: bic({{ Rc = Ra & ~Rb_or_imm; }});
- 0x20: bis({{ Rc = Ra | Rb_or_imm; }});
- 0x28: ornot({{ Rc = Ra | ~Rb_or_imm; }});
- 0x40: xor({{ Rc = Ra ^ Rb_or_imm; }});
- 0x48: eqv({{ Rc = Ra ^ ~Rb_or_imm; }});
-
- // conditional moves
- 0x14: cmovlbs({{ Rc = ((Ra & 1) == 1) ? Rb_or_imm : Rc; }});
- 0x16: cmovlbc({{ Rc = ((Ra & 1) == 0) ? Rb_or_imm : Rc; }});
- 0x24: cmoveq({{ Rc = (Ra == 0) ? Rb_or_imm : Rc; }});
- 0x26: cmovne({{ Rc = (Ra != 0) ? Rb_or_imm : Rc; }});
- 0x44: cmovlt({{ Rc = (Ra.sq < 0) ? Rb_or_imm : Rc; }});
- 0x46: cmovge({{ Rc = (Ra.sq >= 0) ? Rb_or_imm : Rc; }});
- 0x64: cmovle({{ Rc = (Ra.sq <= 0) ? Rb_or_imm : Rc; }});
- 0x66: cmovgt({{ Rc = (Ra.sq > 0) ? Rb_or_imm : Rc; }});
-
- // For AMASK, RA must be R31.
- 0x61: decode RA {
- 31: amask({{ Rc = Rb_or_imm & ~ULL(0x17); }});
- }
-
- // For IMPLVER, RA must be R31 and the B operand
- // must be the immediate value 1.
- 0x6c: decode RA {
- 31: decode IMM {
- 1: decode INTIMM {
- // return EV5 for FULL_SYSTEM and EV6 otherwise
- 1: implver({{
-#if FULL_SYSTEM
- Rc = 1;
-#else
- Rc = 2;
-#endif
- }});
- }
- }
- }
-
-#if FULL_SYSTEM
- // The mysterious 11.25...
- 0x25: WarnUnimpl::eleven25();
-#endif
- }
-
- 0x12: decode INTFUNC {
- 0x39: sll({{ Rc = Ra << Rb_or_imm<5:0>; }});
- 0x34: srl({{ Rc = Ra.uq >> Rb_or_imm<5:0>; }});
- 0x3c: sra({{ Rc = Ra.sq >> Rb_or_imm<5:0>; }});
-
- 0x02: mskbl({{ Rc = Ra & ~(mask( 8) << (Rb_or_imm<2:0> * 8)); }});
- 0x12: mskwl({{ Rc = Ra & ~(mask(16) << (Rb_or_imm<2:0> * 8)); }});
- 0x22: mskll({{ Rc = Ra & ~(mask(32) << (Rb_or_imm<2:0> * 8)); }});
- 0x32: mskql({{ Rc = Ra & ~(mask(64) << (Rb_or_imm<2:0> * 8)); }});
-
- 0x52: mskwh({{
- int bv = Rb_or_imm<2:0>;
- Rc = bv ? (Ra & ~(mask(16) >> (64 - 8 * bv))) : Ra;
- }});
- 0x62: msklh({{
- int bv = Rb_or_imm<2:0>;
- Rc = bv ? (Ra & ~(mask(32) >> (64 - 8 * bv))) : Ra;
- }});
- 0x72: mskqh({{
- int bv = Rb_or_imm<2:0>;
- Rc = bv ? (Ra & ~(mask(64) >> (64 - 8 * bv))) : Ra;
- }});
-
- 0x06: extbl({{ Rc = (Ra.uq >> (Rb_or_imm<2:0> * 8))< 7:0>; }});
- 0x16: extwl({{ Rc = (Ra.uq >> (Rb_or_imm<2:0> * 8))<15:0>; }});
- 0x26: extll({{ Rc = (Ra.uq >> (Rb_or_imm<2:0> * 8))<31:0>; }});
- 0x36: extql({{ Rc = (Ra.uq >> (Rb_or_imm<2:0> * 8)); }});
-
- 0x5a: extwh({{
- Rc = (Ra << (64 - (Rb_or_imm<2:0> * 8))<5:0>)<15:0>; }});
- 0x6a: extlh({{
- Rc = (Ra << (64 - (Rb_or_imm<2:0> * 8))<5:0>)<31:0>; }});
- 0x7a: extqh({{
- Rc = (Ra << (64 - (Rb_or_imm<2:0> * 8))<5:0>); }});
-
- 0x0b: insbl({{ Rc = Ra< 7:0> << (Rb_or_imm<2:0> * 8); }});
- 0x1b: inswl({{ Rc = Ra<15:0> << (Rb_or_imm<2:0> * 8); }});
- 0x2b: insll({{ Rc = Ra<31:0> << (Rb_or_imm<2:0> * 8); }});
- 0x3b: insql({{ Rc = Ra << (Rb_or_imm<2:0> * 8); }});
-
- 0x57: inswh({{
- int bv = Rb_or_imm<2:0>;
- Rc = bv ? (Ra.uq<15:0> >> (64 - 8 * bv)) : 0;
- }});
- 0x67: inslh({{
- int bv = Rb_or_imm<2:0>;
- Rc = bv ? (Ra.uq<31:0> >> (64 - 8 * bv)) : 0;
- }});
- 0x77: insqh({{
- int bv = Rb_or_imm<2:0>;
- Rc = bv ? (Ra.uq >> (64 - 8 * bv)) : 0;
- }});
-
- 0x30: zap({{
- uint64_t zapmask = 0;
- for (int i = 0; i < 8; ++i) {
- if (Rb_or_imm<i:>)
- zapmask |= (mask(8) << (i * 8));
- }
- Rc = Ra & ~zapmask;
- }});
- 0x31: zapnot({{
- uint64_t zapmask = 0;
- for (int i = 0; i < 8; ++i) {
- if (!Rb_or_imm<i:>)
- zapmask |= (mask(8) << (i * 8));
- }
- Rc = Ra & ~zapmask;
- }});
- }
-
- 0x13: decode INTFUNC { // integer multiplies
- 0x00: mull({{ Rc.sl = Ra.sl * Rb_or_imm.sl; }}, IntMultOp);
- 0x20: mulq({{ Rc = Ra * Rb_or_imm; }}, IntMultOp);
- 0x30: umulh({{
- uint64_t hi, lo;
- mul128(Ra, Rb_or_imm, hi, lo);
- Rc = hi;
- }}, IntMultOp);
- 0x40: mullv({{
- // 32-bit multiply with trap on overflow
- int64_t Rax = Ra.sl; // sign extended version of Ra.sl
- int64_t Rbx = Rb_or_imm.sl;
- int64_t tmp = Rax * Rbx;
- // To avoid overflow, all the upper 32 bits must match
- // the sign bit of the lower 32. We code this as
- // checking the upper 33 bits for all 0s or all 1s.
- uint64_t sign_bits = tmp<63:31>;
- if (sign_bits != 0 && sign_bits != mask(33))
- fault = Integer_Overflow_Fault;
- Rc.sl = tmp<31:0>;
- }}, IntMultOp);
- 0x60: mulqv({{
- // 64-bit multiply with trap on overflow
- uint64_t hi, lo;
- mul128(Ra, Rb_or_imm, hi, lo);
- // all the upper 64 bits must match the sign bit of
- // the lower 64
- if (!((hi == 0 && lo<63:> == 0) ||
- (hi == mask(64) && lo<63:> == 1)))
- fault = Integer_Overflow_Fault;
- Rc = lo;
- }}, IntMultOp);
- }
-
- 0x1c: decode INTFUNC {
- 0x00: decode RA { 31: sextb({{ Rc.sb = Rb_or_imm< 7:0>; }}); }
- 0x01: decode RA { 31: sextw({{ Rc.sw = Rb_or_imm<15:0>; }}); }
- 0x32: ctlz({{
- uint64_t count = 0;
- uint64_t temp = Rb;
- if (temp<63:32>) temp >>= 32; else count += 32;
- if (temp<31:16>) temp >>= 16; else count += 16;
- if (temp<15:8>) temp >>= 8; else count += 8;
- if (temp<7:4>) temp >>= 4; else count += 4;
- if (temp<3:2>) temp >>= 2; else count += 2;
- if (temp<1:1>) temp >>= 1; else count += 1;
- if ((temp<0:0>) != 0x1) count += 1;
- Rc = count;
- }}, IntAluOp);
-
- 0x33: cttz({{
- uint64_t count = 0;
- uint64_t temp = Rb;
- if (!(temp<31:0>)) { temp >>= 32; count += 32; }
- if (!(temp<15:0>)) { temp >>= 16; count += 16; }
- if (!(temp<7:0>)) { temp >>= 8; count += 8; }
- if (!(temp<3:0>)) { temp >>= 4; count += 4; }
- if (!(temp<1:0>)) { temp >>= 2; count += 2; }
- if (!(temp<0:0> & ULL(0x1))) count += 1;
- Rc = count;
- }}, IntAluOp);
-
- format FailUnimpl {
- 0x30: ctpop();
- 0x31: perr();
- 0x34: unpkbw();
- 0x35: unpkbl();
- 0x36: pkwb();
- 0x37: pklb();
- 0x38: minsb8();
- 0x39: minsw4();
- 0x3a: minub8();
- 0x3b: minuw4();
- 0x3c: maxub8();
- 0x3d: maxuw4();
- 0x3e: maxsb8();
- 0x3f: maxsw4();
- }
-
- format BasicOperateWithNopCheck {
- 0x70: decode RB {
- 31: ftoit({{ Rc = Fa.uq; }}, FloatCvtOp);
- }
- 0x78: decode RB {
- 31: ftois({{ Rc.sl = t_to_s(Fa.uq); }},
- FloatCvtOp);
- }
- }
- }
- }
-
- // Conditional branches.
- format CondBranch {
- 0x39: beq({{ cond = (Ra == 0); }});
- 0x3d: bne({{ cond = (Ra != 0); }});
- 0x3e: bge({{ cond = (Ra.sq >= 0); }});
- 0x3f: bgt({{ cond = (Ra.sq > 0); }});
- 0x3b: ble({{ cond = (Ra.sq <= 0); }});
- 0x3a: blt({{ cond = (Ra.sq < 0); }});
- 0x38: blbc({{ cond = ((Ra & 1) == 0); }});
- 0x3c: blbs({{ cond = ((Ra & 1) == 1); }});
-
- 0x31: fbeq({{ cond = (Fa == 0); }});
- 0x35: fbne({{ cond = (Fa != 0); }});
- 0x36: fbge({{ cond = (Fa >= 0); }});
- 0x37: fbgt({{ cond = (Fa > 0); }});
- 0x33: fble({{ cond = (Fa <= 0); }});
- 0x32: fblt({{ cond = (Fa < 0); }});
- }
-
- // unconditional branches
- format UncondBranch {
- 0x30: br();
- 0x34: bsr(IsCall);
- }
-
- // indirect branches
- 0x1a: decode JMPFUNC {
- format Jump {
- 0: jmp();
- 1: jsr(IsCall);
- 2: ret(IsReturn);
- 3: jsr_coroutine(IsCall, IsReturn);
- }
- }
-
- // Square root and integer-to-FP moves
- 0x14: decode FP_SHORTFUNC {
- // Integer to FP register moves must have RB == 31
- 0x4: decode RB {
- 31: decode FP_FULLFUNC {
- format BasicOperateWithNopCheck {
- 0x004: itofs({{ Fc.uq = s_to_t(Ra.ul); }}, FloatCvtOp);
- 0x024: itoft({{ Fc.uq = Ra.uq; }}, FloatCvtOp);
- 0x014: FailUnimpl::itoff(); // VAX-format conversion
- }
- }
- }
-
- // Square root instructions must have FA == 31
- 0xb: decode FA {
- 31: decode FP_TYPEFUNC {
- format FloatingPointOperate {
-#if SS_COMPATIBLE_FP
- 0x0b: sqrts({{
- if (Fb < 0.0)
- fault = Arithmetic_Fault;
- Fc = sqrt(Fb);
- }}, FloatSqrtOp);
-#else
- 0x0b: sqrts({{
- if (Fb.sf < 0.0)
- fault = Arithmetic_Fault;
- Fc.sf = sqrt(Fb.sf);
- }}, FloatSqrtOp);
-#endif
- 0x2b: sqrtt({{
- if (Fb < 0.0)
- fault = Arithmetic_Fault;
- Fc = sqrt(Fb);
- }}, FloatSqrtOp);
- }
- }
- }
-
- // VAX-format sqrtf and sqrtg are not implemented
- 0xa: FailUnimpl::sqrtfg();
- }
-
- // IEEE floating point
- 0x16: decode FP_SHORTFUNC_TOP2 {
- // The top two bits of the short function code break this
- // space into four groups: binary ops, compares, reserved, and
- // conversions. See Table 4-12 of AHB. There are different
- // special cases in these different groups, so we decode on
- // these top two bits first just to select a decode strategy.
- // Most of these instructions may have various trapping and
- // rounding mode flags set; these are decoded in the
- // FloatingPointDecode template used by the
- // FloatingPointOperate format.
-
- // add/sub/mul/div: just decode on the short function code
- // and source type. All valid trapping and rounding modes apply.
- 0: decode FP_TRAPMODE {
- // check for valid trapping modes here
- 0,1,5,7: decode FP_TYPEFUNC {
- format FloatingPointOperate {
-#if SS_COMPATIBLE_FP
- 0x00: adds({{ Fc = Fa + Fb; }});
- 0x01: subs({{ Fc = Fa - Fb; }});
- 0x02: muls({{ Fc = Fa * Fb; }}, FloatMultOp);
- 0x03: divs({{ Fc = Fa / Fb; }}, FloatDivOp);
-#else
- 0x00: adds({{ Fc.sf = Fa.sf + Fb.sf; }});
- 0x01: subs({{ Fc.sf = Fa.sf - Fb.sf; }});
- 0x02: muls({{ Fc.sf = Fa.sf * Fb.sf; }}, FloatMultOp);
- 0x03: divs({{ Fc.sf = Fa.sf / Fb.sf; }}, FloatDivOp);
-#endif
-
- 0x20: addt({{ Fc = Fa + Fb; }});
- 0x21: subt({{ Fc = Fa - Fb; }});
- 0x22: mult({{ Fc = Fa * Fb; }}, FloatMultOp);
- 0x23: divt({{ Fc = Fa / Fb; }}, FloatDivOp);
- }
- }
- }
-
- // Floating-point compare instructions must have the default
- // rounding mode, and may use the default trapping mode or
- // /SU. Both trapping modes are treated the same by M5; the
- // only difference on the real hardware (as far a I can tell)
- // is that without /SU you'd get an imprecise trap if you
- // tried to compare a NaN with something else (instead of an
- // "unordered" result).
- 1: decode FP_FULLFUNC {
- format BasicOperateWithNopCheck {
- 0x0a5, 0x5a5: cmpteq({{ Fc = (Fa == Fb) ? 2.0 : 0.0; }},
- FloatCmpOp);
- 0x0a7, 0x5a7: cmptle({{ Fc = (Fa <= Fb) ? 2.0 : 0.0; }},
- FloatCmpOp);
- 0x0a6, 0x5a6: cmptlt({{ Fc = (Fa < Fb) ? 2.0 : 0.0; }},
- FloatCmpOp);
- 0x0a4, 0x5a4: cmptun({{ // unordered
- Fc = (!(Fa < Fb) && !(Fa == Fb) && !(Fa > Fb)) ? 2.0 : 0.0;
- }}, FloatCmpOp);
- }
- }
-
- // The FP-to-integer and integer-to-FP conversion insts
- // require that FA be 31.
- 3: decode FA {
- 31: decode FP_TYPEFUNC {
- format FloatingPointOperate {
- 0x2f: decode FP_ROUNDMODE {
- format FPFixedRounding {
- // "chopped" i.e. round toward zero
- 0: cvttq({{ Fc.sq = (int64_t)trunc(Fb); }},
- Chopped);
- // round to minus infinity
- 1: cvttq({{ Fc.sq = (int64_t)floor(Fb); }},
- MinusInfinity);
- }
- default: cvttq({{ Fc.sq = (int64_t)nearbyint(Fb); }});
- }
-
- // The cvtts opcode is overloaded to be cvtst if the trap
- // mode is 2 or 6 (which are not valid otherwise)
- 0x2c: decode FP_FULLFUNC {
- format BasicOperateWithNopCheck {
- // trap on denorm version "cvtst/s" is
- // simulated same as cvtst
- 0x2ac, 0x6ac: cvtst({{ Fc = Fb.sf; }});
- }
- default: cvtts({{ Fc.sf = Fb; }});
- }
-
- // The trapping mode for integer-to-FP conversions
- // must be /SUI or nothing; /U and /SU are not
- // allowed. The full set of rounding modes are
- // supported though.
- 0x3c: decode FP_TRAPMODE {
- 0,7: cvtqs({{ Fc.sf = Fb.sq; }});
- }
- 0x3e: decode FP_TRAPMODE {
- 0,7: cvtqt({{ Fc = Fb.sq; }});
- }
- }
- }
- }
- }
-
- // misc FP operate
- 0x17: decode FP_FULLFUNC {
- format BasicOperateWithNopCheck {
- 0x010: cvtlq({{
- Fc.sl = (Fb.uq<63:62> << 30) | Fb.uq<58:29>;
- }});
- 0x030: cvtql({{
- Fc.uq = (Fb.uq<31:30> << 62) | (Fb.uq<29:0> << 29);
- }});
-
- // We treat the precise & imprecise trapping versions of
- // cvtql identically.
- 0x130, 0x530: cvtqlv({{
- // To avoid overflow, all the upper 32 bits must match
- // the sign bit of the lower 32. We code this as
- // checking the upper 33 bits for all 0s or all 1s.
- uint64_t sign_bits = Fb.uq<63:31>;
- if (sign_bits != 0 && sign_bits != mask(33))
- fault = Integer_Overflow_Fault;
- Fc.uq = (Fb.uq<31:30> << 62) | (Fb.uq<29:0> << 29);
- }});
-
- 0x020: cpys({{ // copy sign
- Fc.uq = (Fa.uq<63:> << 63) | Fb.uq<62:0>;
- }});
- 0x021: cpysn({{ // copy sign negated
- Fc.uq = (~Fa.uq<63:> << 63) | Fb.uq<62:0>;
- }});
- 0x022: cpyse({{ // copy sign and exponent
- Fc.uq = (Fa.uq<63:52> << 52) | Fb.uq<51:0>;
- }});
-
- 0x02a: fcmoveq({{ Fc = (Fa == 0) ? Fb : Fc; }});
- 0x02b: fcmovne({{ Fc = (Fa != 0) ? Fb : Fc; }});
- 0x02c: fcmovlt({{ Fc = (Fa < 0) ? Fb : Fc; }});
- 0x02d: fcmovge({{ Fc = (Fa >= 0) ? Fb : Fc; }});
- 0x02e: fcmovle({{ Fc = (Fa <= 0) ? Fb : Fc; }});
- 0x02f: fcmovgt({{ Fc = (Fa > 0) ? Fb : Fc; }});
-
- 0x024: mt_fpcr({{ FPCR = Fa.uq; }});
- 0x025: mf_fpcr({{ Fa.uq = FPCR; }});
- }
- }
-
- // miscellaneous mem-format ops
- 0x18: decode MEMFUNC {
- format WarnUnimpl {
- 0x8000: fetch();
- 0xa000: fetch_m();
- 0xe800: ecb();
- }
-
- format MiscPrefetch {
- 0xf800: wh64({{ EA = Rb & ~ULL(63); }},
- {{ xc->writeHint(EA, 64, memAccessFlags); }},
- IsMemRef, IsDataPrefetch, IsStore, MemWriteOp,
- NO_FAULT);
- }
-
- format BasicOperate {
- 0xc000: rpcc({{
-#if FULL_SYSTEM
- /* Rb is a fake dependency so here is a fun way to get
- * the parser to understand that.
- */
- Ra = xc->readIpr(AlphaISA::IPR_CC, fault) + (Rb & 0);
-
-#else
- Ra = curTick;
-#endif
- }});
-
- // All of the barrier instructions below do nothing in
- // their execute() methods (hence the empty code blocks).
- // All of their functionality is hard-coded in the
- // pipeline based on the flags IsSerializing,
- // IsMemBarrier, and IsWriteBarrier. In the current
- // detailed CPU model, the execute() function only gets
- // called at fetch, so there's no way to generate pipeline
- // behavior at any other stage. Once we go to an
- // exec-in-exec CPU model we should be able to get rid of
- // these flags and implement this behavior via the
- // execute() methods.
-
- // trapb is just a barrier on integer traps, where excb is
- // a barrier on integer and FP traps. "EXCB is thus a
- // superset of TRAPB." (Alpha ARM, Sec 4.11.4) We treat
- // them the same though.
- 0x0000: trapb({{ }}, IsSerializing, No_OpClass);
- 0x0400: excb({{ }}, IsSerializing, No_OpClass);
- 0x4000: mb({{ }}, IsMemBarrier, MemReadOp);
- 0x4400: wmb({{ }}, IsWriteBarrier, MemWriteOp);
- }
-
-#if FULL_SYSTEM
- format BasicOperate {
- 0xe000: rc({{
- Ra = xc->readIntrFlag();
- xc->setIntrFlag(0);
- }}, IsNonSpeculative);
- 0xf000: rs({{
- Ra = xc->readIntrFlag();
- xc->setIntrFlag(1);
- }}, IsNonSpeculative);
- }
-#else
- format FailUnimpl {
- 0xe000: rc();
- 0xf000: rs();
- }
-#endif
- }
-
-#if FULL_SYSTEM
- 0x00: CallPal::call_pal({{
- if (!palValid ||
- (palPriv
- && xc->readIpr(AlphaISA::IPR_ICM, fault) != AlphaISA::mode_kernel)) {
- // invalid pal function code, or attempt to do privileged
- // PAL call in non-kernel mode
- fault = Unimplemented_Opcode_Fault;
- }
- else {
- // check to see if simulator wants to do something special
- // on this PAL call (including maybe suppress it)
- bool dopal = xc->simPalCheck(palFunc);
-
- if (dopal) {
- AlphaISA::swap_palshadow(&xc->xcBase()->regs, true);
- xc->setIpr(AlphaISA::IPR_EXC_ADDR, NPC);
- NPC = xc->readIpr(AlphaISA::IPR_PAL_BASE, fault) + palOffset;
- }
- }
- }}, IsNonSpeculative);
-#else
- 0x00: decode PALFUNC {
- format EmulatedCallPal {
- 0x00: halt ({{
- SimExit(curTick, "halt instruction encountered");
- }}, IsNonSpeculative);
- 0x83: callsys({{
- xc->syscall();
- }}, IsNonSpeculative);
- // Read uniq reg into ABI return value register (r0)
- 0x9e: rduniq({{ R0 = Runiq; }});
- // Write uniq reg with value from ABI arg register (r16)
- 0x9f: wruniq({{ Runiq = R16; }});
- }
- }
-#endif
-
-#if FULL_SYSTEM
- format HwLoadStore {
- 0x1b: decode HW_LDST_QUAD {
- 0: hw_ld({{ EA = (Rb + disp) & ~3; }}, {{ Ra = Mem.ul; }}, L);
- 1: hw_ld({{ EA = (Rb + disp) & ~7; }}, {{ Ra = Mem.uq; }}, Q);
- }
-
- 0x1f: decode HW_LDST_COND {
- 0: decode HW_LDST_QUAD {
- 0: hw_st({{ EA = (Rb + disp) & ~3; }},
- {{ Mem.ul = Ra<31:0>; }}, L);
- 1: hw_st({{ EA = (Rb + disp) & ~7; }},
- {{ Mem.uq = Ra.uq; }}, Q);
- }
-
- 1: FailUnimpl::hw_st_cond();
- }
- }
-
- format HwMoveIPR {
- 0x19: hw_mfpr({{
- // this instruction is only valid in PAL mode
- if (!xc->inPalMode()) {
- fault = Unimplemented_Opcode_Fault;
- }
- else {
- Ra = xc->readIpr(ipr_index, fault);
- }
- }});
- 0x1d: hw_mtpr({{
- // this instruction is only valid in PAL mode
- if (!xc->inPalMode()) {
- fault = Unimplemented_Opcode_Fault;
- }
- else {
- xc->setIpr(ipr_index, Ra);
- if (traceData) { traceData->setData(Ra); }
- }
- }});
- }
-
- format BasicOperate {
- 0x1e: hw_rei({{ xc->hwrei(); }}, IsSerializing);
-
- // M5 special opcodes use the reserved 0x01 opcode space
- 0x01: decode M5FUNC {
- 0x00: arm({{
- AlphaPseudo::arm(xc->xcBase());
- }}, IsNonSpeculative);
- 0x01: quiesce({{
- AlphaPseudo::quiesce(xc->xcBase());
- }}, IsNonSpeculative);
- 0x10: ivlb({{
- AlphaPseudo::ivlb(xc->xcBase());
- }}, No_OpClass, IsNonSpeculative);
- 0x11: ivle({{
- AlphaPseudo::ivle(xc->xcBase());
- }}, No_OpClass, IsNonSpeculative);
- 0x20: m5exit_old({{
- AlphaPseudo::m5exit_old(xc->xcBase());
- }}, No_OpClass, IsNonSpeculative);
- 0x21: m5exit({{
- AlphaPseudo::m5exit(xc->xcBase());
- }}, No_OpClass, IsNonSpeculative);
- 0x30: initparam({{ Ra = xc->xcBase()->cpu->system->init_param; }});
- 0x40: resetstats({{
- AlphaPseudo::resetstats(xc->xcBase());
- }}, IsNonSpeculative);
- 0x41: dumpstats({{
- AlphaPseudo::dumpstats(xc->xcBase());
- }}, IsNonSpeculative);
- 0x42: dumpresetstats({{
- AlphaPseudo::dumpresetstats(xc->xcBase());
- }}, IsNonSpeculative);
- 0x43: m5checkpoint({{
- AlphaPseudo::m5checkpoint(xc->xcBase());
- }}, IsNonSpeculative);
- 0x50: m5readfile({{
- AlphaPseudo::readfile(xc->xcBase());
- }}, IsNonSpeculative);
- 0x51: m5break({{
- AlphaPseudo::debugbreak(xc->xcBase());
- }}, IsNonSpeculative);
- 0x52: m5switchcpu({{
- AlphaPseudo::switchcpu(xc->xcBase());
- }}, IsNonSpeculative);
- 0x53: m5addsymbol({{
- AlphaPseudo::addsymbol(xc->xcBase());
- }}, IsNonSpeculative);
-
- }
- }
-#endif
-}
diff --git a/arch/alpha/isa_traits.hh b/arch/alpha/isa_traits.hh
index 2570d12f0..0cf31cb50 100644
--- a/arch/alpha/isa_traits.hh
+++ b/arch/alpha/isa_traits.hh
@@ -29,81 +29,131 @@
#ifndef __ARCH_ALPHA_ISA_TRAITS_HH__
#define __ARCH_ALPHA_ISA_TRAITS_HH__
-#include "arch/alpha/faults.hh"
+namespace LittleEndianGuest {}
+using namespace LittleEndianGuest;
+
+//#include "arch/alpha/faults.hh"
#include "base/misc.hh"
#include "config/full_system.hh"
#include "sim/host.hh"
+#include "sim/faults.hh"
+class ExecContext;
class FastCPU;
class FullCPU;
class Checkpoint;
#define TARGET_ALPHA
-template <class ISA> class StaticInst;
-template <class ISA> class StaticInstPtr;
+class StaticInst;
+class StaticInstPtr;
namespace EV5 {
int DTB_ASN_ASN(uint64_t reg);
int ITB_ASN_ASN(uint64_t reg);
}
-class AlphaISA
+#if !FULL_SYSTEM
+class SyscallReturn {
+ public:
+ template <class T>
+ SyscallReturn(T v, bool s)
+ {
+ retval = (uint64_t)v;
+ success = s;
+ }
+
+ template <class T>
+ SyscallReturn(T v)
+ {
+ success = (v >= 0);
+ retval = (uint64_t)v;
+ }
+
+ ~SyscallReturn() {}
+
+ SyscallReturn& operator=(const SyscallReturn& s) {
+ retval = s.retval;
+ success = s.success;
+ return *this;
+ }
+
+ bool successful() { return success; }
+ uint64_t value() { return retval; }
+
+
+ private:
+ uint64_t retval;
+ bool success;
+};
+
+#endif
+
+
+
+namespace AlphaISA
{
- public:
typedef uint32_t MachInst;
- typedef uint64_t Addr;
+ typedef uint64_t ExtMachInst;
typedef uint8_t RegIndex;
- enum {
- MemoryEnd = 0xffffffffffffffffULL,
-
- NumIntRegs = 32,
- NumFloatRegs = 32,
- NumMiscRegs = 32,
-
- MaxRegsOfAnyType = 32,
- // Static instruction parameters
- MaxInstSrcRegs = 3,
- MaxInstDestRegs = 2,
-
- // semantically meaningful register indices
- ZeroReg = 31, // architecturally meaningful
- // the rest of these depend on the ABI
- StackPointerReg = 30,
- GlobalPointerReg = 29,
- ProcedureValueReg = 27,
- ReturnAddressReg = 26,
- ReturnValueReg = 0,
- FramePointerReg = 15,
- ArgumentReg0 = 16,
- ArgumentReg1 = 17,
- ArgumentReg2 = 18,
- ArgumentReg3 = 19,
- ArgumentReg4 = 20,
- ArgumentReg5 = 21,
-
- LogVMPageSize = 13, // 8K bytes
- VMPageSize = (1 << LogVMPageSize),
-
- BranchPredAddrShiftAmt = 2, // instructions are 4-byte aligned
-
- WordBytes = 4,
- HalfwordBytes = 2,
- ByteBytes = 1,
- DepNA = 0,
- };
+ const int NumIntArchRegs = 32;
+ const int NumPALShadowRegs = 8;
+ const int NumFloatArchRegs = 32;
+ // @todo: Figure out what this number really should be.
+ const int NumMiscArchRegs = 32;
+
+ // Static instruction parameters
+ const int MaxInstSrcRegs = 3;
+ const int MaxInstDestRegs = 2;
+
+ // semantically meaningful register indices
+ const int ZeroReg = 31; // architecturally meaningful
+ // the rest of these depend on the ABI
+ const int StackPointerReg = 30;
+ const int GlobalPointerReg = 29;
+ const int ProcedureValueReg = 27;
+ const int ReturnAddressReg = 26;
+ const int ReturnValueReg = 0;
+ const int FramePointerReg = 15;
+ const int ArgumentReg0 = 16;
+ const int ArgumentReg1 = 17;
+ const int ArgumentReg2 = 18;
+ const int ArgumentReg3 = 19;
+ const int ArgumentReg4 = 20;
+ const int ArgumentReg5 = 21;
+ const int SyscallNumReg = ReturnValueReg;
+ const int SyscallPseudoReturnReg = ArgumentReg4;
+ const int SyscallSuccessReg = 19;
+
+
+
+ const int LogVMPageSize = 13; // 8K bytes
+ const int VMPageSize = (1 << LogVMPageSize);
+
+ const int BranchPredAddrShiftAmt = 2; // instructions are 4-byte aligned
+
+ const int WordBytes = 4;
+ const int HalfwordBytes = 2;
+ const int ByteBytes = 1;
+
+
+ const int NumIntRegs = NumIntArchRegs + NumPALShadowRegs;
+ const int NumFloatRegs = NumFloatArchRegs;
+ const int NumMiscRegs = NumMiscArchRegs;
// These enumerate all the registers for dependence tracking.
enum DependenceTags {
// 0..31 are the integer regs 0..31
// 32..63 are the FP regs 0..31, i.e. use (reg + FP_Base_DepTag)
- FP_Base_DepTag = 32,
- Ctrl_Base_DepTag = 64,
- Fpcr_DepTag = 64, // floating point control register
- Uniq_DepTag = 65,
- IPR_Base_DepTag = 66
+ FP_Base_DepTag = 40,
+ Ctrl_Base_DepTag = 72,
+ Fpcr_DepTag = 72, // floating point control register
+ Uniq_DepTag = 73,
+ Lock_Flag_DepTag = 74,
+ Lock_Addr_DepTag = 75,
+ IPR_Base_DepTag = 76
};
typedef uint64_t IntReg;
@@ -120,40 +170,68 @@ class AlphaISA
double d[NumFloatRegs]; // double-precision floating point view
} FloatRegFile;
+extern const Addr PageShift;
+extern const Addr PageBytes;
+extern const Addr PageMask;
+extern const Addr PageOffset;
+
+// redirected register map, really only used for the full system case.
+extern const int reg_redir[NumIntRegs];
+
+#if FULL_SYSTEM
+
+ typedef uint64_t InternalProcReg;
+
+#include "arch/alpha/isa_fullsys_traits.hh"
+
+#else
+ const int NumInternalProcRegs = 0;
+#endif
+
// control register file contents
typedef uint64_t MiscReg;
- typedef struct {
+ class MiscRegFile {
+ protected:
uint64_t fpcr; // floating point condition codes
uint64_t uniq; // process-unique register
bool lock_flag; // lock flag for LL/SC
Addr lock_addr; // lock address for LL/SC
- } MiscRegFile;
-static const Addr PageShift = 13;
-static const Addr PageBytes = ULL(1) << PageShift;
-static const Addr PageMask = ~(PageBytes - 1);
-static const Addr PageOffset = PageBytes - 1;
+ public:
+ MiscReg readReg(int misc_reg);
+
+ //These functions should be removed once the simplescalar cpu model
+ //has been replaced.
+ int getInstAsid();
+ int getDataAsid();
+
+ MiscReg readRegWithEffect(int misc_reg, Fault &fault, ExecContext *xc);
+
+ Fault setReg(int misc_reg, const MiscReg &val);
+
+ Fault setRegWithEffect(int misc_reg, const MiscReg &val,
+ ExecContext *xc);
+
+ void copyMiscRegs(ExecContext *xc);
#if FULL_SYSTEM
+ protected:
+ InternalProcReg ipr[NumInternalProcRegs]; // Internal processor regs
- typedef uint64_t InternalProcReg;
+ private:
+ MiscReg readIpr(int idx, Fault &fault, ExecContext *xc);
-#include "arch/alpha/isa_fullsys_traits.hh"
+ Fault setIpr(int idx, uint64_t val, ExecContext *xc);
-#else
- enum {
- NumInternalProcRegs = 0
- };
+ void copyIprs(ExecContext *xc);
#endif
-
- enum {
- TotalNumRegs =
- NumIntRegs + NumFloatRegs + NumMiscRegs + NumInternalProcRegs
+ friend class RegFile;
};
- enum {
- TotalDataRegs = NumIntRegs + NumFloatRegs
- };
+ const int TotalNumRegs = NumIntRegs + NumFloatRegs +
+ NumMiscRegs + NumInternalProcRegs;
+
+ const int TotalDataRegs = NumIntRegs + NumFloatRegs;
typedef union {
IntReg intreg;
@@ -167,23 +245,26 @@ static const Addr PageOffset = PageBytes - 1;
MiscRegFile miscRegs; // control register file
Addr pc; // program counter
Addr npc; // next-cycle program counter
+ Addr nnpc;
+
#if FULL_SYSTEM
- IntReg palregs[NumIntRegs]; // PAL shadow registers
- InternalProcReg ipr[NumInternalProcRegs]; // internal processor regs
int intrflag; // interrupt flag
- bool pal_shadow; // using pal_shadow registers
- inline int instAsid() { return EV5::ITB_ASN_ASN(ipr[IPR_ITB_ASN]); }
- inline int dataAsid() { return EV5::DTB_ASN_ASN(ipr[IPR_DTB_ASN]); }
+ inline int instAsid()
+ { return EV5::ITB_ASN_ASN(miscRegs.ipr[IPR_ITB_ASN]); }
+ inline int dataAsid()
+ { return EV5::DTB_ASN_ASN(miscRegs.ipr[IPR_DTB_ASN]); }
#endif // FULL_SYSTEM
void serialize(std::ostream &os);
void unserialize(Checkpoint *cp, const std::string &section);
};
- static StaticInstPtr<AlphaISA> decodeInst(MachInst);
+ static inline ExtMachInst makeExtMI(MachInst inst, const uint64_t &pc);
+
+ StaticInstPtr decodeInst(ExtMachInst);
// return a no-op instruction... used for instruction fetch faults
- static const MachInst NoopMachInst;
+ extern const ExtMachInst NoopMachInst;
enum annotes {
ANNOTE_NONE = 0,
@@ -238,10 +319,10 @@ static const Addr PageOffset = PageBytes - 1;
// Machine operations
- static void saveMachineReg(AnyReg &savereg, const RegFile &reg_file,
+ void saveMachineReg(AnyReg &savereg, const RegFile &reg_file,
int regnum);
- static void restoreMachineReg(RegFile &regs, const AnyReg &reg,
+ void restoreMachineReg(RegFile &regs, const AnyReg &reg,
int regnum);
#if 0
@@ -259,82 +340,41 @@ static const Addr PageOffset = PageBytes - 1;
* @param xc The execution context.
*/
template <class XC>
- static void zeroRegisters(XC *xc);
-};
-
-
-typedef AlphaISA TheISA;
-
-typedef TheISA::MachInst MachInst;
-typedef TheISA::Addr Addr;
-typedef TheISA::RegIndex RegIndex;
-typedef TheISA::IntReg IntReg;
-typedef TheISA::IntRegFile IntRegFile;
-typedef TheISA::FloatReg FloatReg;
-typedef TheISA::FloatRegFile FloatRegFile;
-typedef TheISA::MiscReg MiscReg;
-typedef TheISA::MiscRegFile MiscRegFile;
-typedef TheISA::AnyReg AnyReg;
-typedef TheISA::RegFile RegFile;
-
-const int NumIntRegs = TheISA::NumIntRegs;
-const int NumFloatRegs = TheISA::NumFloatRegs;
-const int NumMiscRegs = TheISA::NumMiscRegs;
-const int TotalNumRegs = TheISA::TotalNumRegs;
-const int VMPageSize = TheISA::VMPageSize;
-const int LogVMPageSize = TheISA::LogVMPageSize;
-const int ZeroReg = TheISA::ZeroReg;
-const int StackPointerReg = TheISA::StackPointerReg;
-const int GlobalPointerReg = TheISA::GlobalPointerReg;
-const int ReturnAddressReg = TheISA::ReturnAddressReg;
-const int ReturnValueReg = TheISA::ReturnValueReg;
-const int ArgumentReg0 = TheISA::ArgumentReg0;
-const int ArgumentReg1 = TheISA::ArgumentReg1;
-const int ArgumentReg2 = TheISA::ArgumentReg2;
-const int BranchPredAddrShiftAmt = TheISA::BranchPredAddrShiftAmt;
-const int MaxAddr = (Addr)-1;
-
-#if !FULL_SYSTEM
-class SyscallReturn {
- public:
- template <class T>
- SyscallReturn(T v, bool s)
- {
- retval = (uint64_t)v;
- success = s;
- }
-
- template <class T>
- SyscallReturn(T v)
- {
- success = (v >= 0);
- retval = (uint64_t)v;
- }
-
- ~SyscallReturn() {}
-
- SyscallReturn& operator=(const SyscallReturn& s) {
- retval = s.retval;
- success = s.success;
- return *this;
- }
-
- bool successful() { return success; }
- uint64_t value() { return retval; }
-
-
- private:
- uint64_t retval;
- bool success;
+ void zeroRegisters(XC *xc);
+
+ const Addr MaxAddr = (Addr)-1;
+
+ static inline void setSyscallReturn(SyscallReturn return_value, RegFile *regs)
+ {
+ // check for error condition. Alpha syscall convention is to
+ // indicate success/failure in reg a3 (r19) and put the
+ // return value itself in the standard return value reg (v0).
+ if (return_value.successful()) {
+ // no error
+ regs->intRegFile[SyscallSuccessReg] = 0;
+ regs->intRegFile[ReturnValueReg] = return_value.value();
+ } else {
+ // got an error, return details
+ regs->intRegFile[SyscallSuccessReg] = (IntReg) -1;
+ regs->intRegFile[ReturnValueReg] = -return_value.value();
+ }
+ }
};
+static inline AlphaISA::ExtMachInst
+AlphaISA::makeExtMI(AlphaISA::MachInst inst, const uint64_t &pc) {
+#if FULL_SYSTEM
+ AlphaISA::ExtMachInst ext_inst = inst;
+ if (pc && 0x1)
+ return ext_inst|=(static_cast<AlphaISA::ExtMachInst>(pc & 0x1) << 32);
+ else
+ return ext_inst;
+#else
+ return AlphaISA::ExtMachInst(inst);
#endif
-
+}
#if FULL_SYSTEM
-typedef TheISA::InternalProcReg InternalProcReg;
-const int NumInternalProcRegs = TheISA::NumInternalProcRegs;
-const int NumInterruptLevels = TheISA::NumInterruptLevels;
#include "arch/alpha/ev5.hh"
#endif
diff --git a/arch/alpha/linux/aligned.hh b/arch/alpha/linux/aligned.hh
new file mode 100644
index 000000000..cabecb283
--- /dev/null
+++ b/arch/alpha/linux/aligned.hh
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2004 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __ARCH_ALPHA_LINUX_ALIGNED_HH__
+#define __ARCH_ALPHA_LINUX_ALIGNED_HH__
+
+
+/* GCC 3.3.X has a bug in which attributes+typedefs don't work. 3.2.X is fine
+ * as in 3.4.X, but the bug is marked will not fix in 3.3.X so here is
+ * the work around.
+ */
+#if (__GNUC__ == 3 && __GNUC_MINOR__ != 3) || __GNUC__ > 3
+typedef uint64_t uint64_ta __attribute__ ((aligned (8))) ;
+typedef int64_t int64_ta __attribute__ ((aligned (8))) ;
+typedef Addr Addr_a __attribute__ ((aligned (8))) ;
+#else
+#define uint64_ta uint64_t __attribute__ ((aligned (8)))
+#define int64_ta int64_t __attribute__ ((aligned (8)))
+#define Addr_a Addr __attribute__ ((aligned (8)))
+#endif /* __GNUC__ __GNUC_MINOR__ */
+
+#endif /* __ARCH_ALPHA_LINUX_ALIGNED_HH__ */
diff --git a/arch/alpha/linux/hwrpb.hh b/arch/alpha/linux/hwrpb.hh
new file mode 100644
index 000000000..869ce026b
--- /dev/null
+++ b/arch/alpha/linux/hwrpb.hh
@@ -0,0 +1,42 @@
+/*
+ * Copyright 1990 Hewlett-Packard Development Company, L.P.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef __ARCH_ALPHA_LINUX_HWRPB_HH__
+#define __ARCH_ALPHA_LINUX_HWRPB_HH__
+
+#include "arch/alpha/linux/aligned.hh"
+
+namespace Linux {
+ struct pcb_struct {
+ uint64_ta rpb_ksp;
+ uint64_ta rpb_usp;
+ uint64_ta rpb_ptbr;
+ uint32_t rpb_cc;
+ uint32_t rpb_psn;
+ uint64_ta rpb_unique;
+ uint64_ta rpb_fen;
+ uint64_ta res1, res2;
+ };
+}
+#endif // __ARCH_ALPHA_LINUX_HWRPB_HH__
diff --git a/arch/alpha/alpha_linux_process.cc b/arch/alpha/linux/process.cc
index 16816e901..1c911bc50 100644
--- a/arch/alpha/alpha_linux_process.cc
+++ b/arch/alpha/linux/process.cc
@@ -26,457 +26,98 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include <dirent.h>
-#include <errno.h>
-#include <fcntl.h> // for host open() flags
-#include <string.h> // for memset()
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
+#include "arch/alpha/linux/process.hh"
+#include "arch/alpha/isa_traits.hh"
-#include "cpu/base.hh"
+#include "base/trace.hh"
#include "cpu/exec_context.hh"
-#include "mem/translating_port.hh"
-#include "sim/fake_syscall.hh"
-#include "sim/host.hh"
-#include "sim/process.hh"
-#include "sim/sim_events.hh"
+#include "kern/linux/linux.hh"
+#include "mem/functional/functional.hh"
-#include "arch/alpha/alpha_common_syscall_emul.hh"
+#include "sim/process.hh"
#include "sim/syscall_emul.hh"
-#include "sim/root.hh" // for curTick & ticksPerSecond
-
-#include "arch/alpha/alpha_linux_process.hh"
-
-#include "base/trace.hh"
using namespace std;
+using namespace AlphaISA;
-///
-/// This class encapsulates the types, structures, constants,
-/// functions, and syscall-number mappings specific to the Alpha Linux
-/// syscall interface.
-///
-class Linux {
-
- public:
-
- //@{
- /// Basic Linux types.
- typedef uint64_t size_t;
- typedef uint64_t off_t;
- typedef int64_t time_t;
- typedef uint32_t uid_t;
- typedef uint32_t gid_t;
- //@}
-
- //@{
- /// open(2) flag values.
- static const int TGT_O_RDONLY = 00000000; //!< O_RDONLY
- static const int TGT_O_WRONLY = 00000001; //!< O_WRONLY
- static const int TGT_O_RDWR = 00000002; //!< O_RDWR
- static const int TGT_O_NONBLOCK = 00000004; //!< O_NONBLOCK
- static const int TGT_O_APPEND = 00000010; //!< O_APPEND
- static const int TGT_O_CREAT = 00001000; //!< O_CREAT
- static const int TGT_O_TRUNC = 00002000; //!< O_TRUNC
- static const int TGT_O_EXCL = 00004000; //!< O_EXCL
- static const int TGT_O_NOCTTY = 00010000; //!< O_NOCTTY
- static const int TGT_O_SYNC = 00040000; //!< O_SYNC
- static const int TGT_O_DRD = 00100000; //!< O_DRD
- static const int TGT_O_DIRECTIO = 00200000; //!< O_DIRECTIO
- static const int TGT_O_CACHE = 00400000; //!< O_CACHE
- static const int TGT_O_DSYNC = 02000000; //!< O_DSYNC
- static const int TGT_O_RSYNC = 04000000; //!< O_RSYNC
- //@}
-
- /// This table maps the target open() flags to the corresponding
- /// host open() flags.
- static OpenFlagTransTable openFlagTable[];
-
- /// Number of entries in openFlagTable[].
- static const int NUM_OPEN_FLAGS;
-
- /// Stat buffer. Note that we can't call it 'stat' since that
- /// gets #defined to something else on some systems.
- struct tgt_stat {
- uint32_t st_dev; //!< device
- uint32_t st_ino; //!< inode
- uint32_t st_mode; //!< mode
- uint32_t st_nlink; //!< link count
- uint32_t st_uid; //!< owner's user ID
- uint32_t st_gid; //!< owner's group ID
- uint32_t st_rdev; //!< device number
- int32_t _pad1; //!< for alignment
- int64_t st_size; //!< file size in bytes
- uint64_t st_atimeX; //!< time of last access
- uint64_t st_mtimeX; //!< time of last modification
- uint64_t st_ctimeX; //!< time of last status change
- uint32_t st_blksize; //!< optimal I/O block size
- int32_t st_blocks; //!< number of blocks allocated
- uint32_t st_flags; //!< flags
- uint32_t st_gen; //!< unknown
- };
-
- // same for stat64
- struct tgt_stat64 {
- uint64_t st_dev;
- uint64_t st_ino;
- uint64_t st_rdev;
- int64_t st_size;
- uint64_t st_blocks;
-
- uint32_t st_mode;
- uint32_t st_uid;
- uint32_t st_gid;
- uint32_t st_blksize;
- uint32_t st_nlink;
- uint32_t __pad0;
-
- uint64_t tgt_st_atime;
- uint64_t st_atime_nsec;
- uint64_t tgt_st_mtime;
- uint64_t st_mtime_nsec;
- uint64_t tgt_st_ctime;
- uint64_t st_ctime_nsec;
- int64_t __unused[3];
- };
-
- /// Length of strings in struct utsname (plus 1 for null char).
- static const int _SYS_NMLN = 65;
-
- /// Interface struct for uname().
- struct utsname {
- char sysname[_SYS_NMLN]; //!< System name.
- char nodename[_SYS_NMLN]; //!< Node name.
- char release[_SYS_NMLN]; //!< OS release.
- char version[_SYS_NMLN]; //!< OS version.
- char machine[_SYS_NMLN]; //!< Machine type.
- };
-
-
- //@{
- /// ioctl() command codes.
- static const unsigned TIOCGETP = 0x40067408;
- static const unsigned TIOCSETP = 0x80067409;
- static const unsigned TIOCSETN = 0x8006740a;
- static const unsigned TIOCSETC = 0x80067411;
- static const unsigned TIOCGETC = 0x40067412;
- static const unsigned FIONREAD = 0x4004667f;
- static const unsigned TIOCISATTY = 0x2000745e;
- static const unsigned TIOCGETS = 0x402c7413;
- static const unsigned TIOCGETA = 0x40127417;
- //@}
-
- /// Resource enumeration for getrlimit().
- enum rlimit_resources {
- RLIMIT_CPU = 0,
- RLIMIT_FSIZE = 1,
- RLIMIT_DATA = 2,
- RLIMIT_STACK = 3,
- RLIMIT_CORE = 4,
- RLIMIT_RSS = 5,
- RLIMIT_NOFILE = 6,
- RLIMIT_AS = 7,
- RLIMIT_VMEM = 7,
- RLIMIT_NPROC = 8,
- RLIMIT_MEMLOCK = 9,
- RLIMIT_LOCKS = 10
- };
-
- /// Limit struct for getrlimit/setrlimit.
- struct rlimit {
- uint64_t rlim_cur; //!< soft limit
- uint64_t rlim_max; //!< hard limit
- };
-
-
- /// For mmap().
- static const unsigned TGT_MAP_ANONYMOUS = 0x10;
-
- /// For gettimeofday().
- struct timeval {
- int64_t tv_sec; //!< seconds
- int64_t tv_usec; //!< microseconds
- };
-
- // For writev/readv
- struct tgt_iovec {
- uint64_t iov_base; // void *
- uint64_t iov_len;
- };
-
- //@{
- /// For getrusage().
- static const int RUSAGE_SELF = 0;
- static const int RUSAGE_CHILDREN = -1;
- static const int RUSAGE_BOTH = -2;
- //@}
-
- /// For getrusage().
- struct rusage {
- struct timeval ru_utime; //!< user time used
- struct timeval ru_stime; //!< system time used
- int64_t ru_maxrss; //!< max rss
- int64_t ru_ixrss; //!< integral shared memory size
- int64_t ru_idrss; //!< integral unshared data "
- int64_t ru_isrss; //!< integral unshared stack "
- int64_t ru_minflt; //!< page reclaims - total vmfaults
- int64_t ru_majflt; //!< page faults
- int64_t ru_nswap; //!< swaps
- int64_t ru_inblock; //!< block input operations
- int64_t ru_oublock; //!< block output operations
- int64_t ru_msgsnd; //!< messages sent
- int64_t ru_msgrcv; //!< messages received
- int64_t ru_nsignals; //!< signals received
- int64_t ru_nvcsw; //!< voluntary context switches
- int64_t ru_nivcsw; //!< involuntary "
- };
-
- /// Helper function to convert a host stat buffer to a target stat
- /// buffer. Also copies the target buffer out to the simulated
- /// memory space. Used by stat(), fstat(), and lstat().
- static void
- copyOutStatBuf(TranslatingPort *memPort, Addr addr, struct stat *host)
- {
- TypedBufferArg<Linux::tgt_stat> tgt(addr);
-
- tgt->st_dev = host->st_dev;
- tgt->st_ino = host->st_ino;
- tgt->st_mode = host->st_mode;
- tgt->st_nlink = host->st_nlink;
- tgt->st_uid = host->st_uid;
- tgt->st_gid = host->st_gid;
- tgt->st_rdev = host->st_rdev;
- tgt->st_size = host->st_size;
- tgt->st_atimeX = host->st_atime;
- tgt->st_mtimeX = host->st_mtime;
- tgt->st_ctimeX = host->st_ctime;
- tgt->st_blksize = host->st_blksize;
- tgt->st_blocks = host->st_blocks;
-
- tgt.copyOut(memPort);
- }
-
- // Same for stat64
- static void
- copyOutStat64Buf(TranslatingPort *memPort, Addr addr, struct stat64 *host)
- {
- TypedBufferArg<Linux::tgt_stat64> tgt(addr);
-
- // XXX byteswaps
- tgt->st_dev = host->st_dev;
- // XXX What about STAT64_HAS_BROKEN_ST_INO ???
- tgt->st_ino = host->st_ino;
- tgt->st_rdev = host->st_rdev;
- tgt->st_size = host->st_size;
- tgt->st_blocks = host->st_blocks;
-
- tgt->st_mode = host->st_mode;
- tgt->st_uid = host->st_uid;
- tgt->st_gid = host->st_gid;
- tgt->st_blksize = host->st_blksize;
- tgt->st_nlink = host->st_nlink;
- tgt->tgt_st_atime = host->st_atime;
- tgt->tgt_st_mtime = host->st_mtime;
- tgt->tgt_st_ctime = host->st_ctime;
-#ifdef STAT_HAVE_NSEC
- tgt->st_atime_nsec = host->st_atime_nsec;
- tgt->st_mtime_nsec = host->st_mtime_nsec;
- tgt->st_ctime_nsec = host->st_ctime_nsec;
-#else
- tgt->st_atime_nsec = 0;
- tgt->st_mtime_nsec = 0;
- tgt->st_ctime_nsec = 0;
-#endif
- tgt.copyOut(memPort);
- }
-
- /// The target system's hostname.
- static const char *hostname;
-
- /// Target uname() handler.
- static SyscallReturn
- unameFunc(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
- {
- TypedBufferArg<Linux::utsname> name(xc->getSyscallArg(0));
-
- strcpy(name->sysname, "Linux");
- strcpy(name->nodename, hostname);
- strcpy(name->release, "2.4.20");
- strcpy(name->version, "#1 Mon Aug 18 11:32:15 EDT 2003");
- strcpy(name->machine, "alpha");
-
- name.copyOut(xc->port);
- return 0;
- }
-
- /// Target osf_getsysyinfo() handler. Even though this call is
- /// borrowed from Tru64, the subcases that get used appear to be
- /// different in practice from those used by Tru64 processes.
- static SyscallReturn
- osf_getsysinfoFunc(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
- {
- unsigned op = xc->getSyscallArg(0);
- // unsigned nbytes = xc->getSyscallArg(2);
- switch (op) {
- case 45: { // GSI_IEEE_FP_CONTROL
- TypedBufferArg<uint64_t> fpcr(xc->getSyscallArg(1));
- // I don't think this exactly matches the HW FPCR
- *fpcr = 0;
- fpcr.copyOut(xc->port);
- return 0;
- }
-
- default:
- cerr << "osf_getsysinfo: unknown op " << op << endl;
- abort();
- break;
- }
-
- return 1;
- }
-
- /// Target osf_setsysinfo() handler.
- static SyscallReturn
- osf_setsysinfoFunc(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
- {
- unsigned op = xc->getSyscallArg(0);
- // unsigned nbytes = xc->getSyscallArg(2);
-
- switch (op) {
-
- case 14: { // SSI_IEEE_FP_CONTROL
- TypedBufferArg<uint64_t> fpcr(xc->getSyscallArg(1));
- // I don't think this exactly matches the HW FPCR
- fpcr.copyIn(xc->port);
- DPRINTFR(SyscallVerbose, "osf_setsysinfo(SSI_IEEE_FP_CONTROL): "
- " setting FPCR to 0x%x\n", *(uint64_t*)fpcr);
- return 0;
- }
-
- default:
- cerr << "osf_setsysinfo: unknown op " << op << endl;
- abort();
- break;
- }
-
- return 1;
- }
-
- /// Target fnctl() handler.
- static SyscallReturn
- fcntlFunc(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
- {
- int fd = xc->getSyscallArg(0);
-
- if (fd < 0 || process->sim_fd(fd) < 0)
- return -EBADF;
-
- int cmd = xc->getSyscallArg(1);
- switch (cmd) {
- case 0: // F_DUPFD
- // if we really wanted to support this, we'd need to do it
- // in the target fd space.
- warn("fcntl(%d, F_DUPFD) not supported, error returned\n", fd);
- return -EMFILE;
-
- case 1: // F_GETFD (get close-on-exec flag)
- case 2: // F_SETFD (set close-on-exec flag)
- return 0;
+/// Target uname() handler.
+static SyscallReturn
+unameFunc(SyscallDesc *desc, int callnum, Process *process,
+ ExecContext *xc)
+{
+ TypedBufferArg<Linux::utsname> name(xc->getSyscallArg(0));
- case 3: // F_GETFL (get file flags)
- case 4: // F_SETFL (set file flags)
- // not sure if this is totally valid, but we'll pass it through
- // to the underlying OS
- warn("fcntl(%d, %d) passed through to host\n", fd, cmd);
- return fcntl(process->sim_fd(fd), cmd);
- // return 0;
+ strcpy(name->sysname, "Linux");
+ strcpy(name->nodename, "m5.eecs.umich.edu");
+ strcpy(name->release, "2.4.20");
+ strcpy(name->version, "#1 Mon Aug 18 11:32:15 EDT 2003");
+ strcpy(name->machine, "alpha");
- case 7: // F_GETLK (get lock)
- case 8: // F_SETLK (set lock)
- case 9: // F_SETLKW (set lock and wait)
- // don't mess with file locking... just act like it's OK
- warn("File lock call (fcntl(%d, %d)) ignored.\n", fd, cmd);
- return 0;
+ name.copyOut(xc->getMemPtr());
+ return 0;
+}
- default:
- warn("Unknown fcntl command %d\n", cmd);
- return 0;
- }
+/// Target osf_getsysyinfo() handler. Even though this call is
+/// borrowed from Tru64, the subcases that get used appear to be
+/// different in practice from those used by Tru64 processes.
+static SyscallReturn
+osf_getsysinfoFunc(SyscallDesc *desc, int callnum, Process *process,
+ ExecContext *xc)
+{
+ unsigned op = xc->getSyscallArg(0);
+ // unsigned nbytes = xc->getSyscallArg(2);
+
+ switch (op) {
+
+ case 45: { // GSI_IEEE_FP_CONTROL
+ TypedBufferArg<uint64_t> fpcr(xc->getSyscallArg(1));
+ // I don't think this exactly matches the HW FPCR
+ *fpcr = 0;
+ fpcr.copyOut(xc->getMemPtr());
+ return 0;
+ }
+
+ default:
+ cerr << "osf_getsysinfo: unknown op " << op << endl;
+ abort();
+ break;
}
- /// Array of syscall descriptors, indexed by call number.
- static SyscallDesc syscallDescs[];
-
- /// Number of syscalls in syscallDescs[].
- static const int Num_Syscall_Descs;
-
- /// Max supported syscall number.
- static const int Max_Syscall_Desc;
-
- /// Do the specified syscall. Just looks the call number up in
- /// the table and invokes the appropriate handler.
- static void
- doSyscall(int callnum, Process *process, ExecContext *xc)
- {
- if (callnum < 0 || callnum > Max_Syscall_Desc) {
- fatal("Syscall %d out of range", callnum);
- }
-
- SyscallDesc *desc = &syscallDescs[callnum];
+ return 1;
+}
- desc->doSyscall(callnum, process, xc);
+/// Target osf_setsysinfo() handler.
+static SyscallReturn
+osf_setsysinfoFunc(SyscallDesc *desc, int callnum, Process *process,
+ ExecContext *xc)
+{
+ unsigned op = xc->getSyscallArg(0);
+ // unsigned nbytes = xc->getSyscallArg(2);
+
+ switch (op) {
+
+ case 14: { // SSI_IEEE_FP_CONTROL
+ TypedBufferArg<uint64_t> fpcr(xc->getSyscallArg(1));
+ // I don't think this exactly matches the HW FPCR
+ fpcr.copyIn(xc->getMemPtr());
+ DPRINTFR(SyscallVerbose, "osf_setsysinfo(SSI_IEEE_FP_CONTROL): "
+ " setting FPCR to 0x%x\n", gtoh(*(uint64_t*)fpcr));
+ return 0;
+ }
+
+ default:
+ cerr << "osf_setsysinfo: unknown op " << op << endl;
+ abort();
+ break;
}
-}; // class Linux
-
-
-// open(2) flags translation table
-OpenFlagTransTable Linux::openFlagTable[] = {
-#ifdef _MSC_VER
- { Linux::TGT_O_RDONLY, _O_RDONLY },
- { Linux::TGT_O_WRONLY, _O_WRONLY },
- { Linux::TGT_O_RDWR, _O_RDWR },
- { Linux::TGT_O_APPEND, _O_APPEND },
- { Linux::TGT_O_CREAT, _O_CREAT },
- { Linux::TGT_O_TRUNC, _O_TRUNC },
- { Linux::TGT_O_EXCL, _O_EXCL },
-#ifdef _O_NONBLOCK
- { Linux::TGT_O_NONBLOCK, _O_NONBLOCK },
-#endif
-#ifdef _O_NOCTTY
- { Linux::TGT_O_NOCTTY, _O_NOCTTY },
-#endif
-#ifdef _O_SYNC
- { Linux::TGT_O_SYNC, _O_SYNC },
-#endif
-#else /* !_MSC_VER */
- { Linux::TGT_O_RDONLY, O_RDONLY },
- { Linux::TGT_O_WRONLY, O_WRONLY },
- { Linux::TGT_O_RDWR, O_RDWR },
- { Linux::TGT_O_APPEND, O_APPEND },
- { Linux::TGT_O_CREAT, O_CREAT },
- { Linux::TGT_O_TRUNC, O_TRUNC },
- { Linux::TGT_O_EXCL, O_EXCL },
- { Linux::TGT_O_NONBLOCK, O_NONBLOCK },
- { Linux::TGT_O_NOCTTY, O_NOCTTY },
-#ifdef O_SYNC
- { Linux::TGT_O_SYNC, O_SYNC },
-#endif
-#endif /* _MSC_VER */
-};
-const int Linux::NUM_OPEN_FLAGS =
- (sizeof(Linux::openFlagTable)/sizeof(Linux::openFlagTable[0]));
+ return 1;
+}
-const char *Linux::hostname = "m5.eecs.umich.edu";
-SyscallDesc Linux::syscallDescs[] = {
+SyscallDesc AlphaLinuxProcess::syscallDescs[] = {
/* 0 */ SyscallDesc("osf_syscall", unimplementedFunc),
/* 1 */ SyscallDesc("exit", exitFunc),
/* 2 */ SyscallDesc("fork", unimplementedFunc),
@@ -497,11 +138,11 @@ SyscallDesc Linux::syscallDescs[] = {
/* 17 */ SyscallDesc("brk", obreakFunc),
/* 18 */ SyscallDesc("osf_getfsstat", unimplementedFunc),
/* 19 */ SyscallDesc("lseek", lseekFunc),
- /* 20 */ SyscallDesc("getxpid", getpidFunc),
+ /* 20 */ SyscallDesc("getxpid", getpidPseudoFunc),
/* 21 */ SyscallDesc("osf_mount", unimplementedFunc),
/* 22 */ SyscallDesc("umount", unimplementedFunc),
/* 23 */ SyscallDesc("setuid", setuidFunc),
- /* 24 */ SyscallDesc("getxuid", getuidFunc),
+ /* 24 */ SyscallDesc("getxuid", getuidPseudoFunc),
/* 25 */ SyscallDesc("exec_with_loader", unimplementedFunc),
/* 26 */ SyscallDesc("osf_ptrace", unimplementedFunc),
/* 27 */ SyscallDesc("osf_nrecvmsg", unimplementedFunc),
@@ -519,12 +160,12 @@ SyscallDesc Linux::syscallDescs[] = {
/* 39 */ SyscallDesc("setpgid", unimplementedFunc),
/* 40 */ SyscallDesc("osf_old_lstat", unimplementedFunc),
/* 41 */ SyscallDesc("dup", unimplementedFunc),
- /* 42 */ SyscallDesc("pipe", unimplementedFunc),
+ /* 42 */ SyscallDesc("pipe", pipePseudoFunc),
/* 43 */ SyscallDesc("osf_set_program_attributes", unimplementedFunc),
/* 44 */ SyscallDesc("osf_profil", unimplementedFunc),
/* 45 */ SyscallDesc("open", openFunc<Linux>),
/* 46 */ SyscallDesc("osf_old_sigaction", unimplementedFunc),
- /* 47 */ SyscallDesc("getxgid", getgidFunc),
+ /* 47 */ SyscallDesc("getxgid", getgidPseudoFunc),
/* 48 */ SyscallDesc("osf_sigprocmask", ignoreFunc),
/* 49 */ SyscallDesc("osf_getlogin", unimplementedFunc),
/* 50 */ SyscallDesc("osf_setlogin", unimplementedFunc),
@@ -924,32 +565,25 @@ SyscallDesc Linux::syscallDescs[] = {
/* 441 */ SyscallDesc("keyctl", unimplementedFunc)
};
-const int Linux::Num_Syscall_Descs =
- sizeof(Linux::syscallDescs) / sizeof(SyscallDesc);
-
-const int Linux::Max_Syscall_Desc = Linux::Num_Syscall_Descs - 1;
-
-
-void
-AlphaLinuxProcess::syscall(ExecContext *xc)
-{
- num_syscalls++;
-
- int64_t callnum = xc->regs.intRegFile[ReturnValueReg];
-
- Linux::doSyscall(callnum, this, xc);
-}
-
-
AlphaLinuxProcess::AlphaLinuxProcess(const std::string &name,
ObjectFile *objFile,
- System *system,
int stdin_fd,
int stdout_fd,
int stderr_fd,
std::vector<std::string> &argv,
std::vector<std::string> &envp)
- : LiveProcess(name, objFile, system, stdin_fd, stdout_fd, stderr_fd,
- argv, envp)
+ : LiveProcess(name, objFile, stdin_fd, stdout_fd, stderr_fd, argv, envp),
+ Num_Syscall_Descs(sizeof(syscallDescs) / sizeof(SyscallDesc))
+{
+ init_regs->intRegFile[0] = 0;
+}
+
+
+
+SyscallDesc*
+AlphaLinuxProcess::getDesc(int callnum)
{
+ if (callnum < 0 || callnum > Num_Syscall_Descs)
+ return NULL;
+ return &syscallDescs[callnum];
}
diff --git a/arch/alpha/alpha_linux_process.hh b/arch/alpha/linux/process.hh
index 6a4f31e5b..2cabc3f76 100644
--- a/arch/alpha/alpha_linux_process.hh
+++ b/arch/alpha/linux/process.hh
@@ -44,8 +44,15 @@ class AlphaLinuxProcess : public LiveProcess
std::vector<std::string> &argv,
std::vector<std::string> &envp);
- /// Syscall emulation function.
- virtual void syscall(ExecContext *xc);
+ virtual SyscallDesc* getDesc(int callnum);
+
+ /// The target system's hostname.
+ static const char *hostname;
+
+ /// Array of syscall descriptors, indexed by call number.
+ static SyscallDesc syscallDescs[];
+
+ const int Num_Syscall_Descs;
};
diff --git a/arch/alpha/linux/system.cc b/arch/alpha/linux/system.cc
new file mode 100644
index 000000000..f9275d15e
--- /dev/null
+++ b/arch/alpha/linux/system.cc
@@ -0,0 +1,289 @@
+/*
+ * Copyright (c) 2004-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @file
+ * This code loads the linux kernel, console, pal and patches certain
+ * functions. The symbol tables are loaded so that traces can show
+ * the executing function and we can skip functions. Various delay
+ * loops are skipped and their final values manually computed to speed
+ * up boot time.
+ */
+
+#include "arch/arguments.hh"
+#include "arch/vtophys.hh"
+#include "arch/alpha/linux/system.hh"
+#include "arch/alpha/linux/threadinfo.hh"
+#include "arch/alpha/system.hh"
+#include "base/loader/symtab.hh"
+#include "cpu/exec_context.hh"
+#include "cpu/base.hh"
+#include "dev/platform.hh"
+#include "kern/linux/printk.hh"
+#include "kern/linux/events.hh"
+#include "mem/functional/memory_control.hh"
+#include "mem/functional/physical.hh"
+#include "sim/builder.hh"
+#include "sim/byteswap.hh"
+
+using namespace std;
+using namespace AlphaISA;
+using namespace Linux;
+
+LinuxAlphaSystem::LinuxAlphaSystem(Params *p)
+ : AlphaSystem(p)
+{
+ Addr addr = 0;
+ Addr paddr = 0;
+
+ /**
+ * The symbol swapper_pg_dir marks the beginning of the kernel and
+ * the location of bootloader passed arguments
+ */
+ if (!kernelSymtab->findAddress("swapper_pg_dir", KernelStart)) {
+ panic("Could not determine start location of kernel");
+ }
+
+ /**
+ * Since we aren't using a bootloader, we have to copy the
+ * kernel arguments directly into the kernel's memory.
+ */
+ paddr = vtophys(physmem, CommandLine());
+ char *commandline = (char *)physmem->dma_addr(paddr, sizeof(uint64_t));
+ if (commandline)
+ strncpy(commandline, params()->boot_osflags.c_str(), CommandLineSize);
+
+ /**
+ * find the address of the est_cycle_freq variable and insert it
+ * so we don't through the lengthly process of trying to
+ * calculated it by using the PIT, RTC, etc.
+ */
+ if (kernelSymtab->findAddress("est_cycle_freq", addr)) {
+ paddr = vtophys(physmem, addr);
+ uint8_t *est_cycle_frequency =
+ physmem->dma_addr(paddr, sizeof(uint64_t));
+
+ if (est_cycle_frequency)
+ *(uint64_t *)est_cycle_frequency =
+ Clock::Frequency / p->boot_cpu_frequency;
+ }
+
+
+ /**
+ * EV5 only supports 127 ASNs so we are going to tell the kernel that the
+ * paritiuclar EV6 we have only supports 127 asns.
+ * @todo At some point we should change ev5.hh and the palcode to support
+ * 255 ASNs.
+ */
+ if (kernelSymtab->findAddress("dp264_mv", addr)) {
+ paddr = vtophys(physmem, addr);
+ char *dp264_mv = (char *)physmem->dma_addr(paddr, sizeof(uint64_t));
+
+ if (dp264_mv) {
+ *(uint32_t*)(dp264_mv+0x18) = LittleEndianGuest::htog((uint32_t)127);
+ } else
+ panic("could not translate dp264_mv addr\n");
+
+ } else
+ panic("could not find dp264_mv\n");
+
+#ifndef NDEBUG
+ kernelPanicEvent = addKernelFuncEvent<BreakPCEvent>("panic");
+ if (!kernelPanicEvent)
+ panic("could not find kernel symbol \'panic\'");
+
+#if 0
+ kernelDieEvent = addKernelFuncEvent<BreakPCEvent>("die_if_kernel");
+ if (!kernelDieEvent)
+ panic("could not find kernel symbol \'die_if_kernel\'");
+#endif
+
+#endif
+
+ /**
+ * Any time ide_delay_50ms, calibarte_delay or
+ * determine_cpu_caches is called just skip the
+ * function. Currently determine_cpu_caches only is used put
+ * information in proc, however if that changes in the future we
+ * will have to fill in the cache size variables appropriately.
+ */
+
+ skipIdeDelay50msEvent =
+ addKernelFuncEvent<SkipFuncEvent>("ide_delay_50ms");
+ skipDelayLoopEvent =
+ addKernelFuncEvent<SkipDelayLoopEvent>("calibrate_delay");
+ skipCacheProbeEvent =
+ addKernelFuncEvent<SkipFuncEvent>("determine_cpu_caches");
+ debugPrintkEvent = addKernelFuncEvent<DebugPrintkEvent>("dprintk");
+ idleStartEvent = addKernelFuncEvent<IdleStartEvent>("cpu_idle");
+
+ if (kernelSymtab->findAddress("alpha_switch_to", addr) && DTRACE(Thread)) {
+ printThreadEvent = new PrintThreadInfo(&pcEventQueue, "threadinfo",
+ addr + sizeof(MachInst) * 6);
+ } else {
+ printThreadEvent = NULL;
+ }
+
+ if (params()->bin_int) {
+ intStartEvent = addPalFuncEvent<InterruptStartEvent>("sys_int_21");
+ if (!intStartEvent)
+ panic("could not find symbol: sys_int_21\n");
+
+ intEndEvent = addPalFuncEvent<InterruptEndEvent>("rti_to_kern");
+ if (!intEndEvent)
+ panic("could not find symbol: rti_to_kern\n");
+
+ intEndEvent2 = addPalFuncEvent<InterruptEndEvent>("rti_to_user");
+ if (!intEndEvent2)
+ panic("could not find symbol: rti_to_user\n");
+
+ intEndEvent3 = addKernelFuncEvent<InterruptEndEvent>("do_softirq");
+ if (!intEndEvent3)
+ panic("could not find symbol: do_softirq\n");
+ }
+}
+
+LinuxAlphaSystem::~LinuxAlphaSystem()
+{
+#ifndef NDEBUG
+ delete kernelPanicEvent;
+#endif
+ delete skipIdeDelay50msEvent;
+ delete skipDelayLoopEvent;
+ delete skipCacheProbeEvent;
+ delete debugPrintkEvent;
+ delete idleStartEvent;
+ delete printThreadEvent;
+ delete intStartEvent;
+ delete intEndEvent;
+ delete intEndEvent2;
+}
+
+
+void
+LinuxAlphaSystem::setDelayLoop(ExecContext *xc)
+{
+ Addr addr = 0;
+ if (kernelSymtab->findAddress("loops_per_jiffy", addr)) {
+ Addr paddr = vtophys(physmem, addr);
+
+ uint8_t *loops_per_jiffy =
+ physmem->dma_addr(paddr, sizeof(uint32_t));
+
+ Tick cpuFreq = xc->getCpuPtr()->frequency();
+ Tick intrFreq = platform->intrFrequency();
+ *(uint32_t *)loops_per_jiffy =
+ (uint32_t)((cpuFreq / intrFreq) * 0.9988);
+ }
+}
+
+
+void
+LinuxAlphaSystem::SkipDelayLoopEvent::process(ExecContext *xc)
+{
+ SkipFuncEvent::process(xc);
+ // calculate and set loops_per_jiffy
+ ((LinuxAlphaSystem *)xc->getSystemPtr())->setDelayLoop(xc);
+}
+
+void
+LinuxAlphaSystem::PrintThreadInfo::process(ExecContext *xc)
+{
+ Linux::ThreadInfo ti(xc);
+
+ DPRINTF(Thread, "Currently Executing Thread %s, pid %d, started at: %d\n",
+ ti.curTaskName(), ti.curTaskPID(), ti.curTaskStart());
+}
+
+
+BEGIN_DECLARE_SIM_OBJECT_PARAMS(LinuxAlphaSystem)
+
+ Param<Tick> boot_cpu_frequency;
+ SimObjectParam<MemoryController *> memctrl;
+ SimObjectParam<PhysicalMemory *> physmem;
+
+ Param<string> kernel;
+ Param<string> console;
+ Param<string> pal;
+
+ Param<string> boot_osflags;
+ Param<string> readfile;
+ Param<unsigned int> init_param;
+
+ Param<uint64_t> system_type;
+ Param<uint64_t> system_rev;
+
+ Param<bool> bin;
+ VectorParam<string> binned_fns;
+ Param<bool> bin_int;
+
+END_DECLARE_SIM_OBJECT_PARAMS(LinuxAlphaSystem)
+
+BEGIN_INIT_SIM_OBJECT_PARAMS(LinuxAlphaSystem)
+
+ INIT_PARAM(boot_cpu_frequency, "Frequency of the boot CPU"),
+ INIT_PARAM(memctrl, "memory controller"),
+ INIT_PARAM(physmem, "phsyical memory"),
+ INIT_PARAM(kernel, "file that contains the kernel code"),
+ INIT_PARAM(console, "file that contains the console code"),
+ INIT_PARAM(pal, "file that contains palcode"),
+ INIT_PARAM_DFLT(boot_osflags, "flags to pass to the kernel during boot",
+ "a"),
+ INIT_PARAM_DFLT(readfile, "file to read startup script from", ""),
+ INIT_PARAM_DFLT(init_param, "numerical value to pass into simulator", 0),
+ INIT_PARAM_DFLT(system_type, "Type of system we are emulating", 34),
+ INIT_PARAM_DFLT(system_rev, "Revision of system we are emulating", 1<<10),
+ INIT_PARAM_DFLT(bin, "is this system to be binned", false),
+ INIT_PARAM(binned_fns, "functions to be broken down and binned"),
+ INIT_PARAM_DFLT(bin_int, "is interrupt code binned seperately?", true)
+
+END_INIT_SIM_OBJECT_PARAMS(LinuxAlphaSystem)
+
+CREATE_SIM_OBJECT(LinuxAlphaSystem)
+{
+ AlphaSystem::Params *p = new AlphaSystem::Params;
+ p->name = getInstanceName();
+ p->boot_cpu_frequency = boot_cpu_frequency;
+ p->memctrl = memctrl;
+ p->physmem = physmem;
+ p->kernel_path = kernel;
+ p->console_path = console;
+ p->palcode = pal;
+ p->boot_osflags = boot_osflags;
+ p->init_param = init_param;
+ p->readfile = readfile;
+ p->system_type = system_type;
+ p->system_rev = system_rev;
+ p->bin = bin;
+ p->binned_fns = binned_fns;
+ p->bin_int = bin_int;
+ return new LinuxAlphaSystem(p);
+}
+
+REGISTER_SIM_OBJECT("LinuxAlphaSystem", LinuxAlphaSystem)
+
diff --git a/arch/alpha/linux/system.hh b/arch/alpha/linux/system.hh
new file mode 100644
index 000000000..035e2a427
--- /dev/null
+++ b/arch/alpha/linux/system.hh
@@ -0,0 +1,146 @@
+/*
+ * Copyright (c) 2004-2006 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __ARCH_ALPHA_LINUX_SYSTEM_HH__
+#define __ARCH_ALPHA_LINUX_SYSTEM_HH__
+
+class ExecContext;
+
+class BreakPCEvent;
+class IdleStartEvent;
+
+#include "arch/alpha/system.hh"
+#include "kern/linux/events.hh"
+
+using namespace AlphaISA;
+using namespace Linux;
+using namespace std;
+
+/**
+ * This class contains linux specific system code (Loading, Events, Binning).
+ * It points to objects that are the system binaries to load and patches them
+ * appropriately to work in simulator.
+ */
+class LinuxAlphaSystem : public AlphaSystem
+{
+ private:
+ class SkipDelayLoopEvent : public SkipFuncEvent
+ {
+ public:
+ SkipDelayLoopEvent(PCEventQueue *q, const std::string &desc, Addr addr)
+ : SkipFuncEvent(q, desc, addr) {}
+ virtual void process(ExecContext *xc);
+ };
+
+ class PrintThreadInfo : public PCEvent
+ {
+ public:
+ PrintThreadInfo(PCEventQueue *q, const std::string &desc, Addr addr)
+ : PCEvent(q, desc, addr) {}
+ virtual void process(ExecContext *xc);
+ };
+
+
+ /**
+ * Addresses defining where the kernel bootloader places various
+ * elements. Details found in include/asm-alpha/system.h
+ */
+ Addr KernelStart; // Lookup the symbol swapper_pg_dir
+
+ public:
+ Addr InitStack() const { return KernelStart + 0x02000; }
+ Addr EmptyPGT() const { return KernelStart + 0x04000; }
+ Addr EmptyPGE() const { return KernelStart + 0x08000; }
+ Addr ZeroPGE() const { return KernelStart + 0x0A000; }
+ Addr StartAddr() const { return KernelStart + 0x10000; }
+
+ Addr Param() const { return ZeroPGE() + 0x0; }
+ Addr CommandLine() const { return Param() + 0x0; }
+ Addr InitrdStart() const { return Param() + 0x100; }
+ Addr InitrdSize() const { return Param() + 0x108; }
+ static const int CommandLineSize = 256;
+
+ private:
+#ifndef NDEBUG
+ /** Event to halt the simulator if the kernel calls panic() */
+ BreakPCEvent *kernelPanicEvent;
+
+ /** Event to halt the simulator if the kernel calls die_if_kernel */
+ BreakPCEvent *kernelDieEvent;
+#endif
+
+ /**
+ * Event to skip determine_cpu_caches() because we don't support
+ * the IPRs that the code can access to figure out cache sizes
+ */
+ SkipFuncEvent *skipCacheProbeEvent;
+
+ /** PC based event to skip the ide_delay_50ms() call */
+ SkipFuncEvent *skipIdeDelay50msEvent;
+
+ /**
+ * PC based event to skip the dprink() call and emulate its
+ * functionality
+ */
+ DebugPrintkEvent *debugPrintkEvent;
+
+ /**
+ * Skip calculate_delay_loop() rather than waiting for this to be
+ * calculated
+ */
+ SkipDelayLoopEvent *skipDelayLoopEvent;
+
+ /**
+ * Event to print information about thread switches if the trace flag
+ * Thread is set
+ */
+ PrintThreadInfo *printThreadEvent;
+
+ /**
+ * Event to bin Interrupts seperately from kernel code
+ */
+ InterruptStartEvent *intStartEvent;
+
+ /**
+ * Event to bin Interrupts seperately from kernel code
+ */
+ InterruptEndEvent *intEndEvent;
+ InterruptEndEvent *intEndEvent2;
+ InterruptEndEvent *intEndEvent3;
+
+ /** Grab the PCBB of the idle process when it starts */
+ IdleStartEvent *idleStartEvent;
+
+ public:
+ LinuxAlphaSystem(Params *p);
+ ~LinuxAlphaSystem();
+
+ void setDelayLoop(ExecContext *xc);
+};
+
+#endif // __ARCH_ALPHA_LINUX_SYSTEM_HH__
diff --git a/arch/alpha/linux/thread_info.hh b/arch/alpha/linux/thread_info.hh
new file mode 100644
index 000000000..88791b00d
--- /dev/null
+++ b/arch/alpha/linux/thread_info.hh
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __ARCH_ALPHA_LINUX_THREAD_INFO_H__
+#define __ARCH_ALPHA_LINUX_THREAD_INFO_H__
+
+#include "arch/alpha/linux/hwrpb.hh"
+
+namespace Linux {
+ struct thread_info {
+ struct pcb_struct pcb;
+ Addr_a task;
+ };
+}
+
+#endif // __ARCH_ALPHA_LINUX_THREAD_INFO_H__
diff --git a/arch/alpha/vptr.hh b/arch/alpha/linux/threadinfo.hh
index d1bda4061..8f03c9314 100644
--- a/arch/alpha/vptr.hh
+++ b/arch/alpha/linux/threadinfo.hh
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004-2005 The Regents of The University of Michigan
+ * Copyright (c) 2004 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -26,89 +26,64 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef __ARCH_ALPHA_VPTR_HH__
-#define __ARCH_ALPHA_VPTR_HH__
+#ifndef __ARCH_ALPHA_LINUX_LINUX_TREADNIFO_HH__
+#define __ARCH_ALPHA_LINUX_LINUX_TREADNIFO_HH__
-#include "arch/alpha/vtophys.hh"
+#include "arch/alpha/linux/thread_info.hh"
+#include "cpu/exec_context.hh"
+#include "kern/linux/sched.hh"
+#include "sim/vptr.hh"
-class ExecContext;
+namespace Linux {
-template <class T>
-class VPtr
+class ThreadInfo
{
- public:
- typedef T Type;
-
private:
ExecContext *xc;
- Addr ptr;
public:
- ExecContext *GetXC() const { return xc; }
- Addr GetPointer() const { return ptr; }
-
- public:
- explicit VPtr(ExecContext *_xc, Addr p = 0) : xc(_xc), ptr(p) { }
- template <class U>
- VPtr(const VPtr<U> &vp) : xc(vp.GetXC()), ptr(vp.GetPointer()) {}
- ~VPtr() {}
-
- bool operator!() const
- {
- return ptr == 0;
- }
-
- VPtr<T> operator+(int offset)
- {
- VPtr<T> ptr(*this);
- ptr += offset;
+ ThreadInfo(ExecContext *exec) : xc(exec) {}
+ ~ThreadInfo() {}
- return ptr;
- }
-
- const VPtr<T> &operator+=(int offset)
+ inline VPtr<thread_info>
+ curThreadInfo()
{
- ptr += offset;
- assert((ptr & (AlphaISA::PageBytes - 1)) + sizeof(T)
- < AlphaISA::PageBytes);
-
- return *this;
+ Addr current;
+
+ /* Each kernel stack is only 2 pages, the start of which is the
+ * thread_info struct. So we can get the address by masking off
+ * the lower 14 bits.
+ */
+ current = xc->readIntReg(TheISA::StackPointerReg) & ~0x3fff;
+ return VPtr<thread_info>(xc, current);
}
- const VPtr<T> &operator=(Addr p)
+ inline VPtr<task_struct>
+ curTaskInfo()
{
- assert((p & (AlphaISA::PageBytes)) + sizeof(T) < AlphaISA::PageBytes);
- ptr = p;
-
- return *this;
+ Addr task = curThreadInfo()->task;
+ return VPtr<task_struct>(xc, task);
}
- template <class U>
- const VPtr<T> &operator=(const VPtr<U> &vp)
+ std::string
+ curTaskName()
{
- xc = vp.GetXC();
- ptr = vp.GetPointer();
-
- return *this;
+ return curTaskInfo()->name;
}
- operator T *()
+ int32_t
+ curTaskPID()
{
- void *addr = vtomem(xc, ptr, sizeof(T));
- return (T *)addr;
+ return curTaskInfo()->pid;
}
- T *operator->()
+ uint64_t
+ curTaskStart()
{
- void *addr = vtomem(xc, ptr, sizeof(T));
- return (T *)addr;
- }
-
- T &operator*()
- {
- void *addr = vtomem(xc, ptr, sizeof(T));
- return *(T *)addr;
+ return curTaskInfo()->start;
}
};
-#endif // __ARCH_ALPHA_VPTR_HH__
+/* namespace Linux */ }
+
+#endif // __ARCH_ALPHA_LINUX_LINUX_THREADINFO_HH__
diff --git a/arch/alpha/process.cc b/arch/alpha/process.cc
new file mode 100644
index 000000000..b2dbe7ad1
--- /dev/null
+++ b/arch/alpha/process.cc
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2003-2004 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "arch/alpha/process.hh"
+
+namespace AlphaISA
+{
+
+LiveProcess *
+createProcess(const std::string &nm, ObjectFile * objFile,
+ int stdin_fd, int stdout_fd, int stderr_fd,
+ std::vector<std::string> &argv, std::vector<std::string> &envp)
+{
+ LiveProcess * process = NULL;
+ if (objFile->getArch() != ObjectFile::Alpha)
+ fatal("Object file does not match architecture.");
+ switch (objFile->getOpSys()) {
+ case ObjectFile::Tru64:
+ process = new AlphaTru64Process(nm, objFile,
+ stdin_fd, stdout_fd, stderr_fd,
+ argv, envp);
+ break;
+
+ case ObjectFile::Linux:
+ process = new AlphaLinuxProcess(nm, objFile,
+ stdin_fd, stdout_fd, stderr_fd,
+ argv, envp);
+ break;
+
+ default:
+ fatal("Unknown/unsupported operating system.");
+ }
+ return process;
+}
+
+} // namespace AlphaISA
diff --git a/arch/alpha/process.hh b/arch/alpha/process.hh
new file mode 100644
index 000000000..4a2a4212e
--- /dev/null
+++ b/arch/alpha/process.hh
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2003-2004 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __ALPHA_PROCESS_HH__
+#define __ALPHA_PROCESS_HH__
+
+#include <string>
+
+#include "arch/alpha/linux/process.hh"
+#include "arch/alpha/tru64/process.hh"
+#include "base/loader/object_file.hh"
+
+namespace AlphaISA
+{
+
+LiveProcess *
+createProcess(const std::string &nm, ObjectFile * objFile,
+ int stdin_fd, int stdout_fd, int stderr_fd,
+ std::vector<std::string> &argv, std::vector<std::string> &envp);
+
+} // namespace AlphaISA
+
+#endif // __ALPHA_PROCESS_HH__
diff --git a/arch/alpha/pseudo_inst.cc b/arch/alpha/pseudo_inst.cc
deleted file mode 100644
index e105b3cc8..000000000
--- a/arch/alpha/pseudo_inst.cc
+++ /dev/null
@@ -1,256 +0,0 @@
-/*
- * Copyright (c) 2003-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <errno.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <cstdio>
-
-#include <string>
-
-#include "arch/alpha/pseudo_inst.hh"
-#include "arch/alpha/vtophys.hh"
-#include "cpu/base.hh"
-#include "cpu/sampler/sampler.hh"
-#include "cpu/exec_context.hh"
-#include "kern/kernel_stats.hh"
-#include "sim/param.hh"
-#include "sim/serialize.hh"
-#include "sim/sim_exit.hh"
-#include "sim/stat_control.hh"
-#include "sim/stats.hh"
-#include "sim/system.hh"
-#include "sim/debug.hh"
-#include "targetarch/vptr.hh"
-
-using namespace std;
-
-extern Sampler *SampCPU;
-
-using namespace Stats;
-
-namespace AlphaPseudo
-{
- bool doStatisticsInsts;
- bool doCheckpointInsts;
- bool doQuiesce;
-
- void
- arm(ExecContext *xc)
- {
- xc->kernelStats->arm();
- }
-
- void
- quiesce(ExecContext *xc)
- {
- if (!doQuiesce)
- return;
-
- xc->suspend();
- xc->kernelStats->quiesce();
- }
-
- void
- ivlb(ExecContext *xc)
- {
- xc->kernelStats->ivlb();
- }
-
- void
- ivle(ExecContext *xc)
- {
- }
-
- void
- m5exit_old(ExecContext *xc)
- {
- SimExit(curTick, "m5_exit_old instruction encountered");
- }
-
- void
- m5exit(ExecContext *xc)
- {
- Tick delay = xc->regs.intRegFile[16];
- Tick when = curTick + delay * Clock::Int::ns;
- SimExit(when, "m5_exit instruction encountered");
- }
-
- void
- resetstats(ExecContext *xc)
- {
- if (!doStatisticsInsts)
- return;
-
- Tick delay = xc->regs.intRegFile[16];
- Tick period = xc->regs.intRegFile[17];
-
- Tick when = curTick + delay * Clock::Int::ns;
- Tick repeat = period * Clock::Int::ns;
-
- using namespace Stats;
- SetupEvent(Reset, when, repeat);
- }
-
- void
- dumpstats(ExecContext *xc)
- {
- if (!doStatisticsInsts)
- return;
-
- Tick delay = xc->regs.intRegFile[16];
- Tick period = xc->regs.intRegFile[17];
-
- Tick when = curTick + delay * Clock::Int::ns;
- Tick repeat = period * Clock::Int::ns;
-
- using namespace Stats;
- SetupEvent(Dump, when, repeat);
- }
-
- void
- addsymbol(ExecContext *xc)
- {
- Addr addr = xc->regs.intRegFile[16];
- char symb[100];
- CopyString(xc, symb, xc->regs.intRegFile[17], 100);
- std::string symbol(symb);
-
- DPRINTF(Loader, "Loaded symbol: %s @ %#llx\n", symbol, addr);
-
- xc->system->kernelSymtab->insert(addr,symbol);
- }
-
- void
- dumpresetstats(ExecContext *xc)
- {
- if (!doStatisticsInsts)
- return;
-
- Tick delay = xc->regs.intRegFile[16];
- Tick period = xc->regs.intRegFile[17];
-
- Tick when = curTick + delay * Clock::Int::ns;
- Tick repeat = period * Clock::Int::ns;
-
- using namespace Stats;
- SetupEvent(Dump|Reset, when, repeat);
- }
-
- void
- m5checkpoint(ExecContext *xc)
- {
- if (!doCheckpointInsts)
- return;
-
- Tick delay = xc->regs.intRegFile[16];
- Tick period = xc->regs.intRegFile[17];
-
- Tick when = curTick + delay * Clock::Int::ns;
- Tick repeat = period * Clock::Int::ns;
-
- Checkpoint::setup(when, repeat);
- }
-
- void
- readfile(ExecContext *xc)
- {
- const string &file = xc->cpu->system->params->readfile;
- if (file.empty()) {
- xc->regs.intRegFile[0] = ULL(0);
- return;
- }
-
- Addr vaddr = xc->regs.intRegFile[16];
- uint64_t len = xc->regs.intRegFile[17];
- uint64_t offset = xc->regs.intRegFile[18];
- uint64_t result = 0;
-
- int fd = ::open(file.c_str(), O_RDONLY, 0);
- if (fd < 0)
- panic("could not open file %s\n", file);
-
- if (::lseek(fd, offset, SEEK_SET) < 0)
- panic("could not seek: %s", strerror(errno));
-
- char *buf = new char[len];
- char *p = buf;
- while (len > 0) {
- int bytes = ::read(fd, p, len);
- if (bytes <= 0)
- break;
-
- p += bytes;
- result += bytes;
- len -= bytes;
- }
-
- close(fd);
- CopyIn(xc, vaddr, buf, result);
- delete [] buf;
- xc->regs.intRegFile[0] = result;
- }
-
- class Context : public ParamContext
- {
- public:
- Context(const string &section) : ParamContext(section) {}
- void checkParams();
- };
-
- Context context("pseudo_inst");
-
- Param<bool> __quiesce(&context, "quiesce",
- "enable quiesce instructions",
- true);
- Param<bool> __statistics(&context, "statistics",
- "enable statistics pseudo instructions",
- true);
- Param<bool> __checkpoint(&context, "checkpoint",
- "enable checkpoint pseudo instructions",
- true);
-
- void
- Context::checkParams()
- {
- doQuiesce = __quiesce;
- doStatisticsInsts = __statistics;
- doCheckpointInsts = __checkpoint;
- }
-
- void debugbreak(ExecContext *xc)
- {
- debug_break();
- }
-
- void switchcpu(ExecContext *xc)
- {
- if (SampCPU)
- SampCPU->switchCPUs();
- }
-}
diff --git a/arch/alpha/stacktrace.cc b/arch/alpha/stacktrace.cc
index 5a8df3d35..26656ab5c 100644
--- a/arch/alpha/stacktrace.cc
+++ b/arch/alpha/stacktrace.cc
@@ -35,31 +35,33 @@
#include "base/trace.hh"
#include "cpu/base.hh"
#include "cpu/exec_context.hh"
+#include "sim/system.hh"
using namespace std;
+using namespace AlphaISA;
ProcessInfo::ProcessInfo(ExecContext *_xc)
: xc(_xc)
{
Addr addr = 0;
- if (!xc->system->kernelSymtab->findAddress("thread_info_size", addr))
+ if (!xc->getSystemPtr()->kernelSymtab->findAddress("thread_info_size", addr))
panic("thread info not compiled into kernel\n");
thread_info_size = *(int32_t *)vtomem(xc, addr, sizeof(int32_t));
- if (!xc->system->kernelSymtab->findAddress("task_struct_size", addr))
+ if (!xc->getSystemPtr()->kernelSymtab->findAddress("task_struct_size", addr))
panic("thread info not compiled into kernel\n");
task_struct_size = *(int32_t *)vtomem(xc, addr, sizeof(int32_t));
- if (!xc->system->kernelSymtab->findAddress("thread_info_task", addr))
+ if (!xc->getSystemPtr()->kernelSymtab->findAddress("thread_info_task", addr))
panic("thread info not compiled into kernel\n");
task_off = *(int32_t *)vtomem(xc, addr, sizeof(int32_t));
- if (!xc->system->kernelSymtab->findAddress("task_struct_pid", addr))
+ if (!xc->getSystemPtr()->kernelSymtab->findAddress("task_struct_pid", addr))
panic("thread info not compiled into kernel\n");
pid_off = *(int32_t *)vtomem(xc, addr, sizeof(int32_t));
- if (!xc->system->kernelSymtab->findAddress("task_struct_comm", addr))
+ if (!xc->getSystemPtr()->kernelSymtab->findAddress("task_struct_comm", addr))
panic("thread info not compiled into kernel\n");
name_off = *(int32_t *)vtomem(xc, addr, sizeof(int32_t));
}
@@ -108,7 +110,7 @@ StackTrace::StackTrace()
{
}
-StackTrace::StackTrace(ExecContext *_xc, StaticInstPtr<TheISA> inst)
+StackTrace::StackTrace(ExecContext *_xc, StaticInstPtr inst)
: xc(0), stack(64)
{
trace(_xc, inst);
@@ -123,10 +125,11 @@ StackTrace::trace(ExecContext *_xc, bool is_call)
{
xc = _xc;
- bool usermode = (xc->regs.ipr[AlphaISA::IPR_DTB_CM] & 0x18) != 0;
+ bool usermode = (xc->readMiscReg(AlphaISA::IPR_DTB_CM) & 0x18) != 0;
- Addr pc = xc->regs.npc;
- bool kernel = xc->system->kernelStart <= pc && pc <= xc->system->kernelEnd;
+ Addr pc = xc->readNextPC();
+ bool kernel = xc->getSystemPtr()->kernelStart <= pc &&
+ pc <= xc->getSystemPtr()->kernelEnd;
if (usermode) {
stack.push_back(user);
@@ -138,8 +141,8 @@ StackTrace::trace(ExecContext *_xc, bool is_call)
return;
}
- SymbolTable *symtab = xc->system->kernelSymtab;
- Addr ksp = xc->regs.intRegFile[TheISA::StackPointerReg];
+ SymbolTable *symtab = xc->getSystemPtr()->kernelSymtab;
+ Addr ksp = xc->readIntReg(TheISA::StackPointerReg);
Addr bottom = ksp & ~0x3fff;
Addr addr;
@@ -148,7 +151,7 @@ StackTrace::trace(ExecContext *_xc, bool is_call)
panic("could not find address %#x", pc);
stack.push_back(addr);
- pc = xc->regs.pc;
+ pc = xc->readPC();
}
Addr ra;
@@ -180,8 +183,8 @@ StackTrace::trace(ExecContext *_xc, bool is_call)
return;
}
- bool kernel = xc->system->kernelStart <= pc &&
- pc <= xc->system->kernelEnd;
+ bool kernel = xc->getSystemPtr()->kernelStart <= pc &&
+ pc <= xc->getSystemPtr()->kernelEnd;
if (!kernel)
return;
@@ -195,22 +198,22 @@ StackTrace::trace(ExecContext *_xc, bool is_call)
bool
StackTrace::isEntry(Addr addr)
{
- if (addr == xc->regs.ipr[AlphaISA::IPR_PALtemp12])
+ if (addr == xc->readMiscReg(AlphaISA::IPR_PALtemp12))
return true;
- if (addr == xc->regs.ipr[AlphaISA::IPR_PALtemp7])
+ if (addr == xc->readMiscReg(AlphaISA::IPR_PALtemp7))
return true;
- if (addr == xc->regs.ipr[AlphaISA::IPR_PALtemp11])
+ if (addr == xc->readMiscReg(AlphaISA::IPR_PALtemp11))
return true;
- if (addr == xc->regs.ipr[AlphaISA::IPR_PALtemp21])
+ if (addr == xc->readMiscReg(AlphaISA::IPR_PALtemp21))
return true;
- if (addr == xc->regs.ipr[AlphaISA::IPR_PALtemp9])
+ if (addr == xc->readMiscReg(AlphaISA::IPR_PALtemp9))
return true;
- if (addr == xc->regs.ipr[AlphaISA::IPR_PALtemp2])
+ if (addr == xc->readMiscReg(AlphaISA::IPR_PALtemp2))
return true;
return false;
@@ -322,8 +325,8 @@ StackTrace::decodePrologue(Addr sp, Addr callpc, Addr func,
void
StackTrace::dump()
{
- StringWrap name(xc->cpu->name());
- SymbolTable *symtab = xc->system->kernelSymtab;
+ StringWrap name(xc->getCpuPtr()->name());
+ SymbolTable *symtab = xc->getSystemPtr()->kernelSymtab;
DPRINTFN("------ Stack ------\n");
diff --git a/arch/alpha/stacktrace.hh b/arch/alpha/stacktrace.hh
index 244e574b6..1d8d97a79 100644
--- a/arch/alpha/stacktrace.hh
+++ b/arch/alpha/stacktrace.hh
@@ -56,6 +56,8 @@ class ProcessInfo
class StackTrace
{
+ protected:
+ typedef TheISA::MachInst MachInst;
private:
ExecContext *xc;
std::vector<Addr> stack;
@@ -70,7 +72,7 @@ class StackTrace
public:
StackTrace();
- StackTrace(ExecContext *xc, StaticInstPtr<TheISA> inst);
+ StackTrace(ExecContext *xc, StaticInstPtr inst);
~StackTrace();
void clear()
@@ -80,7 +82,7 @@ class StackTrace
}
bool valid() const { return xc != NULL; }
- bool trace(ExecContext *xc, StaticInstPtr<TheISA> inst);
+ bool trace(ExecContext *xc, StaticInstPtr inst);
public:
const std::vector<Addr> &getstack() const { return stack; }
@@ -102,7 +104,7 @@ class StackTrace
};
inline bool
-StackTrace::trace(ExecContext *xc, StaticInstPtr<TheISA> inst)
+StackTrace::trace(ExecContext *xc, StaticInstPtr inst)
{
if (!inst->isCall() && !inst->isReturn())
return false;
diff --git a/arch/alpha/system.cc b/arch/alpha/system.cc
new file mode 100644
index 000000000..25543da57
--- /dev/null
+++ b/arch/alpha/system.cc
@@ -0,0 +1,299 @@
+/*
+ * Copyright (c) 2002-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "arch/alpha/system.hh"
+#include "arch/vtophys.hh"
+#include "base/remote_gdb.hh"
+#include "base/loader/object_file.hh"
+#include "base/loader/symtab.hh"
+#include "base/trace.hh"
+#include "mem/functional/memory_control.hh"
+#include "mem/functional/physical.hh"
+#include "sim/byteswap.hh"
+#include "sim/builder.hh"
+
+
+using namespace LittleEndianGuest;
+
+AlphaSystem::AlphaSystem(Params *p)
+ : System(p)
+{
+ consoleSymtab = new SymbolTable;
+ palSymtab = new SymbolTable;
+
+
+ /**
+ * Load the pal, and console code into memory
+ */
+ // Load Console Code
+ console = createObjectFile(params()->console_path);
+ if (console == NULL)
+ fatal("Could not load console file %s", params()->console_path);
+
+ // Load pal file
+ pal = createObjectFile(params()->palcode);
+ if (pal == NULL)
+ fatal("Could not load PALcode file %s", params()->palcode);
+
+
+ // Load program sections into memory
+ pal->loadSections(physmem, true);
+ console->loadSections(physmem, true);
+
+ // load symbols
+ if (!console->loadGlobalSymbols(consoleSymtab))
+ panic("could not load console symbols\n");
+
+ if (!pal->loadGlobalSymbols(palSymtab))
+ panic("could not load pal symbols\n");
+
+ if (!pal->loadLocalSymbols(palSymtab))
+ panic("could not load pal symbols\n");
+
+ if (!console->loadGlobalSymbols(debugSymbolTable))
+ panic("could not load console symbols\n");
+
+ if (!pal->loadGlobalSymbols(debugSymbolTable))
+ panic("could not load pal symbols\n");
+
+ if (!pal->loadLocalSymbols(debugSymbolTable))
+ panic("could not load pal symbols\n");
+
+ Addr addr = 0;
+#ifndef NDEBUG
+ consolePanicEvent = addConsoleFuncEvent<BreakPCEvent>("panic");
+#endif
+
+ /**
+ * Copy the osflags (kernel arguments) into the consoles
+ * memory. (Presently Linux does not use the console service
+ * routine to get these command line arguments, but Tru64 and
+ * others do.)
+ */
+ if (consoleSymtab->findAddress("env_booted_osflags", addr)) {
+ Addr paddr = vtophys(physmem, addr);
+ char *osflags = (char *)physmem->dma_addr(paddr, sizeof(uint32_t));
+
+ if (osflags)
+ strcpy(osflags, params()->boot_osflags.c_str());
+ }
+
+ /**
+ * Set the hardware reset parameter block system type and revision
+ * information to Tsunami.
+ */
+ if (consoleSymtab->findAddress("m5_rpb", addr)) {
+ Addr paddr = vtophys(physmem, addr);
+ char *hwrpb = (char *)physmem->dma_addr(paddr, sizeof(uint64_t));
+
+ if (!hwrpb)
+ panic("could not translate hwrpb addr\n");
+
+ *(uint64_t*)(hwrpb+0x50) = htog(params()->system_type);
+ *(uint64_t*)(hwrpb+0x58) = htog(params()->system_rev);
+ } else
+ panic("could not find hwrpb\n");
+
+}
+
+AlphaSystem::~AlphaSystem()
+{
+ delete consoleSymtab;
+ delete console;
+ delete pal;
+#ifdef DEBUG
+ delete consolePanicEvent;
+#endif
+}
+
+/**
+ * This function fixes up addresses that are used to match PCs for
+ * hooking simulator events on to target function executions.
+ *
+ * Alpha binaries may have multiple global offset table (GOT)
+ * sections. A function that uses the GOT starts with a
+ * two-instruction prolog which sets the global pointer (gp == r29) to
+ * the appropriate GOT section. The proper gp value is calculated
+ * based on the function address, which must be passed by the caller
+ * in the procedure value register (pv aka t12 == r27). This sequence
+ * looks like the following:
+ *
+ * opcode Ra Rb offset
+ * ldah gp,X(pv) 09 29 27 X
+ * lda gp,Y(gp) 08 29 29 Y
+ *
+ * for some constant offsets X and Y. The catch is that the linker
+ * (or maybe even the compiler, I'm not sure) may recognize that the
+ * caller and callee are using the same GOT section, making this
+ * prolog redundant, and modify the call target to skip these
+ * instructions. If we check for execution of the first instruction
+ * of a function (the one the symbol points to) to detect when to skip
+ * it, we'll miss all these modified calls. It might work to
+ * unconditionally check for the third instruction, but not all
+ * functions have this prolog, and there's some chance that those
+ * first two instructions could have undesired consequences. So we do
+ * the Right Thing and pattern-match the first two instructions of the
+ * function to decide where to patch.
+ *
+ * Eventually this code should be moved into an ISA-specific file.
+ */
+Addr
+AlphaSystem::fixFuncEventAddr(Addr addr)
+{
+ // mask for just the opcode, Ra, and Rb fields (not the offset)
+ const uint32_t inst_mask = 0xffff0000;
+ // ldah gp,X(pv): opcode 9, Ra = 29, Rb = 27
+ const uint32_t gp_ldah_pattern = (9 << 26) | (29 << 21) | (27 << 16);
+ // lda gp,Y(gp): opcode 8, Ra = 29, rb = 29
+ const uint32_t gp_lda_pattern = (8 << 26) | (29 << 21) | (29 << 16);
+ // instruction size
+ const int sz = sizeof(uint32_t);
+
+ Addr paddr = vtophys(physmem, addr);
+ uint32_t i1 = *(uint32_t *)physmem->dma_addr(paddr, sz);
+ uint32_t i2 = *(uint32_t *)physmem->dma_addr(paddr+sz, sz);
+
+ if ((i1 & inst_mask) == gp_ldah_pattern &&
+ (i2 & inst_mask) == gp_lda_pattern) {
+ Addr new_addr = addr + 2*sz;
+ DPRINTF(Loader, "fixFuncEventAddr: %p -> %p", addr, new_addr);
+ return new_addr;
+ } else {
+ return addr;
+ }
+}
+
+
+void
+AlphaSystem::setAlphaAccess(Addr access)
+{
+ Addr addr = 0;
+ if (consoleSymtab->findAddress("m5AlphaAccess", addr)) {
+ Addr paddr = vtophys(physmem, addr);
+ uint64_t *m5AlphaAccess =
+ (uint64_t *)physmem->dma_addr(paddr, sizeof(uint64_t));
+
+ if (!m5AlphaAccess)
+ panic("could not translate m5AlphaAccess addr\n");
+
+ *m5AlphaAccess = htog(EV5::Phys2K0Seg(access));
+ } else
+ panic("could not find m5AlphaAccess\n");
+}
+
+bool
+AlphaSystem::breakpoint()
+{
+ return remoteGDB[0]->trap(ALPHA_KENTRY_INT);
+}
+
+void
+AlphaSystem::serialize(std::ostream &os)
+{
+ System::serialize(os);
+ consoleSymtab->serialize("console_symtab", os);
+ palSymtab->serialize("pal_symtab", os);
+}
+
+
+void
+AlphaSystem::unserialize(Checkpoint *cp, const std::string &section)
+{
+ System::unserialize(cp,section);
+ consoleSymtab->unserialize("console_symtab", cp, section);
+ palSymtab->unserialize("pal_symtab", cp, section);
+}
+
+
+BEGIN_DECLARE_SIM_OBJECT_PARAMS(AlphaSystem)
+
+ Param<Tick> boot_cpu_frequency;
+ SimObjectParam<MemoryController *> memctrl;
+ SimObjectParam<PhysicalMemory *> physmem;
+
+ Param<std::string> kernel;
+ Param<std::string> console;
+ Param<std::string> pal;
+
+ Param<std::string> boot_osflags;
+ Param<std::string> readfile;
+ Param<unsigned int> init_param;
+
+ Param<uint64_t> system_type;
+ Param<uint64_t> system_rev;
+
+ Param<bool> bin;
+ VectorParam<std::string> binned_fns;
+ Param<bool> bin_int;
+
+END_DECLARE_SIM_OBJECT_PARAMS(AlphaSystem)
+
+BEGIN_INIT_SIM_OBJECT_PARAMS(AlphaSystem)
+
+ INIT_PARAM(boot_cpu_frequency, "Frequency of the boot CPU"),
+ INIT_PARAM(memctrl, "memory controller"),
+ INIT_PARAM(physmem, "phsyical memory"),
+ INIT_PARAM(kernel, "file that contains the kernel code"),
+ INIT_PARAM(console, "file that contains the console code"),
+ INIT_PARAM(pal, "file that contains palcode"),
+ INIT_PARAM_DFLT(boot_osflags, "flags to pass to the kernel during boot",
+ "a"),
+ INIT_PARAM_DFLT(readfile, "file to read startup script from", ""),
+ INIT_PARAM_DFLT(init_param, "numerical value to pass into simulator", 0),
+ INIT_PARAM_DFLT(system_type, "Type of system we are emulating", 34),
+ INIT_PARAM_DFLT(system_rev, "Revision of system we are emulating", 1<<10),
+ INIT_PARAM_DFLT(bin, "is this system to be binned", false),
+ INIT_PARAM(binned_fns, "functions to be broken down and binned"),
+ INIT_PARAM_DFLT(bin_int, "is interrupt code binned seperately?", true)
+
+END_INIT_SIM_OBJECT_PARAMS(AlphaSystem)
+
+CREATE_SIM_OBJECT(AlphaSystem)
+{
+ AlphaSystem::Params *p = new AlphaSystem::Params;
+ p->name = getInstanceName();
+ p->boot_cpu_frequency = boot_cpu_frequency;
+ p->memctrl = memctrl;
+ p->physmem = physmem;
+ p->kernel_path = kernel;
+ p->console_path = console;
+ p->palcode = pal;
+ p->boot_osflags = boot_osflags;
+ p->init_param = init_param;
+ p->readfile = readfile;
+ p->system_type = system_type;
+ p->system_rev = system_rev;
+ p->bin = bin;
+ p->binned_fns = binned_fns;
+ p->bin_int = bin_int;
+ return new AlphaSystem(p);
+}
+
+REGISTER_SIM_OBJECT("AlphaSystem", AlphaSystem)
+
+
diff --git a/arch/alpha/system.hh b/arch/alpha/system.hh
new file mode 100644
index 000000000..fe1307ac3
--- /dev/null
+++ b/arch/alpha/system.hh
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2002-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __ARCH_ALPHA_SYSTEM_HH__
+#define __ARCH_ALPHA_SYSTEM_HH__
+
+#include <string>
+#include <vector>
+
+#include "sim/system.hh"
+#include "base/loader/symtab.hh"
+#include "cpu/pc_event.hh"
+#include "kern/system_events.hh"
+#include "sim/sim_object.hh"
+
+class AlphaSystem : public System
+{
+ public:
+ struct Params : public System::Params
+ {
+ std::string console_path;
+ std::string palcode;
+ std::string boot_osflags;
+ uint64_t system_type;
+ uint64_t system_rev;
+ };
+
+ AlphaSystem(Params *p);
+
+ ~AlphaSystem();
+
+ virtual bool breakpoint();
+
+/**
+ * Serialization stuff
+ */
+ public:
+ virtual void serialize(std::ostream &os);
+ virtual void unserialize(Checkpoint *cp, const std::string &section);
+
+ /**
+ * Set the m5AlphaAccess pointer in the console
+ */
+ void setAlphaAccess(Addr access);
+
+ /** console symbol table */
+ SymbolTable *consoleSymtab;
+
+ /** pal symbol table */
+ SymbolTable *palSymtab;
+
+ /** Object pointer for the console code */
+ ObjectFile *console;
+
+ /** Object pointer for the PAL code */
+ ObjectFile *pal;
+
+#ifndef NDEBUG
+ /** Event to halt the simulator if the console calls panic() */
+ BreakPCEvent *consolePanicEvent;
+#endif
+ protected:
+ const Params *params() const { return (const Params *)_params; }
+
+ /** Add a function-based event to PALcode. */
+ template <class T>
+ T *AlphaSystem::addPalFuncEvent(const char *lbl)
+ {
+ return addFuncEvent<T>(palSymtab, lbl);
+ }
+
+ /** Add a function-based event to the console code. */
+ template <class T>
+ T *AlphaSystem::addConsoleFuncEvent(const char *lbl)
+ {
+ return addFuncEvent<T>(consoleSymtab, lbl);
+ }
+
+ virtual Addr fixFuncEventAddr(Addr addr);
+
+};
+
+#endif
+
diff --git a/arch/alpha/alpha_memory.cc b/arch/alpha/tlb.cc
index 8dda4d9c4..e30a8e595 100644
--- a/arch/alpha/alpha_memory.cc
+++ b/arch/alpha/tlb.cc
@@ -30,7 +30,7 @@
#include <string>
#include <vector>
-#include "arch/alpha/alpha_memory.hh"
+#include "arch/alpha/tlb.hh"
#include "base/inifile.hh"
#include "base/str.hh"
#include "base/trace.hh"
@@ -293,12 +293,11 @@ AlphaITB::regStats()
void
AlphaITB::fault(Addr pc, ExecContext *xc) const
{
- uint64_t *ipr = xc->regs.ipr;
-
if (!xc->misspeculating()) {
- ipr[AlphaISA::IPR_ITB_TAG] = pc;
- ipr[AlphaISA::IPR_IFAULT_VA_FORM] =
- ipr[AlphaISA::IPR_IVPTBR] | (AlphaISA::VAddr(pc).vpn() << 3);
+ xc->setMiscReg(AlphaISA::IPR_ITB_TAG, pc);
+ xc->setMiscReg(AlphaISA::IPR_IFAULT_VA_FORM,
+ xc->readMiscReg(AlphaISA::IPR_IVPTBR) |
+ (AlphaISA::VAddr(pc).vpn() << 3));
}
}
@@ -306,13 +305,13 @@ AlphaITB::fault(Addr pc, ExecContext *xc) const
Fault
AlphaITB::translate(MemReqPtr &req) const
{
- InternalProcReg *ipr = req->xc->regs.ipr;
+ ExecContext *xc = req->xc;
if (AlphaISA::PcPAL(req->vaddr)) {
// strip off PAL PC marker (lsb is 1)
req->paddr = (req->vaddr & ~3) & PAddrImplMask;
hits++;
- return No_Fault;
+ return NoFault;
}
if (req->flags & PHYSICAL) {
@@ -322,24 +321,24 @@ AlphaITB::translate(MemReqPtr &req) const
if (!validVirtualAddress(req->vaddr)) {
fault(req->vaddr, req->xc);
acv++;
- return ITB_Acv_Fault;
+ return new ItbAcvFault;
}
// VA<42:41> == 2, VA<39:13> maps directly to PA<39:13> for EV5
// VA<47:41> == 0x7e, VA<40:13> maps directly to PA<40:13> for EV6
#if ALPHA_TLASER
- if ((MCSR_SP(ipr[AlphaISA::IPR_MCSR]) & 2) &&
+ if ((MCSR_SP(xc->readMiscReg(AlphaISA::IPR_MCSR)) & 2) &&
VAddrSpaceEV5(req->vaddr) == 2) {
#else
if (VAddrSpaceEV6(req->vaddr) == 0x7e) {
#endif
// only valid in kernel mode
- if (ICM_CM(ipr[AlphaISA::IPR_ICM]) !=
+ if (ICM_CM(xc->readMiscReg(AlphaISA::IPR_ICM)) !=
AlphaISA::mode_kernel) {
fault(req->vaddr, req->xc);
acv++;
- return ITB_Acv_Fault;
+ return new ItbAcvFault;
}
req->paddr = req->vaddr & PAddrImplMask;
@@ -354,24 +353,26 @@ AlphaITB::translate(MemReqPtr &req) const
} else {
// not a physical address: need to look up pte
+ int asn = DTB_ASN_ASN(xc->readMiscReg(AlphaISA::IPR_DTB_ASN));
AlphaISA::PTE *pte = lookup(AlphaISA::VAddr(req->vaddr).vpn(),
- DTB_ASN_ASN(ipr[AlphaISA::IPR_DTB_ASN]));
+ asn);
if (!pte) {
fault(req->vaddr, req->xc);
misses++;
- return ITB_Fault_Fault;
+ return new ItbPageFault;
}
req->paddr = (pte->ppn << AlphaISA::PageShift) +
(AlphaISA::VAddr(req->vaddr).offset() & ~3);
// check permissions for this access
- if (!(pte->xre & (1 << ICM_CM(ipr[AlphaISA::IPR_ICM])))) {
+ if (!(pte->xre &
+ (1 << ICM_CM(xc->readMiscReg(AlphaISA::IPR_ICM))))) {
// instruction access fault
fault(req->vaddr, req->xc);
acv++;
- return ITB_Acv_Fault;
+ return new ItbAcvFault;
}
hits++;
@@ -380,11 +381,11 @@ AlphaITB::translate(MemReqPtr &req) const
// check that the physical address is ok (catch bad physical addresses)
if (req->paddr & ~PAddrImplMask)
- return Machine_Check_Fault;
+ return genMachineCheckFault();
checkCacheability(req);
- return No_Fault;
+ return NoFault;
}
///////////////////////////////////////////////////////////////////////
@@ -469,7 +470,6 @@ AlphaDTB::fault(MemReqPtr &req, uint64_t flags) const
{
ExecContext *xc = req->xc;
AlphaISA::VAddr vaddr = req->vaddr;
- uint64_t *ipr = xc->regs.ipr;
// Set fault address and flags. Even though we're modeling an
// EV5, we use the EV6 technique of not latching fault registers
@@ -479,29 +479,28 @@ AlphaDTB::fault(MemReqPtr &req, uint64_t flags) const
if (!xc->misspeculating()
&& !(req->flags & VPTE) && !(req->flags & NO_FAULT)) {
// set VA register with faulting address
- ipr[AlphaISA::IPR_VA] = req->vaddr;
+ xc->setMiscReg(AlphaISA::IPR_VA, req->vaddr);
// set MM_STAT register flags
- ipr[AlphaISA::IPR_MM_STAT] =
+ xc->setMiscReg(AlphaISA::IPR_MM_STAT,
(((Opcode(xc->getInst()) & 0x3f) << 11)
| ((Ra(xc->getInst()) & 0x1f) << 6)
- | (flags & 0x3f));
+ | (flags & 0x3f)));
// set VA_FORM register with faulting formatted address
- ipr[AlphaISA::IPR_VA_FORM] =
- ipr[AlphaISA::IPR_MVPTBR] | (vaddr.vpn() << 3);
+ xc->setMiscReg(AlphaISA::IPR_VA_FORM,
+ xc->readMiscReg(AlphaISA::IPR_MVPTBR) | (vaddr.vpn() << 3));
}
}
Fault
AlphaDTB::translate(MemReqPtr &req, bool write) const
{
- RegFile *regs = &req->xc->regs;
- Addr pc = regs->pc;
- InternalProcReg *ipr = regs->ipr;
+ ExecContext *xc = req->xc;
+ Addr pc = xc->readPC();
AlphaISA::mode_type mode =
- (AlphaISA::mode_type)DTB_CM_CM(ipr[AlphaISA::IPR_DTB_CM]);
+ (AlphaISA::mode_type)DTB_CM_CM(xc->readMiscReg(AlphaISA::IPR_DTB_CM));
/**
@@ -511,12 +510,13 @@ AlphaDTB::translate(MemReqPtr &req, bool write) const
fault(req, write ? MM_STAT_WR_MASK : 0);
DPRINTF(TLB, "Alignment Fault on %#x, size = %d", req->vaddr,
req->size);
- return Alignment_Fault;
+ return genAlignmentFault();
}
if (pc & 0x1) {
mode = (req->flags & ALTMODE) ?
- (AlphaISA::mode_type)ALT_MODE_AM(ipr[AlphaISA::IPR_ALT_MODE])
+ (AlphaISA::mode_type)ALT_MODE_AM(
+ xc->readMiscReg(AlphaISA::IPR_ALT_MODE))
: AlphaISA::mode_kernel;
}
@@ -530,24 +530,24 @@ AlphaDTB::translate(MemReqPtr &req, bool write) const
MM_STAT_ACV_MASK);
if (write) { write_acv++; } else { read_acv++; }
- return DTB_Fault_Fault;
+ return new DtbPageFault;
}
// Check for "superpage" mapping
#if ALPHA_TLASER
- if ((MCSR_SP(ipr[AlphaISA::IPR_MCSR]) & 2) &&
+ if ((MCSR_SP(xc->readMiscReg(AlphaISA::IPR_MCSR)) & 2) &&
VAddrSpaceEV5(req->vaddr) == 2) {
#else
if (VAddrSpaceEV6(req->vaddr) == 0x7e) {
#endif
// only valid in kernel mode
- if (DTB_CM_CM(ipr[AlphaISA::IPR_DTB_CM]) !=
+ if (DTB_CM_CM(xc->readMiscReg(AlphaISA::IPR_DTB_CM)) !=
AlphaISA::mode_kernel) {
fault(req, ((write ? MM_STAT_WR_MASK : 0) |
MM_STAT_ACV_MASK));
if (write) { write_acv++; } else { read_acv++; }
- return DTB_Acv_Fault;
+ return new DtbAcvFault;
}
req->paddr = req->vaddr & PAddrImplMask;
@@ -566,16 +566,20 @@ AlphaDTB::translate(MemReqPtr &req, bool write) const
else
read_accesses++;
+ int asn = DTB_ASN_ASN(xc->readMiscReg(AlphaISA::IPR_DTB_ASN));
+
// not a physical address: need to look up pte
AlphaISA::PTE *pte = lookup(AlphaISA::VAddr(req->vaddr).vpn(),
- DTB_ASN_ASN(ipr[AlphaISA::IPR_DTB_ASN]));
+ asn);
if (!pte) {
// page fault
fault(req, (write ? MM_STAT_WR_MASK : 0) |
MM_STAT_DTB_MISS_MASK);
if (write) { write_misses++; } else { read_misses++; }
- return (req->flags & VPTE) ? Pdtb_Miss_Fault : Ndtb_Miss_Fault;
+ return (req->flags & VPTE) ?
+ (Fault)(new PDtbMissFault) :
+ (Fault)(new NDtbMissFault);
}
req->paddr = (pte->ppn << AlphaISA::PageShift) +
@@ -588,25 +592,25 @@ AlphaDTB::translate(MemReqPtr &req, bool write) const
MM_STAT_ACV_MASK |
(pte->fonw ? MM_STAT_FONW_MASK : 0));
write_acv++;
- return DTB_Fault_Fault;
+ return new DtbPageFault;
}
if (pte->fonw) {
fault(req, MM_STAT_WR_MASK |
MM_STAT_FONW_MASK);
write_acv++;
- return DTB_Fault_Fault;
+ return new DtbPageFault;
}
} else {
if (!(pte->xre & MODE2MASK(mode))) {
fault(req, MM_STAT_ACV_MASK |
(pte->fonr ? MM_STAT_FONR_MASK : 0));
read_acv++;
- return DTB_Acv_Fault;
+ return new DtbAcvFault;
}
if (pte->fonr) {
fault(req, MM_STAT_FONR_MASK);
read_acv++;
- return DTB_Fault_Fault;
+ return new DtbPageFault;
}
}
}
@@ -619,11 +623,11 @@ AlphaDTB::translate(MemReqPtr &req, bool write) const
// check that the physical address is ok (catch bad physical addresses)
if (req->paddr & ~PAddrImplMask)
- return Machine_Check_Fault;
+ return genMachineCheckFault();
checkCacheability(req);
- return No_Fault;
+ return NoFault;
}
AlphaISA::PTE &
diff --git a/arch/alpha/alpha_memory.hh b/arch/alpha/tlb.hh
index 788923434..de955fa46 100644
--- a/arch/alpha/alpha_memory.hh
+++ b/arch/alpha/tlb.hh
@@ -32,6 +32,7 @@
#include <map>
#include "arch/alpha/isa_traits.hh"
+#include "arch/alpha/faults.hh"
#include "base/statistics.hh"
#include "mem/mem_req.hh"
#include "sim/sim_object.hh"
diff --git a/arch/alpha/tru64/process.cc b/arch/alpha/tru64/process.cc
new file mode 100644
index 000000000..c3a203587
--- /dev/null
+++ b/arch/alpha/tru64/process.cc
@@ -0,0 +1,543 @@
+/*
+ * Copyright (c) 2001-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "arch/alpha/isa_traits.hh"
+#include "arch/alpha/tru64/process.hh"
+#include "cpu/exec_context.hh"
+#include "kern/tru64/tru64.hh"
+#include "mem/functional/functional.hh"
+#include "sim/fake_syscall.hh"
+#include "sim/process.hh"
+#include "sim/syscall_emul.hh"
+
+using namespace std;
+using namespace AlphaISA;
+
+/// Target uname() handler.
+static SyscallReturn
+unameFunc(SyscallDesc *desc, int callnum, Process *process,
+ ExecContext *xc)
+{
+ TypedBufferArg<Tru64::utsname> name(xc->getSyscallArg(0));
+
+ strcpy(name->sysname, "OSF1");
+ strcpy(name->nodename, "m5.eecs.umich.edu");
+ strcpy(name->release, "V5.1");
+ strcpy(name->version, "732");
+ strcpy(name->machine, "alpha");
+
+ name.copyOut(xc->getMemPtr());
+ return 0;
+}
+
+/// Target getsysyinfo() handler.
+static SyscallReturn
+getsysinfoFunc(SyscallDesc *desc, int callnum, Process *process,
+ ExecContext *xc)
+{
+ unsigned op = xc->getSyscallArg(0);
+ unsigned nbytes = xc->getSyscallArg(2);
+
+ switch (op) {
+
+ case Tru64::GSI_MAX_CPU: {
+ TypedBufferArg<uint32_t> max_cpu(xc->getSyscallArg(1));
+ *max_cpu = htog((uint32_t)process->numCpus());
+ max_cpu.copyOut(xc->getMemPtr());
+ return 1;
+ }
+
+ case Tru64::GSI_CPUS_IN_BOX: {
+ TypedBufferArg<uint32_t> cpus_in_box(xc->getSyscallArg(1));
+ *cpus_in_box = htog((uint32_t)process->numCpus());
+ cpus_in_box.copyOut(xc->getMemPtr());
+ return 1;
+ }
+
+ case Tru64::GSI_PHYSMEM: {
+ TypedBufferArg<uint64_t> physmem(xc->getSyscallArg(1));
+ *physmem = htog((uint64_t)1024 * 1024); // physical memory in KB
+ physmem.copyOut(xc->getMemPtr());
+ return 1;
+ }
+
+ case Tru64::GSI_CPU_INFO: {
+ TypedBufferArg<Tru64::cpu_info> infop(xc->getSyscallArg(1));
+
+ infop->current_cpu = htog(0);
+ infop->cpus_in_box = htog(process->numCpus());
+ infop->cpu_type = htog(57);
+ infop->ncpus = htog(process->numCpus());
+ uint64_t cpumask = (1 << process->numCpus()) - 1;
+ infop->cpus_present = infop->cpus_running = htog(cpumask);
+ infop->cpu_binding = htog(0);
+ infop->cpu_ex_binding = htog(0);
+ infop->mhz = htog(667);
+
+ infop.copyOut(xc->getMemPtr());
+ return 1;
+ }
+
+ case Tru64::GSI_PROC_TYPE: {
+ TypedBufferArg<uint64_t> proc_type(xc->getSyscallArg(1));
+ *proc_type = htog((uint64_t)11);
+ proc_type.copyOut(xc->getMemPtr());
+ return 1;
+ }
+
+ case Tru64::GSI_PLATFORM_NAME: {
+ BufferArg bufArg(xc->getSyscallArg(1), nbytes);
+ strncpy((char *)bufArg.bufferPtr(),
+ "COMPAQ Professional Workstation XP1000",
+ nbytes);
+ bufArg.copyOut(xc->getMemPtr());
+ return 1;
+ }
+
+ case Tru64::GSI_CLK_TCK: {
+ TypedBufferArg<uint64_t> clk_hz(xc->getSyscallArg(1));
+ *clk_hz = htog((uint64_t)1024);
+ clk_hz.copyOut(xc->getMemPtr());
+ return 1;
+ }
+
+ default:
+ warn("getsysinfo: unknown op %d\n", op);
+ break;
+ }
+
+ return 0;
+}
+
+/// Target setsysyinfo() handler.
+static SyscallReturn
+setsysinfoFunc(SyscallDesc *desc, int callnum, Process *process,
+ ExecContext *xc)
+{
+ unsigned op = xc->getSyscallArg(0);
+
+ switch (op) {
+ case Tru64::SSI_IEEE_FP_CONTROL:
+ warn("setsysinfo: ignoring ieee_set_fp_control() arg 0x%x\n",
+ xc->getSyscallArg(1));
+ break;
+
+ default:
+ warn("setsysinfo: unknown op %d\n", op);
+ break;
+ }
+
+ return 0;
+}
+
+
+SyscallDesc AlphaTru64Process::syscallDescs[] = {
+ /* 0 */ SyscallDesc("syscall (#0)", Tru64::indirectSyscallFunc,
+ SyscallDesc::SuppressReturnValue),
+ /* 1 */ SyscallDesc("exit", exitFunc),
+ /* 2 */ SyscallDesc("fork", unimplementedFunc),
+ /* 3 */ SyscallDesc("read", readFunc),
+ /* 4 */ SyscallDesc("write", writeFunc),
+ /* 5 */ SyscallDesc("old_open", unimplementedFunc),
+ /* 6 */ SyscallDesc("close", closeFunc),
+ /* 7 */ SyscallDesc("wait4", unimplementedFunc),
+ /* 8 */ SyscallDesc("old_creat", unimplementedFunc),
+ /* 9 */ SyscallDesc("link", unimplementedFunc),
+ /* 10 */ SyscallDesc("unlink", unlinkFunc),
+ /* 11 */ SyscallDesc("execv", unimplementedFunc),
+ /* 12 */ SyscallDesc("chdir", unimplementedFunc),
+ /* 13 */ SyscallDesc("fchdir", unimplementedFunc),
+ /* 14 */ SyscallDesc("mknod", unimplementedFunc),
+ /* 15 */ SyscallDesc("chmod", unimplementedFunc),
+ /* 16 */ SyscallDesc("chown", unimplementedFunc),
+ /* 17 */ SyscallDesc("obreak", obreakFunc),
+ /* 18 */ SyscallDesc("pre_F64_getfsstat", unimplementedFunc),
+ /* 19 */ SyscallDesc("lseek", lseekFunc),
+ /* 20 */ SyscallDesc("getpid", getpidPseudoFunc),
+ /* 21 */ SyscallDesc("mount", unimplementedFunc),
+ /* 22 */ SyscallDesc("unmount", unimplementedFunc),
+ /* 23 */ SyscallDesc("setuid", setuidFunc),
+ /* 24 */ SyscallDesc("getuid", getuidPseudoFunc),
+ /* 25 */ SyscallDesc("exec_with_loader", unimplementedFunc),
+ /* 26 */ SyscallDesc("ptrace", unimplementedFunc),
+ /* 27 */ SyscallDesc("recvmsg", unimplementedFunc),
+ /* 28 */ SyscallDesc("sendmsg", unimplementedFunc),
+ /* 29 */ SyscallDesc("recvfrom", unimplementedFunc),
+ /* 30 */ SyscallDesc("accept", unimplementedFunc),
+ /* 31 */ SyscallDesc("getpeername", unimplementedFunc),
+ /* 32 */ SyscallDesc("getsockname", unimplementedFunc),
+ /* 33 */ SyscallDesc("access", unimplementedFunc),
+ /* 34 */ SyscallDesc("chflags", unimplementedFunc),
+ /* 35 */ SyscallDesc("fchflags", unimplementedFunc),
+ /* 36 */ SyscallDesc("sync", unimplementedFunc),
+ /* 37 */ SyscallDesc("kill", unimplementedFunc),
+ /* 38 */ SyscallDesc("old_stat", unimplementedFunc),
+ /* 39 */ SyscallDesc("setpgid", unimplementedFunc),
+ /* 40 */ SyscallDesc("old_lstat", unimplementedFunc),
+ /* 41 */ SyscallDesc("dup", unimplementedFunc),
+ /* 42 */ SyscallDesc("pipe", unimplementedFunc),
+ /* 43 */ SyscallDesc("set_program_attributes", unimplementedFunc),
+ /* 44 */ SyscallDesc("profil", unimplementedFunc),
+ /* 45 */ SyscallDesc("open", openFunc<Tru64>),
+ /* 46 */ SyscallDesc("obsolete osigaction", unimplementedFunc),
+ /* 47 */ SyscallDesc("getgid", getgidPseudoFunc),
+ /* 48 */ SyscallDesc("sigprocmask", ignoreFunc),
+ /* 49 */ SyscallDesc("getlogin", unimplementedFunc),
+ /* 50 */ SyscallDesc("setlogin", unimplementedFunc),
+ /* 51 */ SyscallDesc("acct", unimplementedFunc),
+ /* 52 */ SyscallDesc("sigpending", unimplementedFunc),
+ /* 53 */ SyscallDesc("classcntl", unimplementedFunc),
+ /* 54 */ SyscallDesc("ioctl", ioctlFunc<Tru64>),
+ /* 55 */ SyscallDesc("reboot", unimplementedFunc),
+ /* 56 */ SyscallDesc("revoke", unimplementedFunc),
+ /* 57 */ SyscallDesc("symlink", unimplementedFunc),
+ /* 58 */ SyscallDesc("readlink", unimplementedFunc),
+ /* 59 */ SyscallDesc("execve", unimplementedFunc),
+ /* 60 */ SyscallDesc("umask", unimplementedFunc),
+ /* 61 */ SyscallDesc("chroot", unimplementedFunc),
+ /* 62 */ SyscallDesc("old_fstat", unimplementedFunc),
+ /* 63 */ SyscallDesc("getpgrp", unimplementedFunc),
+ /* 64 */ SyscallDesc("getpagesize", getpagesizeFunc),
+ /* 65 */ SyscallDesc("mremap", unimplementedFunc),
+ /* 66 */ SyscallDesc("vfork", unimplementedFunc),
+ /* 67 */ SyscallDesc("pre_F64_stat", statFunc<Tru64::PreF64>),
+ /* 68 */ SyscallDesc("pre_F64_lstat", lstatFunc<Tru64::PreF64>),
+ /* 69 */ SyscallDesc("sbrk", unimplementedFunc),
+ /* 70 */ SyscallDesc("sstk", unimplementedFunc),
+ /* 71 */ SyscallDesc("mmap", mmapFunc<Tru64>),
+ /* 72 */ SyscallDesc("ovadvise", unimplementedFunc),
+ /* 73 */ SyscallDesc("munmap", munmapFunc),
+ /* 74 */ SyscallDesc("mprotect", ignoreFunc),
+ /* 75 */ SyscallDesc("madvise", unimplementedFunc),
+ /* 76 */ SyscallDesc("old_vhangup", unimplementedFunc),
+ /* 77 */ SyscallDesc("kmodcall", unimplementedFunc),
+ /* 78 */ SyscallDesc("mincore", unimplementedFunc),
+ /* 79 */ SyscallDesc("getgroups", unimplementedFunc),
+ /* 80 */ SyscallDesc("setgroups", unimplementedFunc),
+ /* 81 */ SyscallDesc("old_getpgrp", unimplementedFunc),
+ /* 82 */ SyscallDesc("setpgrp", unimplementedFunc),
+ /* 83 */ SyscallDesc("setitimer", unimplementedFunc),
+ /* 84 */ SyscallDesc("old_wait", unimplementedFunc),
+ /* 85 */ SyscallDesc("table", Tru64::tableFunc),
+ /* 86 */ SyscallDesc("getitimer", unimplementedFunc),
+ /* 87 */ SyscallDesc("gethostname", gethostnameFunc),
+ /* 88 */ SyscallDesc("sethostname", unimplementedFunc),
+ /* 89 */ SyscallDesc("getdtablesize", unimplementedFunc),
+ /* 90 */ SyscallDesc("dup2", unimplementedFunc),
+ /* 91 */ SyscallDesc("pre_F64_fstat", fstatFunc<Tru64::PreF64>),
+ /* 92 */ SyscallDesc("fcntl", fcntlFunc),
+ /* 93 */ SyscallDesc("select", unimplementedFunc),
+ /* 94 */ SyscallDesc("poll", unimplementedFunc),
+ /* 95 */ SyscallDesc("fsync", unimplementedFunc),
+ /* 96 */ SyscallDesc("setpriority", unimplementedFunc),
+ /* 97 */ SyscallDesc("socket", unimplementedFunc),
+ /* 98 */ SyscallDesc("connect", unimplementedFunc),
+ /* 99 */ SyscallDesc("old_accept", unimplementedFunc),
+ /* 100 */ SyscallDesc("getpriority", unimplementedFunc),
+ /* 101 */ SyscallDesc("old_send", unimplementedFunc),
+ /* 102 */ SyscallDesc("old_recv", unimplementedFunc),
+ /* 103 */ SyscallDesc("sigreturn", Tru64::sigreturnFunc,
+ SyscallDesc::SuppressReturnValue),
+ /* 104 */ SyscallDesc("bind", unimplementedFunc),
+ /* 105 */ SyscallDesc("setsockopt", unimplementedFunc),
+ /* 106 */ SyscallDesc("listen", unimplementedFunc),
+ /* 107 */ SyscallDesc("plock", unimplementedFunc),
+ /* 108 */ SyscallDesc("old_sigvec", unimplementedFunc),
+ /* 109 */ SyscallDesc("old_sigblock", unimplementedFunc),
+ /* 110 */ SyscallDesc("old_sigsetmask", unimplementedFunc),
+ /* 111 */ SyscallDesc("sigsuspend", unimplementedFunc),
+ /* 112 */ SyscallDesc("sigstack", ignoreFunc),
+ /* 113 */ SyscallDesc("old_recvmsg", unimplementedFunc),
+ /* 114 */ SyscallDesc("old_sendmsg", unimplementedFunc),
+ /* 115 */ SyscallDesc("obsolete vtrace", unimplementedFunc),
+ /* 116 */ SyscallDesc("gettimeofday", gettimeofdayFunc<Tru64>),
+ /* 117 */ SyscallDesc("getrusage", getrusageFunc<Tru64>),
+ /* 118 */ SyscallDesc("getsockopt", unimplementedFunc),
+ /* 119 */ SyscallDesc("numa_syscalls", unimplementedFunc),
+ /* 120 */ SyscallDesc("readv", unimplementedFunc),
+ /* 121 */ SyscallDesc("writev", unimplementedFunc),
+ /* 122 */ SyscallDesc("settimeofday", unimplementedFunc),
+ /* 123 */ SyscallDesc("fchown", unimplementedFunc),
+ /* 124 */ SyscallDesc("fchmod", unimplementedFunc),
+ /* 125 */ SyscallDesc("old_recvfrom", unimplementedFunc),
+ /* 126 */ SyscallDesc("setreuid", unimplementedFunc),
+ /* 127 */ SyscallDesc("setregid", unimplementedFunc),
+ /* 128 */ SyscallDesc("rename", renameFunc),
+ /* 129 */ SyscallDesc("truncate", truncateFunc),
+ /* 130 */ SyscallDesc("ftruncate", ftruncateFunc),
+ /* 131 */ SyscallDesc("flock", unimplementedFunc),
+ /* 132 */ SyscallDesc("setgid", unimplementedFunc),
+ /* 133 */ SyscallDesc("sendto", unimplementedFunc),
+ /* 134 */ SyscallDesc("shutdown", unimplementedFunc),
+ /* 135 */ SyscallDesc("socketpair", unimplementedFunc),
+ /* 136 */ SyscallDesc("mkdir", unimplementedFunc),
+ /* 137 */ SyscallDesc("rmdir", unimplementedFunc),
+ /* 138 */ SyscallDesc("utimes", unimplementedFunc),
+ /* 139 */ SyscallDesc("obsolete 4.2 sigreturn", unimplementedFunc),
+ /* 140 */ SyscallDesc("adjtime", unimplementedFunc),
+ /* 141 */ SyscallDesc("old_getpeername", unimplementedFunc),
+ /* 142 */ SyscallDesc("gethostid", unimplementedFunc),
+ /* 143 */ SyscallDesc("sethostid", unimplementedFunc),
+ /* 144 */ SyscallDesc("getrlimit", getrlimitFunc<Tru64>),
+ /* 145 */ SyscallDesc("setrlimit", ignoreFunc),
+ /* 146 */ SyscallDesc("old_killpg", unimplementedFunc),
+ /* 147 */ SyscallDesc("setsid", unimplementedFunc),
+ /* 148 */ SyscallDesc("quotactl", unimplementedFunc),
+ /* 149 */ SyscallDesc("oldquota", unimplementedFunc),
+ /* 150 */ SyscallDesc("old_getsockname", unimplementedFunc),
+ /* 151 */ SyscallDesc("pread", unimplementedFunc),
+ /* 152 */ SyscallDesc("pwrite", unimplementedFunc),
+ /* 153 */ SyscallDesc("pid_block", unimplementedFunc),
+ /* 154 */ SyscallDesc("pid_unblock", unimplementedFunc),
+ /* 155 */ SyscallDesc("signal_urti", unimplementedFunc),
+ /* 156 */ SyscallDesc("sigaction", ignoreFunc),
+ /* 157 */ SyscallDesc("sigwaitprim", unimplementedFunc),
+ /* 158 */ SyscallDesc("nfssvc", unimplementedFunc),
+ /* 159 */ SyscallDesc("getdirentries", Tru64::getdirentriesFunc),
+ /* 160 */ SyscallDesc("pre_F64_statfs", statfsFunc<Tru64::PreF64>),
+ /* 161 */ SyscallDesc("pre_F64_fstatfs", fstatfsFunc<Tru64::PreF64>),
+ /* 162 */ SyscallDesc("unknown #162", unimplementedFunc),
+ /* 163 */ SyscallDesc("async_daemon", unimplementedFunc),
+ /* 164 */ SyscallDesc("getfh", unimplementedFunc),
+ /* 165 */ SyscallDesc("getdomainname", unimplementedFunc),
+ /* 166 */ SyscallDesc("setdomainname", unimplementedFunc),
+ /* 167 */ SyscallDesc("unknown #167", unimplementedFunc),
+ /* 168 */ SyscallDesc("unknown #168", unimplementedFunc),
+ /* 169 */ SyscallDesc("exportfs", unimplementedFunc),
+ /* 170 */ SyscallDesc("unknown #170", unimplementedFunc),
+ /* 171 */ SyscallDesc("unknown #171", unimplementedFunc),
+ /* 172 */ SyscallDesc("unknown #172", unimplementedFunc),
+ /* 173 */ SyscallDesc("unknown #173", unimplementedFunc),
+ /* 174 */ SyscallDesc("unknown #174", unimplementedFunc),
+ /* 175 */ SyscallDesc("unknown #175", unimplementedFunc),
+ /* 176 */ SyscallDesc("unknown #176", unimplementedFunc),
+ /* 177 */ SyscallDesc("unknown #177", unimplementedFunc),
+ /* 178 */ SyscallDesc("unknown #178", unimplementedFunc),
+ /* 179 */ SyscallDesc("unknown #179", unimplementedFunc),
+ /* 180 */ SyscallDesc("unknown #180", unimplementedFunc),
+ /* 181 */ SyscallDesc("alt_plock", unimplementedFunc),
+ /* 182 */ SyscallDesc("unknown #182", unimplementedFunc),
+ /* 183 */ SyscallDesc("unknown #183", unimplementedFunc),
+ /* 184 */ SyscallDesc("getmnt", unimplementedFunc),
+ /* 185 */ SyscallDesc("unknown #185", unimplementedFunc),
+ /* 186 */ SyscallDesc("unknown #186", unimplementedFunc),
+ /* 187 */ SyscallDesc("alt_sigpending", unimplementedFunc),
+ /* 188 */ SyscallDesc("alt_setsid", unimplementedFunc),
+ /* 189 */ SyscallDesc("unknown #189", unimplementedFunc),
+ /* 190 */ SyscallDesc("unknown #190", unimplementedFunc),
+ /* 191 */ SyscallDesc("unknown #191", unimplementedFunc),
+ /* 192 */ SyscallDesc("unknown #192", unimplementedFunc),
+ /* 193 */ SyscallDesc("unknown #193", unimplementedFunc),
+ /* 194 */ SyscallDesc("unknown #194", unimplementedFunc),
+ /* 195 */ SyscallDesc("unknown #195", unimplementedFunc),
+ /* 196 */ SyscallDesc("unknown #196", unimplementedFunc),
+ /* 197 */ SyscallDesc("unknown #197", unimplementedFunc),
+ /* 198 */ SyscallDesc("unknown #198", unimplementedFunc),
+ /* 199 */ SyscallDesc("swapon", unimplementedFunc),
+ /* 200 */ SyscallDesc("msgctl", unimplementedFunc),
+ /* 201 */ SyscallDesc("msgget", unimplementedFunc),
+ /* 202 */ SyscallDesc("msgrcv", unimplementedFunc),
+ /* 203 */ SyscallDesc("msgsnd", unimplementedFunc),
+ /* 204 */ SyscallDesc("semctl", unimplementedFunc),
+ /* 205 */ SyscallDesc("semget", unimplementedFunc),
+ /* 206 */ SyscallDesc("semop", unimplementedFunc),
+ /* 207 */ SyscallDesc("uname", unameFunc),
+ /* 208 */ SyscallDesc("lchown", unimplementedFunc),
+ /* 209 */ SyscallDesc("shmat", unimplementedFunc),
+ /* 210 */ SyscallDesc("shmctl", unimplementedFunc),
+ /* 211 */ SyscallDesc("shmdt", unimplementedFunc),
+ /* 212 */ SyscallDesc("shmget", unimplementedFunc),
+ /* 213 */ SyscallDesc("mvalid", unimplementedFunc),
+ /* 214 */ SyscallDesc("getaddressconf", unimplementedFunc),
+ /* 215 */ SyscallDesc("msleep", unimplementedFunc),
+ /* 216 */ SyscallDesc("mwakeup", unimplementedFunc),
+ /* 217 */ SyscallDesc("msync", unimplementedFunc),
+ /* 218 */ SyscallDesc("signal", unimplementedFunc),
+ /* 219 */ SyscallDesc("utc_gettime", unimplementedFunc),
+ /* 220 */ SyscallDesc("utc_adjtime", unimplementedFunc),
+ /* 221 */ SyscallDesc("unknown #221", unimplementedFunc),
+ /* 222 */ SyscallDesc("security", unimplementedFunc),
+ /* 223 */ SyscallDesc("kloadcall", unimplementedFunc),
+ /* 224 */ SyscallDesc("stat", statFunc<Tru64::F64>),
+ /* 225 */ SyscallDesc("lstat", lstatFunc<Tru64::F64>),
+ /* 226 */ SyscallDesc("fstat", fstatFunc<Tru64::F64>),
+ /* 227 */ SyscallDesc("statfs", statfsFunc<Tru64::F64>),
+ /* 228 */ SyscallDesc("fstatfs", fstatfsFunc<Tru64::F64>),
+ /* 229 */ SyscallDesc("getfsstat", unimplementedFunc),
+ /* 230 */ SyscallDesc("gettimeofday64", unimplementedFunc),
+ /* 231 */ SyscallDesc("settimeofday64", unimplementedFunc),
+ /* 232 */ SyscallDesc("unknown #232", unimplementedFunc),
+ /* 233 */ SyscallDesc("getpgid", unimplementedFunc),
+ /* 234 */ SyscallDesc("getsid", unimplementedFunc),
+ /* 235 */ SyscallDesc("sigaltstack", ignoreFunc),
+ /* 236 */ SyscallDesc("waitid", unimplementedFunc),
+ /* 237 */ SyscallDesc("priocntlset", unimplementedFunc),
+ /* 238 */ SyscallDesc("sigsendset", unimplementedFunc),
+ /* 239 */ SyscallDesc("set_speculative", unimplementedFunc),
+ /* 240 */ SyscallDesc("msfs_syscall", unimplementedFunc),
+ /* 241 */ SyscallDesc("sysinfo", unimplementedFunc),
+ /* 242 */ SyscallDesc("uadmin", unimplementedFunc),
+ /* 243 */ SyscallDesc("fuser", unimplementedFunc),
+ /* 244 */ SyscallDesc("proplist_syscall", unimplementedFunc),
+ /* 245 */ SyscallDesc("ntp_adjtime", unimplementedFunc),
+ /* 246 */ SyscallDesc("ntp_gettime", unimplementedFunc),
+ /* 247 */ SyscallDesc("pathconf", unimplementedFunc),
+ /* 248 */ SyscallDesc("fpathconf", unimplementedFunc),
+ /* 249 */ SyscallDesc("sync2", unimplementedFunc),
+ /* 250 */ SyscallDesc("uswitch", unimplementedFunc),
+ /* 251 */ SyscallDesc("usleep_thread", unimplementedFunc),
+ /* 252 */ SyscallDesc("audcntl", unimplementedFunc),
+ /* 253 */ SyscallDesc("audgen", unimplementedFunc),
+ /* 254 */ SyscallDesc("sysfs", unimplementedFunc),
+ /* 255 */ SyscallDesc("subsys_info", unimplementedFunc),
+ /* 256 */ SyscallDesc("getsysinfo", getsysinfoFunc),
+ /* 257 */ SyscallDesc("setsysinfo", setsysinfoFunc),
+ /* 258 */ SyscallDesc("afs_syscall", unimplementedFunc),
+ /* 259 */ SyscallDesc("swapctl", unimplementedFunc),
+ /* 260 */ SyscallDesc("memcntl", unimplementedFunc),
+ /* 261 */ SyscallDesc("fdatasync", unimplementedFunc),
+ /* 262 */ SyscallDesc("oflock", unimplementedFunc),
+ /* 263 */ SyscallDesc("F64_readv", unimplementedFunc),
+ /* 264 */ SyscallDesc("F64_writev", unimplementedFunc),
+ /* 265 */ SyscallDesc("cdslxlate", unimplementedFunc),
+ /* 266 */ SyscallDesc("sendfile", unimplementedFunc),
+};
+
+
+
+SyscallDesc AlphaTru64Process::machSyscallDescs[] = {
+ /* 0 */ SyscallDesc("kern_invalid", unimplementedFunc),
+ /* 1 */ SyscallDesc("m5_mutex_lock", Tru64::m5_mutex_lockFunc),
+ /* 2 */ SyscallDesc("m5_mutex_trylock", Tru64::m5_mutex_trylockFunc),
+ /* 3 */ SyscallDesc("m5_mutex_unlock", Tru64::m5_mutex_unlockFunc),
+ /* 4 */ SyscallDesc("m5_cond_signal", Tru64::m5_cond_signalFunc),
+ /* 5 */ SyscallDesc("m5_cond_broadcast", Tru64::m5_cond_broadcastFunc),
+ /* 6 */ SyscallDesc("m5_cond_wait", Tru64::m5_cond_waitFunc),
+ /* 7 */ SyscallDesc("m5_thread_exit", Tru64::m5_thread_exitFunc),
+ /* 8 */ SyscallDesc("kern_invalid", unimplementedFunc),
+ /* 9 */ SyscallDesc("kern_invalid", unimplementedFunc),
+ /* 10 */ SyscallDesc("task_self", unimplementedFunc),
+ /* 11 */ SyscallDesc("thread_reply", unimplementedFunc),
+ /* 12 */ SyscallDesc("task_notify", unimplementedFunc),
+ /* 13 */ SyscallDesc("thread_self", unimplementedFunc),
+ /* 14 */ SyscallDesc("kern_invalid", unimplementedFunc),
+ /* 15 */ SyscallDesc("kern_invalid", unimplementedFunc),
+ /* 16 */ SyscallDesc("kern_invalid", unimplementedFunc),
+ /* 17 */ SyscallDesc("kern_invalid", unimplementedFunc),
+ /* 18 */ SyscallDesc("kern_invalid", unimplementedFunc),
+ /* 19 */ SyscallDesc("kern_invalid", unimplementedFunc),
+ /* 20 */ SyscallDesc("msg_send_trap", unimplementedFunc),
+ /* 21 */ SyscallDesc("msg_receive_trap", unimplementedFunc),
+ /* 22 */ SyscallDesc("msg_rpc_trap", unimplementedFunc),
+ /* 23 */ SyscallDesc("kern_invalid", unimplementedFunc),
+ /* 24 */ SyscallDesc("nxm_block", Tru64::nxm_blockFunc),
+ /* 25 */ SyscallDesc("nxm_unblock", Tru64::nxm_unblockFunc),
+ /* 26 */ SyscallDesc("kern_invalid", unimplementedFunc),
+ /* 27 */ SyscallDesc("kern_invalid", unimplementedFunc),
+ /* 28 */ SyscallDesc("kern_invalid", unimplementedFunc),
+ /* 29 */ SyscallDesc("nxm_thread_destroy", unimplementedFunc),
+ /* 30 */ SyscallDesc("lw_wire", unimplementedFunc),
+ /* 31 */ SyscallDesc("lw_unwire", unimplementedFunc),
+ /* 32 */ SyscallDesc("nxm_thread_create", Tru64::nxm_thread_createFunc),
+ /* 33 */ SyscallDesc("nxm_task_init", Tru64::nxm_task_initFunc),
+ /* 34 */ SyscallDesc("kern_invalid", unimplementedFunc),
+ /* 35 */ SyscallDesc("nxm_idle", Tru64::nxm_idleFunc),
+ /* 36 */ SyscallDesc("nxm_wakeup_idle", unimplementedFunc),
+ /* 37 */ SyscallDesc("nxm_set_pthid", unimplementedFunc),
+ /* 38 */ SyscallDesc("nxm_thread_kill", unimplementedFunc),
+ /* 39 */ SyscallDesc("nxm_thread_block", Tru64::nxm_thread_blockFunc),
+ /* 40 */ SyscallDesc("nxm_thread_wakeup", unimplementedFunc),
+ /* 41 */ SyscallDesc("init_process", unimplementedFunc),
+ /* 42 */ SyscallDesc("nxm_get_binding", unimplementedFunc),
+ /* 43 */ SyscallDesc("map_fd", unimplementedFunc),
+ /* 44 */ SyscallDesc("nxm_resched", unimplementedFunc),
+ /* 45 */ SyscallDesc("nxm_set_cancel", unimplementedFunc),
+ /* 46 */ SyscallDesc("nxm_set_binding", unimplementedFunc),
+ /* 47 */ SyscallDesc("stack_create", Tru64::stack_createFunc),
+ /* 48 */ SyscallDesc("nxm_get_state", unimplementedFunc),
+ /* 49 */ SyscallDesc("nxm_thread_suspend", unimplementedFunc),
+ /* 50 */ SyscallDesc("nxm_thread_resume", unimplementedFunc),
+ /* 51 */ SyscallDesc("nxm_signal_check", unimplementedFunc),
+ /* 52 */ SyscallDesc("htg_unix_syscall", unimplementedFunc),
+ /* 53 */ SyscallDesc("kern_invalid", unimplementedFunc),
+ /* 54 */ SyscallDesc("kern_invalid", unimplementedFunc),
+ /* 55 */ SyscallDesc("host_self", unimplementedFunc),
+ /* 56 */ SyscallDesc("host_priv_self", unimplementedFunc),
+ /* 57 */ SyscallDesc("kern_invalid", unimplementedFunc),
+ /* 58 */ SyscallDesc("kern_invalid", unimplementedFunc),
+ /* 59 */ SyscallDesc("swtch_pri", Tru64::swtch_priFunc),
+ /* 60 */ SyscallDesc("swtch", unimplementedFunc),
+ /* 61 */ SyscallDesc("thread_switch", unimplementedFunc),
+ /* 62 */ SyscallDesc("semop_fast", unimplementedFunc),
+ /* 63 */ SyscallDesc("nxm_pshared_init", unimplementedFunc),
+ /* 64 */ SyscallDesc("nxm_pshared_block", unimplementedFunc),
+ /* 65 */ SyscallDesc("nxm_pshared_unblock", unimplementedFunc),
+ /* 66 */ SyscallDesc("nxm_pshared_destroy", unimplementedFunc),
+ /* 67 */ SyscallDesc("nxm_swtch_pri", Tru64::swtch_priFunc),
+ /* 68 */ SyscallDesc("lw_syscall", unimplementedFunc),
+ /* 69 */ SyscallDesc("kern_invalid", unimplementedFunc),
+ /* 70 */ SyscallDesc("mach_sctimes_0", unimplementedFunc),
+ /* 71 */ SyscallDesc("mach_sctimes_1", unimplementedFunc),
+ /* 72 */ SyscallDesc("mach_sctimes_2", unimplementedFunc),
+ /* 73 */ SyscallDesc("mach_sctimes_3", unimplementedFunc),
+ /* 74 */ SyscallDesc("mach_sctimes_4", unimplementedFunc),
+ /* 75 */ SyscallDesc("mach_sctimes_5", unimplementedFunc),
+ /* 76 */ SyscallDesc("mach_sctimes_6", unimplementedFunc),
+ /* 77 */ SyscallDesc("mach_sctimes_7", unimplementedFunc),
+ /* 78 */ SyscallDesc("mach_sctimes_8", unimplementedFunc),
+ /* 79 */ SyscallDesc("mach_sctimes_9", unimplementedFunc),
+ /* 80 */ SyscallDesc("mach_sctimes_10", unimplementedFunc),
+ /* 81 */ SyscallDesc("mach_sctimes_11", unimplementedFunc),
+ /* 82 */ SyscallDesc("mach_sctimes_port_alloc_dealloc", unimplementedFunc)
+};
+
+SyscallDesc*
+AlphaTru64Process::getDesc(int callnum)
+{
+ if (callnum < -Num_Mach_Syscall_Descs || callnum > Num_Syscall_Descs)
+ return NULL;
+
+ if (callnum < 0)
+ return &machSyscallDescs[-callnum];
+ else
+ return &syscallDescs[callnum];
+}
+
+
+AlphaTru64Process::AlphaTru64Process(const std::string &name,
+ ObjectFile *objFile,
+ int stdin_fd,
+ int stdout_fd,
+ int stderr_fd,
+ std::vector<std::string> &argv,
+ std::vector<std::string> &envp)
+ : LiveProcess(name, objFile, stdin_fd, stdout_fd, stderr_fd, argv, envp),
+ Num_Syscall_Descs(sizeof(syscallDescs) / sizeof(SyscallDesc)),
+ Num_Mach_Syscall_Descs(sizeof(machSyscallDescs) / sizeof(SyscallDesc))
+{
+}
diff --git a/arch/alpha/alpha_tru64_process.hh b/arch/alpha/tru64/process.hh
index c28598700..84abd54bf 100644
--- a/arch/alpha/alpha_tru64_process.hh
+++ b/arch/alpha/tru64/process.hh
@@ -43,8 +43,16 @@ class AlphaTru64Process : public LiveProcess
std::vector<std::string> &argv,
std::vector<std::string> &envp);
- /// Syscall emulation function.
- virtual void syscall(ExecContext *xc);
+ /// Array of syscall descriptors, indexed by call number.
+ static SyscallDesc syscallDescs[];
+
+ /// Array of mach syscall descriptors, indexed by call number.
+ static SyscallDesc machSyscallDescs[];
+
+ const int Num_Syscall_Descs;
+ const int Num_Mach_Syscall_Descs;
+
+ virtual SyscallDesc* getDesc(int callnum);
};
diff --git a/arch/alpha/tru64/system.cc b/arch/alpha/tru64/system.cc
new file mode 100644
index 000000000..d09a0c85d
--- /dev/null
+++ b/arch/alpha/tru64/system.cc
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 2003-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "arch/alpha/tru64/system.hh"
+#include "arch/isa_traits.hh"
+#include "arch/vtophys.hh"
+#include "base/loader/symtab.hh"
+#include "base/trace.hh"
+#include "cpu/base.hh"
+#include "cpu/exec_context.hh"
+#include "kern/tru64/tru64_events.hh"
+#include "kern/system_events.hh"
+#include "mem/functional/memory_control.hh"
+#include "mem/functional/physical.hh"
+#include "sim/builder.hh"
+
+using namespace std;
+
+Tru64AlphaSystem::Tru64AlphaSystem(Tru64AlphaSystem::Params *p)
+ : AlphaSystem(p)
+{
+ Addr addr = 0;
+ if (kernelSymtab->findAddress("enable_async_printf", addr)) {
+ Addr paddr = vtophys(physmem, addr);
+ uint8_t *enable_async_printf =
+ physmem->dma_addr(paddr, sizeof(uint32_t));
+
+ if (enable_async_printf)
+ *(uint32_t *)enable_async_printf = 0;
+ }
+
+#ifdef DEBUG
+ kernelPanicEvent = addKernelFuncEvent<BreakPCEvent>("panic");
+ if (!kernelPanicEvent)
+ panic("could not find kernel symbol \'panic\'");
+#endif
+
+ badaddrEvent = addKernelFuncEvent<BadAddrEvent>("badaddr");
+ if (!badaddrEvent)
+ panic("could not find kernel symbol \'badaddr\'");
+
+ skipPowerStateEvent =
+ addKernelFuncEvent<SkipFuncEvent>("tl_v48_capture_power_state");
+ skipScavengeBootEvent =
+ addKernelFuncEvent<SkipFuncEvent>("pmap_scavenge_boot");
+
+#if TRACING_ON
+ printfEvent = addKernelFuncEvent<PrintfEvent>("printf");
+ debugPrintfEvent = addKernelFuncEvent<DebugPrintfEvent>("m5printf");
+ debugPrintfrEvent = addKernelFuncEvent<DebugPrintfrEvent>("m5printfr");
+ dumpMbufEvent = addKernelFuncEvent<DumpMbufEvent>("m5_dump_mbuf");
+#endif
+}
+
+Tru64AlphaSystem::~Tru64AlphaSystem()
+{
+#ifdef DEBUG
+ delete kernelPanicEvent;
+#endif
+ delete badaddrEvent;
+ delete skipPowerStateEvent;
+ delete skipScavengeBootEvent;
+#if TRACING_ON
+ delete printfEvent;
+ delete debugPrintfEvent;
+ delete debugPrintfrEvent;
+ delete dumpMbufEvent;
+#endif
+}
+
+BEGIN_DECLARE_SIM_OBJECT_PARAMS(Tru64AlphaSystem)
+
+ Param<Tick> boot_cpu_frequency;
+ SimObjectParam<MemoryController *> memctrl;
+ SimObjectParam<PhysicalMemory *> physmem;
+
+ Param<string> kernel;
+ Param<string> console;
+ Param<string> pal;
+
+ Param<string> boot_osflags;
+ Param<string> readfile;
+ Param<unsigned int> init_param;
+
+ Param<uint64_t> system_type;
+ Param<uint64_t> system_rev;
+
+ Param<bool> bin;
+ VectorParam<string> binned_fns;
+
+END_DECLARE_SIM_OBJECT_PARAMS(Tru64AlphaSystem)
+
+BEGIN_INIT_SIM_OBJECT_PARAMS(Tru64AlphaSystem)
+
+ INIT_PARAM(boot_cpu_frequency, "frequency of the boot cpu"),
+ INIT_PARAM(memctrl, "memory controller"),
+ INIT_PARAM(physmem, "phsyical memory"),
+ INIT_PARAM(kernel, "file that contains the kernel code"),
+ INIT_PARAM(console, "file that contains the console code"),
+ INIT_PARAM(pal, "file that contains palcode"),
+ INIT_PARAM_DFLT(boot_osflags, "flags to pass to the kernel during boot",
+ "a"),
+ INIT_PARAM_DFLT(readfile, "file to read startup script from", ""),
+ INIT_PARAM_DFLT(init_param, "numerical value to pass into simulator", 0),
+ INIT_PARAM_DFLT(system_type, "Type of system we are emulating", 12),
+ INIT_PARAM_DFLT(system_rev, "Revision of system we are emulating", 2<<1),
+ INIT_PARAM_DFLT(bin, "is this system to be binned", false),
+ INIT_PARAM(binned_fns, "functions to be broken down and binned")
+
+END_INIT_SIM_OBJECT_PARAMS(Tru64AlphaSystem)
+
+CREATE_SIM_OBJECT(Tru64AlphaSystem)
+{
+ AlphaSystem::Params *p = new AlphaSystem::Params;
+ p->name = getInstanceName();
+ p->boot_cpu_frequency = boot_cpu_frequency;
+ p->memctrl = memctrl;
+ p->physmem = physmem;
+ p->kernel_path = kernel;
+ p->console_path = console;
+ p->palcode = pal;
+ p->boot_osflags = boot_osflags;
+ p->init_param = init_param;
+ p->readfile = readfile;
+ p->system_type = system_type;
+ p->system_rev = system_rev;
+ p->bin = bin;
+ p->binned_fns = binned_fns;
+ p->bin_int = false;
+
+ return new Tru64AlphaSystem(p);
+}
+
+REGISTER_SIM_OBJECT("Tru64AlphaSystem", Tru64AlphaSystem)
diff --git a/arch/alpha/tru64/system.hh b/arch/alpha/tru64/system.hh
new file mode 100644
index 000000000..0e0cc1bc8
--- /dev/null
+++ b/arch/alpha/tru64/system.hh
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2003-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __ARCH_ALPHA_TRU64_SYSTEM_HH__
+#define __ARCH_ALPHA_TRU64_SYSTEM_HH__
+
+#include "arch/alpha/system.hh"
+#include "arch/isa_traits.hh"
+#include "sim/system.hh"
+
+class ExecContext;
+
+class BreakPCEvent;
+class BadAddrEvent;
+class SkipFuncEvent;
+class PrintfEvent;
+class DebugPrintfEvent;
+class DebugPrintfrEvent;
+class DumpMbufEvent;
+class AlphaArguments;
+
+class Tru64AlphaSystem : public AlphaSystem
+{
+ private:
+#ifdef DEBUG
+ /** Event to halt the simulator if the kernel calls panic() */
+ BreakPCEvent *kernelPanicEvent;
+#endif
+
+ BadAddrEvent *badaddrEvent;
+ SkipFuncEvent *skipPowerStateEvent;
+ SkipFuncEvent *skipScavengeBootEvent;
+ PrintfEvent *printfEvent;
+ DebugPrintfEvent *debugPrintfEvent;
+ DebugPrintfrEvent *debugPrintfrEvent;
+ DumpMbufEvent *dumpMbufEvent;
+
+ public:
+ Tru64AlphaSystem(Params *p);
+ ~Tru64AlphaSystem();
+
+ static void Printf(AlphaArguments args);
+ static void DumpMbuf(AlphaArguments args);
+};
+
+#endif // __ARCH_ALPHA_TRU64_SYSTEM_HH__
diff --git a/arch/alpha/vtophys.cc b/arch/alpha/vtophys.cc
index 27014164c..40261426d 100644
--- a/arch/alpha/vtophys.cc
+++ b/arch/alpha/vtophys.cc
@@ -34,6 +34,7 @@
#include "mem/functional/physical.hh"
using namespace std;
+using namespace AlphaISA;
AlphaISA::PageTableEntry
kernel_pte_lookup(PhysicalMemory *pmem, Addr ptbr, AlphaISA::VAddr vaddr)
@@ -81,7 +82,7 @@ Addr
vtophys(ExecContext *xc, Addr addr)
{
AlphaISA::VAddr vaddr = addr;
- Addr ptbr = xc->regs.ipr[AlphaISA::IPR_PALtemp20];
+ Addr ptbr = xc->readMiscReg(AlphaISA::IPR_PALtemp20);
Addr paddr = 0;
//@todo Andrew couldn't remember why he commented some of this code
//so I put it back in. Perhaps something to do with gdb debugging?
@@ -94,7 +95,7 @@ vtophys(ExecContext *xc, Addr addr)
paddr = vaddr;
} else {
AlphaISA::PageTableEntry pte =
- kernel_pte_lookup(xc->physmem, ptbr, vaddr);
+ kernel_pte_lookup(xc->getPhysMemPtr(), ptbr, vaddr);
if (pte.valid())
paddr = pte.paddr() | vaddr.offset();
}
@@ -109,14 +110,14 @@ vtophys(ExecContext *xc, Addr addr)
uint8_t *
ptomem(ExecContext *xc, Addr paddr, size_t len)
{
- return xc->physmem->dma_addr(paddr, len);
+ return xc->getPhysMemPtr()->dma_addr(paddr, len);
}
uint8_t *
vtomem(ExecContext *xc, Addr vaddr, size_t len)
{
Addr paddr = vtophys(xc, vaddr);
- return xc->physmem->dma_addr(paddr, len);
+ return xc->getPhysMemPtr()->dma_addr(paddr, len);
}
void
@@ -130,7 +131,7 @@ CopyOut(ExecContext *xc, void *dest, Addr src, size_t cplen)
paddr = vtophys(xc, src);
len = min((int)(AlphaISA::PageBytes - (paddr & AlphaISA::PageOffset)),
(int)cplen);
- dmaaddr = (char *)xc->physmem->dma_addr(paddr, len);
+ dmaaddr = (char *)xc->getPhysMemPtr()->dma_addr(paddr, len);
assert(dmaaddr);
memcpy(dst, dmaaddr, len);
@@ -143,7 +144,8 @@ CopyOut(ExecContext *xc, void *dest, Addr src, size_t cplen)
while (cplen > AlphaISA::PageBytes) {
paddr = vtophys(xc, src);
- dmaaddr = (char *)xc->physmem->dma_addr(paddr, AlphaISA::PageBytes);
+ dmaaddr = (char *)xc->getPhysMemPtr()->dma_addr(paddr,
+ AlphaISA::PageBytes);
assert(dmaaddr);
memcpy(dst, dmaaddr, AlphaISA::PageBytes);
@@ -154,7 +156,7 @@ CopyOut(ExecContext *xc, void *dest, Addr src, size_t cplen)
if (cplen > 0) {
paddr = vtophys(xc, src);
- dmaaddr = (char *)xc->physmem->dma_addr(paddr, cplen);
+ dmaaddr = (char *)xc->getPhysMemPtr()->dma_addr(paddr, cplen);
assert(dmaaddr);
memcpy(dst, dmaaddr, cplen);
@@ -172,7 +174,7 @@ CopyIn(ExecContext *xc, Addr dest, void *source, size_t cplen)
paddr = vtophys(xc, dest);
len = min((int)(AlphaISA::PageBytes - (paddr & AlphaISA::PageOffset)),
(int)cplen);
- dmaaddr = (char *)xc->physmem->dma_addr(paddr, len);
+ dmaaddr = (char *)xc->getPhysMemPtr()->dma_addr(paddr, len);
assert(dmaaddr);
memcpy(dmaaddr, src, len);
@@ -185,7 +187,8 @@ CopyIn(ExecContext *xc, Addr dest, void *source, size_t cplen)
while (cplen > AlphaISA::PageBytes) {
paddr = vtophys(xc, dest);
- dmaaddr = (char *)xc->physmem->dma_addr(paddr, AlphaISA::PageBytes);
+ dmaaddr = (char *)xc->getPhysMemPtr()->dma_addr(paddr,
+ AlphaISA::PageBytes);
assert(dmaaddr);
memcpy(dmaaddr, src, AlphaISA::PageBytes);
@@ -196,7 +199,7 @@ CopyIn(ExecContext *xc, Addr dest, void *source, size_t cplen)
if (cplen > 0) {
paddr = vtophys(xc, dest);
- dmaaddr = (char *)xc->physmem->dma_addr(paddr, cplen);
+ dmaaddr = (char *)xc->getPhysMemPtr()->dma_addr(paddr, cplen);
assert(dmaaddr);
memcpy(dmaaddr, src, cplen);
@@ -213,7 +216,7 @@ CopyString(ExecContext *xc, char *dst, Addr vaddr, size_t maxlen)
paddr = vtophys(xc, vaddr);
len = min((int)(AlphaISA::PageBytes - (paddr & AlphaISA::PageOffset)),
(int)maxlen);
- dmaaddr = (char *)xc->physmem->dma_addr(paddr, len);
+ dmaaddr = (char *)xc->getPhysMemPtr()->dma_addr(paddr, len);
assert(dmaaddr);
char *term = (char *)memchr(dmaaddr, 0, len);
@@ -231,7 +234,8 @@ CopyString(ExecContext *xc, char *dst, Addr vaddr, size_t maxlen)
while (maxlen > AlphaISA::PageBytes) {
paddr = vtophys(xc, vaddr);
- dmaaddr = (char *)xc->physmem->dma_addr(paddr, AlphaISA::PageBytes);
+ dmaaddr = (char *)xc->getPhysMemPtr()->dma_addr(paddr,
+ AlphaISA::PageBytes);
assert(dmaaddr);
char *term = (char *)memchr(dmaaddr, 0, AlphaISA::PageBytes);
@@ -248,7 +252,7 @@ CopyString(ExecContext *xc, char *dst, Addr vaddr, size_t maxlen)
if (maxlen > 0) {
paddr = vtophys(xc, vaddr);
- dmaaddr = (char *)xc->physmem->dma_addr(paddr, maxlen);
+ dmaaddr = (char *)xc->getPhysMemPtr()->dma_addr(paddr, maxlen);
assert(dmaaddr);
char *term = (char *)memchr(dmaaddr, 0, maxlen);