OverflowSet=0x7
};
+ extern char * CondTestAbbrev[];
+
/**
* Base class for all SPARC static instructions.
*/
}
}};
+output decoder {{
+
+ char * CondTestAbbrev[] =
+ {
+ "nev", //Never
+ "e", //Equal
+ "le", //Less or Equal
+ "l", //Less
+ "leu", //Less or Equal Unsigned
+ "c", //Carry set
+ "n", //Negative
+ "o", //Overflow set
+ "a", //Always
+ "ne", //Not Equal
+ "g", //Greater
+ "ge", //Greater or Equal
+ "gu", //Greater Unsigned
+ "cc", //Carry clear
+ "p", //Positive
+ "oc" //Overflow Clear
+ };
+}};
+
def template ROrImmDecode {{
{
return (I ? (SparcStaticInst *)(new %(class_name)sImm(machInst))
}
}});
0x39: Branch::return({{
+ //If both MemAddressNotAligned and
+ //a fill trap happen, it's not clear
+ //which one should be returned.
Addr target = Rs1 + Rs2_or_imm13;
if(target & 0x3)
fault = new MemAddressNotAligned;
else
NNPC = target;
- //This needs to change the register window
- //like restore does
+ if(fault == NoFault)
+ {
+ //CWP should be set directly so that it always happens
+ //Also, this will allow writing to the new window and
+ //reading from the old one
+ Cwp = (Cwp - 1 + NWindows) % NWindows;
+ if(Canrestore == 0)
+ {
+ if(Otherwin)
+ fault = new FillNOther(WstateOther);
+ else
+ fault = new FillNNormal(WstateNormal);
+ }
+ else
+ {
+ Rd = Rs1 + Rs2_or_imm13;
+ Cansave = Cansave + 1;
+ Canrestore = Canrestore - 1;
+ }
+ //This is here to make sure the CWP is written
+ //no matter what. This ensures that the results
+ //are written in the new window as well.
+ xc->setMiscRegWithEffect(MISCREG_CWP, Cwp);
+ }
}});
0x3A: decode CC
{
0x0: Trap::tcci({{
+ if(passesCondition(CcrIcc, COND2))
+ {
+ int lTrapNum = I ? (Rs1 + SW_TRAP) : (Rs1 + Rs2);
+ DPRINTF(Sparc, "The trap number is %d\n", lTrapNum);
#if FULL_SYSTEM
- fault = new TrapInstruction;
+ fault = new TrapInstruction(lTrapNum);
#else
- if(passesCondition(CcrIcc, machInst<25:28>))
+ DPRINTF(Sparc, "The syscall number is %d\n", R1);
+ xc->syscall(R1);
+#endif
+ }
+ else
{
- // At least glibc only uses trap 0,
- // solaris/sunos may use others
- assert((I ? Rs1 + Rs2 : Rs1 + SW_TRAP) == 0);
- xc->syscall();
+ DPRINTF(Sparc, "Didn't fire on %s\n", CondTestAbbrev[machInst<25:28>]);
}
-#endif
}});
0x2: Trap::tccx({{
+ if(passesCondition(CcrXcc, COND2))
+ {
+ int lTrapNum = I ? (Rs1 + SW_TRAP) : (Rs1 + Rs2);
+ DPRINTF(Sparc, "The trap number is %d\n", lTrapNum);
#if FULL_SYSTEM
- fault = new TrapInstruction;
+ fault = new TrapInstruction(lTrapNum);
#else
- if(passesCondition(CcrXcc, machInst<25:28>))
- {
- // At least glibc only uses trap 0,
- // solaris/sunos may use others
- assert((I ? Rs1 + Rs2 : Rs1 + SW_TRAP) == 0);
- xc->syscall();
- }
+ DPRINTF(Sparc, "The syscall number is %d\n", R1);
+ xc->syscall(R1);
#endif
+ }
}});
}
0x3B: Nop::flush({{/*Instruction memory flush*/}});
{
Cwp = (Cwp + 1) % NWindows;
Rd = Rs1 + Rs2_or_imm13;
- Cansave--;
- Canrestore++;
+ Cansave = Cansave - 1;
+ Canrestore = Canrestore + 1;
}
//This is here to make sure the CWP is written
//no matter what. This ensures that the results
else
{
Rd = Rs1 + Rs2_or_imm13;
- Cansave++;
- Canrestore--;
+ Cansave = Cansave + 1;
+ Canrestore = Canrestore - 1;
}
//This is here to make sure the CWP is written
//no matter what. This ensures that the results
format Trap {
0x20: ldf({{fault = new FpDisabled;}});
0x21: decode X {
- 0x0: ldfsr({{fault = new FpDisabled;}});
- 0x1: ldxfsr({{fault = new FpDisabled;}});
+ 0x0: Load::ldfsr({{Fsr = Mem<31:0> | Fsr<63:32>;}}, {{32}});
+ 0x1: Load::ldxfsr({{Fsr = Mem;}}, {{64}});
}
0x22: ldqf({{fault = new FpDisabled;}});
0x23: lddf({{fault = new FpDisabled;}});
0x24: stf({{fault = new FpDisabled;}});
0x25: decode X {
- 0x0: stfsr({{fault = new FpDisabled;}});
- 0x1: stxfsr({{fault = new FpDisabled;}});
+ 0x0: Store::stfsr({{Mem = Fsr<31:0>;}}, {{32}});
+ 0x1: Store::stxfsr({{Mem = Fsr;}}, {{64}});
}
0x26: stqf({{fault = new FpDisabled;}});
0x27: stdf({{fault = new FpDisabled;}});
def format Branch(code, *opt_flags) {{
(usesImm, code, immCode,
rString, iString) = splitOutImm(code)
- codeBlk = CodeBlock(code)
- iop = InstObjParams(name, Name, 'Branch', codeBlk, opt_flags)
+ iop = InstObjParams(name, Name, 'Branch', code, opt_flags)
header_output = BasicDeclare.subst(iop)
decoder_output = BasicConstructor.subst(iop)
exec_output = BranchExecute.subst(iop)
if usesImm:
imm_iop = InstObjParams(name, Name + 'Imm', 'BranchImm' + iString,
- codeBlk, opt_flags)
+ immCode, opt_flags)
header_output += BasicDeclare.subst(imm_iop)
decoder_output += BasicConstructor.subst(imm_iop)
exec_output += BranchExecute.subst(imm_iop)
//Write the resulting state to the execution context
if(fault == NoFault)
{
- %(op_wb)s;
%(cc_code)s;
+ %(op_wb)s;
}
return fault;
}
{
std::stringstream response;
bool load = flags[IsLoad];
+ bool save = flags[IsStore];
printMnemonic(response, mnemonic);
- if(!load)
+ if(save)
{
printReg(response, _srcRegIdx[0]);
ccprintf(response, ", ");
}
ccprintf(response, "[ ");
- printReg(response, _srcRegIdx[load ? 0 : 1]);
+ printReg(response, _srcRegIdx[!save ? 0 : 1]);
ccprintf(response, " + ");
- printReg(response, _srcRegIdx[load ? 1 : 2]);
+ printReg(response, _srcRegIdx[!save ? 1 : 2]);
ccprintf(response, " ]");
if(load)
{
{
std::stringstream response;
bool load = flags[IsLoad];
+ bool save = flags[IsStore];
printMnemonic(response, mnemonic);
- if(!load)
+ if(save)
{
printReg(response, _srcRegIdx[0]);
ccprintf(response, ", ");
}
ccprintf(response, "[ ");
- printReg(response, _srcRegIdx[load ? 0 : 1]);
+ printReg(response, _srcRegIdx[!save ? 0 : 1]);
ccprintf(response, " + 0x%x ]", imm);
if(load)
{
// Constructor
Trap(const char *mnem, ExtMachInst _machInst, OpClass __opClass) :
- SparcStaticInst(mnem, _machInst, __opClass)
+ SparcStaticInst(mnem, _machInst, __opClass), trapNum(SW_TRAP)
{
}
std::string generateDisassembly(Addr pc,
const SymbolTable *symtab) const;
+
+ int trapNum;
};
}};
std::string Trap::generateDisassembly(Addr pc,
const SymbolTable *symtab) const
{
- return "Trap instruction";
+ std::stringstream response;
+
+ printMnemonic(response, mnemonic);
+ ccprintf(response, " ");
+ printReg(response, _srcRegIdx[0]);
+ ccprintf(response, ", 0x%x", trapNum);
+ ccprintf(response, ", or ");
+ printReg(response, _srcRegIdx[1]);
+ return response.str();
}
}};
#'Runiq': ('ControlReg', 'uq', 'Uniq', None, 1),
#'FPCR': ('ControlReg', 'uq', 'Fpcr', None, 1),
'R0': ('IntReg', 'udw', '0', None, 6),
- 'R15': ('IntReg', 'udw', '15', 'IsInteger', 7),
- 'R16': ('IntReg', 'udw', '16', None, 8),
+ 'R1': ('IntReg', 'udw', '1', None, 7),
+ 'R15': ('IntReg', 'udw', '15', 'IsInteger', 8),
+ 'R16': ('IntReg', 'udw', '16', None, 9),
# Control registers
'Pstate': ('ControlReg', 'udw', 'MISCREG_PSTATE', None, 1),
'PstateAg': ('ControlReg', 'udw', 'MISCREG_PSTATE_AG', None, 2),
const int ArgumentReg3 = 11;
const int ArgumentReg4 = 12;
const int ArgumentReg5 = 13;
- const int SyscallNumReg = 1;
// Some OS syscall use a second register (o1) to return a second value
const int SyscallPseudoReturnReg = ArgumentReg1;
//XXX These numbers are bogus
const int MaxInstSrcRegs = 8;
- const int MaxInstDestRegs = 3;
+ const int MaxInstDestRegs = 9;
typedef uint64_t IntReg;
// and put the return value itself in the standard return value reg ().
if (return_value.successful()) {
// no error
- regs->setMiscReg(MISCREG_CCR_ICC_C, 0);
+ regs->setMiscReg(MISCREG_CCR_XCC_C, 0);
regs->setIntReg(ReturnValueReg, return_value.value());
} else {
// got an error, return details
- regs->setMiscReg(MISCREG_CCR_ICC_C, 1);
+ regs->setMiscReg(MISCREG_CCR_XCC_C, 1);
regs->setIntReg(ReturnValueReg, return_value.value());
}
}
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include "arch/sparc/linux/process.hh"
#include "arch/sparc/isa_traits.hh"
+#include "arch/sparc/linux/process.hh"
+#include "arch/sparc/regfile.hh"
#include "base/trace.hh"
#include "cpu/exec_context.hh"
strcpy(name->machine, "sparc");
name.copyOut(xc->getMemPort());
+
+ return 0;
+}
+
+
+SyscallReturn SparcISA::getresuidFunc(SyscallDesc *desc, int num,
+ Process *p, ExecContext *xc)
+{
+ const IntReg id = htog(100);
+ Addr ruid = xc->getSyscallArg(0);
+ Addr euid = xc->getSyscallArg(1);
+ Addr suid = xc->getSyscallArg(2);
+ //Handle the EFAULT case
+ //Set the ruid
+ if(ruid)
+ {
+ BufferArg ruidBuff(ruid, sizeof(IntReg));
+ memcpy(ruidBuff.bufferPtr(), &id, sizeof(IntReg));
+ ruidBuff.copyOut(xc->getMemPort());
+ }
+ //Set the euid
+ if(euid)
+ {
+ BufferArg euidBuff(euid, sizeof(IntReg));
+ memcpy(euidBuff.bufferPtr(), &id, sizeof(IntReg));
+ euidBuff.copyOut(xc->getMemPort());
+ }
+ //Set the suid
+ if(suid)
+ {
+ BufferArg suidBuff(suid, sizeof(IntReg));
+ memcpy(suidBuff.bufferPtr(), &id, sizeof(IntReg));
+ suidBuff.copyOut(xc->getMemPort());
+ }
return 0;
}
/* 106 */ SyscallDesc("rt_sigqueueinfo", unimplementedFunc),
/* 107 */ SyscallDesc("rt_sigsuspend", unimplementedFunc),
/* 108 */ SyscallDesc("setresuid", unimplementedFunc),
- /* 109 */ SyscallDesc("getresuid", unimplementedFunc),
+ /* 109 */ SyscallDesc("getresuid", getresuidFunc),
/* 110 */ SyscallDesc("setresgid", unimplementedFunc),
/* 111 */ SyscallDesc("getresgid", unimplementedFunc),
/* 112 */ SyscallDesc("setregid32", unimplementedFunc),
const int Num_Syscall_Descs;
};
+SyscallReturn getresuidFunc(SyscallDesc *desc, int num,
+ Process *p, ExecContext *xc);
+
} // namespace SparcISA
#endif // __ALPHA_LINUX_PROCESS_HH__
#include "base/loader/object_file.hh"
#include "base/misc.hh"
#include "cpu/exec_context.hh"
+#include "mem/page_table.hh"
+#include "mem/translating_port.hh"
#include "sim/builder.hh"
#include "sim/system.hh"
brk_point = objFile->dataBase() + objFile->dataSize() + objFile->bssSize();
brk_point = roundUp(brk_point, VMPageSize);
- // Set up stack. On Alpha, stack goes below text section. This
- // code should get moved to some architecture-specific spot.
- stack_base = objFile->textBase() - (409600+4096);
+ // Set up stack. On SPARC Linux, stack goes from the top of memory
+ // downward, less the hole for the kernel address space.
+ stack_base = ((Addr)0x80000000000);
// Set up region for mmaps. Tru64 seems to start just above 0 and
// grow up from there.
// Set pointer for next thread stack. Reserve 8M for main stack.
next_thread_stack_base = stack_base - (8 * 1024 * 1024);
-
}
void
SparcLiveProcess::startup()
{
argsInit(MachineBytes, VMPageSize);
+
+ //From the SPARC ABI
+
+ //The process runs in user mode
+ execContexts[0]->setMiscRegWithEffect(MISCREG_PSTATE_PRIV, 0);
+ //Interrupts are enabled
+ execContexts[0]->setMiscRegWithEffect(MISCREG_PSTATE_IE, 1);
+ //Round to nearest
+ execContexts[0]->setMiscRegWithEffect(MISCREG_FSR_RD, 0);
+ //Floating point traps are not enabled
+ execContexts[0]->setMiscRegWithEffect(MISCREG_FSR_TEM, 0);
+ //Turn non standard mode off
+ execContexts[0]->setMiscRegWithEffect(MISCREG_FSR_NS, 0);
+ //The floating point queue is empty
+ execContexts[0]->setMiscRegWithEffect(MISCREG_FSR_QNE, 0);
+ //There are no accrued eexecContext[0]eptions
+ execContexts[0]->setMiscRegWithEffect(MISCREG_FSR_AEXC, 0);
+ //There are no current eexecContext[0]eptions
+ execContexts[0]->setMiscRegWithEffect(MISCREG_FSR_CEXC, 0);
+
+ /*
+ * Register window management registers
+ */
+
+ //No windows contain info from other programs
+ execContexts[0]->setMiscRegWithEffect(MISCREG_OTHERWIN, 0);
+ //There are no windows to pop
+ execContexts[0]->setMiscRegWithEffect(MISCREG_CANRESTORE, 0);
+ //All windows are available to save into
+ execContexts[0]->setMiscRegWithEffect(MISCREG_CANSAVE, NWindows - 2);
+ //All windows are "clean"
+ execContexts[0]->setMiscRegWithEffect(MISCREG_CLEANWIN, NWindows);
+ //Start with register window 0
+ execContexts[0]->setMiscRegWithEffect(MISCREG_CWP, 0);
}
+void
+SparcLiveProcess::argsInit(int intSize, int pageSize)
+{
+ Process::startup();
+
+ Addr alignmentMask = ~(intSize - 1);
+
+ // load object file into target memory
+ objFile->loadSections(initVirtMem);
+ //Figure out how big the initial stack needs to be
+
+ int aux_data_size = 0;
+ //Figure out the aux_data_size?
+ int env_data_size = 0;
+ for (int i = 0; i < envp.size(); ++i) {
+ env_data_size += envp[i].size() + 1;
+ }
+ int arg_data_size = 0;
+ for (int i = 0; i < argv.size(); ++i) {
+ arg_data_size += argv[i].size() + 1;
+ }
+
+ int aux_array_size = intSize * 2 * (auxv.size() + 1);
+
+ int argv_array_size = intSize * (argv.size() + 1);
+ int envp_array_size = intSize * (envp.size() + 1);
+
+ int argc_size = intSize;
+ int window_save_size = intSize * 16;
+
+ int info_block_size =
+ (aux_data_size +
+ env_data_size +
+ arg_data_size +
+ ~alignmentMask) & alignmentMask;
+
+ int info_block_padding =
+ info_block_size -
+ aux_data_size -
+ env_data_size -
+ arg_data_size;
+
+ int space_needed =
+ info_block_size +
+ aux_array_size +
+ envp_array_size +
+ argv_array_size +
+ argc_size +
+ window_save_size;
+
+ stack_min = stack_base - space_needed;
+ stack_min &= alignmentMask;
+ stack_size = stack_base - stack_min;
+
+ // map memory
+ pTable->allocate(roundDown(stack_min, pageSize),
+ roundUp(stack_size, pageSize));
+
+ // map out initial stack contents
+ Addr aux_data_base = stack_base - aux_data_size - info_block_padding;
+ Addr env_data_base = aux_data_base - env_data_size;
+ Addr arg_data_base = env_data_base - arg_data_size;
+ Addr aux_array_base = arg_data_base - aux_array_size;
+ Addr envp_array_base = aux_array_base - envp_array_size;
+ Addr argv_array_base = envp_array_base - argv_array_size;
+ Addr argc_base = argv_array_base - argc_size;
+ Addr window_save_base = argc_base - window_save_size;
+
+ DPRINTF(Sparc, "The addresses of items on the initial stack:\n");
+ DPRINTF(Sparc, "0x%x - aux data\n", aux_data_base);
+ DPRINTF(Sparc, "0x%x - env data\n", env_data_base);
+ DPRINTF(Sparc, "0x%x - arg data\n", arg_data_base);
+ DPRINTF(Sparc, "0x%x - aux array\n", aux_array_base);
+ DPRINTF(Sparc, "0x%x - env array\n", envp_array_base);
+ DPRINTF(Sparc, "0x%x - arg array\n", argv_array_base);
+ DPRINTF(Sparc, "0x%x - argc \n", argc_base);
+ DPRINTF(Sparc, "0x%x - window save\n", window_save_base);
+ DPRINTF(Sparc, "0x%x - stack min\n", stack_min);
+
+ // write contents to stack
+ uint64_t argc = argv.size();
+
+ //Copy the aux stuff? For now just put in the null vect
+ const uint64_t zero = 0;
+ initVirtMem->writeBlob(aux_array_base, (uint8_t*)&zero, 2 * intSize);
+
+ copyStringArray(envp, envp_array_base, env_data_base, initVirtMem);
+ copyStringArray(argv, argv_array_base, arg_data_base, initVirtMem);
+
+ initVirtMem->writeBlob(argc_base, (uint8_t*)&argc, intSize);
+
+ execContexts[0]->setIntReg(ArgumentReg0, argc);
+ execContexts[0]->setIntReg(ArgumentReg1, argv_array_base);
+ execContexts[0]->setIntReg(StackPointerReg, stack_min - StackBias);
+
+ Addr prog_entry = objFile->entryPoint();
+ execContexts[0]->setPC(prog_entry);
+ execContexts[0]->setNextPC(prog_entry + sizeof(MachInst));
+ execContexts[0]->setNextNPC(prog_entry + (2 * sizeof(MachInst)));
+
+// num_processes++;
+}
BEGIN_DECLARE_SIM_OBJECT_PARAMS(SparcLiveProcess)
class SparcLiveProcess : public LiveProcess
{
protected:
+ typedef struct
+ {
+ int64_t a_type;
+ union {
+ int64_t a_val;
+ Addr a_ptr;
+ Addr a_fcn;
+ };
+ } m5_auxv_t;
+
+ static const Addr StackBias = 2047;
+
+ std::vector<m5_auxv_t> auxv;
+
SparcLiveProcess(const std::string &nm, ObjectFile *objFile,
System *_system, int stdin_fd, int stdout_fd, int stderr_fd,
std::vector<std::string> &argv,
std::vector<std::string> &argv,
std::vector<std::string> &envp);
+ void argsInit(int intSize, int pageSize);
+
};
#endif // __SPARC_PROCESS_HH__
const int MaxTL = 4;
// NWINDOWS - number of register windows, can be 3 to 32
- const int NWindows = 6;
+ const int NWindows = 32;
class IntRegFile
{
tickFields.npt = 1; //The TICK register is unreadable by
//non-priveleged software
#else
- //This sets up the initial state of the processor for usermode processes
+/* //This sets up the initial state of the processor for usermode processes
pstateFields.priv = 0; //Process runs in user mode
pstateFields.ie = 1; //Interrupts are enabled
fsrFields.rd = 0; //Round to nearest
otherwin = 0; //No windows contain info from other programs
canrestore = 0; //There are no windows to pop
cansave = MaxTL - 2; //All windows are available to save into
- cleanwin = MaxTL;
+ cleanwin = MaxTL;*/
#endif
}
TheISA::setSyscallReturn(return_value, ®s);
}
- void syscall()
+ void syscall(int64_t callnum)
{
- process->syscall(proxy);
+ process->syscall(callnum, proxy);
}
Counter readFuncExeInst() { return func_exe_inst; }
virtual void setSyscallReturn(SyscallReturn return_value) = 0;
- virtual void syscall() = 0;
+ virtual void syscall(int64_t callnum) = 0;
// Same with st cond failures.
virtual Counter readFuncExeInst() = 0;
void setSyscallReturn(SyscallReturn return_value)
{ actualXC->setSyscallReturn(return_value); }
- void syscall() { actualXC->syscall(); }
+ void syscall(int64_t callnum) { actualXC->syscall(callnum); }
Counter readFuncExeInst() { return actualXC->readFuncExeInst(); }
void ev5_trap(Fault fault) { fault->invoke(xcProxy); }
bool simPalCheck(int palFunc) { return cpuXC->simPalCheck(palFunc); }
#else
- void syscall() { cpuXC->syscall(); }
+ void syscall(int64_t callnum) { cpuXC->syscall(callnum); }
#endif
bool misspeculating() { return cpuXC->misspeculating(); }
////////////////////////////////////////////////////////////////////////
-static void
+void
copyStringArray(vector<string> &strings, Addr array_ptr, Addr data_ptr,
TranslatingPort* memPort)
{
}
void
-LiveProcess::syscall(ExecContext *xc)
+LiveProcess::syscall(int64_t callnum, ExecContext *xc)
{
num_syscalls++;
- int64_t callnum = xc->readIntReg(SyscallNumReg);
-
SyscallDesc *desc = getDesc(callnum);
if (desc == NULL)
fatal("Syscall %d out of range", callnum);
class TranslatingPort;
class System;
+void
+copyStringArray(std::vector<std::string> &strings, Addr array_ptr,
+ Addr data_ptr, TranslatingPort* memPort);
+
class Process : public SimObject
{
public:
// look up simulator fd for given target fd
int sim_fd(int tgt_fd);
- virtual void syscall(ExecContext *xc) = 0;
+ virtual void syscall(int64_t callnum, ExecContext *xc) = 0;
};
//
std::vector<std::string> &argv,
std::vector<std::string> &envp);
- void argsInit(int intSize, int pageSize);
+ virtual void argsInit(int intSize, int pageSize);
public:
- virtual void syscall(ExecContext *xc);
+ virtual void syscall(int64_t callnum, ExecContext *xc);
virtual SyscallDesc* getDesc(int callnum) = 0;
};