diff options
-rw-r--r-- | SConstruct | 58 | ||||
-rw-r--r-- | src/arch/sparc/intregfile.cc | 8 | ||||
-rw-r--r-- | src/arch/sparc/isa/decoder.isa | 57 | ||||
-rw-r--r-- | src/arch/sparc/isa/formats/branch.isa | 10 | ||||
-rw-r--r-- | src/arch/sparc/isa/formats/integerop.isa | 2 | ||||
-rw-r--r-- | src/arch/sparc/process.cc | 66 |
6 files changed, 149 insertions, 52 deletions
diff --git a/SConstruct b/SConstruct index 642d012db..49f6e2eb2 100644 --- a/SConstruct +++ b/SConstruct @@ -119,6 +119,22 @@ def rfind(l, elt, offs = -1): return i raise ValueError, "element not found" +# helper function: compare dotted version numbers. +# E.g., compare_version('1.3.25', '1.4.1') +# returns -1, 0, 1 if v1 is <, ==, > v2 +def compare_versions(v1, v2): + # Convert dotted strings to lists + v1 = map(int, v1.split('.')) + v2 = map(int, v2.split('.')) + # Compare corresponding elements of lists + for n1,n2 in zip(v1, v2): + if n1 < n2: return -1 + if n1 > n2: return 1 + # all corresponding values are equal... see if one has extra values + if len(v1) < len(v2): return -1 + if len(v1) > len(v2): return 1 + return 0 + # Each target must have 'build' in the interior of the path; the # directory below this will determine the build parameters. For # example, for target 'foo/bar/build/ALPHA_SE/arch/alpha/blah.do' we @@ -202,8 +218,26 @@ env.Append(LIBS = py_version_name) if sys.exec_prefix != '/usr': env.Append(LIBPATH = os.path.join(sys.exec_prefix, 'lib')) -# Set up SWIG flags & scanner +# Check for SWIG +if not env.has_key('SWIG'): + print 'Error: SWIG utility not found.' + print ' Please install (see http://www.swig.org) and retry.' + Exit(1) + +# Check for appropriate SWIG version +swig_version = os.popen('swig -version').read().split() +# First 3 words should be "SWIG Version x.y.z" +if swig_version[0] != 'SWIG' or swig_version[1] != 'Version': + print 'Error determining SWIG version.' + Exit(1) + +min_swig_version = '1.3.28' +if compare_versions(swig_version[2], min_swig_version) < 0: + print 'Error: SWIG version', min_swig_version, 'or newer required.' + print ' Installed version:', swig_version[2] + Exit(1) +# Set up SWIG flags & scanner env.Append(SWIGFLAGS=Split('-c++ -python -modern $_CPPINCFLAGS')) import SCons.Scanner @@ -215,15 +249,20 @@ swig_scanner = SCons.Scanner.ClassicCPP("SwigScan", ".i", "CPPPATH", env.Append(SCANNERS = swig_scanner) -# Other default libraries -env.Append(LIBS=['z']) - # Platform-specific configuration. Note again that we assume that all # builds under a given build root run on the same host platform. conf = Configure(env, conf_dir = os.path.join(build_root, '.scons_config'), log_file = os.path.join(build_root, 'scons_config.log')) +# Check for zlib. If the check passes, libz will be automatically +# added to the LIBS environment variable. +if not conf.CheckLibWithHeader('z', 'zlib.h', 'C++'): + print 'Error: did not find needed zlib compression library '\ + 'and/or zlib.h header file.' + print ' Please install zlib and try again.' + Exit(1) + # Check for <fenv.h> (C99 FP environment control) have_fenv = conf.CheckHeader('fenv.h', '<>') if not have_fenv: @@ -237,13 +276,10 @@ have_mysql = mysql_config != None # Check MySQL version. if have_mysql: mysql_version = os.popen(mysql_config + ' --version').read() - mysql_version = mysql_version.split('.') - mysql_major = int(mysql_version[0]) - mysql_minor = int(mysql_version[1]) - # This version check is probably overly conservative, but it deals - # with the versions we have installed. - if mysql_major < 4 or (mysql_major == 4 and mysql_minor < 1): - print "Warning: MySQL v4.1 or newer required." + min_mysql_version = '4.1' + if compare_versions(mysql_version, min_mysql_version) < 0: + print 'Warning: MySQL', min_mysql_version, 'or newer required.' + print ' Version', mysql_version, 'detected.' have_mysql = False # Set up mysql_config commands. diff --git a/src/arch/sparc/intregfile.cc b/src/arch/sparc/intregfile.cc index 0cc0a886a..bef62f6ae 100644 --- a/src/arch/sparc/intregfile.cc +++ b/src/arch/sparc/intregfile.cc @@ -60,9 +60,9 @@ void IntRegFile::clear() { int x; for (x = 0; x < MaxGL; x++) - memset(regGlobals[x], 0, sizeof(regGlobals[x])); + memset(regGlobals[x], 0, sizeof(IntReg) * RegsPerFrame); for(int x = 0; x < 2 * NWindows; x++) - bzero(regSegments[x], sizeof(regSegments[x])); + bzero(regSegments[x], sizeof(IntReg) * RegsPerFrame); } IntRegFile::IntRegFile() @@ -84,8 +84,10 @@ IntReg IntRegFile::readReg(int intReg) Fault IntRegFile::setReg(int intReg, const IntReg &val) { if(intReg) + { DPRINTF(Sparc, "Wrote register %d = 0x%x\n", intReg, val); - regView[intReg >> FrameOffsetBits][intReg & FrameOffsetMask] = val; + regView[intReg >> FrameOffsetBits][intReg & FrameOffsetMask] = val; + } return NoFault; } diff --git a/src/arch/sparc/isa/decoder.isa b/src/arch/sparc/isa/decoder.isa index 304c97f2f..0c8d77362 100644 --- a/src/arch/sparc/isa/decoder.isa +++ b/src/arch/sparc/isa/decoder.isa @@ -41,20 +41,45 @@ decode OP default Unknown::unknown() 0x0: Trap::illtrap({{fault = new IllegalInstruction;}}); format BranchN { - 0x1: decode BPCC + 0x1: decode COND2 { - 0x0: bpcci(19, {{ - if(passesCondition(Ccr<3:0>, COND2)) - NNPC = xc->readPC() + disp; - else - handle_annul - }}); - 0x2: bpccx(19, {{ - if(passesCondition(Ccr<7:4>, COND2)) + //Branch Always + 0x8: decode A + { + 0x0: b(19, {{ NNPC = xc->readPC() + disp; - else - handle_annul - }}); + }}); + 0x1: b(19, {{ + NPC = xc->readPC() + disp; + NNPC = NPC + 4; + }}, ',a'); + } + //Branch Never + 0x0: decode A + { + 0x0: bn(19, {{ + NNPC = NNPC;//Don't do anything + }}); + 0x1: bn(19, {{ + NPC = xc->readNextPC() + 4; + NNPC = NPC + 4; + }}, ',a'); + } + default: decode BPCC + { + 0x0: bpcci(19, {{ + if(passesCondition(Ccr<3:0>, COND2)) + NNPC = xc->readPC() + disp; + else + handle_annul + }}); + 0x2: bpccx(19, {{ + if(passesCondition(Ccr<7:4>, COND2)) + NNPC = xc->readPC() + disp; + else + handle_annul + }}); + } } 0x2: bicc(22, {{ if(passesCondition(Ccr<3:0>, COND2)) @@ -106,7 +131,7 @@ decode OP default Unknown::unknown() } } //SETHI (or NOP if rd == 0 and imm == 0) - 0x4: SetHi::sethi({{Rd = imm;}}); + 0x4: SetHi::sethi({{Rd.udw = imm;}}); 0x5: Trap::fbpfcc({{fault = new FpDisabled;}}); 0x6: Trap::fbfcc({{fault = new FpDisabled;}}); } @@ -535,15 +560,15 @@ decode OP default Unknown::unknown() 0x10: Trap::array8({{fault = new IllegalInstruction;}}); 0x12: Trap::array16({{fault = new IllegalInstruction;}}); 0x14: Trap::array32({{fault = new IllegalInstruction;}}); - 0x18: BasicOperate::alignaddress({{ + 0x18: BasicOperate::alignaddr({{ uint64_t sum = Rs1 + Rs2; - Frd = sum & ~7; + Rd = sum & ~7; Gsr = (Gsr & ~7) | (sum & 7); }}); 0x19: Trap::bmask({{fault = new IllegalInstruction;}}); 0x1A: BasicOperate::alignaddresslittle({{ uint64_t sum = Rs1 + Rs2; - Frd = sum & ~7; + Rd = sum & ~7; Gsr = (Gsr & ~7) | ((~sum + 1) & 7); }}); 0x20: Trap::fcmple16({{fault = new IllegalInstruction;}}); diff --git a/src/arch/sparc/isa/formats/branch.isa b/src/arch/sparc/isa/formats/branch.isa index 8a3f05173..2c206354b 100644 --- a/src/arch/sparc/isa/formats/branch.isa +++ b/src/arch/sparc/isa/formats/branch.isa @@ -224,7 +224,6 @@ let {{ // Primary format for branch instructions: def format Branch(code, *opt_flags) {{ - code = re.sub(r'handle_annul', handle_annul, code) (usesImm, code, immCode, rString, iString) = splitOutImm(code) iop = InstObjParams(name, Name, 'Branch', code, opt_flags) @@ -246,7 +245,14 @@ def format Branch(code, *opt_flags) {{ def format BranchN(bits, code, *opt_flags) {{ code = re.sub(r'handle_annul', handle_annul, code) codeBlk = CodeBlock(code) - iop = InstObjParams(name, Name, "BranchNBits<%d>" % bits, codeBlk, opt_flags) + new_opt_flags = [] + for flag in opt_flags: + if flag == ',a': + name += ',a' + Name += 'Annul' + else: + new_opt_flags += flag + iop = InstObjParams(name, Name, "BranchNBits<%d>" % bits, codeBlk, new_opt_flags) header_output = BasicDeclare.subst(iop) decoder_output = BasicConstructor.subst(iop) exec_output = BranchExecute.subst(iop) diff --git a/src/arch/sparc/isa/formats/integerop.isa b/src/arch/sparc/isa/formats/integerop.isa index 27616216e..83c7e6958 100644 --- a/src/arch/sparc/isa/formats/integerop.isa +++ b/src/arch/sparc/isa/formats/integerop.isa @@ -67,7 +67,7 @@ output header {{ { } - int32_t imm; + int64_t imm; std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; diff --git a/src/arch/sparc/process.cc b/src/arch/sparc/process.cc index 150664148..31989cfe2 100644 --- a/src/arch/sparc/process.cc +++ b/src/arch/sparc/process.cc @@ -56,11 +56,11 @@ SparcLiveProcess::SparcLiveProcess(const std::string &nm, ObjectFile *objFile, // 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)0x80000000000ULL); + stack_base = (Addr)0x80000000000ULL; // Set up region for mmaps. Tru64 seems to start just above 0 and // grow up from there. - mmap_start = mmap_end = 0x800000; + mmap_start = mmap_end = 0xfffff80000000000ULL; // Set pointer for next thread stack. Reserve 8M for main stack. next_thread_stack_base = stack_base - (8 * 1024 * 1024); @@ -110,6 +110,12 @@ SparcLiveProcess::argsInit(int intSize, int pageSize) { Process::startup(); + string filename; + if(argv.size() < 1) + filename = ""; + else + filename = argv[0]; + Addr alignmentMask = ~(intSize - 1); // load object file into target memory @@ -194,8 +200,13 @@ SparcLiveProcess::argsInit(int intSize, int pageSize) //Figure out how big the initial stack needs to be - //Each auxilliary vector is two 8 byte words - int aux_data_size = 2 * intSize * auxv.size(); + // The unaccounted for 0 at the top of the stack + int mysterious_size = intSize; + + //This is the name of the file which is present on the initial stack + //It's purpose is to let the user space linker examine the original file. + int file_name_size = filename.size() + 1; + int env_data_size = 0; for (int i = 0; i < envp.size(); ++i) { env_data_size += envp[i].size() + 1; @@ -205,27 +216,33 @@ SparcLiveProcess::argsInit(int intSize, int pageSize) 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; - + //The info_block needs to be padded so it's size is a multiple of the + //alignment mask. Also, it appears that there needs to be at least some + //padding, so if the size is already a multiple, we need to increase it + //anyway. int info_block_size = - (aux_data_size + + (file_name_size + env_data_size + arg_data_size + - ~alignmentMask) & alignmentMask; + intSize) & alignmentMask; int info_block_padding = info_block_size - - aux_data_size - + file_name_size - env_data_size - arg_data_size; + //Each auxilliary vector is two 8 byte words + int aux_array_size = intSize * 2 * (auxv.size() + 1); + + int envp_array_size = intSize * (envp.size() + 1); + int argv_array_size = intSize * (argv.size() + 1); + + int argc_size = intSize; + int window_save_size = intSize * 16; + int space_needed = + mysterious_size + info_block_size + aux_array_size + envp_array_size + @@ -242,10 +259,11 @@ SparcLiveProcess::argsInit(int intSize, int 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 mysterious_base = stack_base - mysterious_size; + Addr file_name_base = mysterious_base - file_name_size; + Addr env_data_base = file_name_base - env_data_size; Addr arg_data_base = env_data_base - arg_data_size; - Addr auxv_array_base = arg_data_base - aux_array_size; + Addr auxv_array_base = arg_data_base - aux_array_size - info_block_padding; Addr envp_array_base = auxv_array_base - envp_array_size; Addr argv_array_base = envp_array_base - argv_array_size; Addr argc_base = argv_array_base - argc_size; @@ -255,7 +273,7 @@ SparcLiveProcess::argsInit(int intSize, int pageSize) #endif 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 - file name\n", file_name_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 - auxv array\n", auxv_array_base); @@ -266,9 +284,19 @@ SparcLiveProcess::argsInit(int intSize, int pageSize) DPRINTF(Sparc, "0x%x - stack min\n", stack_min); // write contents to stack + + // figure out argc uint64_t argc = argv.size(); uint64_t guestArgc = TheISA::htog(argc); + //Write out the mysterious 0 + uint64_t mysterious_zero = 0; + initVirtMem->writeBlob(mysterious_base, + (uint8_t*)&mysterious_zero, mysterious_size); + + //Write the file name + initVirtMem->writeString(file_name_base, filename.c_str()); + //Copy the aux stuff for(int x = 0; x < auxv.size(); x++) { |