diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/alpha/alpha_linux_process.cc | 46 | ||||
-rw-r--r-- | arch/alpha/alpha_tru64_process.cc | 207 | ||||
-rw-r--r-- | arch/alpha/isa/main.isa | 2 | ||||
-rw-r--r-- | arch/alpha/isa/mem.isa | 153 | ||||
-rwxr-xr-x | arch/isa_parser.py | 18 | ||||
-rw-r--r-- | arch/mips/SConscript | 81 | ||||
-rw-r--r-- | arch/mips/isa/bitfields.isa | 1 | ||||
-rw-r--r-- | arch/mips/isa/decoder.isa | 257 | ||||
-rw-r--r-- | arch/mips/isa/formats.isa | 21 | ||||
-rw-r--r-- | arch/mips/isa/formats/basic.isa | 2 | ||||
-rw-r--r-- | arch/mips/isa/formats/branch.isa | 273 | ||||
-rw-r--r-- | arch/mips/isa/formats/fp.isa | 27 | ||||
-rw-r--r-- | arch/mips/isa/formats/int.isa | 4 | ||||
-rw-r--r-- | arch/mips/isa/formats/mem.isa | 2 | ||||
-rw-r--r-- | arch/mips/isa/formats/noop.isa | 87 | ||||
-rw-r--r-- | arch/mips/isa/formats/unimp.isa | 165 | ||||
-rw-r--r-- | arch/mips/isa/formats/unknown.isa | 52 | ||||
-rw-r--r-- | arch/mips/isa/main.isa | 12 | ||||
-rw-r--r-- | arch/mips/isa/operands.isa | 6 | ||||
-rw-r--r-- | arch/sparc/SConscript | 82 |
20 files changed, 1218 insertions, 280 deletions
diff --git a/arch/alpha/alpha_linux_process.cc b/arch/alpha/alpha_linux_process.cc index 113b41472..fb5e32e63 100644 --- a/arch/alpha/alpha_linux_process.cc +++ b/arch/alpha/alpha_linux_process.cc @@ -296,27 +296,38 @@ class Linux { // Same for stat64 static void - copyOutStat64Buf(FunctionalMemory *mem, Addr addr, hst_stat64 *host) + copyOutStat64Buf(FunctionalMemory *mem, int fd, Addr addr, hst_stat64 *host) { TypedBufferArg<Linux::tgt_stat64> tgt(addr); - // XXX byteswaps - tgt->st_dev = htog(host->st_dev); + // fd == 1 checks are because libc does some checks + // that the stdout is interactive vs. a file + // this makes it work on non-linux systems + if (fd == 1) + tgt->st_dev = htog((uint64_t)0xA); + else + tgt->st_dev = htog((uint64_t)host->st_dev); // XXX What about STAT64_HAS_BROKEN_ST_INO ??? - tgt->st_ino = htog(host->st_ino); - tgt->st_rdev = htog(host->st_rdev); - tgt->st_size = htog(host->st_size); - tgt->st_blocks = htog(host->st_blocks); - - tgt->st_mode = htog(host->st_mode); - tgt->st_uid = htog(host->st_uid); - tgt->st_gid = htog(host->st_gid); - tgt->st_blksize = htog(host->st_blksize); - tgt->st_nlink = htog(host->st_nlink); - tgt->tgt_st_atime = htog(host->st_atime); - tgt->tgt_st_mtime = htog(host->st_mtime); - tgt->tgt_st_ctime = htog(host->st_ctime); -#if defined(STAT_HAVE_NSEC) || (BSD_HOST == 1) + tgt->st_ino = htog((uint64_t)host->st_ino); + if (fd == 1) + tgt->st_rdev = htog((uint64_t)0x880d); + else + tgt->st_rdev = htog((uint64_t)host->st_rdev); + tgt->st_size = htog((int64_t)host->st_size); + tgt->st_blocks = htog((uint64_t)host->st_blocks); + + if (fd == 1) + tgt->st_mode = htog((uint32_t)0x2190); + else + tgt->st_mode = htog((uint32_t)host->st_mode); + tgt->st_uid = htog((uint32_t)host->st_uid); + tgt->st_gid = htog((uint32_t)host->st_gid); + tgt->st_blksize = htog((uint32_t)host->st_blksize); + tgt->st_nlink = htog((uint32_t)host->st_nlink); + tgt->tgt_st_atime = htog((uint64_t)host->st_atime); + tgt->tgt_st_mtime = htog((uint64_t)host->st_mtime); + tgt->tgt_st_ctime = htog((uint64_t)host->st_ctime); +#if defined(STAT_HAVE_NSEC) tgt->st_atime_nsec = htog(host->st_atime_nsec); tgt->st_mtime_nsec = htog(host->st_mtime_nsec); tgt->st_ctime_nsec = htog(host->st_ctime_nsec); @@ -325,6 +336,7 @@ class Linux { tgt->st_mtime_nsec = 0; tgt->st_ctime_nsec = 0; #endif + tgt.copyOut(mem); } diff --git a/arch/alpha/alpha_tru64_process.cc b/arch/alpha/alpha_tru64_process.cc index 1a66d7499..5c24adad9 100644 --- a/arch/alpha/alpha_tru64_process.cc +++ b/arch/alpha/alpha_tru64_process.cc @@ -542,19 +542,19 @@ class Tru64 { { 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->st_dev = htog(host->st_dev); + tgt->st_ino = htog(host->st_ino); + tgt->st_mode = htog(host->st_mode); + tgt->st_nlink = htog(host->st_nlink); + tgt->st_uid = htog(host->st_uid); + tgt->st_gid = htog(host->st_gid); + tgt->st_rdev = htog(host->st_rdev); + tgt->st_size = htog(host->st_size); + tgt->st_atimeX = htog(host->st_atime); + tgt->st_mtimeX = htog(host->st_mtime); + tgt->st_ctimeX = htog(host->st_ctime); + tgt->st_blksize = htog(host->st_blksize); + tgt->st_blocks = htog(host->st_blocks); tgt.copyOut(mem); } @@ -571,14 +571,16 @@ class Tru64 { #if defined(__OpenBSD__) || defined(__APPLE__) || defined(__FreeBSD__) tgt->f_type = 0; #else - tgt->f_type = host->f_type; + tgt->f_type = htog(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; + tgt->f_bsize = htog(host->f_bsize); + tgt->f_blocks = htog(host->f_blocks); + tgt->f_bfree = htog(host->f_bfree); + tgt->f_bavail = htog(host->f_bavail); + tgt->f_files = htog(host->f_files); + tgt->f_ffree = htog(host->f_ffree); + + // Is this as string normally? memcpy(&tgt->f_fsid, &host->f_fsid, sizeof(host->f_fsid)); tgt.copyOut(mem); @@ -623,19 +625,19 @@ class Tru64 { { 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->st_dev = htog(host->st_dev); + tgt->st_ino = htog(host->st_ino); + tgt->st_mode = htog(host->st_mode); + tgt->st_nlink = htog(host->st_nlink); + tgt->st_uid = htog(host->st_uid); + tgt->st_gid = htog(host->st_gid); + tgt->st_rdev = htog(host->st_rdev); + tgt->st_size = htog(host->st_size); + tgt->st_atimeX = htog(host->st_atime); + tgt->st_mtimeX = htog(host->st_mtime); + tgt->st_ctimeX = htog(host->st_ctime); + tgt->st_blksize = htog(host->st_blksize); + tgt->st_blocks = htog(host->st_blocks); tgt.copyOut(mem); } @@ -674,21 +676,21 @@ class Tru64 { case Tru64::GSI_MAX_CPU: { TypedBufferArg<uint32_t> max_cpu(xc->getSyscallArg(1)); - *max_cpu = process->numCpus(); + *max_cpu = htog((uint32_t)process->numCpus()); max_cpu.copyOut(xc->mem); 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 = htog((uint32_t)process->numCpus()); cpus_in_box.copyOut(xc->mem); return 1; } case Tru64::GSI_PHYSMEM: { TypedBufferArg<uint64_t> physmem(xc->getSyscallArg(1)); - *physmem = 1024 * 1024; // physical memory in KB + *physmem = htog((uint64_t)1024 * 1024); // physical memory in KB physmem.copyOut(xc->mem); return 1; } @@ -696,15 +698,15 @@ class Tru64 { 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->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->mem); return 1; @@ -712,7 +714,7 @@ class Tru64 { case Tru64::GSI_PROC_TYPE: { TypedBufferArg<uint64_t> proc_type(xc->getSyscallArg(1)); - *proc_type = 11; + *proc_type = htog((uint64_t)11); proc_type.copyOut(xc->mem); return 1; } @@ -728,7 +730,7 @@ class Tru64 { case Tru64::GSI_CLK_TCK: { TypedBufferArg<uint64_t> clk_hz(xc->getSyscallArg(1)); - *clk_hz = 1024; + *clk_hz = htog((uint64_t)1024); clk_hz.copyOut(xc->mem); return 1; } @@ -824,7 +826,7 @@ class Tru64 { // just pass basep through uninterpreted. TypedBufferArg<int64_t> basep(tgt_basep); basep.copyIn(xc->mem); - long host_basep = (off_t)*basep; + long host_basep = (off_t)htog((int64_t)*basep); int host_result = getdirentries(fd, host_buf, tgt_nbytes, &host_basep); // check for error @@ -858,7 +860,7 @@ class Tru64 { delete [] host_buf; - *basep = host_basep; + *basep = htog((int64_t)host_basep); basep.copyOut(xc->mem); return tgt_buf_ptr - tgt_buf; @@ -879,14 +881,14 @@ class Tru64 { // 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; + regs->npc = htog(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->intRegFile[i] = htog(sc->sc_regs[i]); + regs->floatRegFile.q[i] = htog(sc->sc_fpregs[i]); } - regs->miscRegs.fpcr = sc->sc_fpcr; + regs->miscRegs.fpcr = htog(sc->sc_fpcr); return 0; } @@ -909,15 +911,15 @@ class Tru64 { 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->si_user = htog(curTick / (Clock::Frequency / clk_hz)); + elp->si_nice = htog(0); + elp->si_sys = htog(0); + elp->si_idle = htog(0); + elp->wait = htog(0); + elp->si_hz = htog(clk_hz); + elp->si_phz = htog(clk_hz); + elp->si_boottime = htog(seconds_since_epoch); // seconds since epoch? + elp->si_max_procs = htog(process->numCpus()); elp.copyOut(xc->mem); return 0; } @@ -952,9 +954,10 @@ class Tru64 { // 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); + if (htog(argp->address) == 0) { + argp->address = htog(process->next_thread_stack_base); + int stack_size = (htog(argp->rsize) + htog(argp->ysize) + + htog(argp->gsize)); process->next_thread_stack_base -= stack_size; argp.copyOut(xc->mem); } @@ -978,14 +981,14 @@ class Tru64 { attrp.copyIn(xc->mem); - if (attrp->nxm_version != NXM_LIB_VERSION) { + if (gtoh(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) { + if (gtoh(attrp->flags) != Tru64::NXM_TASK_INIT_VP) { cerr << "nxm_task_init: bad flag value " << attrp->flags << " (expected " << Tru64::NXM_TASK_INIT_VP << ")" << endl; abort(); @@ -1012,10 +1015,10 @@ class Tru64 { // 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->nxm_nslots_per_rad = htog(process->numCpus()); + config->nxm_nrads = htog(1); // only one RAD in our system! + config->nxm_slot_state = htog(slot_state_addr); + config->nxm_rad[0] = htog(rad_state_addr); config.copyOut(xc->mem); @@ -1024,6 +1027,8 @@ class Tru64 { slot_state_size); for (int i = 0; i < process->numCpus(); ++i) { // CPU 0 is bound to the calling process; all others are available + // XXX this code should have an endian conversion, but I don't think + // it works anyway slot_state[i] = (i == 0) ? Tru64::NXM_SLOT_BOUND : Tru64::NXM_SLOT_AVAIL; } @@ -1041,24 +1046,24 @@ class Tru64 { 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.sigmask = htog(0); + ssp->nxm_u.sig = htog(0); + ssp->nxm_u.flags = htog(0); + ssp->nxm_u.cancel_state = htog(0); ssp->nxm_u.nxm_ssig = 0; - ssp->nxm_bits = 0; + ssp->nxm_bits = htog(0); ssp->nxm_quantum = attrp->nxm_quantum; ssp->nxm_set_quantum = attrp->nxm_quantum; - ssp->nxm_sysevent = 0; + ssp->nxm_sysevent = htog(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; + ssp->nxm_u.pth_id = htog(uniq + gtoh(attrp->nxm_uniq_offset)); + ssp->nxm_u.nxm_active = htog(uniq | 1); } else { - ssp->nxm_u.pth_id = 0; - ssp->nxm_u.nxm_active = 0; + ssp->nxm_u.pth_id = htog(0); + ssp->nxm_u.nxm_active = htog(0); } } @@ -1067,7 +1072,7 @@ class Tru64 { // // copy pointer to shared config area out to user // - *configptr_ptr = config_addr; + *configptr_ptr = htog(config_addr); configptr_ptr.copyOut(xc->mem); // Register this as a valid address range with the process @@ -1084,13 +1089,13 @@ class Tru64 { { 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.intRegFile[ArgumentReg0] = gtoh(attrp->registers.a0); + ec->regs.intRegFile[27/*t12*/] = gtoh(attrp->registers.pc); + ec->regs.intRegFile[StackPointerReg] = gtoh(attrp->registers.sp); ec->regs.miscRegs.uniq = uniq_val; - ec->regs.pc = attrp->registers.pc; - ec->regs.npc = attrp->registers.pc + sizeof(MachInst); + ec->regs.pc = gtoh(attrp->registers.pc); + ec->regs.npc = gtoh(attrp->registers.pc) + sizeof(MachInst); ec->activate(); } @@ -1107,7 +1112,7 @@ class Tru64 { // get attribute args attrp.copyIn(xc->mem); - if (attrp->version != NXM_LIB_VERSION) { + if (gtoh(attrp->version) != NXM_LIB_VERSION) { cerr << "nxm_thread_create: thread library version mismatch! " << "got " << attrp->version << ", expected " << NXM_LIB_VERSION << endl; @@ -1132,28 +1137,28 @@ class Tru64 { rad_state_size); rad_state.copyIn(xc->mem); - uint64_t uniq_val = attrp->pthid - rad_state->nxm_uniq_offset; + uint64_t uniq_val = gtoh(attrp->pthid) - gtoh(rad_state->nxm_uniq_offset); - if (attrp->type == Tru64::NXM_TYPE_MANAGER) { + if (gtoh(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 = htog(99); kidp.copyOut(xc->mem); return 0; - } else if (attrp->type == Tru64::NXM_TYPE_VP) { + } else if (gtoh(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) + if (gtoh(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; + ssp->nxm_u.nxm_active = htog(uniq_val | 1); rad_state.copyOut(xc->mem); @@ -1173,6 +1178,8 @@ class Tru64 { fatal(""); } + // XXX This should have an endian conversion but I think this code + // doesn't work anyway slot_state[thread_index] = Tru64::NXM_SLOT_BOUND; slot_state.copyOut(xc->mem); @@ -1188,7 +1195,7 @@ class Tru64 { // 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 = htog(thread_index); kidp.copyOut(xc->mem); return 0; @@ -1320,9 +1327,9 @@ class Tru64 { lockp.copyIn(xc->mem); - if (*lockp == 0) { + if (gtoh(*lockp) == 0) { // lock is free: grab it - *lockp = 1; + *lockp = htog(1); lockp.copyOut(xc->mem); } else { // lock is busy: disable until free @@ -1375,9 +1382,9 @@ class Tru64 { lockp.copyIn(xc->mem); - if (*lockp == 0) { + if (gtoh(*lockp) == 0) { // lock is free: grab it - *lockp = 1; + *lockp = htog(1); lockp.copyOut(xc->mem); return 0; } else { @@ -1434,7 +1441,7 @@ class Tru64 { // user is supposed to acquire lock before entering lockp.copyIn(xc->mem); - assert(*lockp != 0); + assert(gtoh(*lockp) != 0); m5_unlock_mutex(lock_addr, process, xc); diff --git a/arch/alpha/isa/main.isa b/arch/alpha/isa/main.isa index baf2f2658..42fb29404 100644 --- a/arch/alpha/isa/main.isa +++ b/arch/alpha/isa/main.isa @@ -51,7 +51,7 @@ output exec {{ #include <math.h> #if FULL_SYSTEM -#include "arch/alpha/pseudo_inst.hh" +#include "sim/pseudo_inst.hh" #endif #include "base/fenv.hh" #include "config/ss_compatible_fp.hh" diff --git a/arch/alpha/isa/mem.isa b/arch/alpha/isa/mem.isa index 1f6907181..19785e3a8 100644 --- a/arch/alpha/isa/mem.isa +++ b/arch/alpha/isa/mem.isa @@ -164,9 +164,24 @@ def template LoadStoreDeclare {{ %(class_name)s(MachInst 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 @@ -267,6 +282,54 @@ def template LoadExecute {{ }}; +def template LoadInitiateAcc {{ + Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + Addr EA; + Fault fault = No_Fault; + %(mem_acc_type)s Mem = 0; + + %(fp_enable_check)s; + %(op_src_decl)s; + %(op_rd)s; + %(ea_code)s; + + if (fault == No_Fault) { + 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 = No_Fault; + %(mem_acc_type)s Mem = 0; + + %(fp_enable_check)s; + %(op_dest_decl)s; + + memcpy(&Mem, data, sizeof(Mem)); + + if (fault == No_Fault) { + %(memacc_code)s; + } + + if (fault == No_Fault) { + %(op_wb)s; + } + + return fault; + } +}}; + + def template StoreMemAccExecute {{ Fault * %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc, @@ -339,6 +402,60 @@ def template StoreExecute {{ } }}; +def template StoreInitiateAcc {{ + Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + Addr EA; + Fault fault = No_Fault; + uint64_t write_result = 0; + %(mem_acc_type)s Mem = 0; + + %(fp_enable_check)s; + %(op_src_decl)s; + %(op_rd)s; + %(ea_code)s; + + if (fault == No_Fault) { + %(memacc_code)s; + } + + if (fault == No_Fault) { + 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 = No_Fault; + uint64_t write_result = 0; + + %(fp_enable_check)s; + %(op_dest_decl)s; + + memcpy(&write_result, data, sizeof(write_result)); + + if (fault == No_Fault) { + %(postacc_code)s; + } + + if (fault == No_Fault) { + %(op_wb)s; + } + + return fault; + } +}}; + def template MiscMemAccExecute {{ Fault * %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc, @@ -380,6 +497,36 @@ def template MiscExecute {{ } }}; +def template MiscInitiateAcc {{ + Fault %(class_name)s::initiateAcc(%(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; + %(ea_code)s; + + if (fault == No_Fault) { + %(memacc_code)s; + } + + return No_Fault; + } +}}; + + +def template MiscCompleteAcc {{ + Fault %(class_name)s::completeAcc(uint8_t *data, + %(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + return No_Fault; + } +}}; + // load instructions use Ra as dest, so check for // Ra == 31 to detect nops def template LoadNopCheckDecode {{ @@ -455,13 +602,17 @@ def LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, # 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)) + + fullExecTemplate.subst(iop) + + initiateAccTemplate.subst(iop) + + completeAccTemplate.subst(iop)) }}; diff --git a/arch/isa_parser.py b/arch/isa_parser.py index 030bb5a7c..96d3e8438 100755 --- a/arch/isa_parser.py +++ b/arch/isa_parser.py @@ -1138,6 +1138,7 @@ class Operand(object): # template must be careful not to use it if it doesn't apply. if self.isMem(): self.mem_acc_size = self.makeAccSize() + self.mem_acc_type = self.ctype # Finalize additional fields (primarily code fields). This step # is done separately since some of these fields may depend on the @@ -1148,15 +1149,23 @@ class Operand(object): self.constructor = self.makeConstructor() self.op_decl = self.makeDecl() + if self.isMem(): + self.is_src = '' + self.is_dest = '' + if self.is_src: self.op_rd = self.makeRead() + self.op_src_decl = self.makeDecl() else: self.op_rd = '' + self.op_src_decl = '' if self.is_dest: self.op_wb = self.makeWrite() + self.op_dest_decl = self.makeDecl() else: self.op_wb = '' + self.op_dest_decl = '' def isMem(self): return 0 @@ -1589,6 +1598,14 @@ class CodeBlock: self.op_decl = self.operands.concatAttrStrings('op_decl') + is_src = lambda op: op.is_src + is_dest = lambda op: op.is_dest + + self.op_src_decl = \ + self.operands.concatSomeAttrStrings(is_src, 'op_src_decl') + self.op_dest_decl = \ + self.operands.concatSomeAttrStrings(is_dest, 'op_dest_decl') + self.op_rd = self.operands.concatAttrStrings('op_rd') self.op_wb = self.operands.concatAttrStrings('op_wb') @@ -1596,6 +1613,7 @@ class CodeBlock: if self.operands.memOperand: self.mem_acc_size = self.operands.memOperand.mem_acc_size + self.mem_acc_type = self.operands.memOperand.mem_acc_type # Make a basic guess on the operand class (function unit type). # These are good enough for most cases, and will be overridden diff --git a/arch/mips/SConscript b/arch/mips/SConscript new file mode 100644 index 000000000..bd67c98e9 --- /dev/null +++ b/arch/mips/SConscript @@ -0,0 +1,81 @@ +# -*- 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 + +# Import build environment variable from SConstruct. +Import('env') + +################################################### +# +# Define needed sources. +# +################################################### + +# Base sources used by all configurations. +arch_base_sources = Split(''' + arch/mips/decoder.cc + arch/mips/alpha_o3_exec.cc + arch/mips/fast_cpu_exec.cc + arch/mips/simple_cpu_exec.cc + arch/mips/full_cpu_exec.cc + arch/mips/faults.cc + arch/mips/isa_traits.cc + ''') + +# Full-system sources +arch_full_system_sources = Split(''' + arch/mips/alpha_memory.cc + arch/mips/arguments.cc + arch/mips/ev5.cc + arch/mips/osfpal.cc + arch/mips/stacktrace.cc + arch/mips/vtophys.cc + ''') + +# Syscall emulation (non-full-system) sources +arch_syscall_emulation_sources = Split(''' + arch/mips/alpha_common_syscall_emul.cc + arch/mips/alpha_linux_process.cc + arch/mips/alpha_tru64_process.cc + ''') + +# Set up complete list of sources based on configuration. +sources = arch_base_sources + +if env['FULL_SYSTEM']: + sources += arch_full_system_sources +else: + sources += arch_syscall_emulation_sources + +for opt in env.ExportOptions: + env.ConfigFile(opt) + +Return('sources') diff --git a/arch/mips/isa/bitfields.isa b/arch/mips/isa/bitfields.isa index 94a8a6467..bead9c151 100644 --- a/arch/mips/isa/bitfields.isa +++ b/arch/mips/isa/bitfields.isa @@ -15,6 +15,7 @@ def bitfield RT_HI <20:19>; def bitfield RT_LO <18:16>; def bitfield RS <25:21>; +def bitfield RS_MSB <25:25>; def bitfield RS_HI <25:24>; def bitfield RS_LO <23:21>; diff --git a/arch/mips/isa/decoder.isa b/arch/mips/isa/decoder.isa index d6fd90657..6bb5bf4d8 100644 --- a/arch/mips/isa/decoder.isa +++ b/arch/mips/isa/decoder.isa @@ -9,7 +9,7 @@ // //@todo: Distinguish "unknown/future" use insts from "reserved" // ones -decode OPCODE_HI default FailUnimpl::unknown() { +decode OPCODE_HI default Unknown::unknown() { // Derived From ... Table A-2 MIPS32 ISA Manual 0x0: decode OPCODE_LO default FailUnimpl::reserved(){ @@ -66,10 +66,11 @@ decode OPCODE_HI default FailUnimpl::unknown() { 0x3: movn({{ if (Rt != 0) Rd = Rs; }}); } + format WarnUnimpl { - 0x4: syscall({{ xc->syscall()}},IsNonSpeculative); - 0x5: break({{ }}); - 0x7: sync({{ }}); + 0x4: syscall();//{{ xc->syscall()}},IsNonSpeculative + 0x5: break(); + 0x7: sync(); } } @@ -80,14 +81,14 @@ decode OPCODE_HI default FailUnimpl::unknown() { 0x2: mflo({{ Rd = xc->miscRegs.lo; }}); 0x3: mtlo({{ xc->miscRegs.lo = Rs; }}); } - }; + } 0x3: decode FUNCTION_LO { format IntOp { 0x0: mult({{ INT64 temp1 = Rs.sw * Rt.sw; xc->miscRegs.hi->temp1<63:32>; - xc->miscRegs.lo->temp1<31:0> + xc->miscRegs.lo->temp1<31:0>; }}); 0x1: multu({{ @@ -107,7 +108,7 @@ decode OPCODE_HI default FailUnimpl::unknown() { xc->miscRegs.lo = Rs.uw / Rt.uw; }}); } - }; + } 0x4: decode FUNCTION_LO { format IntOp { @@ -127,7 +128,7 @@ decode OPCODE_HI default FailUnimpl::unknown() { 0x2: slt({{ Rd.sw = ( Rs.sw < Rt.sw ) ? 1 : 0}}); 0x3: sltu({{ Rd.uw = ( Rs.uw < Rt.uw ) ? 1 : 0}}); } - }; + } 0x6: decode FUNCTION_LO { format Trap { @@ -143,13 +144,13 @@ decode OPCODE_HI default FailUnimpl::unknown() { 0x1: decode REGIMM_HI { 0x0: decode REGIMM_LO { - format Branch { - 0x0: bltz({{ cond = (Rs.sq < 0); }}); - 0x1: bgez({{ cond = (Rs.sq >= 0); }}); + format CondBranch { + 0x0: bltz({{ cond = (Rs.sw < 0); }}); + 0x1: bgez({{ cond = (Rs.sw >= 0); }}); //MIPS obsolete instructions - 0x2: bltzl({{ cond = (Rs.sq < 0); }}); - 0x3: bgezl({{ cond = (Rs.sq >= 0); }}); + 0x2: bltzl({{ cond = (Rs.sw < 0); }}); + 0x3: bgezl({{ cond = (Rs.sw >= 0); }}); } } @@ -165,19 +166,19 @@ decode OPCODE_HI default FailUnimpl::unknown() { } 0x2: decode REGIMM_LO { - format Branch { - 0x0: bltzal({{ cond = (Rs.sq < 0); }}); - 0x1: bgezal({{ cond = (Rs.sq >= 0); }}); + format CondBranch { + 0x0: bltzal({{ cond = (Rs.sw < 0); }}); + 0x1: bgezal({{ cond = (Rs.sw >= 0); }}); //MIPS obsolete instructions - 0x2: bltzall({{ cond = (Rs.sq < 0); }}); - 0x3: bgezall({{ cond = (Rs.sq >= 0); }}); + 0x2: bltzall({{ cond = (Rs.sw < 0); }}); + 0x3: bgezall({{ cond = (Rs.sw >= 0); }}); } } 0x3: decode REGIMM_LO { format WarnUnimpl { - 0x7: synci({{ }}); + 0x7: synci(); } } } @@ -187,13 +188,13 @@ decode OPCODE_HI default FailUnimpl::unknown() { 0x3: jal(IsCall); } - format Branch { - 0x4: beq({{ cond = (Rs.sq == 0); }}); - 0x5: bne({{ cond = (Rs.sq != 0); }}); - 0x6: blez({{ cond = (Rs.sq <= 0); }}); - 0x7: bgtz({{ cond = (Rs.sq > 0); }}); + format CondBranch { + 0x4: beq({{ cond = (Rs.sw == 0); }}); + 0x5: bne({{ cond = (Rs.sw != 0); }}); + 0x6: blez({{ cond = (Rs.sw <= 0); }}); + 0x7: bgtz({{ cond = (Rs.sw > 0); }}); } - }; + } 0x1: decode OPCODE_LO default FailUnimpl::reserved(){ format IntOp { @@ -205,8 +206,8 @@ decode OPCODE_HI default FailUnimpl::unknown() { 0x5: ori({{ Rt.sw = Rs.sw | INTIMM;}}); 0x6: xori({{ Rt.sw = Rs.sw ^ INTIMM;}}); 0x7: lui({{ Rt = INTIMM << 16}}); - }; - }; + } + } 0x2: decode OPCODE_LO default FailUnimpl::reserved(){ @@ -229,7 +230,7 @@ decode OPCODE_HI default FailUnimpl::unknown() { Rt = xc->miscRegs.cop0[reg_num]; }}); - 0xC: mtc0({{ + 0x4: mtc0({{ //The contents of the coprocessor 0 register specified by the //combination of rd and sel are loaded into general register //rt. Note that not all coprocessor 0 registers support the @@ -243,6 +244,25 @@ decode OPCODE_HI default FailUnimpl::unknown() { xc->miscRegs.cop0[reg_num] = Rt; }}); + 0x8: mftr({{ + //The contents of the coprocessor 0 register specified by the + //combination of rd and sel are loaded into general register + //rt. Note that not all coprocessor 0 registers support the + //sel field. In those instances, the sel field must be zero. + + //MT Code Needed Here + }}); + + 0xC: mttr({{ + //The contents of the coprocessor 0 register specified by the + //combination of rd and sel are loaded into general register + //rt. Note that not all coprocessor 0 registers support the + //sel field. In those instances, the sel field must be zero. + + //MT Code Needed Here + }}); + + 0xA: rdpgpr({{ //Accessing Previous Shadow Set Register Number uint64_t prev = xc->miscRegs.cop0[SRSCtl][PSS]; @@ -252,23 +272,52 @@ decode OPCODE_HI default FailUnimpl::unknown() { }}); } - 0xB: decode SC { - format BasicOp { - 0x0: di({{ - //Accessing Coprocessor 0 "Status" Register - Rt.sw = xc->miscRegs.cop0[12]; - xc->miscRegs.cop0[12][INTERRUPT_ENABLE] = 0; + 0xB: decode RD { + + 0x0: decode SC { + format BasicOp { + 0x0: dvpe({{ + Rt.sw = xc->miscRegs.cop0.MVPControl; + xc->miscRegs.cop0.MVPControl[EVP] = 0; }}); - 0x1: ei({{ - //Accessing Coprocessor 0 "Status" Register - Rt.sw = xc->miscRegs.cop0[12]; - xc->miscRegs.cop0[12][INTERRUPT_ENABLE] = 1; + 0x1: evpe({{ + Rt.sw = xc->miscRegs.cop0.MVPControl; + xc->miscRegs.cop0.MVPControl[EVP] = 1; }}); + } + } + + 0x1: decode SC { + format BasicOp { + 0x0: dmt({{ + Rt.sw = xc->miscRegs.cop0.VPEControl; + xc->miscRegs.cop0.VPEControl[THREAD_ENABLE] = 0; + }}); + + 0x1: emt({{ + Rt.sw = xc->miscRegs.cop0.VPEControl; + xc->miscRegs.cop0.VPEControl[THREAD_ENABLE] = 1; + }}); + } + } + + 0xC: decode SC { + format BasicOp { + 0x0: di({{ + Rt.sw = xc->miscRegs.cop0.Status; + xc->miscRegs.cop0.Status[INTERRUPT_ENABLE] = 0; + }}); + + 0x1: ei({{ + Rt.sw = xc->miscRegs.cop0.Status; + xc->miscRegs.cop0.Status[INTERRUPT_ENABLE] = 1; + }}); + } + } } - } - 0xE: BasicOp::wrpgpr({{ + 0xE: BasicOp::wrpgpr({{ //Accessing Previous Shadow Set Register Number uint64_t prev = xc->miscRegs.cop0[SRSCtl][PSS]; uint64_t reg_num = Rd.uw; @@ -287,9 +336,9 @@ decode OPCODE_HI default FailUnimpl::unknown() { } format WarnUnimpl { - 0x18: eret({{ }}); - 0x1F: deret({{ }}); - 0x20: wait({{ }}); + 0x18: eret(); + 0x1F: deret(); + 0x20: wait(); } } } @@ -311,14 +360,14 @@ decode OPCODE_HI default FailUnimpl::unknown() { 0x1: decode ND { 0x0: decode TF { - format Branch { + format CondBranch { 0x0: bc1f({{ cond = (xc->miscRegs.fpcr == 0); }}); 0x1: bc1t({{ cond = (xc->miscRegs.fpcr == 1); }}); } } 0x1: decode TF { - format Branch { + format CondBranch { 0x0: bc1fl({{ cond = (xc->miscRegs.fpcr == 0); }}); 0x1: bc1tl({{ cond = (xc->miscRegs.fpcr == 1); }}); } @@ -346,7 +395,7 @@ decode OPCODE_HI default FailUnimpl::unknown() { } 0x1: decode RS_LO { - //only legal for 64 bit + //only legal for 64 bit-FP format Float64Op { 0x0: round_l_s({{ Fd = convert_and_round(Fs.sf,RND_NEAREST,FP_LONG,FP_SINGLE);}}); 0x1: trunc_l_s({{ Fd = convert_and_round(Fs.sf,RND_ZERO,FP_LONG,FP_SINGLE);}}); @@ -377,18 +426,21 @@ decode OPCODE_HI default FailUnimpl::unknown() { format Float64Op { 0x2: recips({{ Fd = 1 / Fs; }}); - 0x3: rsqrts{{ Fd = 1 / sqrt(Fs); }}); + 0x3: rsqrts({{ Fd = 1 / sqrt(Fs.ud);}}); } } 0x4: decode RS_LO { - 0x1: cvt_d_s({{ int rnd_mode = xc->miscRegs.fcsr; + + format FloatOp { + 0x1: cvt_d_s({{ int rnd_mode = xc->miscRegs.fcsr; Fd = convert_and_round(Fs.sf,rnd_mode,FP_DOUBLE,FP_SINGLE); }}); - 0x4: cvt_w_s({{ int rnd_mode = xc->miscRegs.fcsr; + 0x4: cvt_w_s({{ int rnd_mode = xc->miscRegs.fcsr; Fd = convert_and_round(Fs.sf,rnd_mode,FP_WORD,FP_SINGLE); }}); + } //only legal for 64 bit format Float64Op { @@ -418,7 +470,7 @@ decode OPCODE_HI default FailUnimpl::unknown() { 0x1: decode RS_LO { //only legal for 64 bit - format FloatOp64 { + format Float64Op { 0x0: round_l_d({{ Fd = convert_and_round(Fs.df,RND_NEAREST,FP_LONG,FP_DOUBLE); }}); 0x1: trunc_l_d({{ Fd = convert_and_round(Fs.df,RND_ZERO,FP_LONG,FP_DOUBLE);}}); 0x2: ceil_l_d({{ Fd = convert_and_round(Fs.df,RND_UP,FP_LONG,FP_DOUBLE);}}); @@ -446,9 +498,9 @@ decode OPCODE_HI default FailUnimpl::unknown() { 0x3: movn({{ if (Rt != 0) Fd.df = Fs.df; }}); } - format FloatOp64 { + format Float64Op { 0x5: recipd({{ Fd.df = 1 / Fs.df}}); - 0x6: rsqrtd{{ Fd.df = 1 / sqrt(Fs.df) }}); + 0x6: rsqrtd({{ Fd.df = 1 / sqrt(Fs.df) }}); } } @@ -466,7 +518,7 @@ decode OPCODE_HI default FailUnimpl::unknown() { } //only legal for 64 bit - format FloatOp64 { + format Float64Op { 0x5: cvt_l_d({{ int rnd_mode = xc->miscRegs.fcsr; Fd = convert_and_round(Fs.df,rnd_mode,FP_LONG,FP_DOUBLE); @@ -512,7 +564,7 @@ decode OPCODE_HI default FailUnimpl::unknown() { //are enabled. " 0x6: decode RS_HI { 0x0: decode RS_LO { - format FloatOp64 { + format Float64Op { 0x0: addps({{ //Must Check for Exception Here... Supposed to Operate on Upper and //Lower Halves Independently but we take simulator shortcut Fd.df = Fs.df + Ft.df; @@ -547,23 +599,23 @@ decode OPCODE_HI default FailUnimpl::unknown() { 0x2: decode RS_LO { 0x1: decode MOVCF { - format FloatOp64 { - 0x0: movfps({{ if ( FPConditionCode(CC) == 0) Fd = Fs;}}) - 0x1: movtps({{ if ( FPConditionCode(CC) == 0) Fd = Fs;}}) + format Float64Op { + 0x0: movfps({{ if ( FPConditionCode(CC) == 0) Fd = Fs;}}); + 0x1: movtps({{ if ( FPConditionCode(CC) == 0) Fd = Fs;}}); } } } 0x4: decode RS_LO { - 0x0: FloatOp64::cvt_s_pu({{ + 0x0: Float64Op::cvt_s_pu({{ int rnd_mode = xc->miscRegs.fcsr; Fd = convert_and_round(Fs.df,rnd_mode,FP_DOUBLE,FP_PS_HI); }}); } 0x5: decode RS_LO { - format FloatOp64 { + format Float64Op { 0x0: cvt_s_pl({{ int rnd_mode = xc->miscRegs.fcsr; Fd = convert_and_round(Fs.df,rnd_mode,FP_SINGLE,FP_PS_LO); @@ -582,27 +634,27 @@ decode OPCODE_HI default FailUnimpl::unknown() { 0x0: decode RS_HI { 0x0: decode RS_LO { format WarnUnimpl { - 0x0: mfc2({{ }}); - 0x2: cfc2({{ }}); - 0x3: mfhc2({{ }}); - 0x4: mtc2({{ }}); - 0x6: ctc2({{ }}); - 0x7: mftc2({{ }}); + 0x0: mfc2(); + 0x2: cfc2(); + 0x3: mfhc2(); + 0x4: mtc2(); + 0x6: ctc2(); + 0x7: mftc2(); } } 0x1: decode ND { 0x0: decode TF { format WarnUnimpl { - 0x0: bc2f({{ cond = (xc->miscRegs.cop2cc == 0); }}, COP2); - 0x1: bc2t({{ cond = (xc->miscRegs.cop2cc == 1); }}, COP2}}); + 0x0: bc2f(); + 0x1: bc2t(); } } 0x1: decode TF { format WarnUnimpl { - 0x0: bc2fl({{ cond = (xc->miscRegs.cop2cc == 0); }}, COP2}}); - 0x1: bc2tl({{ cond = (xc->miscRegs.cop2cc == 1); }}, COP2}}); + 0x0: bc2fl(); + 0x1: bc2tl(); } } } @@ -632,12 +684,13 @@ decode OPCODE_HI default FailUnimpl::unknown() { EA = Rs + Rt; }}, {{ Mem.df = Ft<63:0>;}}); - 0x7: prefx({{ }}); } + + 0x7: WarnUnimpl::prefx(); } format FloatOp { - 0x3: WarnUnimpl::alnv_ps({{ }}); + 0x3: WarnUnimpl::alnv_ps(); format BasicOp { 0x4: decode FUNCTION_LO { @@ -684,13 +737,13 @@ decode OPCODE_HI default FailUnimpl::unknown() { } //MIPS obsolete instructions - format Branch { - 0x4: beql({{ cond = (Rs.sq == 0); }}); - 0x5: bnel({{ cond = (Rs.sq != 0); }}); - 0x6: blezl({{ cond = (Rs.sq <= 0); }}); - 0x7: bgtzl({{ cond = (Rs.sq > 0); }}); + format CondBranch { + 0x4: beql({{ cond = (Rs.sw == 0); }}); + 0x5: bnel({{ cond = (Rs.sw != 0); }}); + 0x6: blezl({{ cond = (Rs.sw <= 0); }}); + 0x7: bgtzl({{ cond = (Rs.sw > 0); }}); } - }; + } 0x3: decode OPCODE_LO default FailUnimpl::reserved() { @@ -758,7 +811,7 @@ decode OPCODE_HI default FailUnimpl::unknown() { } 0x7: decode FUNCTION_LO { - 0x7: WarnUnimpl::sdbbp({{ }}); + 0x7: WarnUnimpl::sdbbp(); } } @@ -767,15 +820,23 @@ decode OPCODE_HI default FailUnimpl::unknown() { 0x0: decode FUNCTION_LO { format WarnUnimpl { - 0x1: ext({{ }}); - 0x4: ins({{ }}); + 0x1: ext(); + 0x4: ins(); + } + } + + 0x1: decode FUNCTION_LO { + format WarnUnimpl { + 0x0: fork(); + 0x1: yield(); } } + //Table A-10 MIPS32 BSHFL Encoding of sa Field 0x4: decode SA { - 0x02: WarnUnimpl::wsbh({{ }}); + 0x02: WarnUnimpl::wsbh(); format BasicOp { 0x10: seb({{ Rd.sw = /* sext32(Rt<7>,24) | */ Rt<7:0>}}); @@ -787,53 +848,53 @@ decode OPCODE_HI default FailUnimpl::unknown() { 0x7: BasicOp::rdhwr({{ Rt = xc->hwRegs[RD];}}); } } - }; + } 0x4: decode OPCODE_LO default FailUnimpl::reserved() { format Memory { 0x0: lb({{ EA = Rs + disp; }}, {{ Rb.sw = Mem.sb; }}); 0x1: lh({{ EA = Rs + disp; }}, {{ Rb.sw = Mem.sh; }}); - 0x2: lwl({{ EA = Rs + disp; }}, {{ Rb.sw = Mem.sw; }}, WordAlign); + 0x2: lwl({{ EA = Rs + disp; }}, {{ Rb.sw = Mem.sw; }});//, WordAlign); 0x3: lw({{ EA = Rs + disp; }}, {{ Rb.uq = Mem.sb; }}); 0x4: lbu({{ EA = Rs + disp; }}, {{ Rb.uw = Mem.ub; }}); 0x5: lhu({{ EA = Rs + disp; }}, {{ Rb.uw = Mem.uh; }}); - 0x6: lwr({{ EA = Rs + disp; }}, {{ Rb.uw = Mem.uw; }}, WordAlign); - }; + 0x6: lwr({{ EA = Rs + disp; }}, {{ Rb.uw = Mem.uw; }});//, WordAlign); + } - 0x7: FailUnimpl::reserved({{ }}); - }; + 0x7: FailUnimpl::reserved(); + } 0x5: decode OPCODE_LO default FailUnimpl::reserved() { format Memory { 0x0: sb({{ EA = Rs + disp; }}, {{ Mem.ub = Rt<7:0>; }}); 0x1: sh({{ EA = Rs + disp; }},{{ Mem.uh = Rt<15:0>; }}); - 0x2: swl({{ EA = Rs + disp; }},{{ Mem.ub = Rt<31:0>; }},WordAlign); + 0x2: swl({{ EA = Rs + disp; }},{{ Mem.ub = Rt<31:0>; }});//,WordAlign); 0x3: sw({{ EA = Rs + disp; }},{{ Mem.ub = Rt<31:0>; }}); - 0x6: swr({{ EA = Rs + disp; }},{{ Mem.ub = Rt<31:0>; }},WordAlign); - }; + 0x6: swr({{ EA = Rs + disp; }},{{ Mem.ub = Rt<31:0>; }});//,WordAlign); + } format WarnUnimpl { - 0x7: cache({{ }}); - }; + 0x7: cache(); + } - }; + } 0x6: decode OPCODE_LO default FailUnimpl::reserved() { - 0x0: WarnUnimpl::ll({{ }}); + 0x0: WarnUnimpl::ll(); format Memory { 0x1: lwc1({{ EA = Rs + disp; }},{{ Ft<31:0> = Mem.uf; }}); 0x5: ldc1({{ EA = Rs + disp; }},{{ Ft<63:0> = Mem.df; }}); - }; - }; + } + } 0x7: decode OPCODE_LO default FailUnimpl::reserved() { - 0x0: WarnUnimpl::sc({{ }}); + 0x0: WarnUnimpl::sc(); format Memory { 0x1: swc1({{ EA = Rs + disp; }},{{ Mem.uf = Ft<31:0>; }}); 0x5: sdc1({{ EA = Rs + disp; }},{{ Mem.df = Ft<63:0>; }}); - }; + } } } diff --git a/arch/mips/isa/formats.isa b/arch/mips/isa/formats.isa index 404314c7a..20ef49d82 100644 --- a/arch/mips/isa/formats.isa +++ b/arch/mips/isa/formats.isa @@ -1,22 +1,29 @@ //Include the basic format //Templates from this format are used later -##include "m5/arch/mips/isa_desc/formats/basic.format" +##include "m5/arch/mips/isa/formats/basic.isa" //Include the integerOp and integerOpCc format -##include "m5/arch/mips/isa_desc/formats/integerop.format" +##include "m5/arch/mips/isa/formats/int.isa" //Include the floatOp format -##include "m5/arch/mips/isa_desc/formats/floatop.format" +##include "m5/arch/mips/isa/formats/fp.isa" //Include the mem format -##include "m5/arch/mips/isa_desc/formats/mem.format" +##include "m5/arch/mips/isa/formats/mem.isa" //Include the trap format -##include "m5/arch/mips/isa_desc/formats/trap.format" +##include "m5/arch/mips/isa/formats/trap.isa" //Include the branch format -##include "m5/arch/mips/isa_desc/formats/branch.format" +##include "m5/arch/mips/isa/formats/branch.isa" //Include the noop format -##include "m5/arch/mips/isa_desc/formats/noop.format" +##include "m5/arch/mips/isa/formats/noop.isa" + + +//Include the noop format +##include "m5/arch/mips/isa/formats/unimp.isa" + +//Include the noop format +##include "m5/arch/mips/isa/formats/unknown.isa" diff --git a/arch/mips/isa/formats/basic.isa b/arch/mips/isa/formats/basic.isa index 8fba9845a..fc97c6ffa 100644 --- a/arch/mips/isa/formats/basic.isa +++ b/arch/mips/isa/formats/basic.isa @@ -56,7 +56,7 @@ def template BasicDecodeWithMnemonic {{ }}; // The most basic instruction format... used only for a few misc. insts -def format BasicOperate(code, *flags) {{ +def format BasicOp(code, *flags) {{ iop = InstObjParams(name, Name, 'MipsStaticInst', CodeBlock(code), flags) header_output = BasicDeclare.subst(iop) decoder_output = BasicConstructor.subst(iop) diff --git a/arch/mips/isa/formats/branch.isa b/arch/mips/isa/formats/branch.isa index a565eb71b..e9c790c53 100644 --- a/arch/mips/isa/formats/branch.isa +++ b/arch/mips/isa/formats/branch.isa @@ -1,57 +1,212 @@ -//////////////////////////////////////////////////////////////////// +// -*- mode:c++ -*- + +// Copyright (c) 2003-2005 The Regents of The University of Michigan +// All rights reserved. // -// Branch instructions +// 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 operations. - */ - class Branch : public MipsStaticInst + + /** + * 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) { - protected: + } - /// Constructor - Branch(const char *mnem, MachInst _machInst, OpClass __opClass) : MipsStaticInst(mnem, _machInst, __opClass) - { - } + const std::string & + disassemble(Addr pc, const SymbolTable *symtab) const; + }; - std::string generateDisassembly(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; -output decoder {{ - std::string Branch::generateDisassembly(Addr pc, const SymbolTable *symtab) const + /// 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) { - return "Disassembly of integer instruction\n"; } + + Addr branchTarget(ExecContext *xc) const; + + std::string + generateDisassembly(Addr pc, const SymbolTable *symtab) const; + }; }}; -def template BranchExecute {{ - Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) 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) { - //Attempt to execute the instruction - try - { - checkPriv; - - %(op_decl)s; - %(op_rd)s; - %(code)s; - } - //If we have an exception for some reason, - //deal with it - catch(MipsException except) - { - //Deal with exception - return No_Fault; - } - - //Write the resulting state to the execution context - %(op_wb)s; - - return No_Fault; + 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) {{ @@ -64,3 +219,41 @@ def format CondBranch(code) {{ 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/mips/isa/formats/fp.isa b/arch/mips/isa/formats/fp.isa index 707109fc2..23fcbaa67 100644 --- a/arch/mips/isa/formats/fp.isa +++ b/arch/mips/isa/formats/fp.isa @@ -27,7 +27,7 @@ output decoder {{ } }}; -def template FPExecute {{ +def template FloatingPointExecute {{ Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const { //These are set to constants when the execute method @@ -70,7 +70,7 @@ def template FPExecute {{ }}; // Primary format for integer operate instructions: -def format FPOp(code, *opt_flags) {{ +def format FloatOp(code, *opt_flags) {{ orig_code = code cblk = CodeBlock(code) checkPriv = (code.find('checkPriv') != -1) @@ -86,12 +86,33 @@ def format FPOp(code, *opt_flags) {{ header_output = BasicDeclare.subst(iop) decoder_output = BasicConstructor.subst(iop) decode_block = BasicDecodeWithMnemonic.subst(iop) - exec_output = IntegerExecute.subst(iop) + exec_output = FloatingPointExecute.subst(iop) +}}; + +// Primary format for integer operate instructions: +def format Float64Op(code, *opt_flags) {{ + orig_code = code + cblk = CodeBlock(code) + checkPriv = (code.find('checkPriv') != -1) + code.replace('checkPriv', '') + if checkPriv: + code.replace('checkPriv;', 'if(!xc->regs.miscRegFile.pstateFields.priv) throw privileged_opcode;') + else: + code.replace('checkPriv;', '') + for (marker, value) in (('ivValue', '0'), ('icValue', '0'), + ('xvValue', '0'), ('xcValue', '0')): + code.replace(marker, value) + iop = InstObjParams(name, Name, 'MipsStaticInst', cblk, opt_flags) + header_output = BasicDeclare.subst(iop) + decoder_output = BasicConstructor.subst(iop) + decode_block = BasicDecodeWithMnemonic.subst(iop) + exec_output = FloatingPointExecute.subst(iop) }}; // Primary format for integer operate instructions: def format FPOpCc(code, icValue, ivValue, xcValue, xvValue, *opt_flags) {{ orig_code = code + cblk = CodeBlock(code) checkPriv = (code.find('checkPriv') != -1) code.replace('checkPriv', '') diff --git a/arch/mips/isa/formats/int.isa b/arch/mips/isa/formats/int.isa index 5b8df54e9..521f3a130 100644 --- a/arch/mips/isa/formats/int.isa +++ b/arch/mips/isa/formats/int.isa @@ -53,9 +53,9 @@ def format IntOp(code, *opt_flags) {{ orig_code = code cblk = CodeBlock(code) - //Figure out if we are creating a IntImmOp or a IntOp + # Figure out if we are creating a IntImmOp or a IntOp strlen = len(name) - if ( name[strlen-1] = 'i' or ( name[strlen-2:] = 'iu')) + if name[strlen-1] == 'i' or name[strlen-2:] == 'iu': iop = InstObjParams(name, Name, 'IntOp', cblk, opt_flags) else: iop = InstObjParams(name, Name, 'IntImmOp', cblk, opt_flags) diff --git a/arch/mips/isa/formats/mem.isa b/arch/mips/isa/formats/mem.isa index 5ed5237c5..e3028eb7c 100644 --- a/arch/mips/isa/formats/mem.isa +++ b/arch/mips/isa/formats/mem.isa @@ -55,7 +55,7 @@ def template MemExecute {{ }}; // Primary format for integer operate instructions: -def format Mem(code, *opt_flags) {{ +def format Memory(code, ea_code = {{ EA = Rb + disp; }},*opt_flags) {{ orig_code = code cblk = CodeBlock(code) iop = InstObjParams(name, Name, 'MipsStaticInst', cblk, opt_flags) diff --git a/arch/mips/isa/formats/noop.isa b/arch/mips/isa/formats/noop.isa index b1ece654d..6d45ba9b6 100644 --- a/arch/mips/isa/formats/noop.isa +++ b/arch/mips/isa/formats/noop.isa @@ -45,3 +45,90 @@ def format Noop(code, *opt_flags) {{ decode_block = BasicDecodeWithMnemonic.subst(iop) exec_output = NoopExecute.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) +}}; + diff --git a/arch/mips/isa/formats/unimp.isa b/arch/mips/isa/formats/unimp.isa new file mode 100644 index 000000000..767888157 --- /dev/null +++ b/arch/mips/isa/formats/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, 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; + }; +}}; + diff --git a/arch/mips/isa/formats/unknown.isa b/arch/mips/isa/formats/unknown.isa new file mode 100644 index 000000000..6eba5b4f9 --- /dev/null +++ b/arch/mips/isa/formats/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 Unimplemented_Opcode_Fault; + } +}}; + +def format Unknown() {{ + decode_block = 'return new Unknown(machInst);\n' +}}; + diff --git a/arch/mips/isa/main.isa b/arch/mips/isa/main.isa index a8c71872b..411e398b4 100644 --- a/arch/mips/isa/main.isa +++ b/arch/mips/isa/main.isa @@ -26,7 +26,7 @@ // (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 "m5/arch/sparc/isa_desc/includes.h" +##include "m5/arch/mips/isa/includes.isa" //////////////////////////////////////////////////////////////////// // @@ -37,16 +37,16 @@ namespace MipsISA; //Include the bitfield definitions -##include "m5/arch/mips/isa_desc/bitfields.h" +##include "m5/arch/mips/isa/bitfields.isa" //Include the operand_types and operand definitions -##include "m5/arch/mips/isa_desc/operands.h" +##include "m5/arch/mips/isa/operands.isa" //Include the base class for mips instructions, and some support code -##include "m5/arch/mips/isa_desc/base.h" +##include "m5/arch/mips/isa/base.isa" //Include the definitions for the instruction formats -##include "m5/arch/mips/isa_desc/formats.h" +##include "m5/arch/mips/isa/formats.isa" //Include the decoder definition -##include "m5/arch/mips/isa_desc/decoder.h" +##include "m5/arch/mips/isa/decoder.isa" diff --git a/arch/mips/isa/operands.isa b/arch/mips/isa/operands.isa index c8e08a436..cf6f10e0b 100644 --- a/arch/mips/isa/operands.isa +++ b/arch/mips/isa/operands.isa @@ -5,8 +5,8 @@ def operand_types {{ 'uhw' : ('unsigned int', 16), 'sw' : ('signed int', 32), 'uw' : ('unsigned int', 32), - 'sdw' : ('signed int', 64), - 'udw' : ('unsigned int', 64), + 'sd' : ('signed int', 64), + 'ud' : ('unsigned int', 64), 'sf' : ('float', 32), 'df' : ('float', 64), 'qf' : ('float', 128) @@ -24,7 +24,7 @@ def operands {{ 'Fs': ('FloatReg', 'sf', 'FS', 'IsFloating', 2), 'Ft': ('FloatReg', 'sf', 'FT', 'IsFloating', 3), - 'Mem': ('Mem', 'udw', None, ('IsMemRef', 'IsLoad', 'IsStore'), 4) + 'Mem': ('Mem', 'ud', None, ('IsMemRef', 'IsLoad', 'IsStore'), 4) #'NPC': ('NPC', 'uq', None, ( None, None, 'IsControl' ), 4), #'Runiq': ('ControlReg', 'uq', 'Uniq', None, 1), diff --git a/arch/sparc/SConscript b/arch/sparc/SConscript new file mode 100644 index 000000000..d8a3749a1 --- /dev/null +++ b/arch/sparc/SConscript @@ -0,0 +1,82 @@ +# -*- 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 + +# Import build environment variable from SConstruct. +Import('env') + +################################################### +# +# Define needed sources. +# +################################################### + +# Base sources used by all configurations. +arch_base_sources = Split(''' + arch/sparc/decoder.cc + arch/sparc/alpha_o3_exec.cc + arch/sparc/fast_cpu_exec.cc + arch/sparc/simple_cpu_exec.cc + arch/sparc/full_cpu_exec.cc + arch/sparc/faults.cc + arch/sparc/isa_traits.cc + ''') + +# Full-system sources +arch_full_system_sources = Split(''' + arch/sparc/alpha_memory.cc + arch/sparc/arguments.cc + arch/sparc/ev5.cc + arch/sparc/osfpal.cc + arch/sparc/stacktrace.cc + arch/sparc/vtophys.cc + ''') + +# Syscall emulation (non-full-system) sources +arch_syscall_emulation_sources = Split(''' + arch/sparc/alpha_common_syscall_emul.cc + arch/sparc/alpha_linux_process.cc + arch/sparc/alpha_tru64_process.cc + ''') + +sources = arch_base_sources + +if env['FULL_SYSTEM']: + sources += arch_full_system_sources + if env['ALPHA_TLASER']: + sources += arch_turbolaser_sources +else: + sources += arch_syscall_emulation_sources + +for opt in env.ExportOptions: + env.ConfigFile(opt) + +Return('sources') |